]> granicus.if.org Git - sudo/commitdiff
Work around an ambiguity in the PAM spec with respect to the conversation
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 9 Mar 2016 16:39:46 +0000 (09:39 -0700)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 9 Mar 2016 16:39:46 +0000 (09:39 -0700)
function.  It is not clear whether the "struct pam_message **msg" is an
array of pointers or a pointer to an array.  Linux-PAM and OpenPAM use
an array of pointers while Solaris/HP-UX/AIX uses a pointer to an array.
Bug #726.

NEWS
config.h.in
configure
configure.ac
plugins/sudoers/auth/pam.c

diff --git a/NEWS b/NEWS
index 9e8f34ff6ce86e557e00404619303cfc72d9ed01..274da1c4824fea64edd54155feb4802f4077fb55 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -63,6 +63,9 @@ What's new in Sudo 1.8.16
  * Fixed a bug in the LDAP and SSSD backends that could allow an
    unauthorized user to list another user's privileges.  Bug #738.
 
+ * The PAM conversation function now works around an ambiguity in the
+   PAM spec with respect to multiple messages.  Bug #726.
+
 What's new in Sudo 1.8.15
 
  * Fixed a bug that prevented sudo from building outside the source tree
index 3d11c0187b12dbb5f8c53b423ba8c98604a56b31..b71d9cdb42026ce379f8cf6db0cbe536bb920a15 100644 (file)
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
+/* Define to 1 if your system uses a Solaris-derived PAM and not Linux-PAM or
+   OpenPAM. */
+#undef PAM_SUN_CODEBASE
+
 /* The default password prompt. */
 #undef PASSPROMPT
 
index 4cdba6eda7673789d535bfea061b2be823815034..04cb265009fa24e67608bf766e5b96e9828c22e0 100755 (executable)
--- a/configure
+++ b/configure
@@ -14729,6 +14729,9 @@ esac
                shadow_funcs="getpwanam issecure"
                ;;
     *-*-solaris2*)
+               $as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h
+
+
                # LD_PRELOAD is space-delimited
                RTLD_PRELOAD_DELIM=" "
 
@@ -14756,6 +14759,9 @@ done
 
                ;;
     *-*-aix*)
+               $as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h
+
+
                # To get all prototypes (so we pass -Wall)
                $as_echo "#define _LINUX_SOURCE_COMPAT 1" >>confdefs.h
 
@@ -14872,6 +14878,9 @@ _ACEOF
 
                ;;
     *-*-hiuxmpp*)
+               $as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h
+
+
                : ${mansectsu='1m'}
                : ${mansectform='4'}
 
@@ -14897,6 +14906,9 @@ done
 
                ;;
     *-*-hpux*)
+               $as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h
+
+
                # AFS support needs -lBSD
                if test "$with_AFS" = "yes"; then
                    AFS_LIBS="-lc -lBSD"
@@ -26577,5 +26589,6 @@ fi
 
 
 
+
 
 
index 4c063979f935398361e780e47775c18f980d2486..bb2ba26992dd8075dd7619a8810a96df21b08ca7 100644 (file)
@@ -1685,6 +1685,8 @@ case "$host" in
                shadow_funcs="getpwanam issecure"
                ;;
     *-*-solaris2*)
+               AC_DEFINE([PAM_SUN_CODEBASE])
+
                # LD_PRELOAD is space-delimited
                RTLD_PRELOAD_DELIM=" "
 
@@ -1702,6 +1704,8 @@ case "$host" in
                AC_CHECK_FUNCS([priv_set], [PSMAN=1])
                ;;
     *-*-aix*)
+               AC_DEFINE([PAM_SUN_CODEBASE])
+
                # To get all prototypes (so we pass -Wall)
                AC_DEFINE([_LINUX_SOURCE_COMPAT])
                SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -Wl,-bI:\$(srcdir)/aixcrypt.exp"
@@ -1756,6 +1760,8 @@ case "$host" in
                ])
                ;;
     *-*-hiuxmpp*)
+               AC_DEFINE([PAM_SUN_CODEBASE])
+
                : ${mansectsu='1m'}
                : ${mansectform='4'}
 
@@ -1771,6 +1777,8 @@ case "$host" in
                AC_CHECK_FUNCS([pstat_getproc])
                ;;
     *-*-hpux*)
+               AC_DEFINE([PAM_SUN_CODEBASE])
+
                # AFS support needs -lBSD
                if test "$with_AFS" = "yes"; then
                    AFS_LIBS="-lc -lBSD"
