static const char * sha1_hash_finish(void *ctx) { static char hash[SHA1_DIGEST_STRING_LENGTH]; SHA1_CTX *hash_ctx = ctx; SHA1End(hash_ctx, hash); return hash; }
/* * skey_fakeprompt() * * Generate a fake prompt for the specified user. * */ static void skey_fakeprompt(char *username, char *skeyprompt) { char hseed[SKEY_MAX_SEED_LEN], *secret, pbuf[SKEY_MAX_PW_LEN+1], *p, *u; u_char flg = 1, *up; size_t secretlen; SHA1_CTX ctx; u_int ptr; int i; /* * 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; isalnum((unsigned char)*p); p++) if (isalpha((unsigned char)*p) && isupper((unsigned char)*p)) *p = (char)tolower((unsigned char)*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'; /* Sequence number */ ptr = ((up[2] + up[3]) % 99) + 1; memset(up, 0, 20); /* SHA1 specific */ free(up); (void)snprintf(skeyprompt, SKEY_MAX_CHALLENGE, "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)snprintf(skeyprompt, SKEY_MAX_CHALLENGE, "otp-%.*s %d %.*s", SKEY_MAX_HASHNAME_LEN, skey_get_algorithm(), 99, SKEY_MAX_SEED_LEN, pbuf); } }