X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=plugins%2Fsudoers%2Fauth%2Fpam.c;h=357781ab7c53d2fc1f84dee909ffd4d8ae4c19bd;hb=e8db7f6eea9b35527ddd4532affabd18a30549b5;hp=0ede540880dfe909dcaf1d858fc5b6c049255907;hpb=98b9fd63cd28a3636a7cd24641b8f497eaadcd50;p=debian%2Fsudo diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index 0ede540..357781a 100644 --- a/plugins/sudoers/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007-2011 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2013 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -21,7 +21,6 @@ #include #include -#include #include #ifdef STDC_HEADERS # include @@ -57,6 +56,11 @@ # endif #endif +/* We don't want to translate the strings in the calls to dgt(). */ +#ifdef PAM_TEXT_DOMAIN +# define dgt(d, t) dgettext(d, t) +#endif + #include "sudoers.h" #include "sudo_auth.h" @@ -68,15 +72,16 @@ # define PAM_CONST #endif -static int converse(int, PAM_CONST struct pam_message **, - struct pam_response **, void *); -static char *def_prompt = "Password:"; -static int getpass_error; - #ifndef PAM_DATA_SILENT #define PAM_DATA_SILENT 0 #endif +static int converse(int, PAM_CONST struct pam_message **, + struct pam_response **, void *); +static char *def_prompt = "Password:"; +static bool sudo_pam_cred_established; +static bool sudo_pam_authenticated; +static int getpass_error; static pam_handle_t *pamh; int @@ -97,7 +102,7 @@ sudo_pam_init(struct passwd *pw, sudo_auth *auth) #endif pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh); if (pam_status != PAM_SUCCESS) { - log_error(USE_ERRNO|NO_MAIL, _("unable to initialize PAM")); + log_warning(USE_ERRNO|NO_MAIL, N_("unable to initialize PAM")); debug_return_int(AUTH_FATAL); } @@ -139,28 +144,31 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth) *pam_status = pam_acct_mgmt(pamh, PAM_SILENT); switch (*pam_status) { case PAM_SUCCESS: + sudo_pam_authenticated = true; debug_return_int(AUTH_SUCCESS); case PAM_AUTH_ERR: - log_error(NO_MAIL, _("account validation failure, " + log_warning(NO_MAIL, N_("account validation failure, " "is your account locked?")); debug_return_int(AUTH_FATAL); case PAM_NEW_AUTHTOK_REQD: - log_error(NO_MAIL, _("Account or password is " + log_warning(NO_MAIL, 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))) - log_error(NO_MAIL, _("pam_chauthtok: %s"), s); + if ((s = pam_strerror(pamh, *pam_status)) != NULL) { + log_warning(NO_MAIL, + N_("unable to change expired password: %s"), s); + } debug_return_int(AUTH_FAILURE); case PAM_AUTHTOK_EXPIRED: - log_error(NO_MAIL, - _("Password expired, contact your system administrator")); + log_warning(NO_MAIL, + N_("Password expired, contact your system administrator")); debug_return_int(AUTH_FATAL); case PAM_ACCT_EXPIRED: - log_error(NO_MAIL, - _("Account expired or PAM config lacks an \"account\" " + log_warning(NO_MAIL, + N_("Account expired or PAM config lacks an \"account\" " "section for sudo, contact your system administrator")); debug_return_int(AUTH_FATAL); } @@ -176,8 +184,8 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth) case PAM_PERM_DENIED: debug_return_int(AUTH_FAILURE); default: - if ((s = pam_strerror(pamh, *pam_status))) - log_error(NO_MAIL, _("pam_authenticate: %s"), s); + if ((s = pam_strerror(pamh, *pam_status)) != NULL) + log_warning(NO_MAIL, N_("PAM authentication error: %s"), s); debug_return_int(AUTH_FATAL); } } @@ -230,7 +238,15 @@ sudo_pam_begin_session(struct passwd *pw, char **user_envp[], sudo_auth *auth) * this is not set and so pam_setcred() returns PAM_PERM_DENIED. * We can't call pam_acct_mgmt() with Linux-PAM for a similar reason. */ - (void) pam_setcred(pamh, PAM_ESTABLISH_CRED); + status = pam_setcred(pamh, PAM_ESTABLISH_CRED); + if (status == PAM_SUCCESS) { + sudo_pam_cred_established = true; + } else if (sudo_pam_authenticated) { + const char *s = pam_strerror(pamh, status); + if (s != NULL) + log_warning(NO_MAIL, N_("unable to establish credentials: %s"), s); + goto done; + } #ifdef HAVE_PAM_GETENVLIST /* @@ -252,13 +268,13 @@ sudo_pam_begin_session(struct passwd *pw, char **user_envp[], sudo_auth *auth) } #endif /* HAVE_PAM_GETENVLIST */ -#ifndef NO_PAM_SESSION - status = pam_open_session(pamh, 0); - if (status != PAM_SUCCESS) { - (void) pam_end(pamh, status | PAM_DATA_SILENT); - pamh = NULL; + if (def_pam_session) { + status = pam_open_session(pamh, 0); + if (status != PAM_SUCCESS) { + (void) pam_end(pamh, status | PAM_DATA_SILENT); + pamh = NULL; + } } -#endif done: debug_return_int(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE); @@ -277,10 +293,10 @@ sudo_pam_end_session(struct passwd *pw, sudo_auth *auth) * XXX - still needed now that session init is in parent? */ (void) pam_set_item(pamh, PAM_USER, pw->pw_name); -#ifndef NO_PAM_SESSION - (void) pam_close_session(pamh, PAM_SILENT); -#endif - (void) pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); + if (def_pam_session) + (void) pam_close_session(pamh, PAM_SILENT); + if (sudo_pam_cred_established) + (void) pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT); pamh = NULL; } @@ -321,7 +337,7 @@ converse(int num_msg, PAM_CONST struct pam_message **msg, if (getpass_error) goto done; - /* Is the sudo prompt standard? (If so, we'l just use PAM's) */ + /* Is the sudo prompt standard? (If so, we'll just use PAM's) */ std_prompt = strncmp(def_prompt, "Password:", 9) == 0 && (def_prompt[9] == '\0' || (def_prompt[9] == ' ' && def_prompt[10] == '\0')); @@ -329,8 +345,8 @@ converse(int num_msg, PAM_CONST struct pam_message **msg, /* Only override PAM prompt if it matches /^Password: ?/ */ #if defined(PAM_TEXT_DOMAIN) && defined(HAVE_LIBINTL_H) if (!def_passprompt_override && (std_prompt || - (strcmp(pm->msg, dgettext(PAM_TEXT_DOMAIN, "Password: ")) && - strcmp(pm->msg, dgettext(PAM_TEXT_DOMAIN, "Password:"))))) + (strcmp(pm->msg, dgt(PAM_TEXT_DOMAIN, "Password: ")) && + strcmp(pm->msg, dgt(PAM_TEXT_DOMAIN, "Password:"))))) prompt = pm->msg; #else if (!def_passprompt_override && (std_prompt ||