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