/* * opie_passverify() * * Check to see if answer is the correct one to the current * challenge. * * Returns: 0 success, -1 failure * */ int opie_passverify(char *username, char *passwd) { int i; struct opie opie; i = opielookup(&opie, username); if (i == -1 || i == 1) return(-1); if (opieverify(&opie, passwd) == 0) return(opie.opie_n); return(-1); }
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); }