andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone

Blame SOURCES/0037-Issue-4609-CVE-info-disclosure-when-authenticating.patch

3280a9
From 316aeae09468d6fd3b35422b236751eb1b5c309e Mon Sep 17 00:00:00 2001
ef1f48
From: Mark Reynolds <mreynolds@redhat.com>
ef1f48
Date: Tue, 9 Feb 2021 14:02:59 -0500
3280a9
Subject: [PATCH 1/2] Issue 4609 - CVE - info disclosure when authenticating
ef1f48
ef1f48
Description:  If you bind as a user that does not exist.  Error 49 is returned
ef1f48
              instead of error 32.  As error 32 discloses that the entry does
ef1f48
              not exist.  When you bind as an entry that does not have userpassword
ef1f48
              set then error 48 (inappropriate auth) is returned, but this
ef1f48
              discloses that the entry does indeed exist.  Instead we should
ef1f48
              always return error 49, even if the password is not set in the
ef1f48
              entry.  This way we do not disclose to an attacker if the Bind
ef1f48
              DN exists or not.
ef1f48
ef1f48
Relates: https://github.com/389ds/389-ds-base/issues/4609
ef1f48
ef1f48
Reviewed by: tbordaz(Thanks!)
ef1f48
---
3280a9
 dirsrvtests/tests/suites/basic/basic_test.py | 39 +++++++++++++++++++-
ef1f48
 ldap/servers/slapd/back-ldbm/ldbm_bind.c     |  4 +-
3280a9
 ldap/servers/slapd/dse.c                     |  7 +++-
3280a9
 3 files changed, 45 insertions(+), 5 deletions(-)
ef1f48
ef1f48
diff --git a/dirsrvtests/tests/suites/basic/basic_test.py b/dirsrvtests/tests/suites/basic/basic_test.py
3280a9
index fc9af46e4..e35f34721 100644
ef1f48
--- a/dirsrvtests/tests/suites/basic/basic_test.py
ef1f48
+++ b/dirsrvtests/tests/suites/basic/basic_test.py
3280a9
@@ -9,7 +9,7 @@
ef1f48
 
ef1f48
 from subprocess import check_output, PIPE, run
ef1f48
 from lib389 import DirSrv
ef1f48
-from lib389.idm.user import UserAccounts
ef1f48
+from lib389.idm.user import UserAccount, UserAccounts
ef1f48
 import pytest
ef1f48
 from lib389.tasks import *
ef1f48
 from lib389.utils import *
3280a9
@@ -1094,6 +1094,43 @@ def test_bind_invalid_entry(topology_st):
3280a9
     topology_st.standalone.simple_bind_s(DN_DM, PW_DM)
ef1f48
 
ef1f48
 
ef1f48
+def test_bind_entry_missing_passwd(topology_st):
ef1f48
+    """
ef1f48
+    :id: af209149-8fb8-48cb-93ea-3e82dd7119d2
ef1f48
+    :setup: Standalone Instance
ef1f48
+    :steps:
ef1f48
+        1. Bind as database entry that does not have userpassword set
ef1f48
+        2. Bind as database entry that does not exist
ef1f48
+        1. Bind as cn=config entry that does not have userpassword set
ef1f48
+        2. Bind as cn=config entry that does not exist
ef1f48
+    :expectedresults:
ef1f48
+        1. Fails with error 49
ef1f48
+        2. Fails with error 49
ef1f48
+        3. Fails with error 49
ef1f48
+        4. Fails with error 49
ef1f48
+    """
ef1f48
+    user = UserAccount(topology_st.standalone, DEFAULT_SUFFIX)
ef1f48
+    with pytest.raises(ldap.INVALID_CREDENTIALS):
ef1f48
+        # Bind as the suffix root entry which does not have a userpassword
ef1f48
+        user.bind("some_password")
ef1f48
+
ef1f48
+    user = UserAccount(topology_st.standalone, "cn=not here," + DEFAULT_SUFFIX)
ef1f48
+    with pytest.raises(ldap.INVALID_CREDENTIALS):
ef1f48
+        # Bind as the entry which does not exist
ef1f48
+        user.bind("some_password")
ef1f48
+
ef1f48
+    # Test cn=config since it has its own code path
ef1f48
+    user = UserAccount(topology_st.standalone, "cn=config")
ef1f48
+    with pytest.raises(ldap.INVALID_CREDENTIALS):
ef1f48
+        # Bind as the config entry which does not have a userpassword
ef1f48
+        user.bind("some_password")
ef1f48
+
ef1f48
+    user = UserAccount(topology_st.standalone, "cn=does not exist,cn=config")
ef1f48
+    with pytest.raises(ldap.INVALID_CREDENTIALS):
ef1f48
+        # Bind as an entry under cn=config that does not exist
ef1f48
+        user.bind("some_password")
ef1f48
+
ef1f48
+
ef1f48
 @pytest.mark.bz1044135
