Update.
[kopensolaris-gnu/glibc.git] / inet / 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 #ifndef lint
35 static char sccsid[] = "@(#)ruserpass.c 8.3 (Berkeley) 4/2/94";
36 #endif /* not lint */
37
38 #include <sys/types.h>
39 #include <sys/stat.h>
40
41 #include <assert.h>
42 #include <ctype.h>
43 #include <err.h>
44 #include <errno.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49
50 /* #include "ftp_var.h" */
51
52 static  int token __P((void));
53 static  FILE *cfile;
54
55 #define DEFAULT 1
56 #define LOGIN   2
57 #define PASSWD  3
58 #define ACCOUNT 4
59 #define MACDEF  5
60 #define ID      10
61 #define MACHINE 11
62
63 static char tokval[100];
64
65 static struct toktab {
66         const char *tokstr;
67         int tval;
68 } toktab[]= {
69         { "default",    DEFAULT },
70         { "login",      LOGIN },
71         { "password",   PASSWD },
72         { "passwd",     PASSWD },
73         { "account",    ACCOUNT },
74         { "machine",    MACHINE },
75         { "macdef",     MACDEF },
76         { NULL,         0 }
77 };
78
79
80
81 int
82 ruserpass(host, aname, apass)
83         char *host, **aname, **apass;
84 {
85         char *hdir, *buf, *tmp;
86         char myname[1024], *mydomain;
87         int t, i, c, usedefault = 0;
88         struct stat stb;
89
90         hdir = __secure_getenv("HOME");
91         if (hdir == NULL) {
92                 /* If we can't get HOME, fail instead of trying ".",
93                    which is no improvement. This really should call
94                    getpwuid(getuid()).  */
95                 /*hdir = ".";*/
96                 return -1;
97         }
98
99         buf = alloca (strlen (hdir) + 8);
100
101         __stpcpy (__stpcpy (buf, hdir), "/.netrc");
102         cfile = fopen(buf, "r");
103         if (cfile == NULL) {
104                 if (errno != ENOENT)
105                         warn("%s", buf);
106                 return (0);
107         }
108         if (__gethostname(myname, sizeof(myname)) < 0)
109                 myname[0] = '\0';
110         if ((mydomain = strchr(myname, '.')) == NULL)
111                 mydomain = "";
112 next:
113         while ((t = token())) switch(t) {
114
115         case DEFAULT:
116                 usedefault = 1;
117                 /* FALL THROUGH */
118
119         case MACHINE:
120                 if (!usedefault) {
121                         if (token() != ID)
122                                 continue;
123                         /*
124                          * Allow match either for user's input host name
125                          * or official hostname.  Also allow match of
126                          * incompletely-specified host in local domain.
127                          */
128                         if (__strcasecmp(host, tokval) == 0)
129                                 goto match;
130 /*                      if (__strcasecmp(hostname, tokval) == 0)
131                                 goto match;
132                         if ((tmp = strchr(hostname, '.')) != NULL &&
133                             __strcasecmp(tmp, mydomain) == 0 &&
134                             __strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
135                             tokval[tmp - hostname] == '\0')
136                                 goto match; */
137                         if ((tmp = strchr(host, '.')) != NULL &&
138                             __strcasecmp(tmp, mydomain) == 0 &&
139                             __strncasecmp(host, tokval, tmp - host) == 0 &&
140                             tokval[tmp - host] == '\0')
141                                 goto match;
142                         continue;
143                 }
144         match:
145                 while ((t = token()) && t != MACHINE && t != DEFAULT) switch(t) {
146
147                 case LOGIN:
148                         if (token())
149                                 if (*aname == 0) {
150                                         *aname = malloc((unsigned) strlen(tokval) + 1);
151                                         (void) strcpy(*aname, tokval);
152                                 } else {
153                                         if (strcmp(*aname, tokval))
154                                                 goto next;
155                                 }
156                         break;
157                 case PASSWD:
158                         if (strcmp(*aname, "anonymous") &&
159                             fstat(fileno(cfile), &stb) >= 0 &&
160                             (stb.st_mode & 077) != 0) {
161         warnx(_("Error: .netrc file is readable by others."));
162         warnx(_("Remove password or make file unreadable by others."));
163                                 goto bad;
164                         }
165                         if (token() && *apass == 0) {
166                                 *apass = malloc((unsigned) strlen(tokval) + 1);
167                                 (void) strcpy(*apass, tokval);
168                         }
169                         break;
170                 case ACCOUNT:
171 #if 0
172                         if (fstat(fileno(cfile), &stb) >= 0
173                             && (stb.st_mode & 077) != 0) {
174         warnx("Error: .netrc file is readable by others.");
175         warnx("Remove account or make file unreadable by others.");
176                                 goto bad;
177                         }
178                         if (token() && *aacct == 0) {
179                                 *aacct = malloc((unsigned) strlen(tokval) + 1);
180                                 (void) strcpy(*aacct, tokval);
181                         }
182 #endif
183                         break;
184                 case MACDEF:
185 #if 0
186                         if (proxy) {
187                                 (void) fclose(cfile);
188                                 return (0);
189                         }
190                         while ((c=getc_unlocked(cfile)) != EOF && c == ' '
191                                || c == '\t');
192                         if (c == EOF || c == '\n') {
193                                 printf("Missing macdef name argument.\n");
194                                 goto bad;
195                         }
196                         if (macnum == 16) {
197                                 printf("Limit of 16 macros have already been defined\n");
198                                 goto bad;
199                         }
200                         tmp = macros[macnum].mac_name;
201                         *tmp++ = c;
202                         for (i=0; i < 8 && (c=getc_unlocked(cfile)) != EOF &&
203                             !isspace(c); ++i) {
204                                 *tmp++ = c;
205                         }
206                         if (c == EOF) {
207                                 printf("Macro definition missing null line terminator.\n");
208                                 goto bad;
209                         }
210                         *tmp = '\0';
211                         if (c != '\n') {
212                                 while ((c=getc_unlocked(cfile)) != EOF
213                                        && c != '\n');
214                         }
215                         if (c == EOF) {
216                                 printf("Macro definition missing null line terminator.\n");
217                                 goto bad;
218                         }
219                         if (macnum == 0) {
220                                 macros[macnum].mac_start = macbuf;
221                         }
222                         else {
223                                 macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
224                         }
225                         tmp = macros[macnum].mac_start;
226                         while (tmp != macbuf + 4096) {
227                                 if ((c=getc_unlocked(cfile)) == EOF) {
228                                 printf("Macro definition missing null line terminator.\n");
229                                         goto bad;
230                                 }
231                                 *tmp = c;
232                                 if (*tmp == '\n') {
233                                         if (*(tmp-1) == '\0') {
234                                            macros[macnum++].mac_end = tmp - 1;
235                                            break;
236                                         }
237                                         *tmp = '\0';
238                                 }
239                                 tmp++;
240                         }
241                         if (tmp == macbuf + 4096) {
242                                 printf("4K macro buffer exceeded\n");
243                                 goto bad;
244                         }
245 #endif
246                         break;
247                 default:
248                         warnx(_("Unknown .netrc keyword %s"), tokval);
249                         break;
250                 }
251                 goto done;
252         }
253 done:
254         (void) fclose(cfile);
255         return (0);
256 bad:
257         (void) fclose(cfile);
258         return (-1);
259 }
260
261 static int
262 token()
263 {
264         char *cp;
265         int c;
266         struct toktab *t;
267
268         if (feof_unlocked(cfile) || ferror_unlocked(cfile))
269                 return (0);
270         while ((c = getc_unlocked(cfile)) != EOF &&
271             (c == '\n' || c == '\t' || c == ' ' || c == ','))
272                 continue;
273         if (c == EOF)
274                 return (0);
275         cp = tokval;
276         if (c == '"') {
277                 while ((c = getc_unlocked(cfile)) != EOF && c != '"') {
278                         if (c == '\\')
279                                 c = getc_unlocked(cfile);
280                         *cp++ = c;
281                 }
282         } else {
283                 *cp++ = c;
284                 while ((c = getc_unlocked(cfile)) != EOF
285                     && c != '\n' && c != '\t' && c != ' ' && c != ',') {
286                         if (c == '\\')
287                                 c = getc_unlocked(cfile);
288                         *cp++ = c;
289                 }
290         }
291         *cp = 0;
292         if (tokval[0] == 0)
293                 return (0);
294         for (t = toktab; t->tokstr; t++)
295                 if (!strcmp(t->tokstr, tokval))
296                         return (t->tval);
297         return (ID);
298 }