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