skey.c revision 1.31
1/* $OpenBSD: skey.c,v 1.31 2015/10/09 21:59:34 tim 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 34void usage(); 35 36extern char *__progname; 37 38int 39main(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 we were called as otp-METHOD, set algorithm based on that */ 47 if (strncmp(__progname, "otp-", 4) == 0) { 48 algo = __progname + 4; 49 if (skey_set_algorithm(algo) == NULL) 50 errx(1, "Unknown hash algorithm %s", algo); 51 } 52 53 for (i = 1; i < argc && argv[i][0] == '-' && strcmp(argv[i], "--");) { 54 if (argv[i][2] == '\0') { 55 /* Single character switch */ 56 switch (argv[i][1]) { 57 case 'n': 58 if (++i == argc) 59 usage(); 60 cnt = strtonum(argv[i], 1, SKEY_MAX_SEQ -1, &errstr); 61 if (errstr) 62 usage(); 63 break; 64 case 'p': 65 if (++i == argc) 66 usage(); 67 if (strlcpy(passwd, argv[i], sizeof(passwd)) >= 68 sizeof(passwd)) 69 errx(1, "Password too long"); 70 pass = 1; 71 break; 72 case 'x': 73 hexmode = 1; 74 break; 75 default: 76 usage(); 77 } 78 } else { 79 /* Multi character switches are hash types */ 80 if (skey_set_algorithm(&argv[i][1]) == NULL) { 81 warnx("Unknown hash algorithm %s", &argv[i][1]); 82 usage(); 83 } 84 } 85 i++; 86 } 87 88 if (argc > i + 2) 89 usage(); 90 91 /* Could be in the form <number>/<seed> */ 92 if (argc <= i + 1) { 93 /* look for / in it */ 94 if (argc <= i) 95 usage(); 96 slash = strchr(argv[i], '/'); 97 if (slash == NULL) 98 usage(); 99 *slash++ = '\0'; 100 seed = slash; 101 102 n = strtonum(argv[i], 0, SKEY_MAX_SEQ, &errstr); 103 if (errstr) { 104 warnx("%s: %s", argv[i], errstr); 105 usage(); 106 } 107 } else { 108 n = strtonum(argv[i], 0, SKEY_MAX_SEQ, &errstr); 109 if (errstr) { 110 warnx("%s: %s", argv[i], errstr); 111 usage(); 112 } 113 seed = argv[++i]; 114 } 115 116 /* Get user's secret passphrase */ 117 if (!pass && (readpassphrase("Enter secret passphrase: ", passwd, 118 sizeof(passwd), 0) == NULL || passwd[0] == '\0')) 119 exit(1); 120 121 /* Crunch seed and passphrase into starting key */ 122 if (keycrunch(key, seed, passwd) != 0) 123 errx(1, "key crunch failed"); 124 125 if (cnt == 1) { 126 while (n-- != 0) 127 f(key); 128 (void)puts(hexmode ? put8(buf, key) : btoe(buf, key)); 129 } else { 130 for (i = 0; i <= n - cnt; i++) 131 f(key); 132 for (; i <= n; i++) { 133 if (hexmode) 134 (void)printf("%d: %s\n", i, put8(buf, key)); 135 else 136 (void)printf("%d: %-29s\n", i, btoe(buf, key)); 137 f(key); 138 } 139 } 140 exit(0); 141} 142 143void 144usage(void) 145{ 146 fprintf(stderr, 147 "usage: %s [-x] [-md5 | -rmd160 | -sha1] [-n count]\n\t" 148 "[-p passphrase] <sequence#>[/] key\n", __progname); 149 exit(1); 150} 151