- Remove unnecessary casts
[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.3 2003/10/04 20:36:45 hmp 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(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(const char *host, char **aname, char **apass, char **aacct)
86 {
87         char *hdir, buf[BUFSIZ], *tmp;
88         char myname[MAXHOSTNAMELEN], *mydomain;
89         int t, i, c, usedefault = 0;
90         struct stat stb;
91
92         hdir = getenv("HOME");
93         if (hdir == NULL)
94                 hdir = ".";
95         if (strlen(hdir) + sizeof(".netrc") < sizeof(buf)) {
96                 (void)snprintf(buf, sizeof buf, "%s/.netrc", hdir);
97         } else {
98                 warnx("%s/.netrc: %s", hdir, strerror(ENAMETOOLONG));
99                 return (0);
100         }
101         cfile = fopen(buf, "r");
102         if (cfile == NULL) {
103                 if (errno != ENOENT)
104                         warn("%s", buf);
105                 return (0);
106         }
107         if (gethostname(myname, sizeof(myname)) < 0)
108                 myname[0] = '\0';
109         if ((mydomain = strchr(myname, '.')) == NULL)
110                 mydomain = "";
111 next:
112         while ((t = token())) switch(t) {
113
114         case DEFAULT:
115                 usedefault = 1;
116                 /* FALL THROUGH */
117
118         case MACH:
119                 if (!usedefault) {
120                         if (token() != ID)
121                                 continue;
122                         /*
123                          * Allow match either for user's input host name
124                          * or official hostname.  Also allow match of
125                          * incompletely-specified host in local domain.
126                          */
127                         if (strcasecmp(host, tokval) == 0)
128                                 goto match;
129                         if (strcasecmp(hostname, tokval) == 0)
130                                 goto match;
131                         if ((tmp = strchr(hostname, '.')) != NULL &&
132                             strcasecmp(tmp, mydomain) == 0 &&
133                             strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
134                             tokval[tmp - hostname] == '\0')
135                                 goto match;
136                         if ((tmp = strchr(host, '.')) != NULL &&
137                             strcasecmp(tmp, mydomain) == 0 &&
138                             strncasecmp(host, tokval, tmp - host) == 0 &&
139                             tokval[tmp - host] == '\0')
140                                 goto match;
141                         continue;
142                 }
143         match:
144                 while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
145
146                 case LOGIN:
147                         if (token()) {
148                                 if (*aname == NULL) {
149                                         *aname = strdup(tokval);
150                                         if (*aname == NULL)
151                                                 err(1, "can't strdup *aname");
152                                 } else {
153                                         if (strcmp(*aname, tokval))
154                                                 goto next;
155                                 }
156                         }
157                         break;
158                 case PASSWD:
159                         if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
160                             fstat(fileno(cfile), &stb) >= 0 &&
161                             (stb.st_mode & 077) != 0) {
162         warnx("Error: .netrc file is readable by others.");
163         warnx("Remove password or make file unreadable by others.");
164                                 goto bad;
165                         }
166                         if (token() && *apass == NULL) {
167                                 *apass = strdup(tokval);
168                                 if (*apass == NULL)
169                                         err(1, "can't strdup *apass");
170                         }
171                         break;
172                 case ACCOUNT:
173                         if (fstat(fileno(cfile), &stb) >= 0
174                             && (stb.st_mode & 077) != 0) {
175         warnx("Error: .netrc file is readable by others.");
176         warnx("Remove account or make file unreadable by others.");
177                                 goto bad;
178                         }
179                         if (token() && *aacct == NULL) {
180                                 *aacct = strdup(tokval);
181                                 if (*aacct == NULL)
182                                         err(1, "can't strdup *aacct");
183                         }
184                         break;
185                 case MACDEF:
186                         if (proxy) {
187                                 (void)fclose(cfile);
188                                 return (0);
189                         }
190                         while ((c=getc(cfile)) != EOF)
191                                 if (c != ' ' && c != '\t')
192                                         break;
193                         if (c == EOF || c == '\n') {
194                                 puts("Missing macdef name argument.");
195                                 goto bad;
196                         }
197                         if (macnum == 16) {
198                                 puts(
199 "Limit of 16 macros have already been defined.");
200                                 goto bad;
201                         }
202                         tmp = macros[macnum].mac_name;
203                         *tmp++ = c;
204                         for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
205                              (!isascii(c) || !isspace(c)); ++i) {
206                                 *tmp++ = c;
207                         }
208                         if (c == EOF) {
209                                 puts(
210 "Macro definition missing null line terminator.");
211                                 goto bad;
212                         }
213                         *tmp = '\0';
214                         if (c != '\n') {
215                                 while ((c=getc(cfile)) != EOF && c != '\n');
216                         }
217                         if (c == EOF) {
218                                 puts(
219 "Macro definition missing null line terminator.");
220                                 goto bad;
221                         }
222                         if (macnum == 0) {
223                                 macros[macnum].mac_start = macbuf;
224                         }
225                         else {
226                                 macros[macnum].mac_start =
227                                     macros[macnum-1].mac_end + 1;
228                         }
229                         tmp = macros[macnum].mac_start;
230                         while (tmp != macbuf + 4096) {
231                                 if ((c=getc(cfile)) == EOF) {
232                                 puts(
233 "Macro definition missing null line terminator.");
234                                         goto bad;
235                                 }
236                                 *tmp = c;
237                                 if (*tmp == '\n') {
238                                         if (*(tmp-1) == '\0') {
239                                            macros[macnum++].mac_end = tmp - 1;
240                                            break;
241                                         }
242                                         *tmp = '\0';
243                                 }
244                                 tmp++;
245                         }
246                         if (tmp == macbuf + 4096) {
247                                 puts("4K macro buffer exceeded.");
248                                 goto bad;
249                         }
250                         break;
251                 default:
252                         warnx("Unknown .netrc keyword %s", tokval);
253                         break;
254                 }
255                 goto done;
256         }
257 done:
258         (void)fclose(cfile);
259         return (0);
260 bad:
261         (void)fclose(cfile);
262         return (-1);
263 }
264
265 static int
266 token(void)
267 {
268         char *cp;
269         int c;
270         struct toktab *t;
271
272         if (feof(cfile) || ferror(cfile))
273                 return (0);
274         while ((c = getc(cfile)) != EOF &&
275             (c == '\n' || c == '\t' || c == ' ' || c == ','))
276                 continue;
277         if (c == EOF)
278                 return (0);
279         cp = tokval;
280         if (c == '"') {
281                 while ((c = getc(cfile)) != EOF && c != '"') {
282                         if (c == '\\')
283                                 c = getc(cfile);
284                         *cp++ = c;
285                 }
286         } else {
287                 *cp++ = c;
288                 while ((c = getc(cfile)) != EOF
289                     && c != '\n' && c != '\t' && c != ' ' && c != ',') {
290                         if (c == '\\')
291                                 c = getc(cfile);
292                         *cp++ = c;
293                 }
294         }
295         *cp = 0;
296         if (tokval[0] == 0)
297                 return (0);
298         for (t = toktab; t->tokstr; t++)
299                 if (!strcmp(t->tokstr, tokval))
300                         return (t->tval);
301         return (ID);
302 }