summaryrefslogtreecommitdiff
path: root/lib/libskey
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>1998-07-03 01:08:15 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>1998-07-03 01:08:15 +0000
commiteb14320b843965f63578cfd5f231b6c092a80a12 (patch)
tree5d995e6d2eed3816b8b260482e0b718f82e8a874 /lib/libskey
parentc580e820ed3cfd1f50916076bb218f8ae8a84786 (diff)
Remove user existance disclosure through "s/key" challenges.
Diffstat (limited to 'lib/libskey')
-rw-r--r--lib/libskey/skey.h5
-rw-r--r--lib/libskey/skeylogin.c131
-rw-r--r--lib/libskey/skeysubr.c4
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;