int main(int argc, char **argv) { struct passwd *pw; struct skey key; char *name = NULL; int error, ch, verbose = 0; if (pledge("stdio rpath wpath flock getpw", NULL) == -1) err(1, "pledge"); while ((ch = getopt(argc, argv, "v")) != -1) switch(ch) { case 'v': verbose = 1; break; default: usage(); } argc -= optind; argv += optind; if (argc == 1) name = argv[0]; else if (argc > 1) usage(); if (name && getuid() != 0) errx(1, "only root may specify an alternate user"); if (name) { if ((pw = getpwnam(name)) == NULL) errx(1, "no passwd entry for %s", name); } else { if ((pw = getpwuid(getuid())) == NULL) errx(1, "no passwd entry for uid %u", getuid()); } if ((name = strdup(pw->pw_name)) == NULL) err(1, "cannot allocate memory"); sevenbit(name); error = skeylookup(&key, name); switch (error) { case 0: /* Success! */ if (verbose) (void)printf("otp-%s ", skey_get_algorithm()); (void)printf("%d %s\n", key.n - 1, key.seed); break; case -1: /* File error */ err(1, "cannot open %s/%s", _PATH_SKEYDIR, name); break; case 1: /* Unknown user */ errx(1, "%s is not listed in %s", name, _PATH_SKEYDIR); break; } (void)fclose(key.keyfile); exit(error ? 1 : 0); }
/* * 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(char *username) { char pbuf[SKEY_MAX_PW_LEN+1], skeyprompt[SKEY_MAX_CHALLENGE+1]; struct skey skey; int i; /* Get the S/Key challenge (may be fake) */ i = skeychallenge(&skey, username, skeyprompt); (void)fprintf(stderr, "%s\nResponse: ", skeyprompt); (void)fflush(stderr); /* Time out on user input after 2 minutes */ tgetline(fileno(stdin), pbuf, sizeof(pbuf), 120); sevenbit(pbuf); (void)rewind(stdin); /* Is it a valid response? */ if (i == 0 && skeyverify(&skey, pbuf) == 0) { if (skey.n < 5) { (void)fprintf(stderr, "\nWarning! Key initialization needed soon. (%d logins left)\n", skey.n); } return (0); } return (-1); }
/* Read in secret password (turns off echo) */ char * readpass(char *buf, int n) { void (*old_handler)(int); /* Turn off echoing */ skey_echo(0); /* Catch SIGINT and save old signal handler */ old_handler = signal(SIGINT, trapped); if (fgets(buf, n, stdin) == NULL) buf[0] = '\0'; rip(buf); (void)putc('\n', stderr); (void)fflush(stderr); /* Restore signal handler and turn echo back on */ if (old_handler != SIG_ERR) (void)signal(SIGINT, old_handler); skey_echo(1); sevenbit(buf); return(buf); }
/* Read in an s/key OTP (does not turn off echo) */ char * readskey(char *buf, int n) { if (fgets(buf, n, stdin) == NULL) buf[0] = '\0'; rip(buf); sevenbit(buf); return(buf); }
static int keycrunch_sha1(char *result, char *seed, char *passwd) { char *buf; SHA1_CTX sha; unsigned int buflen; int i, j; /* * If seed and passwd are defined we are in keycrunch() mode, * else we are in f() mode. */ if (seed && passwd) { buflen = strlen(seed) + strlen(passwd); if ((buf = malloc(buflen + 1)) == NULL) return(-1); (void)strlcpy(buf, seed, buflen + 1); lowcase(buf); (void)strlcat(buf, passwd, buflen + 1); sevenbit(buf); } else { buf = result; buflen = SKEY_BINKEY_SIZE; } /* Crunch the key through SHA1 */ SHA1Init(&sha); SHA1Update(&sha, (unsigned char *)buf, buflen); SHA1Pad(&sha); /* Fold 160 to 64 bits */ sha.state[0] ^= sha.state[2]; sha.state[1] ^= sha.state[3]; sha.state[0] ^= sha.state[4]; /* * SHA1 is a big endian algorithm but RFC2289 mandates that * the result be in little endian form, so we copy to the * result buffer manually. */ for (i = 0, j = 0; j < 8; i++, j += 4) { result[j] = (u_char)(sha.state[i] & 0xff); result[j+1] = (u_char)((sha.state[i] >> 8) & 0xff); result[j+2] = (u_char)((sha.state[i] >> 16) & 0xff); result[j+3] = (u_char)((sha.state[i] >> 24) & 0xff); } if (buf != result) (void)free(buf); return(0); }
static int keycrunch_rmd160(char *result, char *seed, char *passwd) { char *buf; RMD160_CTX rmd; u_int32_t results[5]; unsigned int buflen; /* * If seed and passwd are defined we are in keycrunch() mode, * else we are in f() mode. */ if (seed && passwd) { buflen = strlen(seed) + strlen(passwd); if ((buf = malloc(buflen + 1)) == NULL) return(-1); (void)strlcpy(buf, seed, buflen + 1); lowcase(buf); (void)strlcat(buf, passwd, buflen + 1); sevenbit(buf); } else { buf = result; buflen = SKEY_BINKEY_SIZE; } /* Crunch the key through RMD-160 */ RMD160Init(&rmd); RMD160Update(&rmd, (unsigned char *)buf, buflen); RMD160Final((unsigned char *)results, &rmd); /* Fold 160 to 64 bits */ results[0] ^= results[2]; results[1] ^= results[3]; results[0] ^= results[4]; (void)memcpy((void *)result, (void *)results, SKEY_BINKEY_SIZE); if (buf != result) (void)free(buf); return(0); }