diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2000-11-20 23:46:40 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2000-11-20 23:46:40 +0000 |
commit | da7ed5d122ce6e53ba6035162f80e4b3ea06db7c (patch) | |
tree | 06e3a40b9d6c486f35afeac33dfbf4c2bf41419c /lib | |
parent | 8d4f850ec5a02411225f9f0fb990b6e8665ddf8e (diff) |
Move fake prompt generation from skey_authenticate() to skeychallenge()
and getskeyprompt(). This means that when you get a challenge the
result parameter is always filled in, even if the use is not in the
skeykeys file.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libskey/skeylogin.c | 271 |
1 files changed, 142 insertions, 129 deletions
diff --git a/lib/libskey/skeylogin.c b/lib/libskey/skeylogin.c index 08cf3801e3c..24215079d3c 100644 --- a/lib/libskey/skeylogin.c +++ b/lib/libskey/skeylogin.c @@ -12,7 +12,7 @@ * * S/KEY verification check, lookups, and authentication. * - * $OpenBSD: skeylogin.c,v 1.35 2000/06/23 17:29:41 markus Exp $ + * $OpenBSD: skeylogin.c,v 1.36 2000/11/20 23:46:39 millert Exp $ */ #include <sys/param.h> @@ -38,8 +38,7 @@ #include "skey.h" -char *skipspace __P((char *)); -int skeylookup __P((struct skey *, char *)); +static void skey_fakeprompt __P((char *, char *)); /* Issue a skey challenge for user 'name'. If successful, * fill in the caller's skey structure and return(0). If unsuccessful @@ -58,21 +57,23 @@ getskeyprompt(mp, name, prompt) sevenbit(name); rval = skeylookup(mp, name); - (void)strcpy(prompt, "otp-md0 55 latour1\n"); switch (rval) { - case -1: /* File error */ - return(-1); case 0: /* Lookup succeeded, return challenge */ (void)sprintf(prompt, "otp-%.*s %d %.*s\n", SKEY_MAX_HASHNAME_LEN, skey_get_algorithm(), mp->n - 1, SKEY_MAX_SEED_LEN, mp->seed); return(0); + case 1: /* User not found */ (void)fclose(mp->keyfile); mp->keyfile = NULL; + /* FALLTHROUGH */ + + default: /* File error */ + skey_fakeprompt(name, prompt); + strcat(prompt, "\n"); return(-1); } - return(-1); /* Can't happen */ } /* Return a skey challenge string for user 'name'. If successful, @@ -90,21 +91,23 @@ skeychallenge(mp, name, ss) { int rval; - rval = skeylookup(mp,name); - switch(rval){ - case -1: /* File error */ - return(-1); - case 0: /* Lookup succeeded, issue challenge */ + rval = skeylookup(mp, name); + switch (rval) { + case 0: /* Lookup succeeded, return challenge */ (void)sprintf(ss, "otp-%.*s %d %.*s", SKEY_MAX_HASHNAME_LEN, skey_get_algorithm(), mp->n - 1, SKEY_MAX_SEED_LEN, mp->seed); return(0); + case 1: /* User not found */ (void)fclose(mp->keyfile); mp->keyfile = NULL; + /* FALLTHROUGH */ + + default: /* File error */ + skey_fakeprompt(name, ss); return(-1); } - return(-1); /* Can't happen */ } /* Find an entry in the One-time Password database. @@ -439,140 +442,149 @@ hash_collapse(s) } /* - * skey_authenticate() + * skey_fakeprompt() * - * Used when calling program will allow input of the user's - * response to the challenge. - * - * Returns: 0 success, -1 failure + * Generate a fake prompt for the specified user. * */ -int -skey_authenticate(username) +static void +skey_fakeprompt(username, skeyprompt) char *username; + char *skeyprompt; { int i; u_int ptr; u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up; - char pbuf[SKEY_MAX_PW_LEN+1], skeyprompt[SKEY_MAX_CHALLENGE+1]; - char *secret; + char *secret, pbuf[SKEY_MAX_PW_LEN+1]; + char *p, *u; size_t secretlen; - struct skey skey; SHA1_CTX ctx; - - /* Attempt an S/Key challenge */ - i = skeychallenge(&skey, username, skeyprompt); - /* Cons up a fake prompt if no entry in keys file */ - if (i != 0) { - char *p, *u; - - /* - * Base first 4 chars of seed on hostname. - * Add some filler for short hostnames if necessary. - */ - if (gethostname(pbuf, sizeof(pbuf)) == -1) - *(p = pbuf) = '.'; - else - for (p = pbuf; *p && isalnum(*p); p++) - if (isalpha(*p) && isupper(*p)) - *p = tolower(*p); - if (*p && pbuf - p < 4) - (void)strncpy(p, "asjd", 4 - (pbuf - p)); - pbuf[4] = '\0'; - - /* Hash the username if possible */ - if ((up = SHA1Data(username, strlen(username), NULL)) != NULL) { - struct stat sb; - time_t t; - int fd; - - /* Collapse the hash */ - ptr = hash_collapse(up); - memset(up, 0, strlen(up)); - - /* See if the random file's there, else use ctime */ - if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1 - && fstat(fd, &sb) == 0 && - sb.st_size > (off_t)SKEY_MAX_SEED_LEN && - lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN), - SEEK_SET) != -1 && read(fd, hseed, - SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) { - close(fd); - fd = -1; - secret = hseed; - secretlen = SKEY_MAX_SEED_LEN; - flg = 0; - } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) { - t = sb.st_ctime; - secret = ctime(&t); - secretlen = strlen(secret); - flg = 0; - } - if (fd != -1) - close(fd); + /* + * Base first 4 chars of seed on hostname. + * Add some filler for short hostnames if necessary. + */ + if (gethostname(pbuf, sizeof(pbuf)) == -1) + *(p = pbuf) = '.'; + else + for (p = pbuf; *p && isalnum(*p); p++) + if (isalpha(*p) && isupper(*p)) + *p = tolower(*p); + if (*p && pbuf - p < 4) + (void)strncpy(p, "asjd", 4 - (pbuf - p)); + pbuf[4] = '\0'; + + /* Hash the username if possible */ + if ((up = SHA1Data(username, strlen(username), NULL)) != NULL) { + struct stat sb; + time_t t; + int fd; + + /* Collapse the hash */ + ptr = hash_collapse(up); + memset(up, 0, strlen(up)); + + /* See if the random file's there, else use ctime */ + if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1 + && fstat(fd, &sb) == 0 && + sb.st_size > (off_t)SKEY_MAX_SEED_LEN && + lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN), + SEEK_SET) != -1 && read(fd, hseed, + SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) { + close(fd); + fd = -1; + secret = hseed; + secretlen = SKEY_MAX_SEED_LEN; + flg = 0; + } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) { + t = sb.st_ctime; + secret = ctime(&t); + secretlen = strlen(secret); + flg = 0; } + if (fd != -1) + close(fd); + } - /* Put that in your pipe and smoke it */ - if (flg == 0) { - /* Hash secret value with username */ - SHA1Init(&ctx); - SHA1Update(&ctx, secret, secretlen); - SHA1Update(&ctx, username, strlen(username)); - SHA1End(&ctx, up); - - /* Zero out */ - memset(secret, 0, secretlen); - - /* Now hash the hash */ - SHA1Init(&ctx); - SHA1Update(&ctx, up, strlen(up)); - SHA1End(&ctx, up); - - ptr = hash_collapse(up + 4); - - for (i = 4; i < 9; i++) { - pbuf[i] = (ptr % 10) + '0'; - ptr /= 10; - } - pbuf[i] = '\0'; + /* Put that in your pipe and smoke it */ + if (flg == 0) { + /* Hash secret value with username */ + SHA1Init(&ctx); + SHA1Update(&ctx, secret, secretlen); + SHA1Update(&ctx, username, strlen(username)); + SHA1End(&ctx, up); + + /* Zero out */ + memset(secret, 0, secretlen); + + /* Now hash the hash */ + SHA1Init(&ctx); + SHA1Update(&ctx, up, strlen(up)); + SHA1End(&ctx, up); + + ptr = hash_collapse(up + 4); + + for (i = 4; i < 9; i++) { + pbuf[i] = (ptr % 10) + '0'; + ptr /= 10; + } + pbuf[i] = '\0'; - /* Sequence number */ - ptr = ((up[2] + up[3]) % 99) + 1; + /* Sequence number */ + ptr = ((up[2] + up[3]) % 99) + 1; - memset(up, 0, 20); /* SHA1 specific */ - free(up); + memset(up, 0, 20); /* SHA1 specific */ + free(up); - (void)sprintf(skeyprompt, - "otp-%.*s %d %.*s", - SKEY_MAX_HASHNAME_LEN, - skey_get_algorithm(), - ptr, SKEY_MAX_SEED_LEN, - pbuf); - } else { - /* Base last 8 chars of seed on username */ - u = username; - i = 8; - p = &pbuf[4]; - 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)sprintf(skeyprompt, + "otp-%.*s %d %.*s", + SKEY_MAX_HASHNAME_LEN, + skey_get_algorithm(), + ptr, SKEY_MAX_SEED_LEN, + pbuf); + } else { + /* Base last 8 chars of seed on username */ + u = username; + i = 8; + p = &pbuf[4]; + 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); } +} +/* + * skey_authenticate() + * + * Used when calling program will allow input of the user's + * response to the challenge. + * + * Returns: 0 success, -1 failure + * + */ +int +skey_authenticate(username) + char *username; +{ + int i; + char pbuf[SKEY_MAX_PW_LEN+1], skeyprompt[SKEY_MAX_CHALLENGE+1]; + struct skey skey; + + /* Get the S/Key challenge (may be fake) */ + i = skeychallenge(&skey, username, skeyprompt); (void)fprintf(stderr, "%s\n", skeyprompt); (void)fflush(stderr); @@ -598,6 +610,7 @@ skey_authenticate(username) * 0: Database updated * * The database file is always closed by this call. + * */ int skeyzero(mp, response) |