1b528cefcSMark Murray /*
2b528cefcSMark Murray * Copyright (c) 1985, 1993, 1994
3b528cefcSMark Murray * The Regents of the University of California. All rights reserved.
4b528cefcSMark Murray *
5b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
6b528cefcSMark Murray * modification, are permitted provided that the following conditions
7b528cefcSMark Murray * are met:
8b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
9b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
10b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
12b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
13b528cefcSMark Murray * 3. All advertising materials mentioning features or use of this software
14b528cefcSMark Murray * must display the following acknowledgement:
15b528cefcSMark Murray * This product includes software developed by the University of
16b528cefcSMark Murray * California, Berkeley and its contributors.
17b528cefcSMark Murray * 4. Neither the name of the University nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34b528cefcSMark Murray #include "ftp_locl.h"
35c19800e8SDoug Rabson RCSID("$Id$");
36b528cefcSMark Murray
37b528cefcSMark Murray static int token (void);
38b528cefcSMark Murray static FILE *cfile;
39b528cefcSMark Murray
40b528cefcSMark Murray #define DEFAULT 1
41b528cefcSMark Murray #define LOGIN 2
42b528cefcSMark Murray #define PASSWD 3
43b528cefcSMark Murray #define ACCOUNT 4
44b528cefcSMark Murray #define MACDEF 5
45b528cefcSMark Murray #define PROT 6
46b528cefcSMark Murray #define ID 10
47b528cefcSMark Murray #define MACH 11
48b528cefcSMark Murray
49b528cefcSMark Murray static char tokval[100];
50b528cefcSMark Murray
51b528cefcSMark Murray static struct toktab {
52b528cefcSMark Murray char *tokstr;
53b528cefcSMark Murray int tval;
54b528cefcSMark Murray } toktab[]= {
55b528cefcSMark Murray { "default", DEFAULT },
56b528cefcSMark Murray { "login", LOGIN },
57b528cefcSMark Murray { "password", PASSWD },
58b528cefcSMark Murray { "passwd", PASSWD },
59b528cefcSMark Murray { "account", ACCOUNT },
60b528cefcSMark Murray { "machine", MACH },
61b528cefcSMark Murray { "macdef", MACDEF },
62b528cefcSMark Murray { "prot", PROT },
63b528cefcSMark Murray { NULL, 0 }
64b528cefcSMark Murray };
65b528cefcSMark Murray
66b528cefcSMark Murray /*
67b528cefcSMark Murray * Write a copy of the hostname into `hostname, sz' and return a guess
68b528cefcSMark Murray * as to the `domain' of that hostname.
69b528cefcSMark Murray */
70b528cefcSMark Murray
71b528cefcSMark Murray static char *
guess_domain(char * hostname_str,size_t sz)72c19800e8SDoug Rabson guess_domain (char *hostname_str, size_t sz)
73b528cefcSMark Murray {
74b528cefcSMark Murray struct addrinfo *ai, *a;
75b528cefcSMark Murray struct addrinfo hints;
76b528cefcSMark Murray int error;
77b528cefcSMark Murray char *dot;
78b528cefcSMark Murray
79c19800e8SDoug Rabson if (gethostname (hostname_str, sz) < 0) {
80c19800e8SDoug Rabson strlcpy (hostname_str, "", sz);
81b528cefcSMark Murray return "";
82b528cefcSMark Murray }
83c19800e8SDoug Rabson dot = strchr (hostname_str, '.');
84b528cefcSMark Murray if (dot != NULL)
85b528cefcSMark Murray return dot + 1;
86b528cefcSMark Murray
87b528cefcSMark Murray memset (&hints, 0, sizeof(hints));
88b528cefcSMark Murray hints.ai_flags = AI_CANONNAME;
89b528cefcSMark Murray
90c19800e8SDoug Rabson error = getaddrinfo (hostname_str, NULL, &hints, &ai);
91b528cefcSMark Murray if (error)
92c19800e8SDoug Rabson return hostname_str;
93b528cefcSMark Murray
94b528cefcSMark Murray for (a = ai; a != NULL; a = a->ai_next)
95b528cefcSMark Murray if (a->ai_canonname != NULL) {
96c19800e8SDoug Rabson strlcpy (hostname_str, ai->ai_canonname, sz);
97b528cefcSMark Murray break;
98b528cefcSMark Murray }
99b528cefcSMark Murray freeaddrinfo (ai);
100c19800e8SDoug Rabson dot = strchr (hostname_str, '.');
101b528cefcSMark Murray if (dot != NULL)
102b528cefcSMark Murray return dot + 1;
103b528cefcSMark Murray else
104c19800e8SDoug Rabson return hostname_str;
105b528cefcSMark Murray }
106b528cefcSMark Murray
107b528cefcSMark Murray int
ruserpassword(char * host,char ** aname,char ** apass,char ** aacct)108b528cefcSMark Murray ruserpassword(char *host, char **aname, char **apass, char **aacct)
109b528cefcSMark Murray {
110b528cefcSMark Murray char *hdir, buf[BUFSIZ], *tmp;
111b528cefcSMark Murray int t, i, c, usedefault = 0;
112b528cefcSMark Murray struct stat stb;
113b528cefcSMark Murray
114b528cefcSMark Murray mydomain = guess_domain (myhostname, MaxHostNameLen);
115b528cefcSMark Murray
116b528cefcSMark Murray hdir = getenv("HOME");
117b528cefcSMark Murray if (hdir == NULL)
118b528cefcSMark Murray hdir = ".";
119b528cefcSMark Murray snprintf(buf, sizeof(buf), "%s/.netrc", hdir);
120b528cefcSMark Murray cfile = fopen(buf, "r");
121b528cefcSMark Murray if (cfile == NULL) {
122b528cefcSMark Murray if (errno != ENOENT)
123b528cefcSMark Murray warn("%s", buf);
124b528cefcSMark Murray return (0);
125b528cefcSMark Murray }
126b528cefcSMark Murray
127b528cefcSMark Murray next:
128b528cefcSMark Murray while ((t = token())) switch(t) {
129b528cefcSMark Murray
130b528cefcSMark Murray case DEFAULT:
131b528cefcSMark Murray usedefault = 1;
132b528cefcSMark Murray /* FALL THROUGH */
133b528cefcSMark Murray
134b528cefcSMark Murray case MACH:
135b528cefcSMark Murray if (!usedefault) {
136b528cefcSMark Murray if (token() != ID)
137b528cefcSMark Murray continue;
138b528cefcSMark Murray /*
139b528cefcSMark Murray * Allow match either for user's input host name
140b528cefcSMark Murray * or official hostname. Also allow match of
141b528cefcSMark Murray * incompletely-specified host in local domain.
142b528cefcSMark Murray */
143b528cefcSMark Murray if (strcasecmp(host, tokval) == 0)
144b528cefcSMark Murray goto match;
145b528cefcSMark Murray if (strcasecmp(hostname, tokval) == 0)
146b528cefcSMark Murray goto match;
147b528cefcSMark Murray if ((tmp = strchr(hostname, '.')) != NULL &&
148b528cefcSMark Murray tmp++ &&
149b528cefcSMark Murray strcasecmp(tmp, mydomain) == 0 &&
150b528cefcSMark Murray strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
151b528cefcSMark Murray tokval[tmp - hostname] == '\0')
152b528cefcSMark Murray goto match;
153b528cefcSMark Murray if ((tmp = strchr(host, '.')) != NULL &&
154b528cefcSMark Murray tmp++ &&
155b528cefcSMark Murray strcasecmp(tmp, mydomain) == 0 &&
156b528cefcSMark Murray strncasecmp(host, tokval, tmp - host) == 0 &&
157b528cefcSMark Murray tokval[tmp - host] == '\0')
158b528cefcSMark Murray goto match;
159b528cefcSMark Murray continue;
160b528cefcSMark Murray }
161b528cefcSMark Murray match:
162b528cefcSMark Murray while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
163b528cefcSMark Murray
164b528cefcSMark Murray case LOGIN:
165b528cefcSMark Murray if (token()) {
166b528cefcSMark Murray if (*aname == 0) {
167b528cefcSMark Murray *aname = strdup(tokval);
168b528cefcSMark Murray } else {
169b528cefcSMark Murray if (strcmp(*aname, tokval))
170b528cefcSMark Murray goto next;
171b528cefcSMark Murray }
172b528cefcSMark Murray }
173b528cefcSMark Murray break;
174b528cefcSMark Murray case PASSWD:
175b528cefcSMark Murray if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
176b528cefcSMark Murray fstat(fileno(cfile), &stb) >= 0 &&
177b528cefcSMark Murray (stb.st_mode & 077) != 0) {
178b528cefcSMark Murray warnx("Error: .netrc file is readable by others.");
179b528cefcSMark Murray warnx("Remove password or make file unreadable by others.");
180b528cefcSMark Murray goto bad;
181b528cefcSMark Murray }
182b528cefcSMark Murray if (token() && *apass == 0) {
183b528cefcSMark Murray *apass = strdup(tokval);
184b528cefcSMark Murray }
185b528cefcSMark Murray break;
186b528cefcSMark Murray case ACCOUNT:
187b528cefcSMark Murray if (fstat(fileno(cfile), &stb) >= 0
188b528cefcSMark Murray && (stb.st_mode & 077) != 0) {
189b528cefcSMark Murray warnx("Error: .netrc file is readable by others.");
190b528cefcSMark Murray warnx("Remove account or make file unreadable by others.");
191b528cefcSMark Murray goto bad;
192b528cefcSMark Murray }
193b528cefcSMark Murray if (token() && *aacct == 0) {
194b528cefcSMark Murray *aacct = strdup(tokval);
195b528cefcSMark Murray }
196b528cefcSMark Murray break;
197b528cefcSMark Murray case MACDEF:
198b528cefcSMark Murray if (proxy) {
199b528cefcSMark Murray fclose(cfile);
200b528cefcSMark Murray return (0);
201b528cefcSMark Murray }
202b528cefcSMark Murray while ((c=getc(cfile)) != EOF &&
203b528cefcSMark Murray (c == ' ' || c == '\t'));
204b528cefcSMark Murray if (c == EOF || c == '\n') {
205b528cefcSMark Murray printf("Missing macdef name argument.\n");
206b528cefcSMark Murray goto bad;
207b528cefcSMark Murray }
208b528cefcSMark Murray if (macnum == 16) {
209b528cefcSMark Murray printf("Limit of 16 macros have already been defined\n");
210b528cefcSMark Murray goto bad;
211b528cefcSMark Murray }
212b528cefcSMark Murray tmp = macros[macnum].mac_name;
213b528cefcSMark Murray *tmp++ = c;
214b528cefcSMark Murray for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
215b528cefcSMark Murray !isspace(c); ++i) {
216b528cefcSMark Murray *tmp++ = c;
217b528cefcSMark Murray }
218b528cefcSMark Murray if (c == EOF) {
219b528cefcSMark Murray printf("Macro definition missing null line terminator.\n");
220b528cefcSMark Murray goto bad;
221b528cefcSMark Murray }
222b528cefcSMark Murray *tmp = '\0';
223b528cefcSMark Murray if (c != '\n') {
224b528cefcSMark Murray while ((c=getc(cfile)) != EOF && c != '\n');
225b528cefcSMark Murray }
226b528cefcSMark Murray if (c == EOF) {
227b528cefcSMark Murray printf("Macro definition missing null line terminator.\n");
228b528cefcSMark Murray goto bad;
229b528cefcSMark Murray }
230b528cefcSMark Murray if (macnum == 0) {
231b528cefcSMark Murray macros[macnum].mac_start = macbuf;
232b528cefcSMark Murray }
233b528cefcSMark Murray else {
234b528cefcSMark Murray macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
235b528cefcSMark Murray }
236b528cefcSMark Murray tmp = macros[macnum].mac_start;
237b528cefcSMark Murray while (tmp != macbuf + 4096) {
238b528cefcSMark Murray if ((c=getc(cfile)) == EOF) {
239b528cefcSMark Murray printf("Macro definition missing null line terminator.\n");
240b528cefcSMark Murray goto bad;
241b528cefcSMark Murray }
242b528cefcSMark Murray *tmp = c;
243b528cefcSMark Murray if (*tmp == '\n') {
244b528cefcSMark Murray if (*(tmp-1) == '\0') {
245b528cefcSMark Murray macros[macnum++].mac_end = tmp - 1;
246b528cefcSMark Murray break;
247b528cefcSMark Murray }
248b528cefcSMark Murray *tmp = '\0';
249b528cefcSMark Murray }
250b528cefcSMark Murray tmp++;
251b528cefcSMark Murray }
252b528cefcSMark Murray if (tmp == macbuf + 4096) {
253b528cefcSMark Murray printf("4K macro buffer exceeded\n");
254b528cefcSMark Murray goto bad;
255b528cefcSMark Murray }
256b528cefcSMark Murray break;
257b528cefcSMark Murray case PROT:
258b528cefcSMark Murray token();
259c19800e8SDoug Rabson if(doencrypt == 0 && sec_request_prot(tokval) < 0)
260b528cefcSMark Murray warnx("Unknown protection level \"%s\"", tokval);
261b528cefcSMark Murray break;
262b528cefcSMark Murray default:
263b528cefcSMark Murray warnx("Unknown .netrc keyword %s", tokval);
264b528cefcSMark Murray break;
265b528cefcSMark Murray }
266b528cefcSMark Murray goto done;
267b528cefcSMark Murray }
268b528cefcSMark Murray done:
269b528cefcSMark Murray fclose(cfile);
270b528cefcSMark Murray return (0);
271b528cefcSMark Murray bad:
272b528cefcSMark Murray fclose(cfile);
273b528cefcSMark Murray return (-1);
274b528cefcSMark Murray }
275b528cefcSMark Murray
276b528cefcSMark Murray static int
token(void)277b528cefcSMark Murray token(void)
278b528cefcSMark Murray {
279b528cefcSMark Murray char *cp;
280b528cefcSMark Murray int c;
281b528cefcSMark Murray struct toktab *t;
282b528cefcSMark Murray
283b528cefcSMark Murray if (feof(cfile) || ferror(cfile))
284b528cefcSMark Murray return (0);
285b528cefcSMark Murray while ((c = getc(cfile)) != EOF &&
286b528cefcSMark Murray (c == '\n' || c == '\t' || c == ' ' || c == ','))
287b528cefcSMark Murray continue;
288b528cefcSMark Murray if (c == EOF)
289b528cefcSMark Murray return (0);
290b528cefcSMark Murray cp = tokval;
291b528cefcSMark Murray if (c == '"') {
292b528cefcSMark Murray while ((c = getc(cfile)) != EOF && c != '"') {
293b528cefcSMark Murray if (c == '\\')
294b528cefcSMark Murray c = getc(cfile);
295b528cefcSMark Murray *cp++ = c;
296b528cefcSMark Murray }
297b528cefcSMark Murray } else {
298b528cefcSMark Murray *cp++ = c;
299b528cefcSMark Murray while ((c = getc(cfile)) != EOF
300b528cefcSMark Murray && c != '\n' && c != '\t' && c != ' ' && c != ',') {
301b528cefcSMark Murray if (c == '\\')
302b528cefcSMark Murray c = getc(cfile);
303b528cefcSMark Murray *cp++ = c;
304b528cefcSMark Murray }
305b528cefcSMark Murray }
306b528cefcSMark Murray *cp = 0;
307b528cefcSMark Murray if (tokval[0] == 0)
308b528cefcSMark Murray return (0);
309b528cefcSMark Murray for (t = toktab; t->tokstr; t++)
310b528cefcSMark Murray if (!strcmp(t->tokstr, tokval))
311b528cefcSMark Murray return (t->tval);
312b528cefcSMark Murray return (ID);
313b528cefcSMark Murray }
314