1 /* $OpenBSD: skey.c,v 1.23 2005/07/06 21:45:44 jmc 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 <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <err.h>
29 #include <unistd.h>
30 #include <skey.h>
31
32 void usage(char *);
33
34 int
main(int argc,char * argv[])35 main(int argc, char *argv[])
36 {
37 int n, i, cnt = 1, pass = 0, hexmode = 0;
38 char passwd[SKEY_MAX_PW_LEN+1], key[SKEY_BINKEY_SIZE];
39 char buf[33], *seed, *slash;
40
41 /* If we were called as otp-METHOD, set algorithm based on that */
42 if ((slash = strrchr(argv[0], '/')))
43 slash++;
44 else
45 slash = argv[0];
46 if (strncmp(slash, "otp-", 4) == 0) {
47 slash += 4;
48 if (skey_set_algorithm(slash) == NULL)
49 errx(1, "Unknown hash algorithm %s", slash);
50 }
51
52 for (i = 1; i < argc && argv[i][0] == '-' && strcmp(argv[i], "--");) {
53 if (argv[i][2] == '\0') {
54 /* Single character switch */
55 switch (argv[i][1]) {
56 case 'n':
57 if (++i == argc)
58 usage(argv[0]);
59 cnt = atoi(argv[i]);
60 break;
61 case 'p':
62 if (++i == argc)
63 usage(argv[0]);
64 if (strlcpy(passwd, argv[i], sizeof(passwd)) >=
65 sizeof(passwd))
66 errx(1, "Password too long");
67 pass = 1;
68 break;
69 case 'x':
70 hexmode = 1;
71 break;
72 default:
73 usage(argv[0]);
74 }
75 } else {
76 /* Multi character switches are hash types */
77 if (skey_set_algorithm(&argv[i][1]) == NULL) {
78 warnx("Unknown hash algorithm %s", &argv[i][1]);
79 usage(argv[0]);
80 }
81 }
82 i++;
83 }
84
85 if (argc > i + 2)
86 usage(argv[0]);
87
88 /* Could be in the form <number>/<seed> */
89 if (argc <= i + 1) {
90 /* look for / in it */
91 if (argc <= i)
92 usage(argv[0]);
93 slash = strchr(argv[i], '/');
94 if (slash == NULL)
95 usage(argv[0]);
96 *slash++ = '\0';
97 seed = slash;
98
99 if ((n = atoi(argv[i])) < 0) {
100 warnx("%d not positive", n);
101 usage(argv[0]);
102 } else if (n > SKEY_MAX_SEQ) {
103 warnx("%d is larger than max (%d)", n, SKEY_MAX_SEQ);
104 usage(argv[0]);
105 }
106 } else {
107 if ((n = atoi(argv[i])) < 0) {
108 warnx("%d not positive", n);
109 usage(argv[0]);
110 } else if (n > SKEY_MAX_SEQ) {
111 warnx("%d is larger than max (%d)", n, SKEY_MAX_SEQ);
112 usage(argv[0]);
113 }
114 seed = argv[++i];
115 }
116
117 /* Get user's secret passphrase */
118 if (!pass) {
119 fputs("Reminder - Do not use this program while"
120 " logged in via telnet.\n", stderr);
121 (void)fputs("Enter secret passphrase: ", stderr);
122 readpass(passwd, sizeof(passwd));
123 if (passwd[0] == '\0')
124 exit(1);
125 }
126
127 /* Crunch seed and passphrase into starting key */
128 if (keycrunch(key, seed, passwd) != 0)
129 errx(1, "key crunch failed");
130
131 if (cnt == 1) {
132 while (n-- != 0)
133 f(key);
134 (void)puts(hexmode ? put8(buf, key) : btoe(buf, key));
135 } else {
136 for (i = 0; i <= n - cnt; i++)
137 f(key);
138 for (; i <= n; i++) {
139 (void)printf("%d: %-29s", i, btoe(buf, key));
140 if (hexmode)
141 (void)printf(" %s", put8(buf, key));
142 putchar('\n');
143 f(key);
144 }
145 }
146 exit(0);
147 }
148
149 void
usage(char * s)150 usage(char *s)
151 {
152 fprintf(stderr,
153 "Usage: %s [-x] [-md4 | -md5 | -rmd160 | -sha1] [-n count]\n\t"
154 "[-p passphrase] <sequence#>[/] key\n", s);
155 exit(1);
156 }
157