[Pkg-freeipa-devel] Bug#1093238: bookworm-pu: package 389-ds-base/2.3.1+dfsg1-1+deb12u1

Andrej Shadura andrewsh at debian.org
Thu Jan 16 20:31:20 GMT 2025


Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: 389-ds-base at packages.debian.org, Timo Aaltonen <tjaalton at debian.org>
Control: affects -1 + src:389-ds-base
User: release.debian.org at packages.debian.org
Usertags: pu

[ Reason ]

The current version in bookworm has at least four CVEs unfixed which
are trivially fixable by applying patches from the relevant upstream
branch. These CVEs will be fixed by the upcoming LTS upload into
bullseye, so to make sure users keep these fixes when they switch
to bookworm, we need to get them fixed in bookworm too.

[ Impact ]

None except the server won't crash in certain situations.

[ Tests ]

Only the automated tests which run during the package build.

[ Risks ]

The changes are relatively simple and come with significant test
coverage.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]

The following were cherry-picks with no other changes from the
upstream’s Git repostitory, branch 2.4.6:

 - Security fix for CVE-2024-3657
 - Security fix for CVE-2024-5953
 - Security fix for CVE-2024-8445
 - Security fix for CVE-2024-2199

There were no other changes.

The changes are also available in the following Git branches:

https://salsa.debian.org/lts-team/packages/389-ds-base/-/tree/debian/bookworm-security

https://salsa.debian.org/lts-team/packages/389-ds-base/-/compare/debian%2Fbookworm-security...patch-queue%2Fdebian%2Fbookworm-security

Thanks!

-- 
Cheers,
  Andrej Shadura
