GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ftp/ruserpass.c Lines: 0 145 0.0 %
Date: 2016-12-06 Branches: 0 188 0.0 %

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