diff options
author | Paul Traina <pst@FreeBSD.org> | 1997-02-06 17:52:29 +0000 |
---|---|---|
committer | Paul Traina <pst@FreeBSD.org> | 1997-02-06 17:52:29 +0000 |
commit | 3c491303b581cc737565ed3b33913ac4ceded990 (patch) | |
tree | ec9d150c9da4390c2d223a04ac002523cbfd7f36 /contrib/opie/opiekey.c | |
download | src-3c491303b581cc737565ed3b33913ac4ceded990.tar.gz src-3c491303b581cc737565ed3b33913ac4ceded990.zip |
Initial import of OPIE v2.3 fromvendor/opie/2.3
ftp://ftp.nrl.navy.mil/pub/security/opie/
Notes
Notes:
svn path=/vendor/opie/dist/; revision=22347
svn path=/vendor/opie/2.3/; revision=22349; tag=vendor/opie/2.3
Diffstat (limited to 'contrib/opie/opiekey.c')
-rw-r--r-- | contrib/opie/opiekey.c | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/contrib/opie/opiekey.c b/contrib/opie/opiekey.c new file mode 100644 index 000000000000..17b5ab03507f --- /dev/null +++ b/contrib/opie/opiekey.c @@ -0,0 +1,375 @@ +/* opiekey.c: Stand-alone program for computing responses to OTP challenges. + + Takes a sequence number and seed (presumably from an OPIE challenge) + as command line arguments, prompts for the user's secret pass phrase, + and outputs a response. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from <license@inner.net>. + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. OPIE_PASS_MAX changed to + OPIE_SECRET_MAX. Added extended responses, which created + lots of changes. Eliminated extra variable. Added -x and + -t to help. Added -f flag. Added SHA support. + Modified by cmetz for OPIE 2.22. Print newline after seed too long + message. Check for minimum seed length. Correct a grammar + error. + Modified at NRL for OPIE 2.2. Check opiereadpass() return. + Change opiereadpass() calls to add echo arg. Use FUNCTION + definition et al. Check seed length here, too. Added back + hex output. Reworked final output function. + Modified at NRL for OPIE 2.0. + Written at Bellcore for the S/Key Version 1 software distribution + (skey.c). +*/ +#include "opie_cfg.h" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "opie.h" + +#ifdef __MSDOS__ +#include <dos.h> +#endif + +#if HAVE_FCNTL_H +#include <fcntl.h> +#endif /* HAVE_FCNTL_H */ + +extern char *optarg; +extern int optind, opterr; + +int aflag = 0; + +char *algnames[] = { NULL, NULL, NULL, "SHA-1", "MD4", "MD5" }; +char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" }; + +/******** Begin real source code ***************/ + +static VOIDRET usage FUNCTION((s), char *s) +{ + fprintf(stderr, "usage: %s [-v] [-h] [-f] [-x] [-t type] [-4 | -5 | -s] [-a] [-n count] sequence_number seed\n", s); + exit(1); +} + +#define RESPONSE_STANDARD 0 +#define RESPONSE_WORD 1 +#define RESPONSE_HEX 2 +#define RESPONSE_INIT 3 +#define RESPONSE_INIT_WORD 4 +#define RESPONSE_UNKNOWN 5 + +struct _rtrans { + int type; + char *name; +}; + +static struct _rtrans rtrans[] = { + { RESPONSE_WORD, "word" }, + { RESPONSE_HEX, "hex" }, + { RESPONSE_INIT, "init" }, + { RESPONSE_INIT_WORD, "init-word" }, + { RESPONSE_STANDARD, "" }, + { RESPONSE_STANDARD, "standard" }, + { RESPONSE_STANDARD, "otp" }, + { RESPONSE_UNKNOWN, NULL } +}; + +static void getsecret FUNCTION((secret, promptextra, retype), char *secret AND char *promptextra AND int flags) +{ + fprintf(stderr, "Enter %ssecret pass phrase: ", promptextra); + if (!opiereadpass(secret, OPIE_SECRET_MAX, 0)) { + fprintf(stderr, "Error reading %ssecret pass phrase!\n", promptextra); + exit(1); + } + if (secret[0] && (flags & 1)) { + char verify[OPIE_SECRET_MAX + 1]; + + fprintf(stderr, "Again %ssecret pass phrase: ", promptextra); + if (!opiereadpass(verify, OPIE_SECRET_MAX, 0)) { + fprintf(stderr, "Error reading %ssecret pass phrase!\n", promptextra); + memset(verify, 0, sizeof(verify)); + memset(secret, 0, sizeof(secret)); + exit(1); + } + if (verify[0] && strcmp(verify, secret)) { + fprintf(stderr, "They don't match. Try again.\n"); + memset(verify, 0, sizeof(verify)); + memset(secret, 0, sizeof(secret)); + exit(1); + } + memset(verify, 0, sizeof(verify)); + } + if (!(flags & 2) && opiepasscheck(secret)) { + memset(secret, 0, sizeof(secret)); + fprintf(stderr, "Secret pass phrases must be between %d and %d characters long.\n", OPIE_SECRET_MIN, OPIE_SECRET_MAX); + exit(1); + }; +} + +int main FUNCTION((argc, argv), int argc AND char *argv[]) +{ + /* variable declarations */ + unsigned algorithm = MDX; /* default algorithm per Makefile's MDX + symbol */ + int keynum = 0; + int i; + int count = 1; + char secret[OPIE_SECRET_MAX + 1], newsecret[OPIE_SECRET_MAX + 1]; + char key[8], newkey[8]; + char cko[8], ckn[8], ckxor[8], cv[8]; + char *seed, newseed[OPIE_SEED_MAX + 1]; + char response[OPIE_RESPONSE_MAX + 1]; + char *slash; + int hex = 0; + int type = RESPONSE_STANDARD; + int force; + + if (slash = strchr(argv[0], '/')) + slash++; + else + slash = argv[0]; + + if (!strcmp(slash, "key") || strstr(slash, "md4")) + algorithm = 4; + + if (strstr(slash, "md5")) + algorithm = 5; + + if (strstr(slash, "sha")) + algorithm = 3; + + while ((i = getopt(argc, argv, "fhvn:x45at:s")) != EOF) { + switch (i) { + case 'v': + opieversion(); + + case 'n': + count = atoi(optarg); + break; + + case 'x': + hex = 1; + break; + + case 'f': +#if INSECURE_OVERRIDE + force = 1; +#else /* INSECURE_OVERRIDE */ + fprintf(stderr, "Sorry, but the -f option is not supported by this build of OPIE.\n"); +#endif /* INSECURE_OVERRIDE */ + break; + + case '4': + /* use MD4 algorithm */ + algorithm = 4; + break; + + case '5': + /* use MD5 algorithm */ + algorithm = 5; + break; + + case 'a': + aflag = 1; + break; + + case 't': + { + struct _rtrans *r; + for (r = rtrans; r->name && strcmp(r->name, optarg); r++); + if (!r->name) { + fprintf(stderr, "%s: %s: unknown response type.\n", argv[0], optarg); + exit(1); + } + type = r->type; + } + break; + + case 's': + algorithm = 3; + break; + + default: + usage(argv[0]); + } + } + + if ((argc - optind) < 2) + usage(argv[0]); + + fprintf(stderr, "Using the %s algorithm to compute response.\n", algnames[algorithm]); + + /* get sequence number, which is next-to-last parameter */ + keynum = atoi(argv[optind]); + if (keynum < 1) { + fprintf(stderr, "Sequence number %s is not positive.\n", argv[optind]); + exit(1); + } + /* get seed string, which is last parameter */ + seed = argv[optind + 1]; + { + i = strlen(seed); + + if (i > OPIE_SEED_MAX) { + fprintf(stderr, "Seeds must be less than %d characters long.\n", OPIE_SEED_MAX); + exit(1); + } + if (i < OPIE_SEED_MIN) { + fprintf(stderr, "Seeds must be greater than %d characters long.\n", OPIE_SEED_MIN); + exit(1); + } + } + + fprintf(stderr, "Reminder: Don't use opiekey from telnet or dial-in sessions.\n"); + + if (opieinsecure()) { + fprintf(stderr, "Sorry, but you don't seem to be on the console or a secure terminal.\n"); +#if INSECURE_OVERRIDE + if (force) + fprintf(stderr, "Warning: Continuing could disclose your secret pass phrase to an attacker!\n"); + else +#endif /* INSECURE_OVERRIDE */ + exit(1); + } + + if ((type == RESPONSE_INIT) || (type == RESPONSE_INIT_WORD)) { +#if RETYPE + getsecret(secret, "old ", 1); +#else /* RETYPE */ + getsecret(secret, "old ", 0); +#endif /* RETYPE */ + getsecret(newsecret, "new ", 1); + if (!newsecret[0]) + strcpy(newsecret, secret); + + if (opienewseed(strcpy(newseed, seed)) < 0) { + fprintf(stderr, "Error updating seed.\n"); + goto error; + } + + if (opiekeycrunch(algorithm, newkey, newseed, newsecret)) { + fprintf(stderr, "%s: key crunch failed (1)\n", argv[0]); + goto error; + } + + for (i = 0; i < 499; i++) + opiehash(newkey, algorithm); + + if (opiekeycrunch(algorithm | 0x10, cko, seed, secret)) { + fprintf(stderr, "%s: key crunch failed (2)\n", argv[0]); + goto error; + } + + if (opiekeycrunch(algorithm | 0x10, ckn, newseed, newsecret)) { + fprintf(stderr, "%s: key crunch failed (3)\n", argv[0]); + goto error; + } + + for (i = 0; i < 8; i++) + ckxor[i] = cko[i] ^ ckn[i]; + } else +#if RETYPE + getsecret(secret, "", 1); +#else /* RETYPE */ + getsecret(secret, "", 0); +#endif /* RETYPE */ + + /* Crunch seed and secret password into starting key normally */ + if (opiekeycrunch(algorithm, key, seed, secret)) { + fprintf(stderr, "%s: key crunch failed\n", argv[0]); + goto error; + } + + for (i = 0; i <= (keynum - count); i++) + opiehash(key, algorithm); + + { + char buf[OPIE_SEED_MAX + 48 + 1]; + char *c; + + for (; i <= keynum; i++) { + if (count > 1) + printf("%d: %s", i, (type == RESPONSE_STANDARD) ? "" : "\n"); + + switch(type) { + case RESPONSE_STANDARD: + if (hex) + opiebtoh(response, key); + else + opiebtoe(response, key); + break; + case RESPONSE_WORD: + strcpy(response, "word:"); + strcat(response, opiebtoe(buf, key)); + break; + case RESPONSE_HEX: + strcpy(response, "hex:"); + strcat(response, opiebtoh(buf, key)); + break; + case RESPONSE_INIT: + case RESPONSE_INIT_WORD: + if (type == RESPONSE_INIT) { + strcpy(response, "init:"); + strcat(response, opiebtoh(buf, key)); + sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed); + strcat(response, buf); + strcat(response, opiebtoh(buf, newkey)); + strcat(response, ":"); + strcat(response, opiebtoh(buf, ckxor)); + strcat(response, ":"); + } else { + strcpy(response, "init-word:"); + strcat(response, opiebtoe(buf, key)); + sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed); + strcat(response, buf); + strcat(response, opiebtoe(buf, newkey)); + strcat(response, ":"); + strcat(response, opiebtoe(buf, ckxor)); + strcat(response, ":"); + } + + c = buf; + memcpy(c, cko, sizeof(cko)); c += sizeof(cko); + memcpy(c, key, sizeof(key)); c += sizeof(key); +#ifdef HAVE_ANSISPRINTF + c += sprintf(c, "%s 499 %s", algids[algorithm], newseed); +#else /* HAVE_ANSISPRINTF */ + sprintf(c, "%s 499 %s", algids[algorithm], newseed); + while(*c) c++; +#endif /* HAVE_ANSISPRINTF */ + memcpy(c, newkey, sizeof(newkey)); c += sizeof(newkey); + memcpy(c, ckxor, sizeof(ckxor)); c += sizeof(ckxor); + memcpy(c, cko, sizeof(cko)); c += sizeof(cko); + opiehashlen(algorithm, buf, cv, (unsigned int)c - (unsigned int)buf); + + strcat(response, (type == RESPONSE_INIT) ? opiebtoh(buf, cv) : opiebtoe(buf, cv)); + break; + } + puts(response); + opiehash(key, algorithm); + } + } + + memset(secret, 0, sizeof(secret)); + memset(newsecret, 0, sizeof(newsecret)); + return 0; + +error: + memset(secret, 0, sizeof(secret)); + memset(newsecret, 0, sizeof(newsecret)); + return 1; +} |