]> diplodocus.org Git - nmh/blob - sbr/ruserpass.c
81fd13eadb8f5e4449c2db843d5d6b52660f40c8
[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 "error.h"
26 #include <h/utils.h>
27 #include <pwd.h>
28
29 static FILE *cfile;
30
31 #define TOK_EOF 0
32 #define DEFAULT 1
33 #define LOGIN 2
34 #define PASSWD 3
35 #define ACCOUNT 4
36 #define MACDEF 5
37 #define ID 10
38 #define MACH 11
39
40 #define MAX_TOKVAL_SIZE 1024 /* Including terminating NUL. */
41
42 struct toktab {
43 char *tokstr;
44 int tval;
45 };
46
47 static struct toktab toktabs[] = {
48 { "", TOK_EOF },
49 { "default", DEFAULT },
50 { "login", LOGIN },
51 { "password", PASSWD },
52 { "passwd", PASSWD },
53 { "account", ACCOUNT },
54 { "machine", MACH },
55 { "macdef", MACDEF },
56 { 0, 0 }
57 };
58
59 /*
60 * prototypes
61 */
62 static int token(char *);
63
64
65 void
66 ruserpass(const char *host, char **aname, char **apass, int flags)
67 {
68 int t;
69 struct stat stb;
70
71 init_credentials_file ();
72
73 cfile = fopen (credentials_file, "r");
74 if (cfile == NULL) {
75 if (errno != ENOENT)
76 perror (credentials_file);
77 } else {
78 char tokval[MAX_TOKVAL_SIZE];
79 tokval[0] = '\0';
80
81 bool usedefault = false;
82 while ((t = token(tokval))) {
83 switch(t) {
84 case DEFAULT:
85 usedefault = true;
86 /* FALLTHRU */
87
88 case MACH:
89 if (!usedefault) {
90 if (token(tokval) != ID)
91 continue;
92 /*
93 * Allow match either for user's host name.
94 */
95 if (strcasecmp(host, tokval) == 0)
96 goto match;
97 continue;
98 }
99 match:
100 while ((t = token(tokval)) && t != MACH && t != DEFAULT) {
101 switch(t) {
102 case LOGIN:
103 if (token(tokval) && *aname == 0)
104 *aname = mh_xstrdup(tokval);
105 break;
106
107 case PASSWD:
108 if (!credentials_no_perm_check &&
109 fstat(fileno(cfile), &stb) >= 0 &&
110 (stb.st_mode & 077) != 0) {
111 /* We make this a fatal error to force the
112 user to correct it. */
113 inform("group or other permissions, %#o, "
114 "forbidden: %s", stb.st_mode, credentials_file);
115 die("Remove password or correct file "
116 "permissions.");
117 }
118 if (token(tokval) && *apass == 0)
119 *apass = mh_xstrdup(tokval);
120 break;
121
122 case ACCOUNT:
123 break;
124
125 case MACDEF:
126 fclose(cfile);
127 return;
128
129 default:
130 fprintf(stderr,
131 "Unknown keyword %s in credentials file %s\n",
132 tokval, credentials_file);
133 break;
134 }
135 }
136 return;
137 }
138 }
139 }
140
141 if (!*aname && ! (flags & RUSERPASS_NO_PROMPT_USER)) {
142 char tmp[80];
143 char *myname;
144
145 if ((myname = getlogin()) == NULL) {
146 struct passwd *pp;
147
148 if ((pp = getpwuid (getuid())) != NULL)
149 myname = pp->pw_name;
150 }
151 printf("Name (%s:%s): ", host, myname);
152
153 if (fgets(tmp, sizeof tmp, stdin) == NULL) {
154 advise ("tmp", "fgets");
155 }
156 trim_suffix_c(tmp, '\n');
157 if (*tmp != '\0' || myname == NULL) {
158 myname = tmp;
159 }
160
161 *aname = mh_xstrdup(myname);
162 }
163
164 if (!*apass && ! (flags & RUSERPASS_NO_PROMPT_PASSWORD)) {
165 char prompt[256];
166 char *mypass;
167
168 snprintf(prompt, sizeof(prompt), "Password (%s:%s): ", host, *aname);
169 mypass = nmh_getpass(prompt);
170
171 if (*mypass == '\0') {
172 mypass = *aname;
173 }
174
175 *aname = mh_xstrdup(mypass);
176 }
177
178 }
179
180 static int
181 token(char *tokval)
182 {
183 int c;
184 const char normalStop[] = "\t\n ,"; /* Each breaks a word. */
185 const char *stop;
186 char *cp;
187 struct toktab *t;
188
189 if (feof(cfile) || ferror(cfile))
190 return TOK_EOF;
191
192 stop = normalStop;
193 while ((c = getc(cfile)) != EOF && c && strchr(stop, c))
194 ;
195 if (c == EOF)
196 return TOK_EOF;
197
198 cp = tokval;
199 if (c == '"')
200 /* FIXME: Where is the quoted-string syntax of netrc documented?
201 * This code treats «"foo""bar"» as two tokens without further
202 * separators. */
203 stop = "\"";
204 else
205 /* Might be backslash. Get it again later. It's handled then. */
206 if (ungetc(c, cfile) == EOF)
207 return TOK_EOF;
208
209 while ((c = getc(cfile)) != EOF && c && !strchr(stop, c)) {
210 if (c == '\\' && (c = getc(cfile)) == EOF)
211 return TOK_EOF; /* Discard whole token. */
212
213 *cp++ = c;
214 if (cp - tokval > MAX_TOKVAL_SIZE-1) {
215 die("credential tokens restricted to length %d",
216 MAX_TOKVAL_SIZE - 1);
217 }
218 }
219 *cp = '\0';
220
221 for (t = toktabs; t->tokstr; t++)
222 if (!strcmp(t->tokstr, tokval))
223 return t->tval;
224
225 return ID;
226 }