]> diplodocus.org Git - nmh/blob - sbr/ruserpass.c
77b57a7e951e6aac673a707a097148a1e9ea01f7
[nmh] / sbr / ruserpass.c
1 /* ruserpass.c -- parse .netrc-format file.
2 *
3 * Portions of this code are
4 * Copyright (c) 1985 Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by the University of California, Berkeley. The name of the
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * Portions of this code are Copyright (c) 2013, by the authors of
20 * nmh. See the COPYRIGHT file in the root directory of the nmh
21 * distribution for complete copyright information.
22 */
23
24 #include "h/mh.h"
25 #include "getpass.h"
26 #include "ruserpass.h"
27 #include "credentials.h"
28 #include "error.h"
29 #include "h/utils.h"
30 #include <pwd.h>
31
32 static FILE *cfile;
33
34 #define TOK_EOF 0
35 #define DEFAULT 1
36 #define LOGIN 2
37 #define PASSWD 3
38 #define ACCOUNT 4
39 #define MACDEF 5
40 #define ID 10
41 #define MACH 11
42
43 #define MAX_TOKVAL_SIZE 1024 /* Including terminating NUL. */
44
45 struct toktab {
46 char *tokstr;
47 int tval;
48 };
49
50 static struct toktab toktabs[] = {
51 { "", TOK_EOF },
52 { "default", DEFAULT },
53 { "login", LOGIN },
54 { "password", PASSWD },
55 { "passwd", PASSWD },
56 { "account", ACCOUNT },
57 { "machine", MACH },
58 { "macdef", MACDEF },
59 { 0, 0 }
60 };
61
62 /*
63 * prototypes
64 */
65 static int token(char *);
66
67
68 void
69 ruserpass(const char *host, char **aname, char **apass, int flags)
70 {
71 int t;
72 struct stat stb;
73
74 init_credentials_file ();
75
76 cfile = fopen (credentials_file, "r");
77 if (cfile == NULL) {
78 if (errno != ENOENT)
79 perror (credentials_file);
80 } else {
81 char tokval[MAX_TOKVAL_SIZE];
82 tokval[0] = '\0';
83
84 bool usedefault = false;
85 while ((t = token(tokval))) {
86 switch(t) {
87 case DEFAULT:
88 usedefault = true;
89 /* FALLTHRU */
90
91 case MACH:
92 if (!usedefault) {
93 if (token(tokval) != ID)
94 continue;
95 /*
96 * Allow match either for user's host name.
97 */
98 if (strcasecmp(host, tokval) == 0)
99 goto match;
100 continue;
101 }
102 match:
103 while ((t = token(tokval)) && t != MACH && t != DEFAULT) {
104 switch(t) {
105 case LOGIN:
106 if (token(tokval) && *aname == 0)
107 *aname = mh_xstrdup(tokval);
108 break;
109
110 case PASSWD:
111 if (!credentials_no_perm_check &&
112 fstat(fileno(cfile), &stb) >= 0 &&
113 (stb.st_mode & 077) != 0) {
114 /* We make this a fatal error to force the
115 user to correct it. */
116 inform("group or other permissions, %#o, "
117 "forbidden: %s", stb.st_mode, credentials_file);
118 die("Remove password or correct file "
119 "permissions.");
120 }
121 if (token(tokval) && *apass == 0)
122 *apass = mh_xstrdup(tokval);
123 break;
124
125 case ACCOUNT:
126 break;
127
128 case MACDEF:
129 fclose(cfile);
130 return;
131
132 default:
133 fprintf(stderr,
134 "Unknown keyword %s in credentials file %s\n",
135 tokval, credentials_file);
136 break;
137 }
138 }
139 fclose(cfile);
140 return;
141 }
142 }
143 fclose(cfile);
144 }
145
146 if (!*aname && ! (flags & RUSERPASS_NO_PROMPT_USER)) {
147 char tmp[80];
148 char *myname;
149
150 if ((myname = getlogin()) == NULL) {
151 struct passwd *pp;
152
153 if ((pp = getpwuid (getuid())) != NULL)
154 myname = pp->pw_name;
155 }
156 printf("Name (%s:%s): ", host, myname);
157
158 if (fgets(tmp, sizeof tmp, stdin) == NULL) {
159 advise ("tmp", "fgets");
160 }
161 trim_suffix_c(tmp, '\n');
162 if (*tmp != '\0' || myname == NULL) {
163 myname = tmp;
164 }
165
166 *aname = mh_xstrdup(myname);
167 }
168
169 if (!*apass && ! (flags & RUSERPASS_NO_PROMPT_PASSWORD)) {
170 char prompt[256];
171 char *mypass;
172
173 snprintf(prompt, sizeof(prompt), "Password (%s:%s): ", host, *aname);
174 mypass = nmh_getpass(prompt);
175
176 if (*mypass == '\0') {
177 mypass = *aname;
178 }
179
180 *apass = mh_xstrdup(mypass);
181 }
182
183 }
184
185 static int
186 token(char *tokval)
187 {
188 int c;
189 const char normalStop[] = "\t\n ,"; /* Each breaks a word. */
190 const char *stop;
191 char *cp;
192 struct toktab *t;
193
194 if (feof(cfile) || ferror(cfile))
195 return TOK_EOF;
196
197 stop = normalStop;
198 while ((c = getc(cfile)) != EOF && c && strchr(stop, c))
199 ;
200 if (c == EOF)
201 return TOK_EOF;
202
203 cp = tokval;
204 if (c == '"')
205 /* FIXME: Where is the quoted-string syntax of netrc documented?
206 * This code treats «"foo""bar"» as two tokens without further
207 * separators. */
208 stop = "\"";
209 else
210 /* Might be backslash. Get it again later. It's handled then. */
211 if (ungetc(c, cfile) == EOF)
212 return TOK_EOF;
213
214 while ((c = getc(cfile)) != EOF && c && !strchr(stop, c)) {
215 if (c == '\\' && (c = getc(cfile)) == EOF)
216 return TOK_EOF; /* Discard whole token. */
217
218 *cp++ = c;
219 if (cp - tokval > MAX_TOKVAL_SIZE-1) {
220 die("credential tokens restricted to length %d",
221 MAX_TOKVAL_SIZE - 1);
222 }
223 }
224 *cp = '\0';
225
226 for (t = toktabs; t->tokstr; t++)
227 if (!strcmp(t->tokstr, tokval))
228 return t->tval;
229
230 return ID;
231 }