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