diff --git a/SOURCES/0014-Issue-6417-If-an-entry-RDN-is-identical-to-the-suffi.patch b/SOURCES/0014-Issue-6417-If-an-entry-RDN-is-identical-to-the-suffi.patch new file mode 100644 index 0000000..82b9cfc --- /dev/null +++ b/SOURCES/0014-Issue-6417-If-an-entry-RDN-is-identical-to-the-suffi.patch @@ -0,0 +1,55 @@ +From d1cd9a5675e2953b7c8034ebb87a434cdd3ce0c3 Mon Sep 17 00:00:00 2001 +From: tbordaz +Date: Mon, 2 Dec 2024 17:18:32 +0100 +Subject: [PATCH] Issue 6417 - If an entry RDN is identical to the suffix, then + Entryrdn gets broken during a reindex (#6418) + +Bug description: + During a reindex, the entryrdn index is built at the end from + each entry in the suffix. + If one entry has a RDN that is identical to the suffix DN, + then entryrdn_lookup_dn may erroneously return the suffix DN + as the DN of the entry. + +Fix description: + When the lookup entry has no parent (because index is under + work) the loop lookup the entry using the RDN. + If this RDN matches the suffix DN, then it exits from the loop + with the suffix DN. + Before exiting it checks that the original lookup entryID + is equal to suffix entryID. If it does not match + the function fails and then the DN from the entry will be + built from id2enty + +fixes: #6417 + +Reviewed by: Pierre Rogier, Simon Pichugin (Thanks !!!) +--- + ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +index 5797dd779..83b041192 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +@@ -1224,7 +1224,16 @@ entryrdn_lookup_dn(backend *be, + } + goto bail; + } +- maybesuffix = 1; ++ if (workid == 1) { ++ /* The loop (workid) iterates from the starting 'id' ++ * up to the suffix ID (i.e. '1'). ++ * A corner case (#6417) is if an entry, on the path ++ * 'id' -> suffix, has the same RDN than the suffix. ++ * In order to erroneously believe the loop hits the suffix ++ * we need to check that 'workid' is '1' (suffix) ++ */ ++ maybesuffix = 1; ++ } + } else { + _entryrdn_cursor_print_error("entryrdn_lookup_dn", + key.data, data.size, data.ulen, rc); +-- +2.48.0 + diff --git a/SOURCES/0015-Issue-6224-d2entry-Could-not-open-id2entry-err-0-at-.patch b/SOURCES/0015-Issue-6224-d2entry-Could-not-open-id2entry-err-0-at-.patch new file mode 100644 index 0000000..14a441c --- /dev/null +++ b/SOURCES/0015-Issue-6224-d2entry-Could-not-open-id2entry-err-0-at-.patch @@ -0,0 +1,267 @@ +From 9b2fc77a36156ea987dcea6e2043f8e4c4a6b259 Mon Sep 17 00:00:00 2001 +From: progier389 +Date: Tue, 18 Jun 2024 14:21:07 +0200 +Subject: [PATCH] Issue 6224 - d2entry - Could not open id2entry err 0 - at + startup when having sub-suffixes (#6225) + +Problem:: d2entry - Could not open id2entry err 0 is logged at startup when having sub-suffixes +Reason: The slapi_exist_referral internal search access a backend that is not yet started. +Solution: Limit the internal search to a single backend + +Issue: #6224 + +Reviewed by: @droideck Thanks! + +(cherry picked from commit 796f703021e961fdd8cbc53b4ad4e20258af0e96) +--- + .../tests/suites/ds_logs/ds_logs_test.py | 1 + + .../suites/mapping_tree/regression_test.py | 161 +++++++++++++++++- + ldap/servers/slapd/backend.c | 7 +- + 3 files changed, 159 insertions(+), 10 deletions(-) + +diff --git a/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py b/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py +index 812936c62..84a9c6ec8 100644 +--- a/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py ++++ b/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py +@@ -1222,6 +1222,7 @@ def test_referral_check(topology_st, request): + + request.addfinalizer(fin) + ++<<<<<<< HEAD + def test_referral_subsuffix(topology_st, request): + """Test the results of an inverted parent suffix definition in the configuration. + +diff --git a/dirsrvtests/tests/suites/mapping_tree/regression_test.py b/dirsrvtests/tests/suites/mapping_tree/regression_test.py +index 99d4a1d5f..689ff9f59 100644 +--- a/dirsrvtests/tests/suites/mapping_tree/regression_test.py ++++ b/dirsrvtests/tests/suites/mapping_tree/regression_test.py +@@ -11,10 +11,14 @@ import ldap + import logging + import os + import pytest ++import time + from lib389.backend import Backends, Backend ++from lib389._constants import HOST_STANDALONE, PORT_STANDALONE, DN_DM, PW_DM + from lib389.dbgen import dbgen_users + from lib389.mappingTree import MappingTrees + from lib389.topologies import topology_st ++from lib389.referral import Referrals, Referral ++ + + try: + from lib389.backend import BackendSuffixView +@@ -31,14 +35,26 @@ else: + logging.getLogger(__name__).setLevel(logging.INFO) + log = logging.getLogger(__name__) + ++PARENT_SUFFIX = "dc=parent" ++CHILD1_SUFFIX = f"dc=child1,{PARENT_SUFFIX}" ++CHILD2_SUFFIX = f"dc=child2,{PARENT_SUFFIX}" ++ ++PARENT_REFERRAL_DN = f"cn=ref,ou=People,{PARENT_SUFFIX}" ++CHILD1_REFERRAL_DN = f"cn=ref,ou=people,{CHILD1_SUFFIX}" ++CHILD2_REFERRAL_DN = f"cn=ref,ou=people,{CHILD2_SUFFIX}" ++ ++REFERRAL_CHECK_PEDIOD = 7 ++ ++ ++ + BESTRUCT = [ +- { "bename" : "parent", "suffix": "dc=parent" }, +- { "bename" : "child1", "suffix": "dc=child1,dc=parent" }, +- { "bename" : "child2", "suffix": "dc=child2,dc=parent" }, ++ { "bename" : "parent", "suffix": PARENT_SUFFIX }, ++ { "bename" : "child1", "suffix": CHILD1_SUFFIX }, ++ { "bename" : "child2", "suffix": CHILD2_SUFFIX }, + ] + + +-@pytest.fixture(scope="function") ++@pytest.fixture(scope="module") + def topo(topology_st, request): + bes = [] + +@@ -50,6 +66,9 @@ def topo(topology_st, request): + request.addfinalizer(fin) + + inst = topology_st.standalone ++ # Reduce nsslapd-referral-check-period to accelerate test ++ topology_st.standalone.config.set("nsslapd-referral-check-period", str(REFERRAL_CHECK_PEDIOD)) ++ + ldif_files = {} + for d in BESTRUCT: + bename = d['bename'] +@@ -76,14 +95,13 @@ def topo(topology_st, request): + inst.start() + return topology_st + +-# Parameters for test_change_repl_passwd +-EXPECTED_ENTRIES = (("dc=parent", 39), ("dc=child1,dc=parent", 13), ("dc=child2,dc=parent", 13)) ++# Parameters for test_sub_suffixes + @pytest.mark.parametrize( + "orphan_param", + [ +- pytest.param( ( True, { "dc=parent": 2, "dc=child1,dc=parent":1, "dc=child2,dc=parent":1}), id="orphan-is-true" ), +- pytest.param( ( False, { "dc=parent": 3, "dc=child1,dc=parent":1, "dc=child2,dc=parent":1}), id="orphan-is-false" ), +- pytest.param( ( None, { "dc=parent": 3, "dc=child1,dc=parent":1, "dc=child2,dc=parent":1}), id="no-orphan" ), ++ pytest.param( ( True, { PARENT_SUFFIX: 2, CHILD1_SUFFIX:1, CHILD2_SUFFIX:1}), id="orphan-is-true" ), ++ pytest.param( ( False, { PARENT_SUFFIX: 3, CHILD1_SUFFIX:1, CHILD2_SUFFIX:1}), id="orphan-is-false" ), ++ pytest.param( ( None, { PARENT_SUFFIX: 3, CHILD1_SUFFIX:1, CHILD2_SUFFIX:1}), id="no-orphan" ), + ], + ) + +@@ -128,3 +146,128 @@ def test_sub_suffixes(topo, orphan_param): + 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) ++ ++ ++def test_sub_suffixes_errlog(topo): ++ """ check the entries found on suffix/sub-suffix ++ used int ++ ++ :id: 1db9d52e-28de-11ef-b286-482ae39447e5 ++ :feature: mapping-tree ++ :setup: Standalone instance with 3 additional backends: ++ dc=parent, dc=child1,dc=parent, dc=childr21,dc=parent ++ :steps: ++ 1. Check that id2entry error message is not in the error log. ++ :expectedresults: ++ 1. Success ++ """ ++ inst = topo.standalone ++ assert not inst.searchErrorsLog('id2entry - Could not open id2entry err 0') ++ ++ ++# Parameters for test_referral_subsuffix: ++# a tuple pair containing: ++# - list of referral dn that must be created ++# - dict of searches basedn: expected_number_of_referrals ++@pytest.mark.parametrize( ++ "parameters", ++ [ ++ pytest.param( ((PARENT_REFERRAL_DN, CHILD1_REFERRAL_DN), {PARENT_SUFFIX: 2, CHILD1_SUFFIX:1, CHILD2_SUFFIX:0}), id="Both"), ++ pytest.param( ((PARENT_REFERRAL_DN,), {PARENT_SUFFIX: 1, CHILD1_SUFFIX:0, CHILD2_SUFFIX:0}) , id="Parent"), ++ pytest.param( ((CHILD1_REFERRAL_DN,), {PARENT_SUFFIX: 1, CHILD1_SUFFIX:1, CHILD2_SUFFIX:0}) , id="Child"), ++ pytest.param( ((), {PARENT_SUFFIX: 0, CHILD1_SUFFIX:0, CHILD2_SUFFIX:0}), id="None"), ++ ]) ++ ++def test_referral_subsuffix(topo, request, parameters): ++ """Test the results of an inverted parent suffix definition in the configuration. ++ ++ For more details see: ++ https://www.port389.org/docs/389ds/design/mapping_tree_assembly.html ++ ++ :id: 4e111a22-2a5d-11ef-a890-482ae39447e5 ++ :feature: referrals ++ :setup: Standalone instance with 3 additional backends: ++ dc=parent, dc=child1,dc=parent, dc=childr21,dc=parent ++ ++ :setup: Standalone instance ++ :parametrized: yes ++ :steps: ++ refs,searches = referrals ++ ++ 1. Create the referrals according to the current parameter ++ 2. Wait enough time so they get detected ++ 3. For each search base dn, in the current parameter, perform the two following steps ++ 4. In 3. loop: Perform a search with provided base dn ++ 5. In 3. loop: Check that the number of returned referrals is the expected one. ++ ++ :expectedresults: ++ all steps succeeds ++ """ ++ inst = topo.standalone ++ ++ def fin(): ++ log.info('Deleting all referrals') ++ for ref in Referrals(inst, PARENT_SUFFIX).list(): ++ ref.delete() ++ ++ # Set cleanup callback ++ if DEBUGGING: ++ request.addfinalizer(fin) ++ ++ # Remove all referrals ++ fin() ++ # Add requested referrals ++ for dn in parameters[0]: ++ refs = Referral(inst, dn=dn) ++ refs.create(basedn=dn, properties={ 'cn': 'ref', 'ref': f'ldap://remote/{dn}'}) ++ # Wait that the internal search detects the referrals ++ time.sleep(REFERRAL_CHECK_PEDIOD + 1) ++ # Open a test connection ++ ldc = ldap.initialize(f"ldap://{HOST_STANDALONE}:{PORT_STANDALONE}") ++ ldc.set_option(ldap.OPT_REFERRALS,0) ++ ldc.simple_bind_s(DN_DM,PW_DM) ++ ++ # For each search base dn: ++ for basedn,nbref in parameters[1].items(): ++ log.info(f"Referrals are: {parameters[0]}") ++ # Perform a search with provided base dn ++ result = ldc.search_s(basedn, ldap.SCOPE_SUBTREE, filterstr="(ou=People)") ++ found_dns = [ dn for dn,entry in result if dn is not None ] ++ found_refs = [ entry for dn,entry in result if dn is None ] ++ log.info(f"Search on {basedn} returned {found_dns} and {found_refs}") ++ # Check that the number of returned referrals is the expected one. ++ log.info(f"Search returned {len(found_refs)} referrals. {nbref} are expected.") ++ assert len(found_refs) == nbref ++ ldc.unbind() +diff --git a/ldap/servers/slapd/backend.c b/ldap/servers/slapd/backend.c +index 498f683b1..f86b0b9b6 100644 +--- a/ldap/servers/slapd/backend.c ++++ b/ldap/servers/slapd/backend.c +@@ -230,12 +230,17 @@ slapi_exist_referral(Slapi_Backend *be) + + /* search for ("smart") referral entries */ + search_pb = slapi_pblock_new(); +- server_ctrls = (LDAPControl **) slapi_ch_calloc(2, sizeof (LDAPControl *)); ++ server_ctrls = (LDAPControl **) slapi_ch_calloc(3, sizeof (LDAPControl *)); + server_ctrls[0] = (LDAPControl *) slapi_ch_malloc(sizeof (LDAPControl)); + server_ctrls[0]->ldctl_oid = slapi_ch_strdup(LDAP_CONTROL_MANAGEDSAIT); + server_ctrls[0]->ldctl_value.bv_val = NULL; + server_ctrls[0]->ldctl_value.bv_len = 0; + server_ctrls[0]->ldctl_iscritical = '\0'; ++ server_ctrls[1] = (LDAPControl *) slapi_ch_malloc(sizeof (LDAPControl)); ++ server_ctrls[1]->ldctl_oid = slapi_ch_strdup(MTN_CONTROL_USE_ONE_BACKEND_EXT_OID); ++ server_ctrls[1]->ldctl_value.bv_val = NULL; ++ server_ctrls[1]->ldctl_value.bv_len = 0; ++ server_ctrls[1]->ldctl_iscritical = '\0'; + slapi_search_internal_set_pb(search_pb, suffix, LDAP_SCOPE_SUBTREE, + filter, NULL, 0, server_ctrls, NULL, + (void *) plugin_get_default_component_id(), 0); +-- +2.48.0 + diff --git a/SOURCES/0016-Issue-6224-Fix-merge-issue-in-389-ds-base-2.1-for-ds.patch b/SOURCES/0016-Issue-6224-Fix-merge-issue-in-389-ds-base-2.1-for-ds.patch new file mode 100644 index 0000000..fbfadd4 --- /dev/null +++ b/SOURCES/0016-Issue-6224-Fix-merge-issue-in-389-ds-base-2.1-for-ds.patch @@ -0,0 +1,32 @@ +From ab06b3cebbe0287ef557c0307ca2ee86fe8cb761 Mon Sep 17 00:00:00 2001 +From: progier389 +Date: Thu, 21 Nov 2024 16:26:02 +0100 +Subject: [PATCH] Issue 6224 - Fix merge issue in 389-ds-base-2.1 for + ds_log_test.py (#6414) + +Fix a merge issue during cherry-pick over 389-ds-base-2.1 and 389-ds-base-1.4.3 branches + +Issue: #6224 + +Reviewed by: @mreynolds389 + +(cherry picked from commit 2b541c64b8317209e4dafa4f82918d714039907c) +--- + dirsrvtests/tests/suites/ds_logs/ds_logs_test.py | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py b/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py +index 84a9c6ec8..812936c62 100644 +--- a/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py ++++ b/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py +@@ -1222,7 +1222,6 @@ def test_referral_check(topology_st, request): + + request.addfinalizer(fin) + +-<<<<<<< HEAD + def test_referral_subsuffix(topology_st, request): + """Test the results of an inverted parent suffix definition in the configuration. + +-- +2.48.0 + diff --git a/SOURCES/0017-Issue-6224-Remove-test_referral_subsuffix-from-ds_lo.patch b/SOURCES/0017-Issue-6224-Remove-test_referral_subsuffix-from-ds_lo.patch new file mode 100644 index 0000000..32b152d --- /dev/null +++ b/SOURCES/0017-Issue-6224-Remove-test_referral_subsuffix-from-ds_lo.patch @@ -0,0 +1,214 @@ +From 3fe2cf7cdedcdf5cafb59867e52a1fbe4a643571 Mon Sep 17 00:00:00 2001 +From: Masahiro Matsuya +Date: Fri, 20 Dec 2024 22:37:15 +0900 +Subject: [PATCH] Issue 6224 - Remove test_referral_subsuffix from + ds_logs_test.py (#6456) + +Bug Description: + +test_referral_subsuffix test was removed from main branch and some other +ones for higher versions. But, it was not removed from 389-ds-base-1.4.3 +and 389-ds-base-2.1. The test doesn't work anymore with the fix for +Issue 6224, because the added new control limited one backend for internal +search. The test should be removed. + +Fix Description: + +remove the test from ds_logs_test.py + +relates: https://github.com/389ds/389-ds-base/issues/6224 +--- + .../tests/suites/ds_logs/ds_logs_test.py | 177 ------------------ + 1 file changed, 177 deletions(-) + +diff --git a/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py b/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py +index 812936c62..84d721756 100644 +--- a/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py ++++ b/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py +@@ -1222,183 +1222,6 @@ def test_referral_check(topology_st, request): + + request.addfinalizer(fin) + +-def test_referral_subsuffix(topology_st, request): +- """Test the results of an inverted parent suffix definition in the configuration. +- +- For more details see: +- https://www.port389.org/docs/389ds/design/mapping_tree_assembly.html +- +- :id: 4faf210a-4fde-4e4f-8834-865bdc8f4d37 +- :setup: Standalone instance +- :steps: +- 1. First create two Backends, without mapping trees. +- 2. create the mapping trees for these backends +- 3. reduce nsslapd-referral-check-period to accelerate test +- 4. Remove error log file +- 5. Create a referral entry on parent suffix +- 6. Check that the server detected the referral +- 7. Delete the referral entry +- 8. Check that the server detected the deletion of the referral +- 9. Remove error log file +- 10. Create a referral entry on child suffix +- 11. Check that the server detected the referral on both parent and child suffixes +- 12. Delete the referral entry +- 13. Check that the server detected the deletion of the referral on both parent and child suffixes +- 14. Remove error log file +- 15. Create a referral entry on parent suffix +- 16. Check that the server detected the referral on both parent and child suffixes +- 17. Delete the child referral entry +- 18. Check that the server detected the deletion of the referral on child suffix but not on parent suffix +- 19. Delete the parent referral entry +- 20. Check that the server detected the deletion of the referral parent suffix +- +- :expectedresults: +- all steps succeeds +- """ +- inst = topology_st.standalone +- # Step 1 First create two Backends, without mapping trees. +- PARENT_SUFFIX='dc=parent,dc=com' +- CHILD_SUFFIX='dc=child,%s' % PARENT_SUFFIX +- be1 = create_backend(inst, 'Parent', PARENT_SUFFIX) +- be2 = create_backend(inst, 'Child', CHILD_SUFFIX) +- # Step 2 create the mapping trees for these backends +- mts = MappingTrees(inst) +- mt1 = mts.create(properties={ +- 'cn': PARENT_SUFFIX, +- 'nsslapd-state': 'backend', +- 'nsslapd-backend': 'Parent', +- }) +- mt2 = mts.create(properties={ +- 'cn': CHILD_SUFFIX, +- 'nsslapd-state': 'backend', +- 'nsslapd-backend': 'Child', +- 'nsslapd-parent-suffix': PARENT_SUFFIX, +- }) +- +- dc_ex = Domain(inst, dn=PARENT_SUFFIX) +- assert dc_ex.exists() +- +- dc_st = Domain(inst, dn=CHILD_SUFFIX) +- assert dc_st.exists() +- +- # Step 3 reduce nsslapd-referral-check-period to accelerate test +- # requires a restart done on step 4 +- REFERRAL_CHECK=7 +- topology_st.standalone.config.set("nsslapd-referral-check-period", str(REFERRAL_CHECK)) +- +- # Check that if we create a referral at parent level +- # - referral is detected at parent backend +- # - referral is not detected at child backend +- +- # Step 3 Remove error log file +- topology_st.standalone.stop() +- lpath = topology_st.standalone.ds_error_log._get_log_path() +- os.unlink(lpath) +- topology_st.standalone.start() +- +- # Step 4 Create a referral entry on parent suffix +- rs_parent = Referrals(topology_st.standalone, PARENT_SUFFIX) +- +- referral_entry_parent = rs_parent.create(properties={ +- 'cn': 'testref', +- 'ref': 'ldap://localhost:38901/ou=People,dc=example,dc=com' +- }) +- +- # Step 5 Check that the server detected the referral +- time.sleep(REFERRAL_CHECK + 1) +- assert topology_st.standalone.ds_error_log.match('.*slapd_daemon - New referral entries are detected under %s.*' % PARENT_SUFFIX) +- assert not topology_st.standalone.ds_error_log.match('.*slapd_daemon - New referral entries are detected under %s.*' % CHILD_SUFFIX) +- assert not topology_st.standalone.ds_error_log.match('.*slapd_daemon - No more referral entry under %s' % PARENT_SUFFIX) +- +- # Step 6 Delete the referral entry +- referral_entry_parent.delete() +- +- # Step 7 Check that the server detected the deletion of the referral +- time.sleep(REFERRAL_CHECK + 1) +- assert topology_st.standalone.ds_error_log.match('.*slapd_daemon - No more referral entry under %s' % PARENT_SUFFIX) +- +- # Check that if we create a referral at child level +- # - referral is detected at parent backend +- # - referral is detected at child backend +- +- # Step 8 Remove error log file +- topology_st.standalone.stop() +- lpath = topology_st.standalone.ds_error_log._get_log_path() +- os.unlink(lpath) +- topology_st.standalone.start() +- +- # Step 9 Create a referral entry on child suffix +- rs_child = Referrals(topology_st.standalone, CHILD_SUFFIX) +- referral_entry_child = rs_child.create(properties={ +- 'cn': 'testref', +- 'ref': 'ldap://localhost:38901/ou=People,dc=example,dc=com' +- }) +- +- # Step 10 Check that the server detected the referral on both parent and child suffixes +- time.sleep(REFERRAL_CHECK + 1) +- assert topology_st.standalone.ds_error_log.match('.*slapd_daemon - New referral entries are detected under %s.*' % PARENT_SUFFIX) +- assert topology_st.standalone.ds_error_log.match('.*slapd_daemon - New referral entries are detected under %s.*' % CHILD_SUFFIX) +- assert not topology_st.standalone.ds_error_log.match('.*slapd_daemon - No more referral entry under %s' % CHILD_SUFFIX) +- +- # Step 11 Delete the referral entry +- referral_entry_child.delete() +- +- # Step 12 Check that the server detected the deletion of the referral on both parent and child suffixes +- time.sleep(REFERRAL_CHECK + 1) +- assert topology_st.standalone.ds_error_log.match('.*slapd_daemon - No more referral entry under %s' % PARENT_SUFFIX) +- assert topology_st.standalone.ds_error_log.match('.*slapd_daemon - No more referral entry under %s' % CHILD_SUFFIX) +- +- # Check that if we create a referral at child level and parent level +- # - referral is detected at parent backend +- # - referral is detected at child backend +- +- # Step 13 Remove error log file +- topology_st.standalone.stop() +- lpath = topology_st.standalone.ds_error_log._get_log_path() +- os.unlink(lpath) +- topology_st.standalone.start() +- +- # Step 14 Create a referral entry on parent suffix +- # Create a referral entry on child suffix +- referral_entry_parent = rs_parent.create(properties={ +- 'cn': 'testref', +- 'ref': 'ldap://localhost:38901/ou=People,dc=example,dc=com' +- }) +- referral_entry_child = rs_child.create(properties={ +- 'cn': 'testref', +- 'ref': 'ldap://localhost:38901/ou=People,dc=example,dc=com' +- }) +- +- # Step 15 Check that the server detected the referral on both parent and child suffixes +- time.sleep(REFERRAL_CHECK + 1) +- assert topology_st.standalone.ds_error_log.match('.*slapd_daemon - New referral entries are detected under %s.*' % PARENT_SUFFIX) +- assert topology_st.standalone.ds_error_log.match('.*slapd_daemon - New referral entries are detected under %s.*' % CHILD_SUFFIX) +- assert not topology_st.standalone.ds_error_log.match('.*slapd_daemon - No more referral entry under %s' % CHILD_SUFFIX) +- +- # Step 16 Delete the child referral entry +- referral_entry_child.delete() +- +- # Step 17 Check that the server detected the deletion of the referral on child suffix but not on parent suffix +- time.sleep(REFERRAL_CHECK + 1) +- assert topology_st.standalone.ds_error_log.match('.*slapd_daemon - No more referral entry under %s' % CHILD_SUFFIX) +- assert not topology_st.standalone.ds_error_log.match('.*slapd_daemon - No more referral entry under %s' % PARENT_SUFFIX) +- +- # Step 18 Delete the parent referral entry +- referral_entry_parent.delete() +- +- # Step 19 Check that the server detected the deletion of the referral parent suffix +- time.sleep(REFERRAL_CHECK + 1) +- assert topology_st.standalone.ds_error_log.match('.*slapd_daemon - No more referral entry under %s' % PARENT_SUFFIX) +- +- def fin(): +- log.info('Deleting referral') +- try: +- referral_entry_parent.delete() +- referral.entry_child.delete() +- except: +- pass +- +- request.addfinalizer(fin) + + def test_missing_backend_suffix(topology_st, request): + """Test that the server does not crash if a backend has no suffix +-- +2.48.0 + diff --git a/SOURCES/0018-Issue-6417-2nd-If-an-entry-RDN-is-identical-to-the-s.patch b/SOURCES/0018-Issue-6417-2nd-If-an-entry-RDN-is-identical-to-the-s.patch new file mode 100644 index 0000000..4f44c48 --- /dev/null +++ b/SOURCES/0018-Issue-6417-2nd-If-an-entry-RDN-is-identical-to-the-s.patch @@ -0,0 +1,90 @@ +From 4121ffe7a44fbacf513758661e71e483eb11ee3c Mon Sep 17 00:00:00 2001 +From: tbordaz +Date: Mon, 6 Jan 2025 14:00:39 +0100 +Subject: [PATCH] Issue 6417 - (2nd) If an entry RDN is identical to the + suffix, then Entryrdn gets broken during a reindex (#6460) + +Bug description: + The primary fix has a flaw as it assumes that the + suffix ID is '1'. + If the RUV entry is the first entry of the database + the server loops indefinitely + +Fix description: + Read the suffix ID from the entryrdn index + +fixes: #6417 + +Reviewed by: Pierre Rogier (also reviewed the first fix) +--- + .../suites/replication/regression_m2_test.py | 9 +++++++++ + ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 19 ++++++++++++++++++- + 2 files changed, 27 insertions(+), 1 deletion(-) + +diff --git a/dirsrvtests/tests/suites/replication/regression_m2_test.py b/dirsrvtests/tests/suites/replication/regression_m2_test.py +index abac46ada..72d4b9f89 100644 +--- a/dirsrvtests/tests/suites/replication/regression_m2_test.py ++++ b/dirsrvtests/tests/suites/replication/regression_m2_test.py +@@ -1010,6 +1010,15 @@ def test_online_reinit_may_hang(topo_with_sigkill): + """ + M1 = topo_with_sigkill.ms["supplier1"] + M2 = topo_with_sigkill.ms["supplier2"] ++ ++ # The RFE 5367 (when enabled) retrieves the DN ++ # from the dncache. This hides an issue ++ # with primary fix for 6417. ++ # We need to disable the RFE to verify that the primary ++ # fix is properly fixed. ++ if ds_is_newer('2.3.1'): ++ M1.config.replace('nsslapd-return-original-entrydn', 'off') ++ + M1.stop() + ldif_file = '%s/supplier1.ldif' % M1.get_ldif_dir() + M1.db2ldif(bename=DEFAULT_BENAME, suffixes=[DEFAULT_SUFFIX], +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +index 83b041192..1bbb6252a 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +@@ -1115,6 +1115,7 @@ entryrdn_lookup_dn(backend *be, + rdn_elem *elem = NULL; + int maybesuffix = 0; + int db_retry = 0; ++ ID suffix_id = 1; + + slapi_log_err(SLAPI_LOG_TRACE, "entryrdn_lookup_dn", + "--> entryrdn_lookup_dn\n"); +@@ -1175,6 +1176,22 @@ entryrdn_lookup_dn(backend *be, + /* Setting the bulk fetch buffer */ + data.flags = DB_DBT_MALLOC; + ++ /* Just in case the suffix ID is not '1' retrieve it from the database */ ++ keybuf = slapi_ch_strdup(slapi_sdn_get_ndn(be->be_suffix)); ++ dblayer_value_set(be, &key, keybuf, strlen(keybuf) + 1); ++ rc = dblayer_cursor_op(&ctx.cursor, DBI_OP_MOVE_TO_KEY, &key, &data); ++ if (rc) { ++ slapi_log_err(SLAPI_LOG_WARNING, "entryrdn_lookup_dn", ++ "Fails to retrieve the ID of suffix %s - keep the default value '%d'\n", ++ slapi_sdn_get_ndn(be->be_suffix), ++ suffix_id); ++ } else { ++ elem = (rdn_elem *)data.data; ++ suffix_id = id_stored_to_internal(elem->rdn_elem_id); ++ } ++ dblayer_value_free(be, &data); ++ dblayer_value_free(be, &key); ++ + do { + /* Setting up a key for the node to get its parent */ + slapi_ch_free_string(&keybuf); +@@ -1224,7 +1241,7 @@ entryrdn_lookup_dn(backend *be, + } + goto bail; + } +- if (workid == 1) { ++ if (workid == suffix_id) { + /* The loop (workid) iterates from the starting 'id' + * up to the suffix ID (i.e. '1'). + * A corner case (#6417) is if an entry, on the path +-- +2.48.0 + diff --git a/SOURCES/0019-Issue-6417-2nd-fix-typo.patch b/SOURCES/0019-Issue-6417-2nd-fix-typo.patch new file mode 100644 index 0000000..cbba71d --- /dev/null +++ b/SOURCES/0019-Issue-6417-2nd-fix-typo.patch @@ -0,0 +1,40 @@ +From 1ffcc9aa9a397180fe35283ee61b164471d073fb Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Tue, 7 Jan 2025 10:01:51 +0100 +Subject: [PATCH] Issue 6417 - (2nd) fix typo + +--- + ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +index 1bbb6252a..e2b8273a2 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +@@ -1178,8 +1178,10 @@ entryrdn_lookup_dn(backend *be, + + /* Just in case the suffix ID is not '1' retrieve it from the database */ + keybuf = slapi_ch_strdup(slapi_sdn_get_ndn(be->be_suffix)); +- dblayer_value_set(be, &key, keybuf, strlen(keybuf) + 1); +- rc = dblayer_cursor_op(&ctx.cursor, DBI_OP_MOVE_TO_KEY, &key, &data); ++ key.data = keybuf; ++ key.size = key.ulen = strlen(keybuf) + 1; ++ key.flags = DB_DBT_USERMEM; ++ rc = cursor->c_get(cursor, &key, &data, DB_SET); + if (rc) { + slapi_log_err(SLAPI_LOG_WARNING, "entryrdn_lookup_dn", + "Fails to retrieve the ID of suffix %s - keep the default value '%d'\n", +@@ -1189,8 +1191,8 @@ entryrdn_lookup_dn(backend *be, + elem = (rdn_elem *)data.data; + suffix_id = id_stored_to_internal(elem->rdn_elem_id); + } +- dblayer_value_free(be, &data); +- dblayer_value_free(be, &key); ++ slapi_ch_free(&data.data); ++ slapi_ch_free_string(&keybuf); + + do { + /* Setting up a key for the node to get its parent */ +-- +2.48.0 + diff --git a/SOURCES/0020-Issue-6417-3rd-If-an-entry-RDN-is-identical-to-the-s.patch b/SOURCES/0020-Issue-6417-3rd-If-an-entry-RDN-is-identical-to-the-s.patch new file mode 100644 index 0000000..54ffb8e --- /dev/null +++ b/SOURCES/0020-Issue-6417-3rd-If-an-entry-RDN-is-identical-to-the-s.patch @@ -0,0 +1,75 @@ +From 9e1284122a929fe14633a2aa6e2de4d72891f98f Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Mon, 13 Jan 2025 17:41:18 +0100 +Subject: [PATCH] Issue 6417 - (3rd) If an entry RDN is identical to the + suffix, then Entryrdn gets broken during a reindex (#6480) + +Bug description: + The previous fix had a flaw. + In case entryrdn_lookup_dn is called with an undefined suffix + the lookup of the suffix trigger a crash. + For example it can occur during internal search of an + unexisting map (view plugin). + The issue exists in all releases but is hidden since 2.3. + +Fix description: + testing the suffix is defined + +fixes: #6417 + +Reviewed by: Pierre Rogier (THnaks !) +--- + ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 36 +++++++++++--------- + 1 file changed, 20 insertions(+), 16 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +index e2b8273a2..01c77156f 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +@@ -1176,23 +1176,27 @@ entryrdn_lookup_dn(backend *be, + /* Setting the bulk fetch buffer */ + data.flags = DB_DBT_MALLOC; + +- /* Just in case the suffix ID is not '1' retrieve it from the database */ +- keybuf = slapi_ch_strdup(slapi_sdn_get_ndn(be->be_suffix)); +- key.data = keybuf; +- key.size = key.ulen = strlen(keybuf) + 1; +- key.flags = DB_DBT_USERMEM; +- rc = cursor->c_get(cursor, &key, &data, DB_SET); +- if (rc) { +- slapi_log_err(SLAPI_LOG_WARNING, "entryrdn_lookup_dn", +- "Fails to retrieve the ID of suffix %s - keep the default value '%d'\n", +- slapi_sdn_get_ndn(be->be_suffix), +- suffix_id); +- } else { +- elem = (rdn_elem *)data.data; +- suffix_id = id_stored_to_internal(elem->rdn_elem_id); ++ /* Just in case the suffix ID is not '1' retrieve it from the database ++ * if the suffix is not defined suffix_id remains '1' ++ */ ++ if (be->be_suffix) { ++ keybuf = slapi_ch_strdup(slapi_sdn_get_ndn(be->be_suffix)); ++ key.data = keybuf; ++ key.size = key.ulen = strlen(keybuf) + 1; ++ key.flags = DB_DBT_USERMEM; ++ rc = cursor->c_get(cursor, &key, &data, DB_SET); ++ if (rc) { ++ slapi_log_err(SLAPI_LOG_WARNING, "entryrdn_lookup_dn", ++ "Fails to retrieve the ID of suffix %s - keep the default value '%d'\n", ++ slapi_sdn_get_ndn(be->be_suffix), ++ suffix_id); ++ } else { ++ elem = (rdn_elem *) data.data; ++ suffix_id = id_stored_to_internal(elem->rdn_elem_id); ++ } ++ slapi_ch_free(&data.data); ++ slapi_ch_free_string(&keybuf); + } +- slapi_ch_free(&data.data); +- slapi_ch_free_string(&keybuf); + + do { + /* Setting up a key for the node to get its parent */ +-- +2.48.0 + diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec index d6a5605..0e9fecc 100644 --- a/SPECS/389-ds-base.spec +++ b/SPECS/389-ds-base.spec @@ -48,7 +48,7 @@ ExcludeArch: i686 Summary: 389 Directory Server (base) Name: 389-ds-base Version: 1.4.3.39 -Release: %{?relprefix}9%{?prerel}%{?dist} +Release: %{?relprefix}10%{?prerel}%{?dist} License: GPLv3+ and (ASL 2.0 or MIT) URL: https://www.port389.org Group: System Environment/Daemons @@ -306,7 +306,13 @@ Patch10: 0010-Issue-6103-New-connection-timeout-error-breaks-error.patc Patch11: 0011-Issue-6172-RFE-improve-the-performance-of-evaluation.patch Patch12: 0012-Security-fix-for-CVE-2024-5953.patch Patch13: 0013-Issue-4778-Add-COMPACT_CL5-task-to-dsconf-replicatio.patch - +Patch14: 0014-Issue-6417-If-an-entry-RDN-is-identical-to-the-suffi.patch +Patch15: 0015-Issue-6224-d2entry-Could-not-open-id2entry-err-0-at-.patch +Patch16: 0016-Issue-6224-Fix-merge-issue-in-389-ds-base-2.1-for-ds.patch +Patch17: 0017-Issue-6224-Remove-test_referral_subsuffix-from-ds_lo.patch +Patch18: 0018-Issue-6417-2nd-If-an-entry-RDN-is-identical-to-the-s.patch +Patch19: 0019-Issue-6417-2nd-fix-typo.patch +Patch20: 0020-Issue-6417-3rd-If-an-entry-RDN-is-identical-to-the-s.patch %description 389 Directory Server is an LDAPv3 compliant server. The base package includes the LDAP server and command line utilities for server administration. @@ -435,7 +441,7 @@ A cockpit UI Plugin for configuring and administering the 389 Directory Server %prep %autosetup -p1 -n %{name}-%{version}%{?prerel} %if %{use_rust} -tar xvzf %{SOURCE4} +tar xzf %{SOURCE4} cp %{SOURCE5} src/Cargo.lock %endif %if %{bundle_jemalloc} @@ -927,6 +933,10 @@ exit 0 %doc README.md %changelog +* Fri Jan 17 2025 Viktor Ashirov - 1.4.3.39-10 +- Resolves: RHEL-69822 - "Duplicated DN detected" errors when creating indexes or importing entries. [rhel-8.10.z] +- Resolves: RHEL-71215 - Sub suffix causes "id2entry - Could not open id2entry err 0" error when the Directory Server starts [rhel-8.10.z] + * Fri Nov 22 2024 Viktor Ashirov - 1.4.3.39-9 - Resolves: RHEL-64360 - Cannot compact the replication changelog using dsconf. [rhel-8.10.z]