/* * opie_keyinfo() * * Returns the current sequence number and * seed for the passed user. * */ char * opie_keyinfo(char *username) { int i; static char str[OPIE_CHALLENGE_MAX]; struct opie opie; i = opiechallenge(&opie, username, str); if (i == -1) return(0); return(str); }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { struct opie opie; struct options options; struct passwd *pwd; int retval, i; char *(promptstr[]) = { "%s\nPassword: "******"%s\nPassword [echo on]: "}; char challenge[OPIE_CHALLENGE_MAX]; char prompt[OPIE_CHALLENGE_MAX+22]; char resp[OPIE_SECRET_MAX]; const char *user; const char *response; pam_std_option(&options, other_options, argc, argv); PAM_LOG("Options processed"); /* * It doesn't make sense to use a password that has already been * typed in, since we haven't presented the challenge to the user * yet. */ if (pam_test_option(&options, PAM_OPT_USE_FIRST_PASS, NULL) || pam_test_option(&options, PAM_OPT_TRY_FIRST_PASS, NULL)) PAM_RETURN(PAM_AUTH_ERR); user = NULL; if (pam_test_option(&options, PAM_OPT_AUTH_AS_SELF, NULL)) { pwd = getpwnam(getlogin()); user = pwd->pw_name; } else { retval = pam_get_user(pamh, (const char **)&user, NULL); if (retval != PAM_SUCCESS) PAM_RETURN(retval); } PAM_LOG("Got user: %s", user); /* * Don't call the OPIE atexit() handler when our program exits, * since the module has been unloaded and we will SEGV. */ opiedisableaeh(); opiechallenge(&opie, (char *)user, challenge); for (i = 0; i < 2; i++) { snprintf(prompt, sizeof prompt, promptstr[i], challenge); retval = pam_get_pass(pamh, &response, prompt, &options); if (retval != PAM_SUCCESS) { opieunlock(); PAM_RETURN(retval); } PAM_LOG("Completed challenge %d: %s", i, response); if (response[0] != '\0') break; /* Second time round, echo the password */ pam_set_option(&options, PAM_OPT_ECHO_PASS); } /* We have to copy the response, because opieverify mucks with it. */ snprintf(resp, sizeof resp, "%s", response); /* * Opieverify is supposed to return -1 only if an error occurs. * But it returns -1 even if the response string isn't in the form * it expects. Thus we can't log an error and can only check for * success or lack thereof. */ PAM_RETURN(opieverify(&opie, resp) == 0 ? PAM_SUCCESS : PAM_AUTH_ERR); }