X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/2919e0607cfa8042cea685db3f1f6a8126543305..2b87da3b1fb7c5ca907cb65aa048fada4ad29803:/auth-pam.c diff --git a/auth-pam.c b/auth-pam.c index 4b772c9c..44399ac5 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -27,7 +27,10 @@ #ifdef USE_PAM #include "ssh.h" #include "xmalloc.h" +#include "log.h" #include "servconf.h" +#include "canohost.h" +#include "readpass.h" RCSID("$Id$"); @@ -50,10 +53,26 @@ static const char *pampasswd = NULL; static char *pam_msg = NULL; /* states for pamconv() */ -typedef enum { INITIAL_LOGIN, OTHER } pamstates; -static pamstates pamstate = INITIAL_LOGIN; +enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN; /* remember whether pam_acct_mgmt() returned PAM_NEWAUTHTOK_REQD */ static int password_change_required = 0; +/* remember whether the last pam_authenticate() succeeded or not */ +static int was_authenticated = 0; + +/* accessor which allows us to switch conversation structs according to + * the authentication method being used */ +void pam_set_conv(struct pam_conv *conv) +{ + pam_set_item(pamh, PAM_CONV, conv); +} + +/* start an authentication run */ +int do_pam_authenticate(int flags) +{ + int retval = pam_authenticate(pamh, flags); + was_authenticated = (retval == PAM_SUCCESS); + return retval; +} /* * PAM conversation function. @@ -78,16 +97,16 @@ static int pamconv(int num_msg, const struct pam_message **msg, /* PAM will free this later */ reply = malloc(num_msg * sizeof(*reply)); if (reply == NULL) - return PAM_CONV_ERR; + return PAM_CONV_ERR; for (count = 0; count < num_msg; count++) { - switch ((*msg)[count].msg_style) { + switch(PAM_MSG_MEMBER(msg, count, msg_style)) { case PAM_PROMPT_ECHO_ON: if (pamstate == INITIAL_LOGIN) { free(reply); return PAM_CONV_ERR; } else { - fputs((*msg)[count].msg, stderr); + fputs(PAM_MSG_MEMBER(msg, count, msg), stderr); fgets(buf, sizeof(buf), stdin); reply[count].resp = xstrdup(buf); reply[count].resp_retcode = PAM_SUCCESS; @@ -101,8 +120,8 @@ static int pamconv(int num_msg, const struct pam_message **msg, } reply[count].resp = xstrdup(pampasswd); } else { - reply[count].resp = - xstrdup(read_passphrase((*msg)[count].msg, 1)); + reply[count].resp = + xstrdup(read_passphrase(PAM_MSG_MEMBER(msg, count, msg), 1)); } reply[count].resp_retcode = PAM_SUCCESS; break; @@ -110,9 +129,9 @@ static int pamconv(int num_msg, const struct pam_message **msg, case PAM_TEXT_INFO: if ((*msg)[count].msg != NULL) { if (pamstate == INITIAL_LOGIN) - pam_msg_cat((*msg)[count].msg); + pam_msg_cat(PAM_MSG_MEMBER(msg, count, msg)); else { - fputs((*msg)[count].msg, stderr); + fputs(PAM_MSG_MEMBER(msg, count, msg), stderr); fputs("\n", stderr); } } @@ -139,19 +158,19 @@ void pam_cleanup_proc(void *context) { pam_retval = pam_close_session(pamh, 0); if (pam_retval != PAM_SUCCESS) { - log("Cannot close PAM session[%d]: %.200s", + log("Cannot close PAM session[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); } pam_retval = pam_setcred(pamh, PAM_DELETE_CRED); if (pam_retval != PAM_SUCCESS) { - debug("Cannot delete credentials[%d]: %.200s", + debug("Cannot delete credentials[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); } pam_retval = pam_end(pamh, pam_retval); if (pam_retval != PAM_SUCCESS) { - log("Cannot release PAM authentication[%d]: %.200s", + log("Cannot release PAM authentication[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); } } @@ -163,6 +182,8 @@ int auth_pam_password(struct passwd *pw, const char *password) extern ServerOptions options; int pam_retval; + pam_set_conv(&conv); + /* deny if no user. */ if (pw == NULL) return 0; @@ -172,15 +193,15 @@ int auth_pam_password(struct passwd *pw, const char *password) return 0; pampasswd = password; - + pamstate = INITIAL_LOGIN; - pam_retval = pam_authenticate(pamh, 0); + pam_retval = do_pam_authenticate(0); if (pam_retval == PAM_SUCCESS) { - debug("PAM Password authentication accepted for user \"%.100s\"", + debug("PAM Password authentication accepted for user \"%.100s\"", pw->pw_name); return 1; } else { - debug("PAM Password authentication for \"%.100s\" failed[%d]: %s", + debug("PAM Password authentication for \"%.100s\" failed[%d]: %s", pw->pw_name, pam_retval, PAM_STRERROR(pamh, pam_retval)); return 0; } @@ -190,12 +211,14 @@ int auth_pam_password(struct passwd *pw, const char *password) int do_pam_account(char *username, char *remote_user) { int pam_retval; - - debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname()); - pam_retval = pam_set_item(pamh, PAM_RHOST, - get_canonical_hostname()); + extern ServerOptions options; + + debug("PAM setting rhost to \"%.200s\"", + get_canonical_hostname(options.reverse_mapping_check)); + pam_retval = pam_set_item(pamh, PAM_RHOST, + get_canonical_hostname(options.reverse_mapping_check)); if (pam_retval != PAM_SUCCESS) { - fatal("PAM set rhost failed[%d]: %.200s", + fatal("PAM set rhost failed[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); } @@ -203,7 +226,7 @@ int do_pam_account(char *username, char *remote_user) debug("PAM setting ruser to \"%.200s\"", remote_user); pam_retval = pam_set_item(pamh, PAM_RUSER, remote_user); if (pam_retval != PAM_SUCCESS) { - fatal("PAM set ruser failed[%d]: %.200s", + fatal("PAM set ruser failed[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); } } @@ -219,11 +242,11 @@ int do_pam_account(char *username, char *remote_user) password_change_required = 1; break; default: - log("PAM rejected by account configuration[%d]: %.200s", + log("PAM rejected by account configuration[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); return(0); } - + return(1); } @@ -236,28 +259,33 @@ void do_pam_session(char *username, const char *ttyname) debug("PAM setting tty to \"%.200s\"", ttyname); pam_retval = pam_set_item(pamh, PAM_TTY, ttyname); if (pam_retval != PAM_SUCCESS) { - fatal("PAM set tty failed[%d]: %.200s", + fatal("PAM set tty failed[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); } } pam_retval = pam_open_session(pamh, 0); if (pam_retval != PAM_SUCCESS) { - fatal("PAM session setup failed[%d]: %.200s", + fatal("PAM session setup failed[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); } } -/* Set PAM credentials */ -void do_pam_setcred() +/* Set PAM credentials */ +void do_pam_setcred(void) { int pam_retval; - + debug("PAM establishing creds"); pam_retval = pam_setcred(pamh, PAM_ESTABLISH_CRED); if (pam_retval != PAM_SUCCESS) { - fatal("PAM setcred failed[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); + if(was_authenticated) { + fatal("PAM setcred failed[%d]: %.200s", + pam_retval, PAM_STRERROR(pamh, pam_retval)); + } else { + debug("PAM setcred failed[%d]: %.200s", + pam_retval, PAM_STRERROR(pamh, pam_retval)); + } } } @@ -267,13 +295,13 @@ int pam_password_change_required(void) return password_change_required; } -/* +/* * Have user change authentication token if pam_acct_mgmt() indicated * it was expired. This needs to be called after an interactive * session is established and the user's pty is connected to * stdin/stout/stderr. */ -void do_pam_chauthtok() +void do_pam_chauthtok(void) { int pam_retval; @@ -285,7 +313,7 @@ void do_pam_chauthtok() do { pam_retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); if (pam_retval != PAM_SUCCESS) { - log("PAM pam_chauthtok failed[%d]: %.200s", + log("PAM pam_chauthtok failed[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); } } while (pam_retval != PAM_SUCCESS); @@ -300,30 +328,30 @@ void finish_pam(void) } /* Start PAM authentication for specified account */ -void start_pam(struct passwd *pw) +void start_pam(const char *user) { int pam_retval; - debug("Starting up PAM with username \"%.200s\"", pw->pw_name); + debug("Starting up PAM with username \"%.200s\"", user); - pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv, &pamh); + pam_retval = pam_start(SSHD_PAM_SERVICE, user, &conv, &pamh); if (pam_retval != PAM_SUCCESS) { - fatal("PAM initialisation failed[%d]: %.200s", + fatal("PAM initialisation failed[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); } #ifdef PAM_TTY_KLUDGE /* * Some PAM modules (e.g. pam_time) require a TTY to operate, - * and will fail in various stupid ways if they don't get one. + * and will fail in various stupid ways if they don't get one. * sshd doesn't set the tty until too late in the auth process and may * not even need one (for tty-less connections) - * Kludge: Set a fake PAM_TTY + * Kludge: Set a fake PAM_TTY */ pam_retval = pam_set_item(pamh, PAM_TTY, "ssh"); if (pam_retval != PAM_SUCCESS) { - fatal("PAM set tty failed[%d]: %.200s", + fatal("PAM set tty failed[%d]: %.200s", pam_retval, PAM_STRERROR(pamh, pam_retval)); } #endif /* PAM_TTY_KLUDGE */ @@ -355,9 +383,9 @@ void pam_msg_cat(const char *msg) char *p; size_t new_msg_len; size_t pam_msg_len; - + new_msg_len = strlen(msg); - + if (pam_msg) { pam_msg_len = strlen(pam_msg); pam_msg = xrealloc(pam_msg, new_msg_len + pam_msg_len + 2);