1 |
|
|
/* $OpenBSD: skeyinit.c,v 1.72 2016/05/17 23:36:29 tb Exp $ */ |
2 |
|
|
|
3 |
|
|
/* OpenBSD S/Key (skeyinit.c) |
4 |
|
|
* |
5 |
|
|
* Authors: |
6 |
|
|
* Neil M. Haller <nmh@thumper.bellcore.com> |
7 |
|
|
* Philip R. Karn <karn@chicago.qualcomm.com> |
8 |
|
|
* John S. Walden <jsw@thumper.bellcore.com> |
9 |
|
|
* Scott Chasin <chasin@crimelab.com> |
10 |
|
|
* Todd C. Miller <Todd.Miller@courtesan.com> |
11 |
|
|
* |
12 |
|
|
* S/Key initialization and seed update |
13 |
|
|
*/ |
14 |
|
|
|
15 |
|
|
#include <sys/file.h> |
16 |
|
|
#include <sys/resource.h> |
17 |
|
|
#include <sys/stat.h> |
18 |
|
|
#include <sys/time.h> |
19 |
|
|
|
20 |
|
|
#include <ctype.h> |
21 |
|
|
#include <err.h> |
22 |
|
|
#include <errno.h> |
23 |
|
|
#include <pwd.h> |
24 |
|
|
#include <readpassphrase.h> |
25 |
|
|
#include <stdio.h> |
26 |
|
|
#include <stdlib.h> |
27 |
|
|
#include <string.h> |
28 |
|
|
#include <syslog.h> |
29 |
|
|
#include <time.h> |
30 |
|
|
#include <unistd.h> |
31 |
|
|
#include <limits.h> |
32 |
|
|
#include <utmp.h> |
33 |
|
|
|
34 |
|
|
#include <skey.h> |
35 |
|
|
#include <bsd_auth.h> |
36 |
|
|
|
37 |
|
|
#ifndef SKEY_NAMELEN |
38 |
|
|
#define SKEY_NAMELEN 4 |
39 |
|
|
#endif |
40 |
|
|
|
41 |
|
|
void usage(void); |
42 |
|
|
void secure_mode(int *, char *, char *, size_t, char *, size_t); |
43 |
|
|
void normal_mode(char *, int, char *, char *); |
44 |
|
|
void enable_db(int); |
45 |
|
|
|
46 |
|
|
int |
47 |
|
|
main(int argc, char **argv) |
48 |
|
|
{ |
49 |
|
|
int rval, i, l, n, defaultsetup, rmkey, hexmode, enable; |
50 |
|
|
char hostname[HOST_NAME_MAX+1]; |
51 |
|
|
char seed[SKEY_MAX_SEED_LEN + 1]; |
52 |
|
|
char buf[256], key[SKEY_BINKEY_SIZE], filename[PATH_MAX], *ht; |
53 |
|
|
char lastc, *p, *auth_type; |
54 |
|
|
const char *errstr; |
55 |
|
|
struct skey skey; |
56 |
|
|
struct passwd *pp; |
57 |
|
|
|
58 |
|
|
n = rmkey = hexmode = enable = 0; |
59 |
|
|
defaultsetup = 1; |
60 |
|
|
ht = auth_type = NULL; |
61 |
|
|
|
62 |
|
|
for (i = 1; i < argc && argv[i][0] == '-' && strcmp(argv[i], "--");) { |
63 |
|
|
if (argv[i][2] == '\0') { |
64 |
|
|
/* Single character switch */ |
65 |
|
|
switch (argv[i][1]) { |
66 |
|
|
case 'a': |
67 |
|
|
if (argv[++i] == NULL || argv[i][0] == '\0') |
68 |
|
|
usage(); |
69 |
|
|
auth_type = argv[i]; |
70 |
|
|
break; |
71 |
|
|
case 's': |
72 |
|
|
defaultsetup = 0; |
73 |
|
|
if (auth_type == NULL) |
74 |
|
|
auth_type = "skey"; |
75 |
|
|
break; |
76 |
|
|
case 'x': |
77 |
|
|
hexmode = 1; |
78 |
|
|
break; |
79 |
|
|
case 'r': |
80 |
|
|
rmkey = 1; |
81 |
|
|
break; |
82 |
|
|
case 'n': |
83 |
|
|
if (argv[++i] == NULL || argv[i][0] == '\0') |
84 |
|
|
usage(); |
85 |
|
|
n = strtonum(argv[i], 1, SKEY_MAX_SEQ - 1, &errstr); |
86 |
|
|
if (errstr) |
87 |
|
|
errx(1, "count must be > 0 and < %d", |
88 |
|
|
SKEY_MAX_SEQ); |
89 |
|
|
break; |
90 |
|
|
case 'D': |
91 |
|
|
enable = -1; |
92 |
|
|
break; |
93 |
|
|
case 'E': |
94 |
|
|
enable = 1; |
95 |
|
|
break; |
96 |
|
|
default: |
97 |
|
|
usage(); |
98 |
|
|
} |
99 |
|
|
} else { |
100 |
|
|
/* Multi character switches are hash types */ |
101 |
|
|
if ((ht = skey_set_algorithm(&argv[i][1])) == NULL) { |
102 |
|
|
warnx("Unknown hash algorithm %s", &argv[i][1]); |
103 |
|
|
usage(); |
104 |
|
|
} |
105 |
|
|
} |
106 |
|
|
i++; |
107 |
|
|
} |
108 |
|
|
argv += i; |
109 |
|
|
argc -= i; |
110 |
|
|
|
111 |
|
|
if (argc > 1 || (enable && argc)) |
112 |
|
|
usage(); |
113 |
|
|
|
114 |
|
|
/* Handle -D and -E */ |
115 |
|
|
if (enable) { |
116 |
|
|
enable_db(enable); |
117 |
|
|
exit(0); |
118 |
|
|
} |
119 |
|
|
|
120 |
|
|
if (getuid() != 0) { |
121 |
|
|
if (pledge("stdio rpath wpath cpath fattr flock tty proc exec " |
122 |
|
|
"getpw", NULL) == -1) |
123 |
|
|
err(1, "pledge"); |
124 |
|
|
|
125 |
|
|
if ((pp = getpwuid(getuid())) == NULL) |
126 |
|
|
err(1, "no user with uid %u", getuid()); |
127 |
|
|
|
128 |
|
|
if (argc == 1) { |
129 |
|
|
char me[UT_NAMESIZE + 1]; |
130 |
|
|
|
131 |
|
|
(void)strlcpy(me, pp->pw_name, sizeof me); |
132 |
|
|
if ((pp = getpwnam(argv[0])) == NULL) |
133 |
|
|
errx(1, "User unknown: %s", argv[0]); |
134 |
|
|
if (strcmp(pp->pw_name, me) != 0) |
135 |
|
|
errx(1, "Permission denied."); |
136 |
|
|
} |
137 |
|
|
} else { |
138 |
|
|
if (pledge("stdio rpath wpath cpath fattr flock tty getpw id flock rpath cpath wpath", |
139 |
|
|
NULL) == -1) |
140 |
|
|
err(1, "pledge"); |
141 |
|
|
|
142 |
|
|
if (argc == 1) { |
143 |
|
|
if ((pp = getpwnam(argv[0])) == NULL) { |
144 |
|
|
static struct passwd _pp; |
145 |
|
|
|
146 |
|
|
_pp.pw_name = argv[0]; |
147 |
|
|
pp = &_pp; |
148 |
|
|
warnx("Warning, user unknown: %s", argv[0]); |
149 |
|
|
} else { |
150 |
|
|
/* So the file ends up owned by the proper ID */ |
151 |
|
|
if (setresuid(-1, pp->pw_uid, -1) != 0) |
152 |
|
|
errx(1, "unable to change uid to %u", |
153 |
|
|
pp->pw_uid); |
154 |
|
|
} |
155 |
|
|
} else if ((pp = getpwuid(0)) == NULL) |
156 |
|
|
err(1, "no user with uid 0"); |
157 |
|
|
|
158 |
|
|
if (pledge("stdio rpath wpath cpath fattr flock tty", NULL) |
159 |
|
|
== -1) |
160 |
|
|
err(1, "pledge"); |
161 |
|
|
} |
162 |
|
|
|
163 |
|
|
switch (skey_haskey(pp->pw_name)) { |
164 |
|
|
case -1: |
165 |
|
|
if (errno == ENOENT || errno == EPERM) |
166 |
|
|
errx(1, "S/Key disabled"); |
167 |
|
|
else |
168 |
|
|
err(1, "cannot open database"); |
169 |
|
|
break; |
170 |
|
|
case 0: |
171 |
|
|
/* existing user */ |
172 |
|
|
break; |
173 |
|
|
case 1: |
174 |
|
|
if (!defaultsetup && strcmp(auth_type, "skey") == 0) { |
175 |
|
|
fprintf(stderr, |
176 |
|
|
"You must authenticate yourself before using S/Key for the first time. In\n" |
177 |
|
|
"secure mode this is normally done via an existing S/Key key. However, since\n" |
178 |
|
|
"you do not have an entry in the S/Key database you will have to specify an\n" |
179 |
|
|
"alternate authentication type via the `-a' flag, e.g.\n" |
180 |
|
|
" \"skeyinit -s -a passwd\"\n\n" |
181 |
|
|
"Note that entering a plaintext password over a non-secure link defeats the\n" |
182 |
|
|
"purpose of using S/Key in the fist place.\n"); |
183 |
|
|
exit(1); |
184 |
|
|
} |
185 |
|
|
break; |
186 |
|
|
} |
187 |
|
|
|
188 |
|
|
if (getuid() != 0) { |
189 |
|
|
if ((pp = pw_dup(pp)) == NULL) |
190 |
|
|
err(1, NULL); |
191 |
|
|
if (!auth_userokay(pp->pw_name, auth_type, NULL, NULL)) |
192 |
|
|
errx(1, "Password incorrect"); |
193 |
|
|
} |
194 |
|
|
|
195 |
|
|
if (pledge("stdio rpath wpath cpath fattr flock tty", NULL) == -1) |
196 |
|
|
err(1, "pledge"); |
197 |
|
|
|
198 |
|
|
/* Build up a default seed based on the hostname and some randomness */ |
199 |
|
|
if (gethostname(hostname, sizeof(hostname)) < 0) |
200 |
|
|
err(1, "gethostname"); |
201 |
|
|
for (i = 0, p = seed; hostname[i] && i < SKEY_NAMELEN; i++) { |
202 |
|
|
if (isalnum((unsigned char)hostname[i])) |
203 |
|
|
*p++ = tolower((unsigned char)hostname[i]); |
204 |
|
|
} |
205 |
|
|
for (i = 0; i < 5; i++) |
206 |
|
|
*p++ = arc4random_uniform(10) + '0'; |
207 |
|
|
*p = '\0'; |
208 |
|
|
|
209 |
|
|
/* |
210 |
|
|
* Lookup and lock the record we are about to modify. |
211 |
|
|
* If this is a new entry this will prevent other users |
212 |
|
|
* from appending new entries (and clobbering ours). |
213 |
|
|
*/ |
214 |
|
|
rval = skeylookup(&skey, pp->pw_name); |
215 |
|
|
switch (rval) { |
216 |
|
|
case -1: |
217 |
|
|
err(1, "cannot open database"); |
218 |
|
|
break; |
219 |
|
|
case 0: |
220 |
|
|
/* remove user if asked to do so */ |
221 |
|
|
if (rmkey) { |
222 |
|
|
if (snprintf(filename, sizeof(filename), |
223 |
|
|
"%s/%s", _PATH_SKEYDIR, pp->pw_name) |
224 |
|
|
>= sizeof(filename)) |
225 |
|
|
errc(1, ENAMETOOLONG, |
226 |
|
|
"Cannot remove S/Key entry"); |
227 |
|
|
if (unlink(filename) != 0) |
228 |
|
|
err(1, "Cannot remove S/Key entry"); |
229 |
|
|
printf("S/Key entry for %s removed.\n", |
230 |
|
|
pp->pw_name); |
231 |
|
|
exit(0); |
232 |
|
|
} |
233 |
|
|
|
234 |
|
|
(void)printf("[Updating %s with %s]\n", pp->pw_name, |
235 |
|
|
ht ? ht : skey_get_algorithm()); |
236 |
|
|
(void)printf("Old seed: [%s] %s\n", |
237 |
|
|
skey_get_algorithm(), skey.seed); |
238 |
|
|
|
239 |
|
|
/* |
240 |
|
|
* Sanity check old seed. |
241 |
|
|
*/ |
242 |
|
|
l = strlen(skey.seed); |
243 |
|
|
for (p = skey.seed; *p; p++) { |
244 |
|
|
if (isalpha((unsigned char)*p)) { |
245 |
|
|
if (isupper((unsigned char)*p)) |
246 |
|
|
*p = tolower((unsigned char)*p); |
247 |
|
|
} else if (!isdigit((unsigned char)*p)) { |
248 |
|
|
memmove(p, p + 1, l - (p - skey.seed)); |
249 |
|
|
l--; |
250 |
|
|
} |
251 |
|
|
} |
252 |
|
|
|
253 |
|
|
/* If the seed ends in 0-8 just add one. */ |
254 |
|
|
if (l > 0) { |
255 |
|
|
lastc = skey.seed[l - 1]; |
256 |
|
|
if (isdigit((unsigned char)lastc) && |
257 |
|
|
lastc != '9') { |
258 |
|
|
(void)strlcpy(seed, skey.seed, |
259 |
|
|
sizeof seed); |
260 |
|
|
seed[l - 1] = lastc + 1; |
261 |
|
|
} |
262 |
|
|
if (isdigit((unsigned char)lastc) && |
263 |
|
|
lastc == '9' && l < 16) { |
264 |
|
|
(void)strlcpy(seed, skey.seed, |
265 |
|
|
sizeof seed); |
266 |
|
|
seed[l - 1] = '0'; |
267 |
|
|
seed[l] = '0'; |
268 |
|
|
seed[l + 1] = '\0'; |
269 |
|
|
} |
270 |
|
|
} |
271 |
|
|
break; |
272 |
|
|
case 1: |
273 |
|
|
if (rmkey) |
274 |
|
|
errx(1, "You have no entry to remove."); |
275 |
|
|
(void)printf("[Adding %s with %s]\n", pp->pw_name, |
276 |
|
|
ht ? ht : skey_get_algorithm()); |
277 |
|
|
if (snprintf(filename, sizeof(filename), "%s/%s", |
278 |
|
|
_PATH_SKEYDIR, pp->pw_name) >= sizeof(filename)) |
279 |
|
|
errc(1, ENAMETOOLONG, |
280 |
|
|
"Cannot create S/Key entry"); |
281 |
|
|
if ((l = open(filename, |
282 |
|
|
O_RDWR | O_NONBLOCK | O_CREAT | O_TRUNC |O_NOFOLLOW, |
283 |
|
|
S_IRUSR | S_IWUSR)) == -1 || |
284 |
|
|
flock(l, LOCK_EX) != 0 || |
285 |
|
|
(skey.keyfile = fdopen(l, "r+")) == NULL) |
286 |
|
|
err(1, "Cannot create S/Key entry"); |
287 |
|
|
break; |
288 |
|
|
} |
289 |
|
|
if (fchown(fileno(skey.keyfile), pp->pw_uid, -1) != 0 || |
290 |
|
|
fchmod(fileno(skey.keyfile), S_IRUSR | S_IWUSR) != 0) |
291 |
|
|
err(1, "can't set owner/mode for %s", pp->pw_name); |
292 |
|
|
if (defaultsetup && n == 0) |
293 |
|
|
n = 100; |
294 |
|
|
|
295 |
|
|
/* Set hash type if asked to */ |
296 |
|
|
if (ht && strcmp(ht, skey_get_algorithm()) != 0) |
297 |
|
|
skey_set_algorithm(ht); |
298 |
|
|
|
299 |
|
|
alarm(180); |
300 |
|
|
if (!defaultsetup) |
301 |
|
|
secure_mode(&n, key, seed, sizeof seed, buf, sizeof(buf)); |
302 |
|
|
else |
303 |
|
|
normal_mode(pp->pw_name, n, key, seed); |
304 |
|
|
alarm(0); |
305 |
|
|
|
306 |
|
|
/* XXX - why use malloc here? */ |
307 |
|
|
if ((skey.val = malloc(16 + 1)) == NULL) |
308 |
|
|
err(1, "Can't allocate memory"); |
309 |
|
|
btoa8(skey.val, key); |
310 |
|
|
|
311 |
|
|
(void)fseek(skey.keyfile, 0L, SEEK_SET); |
312 |
|
|
(void)fprintf(skey.keyfile, "%s\n%s\n%04d\n%s\n%s\n", |
313 |
|
|
pp->pw_name, skey_get_algorithm(), n, seed, skey.val); |
314 |
|
|
(void)fclose(skey.keyfile); |
315 |
|
|
|
316 |
|
|
(void)printf("\nID %s skey is otp-%s %d %s\n", pp->pw_name, |
317 |
|
|
skey_get_algorithm(), n, seed); |
318 |
|
|
(void)printf("Next login password: %s\n\n", |
319 |
|
|
hexmode ? put8(buf, key) : btoe(buf, key)); |
320 |
|
|
exit(0); |
321 |
|
|
} |
322 |
|
|
|
323 |
|
|
void |
324 |
|
|
secure_mode(int *count, char *key, char *seed, size_t seedlen, |
325 |
|
|
char *buf, size_t bufsiz) |
326 |
|
|
{ |
327 |
|
|
char *p, newseed[SKEY_MAX_SEED_LEN + 2]; |
328 |
|
|
const char *errstr; |
329 |
|
|
int i, n = *count; |
330 |
|
|
|
331 |
|
|
(void)puts("You need the 6 words generated from the \"skey\" command."); |
332 |
|
|
if (n == 0) { |
333 |
|
|
for (i = 0; ; i++) { |
334 |
|
|
if (i >= 2) |
335 |
|
|
exit(1); |
336 |
|
|
|
337 |
|
|
(void)printf("Enter sequence count from 1 to %d: ", |
338 |
|
|
SKEY_MAX_SEQ); |
339 |
|
|
(void)fgets(buf, bufsiz, stdin); |
340 |
|
|
clearerr(stdin); |
341 |
|
|
rip(buf); |
342 |
|
|
n = strtonum(buf, 1, SKEY_MAX_SEQ-1, &errstr); |
343 |
|
|
if (!errstr) |
344 |
|
|
break; /* Valid range */ |
345 |
|
|
fprintf(stderr, |
346 |
|
|
"ERROR: Count must be between 1 and %d\n", |
347 |
|
|
SKEY_MAX_SEQ - 1); |
348 |
|
|
} |
349 |
|
|
*count= n; |
350 |
|
|
} |
351 |
|
|
|
352 |
|
|
for (i = 0; ; i++) { |
353 |
|
|
if (i >= 2) |
354 |
|
|
exit(1); |
355 |
|
|
|
356 |
|
|
(void)printf("Enter new seed [default %s]: ", seed); |
357 |
|
|
(void)fgets(newseed, sizeof(newseed), stdin); /* XXX */ |
358 |
|
|
clearerr(stdin); |
359 |
|
|
rip(newseed); |
360 |
|
|
if (strlen(newseed) > SKEY_MAX_SEED_LEN) { |
361 |
|
|
(void)fprintf(stderr, "ERROR: Seed must be between 1 " |
362 |
|
|
"and %d characters in length\n", SKEY_MAX_SEED_LEN); |
363 |
|
|
continue; |
364 |
|
|
} |
365 |
|
|
for (p = newseed; *p; p++) { |
366 |
|
|
if (isspace((unsigned char)*p)) { |
367 |
|
|
(void)fputs("ERROR: Seed must not contain " |
368 |
|
|
"any spaces\n", stderr); |
369 |
|
|
break; |
370 |
|
|
} else if (isalpha((unsigned char)*p)) { |
371 |
|
|
if (isupper((unsigned char)*p)) |
372 |
|
|
*p = tolower((unsigned char)*p); |
373 |
|
|
} else if (!isdigit((unsigned char)*p)) { |
374 |
|
|
(void)fputs("ERROR: Seed must be purely " |
375 |
|
|
"alphanumeric\n", stderr); |
376 |
|
|
break; |
377 |
|
|
} |
378 |
|
|
} |
379 |
|
|
if (*p == '\0') |
380 |
|
|
break; /* Valid seed */ |
381 |
|
|
} |
382 |
|
|
if (newseed[0] != '\0') |
383 |
|
|
(void)strlcpy(seed, newseed, seedlen); |
384 |
|
|
|
385 |
|
|
for (i = 0; ; i++) { |
386 |
|
|
if (i >= 2) |
387 |
|
|
exit(1); |
388 |
|
|
|
389 |
|
|
(void)printf("otp-%s %d %s\nS/Key access password: ", |
390 |
|
|
skey_get_algorithm(), n, seed); |
391 |
|
|
(void)fgets(buf, bufsiz, stdin); |
392 |
|
|
clearerr(stdin); |
393 |
|
|
rip(buf); |
394 |
|
|
backspace(buf); |
395 |
|
|
|
396 |
|
|
if (buf[0] == '?') { |
397 |
|
|
(void)puts("Enter 6 words from secure S/Key calculation."); |
398 |
|
|
continue; |
399 |
|
|
} else if (buf[0] == '\0') |
400 |
|
|
exit(1); |
401 |
|
|
|
402 |
|
|
if (etob(key, buf) == 1 || atob8(key, buf) == 0) |
403 |
|
|
break; /* Valid format */ |
404 |
|
|
(void)fputs("ERROR: Invalid format - try again with the 6 words.\n", |
405 |
|
|
stderr); |
406 |
|
|
} |
407 |
|
|
} |
408 |
|
|
|
409 |
|
|
void |
410 |
|
|
normal_mode(char *username, int n, char *key, char *seed) |
411 |
|
|
{ |
412 |
|
|
int i, nn; |
413 |
|
|
char passwd[SKEY_MAX_PW_LEN+2], key2[SKEY_BINKEY_SIZE]; |
414 |
|
|
|
415 |
|
|
/* Get user's secret passphrase */ |
416 |
|
|
for (i = 0; ; i++) { |
417 |
|
|
if (i > 2) |
418 |
|
|
errx(1, "S/Key entry not updated"); |
419 |
|
|
|
420 |
|
|
if (readpassphrase("Enter new secret passphrase: ", passwd, |
421 |
|
|
sizeof(passwd), 0) == NULL || passwd[0] == '\0') |
422 |
|
|
exit(1); |
423 |
|
|
|
424 |
|
|
if (strlen(passwd) < SKEY_MIN_PW_LEN) { |
425 |
|
|
(void)fprintf(stderr, |
426 |
|
|
"ERROR: Your passphrase must be at least %d " |
427 |
|
|
"characters long.\n", SKEY_MIN_PW_LEN); |
428 |
|
|
continue; |
429 |
|
|
} else if (strcmp(passwd, username) == 0) { |
430 |
|
|
(void)fputs("ERROR: Your passphrase may not be the " |
431 |
|
|
"same as your user name.\n", stderr); |
432 |
|
|
continue; |
433 |
|
|
} else if (strspn(passwd, "abcdefghijklmnopqrstuvwxyz") == |
434 |
|
|
strlen(passwd)) { |
435 |
|
|
(void)fputs("ERROR: Your passphrase must contain more " |
436 |
|
|
"than just lower case letters.\nWhitespace, " |
437 |
|
|
"numbers, and punctuation are suggested.\n", |
438 |
|
|
stderr); |
439 |
|
|
continue; |
440 |
|
|
} else if (strlen(passwd) > 63) { |
441 |
|
|
(void)fprintf(stderr, "WARNING: Your passphrase is " |
442 |
|
|
"longer than the recommended maximum length of 63\n"); |
443 |
|
|
} |
444 |
|
|
/* XXX - should check for passphrase that is really too long */ |
445 |
|
|
|
446 |
|
|
/* Crunch seed and passphrase into starting key */ |
447 |
|
|
nn = keycrunch(key, seed, passwd); |
448 |
|
|
explicit_bzero(passwd, sizeof(passwd)); |
449 |
|
|
if (nn != 0) |
450 |
|
|
err(2, "key crunch failed"); |
451 |
|
|
|
452 |
|
|
if (readpassphrase("Again secret passphrase: ", passwd, |
453 |
|
|
sizeof(passwd), 0) == NULL || passwd[0] == '\0') |
454 |
|
|
exit(1); |
455 |
|
|
|
456 |
|
|
/* Crunch seed and passphrase into starting key */ |
457 |
|
|
nn = keycrunch(key2, seed, passwd); |
458 |
|
|
explicit_bzero(passwd, sizeof(passwd)); |
459 |
|
|
if (nn != 0) |
460 |
|
|
err(2, "key crunch failed"); |
461 |
|
|
|
462 |
|
|
if (memcmp(key, key2, sizeof(key2)) == 0) |
463 |
|
|
break; |
464 |
|
|
|
465 |
|
|
(void)fputs("Passphrases do not match.\n", stderr); |
466 |
|
|
} |
467 |
|
|
|
468 |
|
|
nn = n; |
469 |
|
|
while (nn-- != 0) |
470 |
|
|
f(key); |
471 |
|
|
} |
472 |
|
|
|
473 |
|
|
void |
474 |
|
|
enable_db(int op) |
475 |
|
|
{ |
476 |
|
|
if (op == 1) { |
477 |
|
|
/* enable */ |
478 |
|
|
if (mkdir(_PATH_SKEYDIR, 01730) != 0 && errno != EEXIST) |
479 |
|
|
err(1, "can't mkdir %s", _PATH_SKEYDIR); |
480 |
|
|
if (chown(_PATH_SKEYDIR, geteuid(), getegid()) != 0) |
481 |
|
|
err(1, "can't chown %s", _PATH_SKEYDIR); |
482 |
|
|
if (chmod(_PATH_SKEYDIR, 01730) != 0) |
483 |
|
|
err(1, "can't chmod %s", _PATH_SKEYDIR); |
484 |
|
|
} else { |
485 |
|
|
/* disable */ |
486 |
|
|
if (chmod(_PATH_SKEYDIR, 0) != 0 && errno != ENOENT) |
487 |
|
|
err(1, "can't chmod %s", _PATH_SKEYDIR); |
488 |
|
|
} |
489 |
|
|
} |
490 |
|
|
|
491 |
|
|
void |
492 |
|
|
usage(void) |
493 |
|
|
{ |
494 |
|
|
extern char *__progname; |
495 |
|
|
|
496 |
|
|
(void)fprintf(stderr, "usage: %s [-DErsx] [-a auth-type] [-n count]" |
497 |
|
|
"\n\t[-md5 | -rmd160 | -sha1] [user]\n", __progname); |
498 |
|
|
exit(1); |
499 |
|
|
} |