xref: /openbsd/usr.bin/skey/skey.c (revision 7b36286a)
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
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
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