Fix some bugs in replyfilter.
[mmh] / sbr / ruserpass.c
1 /*
2  * Portions of this code are
3  * Copyright (c) 1985 Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms are permitted
7  * provided that the above copyright notice and this paragraph are
8  * duplicated in all such forms and that any documentation,
9  * advertising materials, and other materials related to such
10  * distribution and use acknowledge that the software was developed
11  * by the University of California, Berkeley.  The name of the
12  * University may not be used to endorse or promote products derived
13  * from this software without specific prior written permission.
14  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  */
18
19 #include <h/mh.h>
20 #include <h/utils.h>
21 #include <pwd.h>
22 #include <errno.h>
23
24 static FILE *cfile;
25
26 #ifndef MAXHOSTNAMELEN
27 # define MAXHOSTNAMELEN 64
28 #endif
29
30 #define DEFAULT 1
31 #define LOGIN   2
32 #define PASSWD  3
33 #define ACCOUNT 4
34 #define MACDEF  5
35 #define ID      10
36 #define MACH    11
37
38 static char tokval[100];
39
40 struct toktab {
41     char *tokstr;
42     int tval;
43 };
44
45 static struct toktab toktabs[] = {
46     { "default",  DEFAULT },
47     { "login",    LOGIN },
48     { "password", PASSWD },
49     { "passwd",   PASSWD },
50     { "account",  ACCOUNT },
51     { "machine",  MACH },
52     { "macdef",   MACDEF },
53     { 0,          0 }
54 };
55
56 /*
57  * prototypes
58  */
59 static int token(void);
60
61
62 void
63 ruserpass(char *host, char **aname, char **apass)
64 {
65     char *hdir, buf[BUFSIZ];
66     int t, usedefault = 0;
67     struct stat stb;
68
69     hdir = getenv("HOME");
70     if (hdir == NULL)
71         hdir = ".";
72     snprintf(buf, sizeof(buf), "%s/.netrc", hdir);
73     cfile = fopen(buf, "r");
74     if (cfile == NULL) {
75         if (errno != ENOENT)
76             perror(buf);
77         goto done;
78     }
79
80     while ((t = token())) {
81         switch(t) {
82         case DEFAULT:
83             usedefault = 1;
84             /* FALL THROUGH */
85
86         case MACH:
87             if (!usedefault) {
88                 if (token() != ID)
89                     continue;
90                 /*
91                  * Allow match either for user's host name.
92                  */
93                 if (mh_strcasecmp(host, tokval) == 0)
94                     goto match;
95                 continue;
96             }
97 match:
98             while ((t = token()) && t != MACH && t != DEFAULT) {
99                 switch(t) {
100                 case LOGIN:
101                     if (token() && *aname == 0) {
102                         *aname = mh_xmalloc((size_t) strlen(tokval) + 1);
103                         strcpy(*aname, tokval);
104                     }
105                     break;
106                 case PASSWD:
107                     if (fstat(fileno(cfile), &stb) >= 0 &&
108                         (stb.st_mode & 077) != 0) {
109                         /* We make this a fatal error to force the user to correct it */
110                         advise(NULL, "Error - ~/.netrc file must not be world or group readable.");
111                         adios(NULL, "Remove password or correct file permissions.");
112                     }
113                     if (token() && *apass == 0) {
114                         *apass = mh_xmalloc((size_t) strlen(tokval) + 1);
115                         strcpy(*apass, tokval);
116                     }
117                     break;
118                 case ACCOUNT:
119                     break;
120
121                 case MACDEF:
122                     goto done_close;
123                     break;
124                 default:
125                     fprintf(stderr, "Unknown .netrc keyword %s\n", tokval);
126                     break;
127                 }
128             }
129             goto done;
130         }
131     }
132
133 done_close:
134     fclose(cfile);
135
136 done:
137     if (!*aname) {
138         char tmp[80];
139         char *myname;
140
141         if ((myname = getlogin()) == NULL) {
142             struct passwd *pp;
143
144             if ((pp = getpwuid (getuid())) != NULL)
145                 myname = pp->pw_name;
146         }
147         printf("Name (%s:%s): ", host, myname);
148
149         fgets(tmp, sizeof(tmp) - 1, stdin);
150         tmp[strlen(tmp) - 1] = '\0';
151         if (*tmp != '\0') {
152             myname = tmp;
153         }
154
155         *aname = mh_xmalloc((size_t) strlen(myname) + 1);
156         strcpy (*aname, myname);
157     }
158
159     if (!*apass) {
160         char prompt[256];
161         char *mypass;
162
163         snprintf(prompt, sizeof(prompt), "Password (%s:%s): ", host, *aname);
164         mypass = nmh_getpass(prompt);
165         
166         if (*mypass == '\0') {
167             mypass = *aname;
168         }
169
170         *apass = mh_xmalloc((size_t) strlen(mypass) + 1);
171         strcpy (*apass, mypass);
172     }
173
174 }
175
176 static int
177 token(void)
178 {
179     char *cp;
180     int c;
181     struct toktab *t;
182
183     if (feof(cfile))
184         return (0);
185     while ((c = getc(cfile)) != EOF &&
186            (c == '\n' || c == '\t' || c == ' ' || c == ','))
187         continue;
188     if (c == EOF)
189         return (0);
190     cp = tokval;
191     if (c == '"') {
192         while ((c = getc(cfile)) != EOF && c != '"') {
193             if (c == '\\')
194                 c = getc(cfile);
195             *cp++ = c;
196         }
197     } else {
198         *cp++ = c;
199         while ((c = getc(cfile)) != EOF
200                && c != '\n' && c != '\t' && c != ' ' && c != ',') {
201             if (c == '\\')
202                 c = getc(cfile);
203             *cp++ = c;
204         }
205     }
206     *cp = 0;
207     if (tokval[0] == 0)
208         return (0);
209     for (t = toktabs; t->tokstr; t++)
210         if (!strcmp(t->tokstr, tokval))
211             return (t->tval);
212     return (ID);
213 }