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