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