xref: /original-bsd/usr.bin/ftp/ruserpass.c (revision 3588a932)
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.3 (Berkeley) 03/01/91";
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 not correct mode.\n");
122 	fprintf(stderr, "Remove password or correct mode.\n");
123 				goto bad;
124 			}
125 			if (token() && *apass == 0) {
126 				*apass = malloc((unsigned) strlen(tokval) + 1);
127 				(void) strcpy(*apass, tokval);
128 			}
129 			break;
130 		case ACCOUNT:
131 			if (fstat(fileno(cfile), &stb) >= 0
132 			    && (stb.st_mode & 077) != 0) {
133 	fprintf(stderr, "Error - .netrc file not correct mode.\n");
134 	fprintf(stderr, "Remove account or correct mode.\n");
135 				goto bad;
136 			}
137 			if (token() && *aacct == 0) {
138 				*aacct = malloc((unsigned) strlen(tokval) + 1);
139 				(void) strcpy(*aacct, tokval);
140 			}
141 			break;
142 		case MACDEF:
143 			if (proxy) {
144 				(void) fclose(cfile);
145 				return(0);
146 			}
147 			while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t');
148 			if (c == EOF || c == '\n') {
149 				printf("Missing macdef name argument.\n");
150 				goto bad;
151 			}
152 			if (macnum == 16) {
153 				printf("Limit of 16 macros have already been defined\n");
154 				goto bad;
155 			}
156 			tmp = macros[macnum].mac_name;
157 			*tmp++ = c;
158 			for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
159 			    !isspace(c); ++i) {
160 				*tmp++ = c;
161 			}
162 			if (c == EOF) {
163 				printf("Macro definition missing null line terminator.\n");
164 				goto bad;
165 			}
166 			*tmp = '\0';
167 			if (c != '\n') {
168 				while ((c=getc(cfile)) != EOF && c != '\n');
169 			}
170 			if (c == EOF) {
171 				printf("Macro definition missing null line terminator.\n");
172 				goto bad;
173 			}
174 			if (macnum == 0) {
175 				macros[macnum].mac_start = macbuf;
176 			}
177 			else {
178 				macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
179 			}
180 			tmp = macros[macnum].mac_start;
181 			while (tmp != macbuf + 4096) {
182 				if ((c=getc(cfile)) == EOF) {
183 				printf("Macro definition missing null line terminator.\n");
184 					goto bad;
185 				}
186 				*tmp = c;
187 				if (*tmp == '\n') {
188 					if (*(tmp-1) == '\0') {
189 					   macros[macnum++].mac_end = tmp - 1;
190 					   break;
191 					}
192 					*tmp = '\0';
193 				}
194 				tmp++;
195 			}
196 			if (tmp == macbuf + 4096) {
197 				printf("4K macro buffer exceeded\n");
198 				goto bad;
199 			}
200 			break;
201 		default:
202 	fprintf(stderr, "Unknown .netrc keyword %s\n", tokval);
203 			break;
204 		}
205 		goto done;
206 	}
207 done:
208 	(void) fclose(cfile);
209 	return(0);
210 bad:
211 	(void) fclose(cfile);
212 	return(-1);
213 }
214 
215 static
216 token()
217 {
218 	char *cp;
219 	int c;
220 	struct toktab *t;
221 
222 	if (feof(cfile))
223 		return (0);
224 	while ((c = getc(cfile)) != EOF &&
225 	    (c == '\n' || c == '\t' || c == ' ' || c == ','))
226 		continue;
227 	if (c == EOF)
228 		return (0);
229 	cp = tokval;
230 	if (c == '"') {
231 		while ((c = getc(cfile)) != EOF && c != '"') {
232 			if (c == '\\')
233 				c = getc(cfile);
234 			*cp++ = c;
235 		}
236 	} else {
237 		*cp++ = c;
238 		while ((c = getc(cfile)) != EOF
239 		    && c != '\n' && c != '\t' && c != ' ' && c != ',') {
240 			if (c == '\\')
241 				c = getc(cfile);
242 			*cp++ = c;
243 		}
244 	}
245 	*cp = 0;
246 	if (tokval[0] == 0)
247 		return (0);
248 	for (t = toktab; t->tokstr; t++)
249 		if (!strcmp(t->tokstr, tokval))
250 			return (t->tval);
251 	return (ID);
252 }
253