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