1 |
|
|
/* $OpenBSD: skey.c,v 1.34 2017/05/03 09:51:39 mestre Exp $ */ |
2 |
|
|
/* |
3 |
|
|
* OpenBSD S/Key (skey.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 |
|
|
* |
13 |
|
|
* Stand-alone program for computing responses to S/Key challenges. |
14 |
|
|
* Takes the iteration count and seed as command line args, prompts |
15 |
|
|
* for the user's key, and produces both word and hex format responses. |
16 |
|
|
* |
17 |
|
|
* Usage example: |
18 |
|
|
* >skey 88 ka9q2 |
19 |
|
|
* Enter password: |
20 |
|
|
* OMEN US HORN OMIT BACK AHOY |
21 |
|
|
* > |
22 |
|
|
* |
23 |
|
|
*/ |
24 |
|
|
|
25 |
|
|
#include <err.h> |
26 |
|
|
#include <limits.h> |
27 |
|
|
#include <stdio.h> |
28 |
|
|
#include <stdlib.h> |
29 |
|
|
#include <string.h> |
30 |
|
|
#include <unistd.h> |
31 |
|
|
#include <readpassphrase.h> |
32 |
|
|
#include <skey.h> |
33 |
|
|
|
34 |
|
|
void usage(); |
35 |
|
|
|
36 |
|
|
extern char *__progname; |
37 |
|
|
|
38 |
|
|
int |
39 |
|
|
main(int argc, char *argv[]) |
40 |
|
|
{ |
41 |
|
|
int n, i, cnt = 1, pass = 0, hexmode = 0; |
42 |
|
|
char passwd[SKEY_MAX_PW_LEN+1], key[SKEY_BINKEY_SIZE]; |
43 |
|
|
char buf[33], *seed, *slash, *algo; |
44 |
|
|
const char *errstr; |
45 |
|
|
|
46 |
|
|
if (pledge("stdio tty flock rpath cpath wpath", NULL) == -1) |
47 |
|
|
err(1, "pledge"); |
48 |
|
|
|
49 |
|
|
/* If we were called as otp-METHOD, set algorithm based on that */ |
50 |
|
|
if (strncmp(__progname, "otp-", 4) == 0) { |
51 |
|
|
algo = __progname + 4; |
52 |
|
|
if (skey_set_algorithm(algo) == NULL) |
53 |
|
|
errx(1, "Unknown hash algorithm %s", algo); |
54 |
|
|
} |
55 |
|
|
|
56 |
|
|
for (i = 1; i < argc && argv[i][0] == '-' && strcmp(argv[i], "--");) { |
57 |
|
|
if (argv[i][2] == '\0') { |
58 |
|
|
/* Single character switch */ |
59 |
|
|
switch (argv[i][1]) { |
60 |
|
|
case 'n': |
61 |
|
|
if (++i == argc) |
62 |
|
|
usage(); |
63 |
|
|
cnt = strtonum(argv[i], 1, SKEY_MAX_SEQ -1, &errstr); |
64 |
|
|
if (errstr) |
65 |
|
|
usage(); |
66 |
|
|
break; |
67 |
|
|
case 'p': |
68 |
|
|
if (++i == argc) |
69 |
|
|
usage(); |
70 |
|
|
if (strlcpy(passwd, argv[i], sizeof(passwd)) >= |
71 |
|
|
sizeof(passwd)) |
72 |
|
|
errx(1, "Password too long"); |
73 |
|
|
pass = 1; |
74 |
|
|
break; |
75 |
|
|
case 'x': |
76 |
|
|
hexmode = 1; |
77 |
|
|
break; |
78 |
|
|
default: |
79 |
|
|
usage(); |
80 |
|
|
} |
81 |
|
|
} else { |
82 |
|
|
/* Multi character switches are hash types */ |
83 |
|
|
if (skey_set_algorithm(&argv[i][1]) == NULL) { |
84 |
|
|
warnx("Unknown hash algorithm %s", &argv[i][1]); |
85 |
|
|
usage(); |
86 |
|
|
} |
87 |
|
|
} |
88 |
|
|
i++; |
89 |
|
|
} |
90 |
|
|
|
91 |
|
|
if (argc > i + 2) |
92 |
|
|
usage(); |
93 |
|
|
|
94 |
|
|
/* Could be in the form <number>/<seed> */ |
95 |
|
|
if (argc <= i + 1) { |
96 |
|
|
/* look for / in it */ |
97 |
|
|
if (argc <= i) |
98 |
|
|
usage(); |
99 |
|
|
slash = strchr(argv[i], '/'); |
100 |
|
|
if (slash == NULL) |
101 |
|
|
usage(); |
102 |
|
|
*slash++ = '\0'; |
103 |
|
|
seed = slash; |
104 |
|
|
|
105 |
|
|
n = strtonum(argv[i], 0, SKEY_MAX_SEQ, &errstr); |
106 |
|
|
if (errstr) { |
107 |
|
|
warnx("%s: %s", argv[i], errstr); |
108 |
|
|
usage(); |
109 |
|
|
} |
110 |
|
|
} else { |
111 |
|
|
n = strtonum(argv[i], 0, SKEY_MAX_SEQ, &errstr); |
112 |
|
|
if (errstr) { |
113 |
|
|
warnx("%s: %s", argv[i], errstr); |
114 |
|
|
usage(); |
115 |
|
|
} |
116 |
|
|
seed = argv[++i]; |
117 |
|
|
} |
118 |
|
|
|
119 |
|
|
/* Get user's secret passphrase */ |
120 |
|
|
if (!pass && (readpassphrase("Enter secret passphrase: ", passwd, |
121 |
|
|
sizeof(passwd), 0) == NULL || passwd[0] == '\0')) |
122 |
|
|
exit(1); |
123 |
|
|
|
124 |
|
|
/* Crunch seed and passphrase into starting key */ |
125 |
|
|
if (keycrunch(key, seed, passwd) != 0) { |
126 |
|
|
explicit_bzero(passwd, sizeof(passwd)); |
127 |
|
|
errx(1, "key crunch failed"); |
128 |
|
|
} |
129 |
|
|
|
130 |
|
|
explicit_bzero(passwd, sizeof(passwd)); |
131 |
|
|
|
132 |
|
|
if (cnt == 1) { |
133 |
|
|
while (n-- != 0) |
134 |
|
|
f(key); |
135 |
|
|
(void)puts(hexmode ? put8(buf, key) : btoe(buf, key)); |
136 |
|
|
} else { |
137 |
|
|
for (i = 0; i <= n - cnt; i++) |
138 |
|
|
f(key); |
139 |
|
|
for (; i <= n; i++) { |
140 |
|
|
if (hexmode) |
141 |
|
|
(void)printf("%d: %s\n", i, put8(buf, key)); |
142 |
|
|
else |
143 |
|
|
(void)printf("%d: %-29s\n", i, btoe(buf, key)); |
144 |
|
|
f(key); |
145 |
|
|
} |
146 |
|
|
} |
147 |
|
|
exit(0); |
148 |
|
|
} |
149 |
|
|
|
150 |
|
|
void |
151 |
|
|
usage(void) |
152 |
|
|
{ |
153 |
|
|
fprintf(stderr, |
154 |
|
|
"usage: %s [-x] [-md5 | -rmd160 | -sha1] [-n count]\n\t" |
155 |
|
|
"[-p passphrase] <sequence#>[/] key\n", __progname); |
156 |
|
|
exit(1); |
157 |
|
|
} |