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