]> granicus.if.org Git - sudo/commitdiff
When deciding which prompt to use (PAM's or sudo's) treat the PAM
authorTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 20 Jul 2017 22:06:47 +0000 (16:06 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 20 Jul 2017 22:06:47 +0000 (16:06 -0600)
prompt "username's Password:" as equivalent to "Password:".
Some PAM modules (on AIX at least) use this prompt.

plugins/sudoers/auth/pam.c

index 880eaeedb882bb9e510a6aebf7d2d2d2fcb33496..dbf18bf11b56a6e3d89b2de0b329b4c3395bccef 100644 (file)
@@ -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) {