1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 #include <stdio.h> 43 #include <ctype.h> 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include <errno.h> 47 #include <unistd.h> 48 #include <strings.h> 49 #include <stdlib.h> 50 #include <libintl.h> 51 52 #ifdef SYSV 53 #define index strchr 54 #endif /* SYSV */ 55 56 static void rnetrc(const char *host, char **aname, char **apass); 57 static int token(); 58 59 #define DEFAULT 1 60 #define LOGIN 2 61 #define PASSWD 3 62 #define NOTIFY 4 63 #define WRITE 5 64 #define YES 6 65 #define NO 7 66 #define COMMAND 8 67 #define FORCE 9 68 #define ID 10 69 #define MACHINE 11 70 71 #define MAXTOKEN 11 72 #define NTOKENS (MAXTOKEN - 1 + 2 + 1) /* two duplicates and null, minus id */ 73 74 static struct ruserdata { 75 char tokval[100]; 76 struct toktab { 77 char *tokstr; 78 int tval; 79 } toktab[NTOKENS]; 80 FILE *cfile; 81 } *ruserdata, *_ruserdata(); 82 83 84 static struct ruserdata * 85 _ruserdata() 86 { 87 struct ruserdata *d = ruserdata; 88 struct toktab *t; 89 90 if (d == 0) { 91 if ((d = (struct ruserdata *) 92 calloc(1, sizeof (struct ruserdata))) == NULL) { 93 return (NULL); 94 } 95 ruserdata = d; 96 t = d->toktab; 97 t->tokstr = "default"; t++->tval = DEFAULT; 98 t->tokstr = "login"; t++->tval = LOGIN; 99 t->tokstr = "password"; t++->tval = PASSWD; 100 t->tokstr = "notify"; t++->tval = NOTIFY; 101 t->tokstr = "write"; t++->tval = WRITE; 102 t->tokstr = "yes"; t++->tval = YES; 103 t->tokstr = "y"; t++->tval = YES; 104 t->tokstr = "no"; t++->tval = NO; 105 t->tokstr = "n"; t++->tval = NO; 106 t->tokstr = "command"; t++->tval = COMMAND; 107 t->tokstr = "force"; t++->tval = FORCE; 108 t->tokstr = "machine"; t++->tval = MACHINE; 109 t->tokstr = 0; t->tval = 0; 110 } 111 return (d); 112 } 113 114 115 #define MAXANAME 16 116 117 void 118 _ruserpass(const char *host, char **aname, char **apass) 119 { 120 121 if (*aname == 0 || *apass == 0) 122 rnetrc(host, aname, apass); 123 if (*aname == 0) { 124 char myname[L_cuserid]; 125 126 *aname = malloc(MAXANAME + 1); 127 (void) cuserid(myname); 128 (void) printf(dgettext(TEXT_DOMAIN, "Name (%s:%s): "), 129 host, myname); 130 (void) fflush(stdout); 131 if (read(2, *aname, MAXANAME) <= 0) 132 exit(1); 133 aname[0][MAXANAME] = '\0'; 134 if ((*aname)[0] == '\n') 135 (void) strcpy(*aname, myname); 136 else 137 if (index(*aname, '\n')) 138 *index(*aname, '\n') = 0; 139 } 140 if (*aname && *apass == 0) { 141 (void) printf(dgettext(TEXT_DOMAIN, "Password (%s:%s): "), 142 host, *aname); 143 (void) fflush(stdout); 144 *apass = getpass(""); 145 } 146 } 147 148 149 static void 150 rnetrc(const char *host, char **aname, char **apass) 151 { 152 struct ruserdata *d = _ruserdata(); 153 char *hdir, buf[BUFSIZ]; 154 int t; 155 struct stat64 stb; 156 157 if (d == 0) 158 return; 159 160 hdir = getenv("HOME"); 161 if (hdir == NULL) 162 hdir = "."; 163 (void) sprintf(buf, "%s/.netrc", hdir); 164 d->cfile = fopen(buf, "rF"); 165 if (d->cfile == NULL) { 166 if (errno != ENOENT) 167 perror(buf); 168 return; 169 } 170 next: 171 while ((t = token())) 172 switch (t) { 173 174 case DEFAULT: 175 (void) token(); 176 continue; 177 178 case MACHINE: 179 if (token() != ID || strcmp(host, d->tokval)) 180 continue; 181 while ((t = token()) != 0 && t != MACHINE) 182 switch (t) { 183 184 case LOGIN: 185 if (token()) 186 if (*aname == 0) { 187 *aname = malloc(strlen(d->tokval) + 1); 188 (void) strcpy(*aname, d->tokval); 189 } else { 190 if (strcmp(*aname, d->tokval)) 191 goto next; 192 } 193 break; 194 case PASSWD: 195 if (fstat64(fileno(d->cfile), &stb) >= 0 && 196 (stb.st_mode & 077) != 0) { 197 (void) fprintf(stderr, 198 dgettext(TEXT_DOMAIN, 199 "Error - .netrc file not correct mode.\n")); 200 (void) fprintf(stderr, 201 dgettext(TEXT_DOMAIN, 202 "Remove password or correct mode.\n")); 203 exit(1); 204 } 205 if (token() && *apass == 0) { 206 *apass = malloc(strlen(d->tokval) + 1); 207 (void) strcpy(*apass, d->tokval); 208 } 209 break; 210 case COMMAND: 211 case NOTIFY: 212 case WRITE: 213 case FORCE: 214 (void) token(); 215 break; 216 default: 217 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 218 "Unknown .netrc option %s\n"), d->tokval); 219 break; 220 } 221 goto done; 222 } 223 done: 224 (void) fclose(d->cfile); 225 } 226 227 static int 228 token() 229 { 230 struct ruserdata *d = _ruserdata(); 231 char *cp; 232 int c; 233 struct toktab *t; 234 235 if (d == 0) 236 return (0); 237 238 if (feof(d->cfile)) 239 return (0); 240 while ((c = getc(d->cfile)) != EOF && 241 (c == '\n' || c == '\t' || c == ' ' || c == ',')) 242 continue; 243 if (c == EOF) 244 return (0); 245 cp = d->tokval; 246 if (c == '"') { 247 while ((c = getc(d->cfile)) != EOF && c != '"') { 248 if (c == '\\') 249 c = getc(d->cfile); 250 *cp++ = (char)c; 251 } 252 } else { 253 *cp++ = (char)c; 254 while ((c = getc(d->cfile)) != EOF && 255 c != '\n' && c != '\t' && c != ' ' && c != ',') { 256 if (c == '\\') 257 c = getc(d->cfile); 258 *cp++ = (char)c; 259 } 260 } 261 *cp = 0; 262 if (d->tokval[0] == 0) 263 return (0); 264 for (t = d->toktab; t->tokstr; t++) 265 if ((strcmp(t->tokstr, d->tokval) == 0)) 266 return (t->tval); 267 return (ID); 268 } 269