Package: libpam_ldap
Severity: grave
Tags: security patch
Justification: user security hole

A vulnerability has been found in libpam_ldap:
pam_ldap in nss_ldap on Red Hat Enterprise Linux 4, Fedora Core 3 and
earlier, and possibly other distributions does not return an error
condition when an LDAP directory server responds with a
PasswordPolicyResponse control response, which causes the
pam_authenticate function to return a success code even if
authentication has failed, as originally reported for xscreensaver.

See https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=207286 for
details.

From the patch given in the bugreport, libpam-ldap 180-1.1 in Debian
seems to be vulnerable, too. Please mention the CVE id in the changelog.

I have attached the patch as there is only a .srpm in the redhat bug report.
There's no benefit to be gained from returning success instead of failure when
a policy error is indicated, unless it's one of the errors which maps directly
to a meaningful result code used by PAM's account management functions.

And because not every application will end up calling pam_acct_mgmt(), there
are benefits to not returning success when the user can't do anything about a
policy error (see https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=207286).

--- pam_ldap/pam_ldap.c 2006-09-22 16:55:33.000000000 -0400
+++ pam_ldap/pam_ldap.c 2006-09-22 16:55:41.000000000 -0400
@@ -2057,18 +2057,47 @@
              rc2 = _get_password_policy_response_value (&(*ctlp)->ldctl_value,
                                                         session);
 
-             if (rc2 != LDAP_SUCCESS ||
-                 session->info->policy_error != POLICY_ERROR_SUCCESS)
-               {
-                 /*
-                  * If decoding policy control failed, return the error.
-                  *
-                  * If decoding policy control succeeded, and there is a
-                  * policy error, return LDAP_SUCCESS so that the error
-                  * will be handled in the account management step (see
-                  * above).
-                  */
-                 rc = rc2;
-               }
+             if (rc2 != LDAP_SUCCESS)
+               {
+                 /*
+                  * If decoding policy control failed, and we're not already
+                  * planning to report an error, return the decoding error.
+                  */
+                 if (rc == LDAP_SUCCESS)
+                   {
+                      rc = rc2;
+                   }
+               }
+             else
+               {
+                 /*
+                  * If we have a policy error, and it's one which the PAM spec
+                  * expects us to communicate via the acct_mgmt callback,
+                  * then we suppress the error.  If it's a different kind of
+                  * policy error, then make sure we indicate the error now.
+                  */
+                 switch (session->info->policy_error)
+                   {
+                   case POLICY_ERROR_SUCCESS:
+                     break;
+                   case POLICY_ERROR_CHANGE_AFTER_RESET:
+                   case POLICY_ERROR_PASSWORD_EXPIRED:
+                     rc = LDAP_SUCCESS;
+                     break;
+                   case POLICY_ERROR_ACCOUNT_LOCKED:
+                   case POLICY_ERROR_PASSWORD_MOD_NOT_ALLOWED:
+                   case POLICY_ERROR_MUST_SUPPLY_OLD_PASSWORD:
+                   case POLICY_ERROR_INSUFFICIENT_PASSWORD_QUALITY:
+                   case POLICY_ERROR_PASSWORD_TOO_SHORT:
+                   case POLICY_ERROR_PASSWORD_TOO_YOUNG:
+                   case POLICY_ERROR_PASSWORD_INSUFFICIENT:
+                   default:
+                     ldap_controls_free (controls);
+                     _pam_overwrite (session->info->userpw);
+                     _pam_drop (session->info->userpw);
+                     return PAM_AUTH_ERR;
+                     break;
+                   }
+               }
            }
        }

Reply via email to