# HG changeset patch # User Todd C. Miller # Date 1544201494 25200 # Node ID 656aa910fbaf0be517e012c9271c51eb85c1cca5 # Parent ef83f35c9cb090a8b4fd36942f1e47e65c285dce The fix for bug #843 was incomplete and caused pam_end() to be called early. sudo_pam_approval() must not set the global pam status to an error value if it returns AUTH_SUCCESS. Otherwise, sudo_pam_cleanup() will call pam_end() before sudo_pam_begin_session(). This resulted in a NULL PAM handle being used in sudo_pam_begin_session(). diff -r ef83f35c9cb0 -r 656aa910fbaf plugins/sudoers/auth/pam.c --- a/plugins/sudoers/auth/pam.c Wed Dec 05 10:43:14 2018 -0700 +++ b/plugins/sudoers/auth/pam.c Fri Dec 07 09:51:34 2018 -0700 @@ -210,59 +210,68 @@ sudo_pam_approval(struct passwd *pw, sudo_auth *auth, bool exempt) { const char *s; + int rc, status = AUTH_SUCCESS; int *pam_status = (int *) auth->data; debug_decl(sudo_pam_approval, SUDOERS_DEBUG_AUTH) - *pam_status = pam_acct_mgmt(pamh, PAM_SILENT); - switch (*pam_status) { + rc = pam_acct_mgmt(pamh, PAM_SILENT); + switch (rc) { case PAM_SUCCESS: - debug_return_int(AUTH_SUCCESS); + break; case PAM_AUTH_ERR: log_warningx(0, N_("account validation failure, " "is your account locked?")); - debug_return_int(AUTH_FATAL); + status = AUTH_FATAL; + break; case PAM_NEW_AUTHTOK_REQD: /* Ignore if user is exempt from password restrictions. */ if (exempt) - debug_return_int(AUTH_SUCCESS); + break; /* New password required, try to change it. */ log_warningx(0, N_("Account or password is " "expired, reset your password and try again")); - *pam_status = pam_chauthtok(pamh, - PAM_CHANGE_EXPIRED_AUTHTOK); - if (*pam_status == PAM_SUCCESS) - debug_return_int(AUTH_SUCCESS); - if ((s = pam_strerror(pamh, *pam_status)) == NULL) + rc = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); + if (rc == PAM_SUCCESS) + break; + if ((s = pam_strerror(pamh, rc)) == NULL) s = "unknown error"; log_warningx(0, N_("unable to change expired password: %s"), s); - debug_return_int(AUTH_FAILURE); + status = AUTH_FAILURE; + break; case PAM_AUTHTOK_EXPIRED: /* Ignore if user is exempt from password restrictions. */ if (exempt) - debug_return_int(AUTH_SUCCESS); + break; /* Password expired, cannot be updated by user. */ log_warningx(0, N_("Password expired, contact your system administrator")); - debug_return_int(AUTH_FATAL); + status = AUTH_FATAL; + break; case PAM_ACCT_EXPIRED: log_warningx(0, N_("Account expired or PAM config lacks an \"account\" " "section for sudo, contact your system administrator")); - debug_return_int(AUTH_FATAL); + status = AUTH_FATAL; + break; case PAM_AUTHINFO_UNAVAIL: case PAM_MAXTRIES: case PAM_PERM_DENIED: - s = pam_strerror(pamh, *pam_status); + s = pam_strerror(pamh, rc); log_warningx(0, N_("PAM account management error: %s"), s ? s : "unknown error"); - debug_return_int(AUTH_FAILURE); + status = AUTH_FAILURE; + break; default: - s = pam_strerror(pamh, *pam_status); + s = pam_strerror(pamh, rc); log_warningx(0, N_("PAM account management error: %s"), s ? s : "unknown error"); - debug_return_int(AUTH_FATAL); + status = AUTH_FATAL; + break; } + /* Ignore errors if user is exempt from password restrictions. */ + *pam_status = exempt ? PAM_SUCCESS : rc; + debug_return_int(status); } int