diff --git a/SOURCES/0006-CVE-2024-5953.patch b/SOURCES/0006-CVE-2024-5953.patch
new file mode 100644
index 0000000..37c2179
--- /dev/null
+++ b/SOURCES/0006-CVE-2024-5953.patch
@@ -0,0 +1,145 @@
+From 52a9ee6556a0467f5134fb6392ff1681a38f3252 Mon Sep 17 00:00:00 2001
+From: Pierre Rogier <progier@redhat.com>
+Date: Fri, 14 Jun 2024 13:27:10 +0200
+Subject: [PATCH] CVE-2024-5953
+
+---
+ .../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 4876ff435..160d6f01d 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@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'
+@@ -319,6 +327,47 @@ def test_unhashed_pw_switch(topo_supplier):
+         # Add debugging steps(if any)...
+         pass
+ 
++@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 1e2cf58e7..b9a48d5ca 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 dcac4fcdd..82b8c9501 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");
+-- 
+2.44.0
+
diff --git a/SOURCES/0007-CVE-2024-6237.patch b/SOURCES/0007-CVE-2024-6237.patch
new file mode 100644
index 0000000..780cfa8
--- /dev/null
+++ b/SOURCES/0007-CVE-2024-6237.patch
@@ -0,0 +1,25 @@
+From 323f74c69f84a8482413ecd73cf61d09cfc4a0a1 Mon Sep 17 00:00:00 2001
+From: Thierry Bordaz <tbordaz@redhat.com>
+Date: Mon, 24 Jun 2024 15:51:28 +0200
+Subject: [PATCH] CVE-2024-6237
+
+---
+ ldap/servers/plugins/syntaxes/inchain.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ldap/servers/plugins/syntaxes/inchain.c b/ldap/servers/plugins/syntaxes/inchain.c
+index df19c973b..0a6a04e9f 100644
+--- a/ldap/servers/plugins/syntaxes/inchain.c
++++ b/ldap/servers/plugins/syntaxes/inchain.c
+@@ -277,7 +277,7 @@ inchain_values2keys(Slapi_PBlock *pb, Slapi_Value **vals, Slapi_Value ***ivals,
+     slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &base_sdn);
+ 
+     if (! slapi_attr_is_dn_syntax_type(mrTYPE)) {
+-        slapi_log_err(SLAPI_LOG_ERR, "inchain", "Requires distinguishedName syntax. AttributeDescription %s is not distinguishedName\n");
++        slapi_log_err(SLAPI_LOG_ERR, "inchain", "Requires distinguishedName syntax. AttributeDescription %s is not distinguishedName\n", mrTYPE);
+         result = (Slapi_Value **)slapi_ch_calloc(1, sizeof(Slapi_Value *));
+         *ivals = result;
+         return(0);
+-- 
+2.44.0
+
diff --git a/SOURCES/0008-Issue-5772-ONE-LEVEL-search-fails-to-return-sub-suff.patch b/SOURCES/0008-Issue-5772-ONE-LEVEL-search-fails-to-return-sub-suff.patch
new file mode 100644
index 0000000..406810b
--- /dev/null
+++ b/SOURCES/0008-Issue-5772-ONE-LEVEL-search-fails-to-return-sub-suff.patch
@@ -0,0 +1,192 @@
+From 9501c34df01e35f483201a4bba12a93091b2b13f Mon Sep 17 00:00:00 2001
+From: progier389 <progier@redhat.com>
+Date: Thu, 13 Jun 2024 15:17:36 +0200
+Subject: [PATCH] Issue 5772 - ONE LEVEL search fails to return sub-suffixes
+ (#6219)
+
+Problem: ONE LEVEL scoped search fails to return sub-suffixes entries
+Reason: When such search is done, a one level search is done on the main suffix and base search are done on any matching sub-suffix. But main suffix is processed search (to ensure that parent entries are returned before children ones when searching subtree) and ldbm_back_search change the filter to (&(parentid=xxx)old_filter) so the filter test reject the entry on the sub-suffixes.
+Solution: Revert the backend list when doing one level search so that the sub-suffixes are processed first
+and restore the base dn for the main suffix.
+Alternative rejected: reset the filter when discivering a sub-suffix. Not so easy because filter is altered by the rewriteres.
+And systematic duplication is an useless overhead if there is no matching sub-suffixes (which is the usual case)
+
+Issue: #5772
+
+Reviewed by: @tbordaz, @droideck (Thanks!)
+
+(cherry picked from commit 407bdaa00d1da9f5ff53d66a2e012b17ad658907)
+---
+ .../suites/mapping_tree/regression_test.py    | 36 +++++++++++++++++-
+ ldap/servers/slapd/filterentry.c              | 38 ++++++++++++++++++-
+ ldap/servers/slapd/opshared.c                 | 22 ++++++++++-
+ 3 files changed, 92 insertions(+), 4 deletions(-)
+
+diff --git a/dirsrvtests/tests/suites/mapping_tree/regression_test.py b/dirsrvtests/tests/suites/mapping_tree/regression_test.py
+index f4877da2b..c3fc2c0a2 100644
+--- a/dirsrvtests/tests/suites/mapping_tree/regression_test.py
++++ b/dirsrvtests/tests/suites/mapping_tree/regression_test.py
+@@ -92,7 +92,6 @@ EXPECTED_ENTRIES = (("dc=parent", 39), ("dc=child1,dc=parent", 13), ("dc=child2,
+ @pytest.mark.skipif(not has_orphan_attribute, reason = "compatibility attribute not yet implemented in this version")
+ def test_sub_suffixes(topo, orphan_param):
+     """ check the entries found on suffix/sub-suffix
+-    used int
+ 
+     :id: 5b4421c2-d851-11ec-a760-482ae39447e5
+     :feature: mapping-tree
+@@ -122,8 +121,41 @@ def test_sub_suffixes(topo, orphan_param):
+         log.info(f'Verifying domain component entries count for search under {suffix} ...')
+         entries = topo.standalone.search_s(suffix, ldap.SCOPE_SUBTREE, "(dc=*)")
+         assert len(entries) == expected
+-        log.info('Found {expected} domain component entries as expected while searching {suffix}')
++        log.info(f'Found {expected} domain component entries as expected while searching {suffix}')
+ 
+     log.info('Test PASSED')
+ 
+ 
++def test_one_level_search_on_sub_suffixes(topo):
++    """ Perform one level scoped search accross suffix and sub-suffix
++
++    :id: 92f3139e-280e-11ef-a989-482ae39447e5
++    :feature: mapping-tree
++    :setup: Standalone instance with 3 additional backends:
++            dc=parent, dc=child1,dc=parent, dc=childr21,dc=parent
++    :steps:
++        1. Perform a ONE LEVEL search on dc=parent
++        2. Check that all expected entries have been returned
++        3. Check that only the expected entries have been returned
++    :expectedresults:
++        1. Success
++        2. each expected dn should be in the result set
++        3. Number of returned entries should be the same as the number of expected entries
++    """
++    expected_dns = ( 'dc=child1,dc=parent',
++                         'dc=child2,dc=parent',
++                         'ou=accounting,dc=parent',
++                         'ou=product development,dc=parent',
++                         'ou=product testing,dc=parent',
++                         'ou=human resources,dc=parent',
++                         'ou=payroll,dc=parent',
++                         'ou=people,dc=parent',
++                         'ou=groups,dc=parent', )
++    entries = topo.standalone.search_s("dc=parent", ldap.SCOPE_ONELEVEL, "(objectClass=*)",
++                                       attrlist=("dc","ou"), escapehatch='i am sure')
++    log.info(f'one level search on dc=parent returned the following entries: {entries}')
++    dns = [ entry.dn for entry in entries ]
++    for dn in expected_dns:
++        assert dn in dns
++    assert len(entries) == len(expected_dns)
++
+diff --git a/ldap/servers/slapd/filterentry.c b/ldap/servers/slapd/filterentry.c
+index 4de4aa66e..d2c7e3082 100644
+--- a/ldap/servers/slapd/filterentry.c
++++ b/ldap/servers/slapd/filterentry.c
+@@ -240,6 +240,36 @@ slapi_filter_test_ext(
+ }
+ 
+ 
++static const char *
++filter_type_as_string(int filter_type)
++{
++    switch (filter_type) {
++    case LDAP_FILTER_AND:
++        return "&";
++    case LDAP_FILTER_OR:
++        return "|";
++    case LDAP_FILTER_NOT:
++        return "!";
++    case LDAP_FILTER_EQUALITY:
++        return "=";
++    case LDAP_FILTER_SUBSTRINGS:
++        return "*";
++    case LDAP_FILTER_GE:
++        return ">=";
++    case LDAP_FILTER_LE:
++        return "<=";
++    case LDAP_FILTER_PRESENT:
++        return "=*";
++    case LDAP_FILTER_APPROX:
++        return "~";
++    case LDAP_FILTER_EXT:
++        return "EXT";
++    default:
++        return "?";
++    }
++}
++
++
+ int
+ test_ava_filter(
+     Slapi_PBlock *pb,
+@@ -253,7 +283,13 @@ test_ava_filter(
+ {
+     int rc;
+ 
+-    slapi_log_err(SLAPI_LOG_FILTER, "test_ava_filter", "=>\n");
++    if (slapi_is_loglevel_set(SLAPI_LOG_FILTER)) {
++        char *val = slapi_berval_get_string_copy(&ava->ava_value);
++        char buf[BUFSIZ];
++        slapi_log_err(SLAPI_LOG_FILTER, "test_ava_filter", "=> AVA: %s%s%s\n",
++                      ava->ava_type, filter_type_as_string(ftype), escape_string(val, buf));
++        slapi_ch_free_string(&val);
++    }
+ 
+     *access_check_done = 0;
+ 
+diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
+index f77043afa..540597f45 100644
+--- a/ldap/servers/slapd/opshared.c
++++ b/ldap/servers/slapd/opshared.c
+@@ -219,6 +219,7 @@ cache_return_target_entry(Slapi_PBlock *pb, Slapi_Backend *be, Slapi_Operation *
+         operation_set_target_entry_id(operation, 0);
+     }
+ }
++
+ /*
+  * Returns: 0    - if the operation is successful
+  *        < 0    - if operation fails.
+@@ -481,6 +482,20 @@ op_shared_search(Slapi_PBlock *pb, int send_result)
+             while (be_list[index] && be_list[index + 1]) {
+                 index++;
+             }
++            if (scope == LDAP_SCOPE_ONELEVEL) {
++                /*
++                 * ONE LEVEL searches may ends up on multiple backends
++                 *  with a ONE LEVEL search on a suffix and a BASE search on its
++                 *  subsuffixes. Because LDAP_SCOPE_ONELEVEL rewrite the filter
++                 *  the backends should be reversed so that the BASE search(es)
++                 *  are done first (with the original filter).
++                 */
++                for (int idx = 0; idx <= index/2; idx++) {
++                    be = be_list[index-idx];
++                    be_list[index-idx] = be_list[idx];
++                    be_list[idx] = be;
++                }
++            }
+             be = be_list[index];
+         } else {
+             be = NULL;
+@@ -779,7 +794,6 @@ op_shared_search(Slapi_PBlock *pb, int send_result)
+                         (slapi_sdn_get_ndn_len(basesdn) == 0)) {
+                         int tmp_scope = LDAP_SCOPE_BASE;
+                         slapi_pblock_set(pb, SLAPI_SEARCH_SCOPE, &tmp_scope);
+-
+                         if (free_sdn) {
+                             slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &sdn);
+                             slapi_sdn_free(&sdn);
+@@ -790,6 +804,12 @@ op_shared_search(Slapi_PBlock *pb, int send_result)
+                     } else if (slapi_sdn_issuffix(basesdn, be_suffix)) {
+                         int tmp_scope = LDAP_SCOPE_ONELEVEL;
+                         slapi_pblock_set(pb, SLAPI_SEARCH_SCOPE, &tmp_scope);
++                        if (free_sdn) {
++                            slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &sdn);
++                            slapi_sdn_free(&sdn);
++                            sdn = slapi_sdn_dup(basesdn);
++                            slapi_pblock_set(pb, SLAPI_SEARCH_TARGET_SDN, (void *)sdn);
++                        }
+                     } else {
+                         slapi_sdn_done(&monitorsdn);
+                         goto next_be;
+-- 
+2.45.2
+
diff --git a/SOURCES/0009-Issue-6172-RFE-improve-the-performance-of-evaluation.patch b/SOURCES/0009-Issue-6172-RFE-improve-the-performance-of-evaluation.patch
new file mode 100644
index 0000000..5693fb4
--- /dev/null
+++ b/SOURCES/0009-Issue-6172-RFE-improve-the-performance-of-evaluation.patch
@@ -0,0 +1,220 @@
+From 45e14d64c47080951d9bfa3bcfe8c267d01ce251 Mon Sep 17 00:00:00 2001
+From: tbordaz <tbordaz@redhat.com>
+Date: Wed, 22 May 2024 11:29:05 +0200
+Subject: [PATCH] Issue 6172 - RFE: improve the performance of evaluation of
+ filter component when tested against a large valueset (like group members)
+ (#6173)
+
+Bug description:
+	Before returning an entry (to a SRCH) the server checks that the entry matches the SRCH filter.
+	If a filter component (equality) is testing the value (ava) against a
+	large valueset (like uniquemember values), it takes a long time because
+	of the large number of values and required normalization of the values.
+	This can be improved taking benefit of sorted valueset. Those sorted
+	valueset were created to improve updates of large valueset (groups) but
+	at that time not implemented in SRCH path.
+
+Fix description:
+	In case of LDAP_FILTER_EQUALITY component, the server can get
+	benefit of the sorted valuearray.
+	To limit the risk of regression, we use the sorted valuearray
+	only for the DN syntax attribute. Indeed the sorted valuearray was
+	designed for those type of attribute.
+	With those two limitations, there is no need of a toggle and
+	the call to plugin_call_syntax_filter_ava can be replaced by
+	a call to slapi_valueset_find.
+	In both cases, sorted valueset and plugin_call_syntax_filter_ava, ava and
+	values are normalized.
+	In sorted valueset, the values have been normalized to insert the index
+	in the sorted array and then comparison is done on normalized values.
+	In plugin_call_syntax_filter_ava, all values in valuearray (of valueset) are normalized
+	before comparison.
+
+relates: #6172
+
+Reviewed by: Pierre Rogier, Simon Pichugin (Big Thanks !!!)
+---
+ .../tests/suites/filter/filter_test.py        | 125 ++++++++++++++++++
+ ldap/servers/slapd/filterentry.c              |  22 ++-
+ 2 files changed, 146 insertions(+), 1 deletion(-)
+
+diff --git a/dirsrvtests/tests/suites/filter/filter_test.py b/dirsrvtests/tests/suites/filter/filter_test.py
+index d6bfa5a3b..4baaf04a7 100644
+--- a/dirsrvtests/tests/suites/filter/filter_test.py
++++ b/dirsrvtests/tests/suites/filter/filter_test.py
+@@ -9,7 +9,11 @@
+ import logging
+ 
+ import pytest
++import time
++from lib389.dirsrv_log import DirsrvAccessLog
+ from lib389.tasks import *
++from lib389.backend import Backends, Backend
++from lib389.dbgen import dbgen_users, dbgen_groups
+ from lib389.topologies import topology_st
+ from lib389._constants import PASSWORD, DEFAULT_SUFFIX, DN_DM, SUFFIX
+ from lib389.utils import *
+@@ -304,6 +308,127 @@ def test_extended_search(topology_st):
+     ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter)
+     assert len(ents) == 1
+ 
++def test_match_large_valueset(topology_st):
++    """Test that when returning a big number of entries
++    and that we need to match the filter from a large valueset
++    we get benefit to use the sorted valueset
++
++    :id: 7db5aa88-50e0-4c31-85dd-1d2072cb674c
++
++    :setup: Standalone instance
++
++    :steps:
++         1. Create a users and groups backends and tune them
++         2. Generate a test ldif (2k users and 1K groups with all users)
++         3. Import test ldif file using Offline import (ldif2db).
++         4. Prim the 'groups' entrycache with a "fast" search
++         5. Search the 'groups' with a difficult matching value
++         6. check that etime from step 5 is less than a second
++
++    :expectedresults:
++         1. Create a users and groups backends should PASS
++         2. Generate LDIF should PASS.
++         3. Offline import should PASS.
++         4. Priming should PASS.
++         5. Performance search should PASS.
++         6. Etime of performance search should PASS.
++    """
++
++    log.info('Running test_match_large_valueset...')
++    #
++    # Test online/offline LDIF imports
++    #
++    inst = topology_st.standalone
++    inst.start()
++    backends = Backends(inst)
++    users_suffix = "ou=users,%s" % DEFAULT_SUFFIX
++    users_backend = 'users'
++    users_ldif = 'users_import.ldif'
++    groups_suffix = "ou=groups,%s" % DEFAULT_SUFFIX
++    groups_backend = 'groups'
++    groups_ldif = 'groups_import.ldif'
++    groups_entrycache = '200000000'
++    users_number = 2000
++    groups_number = 1000
++
++
++    # For priming the cache we just want to be fast
++    # taking the first value in the valueset is good
++    # whether the valueset is sorted or not
++    priming_user_rdn = "user0001"
++
++    # For performance testing, this is important to use
++    # user1000 rather then user0001
++    # Because user0001 is the first value in the valueset
++    # whether we use the sorted valuearray or non sorted
++    # valuearray the performance will be similar.
++    # With middle value user1000, the performance boost of
++    # the sorted valuearray will make the difference.
++    perf_user_rdn = "user1000"
++
++    # Step 1. Prepare the backends and tune the groups entrycache
++    try:
++        be_users = backends.create(properties={'parent': DEFAULT_SUFFIX, 'nsslapd-suffix': users_suffix, 'name': users_backend})
++        be_groups = backends.create(properties={'parent': DEFAULT_SUFFIX, 'nsslapd-suffix': groups_suffix, 'name': groups_backend})
++
++        # set the entry cache to 200Mb as the 1K groups of 2K users require at least 170Mb
++        be_groups.replace('nsslapd-cachememsize', groups_entrycache)
++    except:
++        raise
++
++    # Step 2. Generate a test ldif (10k users entries)
++    log.info("Generating users LDIF...")
++    ldif_dir = inst.get_ldif_dir()
++    users_import_ldif = "%s/%s" % (ldif_dir, users_ldif)
++    groups_import_ldif = "%s/%s" % (ldif_dir, groups_ldif)
++    dbgen_users(inst, users_number, users_import_ldif, suffix=users_suffix, generic=True, parent=users_suffix)
++
++    # Generate a test ldif (800 groups with 10k members) that fit in 700Mb entry cache
++    props = {
++        "name": "group",
++        "suffix": groups_suffix,
++        "parent": groups_suffix,
++        "number": groups_number,
++        "numMembers": users_number,
++        "createMembers": False,
++        "memberParent": users_suffix,
++        "membershipAttr": "uniquemember",
++    }
++    dbgen_groups(inst, groups_import_ldif, props)
++
++    # Step 3. Do the both offline imports
++    inst.stop()
++    if not inst.ldif2db(users_backend, None, None, None, users_import_ldif):
++        log.fatal('test_basic_import_export: Offline users import failed')
++        assert False
++    if not inst.ldif2db(groups_backend, None, None, None, groups_import_ldif):
++        log.fatal('test_basic_import_export: Offline groups import failed')
++        assert False
++    inst.start()
++
++    # Step 4. first prime the cache
++    # Just request the 'DN'. We are interested by the time of matching not by the time of transfert
++    entries = topology_st.standalone.search_s(groups_suffix, ldap.SCOPE_SUBTREE, "(&(objectclass=groupOfUniqueNames)(uniquemember=uid=%s,%s))" % (priming_user_rdn, users_suffix), ['dn'])
++    assert len(entries) == groups_number
++
++    # Step 5. Now do the real performance checking it should take less than a second
++    # Just request the 'DN'. We are interested by the time of matching not by the time of transfert
++    search_start = time.time()
++    entries = topology_st.standalone.search_s(groups_suffix, ldap.SCOPE_SUBTREE, "(&(objectclass=groupOfUniqueNames)(uniquemember=uid=%s,%s))" % (perf_user_rdn, users_suffix), ['dn'])
++    duration = time.time() - search_start
++    log.info("Duration of the search was %f", duration)
++
++    # Step 6. Gather the etime from the access log
++    inst.stop()
++    access_log = DirsrvAccessLog(inst)
++    search_result = access_log.match(".*RESULT err=0 tag=101 nentries=%s.*" % groups_number)
++    log.info("Found patterns are %s", search_result[0])
++    log.info("Found patterns are %s", search_result[1])
++    etime = float(search_result[1].split('etime=')[1])
++    log.info("Duration of the search from access log was %f", etime)
++    assert len(entries) == groups_number
++    assert (etime < 1)
++
+ if __name__ == '__main__':
+     # Run isolated
+     # -s for DEBUG mode
+diff --git a/ldap/servers/slapd/filterentry.c b/ldap/servers/slapd/filterentry.c
+index 2a7102828..4de4aa66e 100644
+--- a/ldap/servers/slapd/filterentry.c
++++ b/ldap/servers/slapd/filterentry.c
+@@ -296,7 +296,27 @@ test_ava_filter(
+         rc = -1;
+         for (; a != NULL; a = a->a_next) {
+             if (slapi_attr_type_cmp(ava->ava_type, a->a_type, SLAPI_TYPE_CMP_SUBTYPE) == 0) {
+-                rc = plugin_call_syntax_filter_ava(a, ftype, ava);
++                if ((ftype == LDAP_FILTER_EQUALITY) &&
++                    (slapi_attr_is_dn_syntax_type(a->a_type))) {
++                    /* This path is for a performance improvement */
++
++                    /* In case of equality filter we can get benefit of the
++                     * sorted valuearray (from valueset).
++                     * This improvement is limited to DN syntax attributes for
++                     * which the sorted valueset was designed.
++                     */
++                    Slapi_Value *sval = NULL;
++                    sval = slapi_value_new_berval(&ava->ava_value);
++                    if (slapi_valueset_find((const Slapi_Attr *)a, &a->a_present_values, sval)) {
++                        rc = 0;
++                    }
++                    slapi_value_free(&sval);
++                } else {
++                    /* When sorted valuearray optimization cannot be used
++                     * lets filter the value according to its syntax
++                     */
++                    rc = plugin_call_syntax_filter_ava(a, ftype, ava);
++                }
+                 if (rc == 0) {
+                     break;
+                 }
+-- 
+2.45.2
+
diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec
index 1c6939b..1cd6288 100644
--- a/SPECS/389-ds-base.spec
+++ b/SPECS/389-ds-base.spec
@@ -47,7 +47,7 @@ ExcludeArch: i686
 Summary:          389 Directory Server (base)
 Name:             389-ds-base
 Version:          2.4.5
-Release:          8%{?dist}
+Release:          9%{?dist}
 License:          GPL-3.0-or-later AND (0BSD OR Apache-2.0 OR MIT) AND (Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT) AND (Apache-2.0 OR BSL-1.0) AND (Apache-2.0 OR MIT OR Zlib) AND (Apache-2.0 OR MIT) AND (MIT OR Apache-2.0) AND Unicode-DFS-2016 AND (MIT OR Unlicense) AND Apache-2.0 AND BSD-3-Clause AND MIT AND MPL-2.0
 URL:              https://www.port389.org
 Conflicts:        selinux-policy-base < 3.9.8
@@ -282,11 +282,15 @@ Source2:          %{name}-devel.README
 Source3:          https://github.com/jemalloc/%{jemalloc_name}/releases/download/%{jemalloc_ver}/%{jemalloc_name}-%{jemalloc_ver}.tar.bz2
 %endif
 Source4:          389-ds-base.sysusers
-Patch0:           0001-Issue-3527-Support-HAProxy-and-Instance-on-the-same-.patch
-Patch1:           0002-Issue-6112-RFE-add-new-operation-note-for-MFA-authen.patch
-Patch2:           0003-Issue-6133-Move-slapi_pblock_set_flag_operation_note.patch
-Patch3:           0004-CVE-2024-2199.patch
-Patch4:           0005-CVE-2024-3657.patch
+Patch01:          0001-Issue-3527-Support-HAProxy-and-Instance-on-the-same-.patch
+Patch02:          0002-Issue-6112-RFE-add-new-operation-note-for-MFA-authen.patch
+Patch03:          0003-Issue-6133-Move-slapi_pblock_set_flag_operation_note.patch
+Patch04:          0004-CVE-2024-2199.patch
+Patch05:          0005-CVE-2024-3657.patch
+Patch06:          0006-CVE-2024-5953.patch
+Patch07:          0007-CVE-2024-6237.patch
+Patch08:          0008-Issue-5772-ONE-LEVEL-search-fails-to-return-sub-suff.patch
+Patch09:          0009-Issue-6172-RFE-improve-the-performance-of-evaluation.patch
 
 
 %description
@@ -730,6 +734,13 @@ exit 0
 %endif
 
 %changelog
+* Tue Jul 16 2024 James Chapman <jachapma@redhat.com> - 2.4.5-9
+- Bump version to 2.4.5-9
+- Resolves: RHEL-44323 - unauthenticated user can trigger a DoS by sending a specific extended search request
+- Resolves: RHEL-40945 - Malformed userPassword hash may cause Denial of Service
+- Resolves: RHEL-49457 - perf search result investigation for many large static groups and members 
+- Resolves: RHEL-49459 - subsuffix are not returned in one level scoped search
+
 * Fri May 31 2024 Viktor Ashirov <vashirov@redhat.com> - 2.4.5-8
 - Bump version to 2.4.5-8
 - Fix License tag