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