- /* Hash the username if possible */
- up = malloc(SHA_DIGEST_LENGTH);
- if (up != NULL) {
- struct stat sb;
- time_t t;
- int fd;
-
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, username, strlen(username));
- SHA1_End(&ctx, up);
-
- /* 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 */
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, secret, secretlen);
- SHA1_Update(&ctx, username, strlen(username));
- SHA1_End(&ctx, up);
-
- /* Zero out */
- memset(secret, 0, secretlen);
-
- /* Now hash the hash */
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, up, strlen(up));
- SHA1_End(&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, SHA_DIGEST_LENGTH); /* SHA1 specific */
- free(up);
-
- (void)snprintf(skeyprompt, sizeof 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';