ef1f48
 @pytest.mark.ds47319
ef1f48
 def test_connection_buffer_size(topology_st):
ef1f48
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_bind.c b/ldap/servers/slapd/back-ldbm/ldbm_bind.c
ef1f48
index fa450ecd5..38d115a32 100644
ef1f48
--- a/ldap/servers/slapd/back-ldbm/ldbm_bind.c
ef1f48
+++ b/ldap/servers/slapd/back-ldbm/ldbm_bind.c
ef1f48
@@ -76,8 +76,8 @@ ldbm_back_bind(Slapi_PBlock *pb)
ef1f48
     case LDAP_AUTH_SIMPLE: {
ef1f48
         Slapi_Value cv;
ef1f48
         if (slapi_entry_attr_find(e->ep_entry, "userpassword", &attr) != 0) {
ef1f48
-            slapi_send_ldap_result(pb, LDAP_INAPPROPRIATE_AUTH, NULL,
ef1f48
-                                   NULL, 0, NULL);
ef1f48
+            slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Entry does not have userpassword set");
ef1f48
+            slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
ef1f48
             CACHE_RETURN(&inst->inst_cache, &e);
ef1f48
             rc = SLAPI_BIND_FAIL;
ef1f48
             goto bail;
ef1f48
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
3280a9
index 3c2de75fc..b04fafde6 100644
ef1f48
--- a/ldap/servers/slapd/dse.c
ef1f48
+++ b/ldap/servers/slapd/dse.c
3280a9
@@ -1446,7 +1446,8 @@ dse_bind(Slapi_PBlock *pb) /* JCM There should only be one exit point from this
ef1f48
 
ef1f48
     ec = dse_get_entry_copy(pdse, sdn, DSE_USE_LOCK);
ef1f48
     if (ec == NULL) {
ef1f48
-        slapi_send_ldap_result(pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL);
ef1f48
+        slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Entry does not exist");
ef1f48
+        slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
ef1f48
         return (SLAPI_BIND_FAIL);
ef1f48
     }
ef1f48
 
3280a9
@@ -1454,7 +1455,8 @@ dse_bind(Slapi_PBlock *pb) /* JCM There should only be one exit point from this
ef1f48
     case LDAP_AUTH_SIMPLE: {
ef1f48
         Slapi_Value cv;
ef1f48
         if (slapi_entry_attr_find(ec, "userpassword", &attr) != 0) {
ef1f48
-            slapi_send_ldap_result(pb, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, 0, NULL);
ef1f48
+            slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Entry does not have userpassword set");
ef1f48
+            slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
ef1f48
             slapi_entry_free(ec);
ef1f48
             return SLAPI_BIND_FAIL;
ef1f48
         }
3280a9
@@ -1462,6 +1464,7 @@ dse_bind(Slapi_PBlock *pb) /* JCM There should only be one exit point from this
ef1f48
 
ef1f48
         slapi_value_init_berval(&cv, cred);
ef1f48
         if (slapi_pw_find_sv(bvals, &cv) != 0) {
ef1f48
+            slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Invalid credentials");
ef1f48
             slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
ef1f48
             slapi_entry_free(ec);
ef1f48
             value_done(&cv;;
ef1f48
-- 
ef1f48
2.26.2
ef1f48