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