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