1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 /*static char sccsid[] = "from: @(#)ruserpass.c 5.3 (Berkeley) 3/1/91";*/ 36 static char rcsid[] = "$Id: ruserpass.c,v 1.2 1993/08/01 18:15:24 mycroft Exp $"; 37 #endif /* not lint */ 38 39 #include <sys/types.h> 40 #include <stdio.h> 41 #include <utmp.h> 42 #include <ctype.h> 43 #include <sys/stat.h> 44 #include <errno.h> 45 #include "ftp_var.h" 46 47 char *renvlook(), *malloc(), *index(), *getenv(), *getpass(), *getlogin(); 48 char *strcpy(); 49 struct utmp *getutmp(); 50 static FILE *cfile; 51 52 #define DEFAULT 1 53 #define LOGIN 2 54 #define PASSWD 3 55 #define ACCOUNT 4 56 #define MACDEF 5 57 #define ID 10 58 #define MACH 11 59 60 static char tokval[100]; 61 62 static struct toktab { 63 char *tokstr; 64 int tval; 65 } toktab[]= { 66 "default", DEFAULT, 67 "login", LOGIN, 68 "password", PASSWD, 69 "passwd", PASSWD, 70 "account", ACCOUNT, 71 "machine", MACH, 72 "macdef", MACDEF, 73 0, 0 74 }; 75 76 ruserpass(host, aname, apass, aacct) 77 char *host, **aname, **apass, **aacct; 78 { 79 char *hdir, buf[BUFSIZ], *tmp; 80 char myname[MAXHOSTNAMELEN], *mydomain; 81 int t, i, c, usedefault = 0; 82 struct stat stb; 83 static int token(); 84 85 hdir = getenv("HOME"); 86 if (hdir == NULL) 87 hdir = "."; 88 (void) sprintf(buf, "%s/.netrc", hdir); 89 cfile = fopen(buf, "r"); 90 if (cfile == NULL) { 91 if (errno != ENOENT) 92 perror(buf); 93 return(0); 94 } 95 if (gethostname(myname, sizeof(myname)) < 0) 96 myname[0] = '\0'; 97 if ((mydomain = index(myname, '.')) == NULL) 98 mydomain = ""; 99 next: 100 while ((t = token())) switch(t) { 101 102 case DEFAULT: 103 usedefault = 1; 104 /* FALL THROUGH */ 105 106 case MACH: 107 if (!usedefault) { 108 if (token() != ID) 109 continue; 110 /* 111 * Allow match either for user's input host name 112 * or official hostname. Also allow match of 113 * incompletely-specified host in local domain. 114 */ 115 if (strcasecmp(host, tokval) == 0) 116 goto match; 117 if (strcasecmp(hostname, tokval) == 0) 118 goto match; 119 if ((tmp = index(hostname, '.')) != NULL && 120 strcasecmp(tmp, mydomain) == 0 && 121 strncasecmp(hostname, tokval, tmp-hostname) == 0 && 122 tokval[tmp - hostname] == '\0') 123 goto match; 124 if ((tmp = index(host, '.')) != NULL && 125 strcasecmp(tmp, mydomain) == 0 && 126 strncasecmp(host, tokval, tmp - host) == 0 && 127 tokval[tmp - host] == '\0') 128 goto match; 129 continue; 130 } 131 match: 132 while ((t = token()) && t != MACH && t != DEFAULT) switch(t) { 133 134 case LOGIN: 135 if (token()) 136 if (*aname == 0) { 137 *aname = malloc((unsigned) strlen(tokval) + 1); 138 (void) strcpy(*aname, tokval); 139 } else { 140 if (strcmp(*aname, tokval)) 141 goto next; 142 } 143 break; 144 case PASSWD: 145 if (strcmp(*aname, "anonymous") && 146 fstat(fileno(cfile), &stb) >= 0 && 147 (stb.st_mode & 077) != 0) { 148 fprintf(stderr, "Error - .netrc file not correct mode.\n"); 149 fprintf(stderr, "Remove password or correct mode.\n"); 150 goto bad; 151 } 152 if (token() && *apass == 0) { 153 *apass = malloc((unsigned) strlen(tokval) + 1); 154 (void) strcpy(*apass, tokval); 155 } 156 break; 157 case ACCOUNT: 158 if (fstat(fileno(cfile), &stb) >= 0 159 && (stb.st_mode & 077) != 0) { 160 fprintf(stderr, "Error - .netrc file not correct mode.\n"); 161 fprintf(stderr, "Remove account or correct mode.\n"); 162 goto bad; 163 } 164 if (token() && *aacct == 0) { 165 *aacct = malloc((unsigned) strlen(tokval) + 1); 166 (void) strcpy(*aacct, tokval); 167 } 168 break; 169 case MACDEF: 170 if (proxy) { 171 (void) fclose(cfile); 172 return(0); 173 } 174 while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t'); 175 if (c == EOF || c == '\n') { 176 printf("Missing macdef name argument.\n"); 177 goto bad; 178 } 179 if (macnum == 16) { 180 printf("Limit of 16 macros have already been defined\n"); 181 goto bad; 182 } 183 tmp = macros[macnum].mac_name; 184 *tmp++ = c; 185 for (i=0; i < 8 && (c=getc(cfile)) != EOF && 186 !isspace(c); ++i) { 187 *tmp++ = c; 188 } 189 if (c == EOF) { 190 printf("Macro definition missing null line terminator.\n"); 191 goto bad; 192 } 193 *tmp = '\0'; 194 if (c != '\n') { 195 while ((c=getc(cfile)) != EOF && c != '\n'); 196 } 197 if (c == EOF) { 198 printf("Macro definition missing null line terminator.\n"); 199 goto bad; 200 } 201 if (macnum == 0) { 202 macros[macnum].mac_start = macbuf; 203 } 204 else { 205 macros[macnum].mac_start = macros[macnum-1].mac_end + 1; 206 } 207 tmp = macros[macnum].mac_start; 208 while (tmp != macbuf + 4096) { 209 if ((c=getc(cfile)) == EOF) { 210 printf("Macro definition missing null line terminator.\n"); 211 goto bad; 212 } 213 *tmp = c; 214 if (*tmp == '\n') { 215 if (*(tmp-1) == '\0') { 216 macros[macnum++].mac_end = tmp - 1; 217 break; 218 } 219 *tmp = '\0'; 220 } 221 tmp++; 222 } 223 if (tmp == macbuf + 4096) { 224 printf("4K macro buffer exceeded\n"); 225 goto bad; 226 } 227 break; 228 default: 229 fprintf(stderr, "Unknown .netrc keyword %s\n", tokval); 230 break; 231 } 232 goto done; 233 } 234 done: 235 (void) fclose(cfile); 236 return(0); 237 bad: 238 (void) fclose(cfile); 239 return(-1); 240 } 241 242 static 243 token() 244 { 245 char *cp; 246 int c; 247 struct toktab *t; 248 249 if (feof(cfile)) 250 return (0); 251 while ((c = getc(cfile)) != EOF && 252 (c == '\n' || c == '\t' || c == ' ' || c == ',')) 253 continue; 254 if (c == EOF) 255 return (0); 256 cp = tokval; 257 if (c == '"') { 258 while ((c = getc(cfile)) != EOF && c != '"') { 259 if (c == '\\') 260 c = getc(cfile); 261 *cp++ = c; 262 } 263 } else { 264 *cp++ = c; 265 while ((c = getc(cfile)) != EOF 266 && c != '\n' && c != '\t' && c != ' ' && c != ',') { 267 if (c == '\\') 268 c = getc(cfile); 269 *cp++ = c; 270 } 271 } 272 *cp = 0; 273 if (tokval[0] == 0) 274 return (0); 275 for (t = toktab; t->tokstr; t++) 276 if (!strcmp(t->tokstr, tokval)) 277 return (t->tval); 278 return (ID); 279 } 280