1 /*
2  * Copyright (c) 1985 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #include "precomp.h"
19 
20 #ifndef lint
21 static char sccsid[] = "@(#)ruserpass.c	5.1 (Berkeley) 3/1/89";
22 #endif /* not lint */
23 
24 struct	utmp *getutmp();
25 static	FILE *cfile;
26 
27 #ifndef MAXHOSTNAMELEN
28 #define MAXHOSTNAMELEN 64
29 #endif
30 
31 #define	DEFAULT	1
32 #define	LOGIN	2
33 #define	PASSWD	3
34 #define	ACCOUNT 4
35 #define MACDEF  5
36 #define	ID	10
37 #define	MACH	11
38 
39 static char tokval[100];
40 
41 static struct toktab {
42 	const char *tokstr;
43 	int tval;
44 } toktab[]= {
45 	{"default",	DEFAULT},
46 	{"login",	LOGIN},
47 	{"password",	PASSWD},
48 	{"passwd",	PASSWD},
49 	{"account",	ACCOUNT},
50 	{"machine",	MACH},
51 	{"macdef",	MACDEF},
52 	{0,		0}
53 };
54 
55 extern char *hostname;
56 static int token(void);
57 
ruserpass(const char * host,char ** aname,char ** apass,char ** aacct)58 int ruserpass(const char *host, char **aname, char **apass, char **aacct)
59 {
60 	const char *hdir, *mydomain;
61     char buf[BUFSIZ], *tmp;
62 	char myname[MAXHOSTNAMELEN];
63 	int t, i, c, usedefault = 0;
64 	struct stat stb;
65 
66 	hdir = getenv("HOME");
67 	if (hdir == NULL)
68 		hdir = ".";
69 	(void) sprintf(buf, "%s/.netrc", hdir);
70 	cfile = fopen(buf, "r");
71 	if (cfile == NULL) {
72 		if (errno != ENOENT)
73 			perror(buf);
74 		return(0);
75 	}
76 
77 
78 		  if (gethostname(myname, sizeof(myname)) < 0)
79 		myname[0] = '\0';
80 	if ((mydomain = index(myname, '.')) == NULL)
81 		mydomain = "";
82 next:
83 	while ((t = token())) switch(t) {
84 
85 	case DEFAULT:
86 		usedefault = 1;
87 		/* FALL THROUGH */
88 
89 	case MACH:
90 		if (!usedefault) {
91 			if (token() != ID)
92 				continue;
93 			/*
94 			 * Allow match either for user's input host name
95 			 * or official hostname.  Also allow match of
96 			 * incompletely-specified host in local domain.
97 			 */
98 			if (strcasecmp(host, tokval) == 0)
99 				goto match;
100 			if (strcasecmp(hostname, tokval) == 0)
101 				goto match;
102 			if ((tmp = index(hostname, '.')) != NULL &&
103 				 strcasecmp(tmp, mydomain) == 0 &&
104 				 strncasecmp(hostname, tokval, tmp - hostname) == 0 &&
105 				 tokval[tmp - hostname] == '\0')
106 				goto match;
107 			if ((tmp = index(host, '.')) != NULL &&
108 				 strcasecmp(tmp, mydomain) == 0 &&
109 				 strncasecmp(host, tokval, tmp - host) == 0 &&
110 				 tokval[tmp - host] == '\0')
111 				goto match;
112 			continue;
113 		}
114 	match:
115 		while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
116 
117 		case LOGIN:
118 			if (token()) {
119 				if (*aname == 0) {
120 					*aname = malloc((unsigned) strlen(tokval) + 1);
121 					(void) strcpy(*aname, tokval);
122 				} else {
123 					if (strcmp(*aname, tokval))
124 						goto next;
125 				}
126 			}
127 			break;
128 		case PASSWD:
129 			if (strcmp(*aname, "anonymous") &&
130 			    fstat(fileno(cfile), &stb) >= 0 &&
131 			    (stb.st_mode & 077) != 0) {
132 	fprintf(stderr, "Error - .netrc file not correct mode.\n");
133 	fprintf(stderr, "Remove password or correct mode.\n");
134 				goto bad;
135 			}
136 			if (token() && *apass == 0) {
137 				*apass = malloc((unsigned) strlen(tokval) + 1);
138 				(void) strcpy(*apass, tokval);
139 			}
140 			break;
141 		case ACCOUNT:
142 			if (fstat(fileno(cfile), &stb) >= 0
143 			    && (stb.st_mode & 077) != 0) {
144 	fprintf(stderr, "Error - .netrc file not correct mode.\n");
145 	fprintf(stderr, "Remove account or correct mode.\n");
146 				goto bad;
147 			}
148 			if (token() && *aacct == 0) {
149 				*aacct = malloc((unsigned) strlen(tokval) + 1);
150 				(void) strcpy(*aacct, tokval);
151 			}
152 			break;
153 		case MACDEF:
154 			if (proxy) {
155 				(void) fclose(cfile);
156 				return(0);
157 			}
158 			while ((c=getc(cfile)) != EOF && (c == ' ' || c == '\t'));
159 			if (c == EOF || c == '\n') {
160 				printf("Missing macdef name argument.\n");
161 				goto bad;
162 			}
163 			if (macnum == 16) {
164 				printf("Limit of 16 macros have already been defined\n");
165 				goto bad;
166 			}
167 			tmp = macros[macnum].mac_name;
168 			*tmp++ = c;
169 			for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
170 			    !isspace(c); ++i) {
171 				*tmp++ = c;
172 			}
173 			if (c == EOF) {
174 				printf("Macro definition missing null line terminator.\n");
175 				goto bad;
176 			}
177 			*tmp = '\0';
178 			if (c != '\n') {
179 				while ((c=getc(cfile)) != EOF && c != '\n');
180 			}
181 			if (c == EOF) {
182 				printf("Macro definition missing null line terminator.\n");
183 				goto bad;
184 			}
185 			if (macnum == 0) {
186 				macros[macnum].mac_start = macbuf;
187 			}
188 			else {
189 				macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
190 			}
191 			tmp = macros[macnum].mac_start;
192 			while (tmp != macbuf + 4096) {
193 				if ((c=getc(cfile)) == EOF) {
194 				printf("Macro definition missing null line terminator.\n");
195 					goto bad;
196 				}
197 				*tmp = c;
198 				if (*tmp == '\n') {
199 					if (*(tmp-1) == '\0') {
200 					   macros[macnum++].mac_end = tmp - 1;
201 					   break;
202 					}
203 					*tmp = '\0';
204 				}
205 				tmp++;
206 			}
207 			if (tmp == macbuf + 4096) {
208 				printf("4K macro buffer exceeded\n");
209 				goto bad;
210 			}
211 			break;
212 		default:
213 	fprintf(stderr, "Unknown .netrc keyword %s\n", tokval);
214 			break;
215 		}
216 		goto done;
217 	}
218 done:
219 	(void) fclose(cfile);
220 	return(0);
221 bad:
222 	(void) fclose(cfile);
223 	return(-1);
224 }
225 
token(void)226 static int token(void)
227 {
228    char *cp;
229    int c;
230    struct toktab *t;
231 
232    if (feof(cfile))
233       return (0);
234    while ((c = getc(cfile)) != EOF &&
235           (c == '\r' || c == '\n' || c == '\t' || c == ' ' || c == ','))
236       continue;
237    if (c == EOF)
238       return (0);
239    cp = tokval;
240    if (c == '"') {
241       while ((c = getc(cfile)) != EOF && c != '"') {
242          if (c == '\\')
243             c = getc(cfile);
244          *cp++ = c;
245       }
246    } else {
247       *cp++ = c;
248       while ((c = getc(cfile)) != EOF
249              && c != '\n' && c != '\t' && c != ' ' && c != ',' && c != '\r') {
250          if (c == '\\')
251             c = getc(cfile);
252          *cp++ = c;
253       }
254    }
255    *cp = 0;
256    if (tokval[0] == 0)
257       return (0);
258    for (t = toktab; t->tokstr; t++)
259       if (!strcmp(t->tokstr, tokval))
260          return (t->tval);
261    return (ID);
262 }
263