diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 1998-07-03 01:08:15 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 1998-07-03 01:08:15 +0000 |
commit | eb14320b843965f63578cfd5f231b6c092a80a12 (patch) | |
tree | 5d995e6d2eed3816b8b260482e0b718f82e8a874 /lib/libskey | |
parent | c580e820ed3cfd1f50916076bb218f8ae8a84786 (diff) |
Remove user existance disclosure through "s/key" challenges.
Diffstat (limited to 'lib/libskey')
-rw-r--r-- | lib/libskey/skey.h | 5 | ||||
-rw-r--r-- | lib/libskey/skeylogin.c | 131 | ||||
-rw-r--r-- | lib/libskey/skeysubr.c | 4 |
3 files changed, 116 insertions, 24 deletions
diff --git a/lib/libskey/skey.h b/lib/libskey/skey.h index c7d2b069bf1..e074d8c9329 100644 --- a/lib/libskey/skey.h +++ b/lib/libskey/skey.h @@ -12,7 +12,7 @@ * * Main client header * - * $OpenBSD: skey.h,v 1.10 1997/07/27 21:36:05 millert Exp $ + * $OpenBSD: skey.h,v 1.11 1998/07/03 01:08:11 angelos Exp $ */ /* Server-side data structure for reading keys file during login */ @@ -64,6 +64,9 @@ struct mc { /* Size of a binary key (not NULL-terminated) */ #define SKEY_BINKEY_SIZE 8 +/* Location of random file for bogus challenges */ +#define _SKEY_RAND_FILE_PATH_ "/etc/skey.random" + /* Prototypes */ void f __P((char *x)); int keycrunch __P((char *result, char *seed, char *passwd)); diff --git a/lib/libskey/skeylogin.c b/lib/libskey/skeylogin.c index efaebd692bf..e718d370425 100644 --- a/lib/libskey/skeylogin.c +++ b/lib/libskey/skeylogin.c @@ -8,10 +8,11 @@ * * Modifications: * Todd C. Miller <Todd.Miller@courtesan.com> + * Angelos D. Keromytis <adk@adk.gr> * * S/KEY verification check, lookups, and authentication. * - * $OpenBSD: skeylogin.c,v 1.23 1998/02/24 20:52:48 millert Exp $ + * $OpenBSD: skeylogin.c,v 1.24 1998/07/03 01:08:13 angelos Exp $ */ #include <sys/param.h> @@ -34,6 +35,7 @@ #include <string.h> #include <time.h> #include <unistd.h> +#include <sha1.h> #include "skey.h" @@ -395,6 +397,30 @@ skey_passcheck(username, passwd) return(-1); } +#define ROUND(x) (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \ + ((x)[3])) + +/* + * hash_collapse() + */ +static u_int32_t +hash_collapse(s) + u_char *s; +{ + int len, target; + u_int32_t i; + + if ((strlen(s) % sizeof(u_int32_t)) == 0) + target = strlen(s); /* Multiple of 4 */ + else + target = strlen(s) - (strlen(s) % sizeof(u_int32_t)); + + for (i = 0, len = 0; len < target; len += 4) + i ^= ROUND(s + len); + + return i; +} + /* * skey_authenticate() * @@ -408,10 +434,13 @@ int skey_authenticate(username) char *username; { - int i; + int i, fd, ptr; + u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up; char pbuf[SKEY_MAX_PW_LEN+1], skeyprompt[SKEY_MAX_CHALLENGE+1]; struct skey skey; - + struct stat sb; + SHA1_CTX ctx; + /* Attempt an S/Key challenge */ i = skeychallenge(&skey, username, skeyprompt); @@ -434,24 +463,84 @@ skey_authenticate(username) p = &pbuf[4]; *p = '\0'; - /* Base last 8 chars of seed on username */ - u = username; - i = 8; - do { - if (*u == 0) { - /* Pad remainder with zeros */ - while (--i >= 0) - *p++ = '0'; - break; - } - - *p++ = (*u++ % 10) + '0'; - } while (--i != 0); - pbuf[12] = '\0'; - - (void)sprintf(skeyprompt, "otp-%.*s %d %.*s", - SKEY_MAX_HASHNAME_LEN, skey_get_algorithm(), - 99, SKEY_MAX_SEED_LEN, pbuf); + /* See if the random file's there */ + if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1) { + if ((fstat(fd, &sb) != -1) && + ((up = SHA1Data(username, strlen(username), NULL)) + != NULL)) { + /* Collapse the hash */ + ptr = hash_collapse(up); + + if ((lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN), SEEK_SET) != -1) && (read(fd, hseed, SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN)) { + memset(up, 0, strlen(up)); + + /* Hash secret value with username */ + SHA1Init(&ctx); + SHA1Update(&ctx, hseed, + SKEY_MAX_SEED_LEN); + SHA1Update(&ctx, username, + strlen(username)); + SHA1Final(up, &ctx); + + /* Zero out */ + memset(hseed, 0, SKEY_MAX_SEED_LEN); + + /* Now hash the hash */ + SHA1Init(&ctx); + SHA1Update(&ctx, up, strlen(up)); + SHA1Final(up, &ctx); + + ptr = hash_collapse(up + 4); + + for (i = 0; + i < SKEY_MAX_SEED_LEN; + i++) { + p[i] = (ptr % 10) + '0'; + ptr /= 10; + } + + /* Sequence number */ + ptr = ((up[2] + up[3]) % 99) + 1; + + memset(up, 0, 20); /* SHA1 specific */ + free(up); + flg = 0; + + (void)sprintf(skeyprompt, + "otp-%.*s %d %.*s", + SKEY_MAX_HASHNAME_LEN, + skey_get_algorithm(), + ptr, SKEY_MAX_SEED_LEN, + pbuf); + /* Done */ + } else + free(up); + } + + close(fd); + } + + if (flg) + { + /* Base last 8 chars of seed on username */ + u = username; + i = 8; + do { + if (*u == 0) { + /* Pad remainder with zeros */ + while (--i >= 0) + *p++ = '0'; + break; + } + + *p++ = (*u++ % 10) + '0'; + } while (--i != 0); + pbuf[12] = '\0'; + + (void)sprintf(skeyprompt, "otp-%.*s %d %.*s", + SKEY_MAX_HASHNAME_LEN, skey_get_algorithm(), + 99, SKEY_MAX_SEED_LEN, pbuf); + } } (void)fprintf(stderr, "%s\n", skeyprompt); diff --git a/lib/libskey/skeysubr.c b/lib/libskey/skeysubr.c index e6ac43e4f16..f0edcbde477 100644 --- a/lib/libskey/skeysubr.c +++ b/lib/libskey/skeysubr.c @@ -11,7 +11,7 @@ * * S/KEY misc routines. * - * $OpenBSD: skeysubr.c,v 1.17 1997/07/27 21:36:06 millert Exp $ + * $OpenBSD: skeysubr.c,v 1.18 1998/07/03 01:08:14 angelos Exp $ */ #include <stdio.h> @@ -448,7 +448,7 @@ skipspace(cp) return(cp); } -/* Remove backspaced over charaters from the string */ +/* Remove backspaced over characters from the string */ void backspace(buf) char *buf; |