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