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 1998 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 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 <stdio.h>
43 #include <ctype.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <errno.h>
47 #include <unistd.h>
48 #include <strings.h>
49 #include <stdlib.h>
50 #include <libintl.h>
51 
52 extern char *_dgettext();
53 
54 #ifdef SYSV
55 #define	index	strchr
56 #endif /* SYSV */
57 
58 static void rnetrc(const char *host, char **aname, char **apass);
59 static int token();
60 
61 #define	DEFAULT	1
62 #define	LOGIN	2
63 #define	PASSWD	3
64 #define	NOTIFY	4
65 #define	WRITE	5
66 #define	YES	6
67 #define	NO	7
68 #define	COMMAND	8
69 #define	FORCE	9
70 #define	ID	10
71 #define	MACHINE	11
72 
73 #define	MAXTOKEN  11
74 #define	NTOKENS	(MAXTOKEN - 1 + 2 + 1)	/* two duplicates and null, minus id */
75 
76 static struct ruserdata {
77 	char tokval[100];
78 	struct toktab {
79 		char *tokstr;
80 		int tval;
81 	} toktab[NTOKENS];
82 	FILE *cfile;
83 } *ruserdata, *_ruserdata();
84 
85 
86 static struct ruserdata *
87 _ruserdata()
88 {
89 	struct ruserdata *d = ruserdata;
90 	struct toktab *t;
91 
92 	if (d == 0) {
93 		if ((d = (struct ruserdata *)
94 			calloc(1, sizeof (struct ruserdata))) == NULL) {
95 				return (NULL);
96 		}
97 		ruserdata = d;
98 		t = d->toktab;
99 		t->tokstr = "default";  t++->tval = DEFAULT;
100 		t->tokstr = "login";    t++->tval = LOGIN;
101 		t->tokstr = "password"; t++->tval = PASSWD;
102 		t->tokstr = "notify";   t++->tval = NOTIFY;
103 		t->tokstr = "write";    t++->tval = WRITE;
104 		t->tokstr = "yes";	t++->tval = YES;
105 		t->tokstr = "y";	t++->tval = YES;
106 		t->tokstr = "no";	t++->tval = NO;
107 		t->tokstr = "n";	t++->tval = NO;
108 		t->tokstr = "command";  t++->tval = COMMAND;
109 		t->tokstr = "force";    t++->tval = FORCE;
110 		t->tokstr = "machine";  t++->tval = MACHINE;
111 		t->tokstr = 0;		t->tval = 0;
112 	}
113 	return (d);
114 }
115 
116 
117 #define	MAXANAME	16
118 
119 void
120 _ruserpass(const char *host, char **aname, char **apass)
121 {
122 
123 	if (*aname == 0 || *apass == 0)
124 		rnetrc(host, aname, apass);
125 	if (*aname == 0) {
126 		char myname[L_cuserid];
127 
128 		*aname = malloc(MAXANAME + 1);
129 		(void) cuserid(myname);
130 		(void) printf(_dgettext(TEXT_DOMAIN, "Name (%s:%s): "), host, myname);
131 		(void) fflush(stdout);
132 		if (read(2, *aname, MAXANAME) <= 0)
133 			exit(1);
134 		aname[0][MAXANAME] = '\0';
135 		if ((*aname)[0] == '\n')
136 			(void) strcpy(*aname, myname);
137 		else
138 			if (index(*aname, '\n'))
139 				*index(*aname, '\n') = 0;
140 	}
141 	if (*aname && *apass == 0) {
142 		(void) printf(_dgettext(TEXT_DOMAIN, "Password (%s:%s): "),
143 			host, *aname);
144 		(void) fflush(stdout);
145 		*apass = getpass("");
146 	}
147 }
148 
149 
150 static void
151 rnetrc(const char *host, char **aname, char **apass)
152 {
153 	struct ruserdata *d = _ruserdata();
154 	char *hdir, buf[BUFSIZ];
155 	int t;
156 	struct stat64 stb;
157 
158 	if (d == 0)
159 		return;
160 
161 	hdir = getenv("HOME");
162 	if (hdir == NULL)
163 		hdir = ".";
164 	(void) sprintf(buf, "%s/.netrc", hdir);
165 	d->cfile = fopen(buf, "r");
166 	if (d->cfile == NULL) {
167 		if (errno != ENOENT)
168 			perror(buf);
169 		return;
170 	}
171 next:
172 	while ((t = token()))
173 	switch (t) {
174 
175 	case DEFAULT:
176 		(void) token();
177 		continue;
178 
179 	case MACHINE:
180 		if (token() != ID || strcmp(host, d->tokval))
181 			continue;
182 		while ((t = token()) != 0 && t != MACHINE)
183 		switch (t) {
184 
185 		case LOGIN:
186 			if (token())
187 				if (*aname == 0) {
188 					*aname = malloc(strlen(d->tokval) + 1);
189 					(void) strcpy(*aname, d->tokval);
190 				} else {
191 					if (strcmp(*aname, d->tokval))
192 						goto next;
193 				}
194 			break;
195 		case PASSWD:
196 			if (fstat64(fileno(d->cfile), &stb) >= 0 &&
197 				    (stb.st_mode & 077) != 0) {
198 				(void) fprintf(stderr,
199 				     _dgettext(TEXT_DOMAIN,
200 				     "Error - .netrc file not correct mode.\n"));
201 				(void) fprintf(stderr,
202 				     _dgettext(TEXT_DOMAIN,
203 				     "Remove password or correct mode.\n"));
204 				exit(1);
205 			}
206 			if (token() && *apass == 0) {
207 				*apass = malloc(strlen(d->tokval) + 1);
208 				(void) strcpy(*apass, d->tokval);
209 			}
210 			break;
211 		case COMMAND:
212 		case NOTIFY:
213 		case WRITE:
214 		case FORCE:
215 			(void) token();
216 			break;
217 		default:
218 			(void) fprintf(stderr,
219 			    _dgettext(TEXT_DOMAIN, "Unknown .netrc option %s\n"),
220 			    d->tokval);
221 			break;
222 		}
223 		goto done;
224 	}
225 done:
226 	(void) fclose(d->cfile);
227 }
228 
229 static int
230 token()
231 {
232 	struct ruserdata *d = _ruserdata();
233 	char *cp;
234 	int c;
235 	struct toktab *t;
236 
237 	if (d == 0)
238 		return (0);
239 
240 	if (feof(d->cfile))
241 		return (0);
242 	while ((c = getc(d->cfile)) != EOF &&
243 	    (c == '\n' || c == '\t' || c == ' ' || c == ','))
244 		continue;
245 	if (c == EOF)
246 		return (0);
247 	cp = d->tokval;
248 	if (c == '"') {
249 		while ((c = getc(d->cfile)) != EOF && c != '"') {
250 			if (c == '\\')
251 				c = getc(d->cfile);
252 			*cp++ = (char)c;
253 		}
254 	} else {
255 		*cp++ = (char)c;
256 		while ((c = getc(d->cfile)) != EOF &&
257 			    c != '\n' && c != '\t' && c != ' ' && c != ',') {
258 			if (c == '\\')
259 				c = getc(d->cfile);
260 			*cp++ = (char)c;
261 		}
262 	}
263 	*cp = 0;
264 	if (d->tokval[0] == 0)
265 		return (0);
266 	for (t = d->toktab; t->tokstr; t++)
267 		if ((strcmp(t->tokstr, d->tokval) == 0))
268 			return (t->tval);
269 	return (ID);
270 }
271