Annotation of src/usr.bin/ftp/ruserpass.c, Revision 1.33
1.33 ! lukem 1: /* $NetBSD: ruserpass.c,v 1.32 2007/04/12 01:28:13 lukem Exp $ */
1.6 tls 2:
1.1 cgd 3: /*
1.3 cgd 4: * Copyright (c) 1985, 1993, 1994
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 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.
1.29 agc 15: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
1.14 lukem 32: #include <sys/cdefs.h>
1.1 cgd 33: #ifndef lint
1.11 lukem 34: #if 0
1.6 tls 35: static char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 4/27/95";
1.11 lukem 36: #else
1.33 ! lukem 37: __RCSID("$NetBSD: ruserpass.c,v 1.32 2007/04/12 01:28:13 lukem Exp $");
1.11 lukem 38: #endif
1.1 cgd 39: #endif /* not lint */
40:
41: #include <sys/types.h>
1.3 cgd 42: #include <sys/stat.h>
43:
1.1 cgd 44: #include <ctype.h>
1.3 cgd 45: #include <err.h>
1.1 cgd 46: #include <errno.h>
1.21 lukem 47: #include <netdb.h>
1.3 cgd 48: #include <stdio.h>
49: #include <stdlib.h>
50: #include <string.h>
51: #include <unistd.h>
52:
1.1 cgd 53: #include "ftp_var.h"
54:
1.26 lukem 55: static int token(void);
1.1 cgd 56: static FILE *cfile;
57:
58: #define DEFAULT 1
59: #define LOGIN 2
60: #define PASSWD 3
1.25 lukem 61: #define ACCOUNT 4
62: #define MACDEF 5
1.1 cgd 63: #define ID 10
64: #define MACH 11
65:
66: static char tokval[100];
67:
68: static struct toktab {
1.30 lukem 69: const char *tokstr;
1.1 cgd 70: int tval;
1.17 lukem 71: } toktab[] = {
1.3 cgd 72: { "default", DEFAULT },
73: { "login", LOGIN },
74: { "password", PASSWD },
75: { "passwd", PASSWD },
76: { "account", ACCOUNT },
77: { "machine", MACH },
78: { "macdef", MACDEF },
79: { NULL, 0 }
1.1 cgd 80: };
81:
1.3 cgd 82: int
1.30 lukem 83: ruserpass(const char *host, char **aname, char **apass, char **aacct)
1.1 cgd 84: {
1.28 lukem 85: char *tmp;
1.30 lukem 86: const char *mydomain;
87: char myname[MAXHOSTNAMELEN + 1];
1.1 cgd 88: int t, i, c, usedefault = 0;
89: struct stat stb;
90:
1.28 lukem 91: if (netrc[0] == '\0')
1.8 lukem 92: return (0);
1.28 lukem 93: cfile = fopen(netrc, "r");
1.1 cgd 94: if (cfile == NULL) {
95: if (errno != ENOENT)
1.33 ! lukem 96: warn("Can't read `%s'", netrc);
1.3 cgd 97: return (0);
1.1 cgd 98: }
99: if (gethostname(myname, sizeof(myname)) < 0)
100: myname[0] = '\0';
1.18 mrg 101: myname[sizeof(myname) - 1] = '\0';
1.3 cgd 102: if ((mydomain = strchr(myname, '.')) == NULL)
1.1 cgd 103: mydomain = "";
1.27 lukem 104: next:
1.32 lukem 105: while ((t = token()) > 0) switch(t) {
1.1 cgd 106:
107: case DEFAULT:
108: usedefault = 1;
109: /* FALL THROUGH */
110:
111: case MACH:
112: if (!usedefault) {
1.32 lukem 113: if ((t = token()) == -1)
114: goto bad;
115: if (t != ID)
1.1 cgd 116: continue;
117: /*
118: * Allow match either for user's input host name
1.7 lukem 119: * or official hostname. Also allow match of
1.1 cgd 120: * incompletely-specified host in local domain.
121: */
122: if (strcasecmp(host, tokval) == 0)
123: goto match;
124: if (strcasecmp(hostname, tokval) == 0)
125: goto match;
1.3 cgd 126: if ((tmp = strchr(hostname, '.')) != NULL &&
1.1 cgd 127: strcasecmp(tmp, mydomain) == 0 &&
128: strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
129: tokval[tmp - hostname] == '\0')
130: goto match;
1.3 cgd 131: if ((tmp = strchr(host, '.')) != NULL &&
1.1 cgd 132: strcasecmp(tmp, mydomain) == 0 &&
133: strncasecmp(host, tokval, tmp - host) == 0 &&
134: tokval[tmp - host] == '\0')
135: goto match;
136: continue;
137: }
138: match:
1.32 lukem 139: while ((t = token()) > 0 &&
140: t != MACH && t != DEFAULT) switch(t) {
1.1 cgd 141:
142: case LOGIN:
1.32 lukem 143: if ((t = token()) == -1)
144: goto bad;
145: if (t) {
1.20 lukem 146: if (*aname == NULL)
1.31 christos 147: *aname = ftp_strdup(tokval);
1.20 lukem 148: else {
1.1 cgd 149: if (strcmp(*aname, tokval))
150: goto next;
151: }
1.16 christos 152: }
1.1 cgd 153: break;
154: case PASSWD:
1.6 tls 155: if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
1.1 cgd 156: fstat(fileno(cfile), &stb) >= 0 &&
157: (stb.st_mode & 077) != 0) {
1.33 ! lukem 158: warnx("Error: .netrc file is readable by others");
! 159: warnx("Remove password or make file unreadable by others");
1.1 cgd 160: goto bad;
161: }
1.32 lukem 162: if ((t = token()) == -1)
163: goto bad;
164: if (t && *apass == NULL)
1.31 christos 165: *apass = ftp_strdup(tokval);
1.1 cgd 166: break;
167: case ACCOUNT:
168: if (fstat(fileno(cfile), &stb) >= 0
169: && (stb.st_mode & 077) != 0) {
1.33 ! lukem 170: warnx("Error: .netrc file is readable by others");
! 171: warnx("Remove account or make file unreadable by others");
1.1 cgd 172: goto bad;
173: }
1.32 lukem 174: if ((t = token()) == -1)
175: goto bad;
176: if (t && *aacct == NULL)
1.31 christos 177: *aacct = ftp_strdup(tokval);
1.1 cgd 178: break;
179: case MACDEF:
180: if (proxy) {
1.12 lukem 181: (void)fclose(cfile);
1.3 cgd 182: return (0);
1.1 cgd 183: }
1.17 lukem 184: while ((c = getc(cfile)) != EOF)
1.11 lukem 185: if (c != ' ' && c != '\t')
186: break;
1.1 cgd 187: if (c == EOF || c == '\n') {
1.17 lukem 188: fputs("Missing macdef name argument.\n",
189: ttyout);
1.1 cgd 190: goto bad;
191: }
192: if (macnum == 16) {
1.17 lukem 193: fputs(
194: "Limit of 16 macros have already been defined.\n",
195: ttyout);
1.1 cgd 196: goto bad;
197: }
198: tmp = macros[macnum].mac_name;
199: *tmp++ = c;
1.17 lukem 200: for (i = 0; i < 8 && (c = getc(cfile)) != EOF &&
1.1 cgd 201: !isspace(c); ++i) {
202: *tmp++ = c;
203: }
204: if (c == EOF) {
1.17 lukem 205: fputs(
206: "Macro definition missing null line terminator.\n",
207: ttyout);
1.1 cgd 208: goto bad;
209: }
210: *tmp = '\0';
211: if (c != '\n') {
1.17 lukem 212: while ((c = getc(cfile)) != EOF && c != '\n');
1.1 cgd 213: }
214: if (c == EOF) {
1.17 lukem 215: fputs(
216: "Macro definition missing null line terminator.\n",
217: ttyout);
1.1 cgd 218: goto bad;
219: }
220: if (macnum == 0) {
221: macros[macnum].mac_start = macbuf;
222: }
223: else {
1.9 lukem 224: macros[macnum].mac_start =
225: macros[macnum-1].mac_end + 1;
1.1 cgd 226: }
227: tmp = macros[macnum].mac_start;
228: while (tmp != macbuf + 4096) {
1.17 lukem 229: if ((c = getc(cfile)) == EOF) {
230: fputs(
231: "Macro definition missing null line terminator.\n",
232: ttyout);
1.1 cgd 233: goto bad;
234: }
235: *tmp = c;
236: if (*tmp == '\n') {
1.32 lukem 237: if (tmp == macros[macnum].mac_start) {
238: macros[macnum++].mac_end = tmp;
239: break;
240: } else if (*(tmp - 1) == '\0') {
241: macros[macnum++].mac_end =
242: tmp - 1;
243: break;
1.1 cgd 244: }
245: *tmp = '\0';
246: }
247: tmp++;
248: }
249: if (tmp == macbuf + 4096) {
1.17 lukem 250: fputs("4K macro buffer exceeded.\n",
251: ttyout);
1.1 cgd 252: goto bad;
253: }
254: break;
255: default:
1.33 ! lukem 256: warnx("Unknown .netrc keyword `%s'", tokval);
1.1 cgd 257: break;
258: }
259: goto done;
260: }
1.27 lukem 261: done:
1.32 lukem 262: if (t == -1)
263: goto bad;
1.12 lukem 264: (void)fclose(cfile);
1.3 cgd 265: return (0);
1.27 lukem 266: bad:
1.12 lukem 267: (void)fclose(cfile);
1.3 cgd 268: return (-1);
1.1 cgd 269: }
270:
1.3 cgd 271: static int
1.26 lukem 272: token(void)
1.1 cgd 273: {
274: char *cp;
275: int c;
276: struct toktab *t;
277:
1.3 cgd 278: if (feof(cfile) || ferror(cfile))
1.1 cgd 279: return (0);
280: while ((c = getc(cfile)) != EOF &&
281: (c == '\n' || c == '\t' || c == ' ' || c == ','))
282: continue;
283: if (c == EOF)
284: return (0);
285: cp = tokval;
286: if (c == '"') {
287: while ((c = getc(cfile)) != EOF && c != '"') {
288: if (c == '\\')
1.32 lukem 289: if ((c = getc(cfile)) == EOF)
290: break;
1.1 cgd 291: *cp++ = c;
1.32 lukem 292: if (cp == tokval + sizeof(tokval)) {
293: warnx("Token in .netrc too long");
294: return (-1);
295: }
1.1 cgd 296: }
297: } else {
298: *cp++ = c;
299: while ((c = getc(cfile)) != EOF
300: && c != '\n' && c != '\t' && c != ' ' && c != ',') {
301: if (c == '\\')
1.32 lukem 302: if ((c = getc(cfile)) == EOF)
303: break;
1.1 cgd 304: *cp++ = c;
1.32 lukem 305: if (cp == tokval + sizeof(tokval)) {
306: warnx("Token in .netrc too long");
307: return (-1);
308: }
1.1 cgd 309: }
310: }
311: *cp = 0;
312: if (tokval[0] == 0)
313: return (0);
314: for (t = toktab; t->tokstr; t++)
315: if (!strcmp(t->tokstr, tokval))
316: return (t->tval);
317: return (ID);
318: }
CVSweb <webmaster@jp.NetBSD.org>