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