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