-------------- next part --------------
diff -Nru 389-ds-base-2.3.1+dfsg1/debian/changelog 389-ds-base-2.3.1+dfsg1/debian/changelog
--- 389-ds-base-2.3.1+dfsg1/debian/changelog	2023-01-24 12:21:19.000000000 +0100
+++ 389-ds-base-2.3.1+dfsg1/debian/changelog	2025-01-16 17:16:37.000000000 +0100
@@ -1,3 +1,16 @@
+389-ds-base (2.3.1+dfsg1-1+deb12u1) bookworm-security; urgency=high
+
+  * Non-maintainer upload.
+  * Apply security patches from the upstream:
+    - CVE-2024-2199 and CVE-2024-8445: Crash when modifying userPassword
+      using malformed input (Closes: #1072531, #1082852).
+    - CVE-2024-5953: Denial of service while attempting to log in with
+      a user with a malformed hash in their password.
+    - CVE-2024-3657: Failure on the directory server with specially-crafted
+      LDAP query leading to denial of service.
+
+ -- Andrej Shadura <andrewsh at debian.org>  Thu, 16 Jan 2025 17:16:37 +0100
+
 389-ds-base (2.3.1+dfsg1-1) unstable; urgency=medium
 
   * Repackage the source, filter vendored crates and allow building with
diff -Nru 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-2199.patch 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-2199.patch
--- 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-2199.patch	1970-01-01 01:00:00.000000000 +0100
+++ 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-2199.patch	2025-01-16 17:16:37.000000000 +0100
@@ -0,0 +1,117 @@
+From: James Chapman <jachapma at redhat.com>
+Date: Wed, 1 May 2024 15:01:33 +0100
+Subject: Security fix for CVE-2024-2199
+
+Description:
+A denial of service vulnerability was found in the 389 Directory Server.
+This issue may allow an authenticated user to cause a server crash while
+modifying userPassword using malformed input.
+
+Fix Description:
+When doing a mod on userPassword we reset the pblock modifier after we
+set the modified timestamp, ensuring the pblock data stays valid.
+
+References:
+- https://nvd.nist.gov/vuln/detail/CVE-2024-2199
+- https://access.redhat.com/security/cve/CVE-2024-2199
+- https://bugzilla.redhat.com/show_bug.cgi?id=2267976
+---
+ dirsrvtests/tests/suites/password/password_test.py | 56 ++++++++++++++++++++++
+ ldap/servers/slapd/modify.c                        |  8 +++-
+ 2 files changed, 62 insertions(+), 2 deletions(-)
+
+diff --git a/dirsrvtests/tests/suites/password/password_test.py b/dirsrvtests/tests/suites/password/password_test.py
+index 3807947..b3ff089 100644
+--- a/dirsrvtests/tests/suites/password/password_test.py
++++ b/dirsrvtests/tests/suites/password/password_test.py
+@@ -65,6 +65,62 @@ def test_password_delete_specific_password(topology_st):
+     log.info('test_password_delete_specific_password: PASSED')
+ 
+ 
++def test_password_modify_non_utf8(topology_st):
++    """Attempt a modify of the userPassword attribute with
++    an invalid non utf8 value
++
++    :id: a31af9d5-d665-42b9-8d6e-fea3d0837d36
++    :setup: Standalone instance
++    :steps:
++        1. Add a user if it doesnt exist and set its password
++        2. Verify password with a bind
++        3. Modify userPassword attr with invalid value
++        4. Attempt a bind with invalid password value
++        5. Verify original password with a bind
++    :expectedresults:
++        1. The user with userPassword should be added successfully
++        2. Operation should be successful
++        3. Server returns ldap.UNWILLING_TO_PERFORM
++        4. Server returns ldap.INVALID_CREDENTIALS
++        5. Operation should be successful
++     """
++
++    log.info('Running test_password_modify_non_utf8...')
++
++    # Create user and set password
++    standalone = topology_st.standalone
++    users = UserAccounts(standalone, DEFAULT_SUFFIX)
++    if not users.exists(TEST_USER_PROPERTIES['uid'][0]):
++        user = users.create(properties=TEST_USER_PROPERTIES)
++    else:
++        user = users.get(TEST_USER_PROPERTIES['uid'][0])
++    user.set('userpassword', PASSWORD)
++
++    # Verify password
++    try:
++        user.bind(PASSWORD)
++    except ldap.LDAPError as e:
++        log.fatal('Failed to bind as {}, error: '.format(user.dn) + e.args[0]['desc'])
++        assert False
++
++    # Modify userPassword with an invalid value
++    password = b'tes\x82t-password' # A non UTF-8 encoded password
++    with pytest.raises(ldap.UNWILLING_TO_PERFORM):
++        user.replace('userpassword', password)
++
++    # Verify a bind fails with invalid pasword
++    with pytest.raises(ldap.INVALID_CREDENTIALS):
++        user.bind(password)
++
++    # Verify we can still bind with original password
++    try:
++        user.bind(PASSWORD)
++    except ldap.LDAPError as e:
++        log.fatal('Failed to bind as {}, error: '.format(user.dn) + e.args[0]['desc'])
++        assert False
++
++    log.info('test_password_modify_non_utf8: PASSED')
++
+ if __name__ == '__main__':
+     # Run isolated
+     # -s for DEBUG mode
+diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
+index e017799..51e6a47 100644
+--- a/ldap/servers/slapd/modify.c
++++ b/ldap/servers/slapd/modify.c
+@@ -762,8 +762,10 @@ op_shared_modify(Slapi_PBlock *pb, int pw_change, char *old_pw)
+      * flagged - leave mod attributes alone */
+     if (!repl_op && !skip_modified_attrs && lastmod) {
+         modify_update_last_modified_attr(pb, &smods);
++        slapi_pblock_set(pb, SLAPI_MODIFY_MODS, slapi_mods_get_ldapmods_byref(&smods));
+     }
+ 
++
+     if (0 == slapi_mods_get_num_mods(&smods)) {
+         /* nothing to do - no mods - this is not an error - just
+            send back LDAP_SUCCESS */
+@@ -930,8 +932,10 @@ op_shared_modify(Slapi_PBlock *pb, int pw_change, char *old_pw)
+ 
+             /* encode password */
+             if (pw_encodevals_ext(pb, sdn, va)) {
+-                slapi_log_err(SLAPI_LOG_CRIT, "op_shared_modify", "Unable to hash userPassword attribute for %s.\n", slapi_entry_get_dn_const(e));
+-                send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Unable to store attribute \"userPassword\" correctly\n", 0, NULL);
++                slapi_log_err(SLAPI_LOG_CRIT, "op_shared_modify", "Unable to hash userPassword attribute for %s, "
++                    "check value is utf8 string.\n", slapi_entry_get_dn_const(e));
++                send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Unable to hash \"userPassword\" attribute, "
++                    "check value is utf8 string.\n", 0, NULL);
+                 valuearray_free(&va);
+                 goto free_and_return;
+             }
diff -Nru 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-3657.patch 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-3657.patch
--- 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-3657.patch	1970-01-01 01:00:00.000000000 +0100
+++ 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-3657.patch	2025-01-16 17:16:37.000000000 +0100
@@ -0,0 +1,227 @@
+From: Pierre Rogier <progier at redhat.com>
+Date: Wed, 17 Apr 2024 18:18:04 +0200
+Subject: Security fix for CVE-2024-3657
+
+Description:
+A flaw was found in the 389 Directory Server. A specially-crafted LDAP query
+can potentially cause a failure on the directory server, leading to a denial
+of service.
+
+Fix Description:
+The code was modified to avoid a buffer overflow when logging some requests
+in the audit log.
+
+References:
+- https://nvd.nist.gov/vuln/detail/CVE-2024-3657
+- https://access.redhat.com/security/cve/CVE-2024-3657
+- https://bugzilla.redhat.com/show_bug.cgi?id=2274401
+---
+ .../tests/suites/filter/large_filter_test.py       |  39 +++++++-
+ ldap/servers/slapd/back-ldbm/index.c               | 111 +++++++++++----------
+ 2 files changed, 97 insertions(+), 53 deletions(-)
+
+diff --git a/dirsrvtests/tests/suites/filter/large_filter_test.py b/dirsrvtests/tests/suites/filter/large_filter_test.py
+index 6663c7c..ba6fb76 100644
+--- a/dirsrvtests/tests/suites/filter/large_filter_test.py
++++ b/dirsrvtests/tests/suites/filter/large_filter_test.py
+@@ -13,19 +13,29 @@ verify and testing  Filter from a search
+ 
+ import os
+ import pytest
++import ldap
+ 
+-from lib389._constants import PW_DM
++from lib389._constants import PW_DM, DEFAULT_SUFFIX, ErrorLog
+ from lib389.topologies import topology_st as topo
+ from lib389.idm.user import UserAccounts, UserAccount
+ from lib389.idm.account import Accounts
+ from lib389.backend import Backends
+ from lib389.idm.domain import Domain
++from lib389.utils import get_ldapurl_from_serverid
+ 
+ SUFFIX = 'dc=anuj,dc=com'
+ 
+ pytestmark = pytest.mark.tier1
+ 
+ 
++def open_new_ldapi_conn(dsinstance):
++    ldapurl, certdir = get_ldapurl_from_serverid(dsinstance)
++    assert 'ldapi://' in ldapurl
++    conn = ldap.initialize(ldapurl)
++    conn.sasl_interactive_bind_s("", ldap.sasl.external())
++    return conn
++
++
+ @pytest.fixture(scope="module")
+ def _create_entries(request, topo):
+     """
+@@ -160,6 +170,33 @@ def test_large_filter(topo, _create_entries, real_value):
+     assert len(Accounts(conn, SUFFIX).filter(real_value)) == 3
+ 
+ 
++def test_long_filter_value(topo):
++    """Exercise large eq filter with dn syntax attributes
++
++        :id: b069ef72-fcc3-11ee-981c-482ae39447e5
++        :setup: Standalone
++        :steps:
++            1. Create a specially crafted LDAP filter and
++               pass the filter to a search query with the special repeating string "a\x1Edmin"
++            2. Pass the filter to a search query with repeating string "aAdmin"
++            3. Pass the filter to a search query with string "*"
++        :expectedresults:
++            1. Search should not result in server crash and the server should be running
++    """
++    inst = topo.standalone
++    conn = open_new_ldapi_conn(inst.serverid)
++    inst.config.loglevel(vals=(ErrorLog.DEFAULT,ErrorLog.TRACE,ErrorLog.SEARCH_FILTER))
++    filter_value = "a\x1Edmin" * 1025
++    conn.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, f'(cn={filter_value})')
++    filter_value = "aAdmin" * 1025
++    conn.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, f'(cn={filter_value})')
++    filter_value = "*"
++    conn.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, f'(cn={filter_value})')
++    inst.config.loglevel(vals=(ErrorLog.DEFAULT,))
++    # Check if server is running
++    assert inst.status()
++
++
+ if __name__ == '__main__':
+     CURRENT_FILE = os.path.realpath(__file__)
+     pytest.main("-s -v %s" % CURRENT_FILE)
+diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
+index 5b34a1e..0e9c348 100644
+--- a/ldap/servers/slapd/back-ldbm/index.c
++++ b/ldap/servers/slapd/back-ldbm/index.c
+@@ -74,6 +74,32 @@ typedef struct _index_buffer_handle index_buffer_handle;
+ #define INDEX_BUFFER_FLAG_SERIALIZE 1
+ #define INDEX_BUFFER_FLAG_STATS 2
+ 
++/*
++ * space needed to encode a byte:
++ *  0x00-0x31 and 0x7f-0xff requires 3 bytes: \xx
++ *  0x22 and 0x5C requires 2 bytes: \" and \\
++ *  other requires 1 byte: c
++ */
++static char encode_size[] = {
++    /* 0x00 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
++    /* 0x10 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
++    /* 0x20 */   1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
++    /* 0x30 */   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
++    /* 0x40 */   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
++    /* 0x50 */   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,
++    /* 0x60 */   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
++    /* 0x70 */   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
++    /* 0x80 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
++    /* 0x90 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
++    /* 0xA0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
++    /* 0xB0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
++    /* 0xC0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
++    /* 0xD0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
++    /* 0xE0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
++    /* 0xF0 */   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
++};
++
++
+ /* Index buffering functions */
+ 
+ static int
+@@ -802,65 +828,46 @@ index_add_mods(
+ 
+ /*
+  * Convert a 'struct berval' into a displayable ASCII string
++ * returns the printable string
+  */
+-
+-#define SPECIAL(c) (c < 32 || c > 126 || c == '\\' || c == '"')
+-
+ const char *
+ encode(const struct berval *data, char buf[BUFSIZ])
+ {
+-    char *s;
+-    char *last;
+-    if (data == NULL || data->bv_len == 0)
+-        return "";
+-    last = data->bv_val + data->bv_len - 1;
+-    for (s = data->bv_val; s < last; ++s) {
+-        if (SPECIAL(*s)) {
+-            char *first = data->bv_val;
+-            char *bufNext = buf;
+-            size_t bufSpace = BUFSIZ - 4;
+-            while (1) {
+-                /* printf ("%lu bytes ASCII\n", (unsigned long)(s - first)); */
+-                if (bufSpace < (size_t)(s - first))
+-                    s = first + bufSpace - 1;
+-                if (s != first) {
+-                    memcpy(bufNext, first, s - first);
+-                    bufNext += (s - first);
+-                    bufSpace -= (s - first);
+-                }
+-                do {
+-                    if (bufSpace) {
+-                        *bufNext++ = '\\';
+-                        --bufSpace;
+-                    }
+-                    if (bufSpace < 2) {
+-                        memcpy(bufNext, "..", 2);
+-                        bufNext += 2;
+-                        goto bail;
+-                    }
+-                    if (*s == '\\' || *s == '"') {
+-                        *bufNext++ = *s;
+-                        --bufSpace;
+-                    } else {
+-                        sprintf(bufNext, "%02x", (unsigned)*(unsigned char *)s);
+-                        bufNext += 2;
+-                        bufSpace -= 2;
+-                    }
+-                } while (++s <= last && SPECIAL(*s));
+-                if (s > last)
+-                    break;
+-                first = s;
+-                while (!SPECIAL(*s) && s <= last)
+-                    ++s;
+-            }
+-        bail:
+-            *bufNext = '\0';
+-            /* printf ("%lu chars in buffer\n", (unsigned long)(bufNext - buf)); */
++    if (!data || !data->bv_val) {
++        strcpy(buf, "<NULL>");
++        return buf;
++    }
++    char *endbuff = &buf[BUFSIZ-4];  /* Reserve space to append "...\0" */
++    char *ptout = buf;
++    unsigned char *ptin = (unsigned char*) data->bv_val;
++    unsigned char *endptin = ptin+data->bv_len;
++
++    while (ptin < endptin) {
++        if (ptout >= endbuff) {
++            /*
++             * BUFSIZ(8K) > SLAPI_LOG_BUFSIZ(2K) so the error log message will be
++             * truncated anyway. So there is no real interrest to test if the original
++             * data contains no special characters and return it as is.
++             */
++            strcpy(endbuff, "...");
+             return buf;
+         }
++        switch (encode_size[*ptin]) {
++            case 1:
++                *ptout++ = *ptin++;
++                break;
++            case 2:
++                *ptout++ = '\\';
++                *ptout++ = *ptin++;
++                break;
++            case 3:
++                sprintf(ptout, "\\%02x", *ptin++);
++                ptout += 3;
++                break;
++        }
+     }
+-    /* printf ("%lu bytes, all ASCII\n", (unsigned long)(s - data->bv_val)); */
+-    return data->bv_val;
++    *ptout = 0;
++    return buf;
+ }
+ 
+ static const char *
diff -Nru 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-5953.patch 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-5953.patch
--- 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-5953.patch	1970-01-01 01:00:00.000000000 +0100
+++ 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-5953.patch	2025-01-16 17:16:37.000000000 +0100
@@ -0,0 +1,156 @@
+From: Pierre Rogier <progier at redhat.com>
+Date: Fri, 14 Jun 2024 13:27:10 +0200
+Subject: Security fix for CVE-2024-5953
+
+Description:
+A denial of service vulnerability was found in the 389 Directory Server.
+This issue may allow an authenticated user to cause a server denial
+of service while attempting to log in with a user with a malformed hash
+in their password.
+
+Fix Description:
+To prevent buffer overflow when a bind request is processed, the bind fails
+if the hash size is not coherent without even attempting to process further
+the hashed password.
+
+References:
+- https://nvd.nist.gov/vuln/detail/CVE-2024-5953
+- https://access.redhat.com/security/cve/CVE-2024-5953
+- https://bugzilla.redhat.com/show_bug.cgi?id=2292104
+---
+ .../tests/suites/password/regression_test.py       | 51 +++++++++++++++++++++-
+ ldap/servers/plugins/pwdstorage/md5_pwd.c          |  9 +++-
+ ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c       |  6 +++
+ 3 files changed, 64 insertions(+), 2 deletions(-)
+
+diff --git a/dirsrvtests/tests/suites/password/regression_test.py b/dirsrvtests/tests/suites/password/regression_test.py
+index 24c24fb..eed8e27 100644
+--- a/dirsrvtests/tests/suites/password/regression_test.py
++++ b/dirsrvtests/tests/suites/password/regression_test.py
+@@ -8,11 +8,12 @@
+ import pytest
+ import time
+ import glob
++import base64
+ from lib389._constants import PASSWORD, DN_DM, DEFAULT_SUFFIX
+ from lib389._constants import SUFFIX, PASSWORD, DN_DM, DN_CONFIG, PLUGIN_RETRO_CHANGELOG, DEFAULT_SUFFIX, DEFAULT_CHANGELOG_DB, DEFAULT_BENAME
+ from lib389 import Entry
+ from lib389.topologies import topology_m1 as topo_supplier
+-from lib389.idm.user import UserAccounts
++from lib389.idm.user import UserAccounts, UserAccount
+ from lib389.utils import ldap, os, logging, ensure_bytes, ds_is_newer, ds_supports_new_changelog
+ from lib389.topologies import topology_st as topo
+ from lib389.idm.organizationalunit import OrganizationalUnits
+@@ -40,6 +41,13 @@ TEST_PASSWORDS += ['CNpwtest1ZZZZ', 'ZZZZZCNpwtest1',
+ TEST_PASSWORDS2 = (
+     'CN12pwtest31', 'SN3pwtest231', 'UID1pwtest123', 'MAIL2pwtest12 at redhat.com', '2GN1pwtest123', 'People123')
+ 
++SUPPORTED_SCHEMES = (
++    "{SHA}", "{SSHA}", "{SHA256}", "{SSHA256}",
++    "{SHA384}", "{SSHA384}", "{SHA512}", "{SSHA512}",
++    "{crypt}", "{NS-MTA-MD5}", "{clear}", "{MD5}",
++    "{SMD5}", "{PBKDF2_SHA256}", "{PBKDF2_SHA512}",
++    "{GOST_YESCRYPT}", "{PBKDF2-SHA256}", "{PBKDF2-SHA512}" )
++
+ def _check_unhashed_userpw(inst, user_dn, is_present=False):
+     """Check if unhashed#user#password attribute is present or not in the changelog"""
+     unhashed_pwd_attribute = 'unhashed#user#password'
+@@ -321,6 +329,47 @@ def test_unhashed_pw_switch(topo_supplier):
+         # Add debugging steps(if any)...
+         pass
+ 
++ at pytest.mark.parametrize("scheme", SUPPORTED_SCHEMES )
++def test_long_hashed_password(topo, create_user, scheme):
++    """Check that hashed password with very long value does not cause trouble
++
++    :id: 252a1f76-114b-11ef-8a7a-482ae39447e5
++    :setup: standalone Instance
++    :parametrized: yes
++    :steps:
++        1. Add a test user user
++        2. Set a long password with requested scheme
++        3. Bind on that user using a wrong password
++        4. Check that instance is still alive
++        5. Remove the added user
++    :expectedresults:
++        1. Success
++        2. Success
++        3. Should get ldap.INVALID_CREDENTIALS exception
++        4. Success
++        5. Success
++    """
++    inst = topo.standalone
++    inst.simple_bind_s(DN_DM, PASSWORD)
++    users = UserAccounts(inst, DEFAULT_SUFFIX)
++    # Make sure that server is started as this test may crash it
++    inst.start()
++    # Adding Test user (It may already exists if previous test failed)
++    user2 = UserAccount(inst, dn='uid=test_user_1002,ou=People,dc=example,dc=com')
++    if not user2.exists():
++        user2 = users.create_test_user(uid=1002, gid=2002)
++    # Setting hashed password
++    passwd = 'A'*4000
++    hashed_passwd = scheme.encode('utf-8') + base64.b64encode(passwd.encode('utf-8'))
++    user2.replace('userpassword', hashed_passwd)
++    # Bind on that user using a wrong password
++    with pytest.raises(ldap.INVALID_CREDENTIALS):
++        conn = user2.bind(PASSWORD)
++    # Check that instance is still alive
++    assert inst.status()
++    # Remove the added user
++    user2.delete()
++
+ 
+ if __name__ == '__main__':
+     # Run isolated
+diff --git a/ldap/servers/plugins/pwdstorage/md5_pwd.c b/ldap/servers/plugins/pwdstorage/md5_pwd.c
+index 1e2cf58..b9a48d5 100644
+--- a/ldap/servers/plugins/pwdstorage/md5_pwd.c
++++ b/ldap/servers/plugins/pwdstorage/md5_pwd.c
+@@ -37,6 +37,7 @@ md5_pw_cmp(const char *userpwd, const char *dbpwd)
+     unsigned char hash_out[MD5_HASH_LEN];
+     unsigned char b2a_out[MD5_HASH_LEN * 2]; /* conservative */
+     SECItem binary_item;
++    size_t dbpwd_len = strlen(dbpwd);
+ 
+     ctx = PK11_CreateDigestContext(SEC_OID_MD5);
+     if (ctx == NULL) {
+@@ -45,6 +46,12 @@ md5_pw_cmp(const char *userpwd, const char *dbpwd)
+         goto loser;
+     }
+ 
++    if (dbpwd_len >= sizeof b2a_out) {
++        slapi_log_err(SLAPI_LOG_PLUGIN, MD5_SUBSYSTEM_NAME,
++                      "The hashed password stored in the user entry is longer than any valid md5 hash");
++        goto loser;
++    }
++
+     /* create the hash */
+     PK11_DigestBegin(ctx);
+     PK11_DigestOp(ctx, (const unsigned char *)userpwd, strlen(userpwd));
+@@ -57,7 +64,7 @@ md5_pw_cmp(const char *userpwd, const char *dbpwd)
+     bver = NSSBase64_EncodeItem(NULL, (char *)b2a_out, sizeof b2a_out, &binary_item);
+     /* bver points to b2a_out upon success */
+     if (bver) {
+-        rc = slapi_ct_memcmp(bver, dbpwd, strlen(dbpwd));
++        rc = slapi_ct_memcmp(bver, dbpwd, dbpwd_len);
+     } else {
+         slapi_log_err(SLAPI_LOG_PLUGIN, MD5_SUBSYSTEM_NAME,
+                       "Could not base64 encode hashed value for password compare");
+diff --git a/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c b/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
+index dcac4fc..82b8c95 100644
+--- a/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
++++ b/ldap/servers/plugins/pwdstorage/pbkdf2_pwd.c
+@@ -255,6 +255,12 @@ pbkdf2_sha256_pw_cmp(const char *userpwd, const char *dbpwd)
+     passItem.data = (unsigned char *)userpwd;
+     passItem.len = strlen(userpwd);
+ 
++    if (pwdstorage_base64_decode_len(dbpwd, dbpwd_len) > sizeof dbhash) {
++        /* Hashed value is too long and cannot match any value generated by pbkdf2_sha256_hash */
++        slapi_log_err(SLAPI_LOG_ERR, (char *)schemeName, "Unable to base64 decode dbpwd value. (hashed value is too long)\n");
++        return result;
++    }
++
+     /* Decode the DBpwd to bytes from b64 */
+     if (PL_Base64Decode(dbpwd, dbpwd_len, dbhash) == NULL) {
+         slapi_log_err(SLAPI_LOG_ERR, (char *)schemeName, "Unable to base64 decode dbpwd value\n");
diff -Nru 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-8445.patch 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-8445.patch
--- 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-8445.patch	1970-01-01 01:00:00.000000000 +0100
+++ 389-ds-base-2.3.1+dfsg1/debian/patches/CVE-2024-8445.patch	2025-01-16 17:16:37.000000000 +0100
@@ -0,0 +1,33 @@
+From: Pierre Rogier <progier at redhat.com>
+Date: Mon, 23 Sep 2024 19:18:52 +0200
+Subject: Security fix for CVE-2024-8445
+
+Description:
+The fix for CVE-2024-2199 in 389-ds-base was insufficient to cover all
+scenarios. In certain product versions, this issue may allow
+an authenticated user to cause a server crash while modifying
+`userPassword` using malformed input.
+
+References:
+- https://access.redhat.com/security/cve/CVE-2024-8445
+- https://nvd.nist.gov/vuln/detail/cve-2024-8445
+- https://bugzilla.redhat.com/show_bug.cgi?id=2310110
+- https://nvd.nist.gov/vuln/detail/CVE-2024-2199
+- https://access.redhat.com/security/cve/CVE-2024-2199
+- https://bugzilla.redhat.com/show_bug.cgi?id=2267976
+---
+ ldap/servers/slapd/modify.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
+index 51e6a47..57dac03 100644
+--- a/ldap/servers/slapd/modify.c
++++ b/ldap/servers/slapd/modify.c
+@@ -937,6 +937,7 @@ op_shared_modify(Slapi_PBlock *pb, int pw_change, char *old_pw)
+                 send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Unable to hash \"userPassword\" attribute, "
+                     "check value is utf8 string.\n", 0, NULL);
+                 valuearray_free(&va);
++                slapi_pblock_set(pb, SLAPI_MODIFY_MODS, (void *)slapi_mods_get_ldapmods_passout(&smods));
+                 goto free_and_return;
+             }
+ 
diff -Nru 389-ds-base-2.3.1+dfsg1/debian/patches/series 389-ds-base-2.3.1+dfsg1/debian/patches/series
--- 389-ds-base-2.3.1+dfsg1/debian/patches/series	2023-01-24 12:21:16.000000000 +0100
+++ 389-ds-base-2.3.1+dfsg1/debian/patches/series	2025-01-16 17:16:37.000000000 +0100
@@ -3,3 +3,7 @@
 dont-run-rpm.diff
 use-packaged-rust-registry.diff
 allow-newer-crates.diff
+CVE-2024-2199.patch
+CVE-2024-8445.patch
+CVE-2024-5953.patch
+CVE-2024-3657.patch


More information about the Pkg-freeipa-devel mailing list