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