1 /* $NetBSD: skey.c,v 1.18 2011/09/16 15:39:29 joerg Exp $ */
2
3 /*
4 * S/KEY v1.1b (skey.c)
5 *
6 * Authors:
7 * Neil M. Haller <nmh@thumper.bellcore.com>
8 * Philip R. Karn <karn@chicago.qualcomm.com>
9 * John S. Walden <jsw@thumper.bellcore.com>
10 * Scott Chasin <chasin@crimelab.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 #include <sys/cdefs.h>
25 #ifndef lint
26 __RCSID("$NetBSD: skey.c,v 1.18 2011/09/16 15:39:29 joerg Exp $");
27 #endif
28
29 #include <ctype.h>
30 #include <err.h>
31 #include <fcntl.h>
32 #include <stdio.h>
33 #include <skey.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 __dead static void usage(char *);
39
40 int
main(int argc,char ** argv)41 main(int argc, char **argv)
42 {
43 int n, cnt, i, pass = 0, hexmode = 0;
44 char passwd[SKEY_MAX_PW_LEN+1], key[SKEY_BINKEY_SIZE];
45 char buf[33], *seed, *slash, *t;
46
47 cnt = 1;
48
49 while ((i = getopt(argc, argv, "fn:p:t:x")) != -1) {
50 switch (i) {
51 case 'f':
52 /* this option is ignored now */
53 break;
54 case 'n':
55 cnt = atoi(optarg);
56 break;
57 case 'p':
58 if (strlcpy(passwd, optarg, sizeof(passwd)) >=
59 sizeof(passwd))
60 errx(1, "Password too long");
61 pass = 1;
62 break;
63 case 't':
64 if (skey_set_algorithm(optarg) == NULL) {
65 errx(1, "Unknown hash algorithm %s", optarg);
66 }
67 break;
68 case 'x':
69 hexmode = 1;
70 break;
71 default:
72 usage(argv[0]);
73 break;
74 }
75 }
76
77 /* could be in the form <number>/<seed> */
78 if (argc <= optind + 1) {
79 /* look for / in it */
80 if (argc <= optind)
81 usage(argv[0]);
82 slash = strchr(argv[optind], '/');
83 if (slash == NULL)
84 usage(argv[0]);
85 *slash++ = '\0';
86 seed = slash;
87
88 if ((n = atoi(argv[optind])) < 0) {
89 fprintf(stderr, "%s not positive\n", argv[optind]);
90 usage(argv[0]);
91 } else if (n > SKEY_MAX_SEQ) {
92 warnx("%d is larger than max (%d)", n, SKEY_MAX_SEQ);
93 usage(argv[0]);
94 }
95 } else {
96
97 if ((n = atoi(argv[optind])) < 0) {
98 fprintf(stderr, "%s not positive\n", argv[optind]);
99 usage(argv[0]);
100 } else if (n > SKEY_MAX_SEQ) {
101 warnx("%d is larger than max (%d)", n, SKEY_MAX_SEQ);
102 usage(argv[0]);
103 }
104 seed = argv[++optind];
105 }
106
107 for(t = seed; *t; t++) {
108 if(!isalnum((unsigned char)*t))
109 errx(1, "seed must be alphanumeric");
110 }
111
112 if(!*seed || strlen(seed) > SKEY_MAX_SEED_LEN)
113 errx(1, "seed must be between 1 and %d long", SKEY_MAX_SEED_LEN);
114
115 /* Get user's secret password */
116 if (!pass) {
117 (void)fputs("Reminder - Do not use this program while "
118 "logged in via telnet or rlogin.\n", stderr);
119 fprintf(stderr, "Enter secret password: ");
120 readpass(passwd, sizeof(passwd));
121 if (passwd[0] == '\0')
122 exit(1);
123 }
124
125 if (strlen(passwd) < SKEY_MIN_PW_LEN)
126 warnx(
127 "password should be at least %d characters long according to RFC2289",
128 SKEY_MIN_PW_LEN);
129
130 /* Crunch seed and password into starting key */
131 if (keycrunch(key, seed, passwd) != 0)
132 errx(1, "key crunch failed");
133
134 if (cnt == 1) {
135 while (n-- != 0)
136 f(key);
137 (void)puts(hexmode ? put8(buf, key) : btoe(buf, key));
138 } else {
139 for (i = 0; i <= n - cnt; i++)
140 f(key);
141 for (; i <= n; i++) {
142 (void)printf("%3d: %-29s", i, btoe(buf, key));
143 if (hexmode)
144 (void)printf("\t%s", put8(buf, key));
145 puts("");
146 f(key);
147 }
148 }
149 exit(0);
150 }
151
152 static void
usage(char * s)153 usage(char *s)
154 {
155
156 fprintf(stderr,
157 "usage: %s [-n count] [-p password] [-t hash] [-x] sequence# [/] key\n",
158 s);
159 exit(1);
160 }
161