1 /* $NetBSD: skey.c,v 1.15 2001/07/24 23:53:25 lukem 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.15 2001/07/24 23:53:25 lukem 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 int main(int, char **); 39 void usage(char *); 40 41 int 42 main(int argc, char **argv) 43 { 44 int n, cnt, i, pass = 0, hexmode = 0; 45 char passwd[SKEY_MAX_PW_LEN+1], key[SKEY_BINKEY_SIZE]; 46 char buf[33], *seed, *slash, *t; 47 48 cnt = 1; 49 50 while ((i = getopt(argc, argv, "fn:p:t:x")) != -1) { 51 switch (i) { 52 case 'f': 53 /* this option is ignored now */ 54 break; 55 case 'n': 56 cnt = atoi(optarg); 57 break; 58 case 'p': 59 if (strlcpy(passwd, optarg, sizeof(passwd)) >= 60 sizeof(passwd)) 61 errx(1, "Password too long"); 62 pass = 1; 63 break; 64 case 't': 65 if (skey_set_algorithm(optarg) == NULL) { 66 errx(1, "Unknown hash algorithm %s", optarg); 67 } 68 break; 69 case 'x': 70 hexmode = 1; 71 break; 72 default: 73 usage(argv[0]); 74 break; 75 } 76 } 77 78 /* could be in the form <number>/<seed> */ 79 if (argc <= optind + 1) { 80 /* look for / in it */ 81 if (argc <= optind) 82 usage(argv[0]); 83 slash = strchr(argv[optind], '/'); 84 if (slash == NULL) 85 usage(argv[0]); 86 *slash++ = '\0'; 87 seed = slash; 88 89 if ((n = atoi(argv[optind])) < 0) { 90 fprintf(stderr, "%s not positive\n", argv[optind]); 91 usage(argv[0]); 92 } else if (n > SKEY_MAX_SEQ) { 93 warnx("%d is larger than max (%d)", n, SKEY_MAX_SEQ); 94 usage(argv[0]); 95 } 96 } else { 97 98 if ((n = atoi(argv[optind])) < 0) { 99 fprintf(stderr, "%s not positive\n", argv[optind]); 100 usage(argv[0]); 101 } else if (n > SKEY_MAX_SEQ) { 102 warnx("%d is larger than max (%d)", n, SKEY_MAX_SEQ); 103 usage(argv[0]); 104 } 105 seed = argv[++optind]; 106 } 107 108 for(t = seed; *t; t++) { 109 if(!isalnum(*t)) 110 errx(1, "seed must be alphanumeric"); 111 } 112 113 if(!*seed || strlen(seed) > SKEY_MAX_SEED_LEN) 114 errx(1, "seed must be between 1 and %d long", SKEY_MAX_SEED_LEN); 115 116 /* Get user's secret password */ 117 if (!pass) { 118 (void)fputs("Reminder - Do not use this program while " 119 "logged in via telnet or rlogin.\n", stderr); 120 fprintf(stderr, "Enter secret password: "); 121 readpass(passwd, sizeof(passwd)); 122 if (passwd[0] == '\0') 123 exit(1); 124 } 125 126 if (strlen(passwd) < SKEY_MIN_PW_LEN) 127 warnx( 128 "password should be at least %d characters long according to RFC2289", 129 SKEY_MIN_PW_LEN); 130 131 /* Crunch seed and password into starting key */ 132 if (keycrunch(key, seed, passwd) != 0) 133 errx(1, "key crunch failed"); 134 135 if (cnt == 1) { 136 while (n-- != 0) 137 f(key); 138 (void)puts(hexmode ? put8(buf, key) : btoe(buf, key)); 139 } else { 140 for (i = 0; i <= n - cnt; i++) 141 f(key); 142 for (; i <= n; i++) { 143 (void)printf("%3d: %-29s", i, btoe(buf, key)); 144 if (hexmode) 145 (void)printf("\t%s", put8(buf, key)); 146 puts(""); 147 f(key); 148 } 149 } 150 exit(0); 151 } 152 153 void 154 usage(char *s) 155 { 156 157 fprintf(stderr, 158 "Usage: %s [-n count] [-p password] [-t hash] [-x] sequence# [/] key\n", 159 s); 160 exit(1); 161 } 162