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