1 /* 2 * Copyright (c) 1985, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)ruserpass.c 8.3 (Berkeley) 04/02/94"; 10 #endif /* not lint */ 11 12 #include <sys/types.h> 13 #include <sys/stat.h> 14 15 #include <ctype.h> 16 #include <err.h> 17 #include <errno.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <unistd.h> 22 23 #include "ftp_var.h" 24 25 static int token __P((void)); 26 static FILE *cfile; 27 28 #define DEFAULT 1 29 #define LOGIN 2 30 #define PASSWD 3 31 #define ACCOUNT 4 32 #define MACDEF 5 33 #define ID 10 34 #define MACH 11 35 36 static char tokval[100]; 37 38 static struct toktab { 39 char *tokstr; 40 int tval; 41 } toktab[]= { 42 { "default", DEFAULT }, 43 { "login", LOGIN }, 44 { "password", PASSWD }, 45 { "passwd", PASSWD }, 46 { "account", ACCOUNT }, 47 { "machine", MACH }, 48 { "macdef", MACDEF }, 49 { NULL, 0 } 50 }; 51 52 int 53 ruserpass(host, aname, apass, aacct) 54 char *host, **aname, **apass, **aacct; 55 { 56 char *hdir, buf[BUFSIZ], *tmp; 57 char myname[MAXHOSTNAMELEN], *mydomain; 58 int t, i, c, usedefault = 0; 59 struct stat stb; 60 61 hdir = getenv("HOME"); 62 if (hdir == NULL) 63 hdir = "."; 64 (void) sprintf(buf, "%s/.netrc", hdir); 65 cfile = fopen(buf, "r"); 66 if (cfile == NULL) { 67 if (errno != ENOENT) 68 warn("%s", buf); 69 return (0); 70 } 71 if (gethostname(myname, sizeof(myname)) < 0) 72 myname[0] = '\0'; 73 if ((mydomain = strchr(myname, '.')) == NULL) 74 mydomain = ""; 75 next: 76 while ((t = token())) switch(t) { 77 78 case DEFAULT: 79 usedefault = 1; 80 /* FALL THROUGH */ 81 82 case MACH: 83 if (!usedefault) { 84 if (token() != ID) 85 continue; 86 /* 87 * Allow match either for user's input host name 88 * or official hostname. Also allow match of 89 * incompletely-specified host in local domain. 90 */ 91 if (strcasecmp(host, tokval) == 0) 92 goto match; 93 if (strcasecmp(hostname, tokval) == 0) 94 goto match; 95 if ((tmp = strchr(hostname, '.')) != NULL && 96 strcasecmp(tmp, mydomain) == 0 && 97 strncasecmp(hostname, tokval, tmp-hostname) == 0 && 98 tokval[tmp - hostname] == '\0') 99 goto match; 100 if ((tmp = strchr(host, '.')) != NULL && 101 strcasecmp(tmp, mydomain) == 0 && 102 strncasecmp(host, tokval, tmp - host) == 0 && 103 tokval[tmp - host] == '\0') 104 goto match; 105 continue; 106 } 107 match: 108 while ((t = token()) && t != MACH && t != DEFAULT) switch(t) { 109 110 case LOGIN: 111 if (token()) 112 if (*aname == 0) { 113 *aname = malloc((unsigned) strlen(tokval) + 1); 114 (void) strcpy(*aname, tokval); 115 } else { 116 if (strcmp(*aname, tokval)) 117 goto next; 118 } 119 break; 120 case PASSWD: 121 if (strcmp(*aname, "anonymous") && 122 fstat(fileno(cfile), &stb) >= 0 && 123 (stb.st_mode & 077) != 0) { 124 warnx("Error: .netrc file is readable by others."); 125 warnx("Remove password or make file unreadable by others."); 126 goto bad; 127 } 128 if (token() && *apass == 0) { 129 *apass = malloc((unsigned) strlen(tokval) + 1); 130 (void) strcpy(*apass, tokval); 131 } 132 break; 133 case ACCOUNT: 134 if (fstat(fileno(cfile), &stb) >= 0 135 && (stb.st_mode & 077) != 0) { 136 warnx("Error: .netrc file is readable by others."); 137 warnx("Remove account or make file unreadable by others."); 138 goto bad; 139 } 140 if (token() && *aacct == 0) { 141 *aacct = malloc((unsigned) strlen(tokval) + 1); 142 (void) strcpy(*aacct, tokval); 143 } 144 break; 145 case MACDEF: 146 if (proxy) { 147 (void) fclose(cfile); 148 return (0); 149 } 150 while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t'); 151 if (c == EOF || c == '\n') { 152 printf("Missing macdef name argument.\n"); 153 goto bad; 154 } 155 if (macnum == 16) { 156 printf("Limit of 16 macros have already been defined\n"); 157 goto bad; 158 } 159 tmp = macros[macnum].mac_name; 160 *tmp++ = c; 161 for (i=0; i < 8 && (c=getc(cfile)) != EOF && 162 !isspace(c); ++i) { 163 *tmp++ = c; 164 } 165 if (c == EOF) { 166 printf("Macro definition missing null line terminator.\n"); 167 goto bad; 168 } 169 *tmp = '\0'; 170 if (c != '\n') { 171 while ((c=getc(cfile)) != EOF && c != '\n'); 172 } 173 if (c == EOF) { 174 printf("Macro definition missing null line terminator.\n"); 175 goto bad; 176 } 177 if (macnum == 0) { 178 macros[macnum].mac_start = macbuf; 179 } 180 else { 181 macros[macnum].mac_start = macros[macnum-1].mac_end + 1; 182 } 183 tmp = macros[macnum].mac_start; 184 while (tmp != macbuf + 4096) { 185 if ((c=getc(cfile)) == EOF) { 186 printf("Macro definition missing null line terminator.\n"); 187 goto bad; 188 } 189 *tmp = c; 190 if (*tmp == '\n') { 191 if (*(tmp-1) == '\0') { 192 macros[macnum++].mac_end = tmp - 1; 193 break; 194 } 195 *tmp = '\0'; 196 } 197 tmp++; 198 } 199 if (tmp == macbuf + 4096) { 200 printf("4K macro buffer exceeded\n"); 201 goto bad; 202 } 203 break; 204 default: 205 warnx("Unknown .netrc keyword %s", tokval); 206 break; 207 } 208 goto done; 209 } 210 done: 211 (void) fclose(cfile); 212 return (0); 213 bad: 214 (void) fclose(cfile); 215 return (-1); 216 } 217 218 static int 219 token() 220 { 221 char *cp; 222 int c; 223 struct toktab *t; 224 225 if (feof(cfile) || ferror(cfile)) 226 return (0); 227 while ((c = getc(cfile)) != EOF && 228 (c == '\n' || c == '\t' || c == ' ' || c == ',')) 229 continue; 230 if (c == EOF) 231 return (0); 232 cp = tokval; 233 if (c == '"') { 234 while ((c = getc(cfile)) != EOF && c != '"') { 235 if (c == '\\') 236 c = getc(cfile); 237 *cp++ = c; 238 } 239 } else { 240 *cp++ = c; 241 while ((c = getc(cfile)) != EOF 242 && c != '\n' && c != '\t' && c != ' ' && c != ',') { 243 if (c == '\\') 244 c = getc(cfile); 245 *cp++ = c; 246 } 247 } 248 *cp = 0; 249 if (tokval[0] == 0) 250 return (0); 251 for (t = toktab; t->tokstr; t++) 252 if (!strcmp(t->tokstr, tokval)) 253 return (t->tval); 254 return (ID); 255 } 256