@@ -4352,6 +4360,7 @@ AH_TEMPLATE(HAVE__NSS_XBYY_BUF_ALLOC, [Define to 1 if you have the `_nss_XbyY_bu
 AH_TEMPLATE(HAVE___NSS_XBYY_BUF_ALLOC, [Define to 1 if you have the `__nss_XbyY_buf_alloc' function.])
 AH_TEMPLATE(NEED_RESOLV_H, [Define to 1 if resolv.h must be included to get the `inet_ntop' or `inet_pton' function prototypes.])
 AH_TEMPLATE(HAVE_STRNLEN, [Define to 1 if you have the `strnlen' function.])
+AH_TEMPLATE(PAM_SUN_CODEBASE, [Define to 1 if your system uses a Solaris-derived PAM and not Linux-PAM or OpenPAM.])
 
 dnl
 dnl Bits to copy verbatim into config.h.in
index 90f4eabf1a1d0d8728c4918b02870b4f8366e989..abb19322682b1d6207615743745c47709046aeb7 100644 (file)
 #include "sudo_auth.h"
 
 /* Only OpenPAM and Linux PAM use const qualifiers. */
-#if defined(_OPENPAM) || defined(OPENPAM_VERSION) || \
-    defined(__LIBPAM_VERSION) || defined(__LINUX_PAM__)
+#ifdef PAM_SUN_CODEBASE
+# define PAM_CONST
+#else
 # define PAM_CONST     const
+#endif
+
+/* Ambiguity in spec: is it an array of pointers or a pointer to an array? */
+#ifdef PAM_SUN_CODEBASE
+# define PAM_MSG_GET(msg, n) (*(msg) + (n))
 #else
-# define PAM_CONST
+# define PAM_MSG_GET(msg, n) ((msg)[(n)])
 #endif
 
 #ifndef PAM_DATA_SILENT
@@ -376,11 +382,10 @@ sudo_pam_end_session(struct passwd *pw, sudo_auth *auth)
  */
 static int
 converse(int num_msg, PAM_CONST struct pam_message **msg,
-    struct pam_response **response, void *vcallback)
+    struct pam_response **reply_out, void *vcallback)
 {
-    struct pam_response *pr;
     struct sudo_conv_callback *callback = NULL;
-    PAM_CONST struct pam_message *pm;
+    struct pam_response *reply;
     const char *prompt;
     char *pass;
     int n, type;
@@ -395,15 +400,18 @@ converse(int num_msg, PAM_CONST struct pam_message **msg,
     sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
        "number of PAM messages: %d", num_msg);
 
-    if ((*response = calloc(num_msg, sizeof(struct pam_response))) == NULL) {
+    if ((reply = calloc(num_msg, sizeof(struct pam_response))) == NULL) {
        sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
        debug_return_int(PAM_BUF_ERR);
     }
+    *reply_out = reply;
 
     if (vcallback != NULL)
        callback = *((struct sudo_conv_callback **)vcallback);
 
-    for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) {
+    for (n = 0; n < num_msg; n++) {
+       PAM_CONST struct pam_message *pm = PAM_MSG_GET(msg, n);
+
        type = SUDO_CONV_PROMPT_ECHO_OFF;
        switch (pm->msg_style) {
            case PAM_PROMPT_ECHO_ON:
@@ -447,7 +455,7 @@ converse(int num_msg, PAM_CONST struct pam_message **msg,
                    memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass));
                    goto done;
                }
-               pr->resp = pass;        /* auth_getpass() malloc's a copy */
+               reply[n].resp = pass;   /* auth_getpass() malloc's a copy */
                break;
            case PAM_TEXT_INFO:
                if (pm->msg)
@@ -470,15 +478,17 @@ converse(int num_msg, PAM_CONST struct pam_message **msg,
 done:
     if (ret != PAM_SUCCESS) {
        /* Zero and free allocated memory and return an error. */
-       for (pr = *response, n = num_msg; n--; pr++) {
+       for (n = 0; n < num_msg; n++) {
+           struct pam_response *pr = &reply[n];
+
            if (pr->resp != NULL) {
                memset_s(pr->resp, SUDO_CONV_REPL_MAX, 0, strlen(pr->resp));
                free(pr->resp);
                pr->resp = NULL;
            }
        }
-       free(*response);
-       *response = NULL;
+       free(reply);
+       *reply_out = NULL;
     }
     debug_return_int(ret);
 }