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