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 #include <stdio.h> 41 #include <ctype.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include <errno.h> 45 #include <unistd.h> 46 #include <strings.h> 47 #include <stdlib.h> 48 #include <libintl.h> 49 #include <limits.h> 50 51 #ifdef SYSV 52 #define index strchr 53 #endif /* SYSV */ 54 55 static void rnetrc(const char *host, char **aname, char **apass); 56 static int token(); 57 58 #define DEFAULT 1 59 #define LOGIN 2 60 #define PASSWD 3 61 #define NOTIFY 4 62 #define WRITE 5 63 #define YES 6 64 #define NO 7 65 #define COMMAND 8 66 #define FORCE 9 67 #define ID 10 68 #define MACHINE 11 69 70 #define MAXTOKEN 11 71 #define NTOKENS (MAXTOKEN - 1 + 2 + 1) /* two duplicates and null, minus id */ 72 73 static struct ruserdata { 74 char tokval[100]; 75 struct toktab { 76 char *tokstr; 77 int tval; 78 } toktab[NTOKENS]; 79 FILE *cfile; 80 } *ruserdata, *_ruserdata(); 81 82 83 static struct ruserdata * 84 _ruserdata() 85 { 86 struct ruserdata *d = ruserdata; 87 struct toktab *t; 88 89 if (d == 0) { 90 if ((d = (struct ruserdata *) 91 calloc(1, sizeof (struct ruserdata))) == NULL) { 92 return (NULL); 93 } 94 ruserdata = d; 95 t = d->toktab; 96 t->tokstr = "default"; t++->tval = DEFAULT; 97 t->tokstr = "login"; t++->tval = LOGIN; 98 t->tokstr = "password"; t++->tval = PASSWD; 99 t->tokstr = "notify"; t++->tval = NOTIFY; 100 t->tokstr = "write"; t++->tval = WRITE; 101 t->tokstr = "yes"; t++->tval = YES; 102 t->tokstr = "y"; t++->tval = YES; 103 t->tokstr = "no"; t++->tval = NO; 104 t->tokstr = "n"; t++->tval = NO; 105 t->tokstr = "command"; t++->tval = COMMAND; 106 t->tokstr = "force"; t++->tval = FORCE; 107 t->tokstr = "machine"; t++->tval = MACHINE; 108 t->tokstr = 0; t->tval = 0; 109 } 110 return (d); 111 } 112 113 114 #define MAXANAME 16 115 116 void 117 _ruserpass(const char *host, char **aname, char **apass) 118 { 119 120 if (*aname == 0 || *apass == 0) 121 rnetrc(host, aname, apass); 122 if (*aname == 0) { 123 char myname[L_cuserid]; 124 125 *aname = malloc(MAXANAME + 1); 126 (void) cuserid(myname); 127 (void) printf(dgettext(TEXT_DOMAIN, "Name (%s:%s): "), 128 host, myname); 129 (void) fflush(stdout); 130 if (read(2, *aname, MAXANAME) <= 0) 131 exit(1); 132 aname[0][MAXANAME] = '\0'; 133 if ((*aname)[0] == '\n') 134 (void) strcpy(*aname, myname); 135 else 136 if (index(*aname, '\n')) 137 *index(*aname, '\n') = 0; 138 } 139 if (*aname && *apass == 0) { 140 (void) printf(dgettext(TEXT_DOMAIN, "Password (%s:%s): "), 141 host, *aname); 142 (void) fflush(stdout); 143 *apass = getpass(""); 144 } 145 } 146 147 148 static void 149 rnetrc(const char *host, char **aname, char **apass) 150 { 151 struct ruserdata *d = _ruserdata(); 152 char *hdir, buf[PATH_MAX]; 153 int t; 154 struct stat64 stb; 155 156 if (d == 0) 157 return; 158 159 hdir = getenv("HOME"); 160 if (hdir == NULL) 161 hdir = "."; 162 t = snprintf(buf, sizeof (buf), "%s/.netrc", hdir); 163 if (t < 0 || t >= sizeof (buf)) { 164 if (t < 0) { 165 perror(buf); 166 } else { 167 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 168 "HOME directory name is too long: %s\n"), hdir); 169 } 170 return; 171 } 172 173 d->cfile = fopen(buf, "rF"); 174 if (d->cfile == NULL) { 175 if (errno != ENOENT) 176 perror(buf); 177 return; 178 } 179 next: 180 while ((t = token())) 181 switch (t) { 182 183 case DEFAULT: 184 (void) token(); 185 continue; 186 187 case MACHINE: 188 if (token() != ID || strcmp(host, d->tokval)) 189 continue; 190 while ((t = token()) != 0 && t != MACHINE) 191 switch (t) { 192 193 case LOGIN: 194 if (token()) 195 if (*aname == 0) { 196 *aname = malloc(strlen(d->tokval) + 1); 197 (void) strcpy(*aname, d->tokval); 198 } else { 199 if (strcmp(*aname, d->tokval)) 200 goto next; 201 } 202 break; 203 case PASSWD: 204 if (fstat64(fileno(d->cfile), &stb) >= 0 && 205 (stb.st_mode & 077) != 0) { 206 (void) fprintf(stderr, 207 dgettext(TEXT_DOMAIN, 208 "Error - .netrc file not correct mode.\n")); 209 (void) fprintf(stderr, 210 dgettext(TEXT_DOMAIN, 211 "Remove password or correct mode.\n")); 212 exit(1); 213 } 214 if (token() && *apass == 0) { 215 *apass = malloc(strlen(d->tokval) + 1); 216 (void) strcpy(*apass, d->tokval); 217 } 218 break; 219 case COMMAND: 220 case NOTIFY: 221 case WRITE: 222 case FORCE: 223 (void) token(); 224 break; 225 default: 226 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, 227 "Unknown .netrc option %s\n"), d->tokval); 228 break; 229 } 230 goto done; 231 } 232 done: 233 (void) fclose(d->cfile); 234 } 235 236 static int 237 token() 238 { 239 struct ruserdata *d = _ruserdata(); 240 char *cp; 241 int c; 242 struct toktab *t; 243 244 if (d == 0) 245 return (0); 246 247 if (feof(d->cfile)) 248 return (0); 249 while ((c = getc(d->cfile)) != EOF && 250 (c == '\n' || c == '\t' || c == ' ' || c == ',')) 251 continue; 252 if (c == EOF) 253 return (0); 254 cp = d->tokval; 255 if (c == '"') { 256 while ((c = getc(d->cfile)) != EOF && c != '"') { 257 if (c == '\\') 258 c = getc(d->cfile); 259 *cp++ = (char)c; 260 } 261 } else { 262 *cp++ = (char)c; 263 while ((c = getc(d->cfile)) != EOF && 264 c != '\n' && c != '\t' && c != ' ' && c != ',') { 265 if (c == '\\') 266 c = getc(d->cfile); 267 *cp++ = (char)c; 268 } 269 } 270 *cp = 0; 271 if (d->tokval[0] == 0) 272 return (0); 273 for (t = d->toktab; t->tokstr; t++) 274 if ((strcmp(t->tokstr, d->tokval) == 0)) 275 return (t->tval); 276 return (ID); 277 } 278