1/* $NetBSD: skey.c,v 1.17 2004/11/01 21:52:07 dsl 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.17 2004/11/01 21:52:07 dsl 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 40int 41main(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 152static void 153usage(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