From: Todd C. Miller Date: Thu, 20 Jul 2017 22:06:47 +0000 (-0600) Subject: When deciding which prompt to use (PAM's or sudo's) treat the PAM X-Git-Tag: SUDO_1_8_21^2~27 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=43cbcbc24d3150d92644e4cc2729a4947d7cade8;p=sudo When deciding which prompt to use (PAM's or sudo's) treat the PAM prompt "username's Password:" as equivalent to "Password:". Some PAM modules (on AIX at least) use this prompt. --- diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index 880eaeedb..dbf18bf11 100644 --- a/plugins/sudoers/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -416,6 +416,49 @@ sudo_pam_end_session(struct passwd *pw, sudo_auth *auth) # define PAM_PROMPT_IS_PASSWORD(_p) PROMPT_IS_PASSWORD(_p) #endif /* PAM_TEXT_DOMAIN */ +/* + * We use the PAM prompt in preference to sudo's as long + * as passprompt_override is not set and: + * a) the (translated) sudo prompt matches /^Password: ?/ + * or: + * b) the PAM prompt itself *doesn't* match /^Password: ?/ + * or /^username's Password: ?/ + * + * The intent is to use the PAM prompt for things like + * challenge-response, otherwise use sudo's prompt. + * There may also be cases where a localized translation + * of "Password: " exists for PAM but not for sudo. + */ +static bool +use_pam_prompt(const char *pam_prompt) +{ + size_t user_len; + debug_decl(use_pam_prompt, SUDOERS_DEBUG_AUTH) + + if (!def_passprompt_override) { + /* If sudo prompt matches "^Password: ?$", use PAM prompt. */ + if (PROMPT_IS_PASSWORD(def_prompt)) + debug_return_bool(true); + + /* If PAM prompt matches "^Password: ?$", use sudo prompt. */ + if (PAM_PROMPT_IS_PASSWORD(pam_prompt)) + debug_return_bool(false); + + /* + * Some PAM modules use "^username's Password: ?$" instead of + * "^Password: ?" so check for that too. + */ + user_len = strlen(user_name); + if (strncmp(pam_prompt, user_name, user_len) == 0) { + const char *cp = pam_prompt + user_len; + if (strncmp(cp, "'s Password:", 12) == 0 && + (cp[12] == '\0' || (cp[12] == ' ' && cp[13] == '\0'))) + debug_return_bool(false); + } + } + debug_return_bool(false); +} + /* * ``Conversation function'' for PAM <-> human interaction. */ @@ -461,25 +504,9 @@ converse(int num_msg, PAM_CONST struct pam_message **msg, if (getpass_error) goto done; - /* - * We use the PAM prompt in preference to sudo's as long - * as passprompt_override is not set and: - * a) the (translated) sudo prompt matches /^Password: ?/ - * or: - * b) the PAM prompt itself *doesn't* match /^Password: ?/ - * - * The intent is to use the PAM prompt for things like - * challenge-response, otherwise use sudo's prompt. - * There may also be cases where a localized translation - * of "Password: " exists for PAM but not for sudo. - */ - prompt = def_prompt; - if (!def_passprompt_override) { - if (PROMPT_IS_PASSWORD(def_prompt)) - prompt = pm->msg; - else if (!PAM_PROMPT_IS_PASSWORD(pm->msg)) - prompt = pm->msg; - } + /* Choose either the sudo prompt or the PAM one. */ + prompt = use_pam_prompt(pm->msg) ? pm->msg : def_prompt; + /* Read the password unless interrupted. */ pass = auth_getpass(prompt, def_passwd_timeout * 60, type, callback); if (pass == NULL) {