1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  *	Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	All Rights Reserved  	*/
29 
30 /*
31  *	University Copyright- Copyright (c) 1982, 1986, 1988
32  *	The Regents of the University of California
33  *	All Rights Reserved
34  *
35  *	University Acknowledgment- Portions of this document are derived from
36  *	software developed by the University of California, Berkeley, and its
37  *	contributors.
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 #include "ftp_var.h"
43 
44 static	FILE *cfile;
45 
46 static int rnetrc(char *host, char **aname, char **apass, char **aacct);
47 static int token(void);
48 
49 int
50 ruserpass(char *host, char **aname, char **apass, char **aacct)
51 {
52 #if 0
53 	renv(host, aname, apass, aacct);
54 	if (*aname == 0 || *apass == 0)
55 #endif
56 		return (rnetrc(host, aname, apass, aacct));
57 }
58 
59 #define	DEFAULT	1
60 #define	LOGIN	2
61 #define	PASSWD	3
62 #define	ACCOUNT 4
63 #define	MACDEF	5
64 #define	ID	10
65 #define	MACHINE	11
66 
67 static char tokval[100];
68 
69 static struct toktab {
70 	char *tokstr;
71 	int tval;
72 } toktab[] = {
73 	"default",	DEFAULT,
74 	"login",	LOGIN,
75 	"password",	PASSWD,
76 	"account",	ACCOUNT,
77 	"machine",	MACHINE,
78 	"macdef",	MACDEF,
79 	0,		0
80 };
81 
82 static int
83 rnetrc(char *host, char **aname, char **apass, char **aacct)
84 {
85 	char *hdir, buf[PATH_MAX+1], *tmp;
86 	int t, i, c;
87 	struct stat stb;
88 	extern int errno;
89 
90 	hdir = getenv("HOME");
91 	if (hdir == NULL)
92 		hdir = ".";
93 	if (snprintf(buf, sizeof (buf), "%s/.netrc", hdir) >= sizeof (buf)) {
94 		fprintf(stderr, ".netrc: %s\n", strerror(ENAMETOOLONG));
95 		exit(1);
96 	}
97 
98 	cfile = fopen(buf, "r");
99 	if (cfile == NULL) {
100 		if (errno != ENOENT)
101 			perror(buf);
102 		return (0);
103 	}
104 next:
105 	while ((t = token()))
106 		switch (t) {
107 
108 	case MACHINE:
109 		if (token() != ID || strcmp(host, tokval))
110 			continue;
111 		/* "machine name" matches host */
112 		/* FALLTHROUGH */
113 
114 	case DEFAULT:
115 		/* "default" matches any host */
116 		while (((t = token()) != 0) && t != MACHINE && t != DEFAULT)
117 			switch (t) {
118 
119 		case LOGIN:
120 			if (token())
121 				if (*aname == 0) {
122 					*aname = malloc((unsigned)
123 					    strlen(tokval) + 1);
124 					if (*aname == NULL) {
125 						fprintf(stderr,
126 						    "Error - out of VM\n");
127 						exit(1);
128 					}
129 					(void) strcpy(*aname, tokval);
130 				} else {
131 					if (strcmp(*aname, tokval))
132 						goto next;
133 				}
134 			break;
135 		case PASSWD:
136 			if (fstat(fileno(cfile), &stb) >= 0 &&
137 			    (stb.st_mode & 077) != 0) {
138 				fprintf(stderr, "Error - .netrc file not "
139 				    "correct mode.\n");
140 				fprintf(stderr, "Remove password or correct "
141 				    "mode.\n");
142 				return (-1);
143 			}
144 			if (token() && *apass == 0) {
145 				*apass = malloc((unsigned)strlen(tokval) + 1);
146 				if (*apass == NULL) {
147 					fprintf(stderr, "Error - out of VM\n");
148 					exit(1);
149 				}
150 				(void) strcpy(*apass, tokval);
151 			}
152 			break;
153 		case ACCOUNT:
154 			if (fstat(fileno(cfile), &stb) >= 0 &&
155 			    (stb.st_mode & 077) != 0) {
156 				fprintf(stderr, "Error - .netrc file not "
157 				    "correct mode.\n");
158 				fprintf(stderr, "Remove account or correct "
159 				    "mode.\n");
160 				return (-1);
161 			}
162 			if (token() && *aacct == 0) {
163 				*aacct = malloc((unsigned)strlen(tokval) + 1);
164 				if (*aacct == NULL) {
165 					fprintf(stderr, "Error - out of VM\n");
166 					exit(1);
167 				}
168 				(void) strcpy(*aacct, tokval);
169 			}
170 			break;
171 		case MACDEF:
172 			if (proxy) {
173 				return (0);
174 			}
175 			while ((c = getc(cfile)) != EOF && c == ' ' ||
176 			    c == '\t');
177 			if (c == EOF || c == '\n') {
178 				printf("Missing macdef name argument.\n");
179 				return (-1);
180 			}
181 			if (macnum == 16) {
182 				printf("Limit of 16 macros have already "
183 				    "been defined\n");
184 				return (-1);
185 			}
186 			tmp = macros[macnum].mac_name;
187 			*tmp++ = c;
188 			for (i = 0; i < 8 && (c = getc(cfile)) != EOF &&
189 			    !isspace(c); ++i) {
190 				*tmp++ = c;
191 			}
192 			if (c == EOF) {
193 				printf("Macro definition for `%s` missing "
194 				    "null line terminator.\n",
195 				    macros[macnum].mac_name);
196 				return (-1);
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 for `%s` missing "
204 				    "null line terminator.\n",
205 				    macros[macnum].mac_name);
206 				return (-1);
207 			}
208 			if (macnum == 0) {
209 				macros[macnum].mac_start = macbuf;
210 			} else {
211 				macros[macnum].mac_start =
212 				    macros[macnum-1].mac_end + 1;
213 			}
214 			tmp = macros[macnum].mac_start;
215 			while (tmp != macbuf + 4096) {
216 				if ((c = getc(cfile)) == EOF) {
217 				printf("Macro definition for `%s` missing "
218 				    "null line terminator.\n",
219 				    macros[macnum].mac_name);
220 					return (-1);
221 				}
222 				*tmp = c;
223 				if (*tmp == '\n') {
224 					if (*(tmp-1) == '\0') {
225 						macros[macnum++].mac_end =
226 						    tmp - 1;
227 						break;
228 					}
229 					*tmp = '\0';
230 				}
231 				tmp++;
232 			}
233 			if (tmp == macbuf + 4096) {
234 				printf("4K macro buffer exceeded\n");
235 				return (-1);
236 			}
237 			if (*macros[macnum - 1].mac_start == '\n') {
238 				printf("Macro definition for `%s` is empty, "
239 				    "macro not stored.\n",
240 					macros[--macnum].mac_name);
241 			}
242 			break;
243 		default:
244 			fprintf(stderr, "Unknown .netrc keyword %s\n", tokval);
245 			break;
246 		}
247 		goto done;
248 	}
249 done:
250 	(void) fclose(cfile);
251 	return (0);
252 }
253 
254 static int
255 token(void)
256 {
257 	char *cp;
258 	int c;
259 	struct toktab *t;
260 	int	len;
261 
262 	if (feof(cfile))
263 		return (0);
264 	while ((c = fgetwc(cfile)) != EOF &&
265 	    (c == '\n' || c == '\t' || c == ' ' || c == ','))
266 		continue;
267 	if (c == EOF)
268 		return (0);
269 	cp = tokval;
270 	if (c == '"') {
271 		while ((c = fgetwc(cfile)) != EOF && c != '"') {
272 			if (c == '\\')
273 				c = fgetwc(cfile);
274 			if ((len = wctomb(cp, c)) <= 0) {
275 				len = 1;
276 				*cp = (unsigned char)c;
277 			}
278 			cp += len;
279 		}
280 	} else {
281 		if ((len = wctomb(cp, c)) <= 0) {
282 			*cp = (unsigned char)c;
283 			len = 1;
284 		}
285 		cp += len;
286 		while ((c = fgetwc(cfile)) != EOF && c != '\n' && c != '\t' &&
287 		    c != ' ' && c != ',') {
288 			if (c == '\\')
289 				c = fgetwc(cfile);
290 			if ((len = wctomb(cp, c)) <= 0) {
291 				len = 1;
292 				*cp = (unsigned char)c;
293 			}
294 			cp += len;
295 		}
296 	}
297 	*cp = 0;
298 	if (tokval[0] == 0)
299 		return (0);
300 	for (t = toktab; t->tokstr; t++)
301 		if (strcmp(t->tokstr, tokval) == 0)
302 			return (t->tval);
303 	return (ID);
304 }
305