From 4c04d8bc35c01089a6ec0a234558b3637603d9e1 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Mar 31 2020 09:37:27 +0000 Subject: import 389-ds-base-1.3.10.1-5.el7 --- diff --git a/.389-ds-base.metadata b/.389-ds-base.metadata index df950b5..59b94f6 100644 --- a/.389-ds-base.metadata +++ b/.389-ds-base.metadata @@ -1 +1 @@ -e81bcb4434dd15b1424594dccce432c49e393788 SOURCES/389-ds-base-1.3.9.1.tar.bz2 +c995af6f5693f698c29b72ebfdbc0e60a72cc517 SOURCES/389-ds-base-1.3.10.1.tar.bz2 diff --git a/.gitignore b/.gitignore index 0e8f7f2..a4a9c46 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/389-ds-base-1.3.9.1.tar.bz2 +SOURCES/389-ds-base-1.3.10.1.tar.bz2 diff --git a/SOURCES/0000-CVE-2019-14824-BZ-1748199-deref-plugin-displays-rest.patch b/SOURCES/0000-CVE-2019-14824-BZ-1748199-deref-plugin-displays-rest.patch new file mode 100644 index 0000000..9fd6303 --- /dev/null +++ b/SOURCES/0000-CVE-2019-14824-BZ-1748199-deref-plugin-displays-rest.patch @@ -0,0 +1,53 @@ +From 63fa3ee665b66b36321489c090b24811838837c0 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 3 Sep 2019 13:15:45 -0400 +Subject: [PATCH] CVE-2019-14824 (BZ#1748199) - deref plugin displays + restricted attributes + +Bug Description: If there is an ACI that allows "search" access to an attribute, + the deref plugin access control checks sees this is a "read" + privilege and returns the attribute's value. + +Fix description: For deref plugin we are only concerned with "read" access, not + "search" access. Removed the SLAPI_ACL_SEARCH right flag when + checking access for an attribute. + +Reviewed by: lkrispen & tbordaz(Thanks!) +--- + ldap/servers/plugins/deref/deref.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/ldap/servers/plugins/deref/deref.c b/ldap/servers/plugins/deref/deref.c +index cb5ebb830..ec1884ba3 100644 +--- a/ldap/servers/plugins/deref/deref.c ++++ b/ldap/servers/plugins/deref/deref.c +@@ -573,7 +573,7 @@ deref_do_deref_attr(Slapi_PBlock *pb, BerElement *ctrlber, const char *derefdn, + Slapi_Entry **entries = NULL; + int rc; + +- /* If the access check on the attributes is done without retrieveing the entry ++ /* If the access check on the attributes is done without retrieving the entry + * it cannot handle acis which need teh entry, eg to apply a targetfilter rule + * So the determination of attrs which can be dereferenced is delayed + */ +@@ -596,7 +596,7 @@ deref_do_deref_attr(Slapi_PBlock *pb, BerElement *ctrlber, const char *derefdn, + int ii; + int needattrvals = 1; /* need attrvals sequence? */ + if (deref_check_access(pb, entries[0], derefdn, attrs, &retattrs, +- (SLAPI_ACL_SEARCH | SLAPI_ACL_READ))) { ++ SLAPI_ACL_READ)) { + slapi_log_err(SLAPI_LOG_PLUGIN, DEREF_PLUGIN_SUBSYSTEM, + "deref_do_deref_attr - The client does not have permission to read the requested " + "attributes in entry %s\n", +@@ -714,7 +714,7 @@ deref_pre_entry(Slapi_PBlock *pb) + attrs[1] = NULL; + + if (deref_check_access(pb, ent, NULL, attrs, &retattrs, +- (SLAPI_ACL_SEARCH | SLAPI_ACL_READ))) { ++ SLAPI_ACL_READ)) { + slapi_log_err(SLAPI_LOG_PLUGIN, DEREF_PLUGIN_SUBSYSTEM, + "deref_pre_entry - The client does not have permission to read attribute %s in entry %s\n", + spec->derefattr, slapi_entry_get_dn_const(ent)); +-- +2.21.0 + diff --git a/SOURCES/0000-Ticket-50236-memberOf-should-be-more-robust.patch b/SOURCES/0000-Ticket-50236-memberOf-should-be-more-robust.patch deleted file mode 100644 index 3e67017..0000000 --- a/SOURCES/0000-Ticket-50236-memberOf-should-be-more-robust.patch +++ /dev/null @@ -1,252 +0,0 @@ -From 933b46f1f434ac7c11e155611c91f21e31c4d6f7 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Thu, 21 Feb 2019 16:58:05 -0500 -Subject: [PATCH] Ticket 50236 - memberOf should be more robust - -Bug Description: When doing a modrdn, or any memberOf update, if the entry - already has the memberOf attribute with the same value - the operation is incorrectly rejected. - -Fix Description: If we get an error 20 (type or value exists) return success. - - Also fixed a coding mistake that causes the wrong error - code to be returned. This also required fixing the CI - test to check for the new correct errro code. - -https://pagure.io/389-ds-base/issue/50236 - -Reviewed by: firstyear, spichugi, and tbordaz (Thanks!!!) ---- - .../suites/memberof_plugin/regression_test.py | 48 ++++++++++--------- - ldap/servers/plugins/memberof/memberof.c | 35 ++++++++++---- - 2 files changed, 53 insertions(+), 30 deletions(-) - -diff --git a/dirsrvtests/tests/suites/memberof_plugin/regression_test.py b/dirsrvtests/tests/suites/memberof_plugin/regression_test.py -index 2b0c4aec2..9d0ce35ed 100644 ---- a/dirsrvtests/tests/suites/memberof_plugin/regression_test.py -+++ b/dirsrvtests/tests/suites/memberof_plugin/regression_test.py -@@ -11,13 +11,12 @@ import pytest - import os - import time - import ldap --import subprocess - from random import sample - from lib389.utils import ds_is_older, ensure_list_bytes, ensure_bytes, ensure_str - from lib389.topologies import topology_m1h1c1 as topo, topology_st, topology_m2 as topo_m2 - from lib389._constants import * - from lib389.plugins import MemberOfPlugin --from lib389 import agreement, Entry -+from lib389 import Entry - from lib389.idm.user import UserAccount, UserAccounts, TEST_USER_PROPERTIES - from lib389.idm.group import Groups, Group - from lib389.replica import ReplicationManager -@@ -49,7 +48,7 @@ def add_users(topo_m2, users_num, suffix): - users_list = [] - users = UserAccounts(topo_m2.ms["master1"], suffix, rdn=None) - log.info('Adding %d users' % users_num) -- for num in sample(range(1000), users_num): -+ for num in sample(list(range(1000)), users_num): - num_ran = int(round(num)) - USER_NAME = 'test%05d' % num_ran - user = users.create(properties={ -@@ -76,8 +75,8 @@ def config_memberof(server): - for ent in ents: - log.info('update %s to add nsDS5ReplicatedAttributeListTotal' % ent.dn) - server.agreement.setProperties(agmnt_dn=ents[0].dn, -- properties={RA_FRAC_EXCLUDE:'(objectclass=*) $ EXCLUDE memberOf', -- RA_FRAC_EXCLUDE_TOTAL_UPDATE:'(objectclass=*) $ EXCLUDE '}) -+ properties={RA_FRAC_EXCLUDE: '(objectclass=*) $ EXCLUDE memberOf', -+ RA_FRAC_EXCLUDE_TOTAL_UPDATE: '(objectclass=*) $ EXCLUDE '}) - - - def send_updates_now(server): -@@ -184,14 +183,14 @@ def test_memberof_with_repl(topo): - for i in range(3): - CN = '%s%d' % (GROUP_CN, i) - groups = Groups(M1, SUFFIX) -- testgroup = groups.create(properties={'cn' : CN}) -+ testgroup = groups.create(properties={'cn': CN}) - time.sleep(2) - test_groups.append(testgroup) - - # Step 4 - #Now start testing by adding differnt user to differn group - if not ds_is_older('1.3.7'): -- test_groups[0].remove('objectClass', 'nsMemberOf') -+ test_groups[0].remove('objectClass', 'nsMemberOf') - - member_dn = test_users[0].dn - grp0_dn = test_groups[0].dn -@@ -211,7 +210,7 @@ def test_memberof_with_repl(topo): - # Step 7 - for i in [grp0_dn, grp1_dn]: - for inst in [M1, H1, C1]: -- _find_memberof(inst, member_dn, i) -+ _find_memberof(inst, member_dn, i) - - # Step 8 - for i in [M1, H1, C1]: -@@ -225,7 +224,7 @@ def test_memberof_with_repl(topo): - # For negative testcase, we are using assertionerror - for inst in [M1, H1, C1]: - for i in [grp0_dn, member_dn]: -- with pytest.raises(AssertionError): -+ with pytest.raises(AssertionError): - _find_memberof(inst, i, grp1_dn) - - # Step 11 -@@ -369,7 +368,7 @@ def test_memberof_with_changelog_reset(topo_m2): - 'objectclass': ensure_list_bytes(['top', 'groupOfNames'])} - - for user in users_list: -- dic_of_attributes.setdefault('member',[]) -+ dic_of_attributes.setdefault('member', []) - dic_of_attributes['member'].append(user.dn) - - log.info('Adding the test group using async function') -@@ -427,7 +426,7 @@ def rename_entry(server, cn, from_subtree, to_subtree): - server.rename_s(dn, nrdn, newsuperior=to_subtree, delold=0) - - --def _find_memberof(server, user_dn=None, group_dn=None, find_result=True): -+def _find_memberof_ext(server, user_dn=None, group_dn=None, find_result=True): - assert (server) - assert (user_dn) - assert (group_dn) -@@ -495,18 +494,19 @@ def test_memberof_group(topology_st): - dn2 = '%s,%s' % ('uid=test_m2', SUBTREE_1) - g1 = '%s,%s' % ('cn=g1', SUBTREE_1) - g2 = '%s,%s' % ('cn=g2', SUBTREE_2) -- _find_memberof(inst, dn1, g1, True) -- _find_memberof(inst, dn2, g1, True) -- _find_memberof(inst, dn1, g2, False) -- _find_memberof(inst, dn2, g2, False) -+ _find_memberof_ext(inst, dn1, g1, True) -+ _find_memberof_ext(inst, dn2, g1, True) -+ _find_memberof_ext(inst, dn1, g2, False) -+ _find_memberof_ext(inst, dn2, g2, False) - - rename_entry(inst, 'cn=g2', SUBTREE_2, SUBTREE_1) - - g2n = '%s,%s' % ('cn=g2-new', SUBTREE_1) -- _find_memberof(inst, dn1, g1, True) -- _find_memberof(inst, dn2, g1, True) -- _find_memberof(inst, dn1, g2n, True) -- _find_memberof(inst, dn2, g2n, True) -+ _find_memberof_ext(inst, dn1, g1, True) -+ _find_memberof_ext(inst, dn2, g1, True) -+ _find_memberof_ext(inst, dn1, g2n, True) -+ _find_memberof_ext(inst, dn2, g2n, True) -+ - - def _config_memberof_entrycache_on_modrdn_failure(server): - -@@ -517,11 +517,13 @@ def _config_memberof_entrycache_on_modrdn_failure(server): - (ldap.MOD_REPLACE, 'memberOfEntryScope', peoplebase.encode()), - (ldap.MOD_REPLACE, 'memberOfAutoAddOC', b'nsMemberOf')]) - -+ - def _disable_auto_oc_memberof(server): - MEMBEROF_PLUGIN_DN = ('cn=' + PLUGIN_MEMBER_OF + ',cn=plugins,cn=config') - server.modify_s(MEMBEROF_PLUGIN_DN, - [(ldap.MOD_REPLACE, 'memberOfAutoAddOC', b'nsContainer')]) - -+ - @pytest.mark.ds49967 - def test_entrycache_on_modrdn_failure(topology_st): - """This test checks that when a modrdn fails, the destination entry is not returned by a search -@@ -657,7 +659,7 @@ def test_entrycache_on_modrdn_failure(topology_st): - topology_st.standalone.rename_s(group2_dn, 'cn=group_in2', newsuperior=peoplebase, delold=0) - topology_st.standalone.log.info("This is unexpected, modrdn should fail as the member entry have not the appropriate objectclass") - assert False -- except ldap.OPERATIONS_ERROR: -+ except ldap.OBJECT_CLASS_VIOLATION: - pass - - # retrieve the entry having the specific description value -@@ -671,9 +673,11 @@ def test_entrycache_on_modrdn_failure(topology_st): - assert ent.dn == group2_dn - assert found - -+ - def _config_memberof_silent_memberof_failure(server): - _config_memberof_entrycache_on_modrdn_failure(server) - -+ - def test_silent_memberof_failure(topology_st): - """This test checks that if during a MODRDN, the memberof plugin fails - then MODRDN also fails -@@ -817,7 +821,7 @@ def test_silent_memberof_failure(topology_st): - topology_st.standalone.rename_s(group2_dn, 'cn=group_in2', newsuperior=peoplebase, delold=0) - topology_st.standalone.log.info("This is unexpected, modrdn should fail as the member entry have not the appropriate objectclass") - assert False -- except ldap.OPERATIONS_ERROR: -+ except ldap.OBJECT_CLASS_VIOLATION: - pass - - # Check the those entries have not memberof -@@ -843,7 +847,7 @@ def test_silent_memberof_failure(topology_st): - except ldap.OPERATIONS_ERROR: - pass - -- # Check the those entries have not memberof -+ # Check the those entries do not have memberof - for i in (4, 5): - user_dn = 'cn=user%d,%s' % (i, peoplebase) - ent = topology_st.standalone.getEntry(user_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof']) -diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c -index 329a845a7..b54eb3977 100644 ---- a/ldap/servers/plugins/memberof/memberof.c -+++ b/ldap/servers/plugins/memberof/memberof.c -@@ -919,8 +919,7 @@ memberof_postop_modrdn(Slapi_PBlock *pb) - * entry that is being renamed. */ - for (i = 0; configCopy.groupattrs && configCopy.groupattrs[i]; i++) { - if (0 == slapi_entry_attr_find(post_e, configCopy.groupattrs[i], &attr)) { -- if ((ret = memberof_moddn_attr_list(pb, &configCopy, pre_sdn, -- post_sdn, attr) != 0)) { -+ if ((ret = memberof_moddn_attr_list(pb, &configCopy, pre_sdn, post_sdn, attr)) != 0) { - slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM, - "memberof_postop_modrdn - Update failed for (%s), error (%d)\n", - slapi_sdn_get_dn(pre_sdn), ret); -@@ -1720,12 +1719,32 @@ memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config, int mod_o - replace_mod.mod_values = replace_val; - } - rc = memberof_add_memberof_attr(mods, op_to, config->auto_add_oc); -- if (rc == LDAP_NO_SUCH_ATTRIBUTE) { -- /* the memberof values to be replaced do not exist -- * just add the new values */ -- mods[0] = mods[1]; -- mods[1] = NULL; -- rc = memberof_add_memberof_attr(mods, op_to, config->auto_add_oc); -+ if (rc == LDAP_NO_SUCH_ATTRIBUTE || rc == LDAP_TYPE_OR_VALUE_EXISTS) { -+ if (rc == LDAP_TYPE_OR_VALUE_EXISTS) { -+ /* -+ * For some reason the new modrdn value is present, so retry -+ * the delete by itself and ignore the add op by tweaking -+ * the mod array. -+ */ -+ mods[1] = NULL; -+ rc = memberof_add_memberof_attr(mods, op_to, config->auto_add_oc); -+ } else { -+ /* -+ * The memberof value to be replaced does not exist so just -+ * add the new value. Shuffle the mod array to apply only -+ * the add operation. -+ */ -+ mods[0] = mods[1]; -+ mods[1] = NULL; -+ rc = memberof_add_memberof_attr(mods, op_to, config->auto_add_oc); -+ if (rc == LDAP_TYPE_OR_VALUE_EXISTS) { -+ /* -+ * The entry already has the expected memberOf value, no -+ * problem just return success. -+ */ -+ rc = LDAP_SUCCESS; -+ } -+ } - } - } - } --- -2.17.2 - diff --git a/SOURCES/0001-Issue-50525-nsslapd-defaultnamingcontext-does-not-ch.patch b/SOURCES/0001-Issue-50525-nsslapd-defaultnamingcontext-does-not-ch.patch new file mode 100644 index 0000000..7fb1a01 --- /dev/null +++ b/SOURCES/0001-Issue-50525-nsslapd-defaultnamingcontext-does-not-ch.patch @@ -0,0 +1,250 @@ +From d33743c8604ff4f97947dad14fddab0691e3d19e Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 1 Aug 2019 16:50:34 -0400 +Subject: [PATCH] Issue 50525 - nsslapd-defaultnamingcontext does not change + when the assigned suffix gets deleted + +Bug Description: + +If you delete the suffix that is set as the default naming context, the attribute +is not reset. + +Also using dsconf to delete a backend/suffix fails if there are vlv indexes, encrypted +attributes, or replication is configured. + +Fix Description: + +As for the default naming context, if there is a second suffix configured, it will be +automatically set as the new default naming context, otherwise the attribute is not +modified. + +For dsconf backend delete issue, it now checks and removes replication configuration +and agreements, and removes all the child entries under the backend entry. + +relates: https://pagure.io/389-ds-base/issue/50525 + +Reviewed by: spichugi(Thanks!) +--- + .../be_del_and_default_naming_attr_test.py | 90 +++++++++++++++++++ + ldap/servers/slapd/mapping_tree.c | 50 ++++++----- + src/lib389/lib389/backend.py | 17 ++-- + src/lib389/lib389/replica.py | 2 +- + 4 files changed, 132 insertions(+), 27 deletions(-) + create mode 100644 dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py + +diff --git a/dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py b/dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py +new file mode 100644 +index 000000000..34a2de2ad +--- /dev/null ++++ b/dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py +@@ -0,0 +1,90 @@ ++import logging ++import pytest ++import os ++from lib389._constants import DEFAULT_SUFFIX ++from lib389.topologies import topology_m1 as topo ++from lib389.backend import Backends ++from lib389.encrypted_attributes import EncryptedAttrs ++ ++DEBUGGING = os.getenv("DEBUGGING", default=False) ++if DEBUGGING: ++ logging.getLogger(__name__).setLevel(logging.DEBUG) ++else: ++ logging.getLogger(__name__).setLevel(logging.INFO) ++log = logging.getLogger(__name__) ++ ++SECOND_SUFFIX = 'o=namingcontext' ++THIRD_SUFFIX = 'o=namingcontext2' ++ ++def test_be_delete(topo): ++ """Test that we can delete a backend that contains replication ++ configuration and encrypted attributes. The default naming ++ context should also be updated to reflect the next available suffix ++ ++ :id: 5208f897-7c95-4925-bad0-9ceb95fee678 ++ :setup: Master Instance ++ :steps: ++ 1. Create second backend/suffix ++ 2. Add an encrypted attribute to the default suffix ++ 2. Delete default suffix ++ 3. Check the nsslapd-defaultnamingcontext is updated ++ 4. Delete the last backend ++ 5. Check the namingcontext has not changed ++ 6. Add new backend ++ 7. Set default naming context ++ 8. Verify the naming context is correct ++ :expectedresults: ++ 1. Success ++ 2. Success ++ 3. Success ++ 4. Success ++ 5. Success ++ 6. Success ++ 7. Success ++ 8. Success ++ """ ++ ++ inst = topo.ms["master1"] ++ ++ # Create second suffix ++ backends = Backends(inst) ++ default_backend = backends.get(DEFAULT_SUFFIX) ++ new_backend = backends.create(properties={'nsslapd-suffix': SECOND_SUFFIX, ++ 'name': 'namingRoot'}) ++ ++ # Add encrypted attribute entry under default suffix ++ encrypt_attrs = EncryptedAttrs(inst, basedn='cn=encrypted attributes,{}'.format(default_backend.dn)) ++ encrypt_attrs.create(properties={'cn': 'employeeNumber', 'nsEncryptionAlgorithm': 'AES'}) ++ ++ # Delete default suffix ++ default_backend.delete() ++ ++ # Check that the default naming context is set to the new/second suffix ++ default_naming_ctx = inst.config.get_attr_val_utf8('nsslapd-defaultnamingcontext') ++ assert default_naming_ctx == SECOND_SUFFIX ++ ++ # delete new backend, but the naming context should not change ++ new_backend.delete() ++ ++ # Check that the default naming context is still set to the new/second suffix ++ default_naming_ctx = inst.config.get_attr_val_utf8('nsslapd-defaultnamingcontext') ++ assert default_naming_ctx == SECOND_SUFFIX ++ ++ # Add new backend ++ new_backend = backends.create(properties={'nsslapd-suffix': THIRD_SUFFIX, ++ 'name': 'namingRoot2'}) ++ ++ # manaully set naming context ++ inst.config.set('nsslapd-defaultnamingcontext', THIRD_SUFFIX) ++ ++ # Verify naming context is correct ++ default_naming_ctx = inst.config.get_attr_val_utf8('nsslapd-defaultnamingcontext') ++ assert default_naming_ctx == THIRD_SUFFIX ++ ++ ++if __name__ == '__main__': ++ # Run isolated ++ # -s for DEBUG mode ++ CURRENT_FILE = os.path.realpath(__file__) ++ pytest.main(["-s", CURRENT_FILE]) ++ +diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c +index 834949a67..25e9fb80c 100644 +--- a/ldap/servers/slapd/mapping_tree.c ++++ b/ldap/servers/slapd/mapping_tree.c +@@ -1521,26 +1521,36 @@ done: + strcpy_unescape_value(escaped, suffix); + } + if (escaped && (0 == strcasecmp(escaped, default_naming_context))) { +- int rc = _mtn_update_config_param(LDAP_MOD_DELETE, +- CONFIG_DEFAULT_NAMING_CONTEXT, +- NULL); +- if (rc) { +- slapi_log_err(SLAPI_LOG_ERR, +- "mapping_tree_entry_delete_callback", +- "deleting config param %s failed: RC=%d\n", +- CONFIG_DEFAULT_NAMING_CONTEXT, rc); +- } +- if (LDAP_SUCCESS == rc) { +- char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE] = {0}; +- /* Removing defaultNamingContext from cn=config entry +- * was successful. The remove does not reset the +- * global parameter. We need to reset it separately. */ +- if (config_set_default_naming_context( +- CONFIG_DEFAULT_NAMING_CONTEXT, +- NULL, errorbuf, CONFIG_APPLY)) { +- slapi_log_err(SLAPI_LOG_ERR, "mapping_tree_entry_delete_callback", +- "Setting NULL to %s failed. %s\n", +- CONFIG_DEFAULT_NAMING_CONTEXT, errorbuf); ++ /* ++ * We can not delete the default naming attribute, so instead ++ * replace it only if there is another suffix available ++ */ ++ void *node = NULL; ++ Slapi_DN *sdn; ++ sdn = slapi_get_first_suffix(&node, 0); ++ if (sdn) { ++ char *replacement_suffix = (char *)slapi_sdn_get_dn(sdn); ++ int rc = _mtn_update_config_param(LDAP_MOD_REPLACE, ++ CONFIG_DEFAULT_NAMING_CONTEXT, ++ replacement_suffix); ++ if (rc) { ++ slapi_log_err(SLAPI_LOG_ERR, ++ "mapping_tree_entry_delete_callback", ++ "replacing config param %s failed: RC=%d\n", ++ CONFIG_DEFAULT_NAMING_CONTEXT, rc); ++ } ++ if (LDAP_SUCCESS == rc) { ++ char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE] = {0}; ++ /* Replacing defaultNamingContext from cn=config entry ++ * was successful. The replace does not reset the ++ * global parameter. We need to reset it separately. */ ++ if (config_set_default_naming_context( ++ CONFIG_DEFAULT_NAMING_CONTEXT, ++ replacement_suffix, errorbuf, CONFIG_APPLY)) { ++ slapi_log_err(SLAPI_LOG_ERR, "mapping_tree_entry_delete_callback", ++ "Setting %s tp %s failed. %s\n", ++ CONFIG_DEFAULT_NAMING_CONTEXT, replacement_suffix, errorbuf); ++ } + } + } + } +diff --git a/src/lib389/lib389/backend.py b/src/lib389/lib389/backend.py +index 6f4c8694e..4d32038f6 100644 +--- a/src/lib389/lib389/backend.py ++++ b/src/lib389/lib389/backend.py +@@ -17,6 +17,7 @@ from lib389 import Entry + from lib389._mapped_object import DSLdapObjects, DSLdapObject + from lib389.mappingTree import MappingTrees, MappingTree + from lib389.exceptions import NoSuchEntryError, InvalidArgumentError ++from lib389.replica import Replicas + + # We need to be a factor to the backend monitor + from lib389.monitor import MonitorBackend +@@ -507,20 +508,24 @@ class Backend(DSLdapObject): + mt = self._mts.get(selector=bename) + # Assert the type is "backend" + # Are these the right types....? +- if mt.get_attr_val('nsslapd-state') != ensure_bytes('backend'): ++ if mt.get_attr_val('nsslapd-state').lower() != ensure_bytes('backend'): + raise ldap.UNWILLING_TO_PERFORM('Can not delete the mapping tree, not for a backend! You may need to delete this backend via cn=config .... ;_; ') ++ ++ # Delete replicas first ++ try: ++ Replicas(self._instance).get(mt.get_attr_val_utf8('cn')).delete() ++ except ldap.NO_SUCH_OBJECT: ++ # No replica, no problem ++ pass ++ + # Delete our mapping tree if it exists. + mt.delete() + except ldap.NO_SUCH_OBJECT: + # Righto, it's already gone! Do nothing ... + pass +- # Delete all our related indices +- self._instance.index.delete_all(bename) + + # Now remove our children, this is all ldbm config +- self._instance.delete_branch_s(self._dn, ldap.SCOPE_ONELEVEL) +- # The super will actually delete ourselves. +- super(Backend, self).delete() ++ self._instance.delete_branch_s(self._dn, ldap.SCOPE_SUBTREE) + + def _lint_mappingtree(self): + """Backend lint +diff --git a/src/lib389/lib389/replica.py b/src/lib389/lib389/replica.py +index cdd0a9729..7b45683d9 100644 +--- a/src/lib389/lib389/replica.py ++++ b/src/lib389/lib389/replica.py +@@ -458,7 +458,7 @@ class ReplicaLegacy(object): + try: + self.deleteAgreements(nsuffix) + except ldap.LDAPError as e: +- self.log.fatal('Failed to delete replica agreements!') ++ self.log.fatal('Failed to delete replica agreements! ' + str(e)) + raise + + # Delete the replica +-- +2.21.0 + diff --git a/SOURCES/0001-Ticket-50238-Failed-modrdn-can-corrupt-entry-cache.patch b/SOURCES/0001-Ticket-50238-Failed-modrdn-can-corrupt-entry-cache.patch deleted file mode 100644 index ee050dd..0000000 --- a/SOURCES/0001-Ticket-50238-Failed-modrdn-can-corrupt-entry-cache.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 2a181763d0cff5f31dc18f3e71f79dd815906c09 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Fri, 22 Feb 2019 13:46:48 -0500 -Subject: [PATCH] Ticket 50238 - Failed modrdn can corrupt entry cache - -Bug Description: Under certain conditions (found under IPA) when a backend - transaction plugin fails and causes a modrdn operation to - fail the entry cache no longer contains the original/pre - entry, but instead it has the post modrdn'ed entry with - the original entry's ID - -Fix Description: Upon failure, if the post entry is in the cache, then swap - it out with the original entry. - -https://pagure.io/389-ds-base/issue/50238 - -Reviewed by: firstyear, spichugi, & tboardaz (Thanks!!!) ---- - dirsrvtests/tests/suites/betxns/betxn_test.py | 57 +++++++++++++++++++ - ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 16 ++++-- - 2 files changed, 68 insertions(+), 5 deletions(-) - -diff --git a/dirsrvtests/tests/suites/betxns/betxn_test.py b/dirsrvtests/tests/suites/betxns/betxn_test.py -index 175496495..48181a9ea 100644 ---- a/dirsrvtests/tests/suites/betxns/betxn_test.py -+++ b/dirsrvtests/tests/suites/betxns/betxn_test.py -@@ -8,6 +8,7 @@ - # - import pytest - import six -+import ldap - from lib389.tasks import * - from lib389.utils import * - from lib389.topologies import topology_st -@@ -248,6 +249,62 @@ def test_betxn_memberof(topology_st, dynamic_plugins): - log.info('test_betxn_memberof: PASSED') - - -+def test_betxn_modrdn_memberof(topology_st): -+ """Test modrdn operartions and memberOf -+ -+ :id: 70d0b96e-b693-4bf7-bbf5-102a66ac5994 -+ -+ :setup: Standalone instance -+ -+ :steps: 1. Enable and configure memberOf plugin -+ 2. Set memberofgroupattr="member" and memberofAutoAddOC="nsContainer" -+ 3. Create group and user outside of memberOf plugin scope -+ 4. Do modrdn to move group into scope -+ 5. Do modrdn to move group into scope (again) -+ -+ :expectedresults: -+ 1. memberOf plugin plugin should be ON -+ 2. Set memberofgroupattr="member" and memberofAutoAddOC="nsContainer" should PASS -+ 3. Creating group and user should PASS -+ 4. Modrdn should fail with objectclass violation -+ 5. Second modrdn should also fail with objectclass violation -+ """ -+ -+ peoplebase = 'ou=people,%s' % DEFAULT_SUFFIX -+ memberof = MemberOfPlugin(topology_st.standalone) -+ memberof.enable() -+ memberof.set_autoaddoc('nsContainer') # Bad OC -+ memberof.set('memberOfEntryScope', peoplebase) -+ memberof.set('memberOfAllBackends', 'on') -+ topology_st.standalone.restart() -+ -+ groups = Groups(topology_st.standalone, DEFAULT_SUFFIX) -+ group = groups.create(properties={ -+ 'cn': 'group', -+ }) -+ -+ # Create user and add it to group -+ users = UserAccounts(topology_st.standalone, basedn=DEFAULT_SUFFIX) -+ user = users.create(properties=TEST_USER_PROPERTIES) -+ if not ds_is_older('1.3.7'): -+ user.remove('objectClass', 'nsMemberOf') -+ -+ group.add_member(user.dn) -+ -+ # Attempt modrdn that should fail, but the original entry should stay in the cache -+ with pytest.raises(ldap.OBJECTCLASS_VIOLATION): -+ group.rename('cn=group_to_people', newsuperior=peoplebase) -+ -+ # Should fail, but not with NO_SUCH_OBJECT as the original entry should still be in the cache -+ with pytest.raises(ldap.OBJECTCLASS_VIOLATION): -+ group.rename('cn=group_to_people', newsuperior=peoplebase) -+ -+ # -+ # Done -+ # -+ log.info('test_betxn_modrdn_memberof: PASSED') -+ -+ - if __name__ == '__main__': - # Run isolated - # -s for DEBUG mode -diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -index 684b040b8..e4d0337d4 100644 ---- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -@@ -1411,14 +1411,20 @@ common_return: - "operation failed, the target entry is cleared from dncache (%s)\n", slapi_entry_get_dn(ec->ep_entry)); - CACHE_REMOVE(&inst->inst_dncache, bdn); - CACHE_RETURN(&inst->inst_dncache, &bdn); -+ /* -+ * If the new/invalid entry (ec) is in the cache, that means we need to -+ * swap it out with the original entry (e) --> to undo the swap that -+ * modrdn_rename_entry_update_indexes() did. -+ */ -+ if (cache_is_in_cache(&inst->inst_cache, ec)) { -+ if (cache_replace(&inst->inst_cache, ec, e) != 0) { -+ slapi_log_err(SLAPI_LOG_ALERT, "ldbm_back_modrdn", -+ "failed to replace cache entry after error\n"); -+ } -+ } - } - -- /* remove the new entry from the cache if the op failed - -- otherwise, leave it in */ - if (ec && inst) { -- if (retval && cache_is_in_cache(&inst->inst_cache, ec)) { -- CACHE_REMOVE(&inst->inst_cache, ec); -- } - CACHE_RETURN(&inst->inst_cache, &ec); - } - ec = NULL; --- -2.17.2 - diff --git a/SOURCES/0002-Issue-50530-Directory-Server-not-RFC-4511-compliant-.patch b/SOURCES/0002-Issue-50530-Directory-Server-not-RFC-4511-compliant-.patch new file mode 100644 index 0000000..ccd1762 --- /dev/null +++ b/SOURCES/0002-Issue-50530-Directory-Server-not-RFC-4511-compliant-.patch @@ -0,0 +1,146 @@ +From 51ea1d34b861dfffb12fbe6be4e23d9342fd0fe2 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 2 Aug 2019 14:36:24 -0400 +Subject: [PATCH] Issue 50530 - Directory Server not RFC 4511 compliant with + requested attr "1.1" + +Bug Description: A regression was introduced some time back that changed the + behavior of how the server handled the "1.1" requested attribute + in a search request. If "1.1" was requested along with other + attributes then no attibutes were returned, but in this case "1.1" + is expected to be ignroed. + +Fix Description: Only comply with "1.1" if it is the only requested attribute + +relates: https://pagure.io/389-ds-base/issue/50530 + +Reviewed by: firstyear(Thanks!) +--- + dirsrvtests/tests/suites/basic/basic_test.py | 57 +++++++++++++++++--- + ldap/servers/slapd/result.c | 7 ++- + 2 files changed, 57 insertions(+), 7 deletions(-) + +diff --git a/dirsrvtests/tests/suites/basic/basic_test.py b/dirsrvtests/tests/suites/basic/basic_test.py +index 0f7536b63..cea4f6bfe 100644 +--- a/dirsrvtests/tests/suites/basic/basic_test.py ++++ b/dirsrvtests/tests/suites/basic/basic_test.py +@@ -28,6 +28,7 @@ log = logging.getLogger(__name__) + USER1_DN = 'uid=user1,' + DEFAULT_SUFFIX + USER2_DN = 'uid=user2,' + DEFAULT_SUFFIX + USER3_DN = 'uid=user3,' + DEFAULT_SUFFIX ++USER4_DN = 'uid=user4,' + DEFAULT_SUFFIX + + ROOTDSE_DEF_ATTR_LIST = ('namingContexts', + 'supportedLDAPVersion', +@@ -409,8 +410,8 @@ def test_basic_acl(topology_st, import_example_ldif): + 'uid': 'user1', + 'userpassword': PASSWORD}))) + except ldap.LDAPError as e: +- log.fatal('test_basic_acl: Failed to add test user ' + USER1_DN +- + ': error ' + e.message['desc']) ++ log.fatal('test_basic_acl: Failed to add test user ' + USER1_DN + ++ ': error ' + e.message['desc']) + assert False + + try: +@@ -421,8 +422,8 @@ def test_basic_acl(topology_st, import_example_ldif): + 'uid': 'user2', + 'userpassword': PASSWORD}))) + except ldap.LDAPError as e: +- log.fatal('test_basic_acl: Failed to add test user ' + USER1_DN +- + ': error ' + e.message['desc']) ++ log.fatal('test_basic_acl: Failed to add test user ' + USER1_DN + ++ ': error ' + e.message['desc']) + assert False + + # +@@ -572,6 +573,50 @@ def test_basic_searches(topology_st, import_example_ldif): + log.info('test_basic_searches: PASSED') + + ++@pytest.fixture(scope="module") ++def add_test_entry(topology_st, request): ++ # Add test entry ++ topology_st.standalone.add_s(Entry((USER4_DN, ++ {'objectclass': "top extensibleObject".split(), ++ 'cn': 'user1', 'uid': 'user1'}))) ++ ++ ++search_params = [(['1.1'], 'cn', False), ++ (['1.1', 'cn'], 'cn', True), ++ (['+'], 'nsUniqueId', True), ++ (['*'], 'cn', True), ++ (['cn'], 'cn', True)] ++@pytest.mark.parametrize("attrs, attr, present", search_params) ++def test_search_req_attrs(topology_st, add_test_entry, attrs, attr, present): ++ """Test requested attributes in search operations. ++ :id: 426a59ff-49b8-4a70-b377-0c0634a29b6e ++ :setup: Standalone instance ++ :steps: ++ 1. Test "1.1" does not return any attributes. ++ 2. Test "1.1" is ignored if there are other requested attributes ++ 3. Test "+" returns all operational attributes ++ 4. Test "*" returns all attributes ++ 5. Test requested attributes ++ ++ :expectedresults: ++ 1. Success ++ 2. Success ++ 3. Success ++ 4. Success ++ 5. Success ++ """ ++ ++ log.info("Testing attrs: {} attr: {} present: {}".format(attrs, attr, present)) ++ entry = topology_st.standalone.search_s(USER4_DN, ++ ldap.SCOPE_BASE, ++ 'objectclass=top', ++ attrs) ++ if present: ++ assert entry[0].hasAttr(attr) ++ else: ++ assert not entry[0].hasAttr(attr) ++ ++ + def test_basic_referrals(topology_st, import_example_ldif): + """Test LDAP server in referral mode. + +@@ -716,8 +761,8 @@ def test_basic_systemctl(topology_st, import_example_ldif): + log.info('Attempting to start the server with broken dse.ldif...') + try: + topology_st.standalone.start() +- except: +- log.info('Server failed to start as expected') ++ except Exception as e: ++ log.info('Server failed to start as expected: ' + str(e)) + log.info('Check the status...') + assert (not topology_st.standalone.status()) + log.info('Server failed to start as expected') +diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c +index d9f431cc5..34ddd8566 100644 +--- a/ldap/servers/slapd/result.c ++++ b/ldap/servers/slapd/result.c +@@ -1546,6 +1546,8 @@ send_ldap_search_entry_ext( + * "+" means all operational attributes (rfc3673) + * operational attributes are only retrieved if they are named + * specifically or when "+" is specified. ++ * In the case of "1.1", if there are other requested attributes ++ * then "1.1" should be ignored. + */ + + /* figure out if we want all user attributes or no attributes at all */ +@@ -1560,7 +1562,10 @@ send_ldap_search_entry_ext( + if (strcmp(LDAP_ALL_USER_ATTRS, attrs[i]) == 0) { + alluserattrs = 1; + } else if (strcmp(LDAP_NO_ATTRS, attrs[i]) == 0) { +- noattrs = 1; ++ /* "1.1" is only valid if it's the only requested attribute */ ++ if (i == 0 && attrs[1] == NULL) { ++ noattrs = 1; ++ } + } else if (strcmp(LDAP_ALL_OPERATIONAL_ATTRS, attrs[i]) == 0) { + alloperationalattrs = 1; + } else { +-- +2.21.0 + diff --git a/SOURCES/0002-Ticket-50232-export-creates-not-importable-ldif-file.patch b/SOURCES/0002-Ticket-50232-export-creates-not-importable-ldif-file.patch deleted file mode 100644 index fd1bde2..0000000 --- a/SOURCES/0002-Ticket-50232-export-creates-not-importable-ldif-file.patch +++ /dev/null @@ -1,296 +0,0 @@ -From 70d1336481bd1a36d8b0bdef43a9364c7db58c26 Mon Sep 17 00:00:00 2001 -From: Ludwig Krispenz -Date: Wed, 20 Feb 2019 10:11:15 +0100 -Subject: [PATCH] Ticket 50232 - export creates not importable ldif file - -Bug: If the RUV entry hasa smaller entryid than the suffix entry it will be - exported before the suffix. If that ldif is used for import the RUV entry - is skipped and a new one generated with a different database generation - -Fix: Before exporting the RUV check that the suffix is alread exported, if not - make the RUV entry pending and write it after all othere entries - -Reviewed by: tbordaz, wbrown. Thanks ---- - dirsrvtests/tests/tickets/ticket50232_test.py | 163 ++++++++++++++++++ - ldap/servers/slapd/back-ldbm/ldif2ldbm.c | 58 ++++++- - 2 files changed, 219 insertions(+), 2 deletions(-) - create mode 100644 dirsrvtests/tests/tickets/ticket50232_test.py - -diff --git a/dirsrvtests/tests/tickets/ticket50232_test.py b/dirsrvtests/tests/tickets/ticket50232_test.py -new file mode 100644 -index 000000000..133ed0dfe ---- /dev/null -+++ b/dirsrvtests/tests/tickets/ticket50232_test.py -@@ -0,0 +1,163 @@ -+# --- BEGIN COPYRIGHT BLOCK --- -+# Copyright (C) 2016 Red Hat, Inc. -+# All rights reserved. -+# -+# License: GPL (version 3 or any later version). -+# See LICENSE for details. -+# --- END COPYRIGHT BLOCK --- -+# -+import logging -+ -+import pytest -+# from lib389.tasks import * -+# from lib389.utils import * -+from lib389.topologies import topology_st -+from lib389.replica import ReplicationManager,Replicas -+ -+from lib389._constants import DEFAULT_SUFFIX, BACKEND_NAME -+ -+from lib389.idm.user import UserAccounts -+from lib389.idm.organization import Organization -+from lib389.idm.organizationalunit import OrganizationalUnit -+ -+log = logging.getLogger(__name__) -+ -+NORMAL_SUFFIX = 'o=normal' -+NORMAL_BACKEND_NAME = 'normal' -+REVERSE_SUFFIX = 'o=reverse' -+REVERSE_BACKEND_NAME = 'reverse' -+ -+def _enable_replica(instance, suffix): -+ -+ repl = ReplicationManager(DEFAULT_SUFFIX) -+ repl._ensure_changelog(instance) -+ replicas = Replicas(instance) -+ replicas.create(properties={ -+ 'cn': 'replica', -+ 'nsDS5ReplicaRoot': suffix, -+ 'nsDS5ReplicaId': '1', -+ 'nsDS5Flags': '1', -+ 'nsDS5ReplicaType': '3' -+ }) -+ -+def _populate_suffix(instance, suffixname): -+ -+ o = Organization(instance, 'o={}'.format(suffixname)) -+ o.create(properties={ -+ 'o': suffixname, -+ 'description': 'test' -+ }) -+ ou = OrganizationalUnit(instance, 'ou=people,o={}'.format(suffixname)) -+ ou.create(properties={ -+ 'ou': 'people' -+ }) -+ -+def _get_replica_generation(instance, suffix): -+ -+ replicas = Replicas(instance) -+ replica = replicas.get(suffix) -+ ruv = replica.get_ruv() -+ return ruv._data_generation -+ -+def _test_export_import(instance, suffix, backend): -+ -+ before_generation = _get_replica_generation(instance, suffix) -+ -+ instance.stop() -+ instance.db2ldif( -+ bename=backend, -+ suffixes=[suffix], -+ excludeSuffixes=[], -+ encrypt=False, -+ repl_data=True, -+ outputfile="/tmp/output_file", -+ ) -+ instance.ldif2db( -+ bename=None, -+ excludeSuffixes=None, -+ encrypt=False, -+ suffixes=[suffix], -+ import_file="/tmp/output_file", -+ ) -+ instance.start() -+ after_generation = _get_replica_generation(instance, suffix) -+ -+ assert (before_generation == after_generation) -+ -+def test_ticket50232_normal(topology_st): -+ """ -+ The fix for ticket 50232 -+ -+ -+ The test sequence is: -+ - create suffix -+ - add suffix entry and some child entries -+ - "normally" done after populating suffix: enable replication -+ - get RUV and database generation -+ - export -r -+ - import -+ - get RUV and database generation -+ - assert database generation has not changed -+ """ -+ -+ log.info('Testing Ticket 50232 - export creates not imprtable ldif file, normal creation order') -+ -+ topology_st.standalone.backend.create(NORMAL_SUFFIX, {BACKEND_NAME: NORMAL_BACKEND_NAME}) -+ topology_st.standalone.mappingtree.create(NORMAL_SUFFIX, bename=NORMAL_BACKEND_NAME, parent=None) -+ -+ _populate_suffix(topology_st.standalone, NORMAL_BACKEND_NAME) -+ -+ repl = ReplicationManager(DEFAULT_SUFFIX) -+ repl._ensure_changelog(topology_st.standalone) -+ replicas = Replicas(topology_st.standalone) -+ replicas.create(properties={ -+ 'cn': 'replica', -+ 'nsDS5ReplicaRoot': NORMAL_SUFFIX, -+ 'nsDS5ReplicaId': '1', -+ 'nsDS5Flags': '1', -+ 'nsDS5ReplicaType': '3' -+ }) -+ -+ _test_export_import(topology_st.standalone, NORMAL_SUFFIX, NORMAL_BACKEND_NAME) -+ -+def test_ticket50232_reverse(topology_st): -+ """ -+ The fix for ticket 50232 -+ -+ -+ The test sequence is: -+ - create suffix -+ - enable replication before suffix enztry is added -+ - add suffix entry and some child entries -+ - get RUV and database generation -+ - export -r -+ - import -+ - get RUV and database generation -+ - assert database generation has not changed -+ """ -+ -+ log.info('Testing Ticket 50232 - export creates not imprtable ldif file, normal creation order') -+ -+ # -+ # Setup Replication -+ # -+ log.info('Setting up replication...') -+ repl = ReplicationManager(DEFAULT_SUFFIX) -+ # repl.create_first_master(topology_st.standalone) -+ # -+ # enable dynamic plugins, memberof and retro cl plugin -+ # -+ topology_st.standalone.backend.create(REVERSE_SUFFIX, {BACKEND_NAME: REVERSE_BACKEND_NAME}) -+ topology_st.standalone.mappingtree.create(REVERSE_SUFFIX, bename=REVERSE_BACKEND_NAME, parent=None) -+ -+ _enable_replica(topology_st.standalone, REVERSE_SUFFIX) -+ -+ _populate_suffix(topology_st.standalone, REVERSE_BACKEND_NAME) -+ -+ _test_export_import(topology_st.standalone, REVERSE_SUFFIX, REVERSE_BACKEND_NAME) -+ -+if __name__ == '__main__': -+ # Run isolated -+ # -s for DEBUG mode -+ CURRENT_FILE = os.path.realpath(__file__) -+ pytest.main("-s %s" % CURRENT_FILE) -diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c -index 11c020af0..49fe7cd5d 100644 ---- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c -+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c -@@ -1103,6 +1103,7 @@ bail: - * (reunified at last) - */ - #define LDBM2LDIF_BUSY (-2) -+#define RUVRDN SLAPI_ATTR_UNIQUEID "=" RUV_STORAGE_ENTRY_UNIQUEID - int - ldbm_back_ldbm2ldif(Slapi_PBlock *pb) - { -@@ -1111,6 +1112,7 @@ ldbm_back_ldbm2ldif(Slapi_PBlock *pb) - DB *db = NULL; - DBC *dbc = NULL; - struct backentry *ep; -+ struct backentry *pending_ruv = NULL; - DBT key = {0}; - DBT data = {0}; - char *fname = NULL; -@@ -1146,6 +1148,8 @@ ldbm_back_ldbm2ldif(Slapi_PBlock *pb) - static int load_dse = 1; /* We'd like to load dse just once. */ - int server_running; - export_args eargs = {0}; -+ int32_t suffix_written = 0; -+ int32_t skip_ruv = 0; - - slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_ldbm2ldif", "=>\n"); - -@@ -1463,8 +1467,25 @@ ldbm_back_ldbm2ldif(Slapi_PBlock *pb) - } - } - -- if (0 != return_value) -+ if (DB_NOTFOUND == return_value) { -+ /* reached the end of the database, -+ * check if ruv is pending and write it -+ */ -+ if (pending_ruv) { -+ eargs.ep = pending_ruv; -+ eargs.idindex = idindex; -+ eargs.cnt = &cnt; -+ eargs.lastcnt = &lastcnt; -+ rc = export_one_entry(li, inst, &eargs); -+ backentry_free(&pending_ruv); -+ } -+ break; -+ } -+ -+ if (0 != return_value) { -+ /* error reading database */ - break; -+ } - - /* back to internal format */ - temp_id = id_stored_to_internal((char *)key.data); -@@ -1501,7 +1522,30 @@ ldbm_back_ldbm2ldif(Slapi_PBlock *pb) - rc = get_value_from_string((const char *)data.dptr, - LDBM_PARENTID_STR, &pid_str); - if (rc) { -- rc = 0; /* assume this is a suffix */ -+ /* this could be a suffix or the RUV entry. -+ * If it is the ruv and the suffix is not written -+ * keep the ruv and export as last entry. -+ * -+ * The reason for this is that if the RUV entry is in the -+ * ldif before the suffix entry then at an attempt to import -+ * that ldif the RUV entry would be skipped because the parent -+ * does not exist. Later a new RUV would be generated with -+ * a different database generation and replication is broken -+ */ -+ if (suffix_written) { -+ /* this must be the RUV, just continue and write it */ -+ rc = 0; -+ } else if (0 == strcasecmp(rdn, RUVRDN)) { -+ /* this is the RUV and the suffix is not yet written -+ * make it pending and continue with next entry -+ */ -+ skip_ruv = 1; -+ rc = 0; -+ } else { -+ /* this has to be the suffix */ -+ suffix_written = 1; -+ rc = 0; -+ } - } else { - pid = (ID)strtol(pid_str, (char **)NULL, 10); - slapi_ch_free_string(&pid_str); -@@ -1614,6 +1658,16 @@ ldbm_back_ldbm2ldif(Slapi_PBlock *pb) - continue; - } - -+ if (skip_ruv) { -+ /* now we keep a copy of the ruv entry -+ * and continue with the next entry -+ */ -+ pending_ruv = ep; -+ ep = NULL; -+ skip_ruv = 0; -+ continue; -+ } -+ - eargs.ep = ep; - eargs.idindex = idindex; - eargs.cnt = &cnt; --- -2.17.2 - diff --git a/SOURCES/0003-Issue-50529-LDAP-server-returning-PWP-controls-in-di.patch b/SOURCES/0003-Issue-50529-LDAP-server-returning-PWP-controls-in-di.patch new file mode 100644 index 0000000..a2c9297 --- /dev/null +++ b/SOURCES/0003-Issue-50529-LDAP-server-returning-PWP-controls-in-di.patch @@ -0,0 +1,37 @@ +From 606b7b6a45f6e2014119d0716774323f30862e0c Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 2 Aug 2019 12:07:07 -0400 +Subject: [PATCH] Issue 50529 - LDAP server returning PWP controls in + different sequence + +Description: The server returns password policy controls in different orders + depending on the state of grace logins. The requested control, + if any, should be returned first, followed by any controls the + server might add. + +relates: https://pagure.io/389-ds-base/issue/50529 + +Reviewed by: mreynolds (one line commit rule) +--- + ldap/servers/slapd/pw_mgmt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/pw_mgmt.c b/ldap/servers/slapd/pw_mgmt.c +index befac50cd..ca76fc12f 100644 +--- a/ldap/servers/slapd/pw_mgmt.c ++++ b/ldap/servers/slapd/pw_mgmt.c +@@ -207,10 +207,10 @@ skip: + + /* password expired and user exceeded limit of grace attemps. + * Send result and also the control */ +- slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0); + if (pwresponse_req) { + slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_PWDEXPIRED); + } ++ slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0); + slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, + "password expired!", 0, NULL); + +-- +2.21.0 + diff --git a/SOURCES/0003-Ticket-50234-one-level-search-returns-not-matching-e.patch b/SOURCES/0003-Ticket-50234-one-level-search-returns-not-matching-e.patch deleted file mode 100644 index cb36b7a..0000000 --- a/SOURCES/0003-Ticket-50234-one-level-search-returns-not-matching-e.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 94702aa0f07dcea5b7ebe7886b2fdc9ab0092cf4 Mon Sep 17 00:00:00 2001 -From: Ludwig Krispenz -Date: Thu, 21 Feb 2019 16:54:52 +0100 -Subject: [PATCH] Ticket 50234 - one level search returns not matching entry - -Bug: if in a onelevel search the IDList for the parentid is smaller than the filter - threshold and smaller than the list generated by the search filter - then the intersection is aborted and all children are returned. - -Fix: In the above case we need to set the flag that the filter evaluation - cannot be bypassed - -Reviewed by: William, Thierry. Thanks ---- - dirsrvtests/tests/tickets/ticket50234_test.py | 70 +++++++++++++++++++ - ldap/servers/slapd/back-ldbm/idl_set.c | 1 + - 2 files changed, 71 insertions(+) - create mode 100644 dirsrvtests/tests/tickets/ticket50234_test.py - -diff --git a/dirsrvtests/tests/tickets/ticket50234_test.py b/dirsrvtests/tests/tickets/ticket50234_test.py -new file mode 100644 -index 000000000..c605c4531 ---- /dev/null -+++ b/dirsrvtests/tests/tickets/ticket50234_test.py -@@ -0,0 +1,70 @@ -+# --- BEGIN COPYRIGHT BLOCK --- -+# Copyright (C) 2019 Red Hat, Inc. -+# All rights reserved. -+# -+# License: GPL (version 3 or any later version). -+# See LICENSE for details. -+# --- END COPYRIGHT BLOCK --- -+# -+import logging -+import time -+import ldap -+import pytest -+ -+from lib389.topologies import topology_st -+ -+from lib389._constants import DEFAULT_SUFFIX -+ -+from lib389.idm.user import UserAccount, UserAccounts -+from lib389.idm.organizationalunit import OrganizationalUnit -+ -+log = logging.getLogger(__name__) -+ -+def test_ticket50234(topology_st): -+ """ -+ The fix for ticket 50234 -+ -+ -+ The test sequence is: -+ - create more than 10 entries with objectclass organizational units ou=org{} -+ - add an Account in one of them, eg below ou=org5 -+ - do searches with search base ou=org5 and search filter "objectclass=organizationalunit" -+ - a subtree search should return 1 entry, the base entry -+ - a onelevel search should return no entry -+ """ -+ -+ log.info('Testing Ticket 50234 - onelvel search returns not matching entry') -+ -+ for i in range(1,15): -+ ou = OrganizationalUnit(topology_st.standalone, "ou=Org{},{}".format(i, DEFAULT_SUFFIX)) -+ ou.create(properties={'ou': 'Org'.format(i)}) -+ -+ properties = { -+ 'uid': 'Jeff Vedder', -+ 'cn': 'Jeff Vedder', -+ 'sn': 'user', -+ 'uidNumber': '1000', -+ 'gidNumber': '2000', -+ 'homeDirectory': '/home/' + 'JeffVedder', -+ 'userPassword': 'password' -+ } -+ user = UserAccount(topology_st.standalone, "cn=Jeff Vedder,ou=org5,{}".format(DEFAULT_SUFFIX)) -+ user.create(properties=properties) -+ -+ # in a subtree search the entry used as search base matches the filter and shoul be returned -+ ent = topology_st.standalone.getEntry("ou=org5,{}".format(DEFAULT_SUFFIX), ldap.SCOPE_SUBTREE, "(objectclass=organizationalunit)") -+ -+ # in a onelevel search the only child is an useraccount which does not match the filter -+ # no entry should be returned, which would cause getEntry to raise an exception we need to handle -+ found = 1 -+ try: -+ ent = topology_st.standalone.getEntry("ou=org5,{}".format(DEFAULT_SUFFIX), ldap.SCOPE_ONELEVEL, "(objectclass=organizationalunit)") -+ except ldap.NO_SUCH_OBJECT: -+ found = 0 -+ assert (found == 0) -+ -+if __name__ == '__main__': -+ # Run isolated -+ # -s for DEBUG mode -+ CURRENT_FILE = os.path.realpath(__file__) -+ pytest.main("-s %s" % CURRENT_FILE) -diff --git a/ldap/servers/slapd/back-ldbm/idl_set.c b/ldap/servers/slapd/back-ldbm/idl_set.c -index f9a900f1f..6b6586799 100644 ---- a/ldap/servers/slapd/back-ldbm/idl_set.c -+++ b/ldap/servers/slapd/back-ldbm/idl_set.c -@@ -371,6 +371,7 @@ idl_set_intersect(IDListSet *idl_set, backend *be) - result_list = idl_set->head; - } else if (idl_set->minimum->b_nids <= FILTER_TEST_THRESHOLD) { - result_list = idl_set->minimum; -+ slapi_be_set_flag(be, SLAPI_BE_FLAG_DONT_BYPASS_FILTERTEST); - - /* Free the other IDLs which are not the minimum. */ - IDList *next = NULL; --- -2.17.2 - diff --git a/SOURCES/0004-Issue-50091-shadowWarning-is-not-generated-if-passwo.patch b/SOURCES/0004-Issue-50091-shadowWarning-is-not-generated-if-passwo.patch deleted file mode 100644 index 5740e36..0000000 --- a/SOURCES/0004-Issue-50091-shadowWarning-is-not-generated-if-passwo.patch +++ /dev/null @@ -1,96 +0,0 @@ -From c3c7eabb2dae02977c0a7e1e659a0a928f8fa37d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Barbora=20Smejkalov=C3=A1?= -Date: Fri, 4 Jan 2019 09:14:34 +0100 -Subject: [PATCH] Issue 50091 - shadowWarning is not generated if - passwordWarning is lower than 86400 seconds (1 day). - -Description: -Added test case to check if shadowWarning attribute is generated when passwordWarning is set to lower value than 84600 seconds. - -https://pagure.io/389-ds-base/issue/50091 - -Reviewed by: vashirov, amsharma, spichugi, firstyear (Thank you!) ---- - .../suites/password/pwdPolicy_warning_test.py | 53 ++++++++++++++++++- - 1 file changed, 51 insertions(+), 2 deletions(-) - -diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py -index 1b955c66e..90b712e9e 100644 ---- a/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py -+++ b/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py -@@ -12,14 +12,14 @@ from ldap.controls.ppolicy import PasswordPolicyControl - from lib389.tasks import * - from lib389.utils import * - from lib389.topologies import topology_st -- -+from lib389.idm.user import UserAccounts - from lib389._constants import (DEFAULT_SUFFIX, DN_CONFIG, PASSWORD, DN_DM, - HOST_STANDALONE, PORT_STANDALONE, SERVERID_STANDALONE) - from dateutil.parser import parse as dt_parse - import datetime - - CONFIG_ATTR = 'passwordSendExpiringTime' --USER_DN = 'uid=tuser,{:s}'.format(DEFAULT_SUFFIX) -+USER_DN = 'uid=tuser,{}'.format(DEFAULT_SUFFIX) - USER_PASSWD = 'secret123' - - logging.getLogger(__name__).setLevel(logging.INFO) -@@ -546,6 +546,55 @@ def test_with_local_policy(topology_st, global_policy, local_policy): - topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) - - -+@pytest.mark.bz1589144 -+@pytest.mark.ds50091 -+def test_search_shadowWarning_when_passwordWarning_is_lower(topology_st, global_policy): -+ """Test if value shadowWarning is present with global password policy -+ when passwordWarning is set with lower value. -+ -+ :id: c1e82de6-1aa3-42c3-844a-9720172158a3 -+ :setup: Standalone Instance -+ :steps: -+ 1. Bind as Directory Manager -+ 2. Set global password policy -+ 3. Add test user to instance. -+ 4. Modify passwordWarning to have smaller value than 86400 -+ 5. Bind as the new user -+ 6. Search for shadowWarning attribute -+ 7. Rebind as Directory Manager -+ :expectedresults: -+ 1. Binding should be successful -+ 2. Setting password policy should be successful -+ 3. Adding test user should be successful -+ 4. Modifying passwordWarning should be successful -+ 5. Binding should be successful -+ 6. Attribute shadowWarning should be found -+ 7. Binding should be successful -+ """ -+ -+ users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX) -+ -+ log.info("Bind as %s" % DN_DM) -+ assert topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) -+ -+ log.info("Creating test user") -+ testuser = users.create_test_user(1004) -+ testuser.add('objectclass', 'shadowAccount') -+ testuser.set('userPassword', USER_PASSWD) -+ -+ log.info("Setting passwordWarning to smaller value than 86400") -+ assert topology_st.standalone.config.set('passwordWarning', '86399') -+ -+ log.info("Bind as test user") -+ assert topology_st.standalone.simple_bind_s(testuser.dn, USER_PASSWD) -+ -+ log.info("Check if attribute shadowWarning is present") -+ assert testuser.present('shadowWarning') -+ -+ log.info("Rebinding as DM") -+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) -+ -+ - if __name__ == '__main__': - # Run isolated - # -s for DEBUG mode --- -2.17.2 - diff --git a/SOURCES/0004-Issue-50538-cleanAllRUV-task-limit-is-not-enforced-f.patch b/SOURCES/0004-Issue-50538-cleanAllRUV-task-limit-is-not-enforced-f.patch new file mode 100644 index 0000000..e30d326 --- /dev/null +++ b/SOURCES/0004-Issue-50538-cleanAllRUV-task-limit-is-not-enforced-f.patch @@ -0,0 +1,682 @@ +From 59f03e332061b2c68bb53eed5949ddcfdc563300 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Wed, 7 Aug 2019 20:36:53 -0400 +Subject: [PATCH] Issue 50538 - cleanAllRUV task limit is not enforced for + replicated tasks + +Bug Description: + +There is a hard limit of 64 concurrent cleanAllRUV tasks, but this limit is +only enforced when creating "new" tasks. It was not enforced when a task was +received via an extended operation. There were also race conditions in the +existing logic that allowed the array of cleaned rids to get corrupted . This +allowed for a very large number of task threads to be created. + +Fix Description: + +Maintain a new counter to keep track of the number of clean and abort threads +to make sure it never over runs the rid array buffers. + +relates: https://pagure.io/389-ds-base/issue/50538 + +Reviewed by: lkrispenz(Thanks!) +--- + .../suites/replication/cleanallruv_test.py | 47 +++- + ldap/servers/plugins/replication/repl5.h | 7 +- + .../replication/repl5_replica_config.c | 247 ++++++++++-------- + ldap/servers/plugins/replication/repl_extop.c | 19 +- + 4 files changed, 202 insertions(+), 118 deletions(-) + +diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_test.py +index 620a53e1a..43801dd52 100644 +--- a/dirsrvtests/tests/suites/replication/cleanallruv_test.py ++++ b/dirsrvtests/tests/suites/replication/cleanallruv_test.py +@@ -1,5 +1,5 @@ + # --- BEGIN COPYRIGHT BLOCK --- +-# Copyright (C) 2016 Red Hat, Inc. ++# Copyright (C) 2019 Red Hat, Inc. + # All rights reserved. + # + # License: GPL (version 3 or any later version). +@@ -7,7 +7,6 @@ + # --- END COPYRIGHT BLOCK --- + # + import threading +- + import pytest + from lib389.tasks import * + from lib389.utils import * +@@ -859,6 +858,50 @@ def test_multiple_tasks_with_force(topology_m4): + restore_master4(topology_m4) + + ++def test_max_tasks(topology_m4): ++ """Test we can not create more than 64 cleaning tasks ++ ++ :id: c34d0b40-3c3e-4f53-8656-5e4c2a310a1f ++ :setup: Replication setup with four masters ++ :steps: ++ 1. Stop masters 3 & 4 ++ 2. Create over 64 tasks between m1 and m2 ++ 3. Check logs to see if (>65) tasks were rejected ++ ++ :expectedresults: ++ 1. Success ++ 2. Success ++ 3. Success ++ """ ++ ++ # Stop masters 3 & 4 ++ m1 = topology_m4.ms["master1"] ++ m2 = topology_m4.ms["master2"] ++ m3 = topology_m4.ms["master3"] ++ m4 = topology_m4.ms["master4"] ++ m3.stop() ++ m4.stop() ++ ++ # Add over 64 tasks between master1 & 2 to try to exceed the 64 task limit ++ for i in range(1, 64): ++ cruv_task = CleanAllRUVTask(m1) ++ cruv_task.create(properties={ ++ 'replica-id': str(i), ++ 'replica-base-dn': DEFAULT_SUFFIX, ++ 'replica-force-cleaning': 'no', # This forces these tasks to stick around ++ }) ++ cruv_task = CleanAllRUVTask(m2) ++ cruv_task.create(properties={ ++ 'replica-id': "10" + str(i), ++ 'replica-base-dn': DEFAULT_SUFFIX, ++ 'replica-force-cleaning': 'yes', # This allows the tasks to propagate ++ }) ++ ++ # Check the errors log for our error message in master 1 ++ assert m1.searchErrorsLog('Exceeded maximum number of active CLEANALLRUV tasks') ++>>>>>>> ab24aa4cb... Issue 50538 - cleanAllRUV task limit is not enforced for replicated tasks ++ ++ + if __name__ == '__main__': + # Run isolated + # -s for DEBUG mode +diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h +index 3c7f06f36..b06c6fbf4 100644 +--- a/ldap/servers/plugins/replication/repl5.h ++++ b/ldap/servers/plugins/replication/repl5.h +@@ -80,6 +80,8 @@ + #define CLEANRUV_FINISHED "finished" + #define CLEANRUV_CLEANING "cleaning" + #define CLEANRUV_NO_MAXCSN "no maxcsn" ++#define CLEANALLRUV_ID "CleanAllRUV Task" ++#define ABORT_CLEANALLRUV_ID "Abort CleanAllRUV Task" + + /* DS 5.0 replication protocol error codes */ + #define NSDS50_REPL_REPLICA_READY 0x00 /* Replica ready, go ahead */ +@@ -784,6 +786,7 @@ void multimaster_mtnode_construct_replicas(void); + void multimaster_be_state_change(void *handle, char *be_name, int old_be_state, int new_be_state); + + #define CLEANRIDSIZ 64 /* maximum number for concurrent CLEANALLRUV tasks */ ++#define CLEANRID_BUFSIZ 128 + + typedef struct _cleanruv_data + { +@@ -815,6 +818,8 @@ int get_replica_type(Replica *r); + int replica_execute_cleanruv_task_ext(Object *r, ReplicaId rid); + void add_cleaned_rid(cleanruv_data *data, char *maxcsn); + int is_cleaned_rid(ReplicaId rid); ++int32_t check_and_set_cleanruv_task_count(ReplicaId rid); ++int32_t check_and_set_abort_cleanruv_task_count(void); + int replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int *returncode, char *returntext, void *arg); + void replica_cleanallruv_thread_ext(void *arg); + void stop_ruv_cleaning(void); +@@ -833,8 +838,6 @@ void set_cleaned_rid(ReplicaId rid); + void cleanruv_log(Slapi_Task *task, int rid, char *task_type, int sev_level, char *fmt, ...); + char *replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn); + +- +- + /* replutil.c */ + LDAPControl *create_managedsait_control(void); + LDAPControl *create_backend_control(Slapi_DN *sdn); +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 62bfcf6ce..80a079784 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -30,17 +30,18 @@ + #define CLEANALLRUV "CLEANALLRUV" + #define CLEANALLRUVLEN 11 + #define REPLICA_RDN "cn=replica" +-#define CLEANALLRUV_ID "CleanAllRUV Task" +-#define ABORT_CLEANALLRUV_ID "Abort CleanAllRUV Task" + + int slapi_log_urp = SLAPI_LOG_REPL; +-static ReplicaId cleaned_rids[CLEANRIDSIZ + 1] = {0}; +-static ReplicaId pre_cleaned_rids[CLEANRIDSIZ + 1] = {0}; +-static ReplicaId aborted_rids[CLEANRIDSIZ + 1] = {0}; +-static Slapi_RWLock *rid_lock = NULL; +-static Slapi_RWLock *abort_rid_lock = NULL; ++static ReplicaId cleaned_rids[CLEANRID_BUFSIZ] = {0}; ++static ReplicaId pre_cleaned_rids[CLEANRID_BUFSIZ] = {0}; ++static ReplicaId aborted_rids[CLEANRID_BUFSIZ] = {0}; ++static PRLock *rid_lock = NULL; ++static PRLock *abort_rid_lock = NULL; + static PRLock *notify_lock = NULL; + static PRCondVar *notify_cvar = NULL; ++static PRLock *task_count_lock = NULL; ++static int32_t clean_task_count = 0; ++static int32_t abort_task_count = 0; + + /* Forward Declartions */ + static int replica_config_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg); +@@ -67,8 +68,6 @@ static int replica_cleanallruv_send_abort_extop(Repl_Agmt *ra, Slapi_Task *task, + static int replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *basedn, char *rid_text, char *maxcsn, Slapi_Task *task); + static int replica_cleanallruv_replica_alive(Repl_Agmt *agmt); + static int replica_cleanallruv_check_ruv(char *repl_root, Repl_Agmt *ra, char *rid_text, Slapi_Task *task, char *force); +-static int get_cleanruv_task_count(void); +-static int get_abort_cleanruv_task_count(void); + static int replica_cleanup_task(Object *r, const char *task_name, char *returntext, int apply_mods); + static int replica_task_done(Replica *replica); + static void delete_cleaned_rid_config(cleanruv_data *data); +@@ -114,20 +113,27 @@ replica_config_init() + PR_GetError()); + return -1; + } +- rid_lock = slapi_new_rwlock(); ++ rid_lock = PR_NewLock(); + if (rid_lock == NULL) { + slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_init - " + "Failed to create rid_lock; NSPR error - %d\n", + PR_GetError()); + return -1; + } +- abort_rid_lock = slapi_new_rwlock(); ++ abort_rid_lock = PR_NewLock(); + if (abort_rid_lock == NULL) { + slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_init - " + "Failed to create abort_rid_lock; NSPR error - %d\n", + PR_GetError()); + return -1; + } ++ task_count_lock = PR_NewLock(); ++ if (task_count_lock == NULL) { ++ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_init - " ++ "Failed to create task_count_lock; NSPR error - %d\n", ++ PR_GetError()); ++ return -1; ++ } + if ((notify_lock = PR_NewLock()) == NULL) { + slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_init - " + "Failed to create notify lock; NSPR error - %d\n", +@@ -1483,12 +1489,6 @@ replica_execute_cleanall_ruv_task(Object *r, ReplicaId rid, Slapi_Task *task, co + + cleanruv_log(pre_task, rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Initiating CleanAllRUV Task..."); + +- if (get_cleanruv_task_count() >= CLEANRIDSIZ) { +- /* we are already running the maximum number of tasks */ +- cleanruv_log(pre_task, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, +- "Exceeded maximum number of active CLEANALLRUV tasks(%d)", CLEANRIDSIZ); +- return LDAP_UNWILLING_TO_PERFORM; +- } + /* + * Grab the replica + */ +@@ -1540,6 +1540,13 @@ replica_execute_cleanall_ruv_task(Object *r, ReplicaId rid, Slapi_Task *task, co + goto fail; + } + ++ if (check_and_set_cleanruv_task_count(rid) != LDAP_SUCCESS) { ++ cleanruv_log(NULL, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, ++ "Exceeded maximum number of active CLEANALLRUV tasks(%d)", CLEANRIDSIZ); ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ goto fail; ++ } ++ + /* + * Launch the cleanallruv thread. Once all the replicas are cleaned it will release the rid + */ +@@ -1547,6 +1554,9 @@ replica_execute_cleanall_ruv_task(Object *r, ReplicaId rid, Slapi_Task *task, co + if (data == NULL) { + cleanruv_log(pre_task, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, "Failed to allocate cleanruv_data. Aborting task."); + rc = -1; ++ PR_Lock(task_count_lock); ++ clean_task_count--; ++ PR_Unlock(task_count_lock); + goto fail; + } + data->repl_obj = r; +@@ -1629,13 +1639,13 @@ replica_cleanallruv_thread(void *arg) + int aborted = 0; + int rc = 0; + +- if (!data || slapi_is_shutting_down()) { +- return; /* no data */ +- } +- + /* Increase active thread count to prevent a race condition at server shutdown */ + g_incr_active_threadcnt(); + ++ if (!data || slapi_is_shutting_down()) { ++ goto done; ++ } ++ + if (data->task) { + slapi_task_inc_refcount(data->task); + slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name, +@@ -1682,16 +1692,13 @@ replica_cleanallruv_thread(void *arg) + slapi_task_begin(data->task, 1); + } + /* +- * Presetting the rid prevents duplicate thread creation, but allows the db and changelog to still +- * process updates from the rid. +- * set_cleaned_rid() blocks updates, so we don't want to do that... yet unless we are in force mode. +- * If we are forcing a clean independent of state of other servers for this RID we can set_cleaned_rid() ++ * We have already preset this rid, but if we are forcing a clean independent of state ++ * of other servers for this RID we can set_cleaned_rid() + */ + if (data->force) { + set_cleaned_rid(data->rid); +- } else { +- preset_cleaned_rid(data->rid); + } ++ + rid_text = slapi_ch_smprintf("%d", data->rid); + csn_as_string(data->maxcsn, PR_FALSE, csnstr); + /* +@@ -1861,6 +1868,9 @@ done: + /* + * If the replicas are cleaned, release the rid + */ ++ if (slapi_is_shutting_down()) { ++ stop_ruv_cleaning(); ++ } + if (!aborted && !slapi_is_shutting_down()) { + /* + * Success - the rid has been cleaned! +@@ -1879,10 +1889,9 @@ done: + } else { + cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Propagated task does not delete Keep alive entry (%d).", data->rid); + } +- + clean_agmts(data); + remove_cleaned_rid(data->rid); +- cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Successfully cleaned rid(%d).", data->rid); ++ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Successfully cleaned rid(%d)", data->rid); + } else { + /* + * Shutdown or abort +@@ -1915,6 +1924,10 @@ done: + slapi_ch_free_string(&data->force); + slapi_ch_free_string(&rid_text); + slapi_ch_free((void **)&data); ++ /* decrement task count */ ++ PR_Lock(task_count_lock); ++ clean_task_count--; ++ PR_Unlock(task_count_lock); + g_decr_active_threadcnt(); + } + +@@ -2414,16 +2427,14 @@ replica_send_cleanruv_task(Repl_Agmt *agmt, cleanruv_data *clean_data) + int + is_cleaned_rid(ReplicaId rid) + { +- int i; +- +- slapi_rwlock_rdlock(rid_lock); +- for (i = 0; i < CLEANRIDSIZ && cleaned_rids[i] != 0; i++) { ++ PR_Lock(rid_lock); ++ for (size_t i = 0; i < CLEANRID_BUFSIZ; i++) { + if (rid == cleaned_rids[i]) { +- slapi_rwlock_unlock(rid_lock); ++ PR_Unlock(rid_lock); + return 1; + } + } +- slapi_rwlock_unlock(rid_lock); ++ PR_Unlock(rid_lock); + + return 0; + } +@@ -2431,16 +2442,14 @@ is_cleaned_rid(ReplicaId rid) + int + is_pre_cleaned_rid(ReplicaId rid) + { +- int i; +- +- slapi_rwlock_rdlock(rid_lock); +- for (i = 0; i < CLEANRIDSIZ && pre_cleaned_rids[i] != 0; i++) { ++ PR_Lock(rid_lock); ++ for (size_t i = 0; i < CLEANRID_BUFSIZ; i++) { + if (rid == pre_cleaned_rids[i]) { +- slapi_rwlock_unlock(rid_lock); ++ PR_Unlock(rid_lock); + return 1; + } + } +- slapi_rwlock_unlock(rid_lock); ++ PR_Unlock(rid_lock); + + return 0; + } +@@ -2453,14 +2462,14 @@ is_task_aborted(ReplicaId rid) + if (rid == 0) { + return 0; + } +- slapi_rwlock_rdlock(abort_rid_lock); +- for (i = 0; i < CLEANRIDSIZ && aborted_rids[i] != 0; i++) { ++ PR_Lock(abort_rid_lock); ++ for (i = 0; i < CLEANRID_BUFSIZ && aborted_rids[i] != 0; i++) { + if (rid == aborted_rids[i]) { +- slapi_rwlock_unlock(abort_rid_lock); ++ PR_Unlock(abort_rid_lock); + return 1; + } + } +- slapi_rwlock_unlock(abort_rid_lock); ++ PR_Unlock(abort_rid_lock); + return 0; + } + +@@ -2469,15 +2478,14 @@ preset_cleaned_rid(ReplicaId rid) + { + int i; + +- slapi_rwlock_wrlock(rid_lock); +- for (i = 0; i < CLEANRIDSIZ; i++) { ++ PR_Lock(rid_lock); ++ for (i = 0; i < CLEANRID_BUFSIZ && pre_cleaned_rids[i] != rid; i++) { + if (pre_cleaned_rids[i] == 0) { + pre_cleaned_rids[i] = rid; +- pre_cleaned_rids[i + 1] = 0; + break; + } + } +- slapi_rwlock_unlock(rid_lock); ++ PR_Unlock(rid_lock); + } + + /* +@@ -2490,14 +2498,13 @@ set_cleaned_rid(ReplicaId rid) + { + int i; + +- slapi_rwlock_wrlock(rid_lock); +- for (i = 0; i < CLEANRIDSIZ; i++) { ++ PR_Lock(rid_lock); ++ for (i = 0; i < CLEANRID_BUFSIZ && cleaned_rids[i] != rid; i++) { + if (cleaned_rids[i] == 0) { + cleaned_rids[i] = rid; +- cleaned_rids[i + 1] = 0; + } + } +- slapi_rwlock_unlock(rid_lock); ++ PR_Unlock(rid_lock); + } + + /* +@@ -2569,15 +2576,14 @@ add_aborted_rid(ReplicaId rid, Replica *r, char *repl_root) + int rc; + int i; + +- slapi_rwlock_wrlock(abort_rid_lock); +- for (i = 0; i < CLEANRIDSIZ; i++) { ++ PR_Lock(abort_rid_lock); ++ for (i = 0; i < CLEANRID_BUFSIZ; i++) { + if (aborted_rids[i] == 0) { + aborted_rids[i] = rid; +- aborted_rids[i + 1] = 0; + break; + } + } +- slapi_rwlock_unlock(abort_rid_lock); ++ PR_Unlock(abort_rid_lock); + /* + * Write the rid to the config entry + */ +@@ -2620,21 +2626,24 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip) + char *data; + char *dn; + int rc; +- int i; + + if (r == NULL) + return; + + if (skip) { + /* skip the deleting of the config, and just remove the in memory rid */ +- slapi_rwlock_wrlock(abort_rid_lock); +- for (i = 0; i < CLEANRIDSIZ && aborted_rids[i] != rid; i++) +- ; /* found rid, stop */ +- for (; i < CLEANRIDSIZ; i++) { +- /* rewrite entire array */ +- aborted_rids[i] = aborted_rids[i + 1]; +- } +- slapi_rwlock_unlock(abort_rid_lock); ++ ReplicaId new_abort_rids[CLEANRID_BUFSIZ] = {0}; ++ int32_t idx = 0; ++ ++ PR_Lock(abort_rid_lock); ++ for (size_t i = 0; i < CLEANRID_BUFSIZ; i++) { ++ if (aborted_rids[i] != rid) { ++ new_abort_rids[idx] = aborted_rids[i]; ++ idx++; ++ } ++ } ++ memcpy(aborted_rids, new_abort_rids, sizeof(new_abort_rids)); ++ PR_Unlock(abort_rid_lock); + } else { + /* only remove the config, leave the in-memory rid */ + dn = replica_get_dn(r); +@@ -2792,27 +2801,31 @@ bail: + void + remove_cleaned_rid(ReplicaId rid) + { +- int i; +- /* +- * Remove this rid, and optimize the array +- */ +- slapi_rwlock_wrlock(rid_lock); ++ ReplicaId new_cleaned_rids[CLEANRID_BUFSIZ] = {0}; ++ ReplicaId new_pre_cleaned_rids[CLEANRID_BUFSIZ] = {0}; ++ size_t idx = 0; ++ ++ PR_Lock(rid_lock); + +- for (i = 0; i < CLEANRIDSIZ && cleaned_rids[i] != rid; i++) +- ; /* found rid, stop */ +- for (; i < CLEANRIDSIZ; i++) { +- /* rewrite entire array */ +- cleaned_rids[i] = cleaned_rids[i + 1]; ++ for (size_t i = 0; i < CLEANRID_BUFSIZ; i++) { ++ if (cleaned_rids[i] != rid) { ++ new_cleaned_rids[idx] = cleaned_rids[i]; ++ idx++; ++ } + } ++ memcpy(cleaned_rids, new_cleaned_rids, sizeof(new_cleaned_rids)); ++ + /* now do the preset cleaned rids */ +- for (i = 0; i < CLEANRIDSIZ && pre_cleaned_rids[i] != rid; i++) +- ; /* found rid, stop */ +- for (; i < CLEANRIDSIZ; i++) { +- /* rewrite entire array */ +- pre_cleaned_rids[i] = pre_cleaned_rids[i + 1]; ++ idx = 0; ++ for (size_t i = 0; i < CLEANRID_BUFSIZ; i++) { ++ if (pre_cleaned_rids[i] != rid) { ++ new_pre_cleaned_rids[idx] = pre_cleaned_rids[i]; ++ idx++; ++ } + } ++ memcpy(pre_cleaned_rids, new_pre_cleaned_rids, sizeof(new_pre_cleaned_rids)); + +- slapi_rwlock_unlock(rid_lock); ++ PR_Unlock(rid_lock); + } + + /* +@@ -2840,16 +2853,6 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb __attribute__((unused)), + char *ridstr = NULL; + int rc = SLAPI_DSE_CALLBACK_OK; + +- if (get_abort_cleanruv_task_count() >= CLEANRIDSIZ) { +- /* we are already running the maximum number of tasks */ +- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, +- "Exceeded maximum number of active ABORT CLEANALLRUV tasks(%d)", +- CLEANRIDSIZ); +- cleanruv_log(task, -1, ABORT_CLEANALLRUV_ID, SLAPI_LOG_ERR, "%s", returntext); +- *returncode = LDAP_OPERATIONS_ERROR; +- return SLAPI_DSE_CALLBACK_ERROR; +- } +- + /* allocate new task now */ + task = slapi_new_task(slapi_entry_get_ndn(e)); + +@@ -2934,6 +2937,16 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb __attribute__((unused)), + */ + certify_all = "no"; + } ++ ++ if (check_and_set_abort_cleanruv_task_count() != LDAP_SUCCESS) { ++ /* we are already running the maximum number of tasks */ ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "Exceeded maximum number of active ABORT CLEANALLRUV tasks(%d)", ++ CLEANRIDSIZ); ++ cleanruv_log(task, -1, ABORT_CLEANALLRUV_ID, SLAPI_LOG_ERR, "%s", returntext); ++ *returncode = LDAP_UNWILLING_TO_PERFORM; ++ goto out; ++ } + /* + * Create payload + */ +@@ -3142,6 +3155,9 @@ done: + slapi_ch_free_string(&data->certify); + slapi_sdn_free(&data->sdn); + slapi_ch_free((void **)&data); ++ PR_Lock(task_count_lock); ++ abort_task_count--; ++ PR_Unlock(task_count_lock); + g_decr_active_threadcnt(); + } + +@@ -3493,36 +3509,43 @@ replica_cleanallruv_check_ruv(char *repl_root, Repl_Agmt *agmt, char *rid_text, + return rc; + } + +-static int +-get_cleanruv_task_count(void) ++/* ++ * Before starting a cleanAllRUV task make sure there are not ++ * too many task threads already running. If everything is okay ++ * also pre-set the RID now so rebounding extended ops do not ++ * try to clean it over and over. ++ */ ++int32_t ++check_and_set_cleanruv_task_count(ReplicaId rid) + { +- int i, count = 0; ++ int32_t rc = 0; + +- slapi_rwlock_wrlock(rid_lock); +- for (i = 0; i < CLEANRIDSIZ; i++) { +- if (pre_cleaned_rids[i] != 0) { +- count++; +- } ++ PR_Lock(task_count_lock); ++ if (clean_task_count >= CLEANRIDSIZ) { ++ rc = -1; ++ } else { ++ clean_task_count++; ++ preset_cleaned_rid(rid); + } +- slapi_rwlock_unlock(rid_lock); ++ PR_Unlock(task_count_lock); + +- return count; ++ return rc; + } + +-static int +-get_abort_cleanruv_task_count(void) ++int32_t ++check_and_set_abort_cleanruv_task_count(void) + { +- int i, count = 0; ++ int32_t rc = 0; + +- slapi_rwlock_wrlock(rid_lock); +- for (i = 0; i < CLEANRIDSIZ; i++) { +- if (aborted_rids[i] != 0) { +- count++; ++ PR_Lock(task_count_lock); ++ if (abort_task_count > CLEANRIDSIZ) { ++ rc = -1; ++ } else { ++ abort_task_count++; + } +- } +- slapi_rwlock_unlock(rid_lock); ++ PR_Unlock(task_count_lock); + +- return count; ++ return rc; + } + + /* +diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c +index 68e2544b4..0c2abb6d5 100644 +--- a/ldap/servers/plugins/replication/repl_extop.c ++++ b/ldap/servers/plugins/replication/repl_extop.c +@@ -1393,6 +1393,12 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + rc = LDAP_OPERATIONS_ERROR; + goto out; + } ++ if (check_and_set_abort_cleanruv_task_count() != LDAP_SUCCESS) { ++ cleanruv_log(NULL, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, ++ "Exceeded maximum number of active abort CLEANALLRUV tasks(%d)", CLEANRIDSIZ); ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ goto out; ++ } + /* + * Prepare the abort data + */ +@@ -1499,6 +1505,7 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + if (force == NULL) { + force = "no"; + } ++ + maxcsn = csn_new(); + csn_init_by_string(maxcsn, csnstr); + /* +@@ -1535,13 +1542,21 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + goto free_and_return; + } + ++ if (check_and_set_cleanruv_task_count((ReplicaId)rid) != LDAP_SUCCESS) { ++ cleanruv_log(NULL, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, ++ "Exceeded maximum number of active CLEANALLRUV tasks(%d)", CLEANRIDSIZ); ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ goto free_and_return; ++ } ++ + if (replica_get_type(r) != REPLICA_TYPE_READONLY) { + /* + * Launch the cleanruv monitoring thread. Once all the replicas are cleaned it will release the rid + * + * This will also release mtnode_ext->replica + */ +- slapi_log_err(SLAPI_LOG_INFO, repl_plugin_name, "multimaster_extop_cleanruv - CleanAllRUV Task - Launching cleanAllRUV thread...\n"); ++ ++ cleanruv_log(NULL, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, "Launching cleanAllRUV thread...\n"); + data = (cleanruv_data *)slapi_ch_calloc(1, sizeof(cleanruv_data)); + if (data == NULL) { + slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "multimaster_extop_cleanruv - CleanAllRUV Task - Failed to allocate " +@@ -1635,7 +1650,7 @@ free_and_return: + ber_printf(resp_bere, "{s}", CLEANRUV_ACCEPTED); + ber_flatten(resp_bere, &resp_bval); + slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, resp_bval); +- slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); ++ slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL); + /* resp_bere */ + if (NULL != resp_bere) { + ber_free(resp_bere, 1); +-- +2.21.0 + diff --git a/SOURCES/0005-Issue-49624-modrdn-silently-fails-if-DB-deadlock-occ.patch b/SOURCES/0005-Issue-49624-modrdn-silently-fails-if-DB-deadlock-occ.patch new file mode 100644 index 0000000..3323340 --- /dev/null +++ b/SOURCES/0005-Issue-49624-modrdn-silently-fails-if-DB-deadlock-occ.patch @@ -0,0 +1,39 @@ +From f50dfbb61224e6a9516b93cd3d3957c1fde4798e Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 22 Aug 2019 10:26:24 -0400 +Subject: [PATCH] Issue 49624 - modrdn silently fails if DB deadlock occurs + +Bug Description: + +If a DB Deadlock error occurs during a modrdn operation the entry +cache gets updated (corrupted), but the update is not applied to +the database. + +Fix Description: + +Looks like there was a copy & paste error, and the wrong attribute +was updated during the retry of the modrdn operation. + +relates: https://pagure.io/389-ds-base/issue/49624 + +Reviewed by: lkrispenz (Thanks!) +--- + ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +index 65610d613..433ed88fb 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +@@ -251,7 +251,7 @@ ldbm_back_modrdn(Slapi_PBlock *pb) + slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn); + slapi_sdn_free(&dn_newsuperiordn); + slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, orig_dn_newsuperiordn); +- orig_dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn); ++ dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn); + /* must duplicate ec before returning it to cache, + * which could free the entry. */ + if ((tmpentry = backentry_dup(original_entry ? original_entry : ec)) == NULL) { +-- +2.21.0 + diff --git a/SOURCES/0005-Ticket-50091-shadowWarning-is-not-generated-if-passw.patch b/SOURCES/0005-Ticket-50091-shadowWarning-is-not-generated-if-passw.patch deleted file mode 100644 index dbe4e5a..0000000 --- a/SOURCES/0005-Ticket-50091-shadowWarning-is-not-generated-if-passw.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 576774dc7cc0f7af7505f0f1a19b52e3c84c6625 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Fri, 14 Dec 2018 17:42:22 +0100 -Subject: [PATCH] Ticket 50091 - shadowWarning is not generated if - passwordWarning is lower than 86400 seconds (1 day) - -Bug Description: - For a shadowAccount, if a password policy defines passwordWarning below 1 days (86400 seconds) - then the shadowWarning (in day) is not returned from the entry. In such case its value is '0'. - -Fix Description: - The fix is to accept shadowWarning = 0 as valid value and return it - -https://pagure.io/389-ds-base/issue/50091 - -Reviewed by: Mark Reynolds - -Platforms tested: F27 - -Flag Day: no - -Doc impact: no ---- - ldap/servers/slapd/pw.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c -index ec23ed1a5..11149f51a 100644 ---- a/ldap/servers/slapd/pw.c -+++ b/ldap/servers/slapd/pw.c -@@ -2844,7 +2844,7 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e) - shadowval = _MAX_SHADOW; - } - } -- if (shadowval > 0) { -+ if (shadowval >= 0) { - shwarn = slapi_entry_attr_get_charptr(*e, "shadowWarning"); - if (shwarn) { - sval = strtoll(shwarn, NULL, 0); --- -2.17.2 - diff --git a/SOURCES/0006-Issue-50572-After-running-cl-dump-dbdir-cldb-ldif.do.patch b/SOURCES/0006-Issue-50572-After-running-cl-dump-dbdir-cldb-ldif.do.patch new file mode 100644 index 0000000..2e93871 --- /dev/null +++ b/SOURCES/0006-Issue-50572-After-running-cl-dump-dbdir-cldb-ldif.do.patch @@ -0,0 +1,153 @@ +From d8935139d377ad75be4242db7d3194f3706dc44a Mon Sep 17 00:00:00 2001 +From: Simon Pichugin +Date: Thu, 29 Aug 2019 15:51:56 +0200 +Subject: [PATCH] Issue 50572 - After running cl-dump dbdir/cldb/*ldif.done are + not deleted + +Description: By default, remove ldif.done files after running cl-dump. +Add an option '-l' which allows keep the files. +Update man files. + +https://pagure.io/389-ds-base/issue/50572 + +Reviewed by: firstyear, mreynolds (Thanks!) +--- + ldap/admin/src/scripts/cl-dump.pl | 23 +++++++++++++++-------- + man/man1/cl-dump.1 | 11 +++++++---- + 2 files changed, 22 insertions(+), 12 deletions(-) + +diff --git a/ldap/admin/src/scripts/cl-dump.pl b/ldap/admin/src/scripts/cl-dump.pl +index f4ad5dd33..2e7f20413 100755 +--- a/ldap/admin/src/scripts/cl-dump.pl ++++ b/ldap/admin/src/scripts/cl-dump.pl +@@ -5,7 +5,7 @@ + # All rights reserved. + # + # License: GPL (version 3 or any later version). +-# See LICENSE for details. ++# See LICENSE for details. + # END COPYRIGHT BLOCK + ################################################################################### + # +@@ -13,7 +13,7 @@ + # + # SYNOPSIS: + # cl-dump.pl [-h host] [-p port] [-D bind-dn] -w bind-password | -P bind-cert +-# [-r replica-roots] [-o output-file] [-c] [-v] ++# [-r replica-roots] [-o output-file] [-c] [-l] [-v] + # + # cl-dump.pl -i changelog-ldif-file-with-base64encoding [-o output-file] [-c] + # +@@ -22,7 +22,7 @@ + # + # OPTIONS: + # -c Dump and interpret CSN only. This option can be used with or +-# without -i option. ++# without -i option. + # + # -D bind-dn + # Directory server's bind DN. Default to "cn=Directory Manager" if +@@ -32,6 +32,8 @@ + # Directory server's host. Default to the server where the script + # is running. + # ++# -l Preserve generated ldif.done files from changelogdir ++# + # -i changelog-ldif-file-with-base64encoding + # If you already have a ldif-like changelog, but the changes + # in that file are encoded, you may use this option to +@@ -68,7 +70,7 @@ + # all of this nonsense can be omitted if the mozldapsdk and perldap are + # installed in the operating system locations (e.g. /usr/lib /usr/lib/perl5) + +-$usage="Usage: $0 [-h host] [-p port] [-D bind-dn] [-w bind-password | -P bind-cert] [-r replica-roots] [-o output-file] [-c] [-v]\n\n $0 -i changelog-ldif-file-with-base64encoding [-o output-file] [-c]\n"; ++$usage="Usage: $0 [-h host] [-p port] [-D bind-dn] [-w bind-password | -P bind-cert] [-r replica-roots] [-o output-file] [-c] [-l] [-v]\n\n $0 -i changelog-ldif-file-with-base64encoding [-o output-file] [-c]\n"; + + use Getopt::Std; # Parse command line arguments + use Mozilla::LDAP::Conn; # LDAP module for Perl +@@ -86,7 +88,7 @@ $version = "Directory Server Changelog Dump - Version 1.0"; + $| = 1; + + # Check for legal options +- if (!getopts('h:p:D:w:P:r:o:cvi:')) { ++ if (!getopts('h:p:D:w:P:r:o:clvi:')) { + print $usage; + exit -1; + } +@@ -123,7 +125,7 @@ sub validateArgs + if ($opt_o && ! open (OUTPUT, ">$opt_o")) { + print "Can't create output file $opt_o\n"; + $rc = -1; +- } ++ } + # Open STDOUT if option -o is missing + open (OUTPUT, ">-") if !$opt_o; + +@@ -194,10 +196,15 @@ sub cl_dump_and_decode + else { + &cl_decode ($_); + } +- # Test op -M doesn't work well so we use rename ++ # Test op -M doesn't work well so we use rename/remove + # here to avoid reading the same ldif file more + # than once. +- rename ($ldif, "$ldif.done"); ++ if ($opt_l) { ++ rename ($ldif, "$ldif.done"); ++ } else { ++ # Remove the file - default behaviou when '-l' is not specified ++ unlink ($ldif) ++ } + } + &print_header ($replica, "Not Found") if !$gotldif; + } +diff --git a/man/man1/cl-dump.1 b/man/man1/cl-dump.1 +index db736aca9..fbb836a72 100644 +--- a/man/man1/cl-dump.1 ++++ b/man/man1/cl-dump.1 +@@ -20,7 +20,7 @@ cl-dump \- Dump and decode Directory Server replication change log + .SH SYNOPSIS + .B cl\-dump + [\fI\-h host\fR] [\fI\-p port\fR] [\fI\-D bind\(hydn\fR] \-w bind\(hypassword | \-P bind\(hycert +- [\fI\-r replica\(hyroots\fR] [\fI\-o output\(hyfile\fR] [\fI\-c\fR] [\fI\-v\fR] ++ [\fI\-r replica\(hyroots\fR] [\fI\-o output\(hyfile\fR] [\fI\-c\fR] [\fI\-l\fR] [\fI\-v\fR] + + .PP + .B cl\-dump +@@ -30,12 +30,12 @@ cl-dump \- Dump and decode Directory Server replication change log + Dump and decode Directory Server replication change log + .PP + .\" TeX users may be more comfortable with the \fB\fP and +-.\" \fI\fP escape sequences to invode bold face and italics, ++.\" \fI\fP escape sequences to invode bold face and italics, + .\" respectively. + .SH OPTIONS + A summary of options is included below. + .TP +-.B \-c ++.B \-c + Dump and interpret CSN only. This option can be used with or + without \-i option. + .TP +@@ -47,6 +47,9 @@ the option is omitted. + Directory server's host. Default to the server where the script + is running. + .TP ++.B \-l ++Preserve generated ldif.done files from changelogdir ++.TP + .B \-i changelog\(hyldif\(hyfile\(hywith\(hybase64encoding + If you already have a ldif-like changelog, but the changes + in that file are encoded, you may use this option to +@@ -66,7 +69,7 @@ Specify replica roots whose changelog you want to dump. The replica + roots may be separated by comma. All the replica roots would be + dumped if the option is omitted. + .TP +-.B \-v ++.B \-v + Print the version of this script. + .TP + .B \-w bind\(hypassword +-- +2.21.0 + diff --git a/SOURCES/0006-Ticket-50260-backend-txn-plugins-can-corrupt-entry-c.patch b/SOURCES/0006-Ticket-50260-backend-txn-plugins-can-corrupt-entry-c.patch deleted file mode 100644 index c460987..0000000 --- a/SOURCES/0006-Ticket-50260-backend-txn-plugins-can-corrupt-entry-c.patch +++ /dev/null @@ -1,700 +0,0 @@ -From 669d0b288ca55a144fd1f5ba30199d2d2bb82061 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Thu, 7 Mar 2019 15:38:25 -0500 -Subject: [PATCH] Ticket 50260 - backend txn plugins can corrupt entry cache - -Bug Description: If a nested backend txn plugin fails, any updates - it made that went into the entry cache still persist - after the database transaction is aborted. - -Fix Description: In order to be sure the entry cache is not corrupted - after a backend txn plugin failure we need to flush - all the cache entries that were added to the cache - after the parent operation was started. - - To do this we record the start time the original operation, - (or parent operation), and we record the time any entry - is added to the cache. Then on failure we do a comparision - and remove the entry from the cache if it's not in use. - If it is in use we add a "invalid" flag which triggers - the entry to be removed when the cache entry is returned - by the owner. - -https://pagure.io/389-ds-base/issue/50260 - -CI tested and ASAN approved. - -Reviewed by: firstyear, tbordaz, and lkrispen (Thanks!!!) - -(cherry picked from commit 7ba8a80cfbaed9f6d727f98ed8c284943b3295e1) ---- - dirsrvtests/tests/suites/betxns/betxn_test.py | 114 ++++++++++++++++-- - ldap/servers/slapd/back-ldbm/back-ldbm.h | 68 ++++++----- - ldap/servers/slapd/back-ldbm/backentry.c | 3 +- - ldap/servers/slapd/back-ldbm/cache.c | 112 ++++++++++++++++- - ldap/servers/slapd/back-ldbm/ldbm_add.c | 14 +++ - ldap/servers/slapd/back-ldbm/ldbm_delete.c | 14 +++ - ldap/servers/slapd/back-ldbm/ldbm_modify.c | 14 +++ - ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 32 +++-- - .../servers/slapd/back-ldbm/proto-back-ldbm.h | 1 + - ldap/servers/slapd/slapi-plugin.h | 6 + - 10 files changed, 321 insertions(+), 57 deletions(-) - -diff --git a/dirsrvtests/tests/suites/betxns/betxn_test.py b/dirsrvtests/tests/suites/betxns/betxn_test.py -index 48181a9ea..f03fb93cc 100644 ---- a/dirsrvtests/tests/suites/betxns/betxn_test.py -+++ b/dirsrvtests/tests/suites/betxns/betxn_test.py -@@ -7,12 +7,10 @@ - # --- END COPYRIGHT BLOCK --- - # - import pytest --import six - import ldap - from lib389.tasks import * - from lib389.utils import * - from lib389.topologies import topology_st -- - from lib389._constants import DEFAULT_SUFFIX, PLUGIN_7_BIT_CHECK, PLUGIN_ATTR_UNIQUENESS, PLUGIN_MEMBER_OF - - logging.getLogger(__name__).setLevel(logging.DEBUG) -@@ -249,8 +247,8 @@ def test_betxn_memberof(topology_st, dynamic_plugins): - log.info('test_betxn_memberof: PASSED') - - --def test_betxn_modrdn_memberof(topology_st): -- """Test modrdn operartions and memberOf -+def test_betxn_modrdn_memberof_cache_corruption(topology_st): -+ """Test modrdn operations and memberOf - - :id: 70d0b96e-b693-4bf7-bbf5-102a66ac5994 - -@@ -285,18 +283,18 @@ def test_betxn_modrdn_memberof(topology_st): - - # Create user and add it to group - users = UserAccounts(topology_st.standalone, basedn=DEFAULT_SUFFIX) -- user = users.create(properties=TEST_USER_PROPERTIES) -+ user = users.ensure_state(properties=TEST_USER_PROPERTIES) - if not ds_is_older('1.3.7'): - user.remove('objectClass', 'nsMemberOf') - - group.add_member(user.dn) - - # Attempt modrdn that should fail, but the original entry should stay in the cache -- with pytest.raises(ldap.OBJECTCLASS_VIOLATION): -+ with pytest.raises(ldap.OBJECT_CLASS_VIOLATION): - group.rename('cn=group_to_people', newsuperior=peoplebase) - - # Should fail, but not with NO_SUCH_OBJECT as the original entry should still be in the cache -- with pytest.raises(ldap.OBJECTCLASS_VIOLATION): -+ with pytest.raises(ldap.OBJECT_CLASS_VIOLATION): - group.rename('cn=group_to_people', newsuperior=peoplebase) - - # -@@ -305,6 +303,108 @@ def test_betxn_modrdn_memberof(topology_st): - log.info('test_betxn_modrdn_memberof: PASSED') - - -+def test_ri_and_mep_cache_corruption(topology_st): -+ """Test RI plugin aborts change after MEP plugin fails. -+ This is really testing the entry cache for corruption -+ -+ :id: 70d0b96e-b693-4bf7-bbf5-102a66ac5995 -+ -+ :setup: Standalone instance -+ -+ :steps: 1. Enable and configure mep and ri plugins -+ 2. Add user and add it to a group -+ 3. Disable MEP plugin and remove MEP group -+ 4. Delete user -+ 5. Check that user is still a member of the group -+ -+ :expectedresults: -+ 1. Success -+ 2. Success -+ 3. Success -+ 4. It fails with NO_SUCH_OBJECT -+ 5. Success -+ -+ """ -+ # Start plugins -+ topology_st.standalone.config.set('nsslapd-dynamic-plugins', 'on') -+ mep_plugin = ManagedEntriesPlugin(topology_st.standalone) -+ mep_plugin.enable() -+ ri_plugin = ReferentialIntegrityPlugin(topology_st.standalone) -+ ri_plugin.enable() -+ -+ # Add our org units -+ ous = OrganizationalUnits(topology_st.standalone, DEFAULT_SUFFIX) -+ ou_people = ous.create(properties={'ou': 'managed_people'}) -+ ou_groups = ous.create(properties={'ou': 'managed_groups'}) -+ -+ # Configure MEP -+ mep_templates = MEPTemplates(topology_st.standalone, DEFAULT_SUFFIX) -+ mep_template1 = mep_templates.create(properties={ -+ 'cn': 'MEP template', -+ 'mepRDNAttr': 'cn', -+ 'mepStaticAttr': 'objectclass: posixGroup|objectclass: extensibleObject'.split('|'), -+ 'mepMappedAttr': 'cn: $cn|uid: $cn|gidNumber: $uidNumber'.split('|') -+ }) -+ mep_configs = MEPConfigs(topology_st.standalone) -+ mep_configs.create(properties={'cn': 'config', -+ 'originScope': ou_people.dn, -+ 'originFilter': 'objectclass=posixAccount', -+ 'managedBase': ou_groups.dn, -+ 'managedTemplate': mep_template1.dn}) -+ -+ # Add an entry that meets the MEP scope -+ users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX, -+ rdn='ou={}'.format(ou_people.rdn)) -+ user = users.create(properties={ -+ 'uid': 'test-user1', -+ 'cn': 'test-user', -+ 'sn': 'test-user', -+ 'uidNumber': '10011', -+ 'gidNumber': '20011', -+ 'homeDirectory': '/home/test-user1' -+ }) -+ -+ # Add group -+ groups = Groups(topology_st.standalone, DEFAULT_SUFFIX) -+ user_group = groups.ensure_state(properties={'cn': 'group', 'member': user.dn}) -+ -+ # Check if a managed group entry was created -+ mep_group = Group(topology_st.standalone, dn='cn={},{}'.format(user.rdn, ou_groups.dn)) -+ if not mep_group.exists(): -+ log.fatal("MEP group was not created for the user") -+ assert False -+ -+ # Mess with MEP so it fails -+ mep_plugin.disable() -+ mep_group.delete() -+ mep_plugin.enable() -+ -+ # Add another group for verify entry cache is not corrupted -+ test_group = groups.create(properties={'cn': 'test_group'}) -+ -+ # Delete user, should fail, and user should still be a member -+ with pytest.raises(ldap.NO_SUCH_OBJECT): -+ user.delete() -+ -+ # Verify membership is intact -+ if not user_group.is_member(user.dn): -+ log.fatal("Member was incorrectly removed from the group!! Or so it seems") -+ -+ # Restart server and test again in case this was a cache issue -+ topology_st.standalone.restart() -+ if user_group.is_member(user.dn): -+ log.info("The entry cache was corrupted") -+ assert False -+ -+ assert False -+ -+ # Verify test group is still found in entry cache by deleting it -+ test_group.delete() -+ -+ # Success -+ log.info("Test PASSED") -+ -+ - if __name__ == '__main__': - # Run isolated - # -s for DEBUG mode -diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h -index 4727961a9..6cac605c0 100644 ---- a/ldap/servers/slapd/back-ldbm/back-ldbm.h -+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h -@@ -312,48 +312,52 @@ typedef struct - - struct backcommon - { -- int ep_type; /* to distinguish backdn from backentry */ -- struct backcommon *ep_lrunext; /* for the cache */ -- struct backcommon *ep_lruprev; /* for the cache */ -- ID ep_id; /* entry id */ -- char ep_state; /* state in the cache */ --#define ENTRY_STATE_DELETED 0x1 /* entry is marked as deleted */ --#define ENTRY_STATE_CREATING 0x2 /* entry is being created; don't touch it */ --#define ENTRY_STATE_NOTINCACHE 0x4 /* cache_add failed; not in the cache */ -- int ep_refcnt; /* entry reference cnt */ -- size_t ep_size; /* for cache tracking */ -+ int32_t ep_type; /* to distinguish backdn from backentry */ -+ struct backcommon *ep_lrunext; /* for the cache */ -+ struct backcommon *ep_lruprev; /* for the cache */ -+ ID ep_id; /* entry id */ -+ uint8_t ep_state; /* state in the cache */ -+#define ENTRY_STATE_DELETED 0x1 /* entry is marked as deleted */ -+#define ENTRY_STATE_CREATING 0x2 /* entry is being created; don't touch it */ -+#define ENTRY_STATE_NOTINCACHE 0x4 /* cache_add failed; not in the cache */ -+#define ENTRY_STATE_INVALID 0x8 /* cache entry is invalid and needs to be removed */ -+ int32_t ep_refcnt; /* entry reference cnt */ -+ size_t ep_size; /* for cache tracking */ -+ struct timespec ep_create_time; /* the time the entry was added to the cache */ - }; - --/* From ep_type through ep_size MUST be identical to backcommon */ -+/* From ep_type through ep_create_time MUST be identical to backcommon */ - struct backentry - { -- int ep_type; /* to distinguish backdn from backentry */ -- struct backcommon *ep_lrunext; /* for the cache */ -- struct backcommon *ep_lruprev; /* for the cache */ -- ID ep_id; /* entry id */ -- char ep_state; /* state in the cache */ -- int ep_refcnt; /* entry reference cnt */ -- size_t ep_size; /* for cache tracking */ -- Slapi_Entry *ep_entry; /* real entry */ -+ int32_t ep_type; /* to distinguish backdn from backentry */ -+ struct backcommon *ep_lrunext; /* for the cache */ -+ struct backcommon *ep_lruprev; /* for the cache */ -+ ID ep_id; /* entry id */ -+ uint8_t ep_state; /* state in the cache */ -+ int32_t ep_refcnt; /* entry reference cnt */ -+ size_t ep_size; /* for cache tracking */ -+ struct timespec ep_create_time; /* the time the entry was added to the cache */ -+ Slapi_Entry *ep_entry; /* real entry */ - Slapi_Entry *ep_vlventry; -- void *ep_dn_link; /* linkage for the 3 hash */ -- void *ep_id_link; /* tables used for */ -- void *ep_uuid_link; /* looking up entries */ -- PRMonitor *ep_mutexp; /* protection for mods; make it reentrant */ -+ void *ep_dn_link; /* linkage for the 3 hash */ -+ void *ep_id_link; /* tables used for */ -+ void *ep_uuid_link; /* looking up entries */ -+ PRMonitor *ep_mutexp; /* protection for mods; make it reentrant */ - }; - --/* From ep_type through ep_size MUST be identical to backcommon */ -+/* From ep_type through ep_create_time MUST be identical to backcommon */ - struct backdn - { -- int ep_type; /* to distinguish backdn from backentry */ -- struct backcommon *ep_lrunext; /* for the cache */ -- struct backcommon *ep_lruprev; /* for the cache */ -- ID ep_id; /* entry id */ -- char ep_state; /* state in the cache; share ENTRY_STATE_* */ -- int ep_refcnt; /* entry reference cnt */ -- size_t ep_size; /* for cache tracking */ -+ int32_t ep_type; /* to distinguish backdn from backentry */ -+ struct backcommon *ep_lrunext; /* for the cache */ -+ struct backcommon *ep_lruprev; /* for the cache */ -+ ID ep_id; /* entry id */ -+ uint8_t ep_state; /* state in the cache; share ENTRY_STATE_* */ -+ int32_t ep_refcnt; /* entry reference cnt */ -+ size_t ep_size; /* for cache tracking */ -+ struct timespec ep_create_time; /* the time the entry was added to the cache */ - Slapi_DN *dn_sdn; -- void *dn_id_link; /* for hash table */ -+ void *dn_id_link; /* for hash table */ - }; - - /* for the in-core cache of entries */ -diff --git a/ldap/servers/slapd/back-ldbm/backentry.c b/ldap/servers/slapd/back-ldbm/backentry.c -index f2fe780db..972842bcb 100644 ---- a/ldap/servers/slapd/back-ldbm/backentry.c -+++ b/ldap/servers/slapd/back-ldbm/backentry.c -@@ -23,7 +23,8 @@ backentry_free(struct backentry **bep) - return; - } - ep = *bep; -- PR_ASSERT(ep->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_NOTINCACHE)); -+ -+ PR_ASSERT(ep->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_NOTINCACHE | ENTRY_STATE_INVALID)); - if (ep->ep_entry != NULL) { - slapi_entry_free(ep->ep_entry); - } -diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c -index 86e1f7b39..458d7912f 100644 ---- a/ldap/servers/slapd/back-ldbm/cache.c -+++ b/ldap/servers/slapd/back-ldbm/cache.c -@@ -56,11 +56,14 @@ - #define LOG(...) - #endif - --#define LRU_DETACH(cache, e) lru_detach((cache), (void *)(e)) -+typedef enum { -+ ENTRY_CACHE, -+ DN_CACHE, -+} CacheType; - -+#define LRU_DETACH(cache, e) lru_detach((cache), (void *)(e)) - #define CACHE_LRU_HEAD(cache, type) ((type)((cache)->c_lruhead)) - #define CACHE_LRU_TAIL(cache, type) ((type)((cache)->c_lrutail)) -- - #define BACK_LRU_NEXT(entry, type) ((type)((entry)->ep_lrunext)) - #define BACK_LRU_PREV(entry, type) ((type)((entry)->ep_lruprev)) - -@@ -185,6 +188,7 @@ new_hash(u_long size, u_long offset, HashFn hfn, HashTestFn tfn) - int - add_hash(Hashtable *ht, void *key, uint32_t keylen, void *entry, void **alt) - { -+ struct backcommon *back_entry = (struct backcommon *)entry; - u_long val, slot; - void *e; - -@@ -202,6 +206,7 @@ add_hash(Hashtable *ht, void *key, uint32_t keylen, void *entry, void **alt) - e = HASH_NEXT(ht, e); - } - /* ok, it's not already there, so add it */ -+ back_entry->ep_create_time = slapi_current_rel_time_hr(); - HASH_NEXT(ht, entry) = ht->slot[slot]; - ht->slot[slot] = entry; - return 1; -@@ -492,6 +497,89 @@ cache_make_hashes(struct cache *cache, int type) - } - } - -+/* -+ * Helper function for flush_hash() to calculate if the entry should be -+ * removed from the cache. -+ */ -+static int32_t -+flush_remove_entry(struct timespec *entry_time, struct timespec *start_time) -+{ -+ struct timespec diff; -+ -+ slapi_timespec_diff(entry_time, start_time, &diff); -+ if (diff.tv_sec >= 0) { -+ return 1; -+ } else { -+ return 0; -+ } -+} -+ -+/* -+ * Flush all the cache entries that were added after the "start time" -+ * This is called when a backend transaction plugin fails, and we need -+ * to remove all the possible invalid entries in the cache. -+ * -+ * If the ref count is 0, we can straight up remove it from the cache, but -+ * if the ref count is greater than 1, then the entry is currently in use. -+ * In the later case we set the entry state to ENTRY_STATE_INVALID, and -+ * when the owning thread cache_returns() the cache entry is automatically -+ * removed so another thread can not use/lock the invalid cache entry. -+ */ -+static void -+flush_hash(struct cache *cache, struct timespec *start_time, int32_t type) -+{ -+ void *e, *laste = NULL; -+ Hashtable *ht = cache->c_idtable; -+ -+ cache_lock(cache); -+ -+ for (size_t i = 0; i < ht->size; i++) { -+ e = ht->slot[i]; -+ while (e) { -+ struct backcommon *entry = (struct backcommon *)e; -+ uint64_t remove_it = 0; -+ if (flush_remove_entry(&entry->ep_create_time, start_time)) { -+ /* Mark the entry to be removed */ -+ slapi_log_err(SLAPI_LOG_CACHE, "flush_hash", "[%s] Removing entry id (%d)\n", -+ type ? "DN CACHE" : "ENTRY CACHE", entry->ep_id); -+ remove_it = 1; -+ } -+ laste = e; -+ e = HASH_NEXT(ht, e); -+ -+ if (remove_it) { -+ /* since we have the cache lock we know we can trust refcnt */ -+ entry->ep_state |= ENTRY_STATE_INVALID; -+ if (entry->ep_refcnt == 0) { -+ entry->ep_refcnt++; -+ lru_delete(cache, laste); -+ if (type == ENTRY_CACHE) { -+ entrycache_remove_int(cache, laste); -+ entrycache_return(cache, (struct backentry **)&laste); -+ } else { -+ dncache_remove_int(cache, laste); -+ dncache_return(cache, (struct backdn **)&laste); -+ } -+ } else { -+ /* Entry flagged for removal */ -+ slapi_log_err(SLAPI_LOG_CACHE, "flush_hash", -+ "[%s] Flagging entry to be removed later: id (%d) refcnt: %d\n", -+ type ? "DN CACHE" : "ENTRY CACHE", entry->ep_id, entry->ep_refcnt); -+ } -+ } -+ } -+ } -+ -+ cache_unlock(cache); -+} -+ -+void -+revert_cache(ldbm_instance *inst, struct timespec *start_time) -+{ -+ flush_hash(&inst->inst_cache, start_time, ENTRY_CACHE); -+ flush_hash(&inst->inst_dncache, start_time, DN_CACHE); -+} -+ - /* initialize the cache */ - int - cache_init(struct cache *cache, uint64_t maxsize, long maxentries, int type) -@@ -1142,7 +1230,7 @@ entrycache_return(struct cache *cache, struct backentry **bep) - } else { - ASSERT(e->ep_refcnt > 0); - if (!--e->ep_refcnt) { -- if (e->ep_state & ENTRY_STATE_DELETED) { -+ if (e->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_INVALID)) { - const char *ndn = slapi_sdn_get_ndn(backentry_get_sdn(e)); - if (ndn) { - /* -@@ -1154,6 +1242,13 @@ entrycache_return(struct cache *cache, struct backentry **bep) - LOG("entrycache_return -Failed to remove %s from dn table\n", ndn); - } - } -+ if (e->ep_state & ENTRY_STATE_INVALID) { -+ /* Remove it from the hash table before we free the back entry */ -+ slapi_log_err(SLAPI_LOG_CACHE, "entrycache_return", -+ "Finally flushing invalid entry: %d (%s)\n", -+ e->ep_id, backentry_get_ndn(e)); -+ entrycache_remove_int(cache, e); -+ } - backentry_free(bep); - } else { - lru_add(cache, e); -@@ -1535,7 +1630,7 @@ cache_lock_entry(struct cache *cache, struct backentry *e) - - /* make sure entry hasn't been deleted now */ - cache_lock(cache); -- if (e->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_NOTINCACHE)) { -+ if (e->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_NOTINCACHE | ENTRY_STATE_INVALID)) { - cache_unlock(cache); - PR_ExitMonitor(e->ep_mutexp); - LOG("<= cache_lock_entry (DELETED)\n"); -@@ -1696,7 +1791,14 @@ dncache_return(struct cache *cache, struct backdn **bdn) - } else { - ASSERT((*bdn)->ep_refcnt > 0); - if (!--(*bdn)->ep_refcnt) { -- if ((*bdn)->ep_state & ENTRY_STATE_DELETED) { -+ if ((*bdn)->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_INVALID)) { -+ if ((*bdn)->ep_state & ENTRY_STATE_INVALID) { -+ /* Remove it from the hash table before we free the back dn */ -+ slapi_log_err(SLAPI_LOG_CACHE, "dncache_return", -+ "Finally flushing invalid entry: %d (%s)\n", -+ (*bdn)->ep_id, slapi_sdn_get_dn((*bdn)->dn_sdn)); -+ dncache_remove_int(cache, (*bdn)); -+ } - backdn_free(bdn); - } else { - lru_add(cache, (void *)*bdn); -diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c -index 32c8e71ff..aa5b59aea 100644 ---- a/ldap/servers/slapd/back-ldbm/ldbm_add.c -+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c -@@ -97,6 +97,8 @@ ldbm_back_add(Slapi_PBlock *pb) - PRUint64 conn_id; - int op_id; - int result_sent = 0; -+ int32_t parent_op = 0; -+ struct timespec parent_time; - - if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) { - conn_id = 0; /* connection is NULL */ -@@ -147,6 +149,13 @@ ldbm_back_add(Slapi_PBlock *pb) - slapi_entry_delete_values(e, numsubordinates, NULL); - - dblayer_txn_init(li, &txn); -+ -+ if (txn.back_txn_txn == NULL) { -+ /* This is the parent operation, get the time */ -+ parent_op = 1; -+ parent_time = slapi_current_rel_time_hr(); -+ } -+ - /* the calls to perform searches require the parent txn if any - so set txn to the parent_txn until we begin the child transaction */ - if (parent_txn) { -@@ -1212,6 +1221,11 @@ ldbm_back_add(Slapi_PBlock *pb) - slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); - } - slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); -+ -+ /* Revert the caches if this is the parent operation */ -+ if (parent_op) { -+ revert_cache(inst, &parent_time); -+ } - goto error_return; - } - -diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c -index f5f6c1e3a..3f687eb91 100644 ---- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c -+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c -@@ -79,6 +79,8 @@ ldbm_back_delete(Slapi_PBlock *pb) - ID tomb_ep_id = 0; - int result_sent = 0; - Connection *pb_conn; -+ int32_t parent_op = 0; -+ struct timespec parent_time; - - if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) { - conn_id = 0; /* connection is NULL */ -@@ -100,6 +102,13 @@ ldbm_back_delete(Slapi_PBlock *pb) - dblayer_txn_init(li, &txn); - /* the calls to perform searches require the parent txn if any - so set txn to the parent_txn until we begin the child transaction */ -+ -+ if (txn.back_txn_txn == NULL) { -+ /* This is the parent operation, get the time */ -+ parent_op = 1; -+ parent_time = slapi_current_rel_time_hr(); -+ } -+ - if (parent_txn) { - txn.back_txn_txn = parent_txn; - } else { -@@ -1270,6 +1279,11 @@ replace_entry: - slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &retval); - } - slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); -+ -+ /* Revert the caches if this is the parent operation */ -+ if (parent_op) { -+ revert_cache(inst, &parent_time); -+ } - goto error_return; - } - if (parent_found) { -diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c -index cc4319e5f..b90b3e0f0 100644 ---- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c -+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c -@@ -412,6 +412,8 @@ ldbm_back_modify(Slapi_PBlock *pb) - int fixup_tombstone = 0; - int ec_locked = 0; - int result_sent = 0; -+ int32_t parent_op = 0; -+ struct timespec parent_time; - - slapi_pblock_get(pb, SLAPI_BACKEND, &be); - slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &li); -@@ -426,6 +428,13 @@ ldbm_back_modify(Slapi_PBlock *pb) - dblayer_txn_init(li, &txn); /* must do this before first goto error_return */ - /* the calls to perform searches require the parent txn if any - so set txn to the parent_txn until we begin the child transaction */ -+ -+ if (txn.back_txn_txn == NULL) { -+ /* This is the parent operation, get the time */ -+ parent_op = 1; -+ parent_time = slapi_current_rel_time_hr(); -+ } -+ - if (parent_txn) { - txn.back_txn_txn = parent_txn; - } else { -@@ -864,6 +873,11 @@ ldbm_back_modify(Slapi_PBlock *pb) - slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); - } - slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); -+ -+ /* Revert the caches if this is the parent operation */ -+ if (parent_op) { -+ revert_cache(inst, &parent_time); -+ } - goto error_return; - } - retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN); -diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -index e4d0337d4..73e50ebcc 100644 ---- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -@@ -97,6 +97,8 @@ ldbm_back_modrdn(Slapi_PBlock *pb) - int op_id; - int result_sent = 0; - Connection *pb_conn = NULL; -+ int32_t parent_op = 0; -+ struct timespec parent_time; - - if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) { - conn_id = 0; /* connection is NULL */ -@@ -134,6 +136,13 @@ ldbm_back_modrdn(Slapi_PBlock *pb) - - /* dblayer_txn_init needs to be called before "goto error_return" */ - dblayer_txn_init(li, &txn); -+ -+ if (txn.back_txn_txn == NULL) { -+ /* This is the parent operation, get the time */ -+ parent_op = 1; -+ parent_time = slapi_current_rel_time_hr(); -+ } -+ - /* the calls to perform searches require the parent txn if any - so set txn to the parent_txn until we begin the child transaction */ - if (parent_txn) { -@@ -1208,6 +1217,11 @@ ldbm_back_modrdn(Slapi_PBlock *pb) - slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); - } - slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); -+ -+ /* Revert the caches if this is the parent operation */ -+ if (parent_op) { -+ revert_cache(inst, &parent_time); -+ } - goto error_return; - } - retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN); -@@ -1353,8 +1367,13 @@ error_return: - slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); - } - slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); -+ -+ /* Revert the caches if this is the parent operation */ -+ if (parent_op) { -+ revert_cache(inst, &parent_time); -+ } - } -- retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN); -+ retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN); - - /* Release SERIAL LOCK */ - dblayer_txn_abort(be, &txn); /* abort crashes in case disk full */ -@@ -1411,17 +1430,6 @@ common_return: - "operation failed, the target entry is cleared from dncache (%s)\n", slapi_entry_get_dn(ec->ep_entry)); - CACHE_REMOVE(&inst->inst_dncache, bdn); - CACHE_RETURN(&inst->inst_dncache, &bdn); -- /* -- * If the new/invalid entry (ec) is in the cache, that means we need to -- * swap it out with the original entry (e) --> to undo the swap that -- * modrdn_rename_entry_update_indexes() did. -- */ -- if (cache_is_in_cache(&inst->inst_cache, ec)) { -- if (cache_replace(&inst->inst_cache, ec, e) != 0) { -- slapi_log_err(SLAPI_LOG_ALERT, "ldbm_back_modrdn", -- "failed to replace cache entry after error\n"); -- } -- } - } - - if (ec && inst) { -diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h -index b56f6ef26..e68765bd4 100644 ---- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h -+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h -@@ -55,6 +55,7 @@ void cache_unlock_entry(struct cache *cache, struct backentry *e); - int cache_replace(struct cache *cache, void *oldptr, void *newptr); - int cache_has_otherref(struct cache *cache, void *bep); - int cache_is_in_cache(struct cache *cache, void *ptr); -+void revert_cache(ldbm_instance *inst, struct timespec *start_time); - - #ifdef CACHE_DEBUG - void check_entry_cache(struct cache *cache, struct backentry *e); -diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h -index 54c195eef..0bc3a6fab 100644 ---- a/ldap/servers/slapd/slapi-plugin.h -+++ b/ldap/servers/slapd/slapi-plugin.h -@@ -6765,6 +6765,12 @@ time_t slapi_current_time(void) __attribute__((deprecated)); - * \return timespec of the current relative system time. - */ - struct timespec slapi_current_time_hr(void); -+/** -+ * Returns the current system time as a hr clock -+ * -+ * \return timespec of the current monotonic time. -+ */ -+struct timespec slapi_current_rel_time_hr(void); - /** - * Returns the current system time as a hr clock in UTC timezone. - * This clock adjusts with ntp steps, and should NOT be --- -2.17.2 - diff --git a/SOURCES/0007-Issue-50538-Fix-cherry-pick-error.patch b/SOURCES/0007-Issue-50538-Fix-cherry-pick-error.patch new file mode 100644 index 0000000..7260efe --- /dev/null +++ b/SOURCES/0007-Issue-50538-Fix-cherry-pick-error.patch @@ -0,0 +1,27 @@ +From 5fee4d79db94684d8093501fde3422ad34ac2716 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 3 Sep 2019 13:40:27 -0400 +Subject: [PATCH] Issue 50538 - Fix cherry-pick error + +Description: Remove cherry-=pick error formating + +relates: https://pagure.io/389-ds-base/issue/50538 +--- + dirsrvtests/tests/suites/replication/cleanallruv_test.py | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_test.py +index 43801dd52..caf214b19 100644 +--- a/dirsrvtests/tests/suites/replication/cleanallruv_test.py ++++ b/dirsrvtests/tests/suites/replication/cleanallruv_test.py +@@ -899,7 +899,6 @@ def test_max_tasks(topology_m4): + + # Check the errors log for our error message in master 1 + assert m1.searchErrorsLog('Exceeded maximum number of active CLEANALLRUV tasks') +->>>>>>> ab24aa4cb... Issue 50538 - cleanAllRUV task limit is not enforced for replicated tasks + + + if __name__ == '__main__': +-- +2.21.0 + diff --git a/SOURCES/0007-Ticket-50077-Do-not-automatically-turn-automember-po.patch b/SOURCES/0007-Ticket-50077-Do-not-automatically-turn-automember-po.patch deleted file mode 100644 index 46ad200..0000000 --- a/SOURCES/0007-Ticket-50077-Do-not-automatically-turn-automember-po.patch +++ /dev/null @@ -1,55 +0,0 @@ -From addb07130e93bf8acb32178190451ba7cc9cc888 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Tue, 12 Mar 2019 16:03:29 -0400 -Subject: [PATCH] Ticket 50077 - Do not automatically turn automember postop - modifies on - -Description: Although we have set the new postop processing on by - default in the template-dse.ldif, we do not want to - enable it by default for upgrades (only new installs). - - So if the attribute is not set, it is assumed "off". - -https://pagure.io/389-ds-base/issue/50077 - -Reviewed by: firstyear(Thanks!) - -(cherry picked from commit d318d060f49b67ed1b10f22b52f98e038afa356a) ---- - ldap/servers/plugins/automember/automember.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c -index abd6df805..bb6ff1f8e 100644 ---- a/ldap/servers/plugins/automember/automember.c -+++ b/ldap/servers/plugins/automember/automember.c -@@ -90,7 +90,7 @@ static void automember_task_export_destructor(Slapi_Task *task); - static void automember_task_map_destructor(Slapi_Task *task); - - #define DEFAULT_FILE_MODE PR_IRUSR | PR_IWUSR --static uint64_t plugin_do_modify = 1; -+static uint64_t plugin_do_modify = 0; - static uint64_t plugin_is_betxn = 0; - - /* -@@ -345,15 +345,14 @@ automember_start(Slapi_PBlock *pb) - } - - /* Check and set if we should process modify operations */ -- plugin_do_modify = 1; /* default is "on" */ - if ((slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &plugin_entry) == 0) && plugin_entry){ - if ((do_modify = slapi_fetch_attr(plugin_entry, AUTOMEMBER_DO_MODIFY, NULL)) ) { - if (strcasecmp(do_modify, "on") && strcasecmp(do_modify, "off")) { - slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM, - "automember_start - %s: invalid value \"%s\". Valid values are \"on\" or \"off\". Using default of \"on\"\n", - AUTOMEMBER_DO_MODIFY, do_modify); -- } else if (strcasecmp(do_modify, "off") == 0 ){ -- plugin_do_modify = 0; -+ } else if (strcasecmp(do_modify, "on") == 0 ){ -+ plugin_do_modify = 1; - } - } - } --- -2.17.2 - diff --git a/SOURCES/0008-Issue-50646-Improve-task-handling-during-shutdowns.patch b/SOURCES/0008-Issue-50646-Improve-task-handling-during-shutdowns.patch new file mode 100644 index 0000000..30eabd6 --- /dev/null +++ b/SOURCES/0008-Issue-50646-Improve-task-handling-during-shutdowns.patch @@ -0,0 +1,172 @@ +From 81587cabb358bb24d0ae2623076e09676a4a0620 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 15 Oct 2019 11:02:24 -0400 +Subject: [PATCH] Issue 50646 - Improve task handling during shutdowns + +Bug Description: There is a race condition when stopping the server and + a running import task that can cause a heap-use-after-free. + +Fix Description: For an import task, encapsulate the import thread with + a global thread increment/decrement (just like the export + task). Also improved how tasks are notified to abort by + notifiying them before we wait for active threads to finish. + Then the tasks get destroyed after all threads are complete. + +relates: https://pagure.io/389-ds-base/issue/50646 + +Reviewed by: lkrispen & tbordaz (Thanks!!) +--- + ldap/servers/slapd/back-ldbm/import.c | 3 ++ + ldap/servers/slapd/daemon.c | 5 ++++ + ldap/servers/slapd/main.c | 2 +- + ldap/servers/slapd/slapi-private.h | 1 + + ldap/servers/slapd/task.c | 40 +++++++++++++++++---------- + 5 files changed, 35 insertions(+), 16 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/import.c b/ldap/servers/slapd/back-ldbm/import.c +index 42e2696d3..1c21f6e55 100644 +--- a/ldap/servers/slapd/back-ldbm/import.c ++++ b/ldap/servers/slapd/back-ldbm/import.c +@@ -1626,7 +1626,10 @@ error: + void + import_main(void *arg) + { ++ /* For online import tasks increment/decrement the global thread count */ ++ g_incr_active_threadcnt(); + import_main_offline(arg); ++ g_decr_active_threadcnt(); + } + + int +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index afe0fb737..5d8767df6 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -1218,6 +1218,11 @@ slapd_daemon(daemon_ports_t *ports, ns_thrpool_t *tp) + ns_thrpool_wait(tp); + } + ++ if (!in_referral_mode) { ++ /* signal tasks to start shutting down */ ++ task_cancel_all(); ++ } ++ + threads = g_get_active_threadcnt(); + if (threads > 0) { + slapi_log_err(SLAPI_LOG_INFO, "slapd_daemon", +diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c +index 5e24b3b5f..5ca52ce74 100644 +--- a/ldap/servers/slapd/main.c ++++ b/ldap/servers/slapd/main.c +@@ -1989,7 +1989,7 @@ lookup_plugin_by_instance_name(const char *name) + { + Slapi_Entry **entries = NULL; + Slapi_PBlock *pb = slapi_pblock_new(); +- struct slapdplugin *plugin; ++ struct slapdplugin *plugin = NULL; + char *query, *dn, *cn; + int ret = 0; + +diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h +index b347b6162..d676486a8 100644 +--- a/ldap/servers/slapd/slapi-private.h ++++ b/ldap/servers/slapd/slapi-private.h +@@ -794,6 +794,7 @@ int slapi_lookup_instance_name_by_suffix(char *suffix, + + /* begin and end the task subsystem */ + void task_init(void); ++void task_cancel_all(void); + void task_shutdown(void); + void task_cleanup(void); + +diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c +index 80a238392..7e7094750 100644 +--- a/ldap/servers/slapd/task.c ++++ b/ldap/servers/slapd/task.c +@@ -26,7 +26,7 @@ + */ + static Slapi_Task *global_task_list = NULL; + static PRLock *global_task_lock = NULL; +-static int shutting_down = 0; ++static uint64_t shutting_down = 0; + + /*********************************** + * Private Defines +@@ -588,7 +588,7 @@ new_task(const char *rawdn, void *plugin) + Slapi_Task *task = NULL; + char *dn = NULL; + +- if (rawdn == NULL) { ++ if (rawdn == NULL || shutting_down) { + return NULL; + } + +@@ -600,9 +600,20 @@ new_task(const char *rawdn, void *plugin) + } + task = (Slapi_Task *)slapi_ch_calloc(1, sizeof(Slapi_Task)); + PR_Lock(global_task_lock); ++ if (shutting_down) { ++ /* Abort! Free everything and return NULL */ ++ PR_Unlock(task->task_log_lock); ++ PR_Unlock(global_task_lock); ++ PR_DestroyLock(task->task_log_lock); ++ slapi_ch_free((void **)&task); ++ slapi_ch_free_string(&dn); ++ slapi_log_err(SLAPI_LOG_ERR, "new_task", "Server is shutting down, aborting task: %s\n", rawdn); ++ return NULL; ++ } + task->next = global_task_list; + global_task_list = task; + PR_Unlock(global_task_lock); ++ + task->task_dn = dn; + task->task_state = SLAPI_TASK_SETUP; + task->task_flags = SLAPI_TASK_RUNNING_AS_TASK; +@@ -2990,32 +3001,31 @@ task_init(void) + + /* called when the server is shutting down -- abort all existing tasks */ + void +-task_shutdown(void) +-{ ++task_cancel_all(void) { + Slapi_Task *task; +- int found_any = 0; + +- /* first, cancel all tasks */ + PR_Lock(global_task_lock); + shutting_down = 1; + for (task = global_task_list; task; task = task->next) { +- if ((task->task_state != SLAPI_TASK_CANCELLED) && +- (task->task_state != SLAPI_TASK_FINISHED)) { ++ if (task->task_state != SLAPI_TASK_CANCELLED && ++ task->task_state != SLAPI_TASK_FINISHED) ++ { + task->task_state = SLAPI_TASK_CANCELLED; + if (task->cancel) { +- slapi_log_err(SLAPI_LOG_INFO, "task_shutdown", "Cancelling task '%s'\n", ++ slapi_log_err(SLAPI_LOG_INFO, "task_cancel_all", "Canceling task '%s'\n", + task->task_dn); + (*task->cancel)(task); +- found_any = 1; + } + } + } ++ PR_Unlock(global_task_lock); ++} + +- if (found_any) { +- /* give any tasks 1 second to say their last rites */ +- DS_Sleep(PR_SecondsToInterval(1)); +- } +- ++void ++task_shutdown(void) ++{ ++ /* Now we can destroy the tasks... */ ++ PR_Lock(global_task_lock); + while (global_task_list) { + destroy_task(0, global_task_list); + } +-- +2.21.0 + diff --git a/SOURCES/0008-Ticket-50282-OPERATIONS-ERROR-when-trying-to-delete-.patch b/SOURCES/0008-Ticket-50282-OPERATIONS-ERROR-when-trying-to-delete-.patch deleted file mode 100644 index f75b8d7..0000000 --- a/SOURCES/0008-Ticket-50282-OPERATIONS-ERROR-when-trying-to-delete-.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 57f661a8acea18aa19985d0556a78d81a9361b89 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Thu, 14 Mar 2019 17:33:35 +0100 -Subject: [PATCH 1/4] Ticket 50282 - OPERATIONS ERROR when trying to delete a - group with automember members - -Bug Description: - When automember and memberof are enabled, if a user is member of a group - because of an automember rule. Then when the group is deleted, - memberof updates the member (to update 'memberof' attribute) that - trigger automember to reevaluate the automember rule and add the member - to the group. But at this time the group is already deleted. - Chaining back the failure up to the top level operation the deletion - of the group fails - -Fix Description: - The fix consists to check that if a automember rule tries to add a user - in a group, then to check that the group exists before updating it. - -https://pagure.io/389-ds-base/issue/50282 - -Reviewed by: Mark Reynolds, William Brown - -Platforms tested: F29 - -Flag Day: no - -Doc impact: no ---- - ldap/servers/plugins/automember/automember.c | 23 ++++++++++++++++++++ - 1 file changed, 23 insertions(+) - -diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c -index bb6ff1f8e..fcf0cdb9a 100644 ---- a/ldap/servers/plugins/automember/automember.c -+++ b/ldap/servers/plugins/automember/automember.c -@@ -1636,6 +1636,29 @@ automember_update_member_value(Slapi_Entry *member_e, const char *group_dn, char - char *member_value = NULL; - int freeit = 0; - int rc = 0; -+ Slapi_DN *group_sdn; -+ Slapi_Entry *group_entry = NULL; -+ -+ /* First thing check that the group still exists */ -+ group_sdn = slapi_sdn_new_dn_byval(group_dn); -+ rc = slapi_search_internal_get_entry(group_sdn, NULL, &group_entry, automember_get_plugin_id()); -+ slapi_sdn_free(&group_sdn); -+ if (rc != LDAP_SUCCESS || group_entry == NULL) { -+ if (rc == LDAP_NO_SUCH_OBJECT) { -+ /* the automember group (default or target) does not exist, just skip this definition */ -+ slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM, -+ "automember_update_member_value - group (default or target) does not exist (%s)\n", -+ group_dn); -+ rc = 0; -+ } else { -+ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM, -+ "automember_update_member_value - group (default or target) can not be retrieved (%s) err=%d\n", -+ group_dn, rc); -+ } -+ slapi_entry_free(group_entry); -+ return rc; -+ } -+ slapi_entry_free(group_entry); - - /* If grouping_value is dn, we need to fetch the dn instead. */ - if (slapi_attr_type_cmp(grouping_value, "dn", SLAPI_TYPE_CMP_EXACT) == 0) { --- -2.17.2 - diff --git a/SOURCES/0009-Issue-50653-objectclass-parsing-fails-to-log-error-m.patch b/SOURCES/0009-Issue-50653-objectclass-parsing-fails-to-log-error-m.patch new file mode 100644 index 0000000..7ad32f8 --- /dev/null +++ b/SOURCES/0009-Issue-50653-objectclass-parsing-fails-to-log-error-m.patch @@ -0,0 +1,69 @@ +From df8ad0467a6c5e69b8bd5f48e23582734d78b356 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Wed, 16 Oct 2019 14:16:55 -0400 +Subject: [PATCH] Issue 50653 - objectclass parsing fails to log error message + text + +Description: When replacing an objectclass, if it already exists we + log an error but we do not log what objectclass it is. + This commit adds the error message text. + +relates: https://pagure.io/389-ds-base/issue/50653 + +Reviewed by: abbra(Thanks!) +--- + ldap/servers/slapd/schema.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c +index 68c98341a..e4f0d663e 100644 +--- a/ldap/servers/slapd/schema.c ++++ b/ldap/servers/slapd/schema.c +@@ -126,7 +126,7 @@ static struct dse *pschemadse = NULL; + + static void oc_add_nolock(struct objclass *newoc); + static int oc_delete_nolock(char *ocname); +-static int oc_replace_nolock(const char *ocname, struct objclass *newoc); ++static int oc_replace_nolock(const char *ocname, struct objclass *newoc, char *errorbuf, size_t errorbufsize); + static int oc_check_required(Slapi_PBlock *, Slapi_Entry *, struct objclass *); + static int oc_check_allowed_sv(Slapi_PBlock *, Slapi_Entry *e, const char *type, struct objclass **oclist); + static int schema_delete_objectclasses(Slapi_Entry *entryBefore, +@@ -1110,7 +1110,7 @@ oc_find_oid_nolock(const char *ocoid) + */ + + static int +-oc_replace_nolock(const char *ocname, struct objclass *newoc) ++oc_replace_nolock(const char *ocname, struct objclass *newoc, char *errorbuf, size_t errorbufsize) + { + struct objclass *oc, *pnext; + int rc = LDAP_SUCCESS; +@@ -1130,6 +1130,8 @@ oc_replace_nolock(const char *ocname, struct objclass *newoc) + for (pnext = oc; pnext != NULL; + oc = pnext, pnext = pnext->oc_next) { + if (pnext->oc_name == NULL) { ++ schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_oc, ++ ocname, "Failed to replace objectclass"); + rc = LDAP_OPERATIONS_ERROR; + break; + } +@@ -1146,6 +1148,8 @@ oc_replace_nolock(const char *ocname, struct objclass *newoc) + break; + + } else { ++ schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_oc, ++ ocname, "Can not replace objectclass that already exists"); + rc = LDAP_TYPE_OR_VALUE_EXISTS; + break; + } +@@ -2817,7 +2821,7 @@ add_oc_internal(struct objclass *pnew_oc, char *errorbuf, size_t errorbufsize, i + /* insert new objectclass exactly where the old one one in the linked list*/ + if (!rc && redefined_oc) { + pnew_oc->oc_flags |= OC_FLAG_REDEFINED_OC; +- rc = oc_replace_nolock(pnew_oc->oc_name, pnew_oc); ++ rc = oc_replace_nolock(pnew_oc->oc_name, pnew_oc, errorbuf, errorbufsize); + } + + if (!rc && !redefined_oc) { +-- +2.21.0 + diff --git a/SOURCES/0009-Ticket-49561-MEP-plugin-upon-direct-op-failure-will-.patch b/SOURCES/0009-Ticket-49561-MEP-plugin-upon-direct-op-failure-will-.patch deleted file mode 100644 index 88ec73c..0000000 --- a/SOURCES/0009-Ticket-49561-MEP-plugin-upon-direct-op-failure-will-.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 99802f5290466474ca2f1fdab0bf077ec736a013 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Mon, 18 Mar 2019 13:48:03 +0100 -Subject: [PATCH 2/4] Ticket 49561 - MEP plugin, upon direct op failure, will - delete twice the same managed entry - -Bug Description: - When a failure occurs during betxn_post plugin callback, the betxn_post plugins are called again. - This is to process some kind of undo action (for example usn or dna that manage counters). - - If MEP plugin is called for a managing entry, it deletes the managed entry (that become a tombstone). - If later an other betxn_postop fails, then MEP is called again. - But as it does not detect the operation failure (for DEL and ADD), then it tries again - to delete the managed entry that is already a tombstone. - -Fix Description: - The MEP betxn_post plugin callbacks (ADD and DEL) should catch the operation failure - and return. - It is already in place for MODRDN and MOD. - -https://pagure.io/389-ds-base/issue/49561 - -Reviewed by: Mark Reynold, thanks !! - -Platforms tested: F28 - -Flag Day: no - -Doc impact: no ---- - ldap/servers/plugins/mep/mep.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/ldap/servers/plugins/mep/mep.c b/ldap/servers/plugins/mep/mep.c -index 7f30f412d..a7b60e129 100644 ---- a/ldap/servers/plugins/mep/mep.c -+++ b/ldap/servers/plugins/mep/mep.c -@@ -2471,6 +2471,11 @@ mep_add_post_op(Slapi_PBlock *pb) - slapi_log_err(SLAPI_LOG_TRACE, MEP_PLUGIN_SUBSYSTEM, - "--> mep_add_post_op\n"); - -+ /* Just bail if we aren't ready to service requests yet. */ -+ if (!mep_oktodo(pb)) { -+ return SLAPI_PLUGIN_SUCCESS; -+ } -+ - /* Reload config if a config entry was added. */ - if ((sdn = mep_get_sdn(pb))) { - if (mep_dn_is_config(sdn)) { -@@ -2543,6 +2548,11 @@ mep_del_post_op(Slapi_PBlock *pb) - slapi_log_err(SLAPI_LOG_TRACE, MEP_PLUGIN_SUBSYSTEM, - "--> mep_del_post_op\n"); - -+ /* Just bail if we aren't ready to service requests yet. */ -+ if (!mep_oktodo(pb)) { -+ return SLAPI_PLUGIN_SUCCESS; -+ } -+ - /* Reload config if a config entry was deleted. */ - if ((sdn = mep_get_sdn(pb))) { - if (mep_dn_is_config(sdn)) --- -2.17.2 - diff --git a/SOURCES/0010-Issue-50655-access-log-etime-is-not-properly-formatt.patch b/SOURCES/0010-Issue-50655-access-log-etime-is-not-properly-formatt.patch new file mode 100644 index 0000000..7e90d4b --- /dev/null +++ b/SOURCES/0010-Issue-50655-access-log-etime-is-not-properly-formatt.patch @@ -0,0 +1,32 @@ +From f4a5a7f3074e15c3439fd906bef78568bd6ab13c Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Wed, 16 Oct 2019 16:52:59 -0400 +Subject: [PATCH] Issue 50655 - access log etime is not properly formatted + +Description: The wrong printf format was used for displaying the nanosecond etime + in the access log. + +relates: https://pagure.io/389-ds-base/issue/50655 + +Reviewed by: firstyear(Thanks!) +--- + ldap/servers/slapd/result.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c +index 34ddd8566..61e7a70f9 100644 +--- a/ldap/servers/slapd/result.c ++++ b/ldap/servers/slapd/result.c +@@ -1925,7 +1925,8 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries + struct timespec o_hr_time_end; + slapi_operation_time_elapsed(op, &o_hr_time_end); + +- snprintf(etime, ETIME_BUFSIZ, "%" PRId64 ".%010" PRId64 "", (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec); ++ ++ snprintf(etime, ETIME_BUFSIZ, "%" PRId64 ".%.09" PRId64 "", (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec); + + slapi_pblock_get(pb, SLAPI_OPERATION_NOTES, &operation_notes); + +-- +2.21.0 + diff --git a/SOURCES/0010-Ticket-50260-Invalid-cache-flushing-improvements.patch b/SOURCES/0010-Ticket-50260-Invalid-cache-flushing-improvements.patch deleted file mode 100644 index 969ccb0..0000000 --- a/SOURCES/0010-Ticket-50260-Invalid-cache-flushing-improvements.patch +++ /dev/null @@ -1,290 +0,0 @@ -From e07605531f978f6767c9b1cc947c0012ff6c83e3 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Sun, 17 Mar 2019 13:09:07 -0400 -Subject: [PATCH 3/4] Ticket 50260 - Invalid cache flushing improvements - -Description: The original version of the fix only checked if backend - transaction "post" operation plugins failed, but it did - not check for errors from the backend transaction "pre" - operation plugin. To address this we flush invalid - entries whenever any error occurs. - - We were also not flushing invalid cache entries when - modrdn errors occurred. Modrdns only make changes to - the DN hashtable inside the entry cache, but we were only - checking the ID hashtable. So we also need to check the - DN hashtable in the entry cache for invalid entries. - -https://pagure.io/389-ds-base/issue/50260 - -Reviewed by: firstyear & tbordaz(Thanks!!) - -(cherry picked from commit 33fbced25277b88695bfba7262e606380e9d891f) ---- - dirsrvtests/tests/suites/betxns/betxn_test.py | 23 ++++++---- - ldap/servers/slapd/back-ldbm/cache.c | 42 ++++++++++++++++++- - ldap/servers/slapd/back-ldbm/ldbm_add.c | 9 ++-- - ldap/servers/slapd/back-ldbm/ldbm_delete.c | 11 ++--- - ldap/servers/slapd/back-ldbm/ldbm_modify.c | 10 ++--- - ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 10 ++--- - 6 files changed, 74 insertions(+), 31 deletions(-) - -diff --git a/dirsrvtests/tests/suites/betxns/betxn_test.py b/dirsrvtests/tests/suites/betxns/betxn_test.py -index f03fb93cc..84f5e2087 100644 ---- a/dirsrvtests/tests/suites/betxns/betxn_test.py -+++ b/dirsrvtests/tests/suites/betxns/betxn_test.py -@@ -86,9 +86,7 @@ def test_betxt_7bit(topology_st, dynamic_plugins): - log.fatal('Error while searching for test entry: ' + e.message['desc']) - assert False - -- # - # Cleanup - remove the user -- # - try: - topology_st.standalone.delete_s(USER_DN) - except ldap.LDAPError as e: -@@ -241,14 +239,15 @@ def test_betxn_memberof(topology_st, dynamic_plugins): - except ldap.LDAPError as e: - log.info('test_betxn_memberof: Group2 was correctly rejected (mod add): error ' + e.message['desc']) - -- # -+ # verify entry cache reflects the current/correct state of group1 -+ assert not group1.is_member(group2.dn) -+ - # Done -- # - log.info('test_betxn_memberof: PASSED') - - - def test_betxn_modrdn_memberof_cache_corruption(topology_st): -- """Test modrdn operations and memberOf -+ """Test modrdn operations and memberOf be txn post op failures - - :id: 70d0b96e-b693-4bf7-bbf5-102a66ac5994 - -@@ -297,9 +296,7 @@ def test_betxn_modrdn_memberof_cache_corruption(topology_st): - with pytest.raises(ldap.OBJECT_CLASS_VIOLATION): - group.rename('cn=group_to_people', newsuperior=peoplebase) - -- # - # Done -- # - log.info('test_betxn_modrdn_memberof: PASSED') - - -@@ -374,15 +371,23 @@ def test_ri_and_mep_cache_corruption(topology_st): - log.fatal("MEP group was not created for the user") - assert False - -+ # Test MEP be txn pre op failure does not corrupt entry cache -+ # Should get the same exception for both rename attempts -+ with pytest.raises(ldap.UNWILLING_TO_PERFORM): -+ mep_group.rename("cn=modrdn group") -+ -+ with pytest.raises(ldap.UNWILLING_TO_PERFORM): -+ mep_group.rename("cn=modrdn group") -+ - # Mess with MEP so it fails - mep_plugin.disable() - mep_group.delete() - mep_plugin.enable() - -- # Add another group for verify entry cache is not corrupted -+ # Add another group to verify entry cache is not corrupted - test_group = groups.create(properties={'cn': 'test_group'}) - -- # Delete user, should fail, and user should still be a member -+ # Delete user, should fail in MEP be txn post op, and user should still be a member - with pytest.raises(ldap.NO_SUCH_OBJECT): - user.delete() - -diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c -index 458d7912f..02453abac 100644 ---- a/ldap/servers/slapd/back-ldbm/cache.c -+++ b/ldap/servers/slapd/back-ldbm/cache.c -@@ -517,7 +517,8 @@ flush_remove_entry(struct timespec *entry_time, struct timespec *start_time) - /* - * Flush all the cache entries that were added after the "start time" - * This is called when a backend transaction plugin fails, and we need -- * to remove all the possible invalid entries in the cache. -+ * to remove all the possible invalid entries in the cache. We need -+ * to check both the ID and DN hashtables when checking the entry cache. - * - * If the ref count is 0, we can straight up remove it from the cache, but - * if the ref count is greater than 1, then the entry is currently in use. -@@ -528,8 +529,8 @@ flush_remove_entry(struct timespec *entry_time, struct timespec *start_time) - static void - flush_hash(struct cache *cache, struct timespec *start_time, int32_t type) - { -+ Hashtable *ht = cache->c_idtable; /* start with the ID table as it's in both ENTRY and DN caches */ - void *e, *laste = NULL; -- Hashtable *ht = cache->c_idtable; - - cache_lock(cache); - -@@ -570,6 +571,43 @@ flush_hash(struct cache *cache, struct timespec *start_time, int32_t type) - } - } - -+ if (type == ENTRY_CACHE) { -+ /* Also check the DN hashtable */ -+ ht = cache->c_dntable; -+ -+ for (size_t i = 0; i < ht->size; i++) { -+ e = ht->slot[i]; -+ while (e) { -+ struct backcommon *entry = (struct backcommon *)e; -+ uint64_t remove_it = 0; -+ if (flush_remove_entry(&entry->ep_create_time, start_time)) { -+ /* Mark the entry to be removed */ -+ slapi_log_err(SLAPI_LOG_CACHE, "flush_hash", "[ENTRY CACHE] Removing entry id (%d)\n", -+ entry->ep_id); -+ remove_it = 1; -+ } -+ laste = e; -+ e = HASH_NEXT(ht, e); -+ -+ if (remove_it) { -+ /* since we have the cache lock we know we can trust refcnt */ -+ entry->ep_state |= ENTRY_STATE_INVALID; -+ if (entry->ep_refcnt == 0) { -+ entry->ep_refcnt++; -+ lru_delete(cache, laste); -+ entrycache_remove_int(cache, laste); -+ entrycache_return(cache, (struct backentry **)&laste); -+ } else { -+ /* Entry flagged for removal */ -+ slapi_log_err(SLAPI_LOG_CACHE, "flush_hash", -+ "[ENTRY CACHE] Flagging entry to be removed later: id (%d) refcnt: %d\n", -+ entry->ep_id, entry->ep_refcnt); -+ } -+ } -+ } -+ } -+ } -+ - cache_unlock(cache); - } - -diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c -index aa5b59aea..264f0ceea 100644 ---- a/ldap/servers/slapd/back-ldbm/ldbm_add.c -+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c -@@ -1221,11 +1221,6 @@ ldbm_back_add(Slapi_PBlock *pb) - slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); - } - slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); -- -- /* Revert the caches if this is the parent operation */ -- if (parent_op) { -- revert_cache(inst, &parent_time); -- } - goto error_return; - } - -@@ -1253,6 +1248,10 @@ ldbm_back_add(Slapi_PBlock *pb) - goto common_return; - - error_return: -+ /* Revert the caches if this is the parent operation */ -+ if (parent_op) { -+ revert_cache(inst, &parent_time); -+ } - if (addingentry_id_assigned) { - next_id_return(be, addingentry->ep_id); - } -diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c -index 3f687eb91..1ad846447 100644 ---- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c -+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c -@@ -1279,11 +1279,6 @@ replace_entry: - slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &retval); - } - slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); -- -- /* Revert the caches if this is the parent operation */ -- if (parent_op) { -- revert_cache(inst, &parent_time); -- } - goto error_return; - } - if (parent_found) { -@@ -1370,6 +1365,11 @@ commit_return: - goto common_return; - - error_return: -+ /* Revert the caches if this is the parent operation */ -+ if (parent_op) { -+ revert_cache(inst, &parent_time); -+ } -+ - if (tombstone) { - if (cache_is_in_cache(&inst->inst_cache, tombstone)) { - tomb_ep_id = tombstone->ep_id; /* Otherwise, tombstone might have been freed. */ -@@ -1388,6 +1388,7 @@ error_return: - CACHE_RETURN(&inst->inst_cache, &tombstone); - tombstone = NULL; - } -+ - if (retval == DB_RUNRECOVERY) { - dblayer_remember_disk_filled(li); - ldbm_nasty("ldbm_back_delete", "Delete", 79, retval); -diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c -index b90b3e0f0..b0c477e3f 100644 ---- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c -+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c -@@ -873,11 +873,6 @@ ldbm_back_modify(Slapi_PBlock *pb) - slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); - } - slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); -- -- /* Revert the caches if this is the parent operation */ -- if (parent_op) { -- revert_cache(inst, &parent_time); -- } - goto error_return; - } - retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN); -@@ -901,6 +896,11 @@ ldbm_back_modify(Slapi_PBlock *pb) - goto common_return; - - error_return: -+ /* Revert the caches if this is the parent operation */ -+ if (parent_op) { -+ revert_cache(inst, &parent_time); -+ } -+ - if (postentry != NULL) { - slapi_entry_free(postentry); - postentry = NULL; -diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -index 73e50ebcc..65610d613 100644 ---- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -@@ -1217,11 +1217,6 @@ ldbm_back_modrdn(Slapi_PBlock *pb) - slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); - } - slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); -- -- /* Revert the caches if this is the parent operation */ -- if (parent_op) { -- revert_cache(inst, &parent_time); -- } - goto error_return; - } - retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN); -@@ -1290,6 +1285,11 @@ ldbm_back_modrdn(Slapi_PBlock *pb) - goto common_return; - - error_return: -+ /* Revert the caches if this is the parent operation */ -+ if (parent_op) { -+ revert_cache(inst, &parent_time); -+ } -+ - /* result already sent above - just free stuff */ - if (postentry) { - slapi_entry_free(postentry); --- -2.17.2 - diff --git a/SOURCES/0011-Issue-49850-ldbm_get_nonleaf_ids-slow-for-databases-.patch b/SOURCES/0011-Issue-49850-ldbm_get_nonleaf_ids-slow-for-databases-.patch new file mode 100644 index 0000000..4ab1ce5 --- /dev/null +++ b/SOURCES/0011-Issue-49850-ldbm_get_nonleaf_ids-slow-for-databases-.patch @@ -0,0 +1,70 @@ +From d8875611eefff661ad3f92b6f75b0c90c22918a6 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Wed, 16 Oct 2019 20:27:30 -0400 +Subject: [PATCH] Issue 49850 - ldbm_get_nonleaf_ids() slow for databases with + many non-leaf entries + +Bug Description: The logs from an LDIF import indicated that gathering non-leaf IDs + for creating the ancestorid index took an enormous amount of time, + over 10hrs. The root cause is that the parentid index btree ordering + is lexical, but the IDList being built up from it is sorted numerically. + In the existing code, the IDList is maintained in constantly sorted + order by idl_insert(). + +Fix Description: ldbm_get_nonleaf_ids() switches to idl_append_extend() instead idl_insert() + for building up the IDList and then sorts the result only once, using + qsort with idl_sort_cmp, after the entire list has been gathered. + + The improvement on identical hardware is for the operation to take 10 + seconds rather than 10 hours + +Patch Author: Thomas Lackey Thanks for the great contribution!!! + +relates: https://pagure.io/389-ds-base/issue/49850 + +Reviewed by: mreynolds, tbordaz, and firstyear +--- + ldap/servers/slapd/back-ldbm/ancestorid.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ancestorid.c b/ldap/servers/slapd/back-ldbm/ancestorid.c +index 24642923d..254a3aa3b 100644 +--- a/ldap/servers/slapd/back-ldbm/ancestorid.c ++++ b/ldap/servers/slapd/back-ldbm/ancestorid.c +@@ -82,7 +82,14 @@ ldbm_get_nonleaf_ids(backend *be, DB_TXN *txn, IDList **idl, ImportJob *job) + ret = dbc->c_get(dbc, &key, &data, DB_NEXT_NODUP); + if ((ret == 0) && (*(char *)key.data == EQ_PREFIX)) { + id = (ID)strtoul((char *)key.data + 1, NULL, 10); +- idl_insert(&nodes, id); ++ /* ++ * TEL 20180711 - switch to idl_append instead of idl_insert because there is no ++ * no need to keep the list constantly sorted, which can be very expensive with ++ * large databases (exacerbated by the fact that the parentid btree ordering is ++ * lexical, but the idl_insert ordering is numeric). It is enough to gather them ++ * all together and sort them once at the end. ++ */ ++ idl_append_extend(&nodes, id); + } + key_count++; + if (!(key_count % PROGRESS_INTERVAL)) { +@@ -107,6 +114,17 @@ ldbm_get_nonleaf_ids(backend *be, DB_TXN *txn, IDList **idl, ImportJob *job) + if (ret != 0) + ldbm_nasty("ldbm_get_nonleaf_ids", sourcefile, 13030, ret); + ++ if (ret == 0) { ++ /* now sort it */ ++ import_log_notice(job, SLAPI_LOG_INFO, "ldbm_get_nonleaf_ids", ++ "Starting sort of ancestorid non-leaf IDs..."); ++ ++ qsort((void *)&nodes->b_ids[0], nodes->b_nids, (size_t)sizeof(ID), idl_sort_cmp); ++ ++ import_log_notice(job, SLAPI_LOG_INFO, "ldbm_get_nonleaf_ids", ++ "Finished sort of ancestorid non-leaf IDs."); ++ } ++ + out: + /* Close the cursor */ + if (dbc != NULL) { +-- +2.21.0 + diff --git a/SOURCES/0011-Ticket-50265-the-warning-about-skew-time-could-last-.patch b/SOURCES/0011-Ticket-50265-the-warning-about-skew-time-could-last-.patch deleted file mode 100644 index de141e1..0000000 --- a/SOURCES/0011-Ticket-50265-the-warning-about-skew-time-could-last-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From d56be1addb6f2a696f59e8971d0874a3e0d80ec7 Mon Sep 17 00:00:00 2001 -From: Ludwig Krispenz -Date: Wed, 20 Mar 2019 12:00:42 +0100 -Subject: [PATCH 4/4] Ticket 50265: the warning about skew time could last - forever - -Bug: if the local system time is set back more than 300 seconds - a worning about too much time skew is logged and the sampled - time is updated. This adjustment is done at every write operation - and can increase the time skew and be logged infinitely - -Fix: the intention of the adjustment was to avoid a roll over of seq_num - if the sampled time is not increased for more than 65k oberations. - But this is already handled with an explicite check for seq_num - rollover. The extra adjustment for negative time skew can be removed. - -Reviewed by: Thierry, William. Thanks. ---- - ldap/servers/slapd/csngen.c | 22 +++++++--------------- - 1 file changed, 7 insertions(+), 15 deletions(-) - -diff --git a/ldap/servers/slapd/csngen.c b/ldap/servers/slapd/csngen.c -index 3afc9176b..68dbbda8e 100644 ---- a/ldap/servers/slapd/csngen.c -+++ b/ldap/servers/slapd/csngen.c -@@ -191,22 +191,14 @@ csngen_new_csn(CSNGen *gen, CSN **csn, PRBool notify) - slapi_rwlock_unlock(gen->lock); - return rc; - } -- } else if (delta < -300) { -- /* -- * The maxseqnum could support up to 65535 CSNs per second. -- * That means that we could avoid duplicated CSN's for -- * delta up to 300 secs if update rate is 200/sec (usually -- * the max rate is below 20/sec). -- * Beyond 300 secs, we advance gen->state.sampled_time by -- * one sec to recycle seqnum. -- */ -- slapi_log_err(SLAPI_LOG_WARNING, "csngen_new_csn", "Too much time skew (%d secs). Current seqnum=%0x\n", delta, gen->state.seq_num); -- rc = _csngen_adjust_local_time(gen, gen->state.sampled_time + 1); -- if (rc != CSN_SUCCESS) { -- slapi_rwlock_unlock(gen->lock); -- return rc; -- } - } -+ /* if (delta < 0) this means the local system time was set back -+ * the new csn will be generated based on sampled time, which is -+ * ahead of system time and previously generated csns. -+ * the time stamp of the csn will not change until system time -+ * catches up or is corrected by remote csns. -+ * But we need to ensure that the seq_num does not overflow. -+ */ - - if (gen->state.seq_num == CSN_MAX_SEQNUM) { - slapi_log_err(SLAPI_LOG_INFO, "csngen_new_csn", "Sequence rollover; " --- -2.17.2 - diff --git a/SOURCES/0012-Issue-50536-Audit-log-heading-written-to-log-after-e.patch b/SOURCES/0012-Issue-50536-Audit-log-heading-written-to-log-after-e.patch new file mode 100644 index 0000000..3baf2cb --- /dev/null +++ b/SOURCES/0012-Issue-50536-Audit-log-heading-written-to-log-after-e.patch @@ -0,0 +1,81 @@ +From 177faf2c7080d3476798d305451e8ee19ea47f8d Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Wed, 7 Aug 2019 16:57:17 -0400 +Subject: [PATCH] Issue 50536 - Audit log heading written to log after every + update + +Bug Description: Once the audit log is rotated the log "title" is incorrectly + written to the log after every single update. This happened + becuase when we udpated the state of the log it was applied + to a local variable, and not the log info structure itself. + +Fix Description: After writting the "title", update the state of the log using + a pointer to the log info structure. + +relates: https://pagure.io/389-ds-base/issue/50536 + +Reviewed by: lkrispenz(Thanks!) +--- + ldap/servers/slapd/log.c | 14 +++++++------- + ldap/servers/slapd/proto-slap.h | 2 +- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c +index 2456abf1e..f308a4813 100644 +--- a/ldap/servers/slapd/log.c ++++ b/ldap/servers/slapd/log.c +@@ -2073,11 +2073,11 @@ slapd_log_audit( + int retval = LDAP_SUCCESS; + int lbackend = loginfo.log_backend; /* We copy this to make these next checks atomic */ + +- int state = 0; ++ int *state; + if (sourcelog == SLAPD_AUDIT_LOG) { +- state = loginfo.log_audit_state; ++ state = &loginfo.log_audit_state; + } else if (sourcelog == SLAPD_AUDITFAIL_LOG) { +- state = loginfo.log_auditfail_state; ++ state = &loginfo.log_auditfail_state; + } else { + /* How did we even get here! */ + return 1; +@@ -2106,9 +2106,9 @@ int + slapd_log_audit_internal( + char *buffer, + int buf_len, +- int state) ++ int *state) + { +- if ((state & LOGGING_ENABLED) && (loginfo.log_audit_file != NULL)) { ++ if ((*state & LOGGING_ENABLED) && (loginfo.log_audit_file != NULL)) { + LOG_AUDIT_LOCK_WRITE(); + if (log__needrotation(loginfo.log_audit_fdes, + SLAPD_AUDIT_LOG) == LOG_ROTATE) { +@@ -2122,9 +2122,9 @@ slapd_log_audit_internal( + loginfo.log_audit_rotationsyncclock += PR_ABS(loginfo.log_audit_rotationtime_secs); + } + } +- if (state & LOGGING_NEED_TITLE) { ++ if (*state & LOGGING_NEED_TITLE) { + log_write_title(loginfo.log_audit_fdes); +- state &= ~LOGGING_NEED_TITLE; ++ *state &= ~LOGGING_NEED_TITLE; + } + LOG_WRITE_NOW_NO_ERR(loginfo.log_audit_fdes, buffer, buf_len, 0); + LOG_AUDIT_UNLOCK_WRITE(); +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index a0648ca3c..e37f702ea 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -777,7 +777,7 @@ int slapi_log_access(int level, char *fmt, ...) + ; + #endif + int slapd_log_audit(char *buffer, int buf_len, int sourcelog); +-int slapd_log_audit_internal(char *buffer, int buf_len, int state); ++int slapd_log_audit_internal(char *buffer, int buf_len, int *state); + int slapd_log_auditfail(char *buffer, int buf_len); + int slapd_log_auditfail_internal(char *buffer, int buf_len); + void log_access_flush(void); +-- +2.21.0 + diff --git a/SOURCES/0012-Ticket-50063-Crash-after-attempting-to-restore-a-sin.patch b/SOURCES/0012-Ticket-50063-Crash-after-attempting-to-restore-a-sin.patch deleted file mode 100644 index d85a631..0000000 --- a/SOURCES/0012-Ticket-50063-Crash-after-attempting-to-restore-a-sin.patch +++ /dev/null @@ -1,39 +0,0 @@ -From ed430bcca3e1cf0788fc15786002b0b1c31a130b Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Fri, 30 Nov 2018 11:45:39 -0500 -Subject: [PATCH] Ticket 50063 - Crash after attempting to restore a single - backend - -Description: While we do not support backup/restore of individual backends, - it should not crash the server either. PR_OpenDir will crash - if the file name is NULL, so this fix just prevents the crash - by returning an error if the filename is NULL. - -https://pagure.io/389-ds-base/issue/50063 - -Reviewed by: firstyear & tbordaz(Thanks!!) - -(cherry picked from commit d36f796a7b35bade5a05e197690abf4e49d212ce) ---- - ldap/servers/slapd/back-ldbm/dblayer.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c -index fa931ccbf..64a4e9e4f 100644 ---- a/ldap/servers/slapd/back-ldbm/dblayer.c -+++ b/ldap/servers/slapd/back-ldbm/dblayer.c -@@ -5292,6 +5292,11 @@ dblayer_delete_database_ex(struct ldbminfo *li, char *instance, char *cldir) - } - - /* now smash everything else in the db/ dir */ -+ if (priv->dblayer_home_directory == NULL){ -+ slapi_log_err(SLAPI_LOG_ERR, "dblayer_delete_database_ex", -+ "dblayer_home_directory is NULL, can not proceed\n"); -+ return -1; -+ } - dirhandle = PR_OpenDir(priv->dblayer_home_directory); - if (!dirhandle) { - slapi_log_err(SLAPI_LOG_ERR, "dblayer_delete_database_ex", "PR_OpenDir (%s) failed (%d): %s\n", --- -2.17.2 - diff --git a/SOURCES/0013-Issue-50636-Crash-during-sasl-bind.patch b/SOURCES/0013-Issue-50636-Crash-during-sasl-bind.patch new file mode 100644 index 0000000..aa71560 --- /dev/null +++ b/SOURCES/0013-Issue-50636-Crash-during-sasl-bind.patch @@ -0,0 +1,47 @@ +From fbbbcda083034031e564e8772affe815f2058047 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 17 Oct 2019 09:42:02 -0400 +Subject: [PATCH] Issue 50636 - Crash during sasl bind + +Bug Description: + Sasl bind registers IO layers (sasl_IoMethods) that will be + pushed (and called) by the next incoming operation. + So the next incoming operation should synchronize itself + with the sasl bind. + +Fix Description: + The call to connection_call_io_layer_callbacks, that pushes + registered methods, must hold c_mutex so that it let + a pending sasl bind to fully register the methods. + +https://pagure.io/389-ds-base/issue/50636 + +Reviewed by: Ludwig Krispenz, Mark Reynolds +--- + ldap/servers/slapd/connection.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c +index 845a67091..9abd546f9 100644 +--- a/ldap/servers/slapd/connection.c ++++ b/ldap/servers/slapd/connection.c +@@ -1585,12 +1585,14 @@ connection_threadmain() + */ + pb_conn->c_anonlimits_set = 1; + } +- PR_ExitMonitor(pb_conn->c_mutex); +- ++ /* must hold c_mutex so that it synchronizes the IO layer push ++ * with a potential pending sasl bind that is registering the IO layer ++ */ + if (connection_call_io_layer_callbacks(pb_conn)) { + slapi_log_err(SLAPI_LOG_ERR, "connection_threadmain", + "Could not add/remove IO layers from connection\n"); + } ++ PR_ExitMonitor(pb_conn->c_mutex); + break; + default: + break; +-- +2.21.0 + diff --git a/SOURCES/0013-Ticket-49946-upgrade-of-389-ds-base-could-remove-rep.patch b/SOURCES/0013-Ticket-49946-upgrade-of-389-ds-base-could-remove-rep.patch deleted file mode 100644 index 0204d33..0000000 --- a/SOURCES/0013-Ticket-49946-upgrade-of-389-ds-base-could-remove-rep.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 11f8ecf946c0b56d7d49f7b46429d153d5c19ee1 Mon Sep 17 00:00:00 2001 -From: German Parente -Date: Wed, 10 Oct 2018 10:24:08 +0200 -Subject: [PATCH] Ticket #49946 upgrade of 389-ds-base could remove replication - agreements. - -Bug Description: - -when a replication agreement starts with "cn=->...", the upgrade is removing -the entry. - -Fix Description: - -a check is missing when re-building dse.ldif in "setup-ds.pl -u" that provoked this entry not to be re-added to the file. - -https://pagure.io/389-ds-base/issue/49946 - -Author: German Parente - -Review by: ??? ---- - ldap/admin/src/scripts/FileConn.pm | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/admin/src/scripts/FileConn.pm b/ldap/admin/src/scripts/FileConn.pm -index dcea70904..8a2a1afe6 100644 ---- a/ldap/admin/src/scripts/FileConn.pm -+++ b/ldap/admin/src/scripts/FileConn.pm -@@ -360,7 +360,7 @@ sub add { - return $self->write(); - } - -- if (exists($self->{$ndn})) { -+ if ($ndn && exists($self->{$ndn})) { - $self->setErrorCode(LDAP_ALREADY_EXISTS); - return 0; - } --- -2.17.2 - diff --git a/SOURCES/0014-Ticket-49850-cont-fix-crash-in-ldbm_non_leaf.patch b/SOURCES/0014-Ticket-49850-cont-fix-crash-in-ldbm_non_leaf.patch new file mode 100644 index 0000000..d6afcf3 --- /dev/null +++ b/SOURCES/0014-Ticket-49850-cont-fix-crash-in-ldbm_non_leaf.patch @@ -0,0 +1,29 @@ +From 87b7e568cd1f31ef107a0880dd21198b2b401612 Mon Sep 17 00:00:00 2001 +From: Ludwig Krispenz +Date: Thu, 24 Oct 2019 14:26:20 +0200 +Subject: [PATCH] Ticket 49850 cont -fix crash in ldbm_non_leaf + + Bug: if the ldif to be imported contains only one entry there are no leaf nodes + and the call to qsort crashes + + Fix: check that nodes is not NULL +--- + ldap/servers/slapd/back-ldbm/ancestorid.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ancestorid.c b/ldap/servers/slapd/back-ldbm/ancestorid.c +index 254a3aa3b..f26ac1364 100644 +--- a/ldap/servers/slapd/back-ldbm/ancestorid.c ++++ b/ldap/servers/slapd/back-ldbm/ancestorid.c +@@ -114,7 +114,7 @@ ldbm_get_nonleaf_ids(backend *be, DB_TXN *txn, IDList **idl, ImportJob *job) + if (ret != 0) + ldbm_nasty("ldbm_get_nonleaf_ids", sourcefile, 13030, ret); + +- if (ret == 0) { ++ if (ret == 0 && nodes) { + /* now sort it */ + import_log_notice(job, SLAPI_LOG_INFO, "ldbm_get_nonleaf_ids", + "Starting sort of ancestorid non-leaf IDs..."); +-- +2.21.0 + diff --git a/SOURCES/0014-Ticket-49873-Contention-on-virtual-attribute-lookup.patch b/SOURCES/0014-Ticket-49873-Contention-on-virtual-attribute-lookup.patch deleted file mode 100644 index 7918e9e..0000000 --- a/SOURCES/0014-Ticket-49873-Contention-on-virtual-attribute-lookup.patch +++ /dev/null @@ -1,359 +0,0 @@ -From 82b21b4b939acd4dfac8c061bf19ad2494680485 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Tue, 15 Jan 2019 11:13:42 +0100 -Subject: [PATCH] Ticket 49873 - Contention on virtual attribute lookup - -Bug Description: - During lookup of the virtual attribute table (filter evaluation and returned attribute) - the lock is acquired many times in read. For example it is acquired for each targetfilter aci and for - each evaluated entry. - Unfortunately RW lock is expensive and appears frequently on pstacks. - The lock exists because the table can be updated but update is very rare (addition of a new service provider). - So it slows down general proceeding for exceptional events. - -Fix Description: - The fix is to acquire/release the read lock at the operation level and set a per-cpu flag, so that later lookup - would just check the flag. - - SSL initialization does internal searches that access the vattr_global_lock - Call of vattr_global_lock_create needs to be called before slapd_do_all_nss_ssl_init. - - Also, 'main' may or may not fork, the initialization fo the thread private variable - is done either on the child or parent depending if main forks or not. - - The leak is fixed using a destructor callback of the private variable and so - call PR_SetThreadPrivate only if there is no private variable. - - This patch is the merge of the four 49873 patches done in master - -https://pagure.io/389-ds-base/issue/49873 - -Reviewed by: Ludwig Krispenz, William Brown , Simon Pichugi (thanks !!) - -Platforms tested: F28 - -Flag Day: no - -Doc impact: no ---- - ldap/servers/slapd/detach.c | 9 ++ - ldap/servers/slapd/opshared.c | 6 ++ - ldap/servers/slapd/proto-slap.h | 5 + - ldap/servers/slapd/vattr.c | 164 ++++++++++++++++++++++++++++---- - 4 files changed, 167 insertions(+), 17 deletions(-) - -diff --git a/ldap/servers/slapd/detach.c b/ldap/servers/slapd/detach.c -index 681e6a701..d5c95a04f 100644 ---- a/ldap/servers/slapd/detach.c -+++ b/ldap/servers/slapd/detach.c -@@ -144,6 +144,10 @@ detach(int slapd_exemode, int importexport_encrypt, int s_port, daemon_ports_t * - } - break; - } -+ /* The thread private counter needs to be allocated after the fork -+ * it is not inherited from parent process -+ */ -+ vattr_global_lock_create(); - - /* call this right after the fork, but before closing stdin */ - if (slapd_do_all_nss_ssl_init(slapd_exemode, importexport_encrypt, s_port, ports_info)) { -@@ -174,6 +178,11 @@ detach(int slapd_exemode, int importexport_encrypt, int s_port, daemon_ports_t * - - g_set_detached(1); - } else { /* not detaching - call nss/ssl init */ -+ /* The thread private counter needs to be allocated after the fork -+ * it is not inherited from parent process -+ */ -+ vattr_global_lock_create(); -+ - if (slapd_do_all_nss_ssl_init(slapd_exemode, importexport_encrypt, s_port, ports_info)) { - return 1; - } -diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c -index 50b7ae8f6..cf6cdff01 100644 ---- a/ldap/servers/slapd/opshared.c -+++ b/ldap/servers/slapd/opshared.c -@@ -244,6 +244,7 @@ op_shared_search(Slapi_PBlock *pb, int send_result) - int pr_idx = -1; - Slapi_DN *orig_sdn = NULL; - int free_sdn = 0; -+ PRBool vattr_lock_acquired = PR_FALSE; - - be_list[0] = NULL; - referral_list[0] = NULL; -@@ -511,6 +512,8 @@ op_shared_search(Slapi_PBlock *pb, int send_result) - } - - slapi_pblock_set(pb, SLAPI_BACKEND_COUNT, &index); -+ vattr_rdlock(); -+ vattr_lock_acquired = PR_TRUE; - - if (be) { - slapi_pblock_set(pb, SLAPI_BACKEND, be); -@@ -969,6 +972,9 @@ free_and_return: - } else if (be_single) { - slapi_be_Unlock(be_single); - } -+ if (vattr_lock_acquired) { -+ vattr_rd_unlock(); -+ } - - free_and_return_nolock: - slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc); -diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h -index 7a429b238..79017e68d 100644 ---- a/ldap/servers/slapd/proto-slap.h -+++ b/ldap/servers/slapd/proto-slap.h -@@ -1409,6 +1409,11 @@ void subentry_create_filter(Slapi_Filter **filter); - * vattr.c - */ - void vattr_init(void); -+void vattr_global_lock_create(void); -+void vattr_rdlock(); -+void vattr_rd_unlock(); -+void vattr_wrlock(); -+void vattr_wr_unlock(); - void vattr_cleanup(void); - - /* -diff --git a/ldap/servers/slapd/vattr.c b/ldap/servers/slapd/vattr.c -index f7c473ab1..852a887ce 100644 ---- a/ldap/servers/slapd/vattr.c -+++ b/ldap/servers/slapd/vattr.c -@@ -102,6 +102,16 @@ int vattr_basic_sp_init(); - - void **statechange_api; - -+struct _vattr_map -+{ -+ Slapi_RWLock *lock; -+ PLHashTable *hashtable; /* Hash table */ -+}; -+typedef struct _vattr_map vattr_map; -+ -+static vattr_map *the_map = NULL; -+static PRUintn thread_private_global_vattr_lock; -+ - /* Housekeeping Functions, called by server startup/shutdown code */ - - /* Called on server startup, init all structures etc */ -@@ -115,7 +125,136 @@ vattr_init() - vattr_basic_sp_init(); - #endif - } -+/* -+ * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/PR_NewThreadPrivateIndex -+ * It is called each time: -+ * - PR_SetThreadPrivate is call with a not NULL private value -+ * - on thread exit -+ */ -+static void -+vattr_global_lock_free(void *ptr) -+{ -+ int *nb_acquired = ptr; -+ if (nb_acquired) { -+ slapi_ch_free((void **)&nb_acquired); -+ } -+} -+/* Create a private variable for each individual thread of the current process */ -+void -+vattr_global_lock_create() -+{ -+ if (PR_NewThreadPrivateIndex(&thread_private_global_vattr_lock, vattr_global_lock_free) != PR_SUCCESS) { -+ slapi_log_err(SLAPI_LOG_ALERT, -+ "vattr_global_lock_create", "Failure to create global lock for virtual attribute !\n"); -+ PR_ASSERT(0); -+ } -+} -+static int -+global_vattr_lock_get_acquired_count() -+{ -+ int *nb_acquired; -+ nb_acquired = (int *) PR_GetThreadPrivate(thread_private_global_vattr_lock); -+ if (nb_acquired == NULL) { -+ /* if it was not initialized set it to zero */ -+ nb_acquired = (int *) slapi_ch_calloc(1, sizeof(int)); -+ PR_SetThreadPrivate(thread_private_global_vattr_lock, (void *) nb_acquired); -+ } -+ return *nb_acquired; -+} -+static void -+global_vattr_lock_set_acquired_count(int nb_acquired) -+{ -+ int *val; -+ val = (int *) PR_GetThreadPrivate(thread_private_global_vattr_lock); -+ if (val == NULL) { -+ /* if it was not initialized set it to zero */ -+ val = (int *) slapi_ch_calloc(1, sizeof(int)); -+ PR_SetThreadPrivate(thread_private_global_vattr_lock, (void *) val); -+ } -+ *val = nb_acquired; -+} -+/* The map lock can be acquired recursively. So only the first rdlock -+ * will acquire the lock. -+ * A optimization acquires it at high level (op_shared_search), so that -+ * later calls during the operation processing will just increase/decrease a counter. -+ */ -+void -+vattr_rdlock() -+{ -+ int nb_acquire = global_vattr_lock_get_acquired_count(); -+ -+ if (nb_acquire == 0) { -+ /* The lock was not held just acquire it */ -+ slapi_rwlock_rdlock(the_map->lock); -+ } -+ nb_acquire++; -+ global_vattr_lock_set_acquired_count(nb_acquire); -+ -+} -+/* The map lock can be acquired recursively. So only the last unlock -+ * will release the lock. -+ * A optimization acquires it at high level (op_shared_search), so that -+ * later calls during the operation processing will just increase/decrease a counter. -+ */ -+void -+vattr_rd_unlock() -+{ -+ int nb_acquire = global_vattr_lock_get_acquired_count(); - -+ if (nb_acquire >= 1) { -+ nb_acquire--; -+ if (nb_acquire == 0) { -+ slapi_rwlock_unlock(the_map->lock); -+ } -+ global_vattr_lock_set_acquired_count(nb_acquire); -+ } else { -+ /* this is likely the consequence of lock acquire in read during an internal search -+ * but the search callback updated the map and release the readlock and acquired -+ * it in write. -+ * So after the update the lock was no longer held but when completing the internal -+ * search we release the global read lock, that now has nothing to do -+ */ -+ slapi_log_err(SLAPI_LOG_DEBUG, -+ "vattr_rd_unlock", "vattr lock no longer acquired in read.\n"); -+ } -+} -+ -+/* The map lock is acquired in write (updating the map) -+ * It exists a possibility that lock is acquired in write while it is already -+ * hold in read by this thread (internal search with updating callback) -+ * In such situation, the we must abandon the read global lock and acquire in write -+ */ -+void -+vattr_wrlock() -+{ -+ int nb_read_acquire = global_vattr_lock_get_acquired_count(); -+ -+ if (nb_read_acquire) { -+ /* The lock was acquired in read but we need it in write -+ * release it and set the global vattr_lock counter to 0 -+ */ -+ slapi_rwlock_unlock(the_map->lock); -+ global_vattr_lock_set_acquired_count(0); -+ } -+ slapi_rwlock_wrlock(the_map->lock); -+} -+/* The map lock is release from a write write (updating the map) -+ */ -+void -+vattr_wr_unlock() -+{ -+ int nb_read_acquire = global_vattr_lock_get_acquired_count(); -+ -+ if (nb_read_acquire) { -+ /* The lock being acquired in write, the private thread counter -+ * (that count the number of time it was acquired in read) should be 0 -+ */ -+ slapi_log_err(SLAPI_LOG_INFO, -+ "vattr_unlock", "The lock was acquired in write. We should not be here\n"); -+ PR_ASSERT(nb_read_acquire == 0); -+ } -+ slapi_rwlock_unlock(the_map->lock); -+} - /* Called on server shutdown, free all structures, inform service providers that we're going down etc */ - void - vattr_cleanup() -@@ -1811,15 +1950,6 @@ typedef struct _vattr_map_entry vattr_map_entry; - - vattr_map_entry test_entry = {NULL}; - --struct _vattr_map --{ -- Slapi_RWLock *lock; -- PLHashTable *hashtable; /* Hash table */ --}; --typedef struct _vattr_map vattr_map; -- --static vattr_map *the_map = NULL; -- - static PRIntn - vattr_hash_compare_keys(const void *v1, const void *v2) - { -@@ -1939,11 +2069,11 @@ vattr_map_lookup(const char *type_to_find, vattr_map_entry **result) - } - - /* Get the reader lock */ -- slapi_rwlock_rdlock(the_map->lock); -+ vattr_rdlock(); - *result = (vattr_map_entry *)PL_HashTableLookupConst(the_map->hashtable, - (void *)basetype); - /* Release ze lock */ -- slapi_rwlock_unlock(the_map->lock); -+ vattr_rd_unlock(); - - if (tmp) { - slapi_ch_free_string(&tmp); -@@ -1962,13 +2092,13 @@ vattr_map_insert(vattr_map_entry *vae) - { - PR_ASSERT(the_map); - /* Get the writer lock */ -- slapi_rwlock_wrlock(the_map->lock); -+ vattr_wrlock(); - /* Insert the thing */ - /* It's illegal to call this function if the entry is already there */ - PR_ASSERT(NULL == PL_HashTableLookupConst(the_map->hashtable, (void *)vae->type_name)); - PL_HashTableAdd(the_map->hashtable, (void *)vae->type_name, (void *)vae); - /* Unlock and we're done */ -- slapi_rwlock_unlock(the_map->lock); -+ vattr_wr_unlock(); - return 0; - } - -@@ -2105,13 +2235,13 @@ schema_changed_callback(Slapi_Entry *e __attribute__((unused)), - void *caller_data __attribute__((unused))) - { - /* Get the writer lock */ -- slapi_rwlock_wrlock(the_map->lock); -+ vattr_wrlock(); - - /* go through the list */ - PL_HashTableEnumerateEntries(the_map->hashtable, vattr_map_entry_rebuild_schema, 0); - - /* Unlock and we're done */ -- slapi_rwlock_unlock(the_map->lock); -+ vattr_wr_unlock(); - } - - -@@ -2131,7 +2261,7 @@ slapi_vattr_schema_check_type(Slapi_Entry *e, char *type) - objAttrValue *obj; - - if (0 == vattr_map_lookup(type, &map_entry)) { -- slapi_rwlock_rdlock(the_map->lock); -+ vattr_rdlock(); - - obj = map_entry->objectclasses; - -@@ -2148,7 +2278,7 @@ slapi_vattr_schema_check_type(Slapi_Entry *e, char *type) - obj = obj->pNext; - } - -- slapi_rwlock_unlock(the_map->lock); -+ vattr_rd_unlock(); - } - - slapi_valueset_free(vs); --- -2.17.2 - diff --git a/SOURCES/0015-Ticket-49624-cont-DB-Deadlock-on-modrdn-appears-to-c.patch b/SOURCES/0015-Ticket-49624-cont-DB-Deadlock-on-modrdn-appears-to-c.patch new file mode 100644 index 0000000..9e469a4 --- /dev/null +++ b/SOURCES/0015-Ticket-49624-cont-DB-Deadlock-on-modrdn-appears-to-c.patch @@ -0,0 +1,162 @@ +From 1e050b8bee725bfdc4bb6e12bf062227437935a7 Mon Sep 17 00:00:00 2001 +From: Ludwig Krispenz +Date: Thu, 30 Jan 2020 17:26:35 +0100 +Subject: [PATCH] Ticket 49624 cont - DB Deadlock on modrdn appears to + corrupt database and entry cache + + Bug: If there are deadlocks a transaction will be retried. In the case + of modrdn operation there is an error in handling the newsuperior + dn, which has to be reset when the txn is repeated. + There is also an error in freeing the entry stored in the pblock which can + lead to a double free + There is also a memory leak for ec entries + + Fix: check if the newsuperior in the pblock was changed before the retry and + only then free and reset it. + check and protect pblock entry from double free + remove ec entry from cache + + There is also a message at shutdown that entries remain in the entry cache + although no leaks are reported and a hash dump didn't show entries. + Change log level to avoid confusion + + Reviewed by: Thierry, William, Viktor - Thanks +--- + ldap/servers/slapd/back-ldbm/cache.c | 2 +- + ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 60 ++++++++++++++++------ + 2 files changed, 44 insertions(+), 18 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c +index 02453abac..c8d9f606b 100644 +--- a/ldap/servers/slapd/back-ldbm/cache.c ++++ b/ldap/servers/slapd/back-ldbm/cache.c +@@ -723,7 +723,7 @@ entrycache_clear_int(struct cache *cache) + } + cache->c_maxsize = size; + if (cache->c_curentries > 0) { +- slapi_log_err(SLAPI_LOG_WARNING, ++ slapi_log_err(SLAPI_LOG_CACHE, + "entrycache_clear_int", "There are still %" PRIu64 " entries " + "in the entry cache.\n", + cache->c_curentries); +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +index 433ed88fb..26698012a 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +@@ -67,6 +67,7 @@ ldbm_back_modrdn(Slapi_PBlock *pb) + Slapi_DN *dn_newsuperiordn = NULL; + Slapi_DN dn_parentdn; + Slapi_DN *orig_dn_newsuperiordn = NULL; ++ Slapi_DN *pb_dn_newsuperiordn = NULL; /* used to check what is currently in the pblock */ + Slapi_Entry *target_entry = NULL; + Slapi_Entry *original_targetentry = NULL; + int rc; +@@ -248,30 +249,45 @@ ldbm_back_modrdn(Slapi_PBlock *pb) + slapi_sdn_set_dn_byref(&dn_newrdn, original_newrdn); + original_newrdn = slapi_ch_strdup(original_newrdn); + +- slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn); +- slapi_sdn_free(&dn_newsuperiordn); +- slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, orig_dn_newsuperiordn); +- dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn); ++ /* we need to restart with the original newsuperiordn which could have ++ * been modified. So check what is in the pblock, if it was changed ++ * free it, reset orig dn in th epblock and recreate a working superior ++ */ ++ slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &pb_dn_newsuperiordn); ++ if (pb_dn_newsuperiordn != orig_dn_newsuperiordn) { ++ slapi_sdn_free(&pb_dn_newsuperiordn); ++ slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, orig_dn_newsuperiordn); ++ dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn); ++ } + /* must duplicate ec before returning it to cache, + * which could free the entry. */ +- if ((tmpentry = backentry_dup(original_entry ? original_entry : ec)) == NULL) { ++ if (!original_entry) { ++ slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_modrdn", ++ "retrying transaction, but no original entry found\n"); ++ ldap_result_code = LDAP_OPERATIONS_ERROR; ++ goto error_return; ++ } ++ if ((tmpentry = backentry_dup(original_entry)) == NULL) { + ldap_result_code = LDAP_OPERATIONS_ERROR; + goto error_return; + } + slapi_pblock_get(pb, SLAPI_MODRDN_EXISTING_ENTRY, &ent); + if (cache_is_in_cache(&inst->inst_cache, ec)) { + CACHE_REMOVE(&inst->inst_cache, ec); +- if (ent && (ent == ec->ep_entry)) { +- /* +- * On a retry, it's possible that ec is now stored in the +- * pblock as SLAPI_MODRDN_EXISTING_ENTRY. "ec" will be freed +- * by CACHE_RETURN below, so set ent to NULL so don't free +- * it again. +- */ +- ent = NULL; +- } ++ } ++ if (ent && (ent == ec->ep_entry)) { ++ /* ++ * On a retry, it's possible that ec is now stored in the ++ * pblock as SLAPI_MODRDN_EXISTING_ENTRY. "ec" will be freed ++ * by CACHE_RETURN below, so set ent to NULL so don't free ++ * it again. ++ * And it needs to be checked always. ++ */ ++ ent = NULL; + } + CACHE_RETURN(&inst->inst_cache, &ec); ++ ++ /* LK why do we need this ????? */ + if (!cache_is_in_cache(&inst->inst_cache, e)) { + if (CACHE_ADD(&inst->inst_cache, e, NULL) < 0) { + slapi_log_err(SLAPI_LOG_CACHE, +@@ -1087,8 +1103,9 @@ ldbm_back_modrdn(Slapi_PBlock *pb) + if (slapi_sdn_get_dn(dn_newsuperiordn) != NULL) { + retval = ldbm_ancestorid_move_subtree(be, sdn, &dn_newdn, e->ep_id, children, &txn); + if (retval != 0) { +- if (retval == DB_LOCK_DEADLOCK) ++ if (retval == DB_LOCK_DEADLOCK) { + continue; ++ } + if (retval == DB_RUNRECOVERY || LDBM_OS_ERR_IS_DISKFULL(retval)) + disk_full = 1; + MOD_SET_ERROR(ldap_result_code, +@@ -1108,8 +1125,9 @@ ldbm_back_modrdn(Slapi_PBlock *pb) + e->ep_id, &txn, is_tombstone); + slapi_rdn_done(&newsrdn); + if (retval != 0) { +- if (retval == DB_LOCK_DEADLOCK) ++ if (retval == DB_LOCK_DEADLOCK) { + continue; ++ } + if (retval == DB_RUNRECOVERY || LDBM_OS_ERR_IS_DISKFULL(retval)) + disk_full = 1; + MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count); +@@ -1500,7 +1518,12 @@ common_return: + done_with_pblock_entry(pb, SLAPI_MODRDN_NEWPARENT_ENTRY); + done_with_pblock_entry(pb, SLAPI_MODRDN_TARGET_ENTRY); + slapi_ch_free_string(&original_newrdn); +- slapi_sdn_free(&orig_dn_newsuperiordn); ++ slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &pb_dn_newsuperiordn); ++ if (pb_dn_newsuperiordn != orig_dn_newsuperiordn) { ++ slapi_sdn_free(&orig_dn_newsuperiordn); ++ } else { ++ slapi_sdn_free(&dn_newsuperiordn); ++ } + backentry_free(&original_entry); + backentry_free(&tmpentry); + slapi_entry_free(original_targetentry); +@@ -1561,6 +1584,9 @@ moddn_unlock_and_return_entry( + /* Something bad happened so we should give back all the entries */ + if (*targetentry != NULL) { + cache_unlock_entry(&inst->inst_cache, *targetentry); ++ if (cache_is_in_cache(&inst->inst_cache, *targetentry)) { ++ CACHE_REMOVE(&inst->inst_cache, *targetentry); ++ } + CACHE_RETURN(&inst->inst_cache, targetentry); + *targetentry = NULL; + } +-- +2.21.1 + diff --git a/SOURCES/0015-Ticket-49958-extended-search-fail-to-match-entries.patch b/SOURCES/0015-Ticket-49958-extended-search-fail-to-match-entries.patch deleted file mode 100644 index dcd583f..0000000 --- a/SOURCES/0015-Ticket-49958-extended-search-fail-to-match-entries.patch +++ /dev/null @@ -1,261 +0,0 @@ -From cfadaa740b34f1bc1b14db253d7a7cb25f7125d8 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Mon, 24 Sep 2018 14:14:16 +0200 -Subject: [PATCH] Ticket 49958: extended search fail to match entries - -Bug Description: - During an extended search, a structure is created for each filter component. - The structure contains the keys generated from the assertion and using the given - matching rule indexer. - Later the keys will be compared (with the MR) with keys generated from the - attribute values of the candidate entries. - The bug is that parsing the assertion, instead of removing the heading spaces - the routine clear the assertion that is empty. So the generated keys is NULL. - -Fix Description: - The fix consists to only remove heading spaces - -https://pagure.io/389-ds-base/issue/49958 - -Reviewed by: Mark Reynolds - -Platforms tested: F27 - -Flag Day: no - -Doc impact: no ---- - .../tests/suites/filter/filter_test.py | 200 ++++++++++++++++++ - ldap/servers/plugins/collation/orfilter.c | 4 +- - 2 files changed, 201 insertions(+), 3 deletions(-) - -diff --git a/dirsrvtests/tests/suites/filter/filter_test.py b/dirsrvtests/tests/suites/filter/filter_test.py -index 280db68a3..4d2dd3055 100644 ---- a/dirsrvtests/tests/suites/filter/filter_test.py -+++ b/dirsrvtests/tests/suites/filter/filter_test.py -@@ -82,6 +82,206 @@ def test_filter_search_original_attrs(topology_st): - - log.info('test_filter_search_original_attrs: PASSED') - -+@pytest.mark.bz1511462 -+def test_filter_scope_one(topology_st): -+ """Test ldapsearch with scope one gives only single entry -+ -+ :id: cf5a6078-bbe6-4d43-ac71-553c45923f91 -+ :setup: Standalone instance -+ :steps: -+ 1. Search cn=Directory Administrators,dc=example,dc=com using ldapsearch with -+ scope one using base as dc=example,dc=com -+ 2. Check that search should return only one entry -+ :expectedresults: -+ 1. This should pass -+ 2. This should pass -+ """ -+ -+ parent_dn="dn: dc=example,dc=com" -+ child_dn="dn: cn=Directory Administrators,dc=example,dc=com" -+ -+ log.info('Search user using ldapsearch with scope one') -+ results = topology_st.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_ONELEVEL,'cn=Directory Administrators',['cn'] ) -+ log.info(results) -+ -+ log.info('Search should only have one entry') -+ assert len(results) == 1 -+ -+@pytest.mark.ds47313 -+def test_filter_with_attribute_subtype(topology_st): -+ """Adds 2 test entries and Search with -+ filters including subtype and ! -+ -+ :id: 0e69f5f2-6a0a-480e-8282-fbcc50231908 -+ :setup: Standalone instance -+ :steps: -+ 1. Add 2 entries and create 3 filters -+ 2. Search for entry with filter: (&(cn=test_entry en only)(!(cn=test_entry fr))) -+ 3. Search for entry with filter: (&(cn=test_entry en only)(!(cn;fr=test_entry fr))) -+ 4. Search for entry with filter: (&(cn=test_entry en only)(!(cn;en=test_entry en))) -+ 5. Delete the added entries -+ :expectedresults: -+ 1. Operation should be successful -+ 2. Search should be successful -+ 3. Search should be successful -+ 4. Search should not be successful -+ 5. Delete the added entries -+ """ -+ -+ # bind as directory manager -+ topology_st.standalone.log.info("Bind as %s" % DN_DM) -+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD) -+ -+ # enable filter error logging -+ # mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '32')] -+ # topology_st.standalone.modify_s(DN_CONFIG, mod) -+ -+ topology_st.standalone.log.info("\n\n######################### ADD ######################\n") -+ -+ # Prepare the entry with cn;fr & cn;en -+ entry_name_fr = '%s fr' % (ENTRY_NAME) -+ entry_name_en = '%s en' % (ENTRY_NAME) -+ entry_name_both = '%s both' % (ENTRY_NAME) -+ entry_dn_both = 'cn=%s, %s' % (entry_name_both, SUFFIX) -+ entry_both = Entry(entry_dn_both) -+ entry_both.setValues('objectclass', 'top', 'person') -+ entry_both.setValues('sn', entry_name_both) -+ entry_both.setValues('cn', entry_name_both) -+ entry_both.setValues('cn;fr', entry_name_fr) -+ entry_both.setValues('cn;en', entry_name_en) -+ -+ # Prepare the entry with one member -+ entry_name_en_only = '%s en only' % (ENTRY_NAME) -+ entry_dn_en_only = 'cn=%s, %s' % (entry_name_en_only, SUFFIX) -+ entry_en_only = Entry(entry_dn_en_only) -+ entry_en_only.setValues('objectclass', 'top', 'person') -+ entry_en_only.setValues('sn', entry_name_en_only) -+ entry_en_only.setValues('cn', entry_name_en_only) -+ entry_en_only.setValues('cn;en', entry_name_en) -+ -+ topology_st.standalone.log.info("Try to add Add %s: %r" % (entry_dn_both, entry_both)) -+ topology_st.standalone.add_s(entry_both) -+ -+ topology_st.standalone.log.info("Try to add Add %s: %r" % (entry_dn_en_only, entry_en_only)) -+ topology_st.standalone.add_s(entry_en_only) -+ -+ topology_st.standalone.log.info("\n\n######################### SEARCH ######################\n") -+ -+ # filter: (&(cn=test_entry en only)(!(cn=test_entry fr))) -+ myfilter = '(&(sn=%s)(!(cn=%s)))' % (entry_name_en_only, entry_name_fr) -+ topology_st.standalone.log.info("Try to search with filter %s" % myfilter) -+ ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter) -+ assert len(ents) == 1 -+ assert ensure_str(ents[0].sn) == entry_name_en_only -+ topology_st.standalone.log.info("Found %s" % ents[0].dn) -+ -+ # filter: (&(cn=test_entry en only)(!(cn;fr=test_entry fr))) -+ myfilter = '(&(sn=%s)(!(cn;fr=%s)))' % (entry_name_en_only, entry_name_fr) -+ topology_st.standalone.log.info("Try to search with filter %s" % myfilter) -+ ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter) -+ assert len(ents) == 1 -+ assert ensure_str(ents[0].sn) == entry_name_en_only -+ topology_st.standalone.log.info("Found %s" % ents[0].dn) -+ -+ # filter: (&(cn=test_entry en only)(!(cn;en=test_entry en))) -+ myfilter = '(&(sn=%s)(!(cn;en=%s)))' % (entry_name_en_only, entry_name_en) -+ topology_st.standalone.log.info("Try to search with filter %s" % myfilter) -+ ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter) -+ assert len(ents) == 0 -+ topology_st.standalone.log.info("Found none") -+ -+ topology_st.standalone.log.info("\n\n######################### DELETE ######################\n") -+ -+ topology_st.standalone.log.info("Try to delete %s " % entry_dn_both) -+ topology_st.standalone.delete_s(entry_dn_both) -+ -+ topology_st.standalone.log.info("Try to delete %s " % entry_dn_en_only) -+ topology_st.standalone.delete_s(entry_dn_en_only) -+ -+ log.info('Testcase PASSED') -+ -+@pytest.mark.bz1615155 -+def test_extended_search(topology_st): -+ """Test we can search with equality extended matching rule -+ -+ :id: -+ :setup: Standalone instance -+ :steps: -+ 1. Add a test user with 'sn: ext-test-entry' -+ 2. Search '(cn:de:=ext-test-entry)' -+ 3. Search '(sn:caseIgnoreIA5Match:=EXT-TEST-ENTRY)' -+ 4. Search '(sn:caseIgnoreMatch:=EXT-TEST-ENTRY)' -+ 5. Search '(sn:caseExactMatch:=EXT-TEST-ENTRY)' -+ 6. Search '(sn:caseExactMatch:=ext-test-entry)' -+ 7. Search '(sn:caseExactIA5Match:=EXT-TEST-ENTRY)' -+ 8. Search '(sn:caseExactIA5Match:=ext-test-entry)' -+ :expectedresults: -+ 1. This should pass -+ 2. This should return one entry -+ 3. This should return one entry -+ 4. This should return one entry -+ 5. This should return NO entry -+ 6. This should return one entry -+ 7. This should return NO entry -+ 8. This should return one entry -+ 3. return one entry -+ """ -+ log.info('Running test_filter_escaped...') -+ -+ ATTR_VAL = 'ext-test-entry' -+ USER1_DN = "uid=%s,%s" % (ATTR_VAL, DEFAULT_SUFFIX) -+ -+ try: -+ topology_st.standalone.add_s(Entry((USER1_DN, {'objectclass': "top extensibleObject".split(), -+ 'sn': ATTR_VAL.encode(), -+ 'cn': ATTR_VAL.encode(), -+ 'uid': ATTR_VAL.encode()}))) -+ except ldap.LDAPError as e: -+ log.fatal('test_extended_search: Failed to add test user ' + USER1_DN + ': error ' + -+ e.message['desc']) -+ assert False -+ -+ # filter: '(cn:de:=ext-test-entry)' -+ myfilter = '(cn:de:=%s)' % ATTR_VAL -+ topology_st.standalone.log.info("Try to search with filter %s" % myfilter) -+ ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter) -+ assert len(ents) == 1 -+ -+ # filter: '(sn:caseIgnoreIA5Match:=EXT-TEST-ENTRY)' -+ myfilter = '(cn:caseIgnoreIA5Match:=%s)' % ATTR_VAL.upper() -+ topology_st.standalone.log.info("Try to search with filter %s" % myfilter) -+ ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter) -+ assert len(ents) == 1 -+ -+ # filter: '(sn:caseIgnoreMatch:=EXT-TEST-ENTRY)' -+ myfilter = '(cn:caseIgnoreMatch:=%s)' % ATTR_VAL.upper() -+ topology_st.standalone.log.info("Try to search with filter %s" % myfilter) -+ ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter) -+ assert len(ents) == 1 -+ -+ # filter: '(sn:caseExactMatch:=EXT-TEST-ENTRY)' -+ myfilter = '(cn:caseExactMatch:=%s)' % ATTR_VAL.upper() -+ topology_st.standalone.log.info("Try to search with filter %s" % myfilter) -+ ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter) -+ assert len(ents) == 0 -+ -+ # filter: '(sn:caseExactMatch:=ext-test-entry)' -+ myfilter = '(cn:caseExactMatch:=%s)' % ATTR_VAL -+ topology_st.standalone.log.info("Try to search with filter %s" % myfilter) -+ ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter) -+ assert len(ents) == 1 -+ -+ # filter: '(sn:caseExactIA5Match:=EXT-TEST-ENTRY)' -+ myfilter = '(cn:caseExactIA5Match:=%s)' % ATTR_VAL.upper() -+ topology_st.standalone.log.info("Try to search with filter %s" % myfilter) -+ ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter) -+ assert len(ents) == 0 -+ -+ # filter: '(sn:caseExactIA5Match:=ext-test-entry)' -+ myfilter = '(cn:caseExactIA5Match:=%s)' % ATTR_VAL -+ topology_st.standalone.log.info("Try to search with filter %s" % myfilter) -+ ents = topology_st.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, myfilter) -+ assert len(ents) == 1 - - if __name__ == '__main__': - # Run isolated -diff --git a/ldap/servers/plugins/collation/orfilter.c b/ldap/servers/plugins/collation/orfilter.c -index 7705de9d6..c092d77ca 100644 ---- a/ldap/servers/plugins/collation/orfilter.c -+++ b/ldap/servers/plugins/collation/orfilter.c -@@ -531,10 +531,8 @@ or_filter_create(Slapi_PBlock *pb) - default: - break; - } -- for (; len > 0 && *val != ' '; ++val, --len) -+ for (; len > 0 && *val == ' '; ++val, --len) - ; -- if (len > 0) -- ++val, --len; /* skip the space */ - bv.bv_len = len; - bv.bv_val = (len > 0) ? val : NULL; - } else { /* mrOID does not identify an ordering rule. */ --- -2.17.2 - diff --git a/SOURCES/0016-Ticket-50028-ds-replcheck-y-option-throws-usage-erro.patch b/SOURCES/0016-Ticket-50028-ds-replcheck-y-option-throws-usage-erro.patch deleted file mode 100644 index fa48834..0000000 --- a/SOURCES/0016-Ticket-50028-ds-replcheck-y-option-throws-usage-erro.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 24ffb21ba81fcd1272aa3232c5f17cee6c7568ef Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Thu, 4 Apr 2019 12:43:13 -0400 -Subject: [PATCH] Ticket 50028 - ds-replcheck -y option throws usage error - -Description: Using the password file option (-y) causes - a usage error to occur. The arg validation - needs to properly check for this option. - -https://pagure.io/389-ds-base/issue/50028 - -Reviewed by: mreynolds(one line commit rule) ---- - ldap/admin/src/scripts/ds-replcheck | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/admin/src/scripts/ds-replcheck b/ldap/admin/src/scripts/ds-replcheck -index f48240699..e18465dc0 100755 ---- a/ldap/admin/src/scripts/ds-replcheck -+++ b/ldap/admin/src/scripts/ds-replcheck -@@ -1209,7 +1209,7 @@ def main(): - elif (args.mldif is None and - (args.suffix is None or - args.binddn is None or -- (args.bindpw is None and args.prompt is False) or -+ (args.bindpw is None and (args.prompt is False and args.pass_file is None)) or - args.murl is None or - args.rurl is None)): - print("\n-------> Missing required options for online mode!\n") --- -2.17.2 - diff --git a/SOURCES/0018-Ticket-49990-Increase-the-default-FD-limits.patch b/SOURCES/0018-Ticket-49990-Increase-the-default-FD-limits.patch deleted file mode 100644 index 38643c8..0000000 --- a/SOURCES/0018-Ticket-49990-Increase-the-default-FD-limits.patch +++ /dev/null @@ -1,270 +0,0 @@ -From a825c288665556013a51a7efba2e07bc16ee4ee8 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Fri, 5 Apr 2019 09:16:02 -0400 -Subject: [PATCH] Ticket 49990 - Increase the default FD limits - -Description: As discussed in the ticket, this fix sets the maxdescriptors - to the maximum allowed by the OS/systemd. If this limit can - not be obtained then we fall back to 8192 as the limit - -https://pagure.io/389-ds-base/issue/49990 - -Reviewed by: tbordaz & firstyear(Thanks!!) - -(cherry picked from commit 8ca142034a051122b78bdaa3a948d3c50d4cca7e) -(cherry picked from commit 2c583a97cffa54a7da9922215ae37156174a37c5) ---- - .../suites/resource_limits/fdlimits_test.py | 63 +++++++++++++++++++ - ldap/servers/slapd/libglobs.c | 26 +++++--- - ldap/servers/slapd/main.c | 5 +- - ldap/servers/slapd/proto-slap.h | 4 +- - ldap/servers/slapd/slap.h | 6 +- - wrappers/systemd.template.service.in | 1 - - wrappers/systemd.template.sysconfig | 3 +- - 7 files changed, 90 insertions(+), 18 deletions(-) - create mode 100644 dirsrvtests/tests/suites/resource_limits/fdlimits_test.py - -diff --git a/dirsrvtests/tests/suites/resource_limits/fdlimits_test.py b/dirsrvtests/tests/suites/resource_limits/fdlimits_test.py -new file mode 100644 -index 000000000..e5b14a747 ---- /dev/null -+++ b/dirsrvtests/tests/suites/resource_limits/fdlimits_test.py -@@ -0,0 +1,63 @@ -+import logging -+import pytest -+import os -+import ldap -+from lib389._constants import * -+from lib389.topologies import topology_st -+ -+logging.getLogger(__name__).setLevel(logging.INFO) -+log = logging.getLogger(__name__) -+ -+FD_ATTR = "nsslapd-maxdescriptors" -+SYSTEMD_VAL = "16384" -+CUSTOM_VAL = "9000" -+TOO_HIGH_VAL = "65536" -+TOO_LOW_VAL = "0" -+ -+ -+def test_fd_limits(topology_st): -+ """Test the default limits, and custom limits -+ -+ :id: fa0a5106-612f-428f-84c0-9c85c34d0433 -+ :setup: Standalone Instance -+ :steps: -+ 1. Check default limit -+ 2. Change default limit -+ 3. Check invalid/too high limit is rejected -+ 4. Check invalid/too low limit is rejected -+ :expectedresults: -+ 1. Success -+ 2. Success -+ 3. Success -+ 4 Success -+ """ -+ -+ # Check systemd default -+ max_fd = topology_st.standalone.config.get_attr_val_utf8(FD_ATTR) -+ assert max_fd == SYSTEMD_VAL -+ -+ # Check custom value is applied -+ topology_st.standalone.config.set(FD_ATTR, CUSTOM_VAL) -+ max_fd = topology_st.standalone.config.get_attr_val_utf8(FD_ATTR) -+ assert max_fd == CUSTOM_VAL -+ -+ # Attempt to use val that is too high -+ with pytest.raises(ldap.UNWILLING_TO_PERFORM): -+ topology_st.standalone.config.set(FD_ATTR, TOO_HIGH_VAL) -+ max_fd = topology_st.standalone.config.get_attr_val_utf8(FD_ATTR) -+ assert max_fd == CUSTOM_VAL -+ -+ # Attempt to use val that is too low -+ with pytest.raises(ldap.OPERATIONS_ERROR): -+ topology_st.standalone.config.set(FD_ATTR, TOO_LOW_VAL) -+ max_fd = topology_st.standalone.config.get_attr_val_utf8(FD_ATTR) -+ assert max_fd == CUSTOM_VAL -+ -+ log.info("Test PASSED") -+ -+ -+if __name__ == '__main__': -+ # Run isolated -+ # -s for DEBUG mode -+ CURRENT_FILE = os.path.realpath(__file__) -+ pytest.main(["-s", CURRENT_FILE]) -diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c -index 59f8d06d5..91c3a4a89 100644 ---- a/ldap/servers/slapd/libglobs.c -+++ b/ldap/servers/slapd/libglobs.c -@@ -131,6 +131,7 @@ - #if defined(LINUX) - #include - #endif -+#include - - #define REMOVE_CHANGELOG_CMD "remove" - -@@ -1465,6 +1466,8 @@ void - FrontendConfig_init(void) - { - slapdFrontendConfig_t *cfg = getFrontendConfig(); -+ struct rlimit rlp; -+ int64_t maxdescriptors = SLAPD_DEFAULT_MAXDESCRIPTORS; - - #if SLAPI_CFG_USE_RWLOCK == 1 - /* initialize the read/write configuration lock */ -@@ -1480,6 +1483,11 @@ FrontendConfig_init(void) - exit(-1); - } - #endif -+ /* Default the maximum fd's to the maximum allowed */ -+ if (getrlimit(RLIMIT_NOFILE, &rlp) == 0) { -+ maxdescriptors = (int64_t)rlp.rlim_max; -+ } -+ - /* Take the lock to make sure we barrier correctly. */ - CFG_LOCK_WRITE(cfg); - -@@ -1514,7 +1522,7 @@ FrontendConfig_init(void) - /* minssf is applied to rootdse, by default */ - init_minssf_exclude_rootdse = cfg->minssf_exclude_rootdse = LDAP_OFF; - cfg->validate_cert = SLAPD_DEFAULT_VALIDATE_CERT; -- cfg->maxdescriptors = SLAPD_DEFAULT_MAXDESCRIPTORS; -+ cfg->maxdescriptors = maxdescriptors; - cfg->groupevalnestlevel = SLAPD_DEFAULT_GROUPEVALNESTLEVEL; - cfg->snmp_index = SLAPD_DEFAULT_SNMP_INDEX; - cfg->SSLclientAuth = SLAPD_DEFAULT_SSLCLIENTAUTH; -@@ -1665,8 +1673,7 @@ FrontendConfig_init(void) - init_ndn_cache_enabled = cfg->ndn_cache_enabled = LDAP_ON; - cfg->ndn_cache_max_size = SLAPD_DEFAULT_NDN_SIZE; - init_sasl_mapping_fallback = cfg->sasl_mapping_fallback = LDAP_OFF; -- init_ignore_vattrs = -- cfg->ignore_vattrs = LDAP_OFF; -+ init_ignore_vattrs = cfg->ignore_vattrs = LDAP_OFF; - cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE; - cfg->unhashed_pw_switch = SLAPD_DEFAULT_UNHASHED_PW_SWITCH; - init_return_orig_type = cfg->return_orig_type = LDAP_OFF; -@@ -4011,13 +4018,12 @@ config_set_maxthreadsperconn(const char *attrname, char *value, char *errorbuf, - return retVal; - } - --#include --int -+int32_t - config_set_maxdescriptors(const char *attrname, char *value, char *errorbuf, int apply) - { -- int retVal = LDAP_SUCCESS; -- long nValue = 0; -- int maxVal = 65535; -+ int32_t retVal = LDAP_SUCCESS; -+ int64_t nValue = 0; -+ int64_t maxVal = 65535; - struct rlimit rlp; - char *endp = NULL; - -@@ -5493,11 +5499,11 @@ config_get_maxthreadsperconn() - return slapi_atomic_load_32(&(slapdFrontendConfig->maxthreadsperconn), __ATOMIC_ACQUIRE); - } - --int -+int64_t - config_get_maxdescriptors(void) - { - slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); -- int retVal; -+ int64_t retVal; - - CFG_LOCK_READ(slapdFrontendConfig); - retVal = slapdFrontendConfig->maxdescriptors; -diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c -index 219c91294..5e24b3b5f 100644 ---- a/ldap/servers/slapd/main.c -+++ b/ldap/servers/slapd/main.c -@@ -1074,7 +1074,10 @@ main(int argc, char **argv) - slapi_ch_free((void **)&versionstring); - } - -- /* -sduloutre: compute_init() and entry_computed_attr_init() moved up */ -+ /* log the max fd limit as it is typically set in env/systemd */ -+ slapi_log_err(SLAPI_LOG_INFO, "main", -+ "Setting the maximum file descriptor limit to: %ld\n", -+ config_get_maxdescriptors()); - - if (mcfg.slapd_exemode != SLAPD_EXEMODE_REFERRAL) { - int rc; -diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h -index 79017e68d..a0648ca3c 100644 ---- a/ldap/servers/slapd/proto-slap.h -+++ b/ldap/servers/slapd/proto-slap.h -@@ -383,7 +383,7 @@ int config_set_malloc_mxfast(const char *attrname, char *value, char *errorbuf, - int config_set_malloc_trim_threshold(const char *attrname, char *value, char *errorbuf, int apply); - int config_set_malloc_mmap_threshold(const char *attrname, char *value, char *errorbuf, int apply); - #endif --int config_set_maxdescriptors(const char *attrname, char *value, char *errorbuf, int apply); -+int32_t config_set_maxdescriptors(const char *attrname, char *value, char *errorbuf, int apply); - int config_set_localuser(const char *attrname, char *value, char *errorbuf, int apply); - - int config_set_maxsimplepaged_per_conn(const char *attrname, char *value, char *errorbuf, int apply); -@@ -465,7 +465,7 @@ char *config_get_workingdir(void); - char *config_get_encryptionalias(void); - int32_t config_get_threadnumber(void); - int config_get_maxthreadsperconn(void); --int config_get_maxdescriptors(void); -+int64_t config_get_maxdescriptors(void); - int config_get_reservedescriptors(void); - int config_get_ioblocktimeout(void); - int config_get_idletimeout(void); -diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h -index 618e245b6..bce720974 100644 ---- a/ldap/servers/slapd/slap.h -+++ b/ldap/servers/slapd/slap.h -@@ -351,8 +351,8 @@ typedef void (*VFPV)(); /* takes undefined arguments */ - - #define SLAPD_DEFAULT_PAGEDSIZELIMIT 0 - #define SLAPD_DEFAULT_PAGEDSIZELIMIT_STR "0" --#define SLAPD_DEFAULT_MAXDESCRIPTORS 1024 --#define SLAPD_DEFAULT_MAXDESCRIPTORS_STR "1024" -+#define SLAPD_DEFAULT_MAXDESCRIPTORS 8192 -+#define SLAPD_DEFAULT_MAXDESCRIPTORS_STR "8192" - #define SLAPD_DEFAULT_MAX_FILTER_NEST_LEVEL 40 - #define SLAPD_DEFAULT_MAX_FILTER_NEST_LEVEL_STR "40" - #define SLAPD_DEFAULT_GROUPEVALNESTLEVEL 0 -@@ -2254,7 +2254,7 @@ typedef struct _slapdFrontendConfig - int idletimeout; - slapi_int_t ioblocktimeout; - slapi_onoff_t lastmod; -- int maxdescriptors; -+ int64_t maxdescriptors; - int conntablesize; - slapi_int_t maxthreadsperconn; - int outbound_ldap_io_timeout; -diff --git a/wrappers/systemd.template.service.in b/wrappers/systemd.template.service.in -index 0d88900b6..4c1b13d98 100644 ---- a/wrappers/systemd.template.service.in -+++ b/wrappers/systemd.template.service.in -@@ -28,7 +28,6 @@ EnvironmentFile=@initconfigdir@/@package_name@-%i - PIDFile=@localstatedir@/run/@package_name@/slapd-%i.pid - ExecStartPre=@sbindir@/ds_systemd_ask_password_acl @instconfigdir@/slapd-%i/dse.ldif - ExecStart=@sbindir@/ns-slapd -D @instconfigdir@/slapd-%i -i @localstatedir@/run/@package_name@/slapd-%i.pid -- - # Hardening options: - # PrivateDevices=true - # ProtectSystem=true -diff --git a/wrappers/systemd.template.sysconfig b/wrappers/systemd.template.sysconfig -index 903876b17..76c004d40 100644 ---- a/wrappers/systemd.template.sysconfig -+++ b/wrappers/systemd.template.sysconfig -@@ -7,7 +7,8 @@ - - # This controls the number of file handles avaliable. File handles - # correlate to sockets for the process, and our access to logs and --# databases. -+# databases. Note, the configuration setting in Directory Server, -+# "nsslapd-maxdescriptors", can override this limit. - LimitNOFILE=16384 - - # You can limit the memory in the cgroup with these, and ns-slapd --- -2.17.2 - diff --git a/SOURCES/0019-Ticket-50053-Subtree-password-policy-overrides-a-use.patch b/SOURCES/0019-Ticket-50053-Subtree-password-policy-overrides-a-use.patch deleted file mode 100644 index af6af73..0000000 --- a/SOURCES/0019-Ticket-50053-Subtree-password-policy-overrides-a-use.patch +++ /dev/null @@ -1,44 +0,0 @@ -From f6e1acdefc97aa0f808b622c6f6a3dc0a683d457 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Mon, 15 Apr 2019 11:23:46 -0400 -Subject: [PATCH] Ticket 50053 - Subtree password policy overrides a - user-defined password policy - -Bug Description: - -When an entry contains an attribute that is also defined by a cos definition -a specifier defines which values win: the real values that are in the entry or the -virtual values that are cos defined. -The specifier 'default' means that the real values are the winners (returned). -'operational-default' has the same behavior but just specify that the attribute -is operational. -The bug is that when real values exists, the 'operational-default' specifier -drops the real values in favor of the virtual ones. - -Fix Description: - -Change the test, so that real values are not kept for 'operation-default' -Note: the full routine cos_cache_query_attr looks quite messy and error prone -It would be nice to rewrite it when we have time - -https://pagure.io/389-ds-base/issue/50053 ---- - ldap/servers/plugins/cos/cos_cache.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c -index 5e0cf1725..64c0441c4 100644 ---- a/ldap/servers/plugins/cos/cos_cache.c -+++ b/ldap/servers/plugins/cos/cos_cache.c -@@ -2279,7 +2279,7 @@ cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Slapi_Entry * - /* now for the tests */ - - /* would we be allowed to supply this attribute if we had one? */ -- if (entry_has_value && !pAttr->attr_override && !pAttr->attr_operational && !pAttr->attr_operational_default) { -+ if (entry_has_value && !pAttr->attr_override && !pAttr->attr_operational) { - /* answer: no, move on to the next attribute */ - attr_index++; - continue; --- -2.17.2 - diff --git a/SOURCES/0020-Ticket-49866-Add-passwordSendExpiringTime-to-objectc.patch b/SOURCES/0020-Ticket-49866-Add-passwordSendExpiringTime-to-objectc.patch deleted file mode 100644 index fca53c5..0000000 --- a/SOURCES/0020-Ticket-49866-Add-passwordSendExpiringTime-to-objectc.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 97eff45e36a6fe0cc11172b435d8c90908da81e9 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Fri, 10 May 2019 10:55:28 -0400 -Subject: [PATCH] Ticket 49866 - Add passwordSendExpiringTime to objectclass - -Description: add the expringtime attribute to the passwordPolicy objectclass - -https://pagure.io/389-ds-base/issue/49866 - -Reviewed by: mreynolds(one line commit rule) ---- - ldap/schema/02common.ldif | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif -index 70d64c0d2..b44e860b3 100644 ---- a/ldap/schema/02common.ldif -+++ b/ldap/schema/02common.ldif -@@ -142,7 +142,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.7 NAME 'nsLicenseUser' DESC 'Netscape def - objectClasses: ( 2.16.840.1.113730.3.2.1 NAME 'changeLogEntry' DESC 'LDAP changelog objectclass' SUP top MUST ( targetdn $ changeTime $ changenumber $ changeType ) MAY ( changes $ newrdn $ deleteoldrdn $ newsuperior ) X-ORIGIN 'Changelog Internet Draft' ) - objectClasses: ( 2.16.840.1.113730.3.2.6 NAME 'referral' DESC 'LDAP referrals objectclass' SUP top MAY ( ref ) X-ORIGIN 'LDAPv3 referrals Internet Draft' ) - objectClasses: ( 2.16.840.1.113730.3.2.12 NAME 'passwordObject' DESC 'Netscape defined password policy objectclass' SUP top MAY ( pwdpolicysubentry $ passwordExpirationTime $ passwordExpWarned $ passwordRetryCount $ retryCountResetTime $ accountUnlockTime $ passwordHistory $ passwordAllowChangeTime $ passwordGraceUserTime ) X-ORIGIN 'Netscape Directory Server' ) --objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime $ passwordAdminDN ) X-ORIGIN 'Netscape Directory Server' ) -+objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime $ passwordAdminDN $ passwordSendExpiringTime ) X-ORIGIN 'Netscape Directory Server' ) - objectClasses: ( 2.16.840.1.113730.3.2.30 NAME 'glue' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' ) - objectClasses: ( 2.16.840.1.113730.3.2.32 NAME 'netscapeMachineData' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' ) - objectClasses: ( 2.16.840.1.113730.3.2.38 NAME 'vlvSearch' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ vlvBase $ vlvScope $ vlvFilter ) MAY ( multiLineDescription ) X-ORIGIN 'Netscape Directory Server' ) --- -2.17.2 - diff --git a/SOURCES/0021-Ticket-50013-Log-warn-instead-of-ERR-when-aci-target.patch b/SOURCES/0021-Ticket-50013-Log-warn-instead-of-ERR-when-aci-target.patch deleted file mode 100644 index 377268a..0000000 --- a/SOURCES/0021-Ticket-50013-Log-warn-instead-of-ERR-when-aci-target.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 11ec6a5bb6978f379206de5f2df9fc7c79a9a1c8 Mon Sep 17 00:00:00 2001 -From: German Parente -Date: Tue, 6 Nov 2018 18:46:42 +0100 -Subject: [PATCH] Ticket 50013 - Log warn instead of ERR when aci target does - not exist. - -Bug Description: - -This is something we have very often in IPA context and customers are very often asking why there are errors in the logs: - -[31/Oct/2018:05:52:23.436616394 -0400] - ERR - NSACLPlugin - acl_parse - The ACL target cn=groups,cn=compat,dc=cgparente,dc=local does not exist -[31/Oct/2018:05:52:23.438951763 -0400] - ERR - NSACLPlugin - acl_parse - The ACL target cn=computers,cn=compat,dc=cgparente,dc=local does not exist - -Fix Description: - -just log WARN instead of ERR - -https://pagure.io/389-ds-base/issue/50013 - -Author: German Parente - -Review by: ??? ---- - ldap/servers/plugins/acl/aclparse.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/servers/plugins/acl/aclparse.c b/ldap/servers/plugins/acl/aclparse.c -index a425adbd8..906c1d099 100644 ---- a/ldap/servers/plugins/acl/aclparse.c -+++ b/ldap/servers/plugins/acl/aclparse.c -@@ -147,7 +147,7 @@ acl_parse(Slapi_PBlock *pb, char *str, aci_t *aci_item, char **errbuf) - slapi_search_internal_pb(temppb); - slapi_pblock_get(temppb, SLAPI_PLUGIN_INTOP_RESULT, &rc); - if (rc != LDAP_SUCCESS) { -- slapi_log_err(SLAPI_LOG_ERR, plugin_name, -+ slapi_log_err(SLAPI_LOG_WARNING, plugin_name, - "acl_parse - The ACL target %s does not exist\n", slapi_sdn_get_dn(&targdn)); - } - --- -2.17.2 - diff --git a/SOURCES/0022-Ticket-49997-RFE-ds-replcheck-could-validate-suffix-.patch b/SOURCES/0022-Ticket-49997-RFE-ds-replcheck-could-validate-suffix-.patch deleted file mode 100644 index aec4eb6..0000000 --- a/SOURCES/0022-Ticket-49997-RFE-ds-replcheck-could-validate-suffix-.patch +++ /dev/null @@ -1,82 +0,0 @@ -From d116dd899b4ad64b0ab14f3e153e76a95f54937e Mon Sep 17 00:00:00 2001 -From: German Parente -Date: Sun, 28 Oct 2018 16:29:09 +0100 -Subject: [PATCH] Ticket 49997 RFE: ds-replcheck could validate suffix exists - and it's replicated - -Bug Description: - -seen at customer site, as first request to ldap database is the RUV, if the suffix provided in the command line does not exist or it's not replicated, we have an error message that it's regarding the RUV: - -ds-replcheck -D "cn=directory manager" -w secret12 -b "o=ipaca" -r ldap://ipamaster.germanparente.local:389 -m ldap://ipareplica.germanparente.local -Performing online report... -Connecting to servers... -Gathering Master's RUV... -Error: Failed to get Master RUV entry: {'desc': 'No such object'} - -Fix Description: - -add function to validate suffix exists and it's replicated - -https://pagure.io/389-ds-base/issue/49997 - -Author: German Parente - -Review by: ??? ---- - ldap/admin/src/scripts/ds-replcheck | 32 +++++++++++++++++++++++++++++ - 1 file changed, 32 insertions(+) - -diff --git a/ldap/admin/src/scripts/ds-replcheck b/ldap/admin/src/scripts/ds-replcheck -index e18465dc0..57748b09f 100755 ---- a/ldap/admin/src/scripts/ds-replcheck -+++ b/ldap/admin/src/scripts/ds-replcheck -@@ -816,6 +816,30 @@ def check_for_diffs(mentries, mglue, rentries, rglue, report, opts): - - return report - -+def validate_suffix(ldapnode, suffix, hostname): -+ # Validate suffix exists -+ try: -+ master_basesuffix = ldapnode.search_s(suffix, ldap.SCOPE_BASE ) -+ except ldap.NO_SUCH_OBJECT: -+ print("Error: Failed to validate suffix in {}. {} does not exist.".format(hostname, suffix)) -+ return False -+ except ldap.LDAPError as e: -+ print("Error: failed to validate suffix in {} ({}). ".format(hostname, str(e))) -+ return False -+ -+ # Check suffix is replicated -+ try: -+ replica_filter = "(&(objectclass=nsds5replica)(nsDS5ReplicaRoot=%s))" % suffix -+ master_replica = ldapnode.search_s("cn=config",ldap.SCOPE_SUBTREE,replica_filter) -+ if (len(master_replica) != 1): -+ print("Error: Failed to validate suffix in {}. {} is not replicated.".format(hostname, suffix)) -+ return False -+ except ldap.LDAPError as e: -+ print("Error: failed to validate suffix in {} ({}). ".format(hostname, str(e))) -+ return False -+ -+ return True -+ - - def connect_to_replicas(opts): - ''' Start the paged results searches -@@ -888,6 +912,14 @@ def connect_to_replicas(opts): - "Please check your credentials and LDAP urls are correct.".format(str(e))) - exit(1) - -+ # Validate suffix -+ print ("Validating suffix ...") -+ if not validate_suffix(master, opts['suffix'], opts['mhost']): -+ exit(1) -+ -+ if not validate_suffix(replica,opts['suffix'], opts['rhost']): -+ exit(1) -+ - # Get the RUVs - print ("Gathering Master's RUV...") - try: --- -2.17.2 - diff --git a/SOURCES/0023-Ticket-50363-ds-replcheck-incorrectly-reports-error-.patch b/SOURCES/0023-Ticket-50363-ds-replcheck-incorrectly-reports-error-.patch deleted file mode 100644 index 1d17485..0000000 --- a/SOURCES/0023-Ticket-50363-ds-replcheck-incorrectly-reports-error-.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 86bbfb42aa03a7dd1ea0a9faa130d3cdb31aab5e Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Mon, 13 May 2019 10:03:58 -0400 -Subject: [PATCH] Ticket 50363 - ds-replcheck incorrectly reports error out of - order multi-valued attributes - -Bug Description: If for some reason an entry's multi-valued attribute - values are in different orders on different replicas - the tool reports this as an inconsistency when it is - not. - -Fix Description: For both offline & online processing sort each entry's - multi-valued attribute values. - -https://pagure.io/389-ds-base/issue/50363 - -Reviewed by: firstyear & mhonek (Thanks!!) ---- - ldap/admin/src/scripts/ds-replcheck | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/ldap/admin/src/scripts/ds-replcheck b/ldap/admin/src/scripts/ds-replcheck -index 57748b09f..a9411cb4f 100755 ---- a/ldap/admin/src/scripts/ds-replcheck -+++ b/ldap/admin/src/scripts/ds-replcheck -@@ -110,7 +110,7 @@ def convert_entries(entries): - - for entry in entries: - new_entry = Entry(entry) -- new_entry.data = {k.lower(): v for k, v in list(new_entry.data.items())} -+ new_entry.data = {k.lower(): sorted(v) for k, v in list(new_entry.data.items())} - if new_entry.dn.endswith("cn=mapping tree,cn=config"): - '''Skip replica entry (ldapsearch brings this in because the filter - we use triggers an internal operation to return the config entry - so -@@ -381,6 +381,11 @@ def ldif_search(LDIF, dn): - # Keep track of entry index - we use this later when searching the LDIF again - result['idx'] = count - -+ # Sort all the multi-valued attributes -+ for k, v in data.items(): -+ v.sort() -+ data[k] = v -+ - result['glue'] = None - if found_conflict and found_subentry and found_tombstone is False: - result['entry'] = None --- -2.17.2 - diff --git a/SOURCES/0024-Ticket-50370-CleanAllRUV-task-crashing-during-server.patch b/SOURCES/0024-Ticket-50370-CleanAllRUV-task-crashing-during-server.patch deleted file mode 100644 index ff0c5ef..0000000 --- a/SOURCES/0024-Ticket-50370-CleanAllRUV-task-crashing-during-server.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 5bed4704f3fa6fc6fca1cad9f132985cc7f68056 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Tue, 14 May 2019 13:58:42 -0400 -Subject: [PATCH] Ticket 50370 - CleanAllRUV task crashing during server - shutdown - -Description: There is a race condition during server shutdown that - can cause the server to crash. Increment the active - thread count for each cleaning task to prevent the plugins - from being closed before the thread terminates. - -https://pagure.io/389-ds-base/issue/50370 - -Reviewed by: firstyear(Thanks!) - -(cherry picked from commit 7141b8d10382e8dcb8528b57e5226c82506b79b9) ---- - .../plugins/replication/repl5_replica_config.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - -diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c -index a952b687d..b4aff9eb4 100644 ---- a/ldap/servers/plugins/replication/repl5_replica_config.c -+++ b/ldap/servers/plugins/replication/repl5_replica_config.c -@@ -1630,9 +1630,13 @@ replica_cleanallruv_thread(void *arg) - int aborted = 0; - int rc = 0; - -- if (!data) { -+ if (!data || slapi_is_shutting_down()) { - return; /* no data */ - } -+ -+ /* Increase active thread count to prevent a race condition at server shutdown */ -+ g_incr_active_threadcnt(); -+ - if (data->task) { - slapi_task_inc_refcount(data->task); - slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name, -@@ -1912,6 +1916,7 @@ done: - slapi_ch_free_string(&data->force); - slapi_ch_free_string(&rid_text); - slapi_ch_free((void **)&data); -+ g_decr_active_threadcnt(); - } - - /* -@@ -3005,9 +3010,13 @@ replica_abort_task_thread(void *arg) - int release_it = 0; - int count = 0, rc = 0; - -- if (!data) { -+ if (!data || slapi_is_shutting_down()) { - return; /* no data */ - } -+ -+ /* Increase active thread count to prevent a race condition at server shutdown */ -+ g_incr_active_threadcnt(); -+ - if (data->task) { - slapi_task_inc_refcount(data->task); - slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name, "replica_abort_task_thread --> refcount incremented.\n"); -@@ -3134,6 +3143,7 @@ done: - slapi_ch_free_string(&data->certify); - slapi_sdn_free(&data->sdn); - slapi_ch_free((void **)&data); -+ g_decr_active_threadcnt(); - } - - static int --- -2.17.2 - diff --git a/SOURCES/0025-Ticket-50378-ACI-s-with-IPv4-and-IPv6-bind-rules-do-.patch b/SOURCES/0025-Ticket-50378-ACI-s-with-IPv4-and-IPv6-bind-rules-do-.patch deleted file mode 100644 index b4d8c86..0000000 --- a/SOURCES/0025-Ticket-50378-ACI-s-with-IPv4-and-IPv6-bind-rules-do-.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 7264a239b71b4b5adc6740457586520ad0ba1d3f Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Wed, 15 May 2019 16:04:55 -0400 -Subject: [PATCH] Ticket 50378 - ACI's with IPv4 and IPv6 bind rules do not - work for IPv6 clients - -Description: When the client is a IPv6 client, any ACI's that contain bind rules - for IPv4 addresses essentially break that aci causing it to not be - fully evaluated. - - For example we have an aci like this: - - aci: (targetattr != "aci")(version 3.0; aci "rootdse anon read access"; allow( - read,search,compare) userdn="ldap:///anyone" and - (ip="127.0.0.1" or ip="2620:52:0:84:f816:3eff:fe4b:4f35");) - - So when the client is IPv6 we start processing the IP addresses in - the ACI, as soon as a IPv4 address is found the ACI evaluation stops - and in this case the IPv6 address is never checked and access is denied. - - The problem is that we set the wrong return code variable in libaccess - -https://pagure.io/389-ds-base/issue/50378 - -Reviewed by: mreynolds (one line commit rule) - -(cherry picked from commit 41c30fd557d4cc0aaaf8a9f7767d37746f4c4bc4) ---- - lib/libaccess/lasip.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/lib/libaccess/lasip.cpp b/lib/libaccess/lasip.cpp -index eea7affba..30c546df7 100644 ---- a/lib/libaccess/lasip.cpp -+++ b/lib/libaccess/lasip.cpp -@@ -598,7 +598,7 @@ int LASIpEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, - - node = context->treetop_ipv6; - if ( node == NULL ) { -- retcode = (comparator == CMP_OP_EQ ? LAS_EVAL_FALSE : LAS_EVAL_TRUE); -+ rc = (comparator == CMP_OP_EQ ? LAS_EVAL_FALSE : LAS_EVAL_TRUE); - } else { - addr = PR_ntohs( ipv6->_S6_un._S6_u16[field]); - for (bit = 127; bit >= 0 ; bit--, bit_position--) { --- -2.17.2 - diff --git a/SOURCES/0026-Ticket-50396-Crash-in-PAM-plugin-when-user-does-not-.patch b/SOURCES/0026-Ticket-50396-Crash-in-PAM-plugin-when-user-does-not-.patch deleted file mode 100644 index a31a89a..0000000 --- a/SOURCES/0026-Ticket-50396-Crash-in-PAM-plugin-when-user-does-not-.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 44b6f98bc687f3ec3ae2c40b8086f1bd4936b827 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Mon, 20 May 2019 15:06:54 -0400 -Subject: [PATCH] Ticket 50396 - Crash in PAM plugin when user does not exist - -Description: pam passthru & addn plugin causes crash in bind when - user does not exist. Need to make sure we don't - dereference NULL pointer. - -https://pagure.io/389-ds-base/issue/50396 - -Reviewed by: mreynolds & tbordaz - -(cherry picked from commit 0935b8af6c8925c7a79a0a22103142ef5f7c5960) ---- - ldap/servers/plugins/pam_passthru/pam_ptpreop.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/ldap/servers/plugins/pam_passthru/pam_ptpreop.c b/ldap/servers/plugins/pam_passthru/pam_ptpreop.c -index de9448b90..b62c3c6b6 100644 ---- a/ldap/servers/plugins/pam_passthru/pam_ptpreop.c -+++ b/ldap/servers/plugins/pam_passthru/pam_ptpreop.c -@@ -436,8 +436,9 @@ pam_passthru_bindpreop(Slapi_PBlock *pb) - * We only handle simple bind requests that include non-NULL binddn and - * credentials. Let the Directory Server itself handle everything else. - */ -- if ((method != LDAP_AUTH_SIMPLE) || (*normbinddn == '\0') || -- (creds->bv_len == 0)) { -+ if (method != LDAP_AUTH_SIMPLE || normbinddn == NULL || -+ *normbinddn == '\0' || creds->bv_len == 0) -+ { - slapi_log_err(SLAPI_LOG_PLUGIN, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, - "pam_passthru_bindpreop - Not handled (not simple bind or NULL dn/credentials)\n"); - return retcode; --- -2.17.2 - diff --git a/SOURCES/0027-Ticket-50393-maxlogsperdir-accepting-negative-values.patch b/SOURCES/0027-Ticket-50393-maxlogsperdir-accepting-negative-values.patch deleted file mode 100644 index 1da3a1a..0000000 --- a/SOURCES/0027-Ticket-50393-maxlogsperdir-accepting-negative-values.patch +++ /dev/null @@ -1,428 +0,0 @@ -From 03695c416f7f8311afbded390f3c0ff3637a10d4 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Mon, 20 May 2019 11:38:05 -0400 -Subject: [PATCH] Ticket 50393 - maxlogsperdir accepting negative values - -Description: Improve the log "digit" config setting validation - for all settings. - -https://pagure.io/389-ds-base/issue/50393 - -Reviewed by: tbordaz, firstyear, mhonek, and spichugi (Thanks!!!!) - -(cherry picked from commit ca70d06fbb7a2c06c62f0ba5b192dba36f24b8e3) ---- - dirsrvtests/tests/suites/logging/__init__.py | 3 + - .../suites/logging/logging_config_test.py | 86 +++++++++++ - ldap/servers/slapd/log.c | 143 +++++++++++++----- - 3 files changed, 192 insertions(+), 40 deletions(-) - create mode 100644 dirsrvtests/tests/suites/logging/__init__.py - create mode 100644 dirsrvtests/tests/suites/logging/logging_config_test.py - -diff --git a/dirsrvtests/tests/suites/logging/__init__.py b/dirsrvtests/tests/suites/logging/__init__.py -new file mode 100644 -index 000000000..7f812e357 ---- /dev/null -+++ b/dirsrvtests/tests/suites/logging/__init__.py -@@ -0,0 +1,3 @@ -+""" -+ :Requirement: 389-ds-base: Directory Server Logging Configurations -+""" -diff --git a/dirsrvtests/tests/suites/logging/logging_config_test.py b/dirsrvtests/tests/suites/logging/logging_config_test.py -new file mode 100644 -index 000000000..4d8d68ab5 ---- /dev/null -+++ b/dirsrvtests/tests/suites/logging/logging_config_test.py -@@ -0,0 +1,86 @@ -+import logging -+import pytest -+import os -+import ldap -+from lib389._constants import * -+from lib389.topologies import topology_st as topo -+ -+DEBUGGING = os.getenv("DEBUGGING", default=False) -+if DEBUGGING: -+ logging.getLogger(__name__).setLevel(logging.DEBUG) -+else: -+ logging.getLogger(__name__).setLevel(logging.INFO) -+log = logging.getLogger(__name__) -+ -+big_value = "1111111111111111111111111111111111111111111" -+ -+ -+@pytest.mark.parametrize("attr, invalid_vals, valid_vals", -+ [ -+ ("logexpirationtime", ["-2", "0"], ["1", "-1"]), -+ ("maxlogsize", ["-2", "0"], ["100", "-1"]), -+ ("logmaxdiskspace", ["-2", "0"], ["100", "-1"]), -+ ("logminfreediskspace", ["-2", "0"], ["100", "-1"]), -+ ("mode", ["888", "778", "77", "7777"], ["777", "000", "600"]), -+ ("maxlogsperdir", ["-1", "0"], ["1", "20"]), -+ ("logrotationsynchour", ["-1", "24"], ["0", "23"]), -+ ("logrotationsyncmin", ["-1", "60"], ["0", "59"]), -+ ("logrotationtime", ["-2", "0"], ["100", "-1"]) -+ ]) -+def test_logging_digit_config(topo, attr, invalid_vals, valid_vals): -+ """Validate logging config settings -+ -+ :id: a0ef30e5-538b-46fa-9762-01a4435a15e9 -+ :setup: Standalone Instance -+ :steps: -+ 1. Test log expiration time -+ 2. Test log max size -+ 3. Test log max disk space -+ 4. Test log min disk space -+ 5. Test log mode -+ 6. Test log max number of logs -+ 7. Test log rotation hour -+ 8. Test log rotation minute -+ 9. Test log rotation time -+ :expectedresults: -+ 1. Success -+ 2. Success -+ 3. Success -+ 4. Success -+ 5. Success -+ 6. Success -+ 7. Success -+ 8. Success -+ 9. Success -+ """ -+ -+ accesslog_attr = "nsslapd-accesslog-{}".format(attr) -+ auditlog_attr = "nsslapd-auditlog-{}".format(attr) -+ auditfaillog_attr = "nsslapd-auditfaillog-{}".format(attr) -+ errorlog_attr = "nsslapd-errorlog-{}".format(attr) -+ -+ # Test each log -+ for attr in [accesslog_attr, auditlog_attr, auditfaillog_attr, errorlog_attr]: -+ # Invalid values -+ for invalid_val in invalid_vals: -+ with pytest.raises(ldap.LDAPError): -+ topo.standalone.config.set(attr, invalid_val) -+ -+ # Invalid high value -+ with pytest.raises(ldap.LDAPError): -+ topo.standalone.config.set(attr, big_value) -+ -+ # Non digits -+ with pytest.raises(ldap.LDAPError): -+ topo.standalone.config.set(attr, "abc") -+ -+ # Valid values -+ for valid_val in valid_vals: -+ topo.standalone.config.set(attr, valid_val) -+ -+ -+if __name__ == '__main__': -+ # Run isolated -+ # -s for DEBUG mode -+ CURRENT_FILE = os.path.realpath(__file__) -+ pytest.main(["-s", CURRENT_FILE]) -diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c -index 7dd71541b..2456abf1e 100644 ---- a/ldap/servers/slapd/log.c -+++ b/ldap/servers/slapd/log.c -@@ -817,8 +817,9 @@ log_update_auditfaillogdir(char *pathname, int apply) - int - log_set_mode(const char *attrname, char *value, int logtype, char *errorbuf, int apply) - { -- int v = 0; -+ int64_t v = 0; - int retval = LDAP_SUCCESS; -+ char *endp = NULL; - slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); - - if (NULL == value) { -@@ -833,7 +834,18 @@ log_set_mode(const char *attrname, char *value, int logtype, char *errorbuf, int - return LDAP_SUCCESS; - } - -- v = strtol(value, NULL, 8); -+ errno = 0; -+ v = strtol(value, &endp, 8); -+ if (*endp != '\0' || errno == ERANGE || -+ strlen(value) != 3 || -+ v > 0777 /* octet of 777 511 */ || -+ v < 0) -+ { -+ slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, -+ "Invalid value \"%s\" for attribute (%s) (%ld), value must be three digits between 000 and 777", -+ value, attrname, v); -+ return LDAP_UNWILLING_TO_PERFORM; -+ } - - switch (logtype) { - case SLAPD_ACCESS_LOG: -@@ -895,9 +907,9 @@ int - log_set_numlogsperdir(const char *attrname, char *numlogs_str, int logtype, char *returntext, int apply) - { - slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); -- -+ char *endp = NULL; - int rv = LDAP_SUCCESS; -- int numlogs; -+ int64_t numlogs; - - if (logtype != SLAPD_ACCESS_LOG && - logtype != SLAPD_ERROR_LOG && -@@ -911,7 +923,14 @@ log_set_numlogsperdir(const char *attrname, char *numlogs_str, int logtype, char - return rv; - } - -- numlogs = atoi(numlogs_str); -+ errno = 0; -+ numlogs = strtol(numlogs_str, &endp, 10); -+ if (*endp != '\0' || errno == ERANGE || numlogs < 1) { -+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, -+ "Invalid value \"%s\" for attribute (%s), value must be between 1 and 2147483647", -+ numlogs_str, attrname); -+ return LDAP_UNWILLING_TO_PERFORM; -+ } - - if (numlogs >= 1) { - switch (logtype) { -@@ -960,21 +979,25 @@ int - log_set_logsize(const char *attrname, char *logsize_str, int logtype, char *returntext, int apply) - { - int rv = LDAP_SUCCESS; -- PRInt64 max_logsize; /* in bytes */ -- int logsize; /* in megabytes */ -+ int64_t max_logsize; /* in bytes */ -+ int64_t logsize; /* in megabytes */ -+ char *endp = NULL; - slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); - - if (!apply || !logsize_str || !*logsize_str) - return rv; - -- logsize = atoi(logsize_str); -+ errno = 0; -+ logsize = strtol(logsize_str, &endp, 10); -+ if (*endp != '\0' || errno == ERANGE || logsize < -1 || logsize == 0) { -+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, -+ "Invalid value \"%s\" for attribute (%s), value must be \"-1\" or greater than 0", -+ logsize_str, attrname); -+ return LDAP_UNWILLING_TO_PERFORM; -+ } - - /* convert it to bytes */ -- max_logsize = (PRInt64)logsize * LOG_MB_IN_BYTES; -- -- if (max_logsize <= 0) { -- max_logsize = -1; -- } -+ max_logsize = logsize * LOG_MB_IN_BYTES; - - switch (logtype) { - case SLAPD_ACCESS_LOG: -@@ -1101,8 +1124,9 @@ log_set_rotationsync_enabled(const char *attrname, char *value, int logtype, cha - int - log_set_rotationsynchour(const char *attrname, char *rhour_str, int logtype, char *returntext, int apply) - { -- int rhour = -1; -+ int64_t rhour = -1; - int rv = LDAP_SUCCESS; -+ char *endp = NULL; - slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); - - if (logtype != SLAPD_ACCESS_LOG && -@@ -1115,12 +1139,19 @@ log_set_rotationsynchour(const char *attrname, char *rhour_str, int logtype, cha - } - - /* return if we aren't doing this for real */ -- if (!apply) { -+ if (!apply || !rhour_str || !*rhour_str) { - return rv; - } - -- if (rhour_str && *rhour_str != '\0') -- rhour = atol(rhour_str); -+ errno = 0; -+ rhour = strtol(rhour_str, &endp, 10); -+ if (*endp != '\0' || errno == ERANGE || rhour < 0 || rhour > 23) { -+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, -+ "Invalid value \"%s\" for attribute (%s), value must be \"0\" thru \"23\"", -+ rhour_str, attrname); -+ return LDAP_UNWILLING_TO_PERFORM; -+ } -+ - if (rhour > 23) - rhour = rhour % 24; - -@@ -1161,8 +1192,9 @@ log_set_rotationsynchour(const char *attrname, char *rhour_str, int logtype, cha - int - log_set_rotationsyncmin(const char *attrname, char *rmin_str, int logtype, char *returntext, int apply) - { -- int rmin = -1; -+ int64_t rmin = -1; - int rv = LDAP_SUCCESS; -+ char *endp = NULL; - slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); - - if (logtype != SLAPD_ACCESS_LOG && -@@ -1175,14 +1207,18 @@ log_set_rotationsyncmin(const char *attrname, char *rmin_str, int logtype, char - } - - /* return if we aren't doing this for real */ -- if (!apply) { -+ if (!apply || !rmin_str || !*rmin_str) { - return rv; - } - -- if (rmin_str && *rmin_str != '\0') -- rmin = atol(rmin_str); -- if (rmin > 59) -- rmin = rmin % 60; -+ errno = 0; -+ rmin = strtol(rmin_str, &endp, 10); -+ if (*endp != '\0' || errno == ERANGE || rmin < 0 || rmin > 59) { -+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, -+ "Invalid value \"%s\" for attribute (%s), value must be between \"0\" and \"59\"", -+ rmin_str, attrname); -+ return LDAP_UNWILLING_TO_PERFORM; -+ } - - switch (logtype) { - case SLAPD_ACCESS_LOG: -@@ -1229,8 +1265,9 @@ log_set_rotationtime(const char *attrname, char *rtime_str, int logtype, char *r - { - - int runit = 0; -- int value, rtime; -+ int64_t value, rtime; - int rv = LDAP_SUCCESS; -+ char *endp = NULL; - slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); - - if (logtype != SLAPD_ACCESS_LOG && -@@ -1247,7 +1284,14 @@ log_set_rotationtime(const char *attrname, char *rtime_str, int logtype, char *r - return rv; - } - -- rtime = atoi(rtime_str); -+ errno = 0; -+ rtime = strtol(rtime_str, &endp, 10); -+ if (*endp != '\0' || errno == ERANGE || rtime < -1 || rtime == 0) { -+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, -+ "Invalid value \"%s\" for attribute (%s), value must be \"-1\" or greater than \"0\"", -+ rtime_str, attrname); -+ return LDAP_UNWILLING_TO_PERFORM; -+ } - - if (0 == rtime) { - rtime = -1; /* Value Range: -1 | 1 to PR_INT32_MAX */ -@@ -1332,7 +1376,6 @@ log_set_rotationtimeunit(const char *attrname, char *runit, int logtype, char *e - int origvalue = 0, value = 0; - int runitType; - int rv = 0; -- - slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); - - if (logtype != SLAPD_ACCESS_LOG && -@@ -1448,10 +1491,10 @@ int - log_set_maxdiskspace(const char *attrname, char *maxdiskspace_str, int logtype, char *errorbuf, int apply) - { - int rv = 0; -- PRInt64 mlogsize = 0; /* in bytes */ -- PRInt64 maxdiskspace; /* in bytes */ -- int s_maxdiskspace; /* in megabytes */ -- -+ int64_t mlogsize = 0; /* in bytes */ -+ int64_t maxdiskspace; /* in bytes */ -+ int64_t s_maxdiskspace; /* in megabytes */ -+ char *endp = NULL; - slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); - - if (logtype != SLAPD_ACCESS_LOG && -@@ -1465,7 +1508,14 @@ log_set_maxdiskspace(const char *attrname, char *maxdiskspace_str, int logtype, - if (!apply || !maxdiskspace_str || !*maxdiskspace_str) - return rv; - -- s_maxdiskspace = atoi(maxdiskspace_str); -+ errno = 0; -+ s_maxdiskspace = strtol(maxdiskspace_str, &endp, 10); -+ if (*endp != '\0' || errno == ERANGE || s_maxdiskspace < -1 || s_maxdiskspace == 0) { -+ slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, -+ "Invalid value \"%s\" for attribute (%s), value must be \"-1\" or greater than 0", -+ maxdiskspace_str, attrname); -+ return LDAP_UNWILLING_TO_PERFORM; -+ } - - /* Disk space are in MB but store in bytes */ - switch (logtype) { -@@ -1538,9 +1588,9 @@ int - log_set_mindiskspace(const char *attrname, char *minfreespace_str, int logtype, char *errorbuf, int apply) - { - int rv = LDAP_SUCCESS; -- int minfreespace; /* in megabytes */ -- PRInt64 minfreespaceB; /* in bytes */ -- -+ int64_t minfreespace; /* in megabytes */ -+ int64_t minfreespaceB; /* in bytes */ -+ char *endp = NULL; - slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); - - if (logtype != SLAPD_ACCESS_LOG && -@@ -1556,11 +1606,18 @@ log_set_mindiskspace(const char *attrname, char *minfreespace_str, int logtype, - return rv; - } - -- minfreespace = atoi(minfreespace_str); -+ errno = 0; -+ minfreespace = strtol(minfreespace_str, &endp, 10); -+ if (*endp != '\0' || errno == ERANGE || minfreespace < -1 || minfreespace == 0) { -+ slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, -+ "Invalid value \"%s\" for attribute (%s), value must be \"-1\" or greater than 0", -+ minfreespace_str, attrname); -+ return LDAP_UNWILLING_TO_PERFORM; -+ } - - /* Disk space are in MB but store in bytes */ - if (minfreespace >= 1) { -- minfreespaceB = (PRInt64)minfreespace * LOG_MB_IN_BYTES; -+ minfreespaceB = minfreespace * LOG_MB_IN_BYTES; - switch (logtype) { - case SLAPD_ACCESS_LOG: - LOG_ACCESS_LOCK_WRITE(); -@@ -1602,10 +1659,10 @@ log_set_mindiskspace(const char *attrname, char *minfreespace_str, int logtype, - int - log_set_expirationtime(const char *attrname, char *exptime_str, int logtype, char *errorbuf, int apply) - { -- -- int eunit, value, exptime; -+ int64_t eunit, value, exptime; - int rsec = 0; - int rv = 0; -+ char *endp = NULL; - slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); - - if (logtype != SLAPD_ACCESS_LOG && -@@ -1621,7 +1678,14 @@ log_set_expirationtime(const char *attrname, char *exptime_str, int logtype, cha - return rv; - } - -- exptime = atoi(exptime_str); /* <= 0: no exptime */ -+ errno = 0; -+ exptime = strtol(exptime_str, &endp, 10); -+ if (*endp != '\0' || errno == ERANGE || exptime < -1 || exptime == 0) { -+ slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, -+ "Invalid value \"%s\" for attribute (%s), value must be \"-1\" or greater than 0", -+ exptime_str, attrname); -+ return LDAP_UNWILLING_TO_PERFORM; -+ } - - switch (logtype) { - case SLAPD_ACCESS_LOG: -@@ -1734,7 +1798,6 @@ log_set_expirationtimeunit(const char *attrname, char *expunit, int logtype, cha - } else { - slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: invalid time unit \"%s\"", attrname, expunit); - rv = LDAP_OPERATIONS_ERROR; -- ; - } - - /* return if we aren't doing this for real */ --- -2.17.2 - diff --git a/SOURCES/0028-Issue-49754-Instance-created-using-dscreate-can-t-be.patch b/SOURCES/0028-Issue-49754-Instance-created-using-dscreate-can-t-be.patch deleted file mode 100644 index 2576667..0000000 --- a/SOURCES/0028-Issue-49754-Instance-created-using-dscreate-can-t-be.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 1e31c091f4a62d09fe8e2fbd1fda2d67ccbe8508 Mon Sep 17 00:00:00 2001 -From: Viktor Ashirov -Date: Thu, 23 May 2019 15:38:16 +0200 -Subject: [PATCH] Issue 49754 - Instance created using dscreate can't be - upgraded - -Bug Description: -On 1.3.9 remove_ds_instance() is destructive and deletes -/usr/lib64/dirsrv together with perl modules and 389-ds-base libs. - -Fix Description: -Backport defaults.inf changes for inst_dir - -Relates: https://pagure.io/389-ds-base/issue/49754 - -Reviewed by: mreynolds (Thanks!) ---- - ldap/admin/src/defaults.inf.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/admin/src/defaults.inf.in b/ldap/admin/src/defaults.inf.in -index 8565ff7a0..eff88f238 100644 ---- a/ldap/admin/src/defaults.inf.in -+++ b/ldap/admin/src/defaults.inf.in -@@ -35,7 +35,7 @@ config_dir = @instconfigdir@/slapd-{instance_name} - local_state_dir = @localstatedir@ - run_dir = @localstatedir@/run/dirsrv - pid_file = @localstatedir@/run/dirsrv/slapd-{instance_name}.pid --inst_dir = @serverdir@ -+inst_dir = @serverdir@/slapd-{instance_name} - plugin_dir = @serverplugindir@ - system_schema_dir = @systemschemadir@ - --- -2.17.2 - diff --git a/SOURCES/0029-Ticket-50413-ds-replcheck-Always-display-the-Result-.patch b/SOURCES/0029-Ticket-50413-ds-replcheck-Always-display-the-Result-.patch deleted file mode 100644 index 094e1b3..0000000 --- a/SOURCES/0029-Ticket-50413-ds-replcheck-Always-display-the-Result-.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 62173da703e1c0403f8102ad10a6ca9d0e8e7c82 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Thu, 30 May 2019 15:38:27 -0400 -Subject: [PATCH] Ticket 50413 - ds-replcheck - Always display the Result - Summary - -Description: Previously we only printed a "Result Summary" if there - were no inconsistencies and the entry counts matched. - However, the entry counts do not need to match. So - this made the "Result Summary" checks too strict, and - if things were out of sync there was no Result Summary - printed at all. This fix just always prints a result - summary and it removes the entry count check. - -https://pagure.io/389-ds-base/issue/50413 - -Reviewed by: ? - -(cherry picked from commit 423a7ba01ed3bad52c8caa6a20267f2335b3c69f) ---- - ldap/admin/src/scripts/ds-replcheck | 29 +++++++++++++++++------------ - 1 file changed, 17 insertions(+), 12 deletions(-) - -diff --git a/ldap/admin/src/scripts/ds-replcheck b/ldap/admin/src/scripts/ds-replcheck -index a9411cb4f..aea32fdb4 100755 ---- a/ldap/admin/src/scripts/ds-replcheck -+++ b/ldap/admin/src/scripts/ds-replcheck -@@ -581,14 +581,14 @@ def do_offline_report(opts, output_file=None): - MLDIF = open(opts['mldif'], "r") - except Exception as e: - print('Failed to open Master LDIF: ' + str(e)) -- return None -+ return - - try: - RLDIF = open(opts['rldif'], "r") - except Exception as e: - print('Failed to open Replica LDIF: ' + str(e)) - MLDIF.close() -- return None -+ return - - # Verify LDIF Files - try: -@@ -598,7 +598,7 @@ def do_offline_report(opts, output_file=None): - print('Master LDIF file in invalid, aborting...') - MLDIF.close() - RLDIF.close() -- return None -+ return - try: - print("Validating Replica ldif file ({})...".format(opts['rldif'])) - LDIFRecordList(RLDIF).parse() -@@ -606,7 +606,7 @@ def do_offline_report(opts, output_file=None): - print('Replica LDIF file is invalid, aborting...') - MLDIF.close() - RLDIF.close() -- return None -+ return - - # Get all the dn's, and entry counts - print ("Gathering all the DN's...") -@@ -758,10 +758,13 @@ def do_offline_report(opts, output_file=None): - final_report += ('=====================================================\n\n') - for diff in diff_report: - final_report += ('%s\n' % (diff)) -- if missing_report == "" and len(diff_report) == 0 and m_count == r_count: -- final_report += ('\nResult\n') -- final_report += ('=====================================================\n\n') -- final_report += ('No differences between Master and Replica\n') -+ -+ final_report += ('\nResult\n') -+ final_report += ('=====================================================\n\n') -+ if missing_report == "" and len(diff_report) == 0: -+ final_report += ('No replication differences between Master and Replica\n') -+ else: -+ final_report += ('There are replication differences between Master and Replica\n') - - if output_file: - output_file.write(final_report) -@@ -1009,10 +1012,12 @@ def print_online_report(report, opts, output_file): - for diff in report['diff']: - final_report += ('%s\n' % (diff)) - -- if not missing and len(report['diff']) == 0 and report['m_count'] == report['r_count']: -- final_report += ('\nResult\n') -- final_report += ('=====================================================\n\n') -- final_report += ('No differences between Master and Replica\n') -+ final_report += ('\nResult\n') -+ final_report += ('=====================================================\n\n') -+ if not missing and len(report['diff']) == 0: -+ final_report += ('No replication differences between Master and Replica\n') -+ else: -+ final_report += ('There are replication differences between Master and Replica\n') - - if output_file: - output_file.write(final_report) --- -2.17.2 - diff --git a/SOURCES/0030-Ticket-50389-ns-slapd-craches-while-two-threads-are-.patch b/SOURCES/0030-Ticket-50389-ns-slapd-craches-while-two-threads-are-.patch deleted file mode 100644 index db41887..0000000 --- a/SOURCES/0030-Ticket-50389-ns-slapd-craches-while-two-threads-are-.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 6b7f87a557170164518d7c3b8e408304f2a9c1f4 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Fri, 17 May 2019 14:31:45 +0200 -Subject: [PATCH] Ticket 50389 - ns-slapd craches while two threads are polling - the same connection - -Bug Description: - nspr IO is not multi-threaded safe. - 389-ds should not be in a situation where several threads are polling - a same connection at the same time. - The scenario is a worker send back an operation result at the same time - another worker wants to read an incoming request. - -Fix Description: - The fix consist in synchonizing polling with c_pdumutex. - - The thread that sends data (flush_ber) hold c_pdumutex. - - The thread that reads the data does a non blocking read. It then - enforce ioblocktimeout with iteration of poll. - The reading thread must hold c_pdumutex during poll to synchronize - with the reader thread. - The reading thread must poll with a small timeout - (CONN_TURBO_TIMEOUT_INTERVAL). In order to not block - the thread that send back data, the fix reduces the delay to 0.1s. - -https://pagure.io/389-ds-base/issue/50389 - -Reviewed by: Mark Reynolds, Matus Honek, William Brown - -Platforms tested: F28 - -Flag Day: no - -Doc impact: no - -(cherry picked from commit 2886ba77f664e4734a7ddfe4146f229caca49ce4) ---- - ldap/servers/slapd/connection.c | 5 ++++- - ldap/servers/slapd/daemon.c | 2 ++ - 2 files changed, 6 insertions(+), 1 deletion(-) - -diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c -index 188383b97..945602f20 100644 ---- a/ldap/servers/slapd/connection.c -+++ b/ldap/servers/slapd/connection.c -@@ -932,7 +932,8 @@ connection_free_private_buffer(Connection *conn) - #define CONN_DONE 3 - #define CONN_TIMEDOUT 4 - --#define CONN_TURBO_TIMEOUT_INTERVAL 1000 /* milliseconds */ -+#define CONN_TURBO_TIMEOUT_INTERVAL 100 /* milliseconds */ -+#define CONN_TURBO_TIMEOUT_MAXIMUM 5 /* attempts * interval IE 2000ms with 400 * 5 */ - #define CONN_TURBO_CHECK_INTERVAL 5 /* seconds */ - #define CONN_TURBO_PERCENTILE 50 /* proportion of threads allowed to be in turbo mode */ - #define CONN_TURBO_HYSTERESIS 0 /* avoid flip flopping in and out of turbo mode */ -@@ -1207,7 +1208,9 @@ connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, int * - pr_pd.fd = (PRFileDesc *)conn->c_prfd; - pr_pd.in_flags = PR_POLL_READ; - pr_pd.out_flags = 0; -+ PR_Lock(conn->c_pdumutex); - ret = PR_Poll(&pr_pd, 1, timeout); -+ PR_Unlock(conn->c_pdumutex); - waits_done++; - /* Did we time out ? */ - if (0 == ret) { -diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c -index c77e1f15c..4841a8a5c 100644 ---- a/ldap/servers/slapd/daemon.c -+++ b/ldap/servers/slapd/daemon.c -@@ -1943,6 +1943,8 @@ ns_handle_pr_read_ready(struct ns_job_t *job) - * or something goes seriously wrong. Otherwise, return 0. - * If -1 is returned, PR_GetError() explains why. - * Revision: handle changed to void * to allow 64bit support -+ * -+ * Caller (flush_ber) must hold conn->c_pdumutex - */ - static int - slapd_poll(void *handle, int output) --- -2.17.2 - diff --git a/SOURCES/0031-Issue-50123-with_tmpfiles_d-is-associated-with-syste.patch b/SOURCES/0031-Issue-50123-with_tmpfiles_d-is-associated-with-syste.patch deleted file mode 100644 index d416959..0000000 --- a/SOURCES/0031-Issue-50123-with_tmpfiles_d-is-associated-with-syste.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 957145f661d074aaca1a7aa325fa6943dda80b0c Mon Sep 17 00:00:00 2001 -From: Viktor Ashirov -Date: Thu, 9 May 2019 15:01:22 +0200 -Subject: [PATCH] Issue 50123 - with_tmpfiles_d is associated with systemd - -Bug Description: -Tests fail on 1.3.9 because of the missing tmpfiles_d -in defaults.inf - -Fix Description: -Add tmpfiles_d to defaults.inf - -Fixes https://pagure.io/389-ds-base/issue/50123 - -Reviewed by: mreynolds (Thanks!) ---- - ldap/admin/src/defaults.inf.in | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/ldap/admin/src/defaults.inf.in b/ldap/admin/src/defaults.inf.in -index eff88f238..91486c8e3 100644 ---- a/ldap/admin/src/defaults.inf.in -+++ b/ldap/admin/src/defaults.inf.in -@@ -38,6 +38,7 @@ pid_file = @localstatedir@/run/dirsrv/slapd-{instance_name}.pid - inst_dir = @serverdir@/slapd-{instance_name} - plugin_dir = @serverplugindir@ - system_schema_dir = @systemschemadir@ -+tmpfiles_d = @with_tmpfiles_d@ - - ; These values can be altered in an installation of ds - user = dirsrv --- -2.17.2 - diff --git a/SOURCES/0032-Issue-50426-nsSSL3Ciphers-is-limited-to-1024-charact.patch b/SOURCES/0032-Issue-50426-nsSSL3Ciphers-is-limited-to-1024-charact.patch deleted file mode 100644 index a6b4931..0000000 --- a/SOURCES/0032-Issue-50426-nsSSL3Ciphers-is-limited-to-1024-charact.patch +++ /dev/null @@ -1,186 +0,0 @@ -From c2637e437d5b9fa33410856d2059c2921a90fdac Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Fri, 7 Jun 2019 09:21:31 -0400 -Subject: [PATCH] Issue 50426 - nsSSL3Ciphers is limited to 1024 characters - -Bug Description: There was a hardcoded buffer for processing TLS ciphers. - Anything over 1024 characters was truncated and was not - applied. - -Fix Description: Don't use a fixed size buffer and just use the entire - string. When printing errors about invalid format then - we must use a fixed sized buffer, but we will truncate - that log value as to not exceed the ssl logging function's - buffer, and still output a useful message. - -ASAN approved - -https://pagure.io/389-ds-base/issue/50426 - -Reviewed by: firstyear, tbordaz, and spichugi (Thanks!!!) - -(cherry picked from commit 22f2f9a1502e63bb169b7d599b5a3b35ddb31b8a) ---- - dirsrvtests/tests/suites/tls/cipher_test.py | 51 +++++++++++++++++++++ - ldap/servers/slapd/ssl.c | 34 ++++++-------- - 2 files changed, 66 insertions(+), 19 deletions(-) - create mode 100644 dirsrvtests/tests/suites/tls/cipher_test.py - -diff --git a/dirsrvtests/tests/suites/tls/cipher_test.py b/dirsrvtests/tests/suites/tls/cipher_test.py -new file mode 100644 -index 000000000..058931046 ---- /dev/null -+++ b/dirsrvtests/tests/suites/tls/cipher_test.py -@@ -0,0 +1,51 @@ -+import pytest -+import os -+from lib389.config import Encryption -+from lib389.topologies import topology_st as topo -+ -+ -+def test_long_cipher_list(topo): -+ """Test a long cipher list, and makre sure it is not truncated -+ -+ :id: bc400f54-3966-49c8-b640-abbf4fb2377d -+ :setup: Standalone Instance -+ :steps: -+ 1. Set nsSSL3Ciphers to a very long list of ciphers -+ 2. Ciphers are applied correctly -+ :expectedresults: -+ 1. Success -+ 2. Success -+ """ -+ ENABLED_CIPHER = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384::AES-GCM::AEAD::256" -+ DISABLED_CIPHER = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256::AES-GCM::AEAD::128" -+ CIPHER_LIST = ( -+ "-all,-SSL_CK_RC4_128_WITH_MD5,-SSL_CK_RC4_128_EXPORT40_WITH_MD5,-SSL_CK_RC2_128_CBC_WITH_MD5," -+ "-SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5,-SSL_CK_DES_64_CBC_WITH_MD5,-SSL_CK_DES_192_EDE3_CBC_WITH_MD5," -+ "-TLS_RSA_WITH_RC4_128_MD5,-TLS_RSA_WITH_RC4_128_SHA,-TLS_RSA_WITH_3DES_EDE_CBC_SHA," -+ "-TLS_RSA_WITH_DES_CBC_SHA,-SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,-SSL_RSA_FIPS_WITH_DES_CBC_SHA," -+ "-TLS_RSA_EXPORT_WITH_RC4_40_MD5,-TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,-TLS_RSA_WITH_NULL_MD5," -+ "-TLS_RSA_WITH_NULL_SHA,-TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,-SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA," -+ "-SSL_FORTEZZA_DMS_WITH_RC4_128_SHA,-SSL_FORTEZZA_DMS_WITH_NULL_SHA,-TLS_DHE_DSS_WITH_DES_CBC_SHA," -+ "-TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,-TLS_DHE_RSA_WITH_DES_CBC_SHA,-TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA," -+ "+TLS_RSA_WITH_AES_128_CBC_SHA,-TLS_DHE_DSS_WITH_AES_128_CBC_SHA,-TLS_DHE_RSA_WITH_AES_128_CBC_SHA," -+ "+TLS_RSA_WITH_AES_256_CBC_SHA,-TLS_DHE_DSS_WITH_AES_256_CBC_SHA,-TLS_DHE_RSA_WITH_AES_256_CBC_SHA," -+ "-TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,-TLS_DHE_DSS_WITH_RC4_128_SHA,-TLS_ECDHE_RSA_WITH_RC4_128_SHA," -+ "-TLS_RSA_WITH_NULL_SHA,-TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,-SSL_CK_DES_192_EDE3_CBC_WITH_MD5," -+ "-TLS_RSA_WITH_RC4_128_MD5,-TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,-TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA," -+ "-TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,+TLS_AES_128_GCM_SHA256,+TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" -+ ) -+ -+ topo.standalone.enable_tls() -+ enc = Encryption(topo.standalone) -+ enc.set('nsSSL3Ciphers', CIPHER_LIST) -+ topo.standalone.restart() -+ enabled_ciphers = enc.get_attr_vals_utf8('nssslenabledciphers') -+ assert ENABLED_CIPHER in enabled_ciphers -+ assert DISABLED_CIPHER not in enabled_ciphers -+ -+ -+if __name__ == '__main__': -+ # Run isolated -+ # -s for DEBUG mode -+ CURRENT_FILE = os.path.realpath(__file__) -+ pytest.main(["-s", CURRENT_FILE]) -diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c -index b8eba2da4..ed054db44 100644 ---- a/ldap/servers/slapd/ssl.c -+++ b/ldap/servers/slapd/ssl.c -@@ -95,7 +95,6 @@ static char *configDN = "cn=encryption,cn=config"; - #define CIPHER_SET_ALLOWWEAKDHPARAM 0x200 /* allowWeakDhParam is on */ - #define CIPHER_SET_DISALLOWWEAKDHPARAM 0x400 /* allowWeakDhParam is off */ - -- - #define CIPHER_SET_ISDEFAULT(flag) \ - (((flag)&CIPHER_SET_DEFAULT) ? PR_TRUE : PR_FALSE) - #define CIPHER_SET_ISALL(flag) \ -@@ -689,10 +688,12 @@ _conf_setciphers(char *setciphers, int flags) - active = 0; - break; - default: -- PR_snprintf(err, sizeof(err), "invalid ciphers <%s>: format is " -- "+cipher1,-cipher2...", -- raw); -- return slapi_ch_strdup(err); -+ if (strlen(raw) > MAGNUS_ERROR_LEN) { -+ PR_snprintf(err, sizeof(err) - 3, "%s...", raw); -+ return slapi_ch_smprintf("invalid ciphers <%s>: format is +cipher1,-cipher2...", err); -+ } else { -+ return slapi_ch_smprintf("invalid ciphers <%s>: format is +cipher1,-cipher2...", raw); -+ } - } - if ((t = strchr(setciphers, ','))) - *t++ = '\0'; -@@ -1689,7 +1690,6 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) - PRUint16 NSSVersionMax = enabledNSSVersions.max; - char mymin[VERSION_STR_LENGTH], mymax[VERSION_STR_LENGTH]; - char newmax[VERSION_STR_LENGTH]; -- char cipher_string[1024]; - int allowweakcipher = CIPHER_SET_DEFAULTWEAKCIPHER; - int_fast16_t renegotiation = (int_fast16_t)SSL_RENEGOTIATE_REQUIRES_XTN; - -@@ -1730,21 +1730,17 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) - "Ignoring it and set it to default.", val, configDN); - } - } -- slapi_ch_free((void **)&val); -+ slapi_ch_free_string(&val); - - /* Set SSL cipher preferences */ -- *cipher_string = 0; -- if (ciphers && (*ciphers) && PL_strcmp(ciphers, "blank")) -- PL_strncpyz(cipher_string, ciphers, sizeof(cipher_string)); -- slapi_ch_free((void **)&ciphers); -- -- if (NULL != (val = _conf_setciphers(cipher_string, allowweakcipher))) { -+ if (NULL != (val = _conf_setciphers(ciphers, allowweakcipher))) { - errorCode = PR_GetError(); - slapd_SSL_warn("Failed to set SSL cipher " - "preference information: %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", - val, errorCode, slapd_pr_strerror(errorCode)); -- slapi_ch_free((void **)&val); -+ slapi_ch_free_string(&val); - } -+ slapi_ch_free_string(&ciphers); - freeConfigEntry(&e); - - /* Import pr fd into SSL */ -@@ -1815,12 +1811,12 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) - activation = slapi_entry_attr_get_charptr(e, "nssslactivation"); - if ((!activation) || (!PL_strcasecmp(activation, "off"))) { - /* this family was turned off, goto next */ -- slapi_ch_free((void **)&activation); -+ slapi_ch_free_string(&activation); - freeConfigEntry(&e); - continue; - } - -- slapi_ch_free((void **)&activation); -+ slapi_ch_free_string(&activation); - - token = slapi_entry_attr_get_charptr(e, "nsssltoken"); - personality = slapi_entry_attr_get_charptr(e, "nssslpersonalityssl"); -@@ -1837,8 +1833,8 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) - "family information. Missing nsssltoken or" - "nssslpersonalityssl in %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", - *family, errorCode, slapd_pr_strerror(errorCode)); -- slapi_ch_free((void **)&token); -- slapi_ch_free((void **)&personality); -+ slapi_ch_free_string(&token); -+ slapi_ch_free_string(&personality); - freeConfigEntry(&e); - continue; - } -@@ -1865,7 +1861,7 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) - "private key for cert %s of family %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", - cert_name, *family, - errorCode, slapd_pr_strerror(errorCode)); -- slapi_ch_free((void **)&personality); -+ slapi_ch_free_string(&personality); - CERT_DestroyCertificate(cert); - cert = NULL; - freeConfigEntry(&e); --- -2.17.2 - diff --git a/SOURCES/0033-Ticket-50329-2nd-Possible-Security-Issue-DOS-due-to-.patch b/SOURCES/0033-Ticket-50329-2nd-Possible-Security-Issue-DOS-due-to-.patch deleted file mode 100644 index f9de876..0000000 --- a/SOURCES/0033-Ticket-50329-2nd-Possible-Security-Issue-DOS-due-to-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 335f2a35433a949fc30101655a40940bc6ecec12 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Wed, 15 May 2019 17:46:14 +0200 -Subject: [PATCH] Ticket 50329 - (2nd) Possible Security Issue: DOS due to - ioblocktimeout not applying to TLS - -Bug Description: - A secure socket is configured in blocking mode. If an event - is detected on a secure socket a worker tries to receive the request. - If handshake occurs during the read, it can hang longer than - ioblocktimeout because it takes into account the socket option - rather than the timeout used for the ssl_Recv - -Fix Description: - The fix is specific to secure socket and set this socket option - to do non blocking IO. - -https://pagure.io/389-ds-base/issue/50329 - -Reviewed by: ? - -Platforms tested: F28, RHEL7.6 - -Flag Day: no - -Doc impact: no ---- - ldap/servers/slapd/daemon.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c -index 4841a8a5c..afe0fb737 100644 ---- a/ldap/servers/slapd/daemon.c -+++ b/ldap/servers/slapd/daemon.c -@@ -3193,7 +3193,7 @@ configure_pr_socket(PRFileDesc **pr_socket, int secure, int local) - - if (secure) { - pr_socketoption.option = PR_SockOpt_Nonblocking; -- pr_socketoption.value.non_blocking = 0; -+ pr_socketoption.value.non_blocking = 1; - if (PR_SetSocketOption(*pr_socket, &pr_socketoption) == PR_FAILURE) { - PRErrorCode prerr = PR_GetError(); - slapi_log_err(SLAPI_LOG_ERR, --- -2.21.0 - diff --git a/SOURCES/0034-CVE-deref-plugin-displays-restricted-attributes.patch b/SOURCES/0034-CVE-deref-plugin-displays-restricted-attributes.patch deleted file mode 100644 index be518ec..0000000 --- a/SOURCES/0034-CVE-deref-plugin-displays-restricted-attributes.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 816175c782e708de8ae47d3788dba3a6ed0fe3d8 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Mon, 28 Oct 2019 11:01:33 -0400 -Subject: [PATCH] CVE - deref plugin displays restricted attributes - -Bug Description: If there is an ACI that allows "search" access to an attribute, - the deref plugin access control checks sees this is a "read" - privilege and returns the attribute's value. - -Fix description: For deref plugin we are only concerned with "read" access, not - "search" access. Removed the SLAPI_ACL_SEARCH right flag when - checking access for an attribute. - -Reviewed by: lkrispen ---- - ldap/servers/plugins/deref/deref.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/ldap/servers/plugins/deref/deref.c b/ldap/servers/plugins/deref/deref.c -index cb5ebb830..ec1884ba3 100644 ---- a/ldap/servers/plugins/deref/deref.c -+++ b/ldap/servers/plugins/deref/deref.c -@@ -573,7 +573,7 @@ deref_do_deref_attr(Slapi_PBlock *pb, BerElement *ctrlber, const char *derefdn, - Slapi_Entry **entries = NULL; - int rc; - -- /* If the access check on the attributes is done without retrieveing the entry -+ /* If the access check on the attributes is done without retrieving the entry - * it cannot handle acis which need teh entry, eg to apply a targetfilter rule - * So the determination of attrs which can be dereferenced is delayed - */ -@@ -596,7 +596,7 @@ deref_do_deref_attr(Slapi_PBlock *pb, BerElement *ctrlber, const char *derefdn, - int ii; - int needattrvals = 1; /* need attrvals sequence? */ - if (deref_check_access(pb, entries[0], derefdn, attrs, &retattrs, -- (SLAPI_ACL_SEARCH | SLAPI_ACL_READ))) { -+ SLAPI_ACL_READ)) { - slapi_log_err(SLAPI_LOG_PLUGIN, DEREF_PLUGIN_SUBSYSTEM, - "deref_do_deref_attr - The client does not have permission to read the requested " - "attributes in entry %s\n", -@@ -714,7 +714,7 @@ deref_pre_entry(Slapi_PBlock *pb) - attrs[1] = NULL; - - if (deref_check_access(pb, ent, NULL, attrs, &retattrs, -- (SLAPI_ACL_SEARCH | SLAPI_ACL_READ))) { -+ SLAPI_ACL_READ)) { - slapi_log_err(SLAPI_LOG_PLUGIN, DEREF_PLUGIN_SUBSYSTEM, - "deref_pre_entry - The client does not have permission to read attribute %s in entry %s\n", - spec->derefattr, slapi_entry_get_dn_const(ent)); --- -2.21.0 - diff --git a/SOURCES/0035-Issue-49624-modrdn-silently-fails-if-DB-deadlock-occ.patch b/SOURCES/0035-Issue-49624-modrdn-silently-fails-if-DB-deadlock-occ.patch deleted file mode 100644 index b4d283f..0000000 --- a/SOURCES/0035-Issue-49624-modrdn-silently-fails-if-DB-deadlock-occ.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 40d1c78f85a40065e6c7d1399368885d7f684f54 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Thu, 22 Aug 2019 10:26:24 -0400 -Subject: [PATCH] Issue 49624 - modrdn silently fails if DB deadlock occurs - -Bug Description: - -If a DB Deadlock error occurs during a modrdn operation the entry -cache gets updated (corrupted), but the update is not applied to -the database. - -Fix Description: - -Looks like there was a copy & paste error, and the wrong attribute -was updated during the retry of the modrdn operation. - -relates: https://pagure.io/389-ds-base/issue/49624 - -Reviewed by: lkrispenz (Thanks!) ---- - ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -index 65610d613..433ed88fb 100644 ---- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c -@@ -251,7 +251,7 @@ ldbm_back_modrdn(Slapi_PBlock *pb) - slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn); - slapi_sdn_free(&dn_newsuperiordn); - slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, orig_dn_newsuperiordn); -- orig_dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn); -+ dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn); - /* must duplicate ec before returning it to cache, - * which could free the entry. */ - if ((tmpentry = backentry_dup(original_entry ? original_entry : ec)) == NULL) { --- -2.21.0 - diff --git a/SOURCES/0036-Issue-50536-Audit-log-heading-written-to-log-after-e.patch b/SOURCES/0036-Issue-50536-Audit-log-heading-written-to-log-after-e.patch deleted file mode 100644 index fcc5ebe..0000000 --- a/SOURCES/0036-Issue-50536-Audit-log-heading-written-to-log-after-e.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 2fb026b0fe7e35dfabcb90b79fae3e60f9f95340 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Wed, 7 Aug 2019 16:57:17 -0400 -Subject: [PATCH] Issue 50536 - Audit log heading written to log after every - update - -Bug Description: Once the audit log is rotated the log "title" is incorrectly - written to the log after every single update. This happened - becuase when we udpated the state of the log it was applied - to a local variable, and not the log info structure itself. - -Fix Description: After writting the "title", update the state of the log using - a pointer to the log info structure. - -relates: https://pagure.io/389-ds-base/issue/50536 - -Reviewed by: lkrispenz(Thanks!) ---- - ldap/servers/slapd/log.c | 14 +++++++------- - ldap/servers/slapd/proto-slap.h | 2 +- - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c -index 2456abf1e..f308a4813 100644 ---- a/ldap/servers/slapd/log.c -+++ b/ldap/servers/slapd/log.c -@@ -2073,11 +2073,11 @@ slapd_log_audit( - int retval = LDAP_SUCCESS; - int lbackend = loginfo.log_backend; /* We copy this to make these next checks atomic */ - -- int state = 0; -+ int *state; - if (sourcelog == SLAPD_AUDIT_LOG) { -- state = loginfo.log_audit_state; -+ state = &loginfo.log_audit_state; - } else if (sourcelog == SLAPD_AUDITFAIL_LOG) { -- state = loginfo.log_auditfail_state; -+ state = &loginfo.log_auditfail_state; - } else { - /* How did we even get here! */ - return 1; -@@ -2106,9 +2106,9 @@ int - slapd_log_audit_internal( - char *buffer, - int buf_len, -- int state) -+ int *state) - { -- if ((state & LOGGING_ENABLED) && (loginfo.log_audit_file != NULL)) { -+ if ((*state & LOGGING_ENABLED) && (loginfo.log_audit_file != NULL)) { - LOG_AUDIT_LOCK_WRITE(); - if (log__needrotation(loginfo.log_audit_fdes, - SLAPD_AUDIT_LOG) == LOG_ROTATE) { -@@ -2122,9 +2122,9 @@ slapd_log_audit_internal( - loginfo.log_audit_rotationsyncclock += PR_ABS(loginfo.log_audit_rotationtime_secs); - } - } -- if (state & LOGGING_NEED_TITLE) { -+ if (*state & LOGGING_NEED_TITLE) { - log_write_title(loginfo.log_audit_fdes); -- state &= ~LOGGING_NEED_TITLE; -+ *state &= ~LOGGING_NEED_TITLE; - } - LOG_WRITE_NOW_NO_ERR(loginfo.log_audit_fdes, buffer, buf_len, 0); - LOG_AUDIT_UNLOCK_WRITE(); -diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h -index a0648ca3c..e37f702ea 100644 ---- a/ldap/servers/slapd/proto-slap.h -+++ b/ldap/servers/slapd/proto-slap.h -@@ -777,7 +777,7 @@ int slapi_log_access(int level, char *fmt, ...) - ; - #endif - int slapd_log_audit(char *buffer, int buf_len, int sourcelog); --int slapd_log_audit_internal(char *buffer, int buf_len, int state); -+int slapd_log_audit_internal(char *buffer, int buf_len, int *state); - int slapd_log_auditfail(char *buffer, int buf_len); - int slapd_log_auditfail_internal(char *buffer, int buf_len); - void log_access_flush(void); --- -2.21.0 - diff --git a/SOURCES/0037-Issue-50636-Crash-during-sasl-bind.patch b/SOURCES/0037-Issue-50636-Crash-during-sasl-bind.patch deleted file mode 100644 index 7285610..0000000 --- a/SOURCES/0037-Issue-50636-Crash-during-sasl-bind.patch +++ /dev/null @@ -1,47 +0,0 @@ -From b4b8c8adcda0168cc18e40045d0a25eaf74ba4e1 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Thu, 17 Oct 2019 09:42:02 -0400 -Subject: [PATCH] Issue 50636 - Crash during sasl bind - -Bug Description: - Sasl bind registers IO layers (sasl_IoMethods) that will be - pushed (and called) by the next incoming operation. - So the next incoming operation should synchronize itself - with the sasl bind. - -Fix Description: - The call to connection_call_io_layer_callbacks, that pushes - registered methods, must hold c_mutex so that it let - a pending sasl bind to fully register the methods. - -https://pagure.io/389-ds-base/issue/50636 - -Reviewed by: Ludwig Krispenz, Mark Reynolds ---- - ldap/servers/slapd/connection.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c -index 945602f20..3599512af 100644 ---- a/ldap/servers/slapd/connection.c -+++ b/ldap/servers/slapd/connection.c -@@ -1584,12 +1584,14 @@ connection_threadmain() - */ - pb_conn->c_anonlimits_set = 1; - } -- PR_ExitMonitor(pb_conn->c_mutex); -- -+ /* must hold c_mutex so that it synchronizes the IO layer push -+ * with a potential pending sasl bind that is registering the IO layer -+ */ - if (connection_call_io_layer_callbacks(pb_conn)) { - slapi_log_err(SLAPI_LOG_ERR, "connection_threadmain", - "Could not add/remove IO layers from connection\n"); - } -+ PR_ExitMonitor(pb_conn->c_mutex); - break; - default: - break; --- -2.21.0 - diff --git a/SOURCES/0038-Issue-49850-ldbm_get_nonleaf_ids-slow-for-databases-.patch b/SOURCES/0038-Issue-49850-ldbm_get_nonleaf_ids-slow-for-databases-.patch deleted file mode 100644 index 2928fda..0000000 --- a/SOURCES/0038-Issue-49850-ldbm_get_nonleaf_ids-slow-for-databases-.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 8355b844dbc7097ddc5639a1da0932c60ca50aee Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Wed, 16 Oct 2019 20:27:30 -0400 -Subject: [PATCH] Issue 49850 - ldbm_get_nonleaf_ids() slow for databases with - many non-leaf entries - -Bug Description: The logs from an LDIF import indicated that gathering non-leaf IDs - for creating the ancestorid index took an enormous amount of time, - over 10hrs. The root cause is that the parentid index btree ordering - is lexical, but the IDList being built up from it is sorted numerically. - In the existing code, the IDList is maintained in constantly sorted - order by idl_insert(). - -Fix Description: ldbm_get_nonleaf_ids() switches to idl_append_extend() instead idl_insert() - for building up the IDList and then sorts the result only once, using - qsort with idl_sort_cmp, after the entire list has been gathered. - - The improvement on identical hardware is for the operation to take 10 - seconds rather than 10 hours - -Patch Author: Thomas Lackey Thanks for the great contribution!!! - -relates: https://pagure.io/389-ds-base/issue/49850 - -Reviewed by: mreynolds, tbordaz, and firstyear ---- - ldap/servers/slapd/back-ldbm/ancestorid.c | 20 +++++++++++++++++++- - 1 file changed, 19 insertions(+), 1 deletion(-) - -diff --git a/ldap/servers/slapd/back-ldbm/ancestorid.c b/ldap/servers/slapd/back-ldbm/ancestorid.c -index 24642923d..254a3aa3b 100644 ---- a/ldap/servers/slapd/back-ldbm/ancestorid.c -+++ b/ldap/servers/slapd/back-ldbm/ancestorid.c -@@ -82,7 +82,14 @@ ldbm_get_nonleaf_ids(backend *be, DB_TXN *txn, IDList **idl, ImportJob *job) - ret = dbc->c_get(dbc, &key, &data, DB_NEXT_NODUP); - if ((ret == 0) && (*(char *)key.data == EQ_PREFIX)) { - id = (ID)strtoul((char *)key.data + 1, NULL, 10); -- idl_insert(&nodes, id); -+ /* -+ * TEL 20180711 - switch to idl_append instead of idl_insert because there is no -+ * no need to keep the list constantly sorted, which can be very expensive with -+ * large databases (exacerbated by the fact that the parentid btree ordering is -+ * lexical, but the idl_insert ordering is numeric). It is enough to gather them -+ * all together and sort them once at the end. -+ */ -+ idl_append_extend(&nodes, id); - } - key_count++; - if (!(key_count % PROGRESS_INTERVAL)) { -@@ -107,6 +114,17 @@ ldbm_get_nonleaf_ids(backend *be, DB_TXN *txn, IDList **idl, ImportJob *job) - if (ret != 0) - ldbm_nasty("ldbm_get_nonleaf_ids", sourcefile, 13030, ret); - -+ if (ret == 0) { -+ /* now sort it */ -+ import_log_notice(job, SLAPI_LOG_INFO, "ldbm_get_nonleaf_ids", -+ "Starting sort of ancestorid non-leaf IDs..."); -+ -+ qsort((void *)&nodes->b_ids[0], nodes->b_nids, (size_t)sizeof(ID), idl_sort_cmp); -+ -+ import_log_notice(job, SLAPI_LOG_INFO, "ldbm_get_nonleaf_ids", -+ "Finished sort of ancestorid non-leaf IDs."); -+ } -+ - out: - /* Close the cursor */ - if (dbc != NULL) { --- -2.21.0 - diff --git a/SOURCES/0039-Ticket-49850-cont-fix-crash-in-ldbm_non_leaf.patch b/SOURCES/0039-Ticket-49850-cont-fix-crash-in-ldbm_non_leaf.patch deleted file mode 100644 index 4f6d607..0000000 --- a/SOURCES/0039-Ticket-49850-cont-fix-crash-in-ldbm_non_leaf.patch +++ /dev/null @@ -1,29 +0,0 @@ -From c9e602ebdb0fb8b8ee526d272e8a6fdf23a26a4b Mon Sep 17 00:00:00 2001 -From: Ludwig Krispenz -Date: Thu, 24 Oct 2019 14:26:20 +0200 -Subject: [PATCH] Ticket 49850 cont -fix crash in ldbm_non_leaf - - Bug: if the ldif to be imported contains only one entry there are no leaf nodes - and the call to qsort crashes - - Fix: check that nodes is not NULL ---- - ldap/servers/slapd/back-ldbm/ancestorid.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/servers/slapd/back-ldbm/ancestorid.c b/ldap/servers/slapd/back-ldbm/ancestorid.c -index 254a3aa3b..f26ac1364 100644 ---- a/ldap/servers/slapd/back-ldbm/ancestorid.c -+++ b/ldap/servers/slapd/back-ldbm/ancestorid.c -@@ -114,7 +114,7 @@ ldbm_get_nonleaf_ids(backend *be, DB_TXN *txn, IDList **idl, ImportJob *job) - if (ret != 0) - ldbm_nasty("ldbm_get_nonleaf_ids", sourcefile, 13030, ret); - -- if (ret == 0) { -+ if (ret == 0 && nodes) { - /* now sort it */ - import_log_notice(job, SLAPI_LOG_INFO, "ldbm_get_nonleaf_ids", - "Starting sort of ancestorid non-leaf IDs..."); --- -2.21.0 - diff --git a/SOURCES/0040-Issue-50538-cleanAllRUV-task-limit-is-not-enforced-f.patch b/SOURCES/0040-Issue-50538-cleanAllRUV-task-limit-is-not-enforced-f.patch deleted file mode 100644 index 0743a34..0000000 --- a/SOURCES/0040-Issue-50538-cleanAllRUV-task-limit-is-not-enforced-f.patch +++ /dev/null @@ -1,682 +0,0 @@ -From 94703d5171853b69bb8ef9574f32bc9f0c051632 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Wed, 7 Aug 2019 20:36:53 -0400 -Subject: [PATCH] Issue 50538 - cleanAllRUV task limit is not enforced for - replicated tasks - -Bug Description: - -There is a hard limit of 64 concurrent cleanAllRUV tasks, but this limit is -only enforced when creating "new" tasks. It was not enforced when a task was -received via an extended operation. There were also race conditions in the -existing logic that allowed the array of cleaned rids to get corrupted . This -allowed for a very large number of task threads to be created. - -Fix Description: - -Maintain a new counter to keep track of the number of clean and abort threads -to make sure it never over runs the rid array buffers. - -relates: https://pagure.io/389-ds-base/issue/50538 - -Reviewed by: lkrispenz(Thanks!) ---- - .../suites/replication/cleanallruv_test.py | 47 +++- - ldap/servers/plugins/replication/repl5.h | 7 +- - .../replication/repl5_replica_config.c | 247 ++++++++++-------- - ldap/servers/plugins/replication/repl_extop.c | 19 +- - 4 files changed, 202 insertions(+), 118 deletions(-) - -diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_test.py -index 620a53e1a..43801dd52 100644 ---- a/dirsrvtests/tests/suites/replication/cleanallruv_test.py -+++ b/dirsrvtests/tests/suites/replication/cleanallruv_test.py -@@ -1,5 +1,5 @@ - # --- BEGIN COPYRIGHT BLOCK --- --# Copyright (C) 2016 Red Hat, Inc. -+# Copyright (C) 2019 Red Hat, Inc. - # All rights reserved. - # - # License: GPL (version 3 or any later version). -@@ -7,7 +7,6 @@ - # --- END COPYRIGHT BLOCK --- - # - import threading -- - import pytest - from lib389.tasks import * - from lib389.utils import * -@@ -859,6 +858,50 @@ def test_multiple_tasks_with_force(topology_m4): - restore_master4(topology_m4) - - -+def test_max_tasks(topology_m4): -+ """Test we can not create more than 64 cleaning tasks -+ -+ :id: c34d0b40-3c3e-4f53-8656-5e4c2a310a1f -+ :setup: Replication setup with four masters -+ :steps: -+ 1. Stop masters 3 & 4 -+ 2. Create over 64 tasks between m1 and m2 -+ 3. Check logs to see if (>65) tasks were rejected -+ -+ :expectedresults: -+ 1. Success -+ 2. Success -+ 3. Success -+ """ -+ -+ # Stop masters 3 & 4 -+ m1 = topology_m4.ms["master1"] -+ m2 = topology_m4.ms["master2"] -+ m3 = topology_m4.ms["master3"] -+ m4 = topology_m4.ms["master4"] -+ m3.stop() -+ m4.stop() -+ -+ # Add over 64 tasks between master1 & 2 to try to exceed the 64 task limit -+ for i in range(1, 64): -+ cruv_task = CleanAllRUVTask(m1) -+ cruv_task.create(properties={ -+ 'replica-id': str(i), -+ 'replica-base-dn': DEFAULT_SUFFIX, -+ 'replica-force-cleaning': 'no', # This forces these tasks to stick around -+ }) -+ cruv_task = CleanAllRUVTask(m2) -+ cruv_task.create(properties={ -+ 'replica-id': "10" + str(i), -+ 'replica-base-dn': DEFAULT_SUFFIX, -+ 'replica-force-cleaning': 'yes', # This allows the tasks to propagate -+ }) -+ -+ # Check the errors log for our error message in master 1 -+ assert m1.searchErrorsLog('Exceeded maximum number of active CLEANALLRUV tasks') -+>>>>>>> ab24aa4cb... Issue 50538 - cleanAllRUV task limit is not enforced for replicated tasks -+ -+ - if __name__ == '__main__': - # Run isolated - # -s for DEBUG mode -diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h -index e08fec752..d414926c2 100644 ---- a/ldap/servers/plugins/replication/repl5.h -+++ b/ldap/servers/plugins/replication/repl5.h -@@ -80,6 +80,8 @@ - #define CLEANRUV_FINISHED "finished" - #define CLEANRUV_CLEANING "cleaning" - #define CLEANRUV_NO_MAXCSN "no maxcsn" -+#define CLEANALLRUV_ID "CleanAllRUV Task" -+#define ABORT_CLEANALLRUV_ID "Abort CleanAllRUV Task" - - /* DS 5.0 replication protocol error codes */ - #define NSDS50_REPL_REPLICA_READY 0x00 /* Replica ready, go ahead */ -@@ -784,6 +786,7 @@ void multimaster_mtnode_construct_replicas(void); - void multimaster_be_state_change(void *handle, char *be_name, int old_be_state, int new_be_state); - - #define CLEANRIDSIZ 64 /* maximum number for concurrent CLEANALLRUV tasks */ -+#define CLEANRID_BUFSIZ 128 - - typedef struct _cleanruv_data - { -@@ -815,6 +818,8 @@ int get_replica_type(Replica *r); - int replica_execute_cleanruv_task_ext(Object *r, ReplicaId rid); - void add_cleaned_rid(cleanruv_data *data, char *maxcsn); - int is_cleaned_rid(ReplicaId rid); -+int32_t check_and_set_cleanruv_task_count(ReplicaId rid); -+int32_t check_and_set_abort_cleanruv_task_count(void); - int replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int *returncode, char *returntext, void *arg); - void replica_cleanallruv_thread_ext(void *arg); - void stop_ruv_cleaning(void); -@@ -833,8 +838,6 @@ void set_cleaned_rid(ReplicaId rid); - void cleanruv_log(Slapi_Task *task, int rid, char *task_type, int sev_level, char *fmt, ...); - char *replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn); - -- -- - /* replutil.c */ - LDAPControl *create_managedsait_control(void); - LDAPControl *create_backend_control(Slapi_DN *sdn); -diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c -index b4aff9eb4..0ba2cd976 100644 ---- a/ldap/servers/plugins/replication/repl5_replica_config.c -+++ b/ldap/servers/plugins/replication/repl5_replica_config.c -@@ -30,17 +30,18 @@ - #define CLEANALLRUV "CLEANALLRUV" - #define CLEANALLRUVLEN 11 - #define REPLICA_RDN "cn=replica" --#define CLEANALLRUV_ID "CleanAllRUV Task" --#define ABORT_CLEANALLRUV_ID "Abort CleanAllRUV Task" - - int slapi_log_urp = SLAPI_LOG_REPL; --static ReplicaId cleaned_rids[CLEANRIDSIZ + 1] = {0}; --static ReplicaId pre_cleaned_rids[CLEANRIDSIZ + 1] = {0}; --static ReplicaId aborted_rids[CLEANRIDSIZ + 1] = {0}; --static Slapi_RWLock *rid_lock = NULL; --static Slapi_RWLock *abort_rid_lock = NULL; -+static ReplicaId cleaned_rids[CLEANRID_BUFSIZ] = {0}; -+static ReplicaId pre_cleaned_rids[CLEANRID_BUFSIZ] = {0}; -+static ReplicaId aborted_rids[CLEANRID_BUFSIZ] = {0}; -+static PRLock *rid_lock = NULL; -+static PRLock *abort_rid_lock = NULL; - static PRLock *notify_lock = NULL; - static PRCondVar *notify_cvar = NULL; -+static PRLock *task_count_lock = NULL; -+static int32_t clean_task_count = 0; -+static int32_t abort_task_count = 0; - - /* Forward Declartions */ - static int replica_config_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg); -@@ -67,8 +68,6 @@ static int replica_cleanallruv_send_abort_extop(Repl_Agmt *ra, Slapi_Task *task, - static int replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *basedn, char *rid_text, char *maxcsn, Slapi_Task *task); - static int replica_cleanallruv_replica_alive(Repl_Agmt *agmt); - static int replica_cleanallruv_check_ruv(char *repl_root, Repl_Agmt *ra, char *rid_text, Slapi_Task *task, char *force); --static int get_cleanruv_task_count(void); --static int get_abort_cleanruv_task_count(void); - static int replica_cleanup_task(Object *r, const char *task_name, char *returntext, int apply_mods); - static int replica_task_done(Replica *replica); - static void delete_cleaned_rid_config(cleanruv_data *data); -@@ -114,20 +113,27 @@ replica_config_init() - PR_GetError()); - return -1; - } -- rid_lock = slapi_new_rwlock(); -+ rid_lock = PR_NewLock(); - if (rid_lock == NULL) { - slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_init - " - "Failed to create rid_lock; NSPR error - %d\n", - PR_GetError()); - return -1; - } -- abort_rid_lock = slapi_new_rwlock(); -+ abort_rid_lock = PR_NewLock(); - if (abort_rid_lock == NULL) { - slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_init - " - "Failed to create abort_rid_lock; NSPR error - %d\n", - PR_GetError()); - return -1; - } -+ task_count_lock = PR_NewLock(); -+ if (task_count_lock == NULL) { -+ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_init - " -+ "Failed to create task_count_lock; NSPR error - %d\n", -+ PR_GetError()); -+ return -1; -+ } - if ((notify_lock = PR_NewLock()) == NULL) { - slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_init - " - "Failed to create notify lock; NSPR error - %d\n", -@@ -1484,12 +1490,6 @@ replica_execute_cleanall_ruv_task(Object *r, ReplicaId rid, Slapi_Task *task, co - - cleanruv_log(pre_task, rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Initiating CleanAllRUV Task..."); - -- if (get_cleanruv_task_count() >= CLEANRIDSIZ) { -- /* we are already running the maximum number of tasks */ -- cleanruv_log(pre_task, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, -- "Exceeded maximum number of active CLEANALLRUV tasks(%d)", CLEANRIDSIZ); -- return LDAP_UNWILLING_TO_PERFORM; -- } - /* - * Grab the replica - */ -@@ -1541,6 +1541,13 @@ replica_execute_cleanall_ruv_task(Object *r, ReplicaId rid, Slapi_Task *task, co - goto fail; - } - -+ if (check_and_set_cleanruv_task_count(rid) != LDAP_SUCCESS) { -+ cleanruv_log(NULL, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, -+ "Exceeded maximum number of active CLEANALLRUV tasks(%d)", CLEANRIDSIZ); -+ rc = LDAP_UNWILLING_TO_PERFORM; -+ goto fail; -+ } -+ - /* - * Launch the cleanallruv thread. Once all the replicas are cleaned it will release the rid - */ -@@ -1548,6 +1555,9 @@ replica_execute_cleanall_ruv_task(Object *r, ReplicaId rid, Slapi_Task *task, co - if (data == NULL) { - cleanruv_log(pre_task, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, "Failed to allocate cleanruv_data. Aborting task."); - rc = -1; -+ PR_Lock(task_count_lock); -+ clean_task_count--; -+ PR_Unlock(task_count_lock); - goto fail; - } - data->repl_obj = r; -@@ -1630,13 +1640,13 @@ replica_cleanallruv_thread(void *arg) - int aborted = 0; - int rc = 0; - -- if (!data || slapi_is_shutting_down()) { -- return; /* no data */ -- } -- - /* Increase active thread count to prevent a race condition at server shutdown */ - g_incr_active_threadcnt(); - -+ if (!data || slapi_is_shutting_down()) { -+ goto done; -+ } -+ - if (data->task) { - slapi_task_inc_refcount(data->task); - slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name, -@@ -1683,16 +1693,13 @@ replica_cleanallruv_thread(void *arg) - slapi_task_begin(data->task, 1); - } - /* -- * Presetting the rid prevents duplicate thread creation, but allows the db and changelog to still -- * process updates from the rid. -- * set_cleaned_rid() blocks updates, so we don't want to do that... yet unless we are in force mode. -- * If we are forcing a clean independent of state of other servers for this RID we can set_cleaned_rid() -+ * We have already preset this rid, but if we are forcing a clean independent of state -+ * of other servers for this RID we can set_cleaned_rid() - */ - if (data->force) { - set_cleaned_rid(data->rid); -- } else { -- preset_cleaned_rid(data->rid); - } -+ - rid_text = slapi_ch_smprintf("%d", data->rid); - csn_as_string(data->maxcsn, PR_FALSE, csnstr); - /* -@@ -1862,6 +1869,9 @@ done: - /* - * If the replicas are cleaned, release the rid - */ -+ if (slapi_is_shutting_down()) { -+ stop_ruv_cleaning(); -+ } - if (!aborted && !slapi_is_shutting_down()) { - /* - * Success - the rid has been cleaned! -@@ -1880,10 +1890,9 @@ done: - } else { - cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Propagated task does not delete Keep alive entry (%d).", data->rid); - } -- - clean_agmts(data); - remove_cleaned_rid(data->rid); -- cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Successfully cleaned rid(%d).", data->rid); -+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Successfully cleaned rid(%d)", data->rid); - } else { - /* - * Shutdown or abort -@@ -1916,6 +1925,10 @@ done: - slapi_ch_free_string(&data->force); - slapi_ch_free_string(&rid_text); - slapi_ch_free((void **)&data); -+ /* decrement task count */ -+ PR_Lock(task_count_lock); -+ clean_task_count--; -+ PR_Unlock(task_count_lock); - g_decr_active_threadcnt(); - } - -@@ -2415,16 +2428,14 @@ replica_send_cleanruv_task(Repl_Agmt *agmt, cleanruv_data *clean_data) - int - is_cleaned_rid(ReplicaId rid) - { -- int i; -- -- slapi_rwlock_rdlock(rid_lock); -- for (i = 0; i < CLEANRIDSIZ && cleaned_rids[i] != 0; i++) { -+ PR_Lock(rid_lock); -+ for (size_t i = 0; i < CLEANRID_BUFSIZ; i++) { - if (rid == cleaned_rids[i]) { -- slapi_rwlock_unlock(rid_lock); -+ PR_Unlock(rid_lock); - return 1; - } - } -- slapi_rwlock_unlock(rid_lock); -+ PR_Unlock(rid_lock); - - return 0; - } -@@ -2432,16 +2443,14 @@ is_cleaned_rid(ReplicaId rid) - int - is_pre_cleaned_rid(ReplicaId rid) - { -- int i; -- -- slapi_rwlock_rdlock(rid_lock); -- for (i = 0; i < CLEANRIDSIZ && pre_cleaned_rids[i] != 0; i++) { -+ PR_Lock(rid_lock); -+ for (size_t i = 0; i < CLEANRID_BUFSIZ; i++) { - if (rid == pre_cleaned_rids[i]) { -- slapi_rwlock_unlock(rid_lock); -+ PR_Unlock(rid_lock); - return 1; - } - } -- slapi_rwlock_unlock(rid_lock); -+ PR_Unlock(rid_lock); - - return 0; - } -@@ -2454,14 +2463,14 @@ is_task_aborted(ReplicaId rid) - if (rid == 0) { - return 0; - } -- slapi_rwlock_rdlock(abort_rid_lock); -- for (i = 0; i < CLEANRIDSIZ && aborted_rids[i] != 0; i++) { -+ PR_Lock(abort_rid_lock); -+ for (i = 0; i < CLEANRID_BUFSIZ && aborted_rids[i] != 0; i++) { - if (rid == aborted_rids[i]) { -- slapi_rwlock_unlock(abort_rid_lock); -+ PR_Unlock(abort_rid_lock); - return 1; - } - } -- slapi_rwlock_unlock(abort_rid_lock); -+ PR_Unlock(abort_rid_lock); - return 0; - } - -@@ -2470,15 +2479,14 @@ preset_cleaned_rid(ReplicaId rid) - { - int i; - -- slapi_rwlock_wrlock(rid_lock); -- for (i = 0; i < CLEANRIDSIZ; i++) { -+ PR_Lock(rid_lock); -+ for (i = 0; i < CLEANRID_BUFSIZ && pre_cleaned_rids[i] != rid; i++) { - if (pre_cleaned_rids[i] == 0) { - pre_cleaned_rids[i] = rid; -- pre_cleaned_rids[i + 1] = 0; - break; - } - } -- slapi_rwlock_unlock(rid_lock); -+ PR_Unlock(rid_lock); - } - - /* -@@ -2491,14 +2499,13 @@ set_cleaned_rid(ReplicaId rid) - { - int i; - -- slapi_rwlock_wrlock(rid_lock); -- for (i = 0; i < CLEANRIDSIZ; i++) { -+ PR_Lock(rid_lock); -+ for (i = 0; i < CLEANRID_BUFSIZ && cleaned_rids[i] != rid; i++) { - if (cleaned_rids[i] == 0) { - cleaned_rids[i] = rid; -- cleaned_rids[i + 1] = 0; - } - } -- slapi_rwlock_unlock(rid_lock); -+ PR_Unlock(rid_lock); - } - - /* -@@ -2570,15 +2577,14 @@ add_aborted_rid(ReplicaId rid, Replica *r, char *repl_root) - int rc; - int i; - -- slapi_rwlock_wrlock(abort_rid_lock); -- for (i = 0; i < CLEANRIDSIZ; i++) { -+ PR_Lock(abort_rid_lock); -+ for (i = 0; i < CLEANRID_BUFSIZ; i++) { - if (aborted_rids[i] == 0) { - aborted_rids[i] = rid; -- aborted_rids[i + 1] = 0; - break; - } - } -- slapi_rwlock_unlock(abort_rid_lock); -+ PR_Unlock(abort_rid_lock); - /* - * Write the rid to the config entry - */ -@@ -2621,21 +2627,24 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip) - char *data; - char *dn; - int rc; -- int i; - - if (r == NULL) - return; - - if (skip) { - /* skip the deleting of the config, and just remove the in memory rid */ -- slapi_rwlock_wrlock(abort_rid_lock); -- for (i = 0; i < CLEANRIDSIZ && aborted_rids[i] != rid; i++) -- ; /* found rid, stop */ -- for (; i < CLEANRIDSIZ; i++) { -- /* rewrite entire array */ -- aborted_rids[i] = aborted_rids[i + 1]; -- } -- slapi_rwlock_unlock(abort_rid_lock); -+ ReplicaId new_abort_rids[CLEANRID_BUFSIZ] = {0}; -+ int32_t idx = 0; -+ -+ PR_Lock(abort_rid_lock); -+ for (size_t i = 0; i < CLEANRID_BUFSIZ; i++) { -+ if (aborted_rids[i] != rid) { -+ new_abort_rids[idx] = aborted_rids[i]; -+ idx++; -+ } -+ } -+ memcpy(aborted_rids, new_abort_rids, sizeof(new_abort_rids)); -+ PR_Unlock(abort_rid_lock); - } else { - /* only remove the config, leave the in-memory rid */ - dn = replica_get_dn(r); -@@ -2793,27 +2802,31 @@ bail: - void - remove_cleaned_rid(ReplicaId rid) - { -- int i; -- /* -- * Remove this rid, and optimize the array -- */ -- slapi_rwlock_wrlock(rid_lock); -+ ReplicaId new_cleaned_rids[CLEANRID_BUFSIZ] = {0}; -+ ReplicaId new_pre_cleaned_rids[CLEANRID_BUFSIZ] = {0}; -+ size_t idx = 0; -+ -+ PR_Lock(rid_lock); - -- for (i = 0; i < CLEANRIDSIZ && cleaned_rids[i] != rid; i++) -- ; /* found rid, stop */ -- for (; i < CLEANRIDSIZ; i++) { -- /* rewrite entire array */ -- cleaned_rids[i] = cleaned_rids[i + 1]; -+ for (size_t i = 0; i < CLEANRID_BUFSIZ; i++) { -+ if (cleaned_rids[i] != rid) { -+ new_cleaned_rids[idx] = cleaned_rids[i]; -+ idx++; -+ } - } -+ memcpy(cleaned_rids, new_cleaned_rids, sizeof(new_cleaned_rids)); -+ - /* now do the preset cleaned rids */ -- for (i = 0; i < CLEANRIDSIZ && pre_cleaned_rids[i] != rid; i++) -- ; /* found rid, stop */ -- for (; i < CLEANRIDSIZ; i++) { -- /* rewrite entire array */ -- pre_cleaned_rids[i] = pre_cleaned_rids[i + 1]; -+ idx = 0; -+ for (size_t i = 0; i < CLEANRID_BUFSIZ; i++) { -+ if (pre_cleaned_rids[i] != rid) { -+ new_pre_cleaned_rids[idx] = pre_cleaned_rids[i]; -+ idx++; -+ } - } -+ memcpy(pre_cleaned_rids, new_pre_cleaned_rids, sizeof(new_pre_cleaned_rids)); - -- slapi_rwlock_unlock(rid_lock); -+ PR_Unlock(rid_lock); - } - - /* -@@ -2841,16 +2854,6 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb __attribute__((unused)), - char *ridstr = NULL; - int rc = SLAPI_DSE_CALLBACK_OK; - -- if (get_abort_cleanruv_task_count() >= CLEANRIDSIZ) { -- /* we are already running the maximum number of tasks */ -- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, -- "Exceeded maximum number of active ABORT CLEANALLRUV tasks(%d)", -- CLEANRIDSIZ); -- cleanruv_log(task, -1, ABORT_CLEANALLRUV_ID, SLAPI_LOG_ERR, "%s", returntext); -- *returncode = LDAP_OPERATIONS_ERROR; -- return SLAPI_DSE_CALLBACK_ERROR; -- } -- - /* allocate new task now */ - task = slapi_new_task(slapi_entry_get_ndn(e)); - -@@ -2935,6 +2938,16 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb __attribute__((unused)), - */ - certify_all = "no"; - } -+ -+ if (check_and_set_abort_cleanruv_task_count() != LDAP_SUCCESS) { -+ /* we are already running the maximum number of tasks */ -+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, -+ "Exceeded maximum number of active ABORT CLEANALLRUV tasks(%d)", -+ CLEANRIDSIZ); -+ cleanruv_log(task, -1, ABORT_CLEANALLRUV_ID, SLAPI_LOG_ERR, "%s", returntext); -+ *returncode = LDAP_UNWILLING_TO_PERFORM; -+ goto out; -+ } - /* - * Create payload - */ -@@ -3143,6 +3156,9 @@ done: - slapi_ch_free_string(&data->certify); - slapi_sdn_free(&data->sdn); - slapi_ch_free((void **)&data); -+ PR_Lock(task_count_lock); -+ abort_task_count--; -+ PR_Unlock(task_count_lock); - g_decr_active_threadcnt(); - } - -@@ -3494,36 +3510,43 @@ replica_cleanallruv_check_ruv(char *repl_root, Repl_Agmt *agmt, char *rid_text, - return rc; - } - --static int --get_cleanruv_task_count(void) -+/* -+ * Before starting a cleanAllRUV task make sure there are not -+ * too many task threads already running. If everything is okay -+ * also pre-set the RID now so rebounding extended ops do not -+ * try to clean it over and over. -+ */ -+int32_t -+check_and_set_cleanruv_task_count(ReplicaId rid) - { -- int i, count = 0; -+ int32_t rc = 0; - -- slapi_rwlock_wrlock(rid_lock); -- for (i = 0; i < CLEANRIDSIZ; i++) { -- if (pre_cleaned_rids[i] != 0) { -- count++; -- } -+ PR_Lock(task_count_lock); -+ if (clean_task_count >= CLEANRIDSIZ) { -+ rc = -1; -+ } else { -+ clean_task_count++; -+ preset_cleaned_rid(rid); - } -- slapi_rwlock_unlock(rid_lock); -+ PR_Unlock(task_count_lock); - -- return count; -+ return rc; - } - --static int --get_abort_cleanruv_task_count(void) -+int32_t -+check_and_set_abort_cleanruv_task_count(void) - { -- int i, count = 0; -+ int32_t rc = 0; - -- slapi_rwlock_wrlock(rid_lock); -- for (i = 0; i < CLEANRIDSIZ; i++) { -- if (aborted_rids[i] != 0) { -- count++; -+ PR_Lock(task_count_lock); -+ if (abort_task_count > CLEANRIDSIZ) { -+ rc = -1; -+ } else { -+ abort_task_count++; - } -- } -- slapi_rwlock_unlock(rid_lock); -+ PR_Unlock(task_count_lock); - -- return count; -+ return rc; - } - - /* -diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c -index 68e2544b4..0c2abb6d5 100644 ---- a/ldap/servers/plugins/replication/repl_extop.c -+++ b/ldap/servers/plugins/replication/repl_extop.c -@@ -1393,6 +1393,12 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) - rc = LDAP_OPERATIONS_ERROR; - goto out; - } -+ if (check_and_set_abort_cleanruv_task_count() != LDAP_SUCCESS) { -+ cleanruv_log(NULL, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, -+ "Exceeded maximum number of active abort CLEANALLRUV tasks(%d)", CLEANRIDSIZ); -+ rc = LDAP_UNWILLING_TO_PERFORM; -+ goto out; -+ } - /* - * Prepare the abort data - */ -@@ -1499,6 +1505,7 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) - if (force == NULL) { - force = "no"; - } -+ - maxcsn = csn_new(); - csn_init_by_string(maxcsn, csnstr); - /* -@@ -1535,13 +1542,21 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) - goto free_and_return; - } - -+ if (check_and_set_cleanruv_task_count((ReplicaId)rid) != LDAP_SUCCESS) { -+ cleanruv_log(NULL, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, -+ "Exceeded maximum number of active CLEANALLRUV tasks(%d)", CLEANRIDSIZ); -+ rc = LDAP_UNWILLING_TO_PERFORM; -+ goto free_and_return; -+ } -+ - if (replica_get_type(r) != REPLICA_TYPE_READONLY) { - /* - * Launch the cleanruv monitoring thread. Once all the replicas are cleaned it will release the rid - * - * This will also release mtnode_ext->replica - */ -- slapi_log_err(SLAPI_LOG_INFO, repl_plugin_name, "multimaster_extop_cleanruv - CleanAllRUV Task - Launching cleanAllRUV thread...\n"); -+ -+ cleanruv_log(NULL, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, "Launching cleanAllRUV thread...\n"); - data = (cleanruv_data *)slapi_ch_calloc(1, sizeof(cleanruv_data)); - if (data == NULL) { - slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "multimaster_extop_cleanruv - CleanAllRUV Task - Failed to allocate " -@@ -1635,7 +1650,7 @@ free_and_return: - ber_printf(resp_bere, "{s}", CLEANRUV_ACCEPTED); - ber_flatten(resp_bere, &resp_bval); - slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, resp_bval); -- slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); -+ slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL); - /* resp_bere */ - if (NULL != resp_bere) { - ber_free(resp_bere, 1); --- -2.21.0 - diff --git a/SOURCES/0041-Fix-cherry-pick-error-for-cleanAllRUV-issue.patch b/SOURCES/0041-Fix-cherry-pick-error-for-cleanAllRUV-issue.patch deleted file mode 100644 index 6cd3bc1..0000000 --- a/SOURCES/0041-Fix-cherry-pick-error-for-cleanAllRUV-issue.patch +++ /dev/null @@ -1,24 +0,0 @@ -From cbbadc2d339eef9e3220cbaa8578d17b95b66265 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Fri, 1 Nov 2019 09:52:18 -0400 -Subject: [PATCH 2/2] Fix cherry-pick error for cleanAllRUV issue - ---- - dirsrvtests/tests/suites/replication/cleanallruv_test.py | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_test.py -index 43801dd52..caf214b19 100644 ---- a/dirsrvtests/tests/suites/replication/cleanallruv_test.py -+++ b/dirsrvtests/tests/suites/replication/cleanallruv_test.py -@@ -899,7 +899,6 @@ def test_max_tasks(topology_m4): - - # Check the errors log for our error message in master 1 - assert m1.searchErrorsLog('Exceeded maximum number of active CLEANALLRUV tasks') -->>>>>>> ab24aa4cb... Issue 50538 - cleanAllRUV task limit is not enforced for replicated tasks - - - if __name__ == '__main__': --- -2.21.0 - diff --git a/SOURCES/0042-Ticket-50736-RetroCL-trimming-may-crash-at-shutdown-.patch b/SOURCES/0042-Ticket-50736-RetroCL-trimming-may-crash-at-shutdown-.patch deleted file mode 100644 index b0bc6a8..0000000 --- a/SOURCES/0042-Ticket-50736-RetroCL-trimming-may-crash-at-shutdown-.patch +++ /dev/null @@ -1,263 +0,0 @@ -From 9a8ee0954699da05501ded2900a834584346ef85 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Mon, 25 Nov 2019 10:59:44 +0100 -Subject: [PATCH] Ticket 50736 - RetroCL trimming may crash at shutdown if - trimming configuration is invalid - -Bug Description: - If config of retroCL trimming contains invalid value for trim-interval - and/or maxage, then the trimming initialization is skipped. - In such case the trimming structures are not allocated and if they - are freed at shutdown it triggers a crash - -Fix Description: - When trimming mechanism is stopped (at shutdown) check that - it was successfully initialized before freeing the structs - -https://pagure.io/389-ds-base/issue/50736 - -Reviewed by: Mark Reynolds - -Platforms tested: F30 - -Flag Day: no - -Doc impact: no ---- - .../suites/replication/changelog_test.py | 185 ++++++++++++++++++ - ldap/servers/plugins/retrocl/retrocl_trim.c | 17 +- - 2 files changed, 196 insertions(+), 6 deletions(-) - -diff --git a/dirsrvtests/tests/suites/replication/changelog_test.py b/dirsrvtests/tests/suites/replication/changelog_test.py -index 0b6b886f3..0d3e85bb2 100755 ---- a/dirsrvtests/tests/suites/replication/changelog_test.py -+++ b/dirsrvtests/tests/suites/replication/changelog_test.py -@@ -16,6 +16,12 @@ from lib389.replica import Replicas - from lib389.idm.user import UserAccounts - from lib389.topologies import topology_m2 as topo - from lib389._constants import * -+from lib389.plugins import RetroChangelogPlugin -+from lib389.dseldif import DSEldif -+from lib389.tasks import * -+from lib389.utils import * -+ -+pytestmark = pytest.mark.tier1 - - TEST_ENTRY_NAME = 'replusr' - NEW_RDN_NAME = 'cl5usr' -@@ -235,6 +241,185 @@ def test_verify_changelog_offline_backup(topo): - _check_changelog_ldif(topo, changelog_ldif) - - -+@pytest.mark.ds47669 -+def test_changelog_maxage(topo, changelog_init): -+ """Check nsslapd-changelog max age values -+ -+ :id: d284ff27-03b2-412c-ac74-ac4f2d2fae3b -+ :setup: Replication with two master, change nsslapd-changelogdir to -+ '/var/lib/dirsrv/slapd-master1/changelog' and -+ set cn=Retro Changelog Plugin,cn=plugins,cn=config to 'on' -+ :steps: -+ 1. Set nsslapd-changelogmaxage in cn=changelog5,cn=config to values - '12345','10s','30M','12h','2D','4w' -+ 2. Set nsslapd-changelogmaxage in cn=changelog5,cn=config to values - '-123','xyz' -+ -+ :expectedresults: -+ 1. Operation should be successful -+ 2. Operation should be unsuccessful -+ """ -+ log.info('1. Test nsslapd-changelogmaxage in cn=changelog5,cn=config') -+ -+ # bind as directory manager -+ topo.ms["master1"].log.info("Bind as %s" % DN_DM) -+ topo.ms["master1"].simple_bind_s(DN_DM, PASSWORD) -+ -+ add_and_check(topo, CHANGELOG, MAXAGE, '12345', True) -+ add_and_check(topo, CHANGELOG, MAXAGE, '10s', True) -+ add_and_check(topo, CHANGELOG, MAXAGE, '30M', True) -+ add_and_check(topo, CHANGELOG, MAXAGE, '12h', True) -+ add_and_check(topo, CHANGELOG, MAXAGE, '2D', True) -+ add_and_check(topo, CHANGELOG, MAXAGE, '4w', True) -+ add_and_check(topo, CHANGELOG, MAXAGE, '-123', False) -+ add_and_check(topo, CHANGELOG, MAXAGE, 'xyz', False) -+ -+ -+@pytest.mark.ds47669 -+def test_ticket47669_changelog_triminterval(topo, changelog_init): -+ """Check nsslapd-changelog triminterval values -+ -+ :id: 8f850c37-7e7c-49dd-a4e0-9344638616d6 -+ :setup: Replication with two master, change nsslapd-changelogdir to -+ '/var/lib/dirsrv/slapd-master1/changelog' and -+ set cn=Retro Changelog Plugin,cn=plugins,cn=config to 'on' -+ :steps: -+ 1. Set nsslapd-changelogtrim-interval in cn=changelog5,cn=config to values - -+ '12345','10s','30M','12h','2D','4w' -+ 2. Set nsslapd-changelogtrim-interval in cn=changelog5,cn=config to values - '-123','xyz' -+ -+ :expectedresults: -+ 1. Operation should be successful -+ 2. Operation should be unsuccessful -+ """ -+ log.info('2. Test nsslapd-changelogtrim-interval in cn=changelog5,cn=config') -+ -+ # bind as directory manager -+ topo.ms["master1"].log.info("Bind as %s" % DN_DM) -+ topo.ms["master1"].simple_bind_s(DN_DM, PASSWORD) -+ -+ add_and_check(topo, CHANGELOG, TRIMINTERVAL, '12345', True) -+ add_and_check(topo, CHANGELOG, TRIMINTERVAL, '10s', True) -+ add_and_check(topo, CHANGELOG, TRIMINTERVAL, '30M', True) -+ add_and_check(topo, CHANGELOG, TRIMINTERVAL, '12h', True) -+ add_and_check(topo, CHANGELOG, TRIMINTERVAL, '2D', True) -+ add_and_check(topo, CHANGELOG, TRIMINTERVAL, '4w', True) -+ add_and_check(topo, CHANGELOG, TRIMINTERVAL, '-123', False) -+ add_and_check(topo, CHANGELOG, TRIMINTERVAL, 'xyz', False) -+ -+ -+@pytest.mark.ds47669 -+def test_changelog_compactdbinterval(topo, changelog_init): -+ """Check nsslapd-changelog compactdbinterval values -+ -+ :id: 0f4b3118-9dfa-4c2a-945c-72847b42a48c -+ :setup: Replication with two master, change nsslapd-changelogdir to -+ '/var/lib/dirsrv/slapd-master1/changelog' and -+ set cn=Retro Changelog Plugin,cn=plugins,cn=config to 'on' -+ :steps: -+ 1. Set nsslapd-changelogcompactdb-interval in cn=changelog5,cn=config to values - -+ '12345','10s','30M','12h','2D','4w' -+ 2. Set nsslapd-changelogcompactdb-interval in cn=changelog5,cn=config to values - -+ '-123','xyz' -+ -+ :expectedresults: -+ 1. Operation should be successful -+ 2. Operation should be unsuccessful -+ """ -+ log.info('3. Test nsslapd-changelogcompactdb-interval in cn=changelog5,cn=config') -+ -+ # bind as directory manager -+ topo.ms["master1"].log.info("Bind as %s" % DN_DM) -+ topo.ms["master1"].simple_bind_s(DN_DM, PASSWORD) -+ -+ add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '12345', True) -+ add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '10s', True) -+ add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '30M', True) -+ add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '12h', True) -+ add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '2D', True) -+ add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '4w', True) -+ add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '-123', False) -+ add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, 'xyz', False) -+ -+ -+@pytest.mark.ds47669 -+def test_retrochangelog_maxage(topo, changelog_init): -+ """Check nsslapd-retrochangelog max age values -+ -+ :id: 0cb84d81-3e86-4dbf-84a2-66aefd8281db -+ :setup: Replication with two master, change nsslapd-changelogdir to -+ '/var/lib/dirsrv/slapd-master1/changelog' and -+ set cn=Retro Changelog Plugin,cn=plugins,cn=config to 'on' -+ :steps: -+ 1. Set nsslapd-changelogmaxage in cn=Retro Changelog Plugin,cn=plugins,cn=config to values - -+ '12345','10s','30M','12h','2D','4w' -+ 2. Set nsslapd-changelogmaxage in cn=Retro Changelog Plugin,cn=plugins,cn=config to values - -+ '-123','xyz' -+ -+ :expectedresults: -+ 1. Operation should be successful -+ 2. Operation should be unsuccessful -+ """ -+ log.info('4. Test nsslapd-changelogmaxage in cn=Retro Changelog Plugin,cn=plugins,cn=config') -+ -+ # bind as directory manager -+ topo.ms["master1"].log.info("Bind as %s" % DN_DM) -+ topo.ms["master1"].simple_bind_s(DN_DM, PASSWORD) -+ -+ add_and_check(topo, RETROCHANGELOG, MAXAGE, '12345', True) -+ add_and_check(topo, RETROCHANGELOG, MAXAGE, '10s', True) -+ add_and_check(topo, RETROCHANGELOG, MAXAGE, '30M', True) -+ add_and_check(topo, RETROCHANGELOG, MAXAGE, '12h', True) -+ add_and_check(topo, RETROCHANGELOG, MAXAGE, '2D', True) -+ add_and_check(topo, RETROCHANGELOG, MAXAGE, '4w', True) -+ add_and_check(topo, RETROCHANGELOG, MAXAGE, '-123', False) -+ add_and_check(topo, RETROCHANGELOG, MAXAGE, 'xyz', False) -+ -+ topo.ms["master1"].log.info("ticket47669 was successfully verified.") -+ -+@pytest.mark.ds50736 -+def test_retrochangelog_trimming_crash(topo, changelog_init): -+ """Check that when retroCL nsslapd-retrocthangelog contains invalid -+ value, then the instance does not crash at shutdown -+ -+ :id: 5d9bd7ca-e9bf-4be9-8fc8-902aa5513052 -+ :setup: Replication with two master, change nsslapd-changelogdir to -+ '/var/lib/dirsrv/slapd-master1/changelog' and -+ set cn=Retro Changelog Plugin,cn=plugins,cn=config to 'on' -+ :steps: -+ 1. Set nsslapd-changelogmaxage in cn=Retro Changelog Plugin,cn=plugins,cn=config to value '-1' -+ This value is invalid. To disable retroCL trimming it should be set to 0 -+ 2. Do several restart -+ 3. check there is no 'Detected Disorderly Shutdown' message (crash) -+ 4. restore valid value for nsslapd-changelogmaxage '1w' -+ -+ :expectedresults: -+ 1. Operation should be successful -+ 2. Operation should be successful -+ 3. Operation should be successful -+ 4. Operation should be successful -+ """ -+ log.info('1. Test retroCL trimming crash in cn=Retro Changelog Plugin,cn=plugins,cn=config') -+ -+ # set the nsslapd-changelogmaxage directly on dse.ldif -+ # because the set value is invalid -+ topo.ms["master1"].log.info("ticket50736 start verification") -+ topo.ms["master1"].stop() -+ retroPlugin = RetroChangelogPlugin(topo.ms["master1"]) -+ dse_ldif = DSEldif(topo.ms["master1"]) -+ dse_ldif.replace(retroPlugin.dn, 'nsslapd-changelogmaxage', '-1') -+ topo.ms["master1"].start() -+ -+ # The crash should be systematic, but just in case do several restart -+ # with a delay to let all plugin init -+ for i in range(5): -+ time.sleep(1) -+ topo.ms["master1"].stop() -+ topo.ms["master1"].start() -+ -+ assert not topo.ms["master1"].detectDisorderlyShutdown() -+ -+ topo.ms["master1"].log.info("ticket 50736 was successfully verified.") -+ -+ - if __name__ == '__main__': - # Run isolated - # -s for DEBUG mode -diff --git a/ldap/servers/plugins/retrocl/retrocl_trim.c b/ldap/servers/plugins/retrocl/retrocl_trim.c -index a46534984..0378eb7f6 100644 ---- a/ldap/servers/plugins/retrocl/retrocl_trim.c -+++ b/ldap/servers/plugins/retrocl/retrocl_trim.c -@@ -481,11 +481,16 @@ retrocl_init_trimming(void) - void - retrocl_stop_trimming(void) - { -- retrocl_trimming = 0; -- if (retrocl_trim_ctx) { -- slapi_eq_cancel(retrocl_trim_ctx); -- retrocl_trim_ctx = NULL; -+ if (retrocl_trimming) { -+ /* RetroCL trimming config was valid and trimming struct allocated -+ * Let's free them -+ */ -+ retrocl_trimming = 0; -+ if (retrocl_trim_ctx) { -+ slapi_eq_cancel(retrocl_trim_ctx); -+ retrocl_trim_ctx = NULL; -+ } -+ PR_DestroyLock(ts.ts_s_trim_mutex); -+ ts.ts_s_trim_mutex = NULL; - } -- PR_DestroyLock(ts.ts_s_trim_mutex); -- ts.ts_s_trim_mutex = NULL; - } --- -2.21.1 - diff --git a/SOURCES/0043-Issue-50529-LDAP-server-returning-PWP-controls-in-di.patch b/SOURCES/0043-Issue-50529-LDAP-server-returning-PWP-controls-in-di.patch deleted file mode 100644 index 0eeb397..0000000 --- a/SOURCES/0043-Issue-50529-LDAP-server-returning-PWP-controls-in-di.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 37449e509f4a4253bacea57adf6c1d860eaaf1bb Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Fri, 2 Aug 2019 12:07:07 -0400 -Subject: [PATCH] Issue 50529 - LDAP server returning PWP controls in - different sequence - -Description: The server returns password policy controls in different orders - depending on the state of grace logins. The requested control, - if any, should be returned first, followed by any controls the - server might add. - -relates: https://pagure.io/389-ds-base/issue/50529 - -Reviewed by: mreynolds (one line commit rule) ---- - ldap/servers/slapd/pw_mgmt.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/servers/slapd/pw_mgmt.c b/ldap/servers/slapd/pw_mgmt.c -index befac50cd..ca76fc12f 100644 ---- a/ldap/servers/slapd/pw_mgmt.c -+++ b/ldap/servers/slapd/pw_mgmt.c -@@ -207,10 +207,10 @@ skip: - - /* password expired and user exceeded limit of grace attemps. - * Send result and also the control */ -- slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0); - if (pwresponse_req) { - slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_PWDEXPIRED); - } -+ slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0); - slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, - "password expired!", 0, NULL); - --- -2.21.1 - diff --git a/SOURCES/0044-Issue-50572-After-running-cl-dump-dbdir-cldb-ldif.do.patch b/SOURCES/0044-Issue-50572-After-running-cl-dump-dbdir-cldb-ldif.do.patch deleted file mode 100644 index 4441022..0000000 --- a/SOURCES/0044-Issue-50572-After-running-cl-dump-dbdir-cldb-ldif.do.patch +++ /dev/null @@ -1,153 +0,0 @@ -From c0f3b0c3c95aad6b67a80643bbf389acf7aa191d Mon Sep 17 00:00:00 2001 -From: Simon Pichugin -Date: Thu, 29 Aug 2019 15:51:56 +0200 -Subject: [PATCH] Issue 50572 - After running cl-dump dbdir/cldb/*ldif.done are - not deleted - -Description: By default, remove ldif.done files after running cl-dump. -Add an option '-l' which allows keep the files. -Update man files. - -https://pagure.io/389-ds-base/issue/50572 - -Reviewed by: firstyear, mreynolds (Thanks!) ---- - ldap/admin/src/scripts/cl-dump.pl | 23 +++++++++++++++-------- - man/man1/cl-dump.1 | 11 +++++++---- - 2 files changed, 22 insertions(+), 12 deletions(-) - -diff --git a/ldap/admin/src/scripts/cl-dump.pl b/ldap/admin/src/scripts/cl-dump.pl -index f4ad5dd33..2e7f20413 100755 ---- a/ldap/admin/src/scripts/cl-dump.pl -+++ b/ldap/admin/src/scripts/cl-dump.pl -@@ -5,7 +5,7 @@ - # All rights reserved. - # - # License: GPL (version 3 or any later version). --# See LICENSE for details. -+# See LICENSE for details. - # END COPYRIGHT BLOCK - ################################################################################### - # -@@ -13,7 +13,7 @@ - # - # SYNOPSIS: - # cl-dump.pl [-h host] [-p port] [-D bind-dn] -w bind-password | -P bind-cert --# [-r replica-roots] [-o output-file] [-c] [-v] -+# [-r replica-roots] [-o output-file] [-c] [-l] [-v] - # - # cl-dump.pl -i changelog-ldif-file-with-base64encoding [-o output-file] [-c] - # -@@ -22,7 +22,7 @@ - # - # OPTIONS: - # -c Dump and interpret CSN only. This option can be used with or --# without -i option. -+# without -i option. - # - # -D bind-dn - # Directory server's bind DN. Default to "cn=Directory Manager" if -@@ -32,6 +32,8 @@ - # Directory server's host. Default to the server where the script - # is running. - # -+# -l Preserve generated ldif.done files from changelogdir -+# - # -i changelog-ldif-file-with-base64encoding - # If you already have a ldif-like changelog, but the changes - # in that file are encoded, you may use this option to -@@ -68,7 +70,7 @@ - # all of this nonsense can be omitted if the mozldapsdk and perldap are - # installed in the operating system locations (e.g. /usr/lib /usr/lib/perl5) - --$usage="Usage: $0 [-h host] [-p port] [-D bind-dn] [-w bind-password | -P bind-cert] [-r replica-roots] [-o output-file] [-c] [-v]\n\n $0 -i changelog-ldif-file-with-base64encoding [-o output-file] [-c]\n"; -+$usage="Usage: $0 [-h host] [-p port] [-D bind-dn] [-w bind-password | -P bind-cert] [-r replica-roots] [-o output-file] [-c] [-l] [-v]\n\n $0 -i changelog-ldif-file-with-base64encoding [-o output-file] [-c]\n"; - - use Getopt::Std; # Parse command line arguments - use Mozilla::LDAP::Conn; # LDAP module for Perl -@@ -86,7 +88,7 @@ $version = "Directory Server Changelog Dump - Version 1.0"; - $| = 1; - - # Check for legal options -- if (!getopts('h:p:D:w:P:r:o:cvi:')) { -+ if (!getopts('h:p:D:w:P:r:o:clvi:')) { - print $usage; - exit -1; - } -@@ -123,7 +125,7 @@ sub validateArgs - if ($opt_o && ! open (OUTPUT, ">$opt_o")) { - print "Can't create output file $opt_o\n"; - $rc = -1; -- } -+ } - # Open STDOUT if option -o is missing - open (OUTPUT, ">-") if !$opt_o; - -@@ -194,10 +196,15 @@ sub cl_dump_and_decode - else { - &cl_decode ($_); - } -- # Test op -M doesn't work well so we use rename -+ # Test op -M doesn't work well so we use rename/remove - # here to avoid reading the same ldif file more - # than once. -- rename ($ldif, "$ldif.done"); -+ if ($opt_l) { -+ rename ($ldif, "$ldif.done"); -+ } else { -+ # Remove the file - default behaviou when '-l' is not specified -+ unlink ($ldif) -+ } - } - &print_header ($replica, "Not Found") if !$gotldif; - } -diff --git a/man/man1/cl-dump.1 b/man/man1/cl-dump.1 -index db736aca9..fbb836a72 100644 ---- a/man/man1/cl-dump.1 -+++ b/man/man1/cl-dump.1 -@@ -20,7 +20,7 @@ cl-dump \- Dump and decode Directory Server replication change log - .SH SYNOPSIS - .B cl\-dump - [\fI\-h host\fR] [\fI\-p port\fR] [\fI\-D bind\(hydn\fR] \-w bind\(hypassword | \-P bind\(hycert -- [\fI\-r replica\(hyroots\fR] [\fI\-o output\(hyfile\fR] [\fI\-c\fR] [\fI\-v\fR] -+ [\fI\-r replica\(hyroots\fR] [\fI\-o output\(hyfile\fR] [\fI\-c\fR] [\fI\-l\fR] [\fI\-v\fR] - - .PP - .B cl\-dump -@@ -30,12 +30,12 @@ cl-dump \- Dump and decode Directory Server replication change log - Dump and decode Directory Server replication change log - .PP - .\" TeX users may be more comfortable with the \fB\fP and --.\" \fI\fP escape sequences to invode bold face and italics, -+.\" \fI\fP escape sequences to invode bold face and italics, - .\" respectively. - .SH OPTIONS - A summary of options is included below. - .TP --.B \-c -+.B \-c - Dump and interpret CSN only. This option can be used with or - without \-i option. - .TP -@@ -47,6 +47,9 @@ the option is omitted. - Directory server's host. Default to the server where the script - is running. - .TP -+.B \-l -+Preserve generated ldif.done files from changelogdir -+.TP - .B \-i changelog\(hyldif\(hyfile\(hywith\(hybase64encoding - If you already have a ldif-like changelog, but the changes - in that file are encoded, you may use this option to -@@ -66,7 +69,7 @@ Specify replica roots whose changelog you want to dump. The replica - roots may be separated by comma. All the replica roots would be - dumped if the option is omitted. - .TP --.B \-v -+.B \-v - Print the version of this script. - .TP - .B \-w bind\(hypassword --- -2.21.1 - diff --git a/SOURCES/0045-Issue-50655-access-log-etime-is-not-properly-formatt.patch b/SOURCES/0045-Issue-50655-access-log-etime-is-not-properly-formatt.patch deleted file mode 100644 index 975ce26..0000000 --- a/SOURCES/0045-Issue-50655-access-log-etime-is-not-properly-formatt.patch +++ /dev/null @@ -1,32 +0,0 @@ -From c8977a03f2c65978ad7977030d55bc830bc1f852 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Wed, 16 Oct 2019 16:52:59 -0400 -Subject: [PATCH] Issue 50655 - access log etime is not properly formatted - -Description: The wrong printf format was used for displaying the nanosecond etime - in the access log. - -relates: https://pagure.io/389-ds-base/issue/50655 - -Reviewed by: firstyear(Thanks!) ---- - ldap/servers/slapd/result.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c -index d9f431cc5..393b3f6cd 100644 ---- a/ldap/servers/slapd/result.c -+++ b/ldap/servers/slapd/result.c -@@ -1920,7 +1920,8 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries - struct timespec o_hr_time_end; - slapi_operation_time_elapsed(op, &o_hr_time_end); - -- snprintf(etime, ETIME_BUFSIZ, "%" PRId64 ".%010" PRId64 "", (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec); -+ -+ snprintf(etime, ETIME_BUFSIZ, "%" PRId64 ".%.09" PRId64 "", (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec); - - slapi_pblock_get(pb, SLAPI_OPERATION_NOTES, &operation_notes); - --- -2.21.1 - diff --git a/SOURCES/0046-Issue-50834-Incorrectly-setting-the-NSS-default-SSL-.patch b/SOURCES/0046-Issue-50834-Incorrectly-setting-the-NSS-default-SSL-.patch deleted file mode 100644 index 27b3324..0000000 --- a/SOURCES/0046-Issue-50834-Incorrectly-setting-the-NSS-default-SSL-.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 5c4e9f2017ba6c0415fe8352587db61dd9451ee4 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Mon, 20 Jan 2020 13:16:36 -0500 -Subject: [PATCH] Issue 50834 - Incorrectly setting the NSS default SSL version - max - -Description: We've been using the wrong function to get the NSS max - version We were calling SSL_VersionRangeGetSupported() - which gets the versions NSS "can" handle, but - SSL_VersionRangeGetDefault() gets the versions that - are actually "enabled". - -relates: https://pagure.io/389-ds-base/issue/50834 - -Reviewed by: mreynolds(one line commit rule) ---- - ldap/servers/slapd/ssl.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c -index ed054db44..c71e3019b 100644 ---- a/ldap/servers/slapd/ssl.c -+++ b/ldap/servers/slapd/ssl.c -@@ -1164,7 +1164,7 @@ slapd_nss_init(int init_ssl __attribute__((unused)), int config_available __attr - char *certdir; - char emin[VERSION_STR_LENGTH], emax[VERSION_STR_LENGTH]; - /* Get the range of the supported SSL version */ -- SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledNSSVersions); -+ SSL_VersionRangeGetDefault(ssl_variant_stream, &enabledNSSVersions); - - (void)slapi_getSSLVersion_str(enabledNSSVersions.min, emin, sizeof(emin)); - (void)slapi_getSSLVersion_str(enabledNSSVersions.max, emax, sizeof(emax)); --- -2.21.1 - diff --git a/SOURCES/0047-Ticket-50428-Log-the-actual-base-DN-when-the-search-.patch b/SOURCES/0047-Ticket-50428-Log-the-actual-base-DN-when-the-search-.patch deleted file mode 100644 index 90f1370..0000000 --- a/SOURCES/0047-Ticket-50428-Log-the-actual-base-DN-when-the-search-.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 572ed29e447141f532f2d84f9ea78c48308ad684 Mon Sep 17 00:00:00 2001 -From: Thierry Bordaz -Date: Fri, 7 Jun 2019 11:35:46 +0200 -Subject: [PATCH] Ticket 50428 - Log the actual base DN when the search fails - with "invalid attribute request" - -Bug Description: - When a search request contains invalid parameters (attribute list with empty attribute - name, unknown scope, invalid filter..) the search is rejected but the access log - contains a wrong base search: ... SRCH base="(null)"... - This is because it does not use for logging the variable that gather the actual base ('rawbase') - -Fix Description: - Use 'rawbase' value for logging - -https://pagure.io/389-ds-base/issue/50428 - -Reviewed by: Mark Reynolds - -Platforms tested: F28 - -Flag Day: no - -Doc impact: no ---- - ldap/servers/slapd/search.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c -index 7e253f535..2a9979552 100644 ---- a/ldap/servers/slapd/search.c -+++ b/ldap/servers/slapd/search.c -@@ -154,6 +154,7 @@ do_search(Slapi_PBlock *pb) - goto free_and_return; - } - } -+ base = rawbase; - - /* - * ignore negative time and size limits since they make no sense --- -2.21.1 - diff --git a/SOURCES/0048-Issue-50530-Directory-Server-not-RFC-4511-compliant-.patch b/SOURCES/0048-Issue-50530-Directory-Server-not-RFC-4511-compliant-.patch deleted file mode 100644 index 3836923..0000000 --- a/SOURCES/0048-Issue-50530-Directory-Server-not-RFC-4511-compliant-.patch +++ /dev/null @@ -1,146 +0,0 @@ -From c629c7ffe35bb2a09ad4dfa60d56fb01a51915d0 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Fri, 2 Aug 2019 14:36:24 -0400 -Subject: [PATCH] Issue 50530 - Directory Server not RFC 4511 compliant with - requested attr "1.1" - -Bug Description: A regression was introduced some time back that changed the - behavior of how the server handled the "1.1" requested attribute - in a search request. If "1.1" was requested along with other - attributes then no attibutes were returned, but in this case "1.1" - is expected to be ignroed. - -Fix Description: Only comply with "1.1" if it is the only requested attribute - -relates: https://pagure.io/389-ds-base/issue/50530 - -Reviewed by: firstyear(Thanks!) ---- - dirsrvtests/tests/suites/basic/basic_test.py | 57 +++++++++++++++++--- - ldap/servers/slapd/result.c | 7 ++- - 2 files changed, 57 insertions(+), 7 deletions(-) - -diff --git a/dirsrvtests/tests/suites/basic/basic_test.py b/dirsrvtests/tests/suites/basic/basic_test.py -index 0f7536b63..cea4f6bfe 100644 ---- a/dirsrvtests/tests/suites/basic/basic_test.py -+++ b/dirsrvtests/tests/suites/basic/basic_test.py -@@ -28,6 +28,7 @@ log = logging.getLogger(__name__) - USER1_DN = 'uid=user1,' + DEFAULT_SUFFIX - USER2_DN = 'uid=user2,' + DEFAULT_SUFFIX - USER3_DN = 'uid=user3,' + DEFAULT_SUFFIX -+USER4_DN = 'uid=user4,' + DEFAULT_SUFFIX - - ROOTDSE_DEF_ATTR_LIST = ('namingContexts', - 'supportedLDAPVersion', -@@ -409,8 +410,8 @@ def test_basic_acl(topology_st, import_example_ldif): - 'uid': 'user1', - 'userpassword': PASSWORD}))) - except ldap.LDAPError as e: -- log.fatal('test_basic_acl: Failed to add test user ' + USER1_DN -- + ': error ' + e.message['desc']) -+ log.fatal('test_basic_acl: Failed to add test user ' + USER1_DN + -+ ': error ' + e.message['desc']) - assert False - - try: -@@ -421,8 +422,8 @@ def test_basic_acl(topology_st, import_example_ldif): - 'uid': 'user2', - 'userpassword': PASSWORD}))) - except ldap.LDAPError as e: -- log.fatal('test_basic_acl: Failed to add test user ' + USER1_DN -- + ': error ' + e.message['desc']) -+ log.fatal('test_basic_acl: Failed to add test user ' + USER1_DN + -+ ': error ' + e.message['desc']) - assert False - - # -@@ -572,6 +573,50 @@ def test_basic_searches(topology_st, import_example_ldif): - log.info('test_basic_searches: PASSED') - - -+@pytest.fixture(scope="module") -+def add_test_entry(topology_st, request): -+ # Add test entry -+ topology_st.standalone.add_s(Entry((USER4_DN, -+ {'objectclass': "top extensibleObject".split(), -+ 'cn': 'user1', 'uid': 'user1'}))) -+ -+ -+search_params = [(['1.1'], 'cn', False), -+ (['1.1', 'cn'], 'cn', True), -+ (['+'], 'nsUniqueId', True), -+ (['*'], 'cn', True), -+ (['cn'], 'cn', True)] -+@pytest.mark.parametrize("attrs, attr, present", search_params) -+def test_search_req_attrs(topology_st, add_test_entry, attrs, attr, present): -+ """Test requested attributes in search operations. -+ :id: 426a59ff-49b8-4a70-b377-0c0634a29b6e -+ :setup: Standalone instance -+ :steps: -+ 1. Test "1.1" does not return any attributes. -+ 2. Test "1.1" is ignored if there are other requested attributes -+ 3. Test "+" returns all operational attributes -+ 4. Test "*" returns all attributes -+ 5. Test requested attributes -+ -+ :expectedresults: -+ 1. Success -+ 2. Success -+ 3. Success -+ 4. Success -+ 5. Success -+ """ -+ -+ log.info("Testing attrs: {} attr: {} present: {}".format(attrs, attr, present)) -+ entry = topology_st.standalone.search_s(USER4_DN, -+ ldap.SCOPE_BASE, -+ 'objectclass=top', -+ attrs) -+ if present: -+ assert entry[0].hasAttr(attr) -+ else: -+ assert not entry[0].hasAttr(attr) -+ -+ - def test_basic_referrals(topology_st, import_example_ldif): - """Test LDAP server in referral mode. - -@@ -716,8 +761,8 @@ def test_basic_systemctl(topology_st, import_example_ldif): - log.info('Attempting to start the server with broken dse.ldif...') - try: - topology_st.standalone.start() -- except: -- log.info('Server failed to start as expected') -+ except Exception as e: -+ log.info('Server failed to start as expected: ' + str(e)) - log.info('Check the status...') - assert (not topology_st.standalone.status()) - log.info('Server failed to start as expected') -diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c -index 393b3f6cd..61e7a70f9 100644 ---- a/ldap/servers/slapd/result.c -+++ b/ldap/servers/slapd/result.c -@@ -1546,6 +1546,8 @@ send_ldap_search_entry_ext( - * "+" means all operational attributes (rfc3673) - * operational attributes are only retrieved if they are named - * specifically or when "+" is specified. -+ * In the case of "1.1", if there are other requested attributes -+ * then "1.1" should be ignored. - */ - - /* figure out if we want all user attributes or no attributes at all */ -@@ -1560,7 +1562,10 @@ send_ldap_search_entry_ext( - if (strcmp(LDAP_ALL_USER_ATTRS, attrs[i]) == 0) { - alluserattrs = 1; - } else if (strcmp(LDAP_NO_ATTRS, attrs[i]) == 0) { -- noattrs = 1; -+ /* "1.1" is only valid if it's the only requested attribute */ -+ if (i == 0 && attrs[1] == NULL) { -+ noattrs = 1; -+ } - } else if (strcmp(LDAP_ALL_OPERATIONAL_ATTRS, attrs[i]) == 0) { - alloperationalattrs = 1; - } else { --- -2.21.1 - diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec index ac72c06..f131749 100644 --- a/SPECS/389-ds-base.spec +++ b/SPECS/389-ds-base.spec @@ -38,8 +38,8 @@ Summary: 389 Directory Server (%{variant}) Name: 389-ds-base -Version: 1.3.9.1 -Release: %{?relprefix}13%{?prerel}%{?dist} +Version: 1.3.10.1 +Release: %{?relprefix}5%{?prerel}%{?dist} License: GPLv3+ URL: https://www.port389.org/ Group: System Environment/Daemons @@ -145,55 +145,22 @@ Requires: gperftools-libs Source0: https://releases.pagure.org/389-ds-base/%{name}-%{version}%{?prerel}.tar.bz2 Source1: %{name}-git.sh Source2: %{name}-devel.README -Patch00: 0000-Ticket-50236-memberOf-should-be-more-robust.patch -Patch01: 0001-Ticket-50238-Failed-modrdn-can-corrupt-entry-cache.patch -Patch02: 0002-Ticket-50232-export-creates-not-importable-ldif-file.patch -Patch03: 0003-Ticket-50234-one-level-search-returns-not-matching-e.patch -Patch04: 0004-Issue-50091-shadowWarning-is-not-generated-if-passwo.patch -Patch05: 0005-Ticket-50091-shadowWarning-is-not-generated-if-passw.patch -Patch06: 0006-Ticket-50260-backend-txn-plugins-can-corrupt-entry-c.patch -Patch07: 0007-Ticket-50077-Do-not-automatically-turn-automember-po.patch -Patch08: 0008-Ticket-50282-OPERATIONS-ERROR-when-trying-to-delete-.patch -Patch09: 0009-Ticket-49561-MEP-plugin-upon-direct-op-failure-will-.patch -Patch10: 0010-Ticket-50260-Invalid-cache-flushing-improvements.patch -Patch11: 0011-Ticket-50265-the-warning-about-skew-time-could-last-.patch -Patch12: 0012-Ticket-50063-Crash-after-attempting-to-restore-a-sin.patch -Patch13: 0013-Ticket-49946-upgrade-of-389-ds-base-could-remove-rep.patch -Patch14: 0014-Ticket-49873-Contention-on-virtual-attribute-lookup.patch -Patch15: 0015-Ticket-49958-extended-search-fail-to-match-entries.patch -Patch16: 0016-Ticket-50028-ds-replcheck-y-option-throws-usage-erro.patch -#Patch17: 0017-Ticket-50329-Possible-Security-Issue-DOS-due-to-iobl.patch -Patch18: 0018-Ticket-49990-Increase-the-default-FD-limits.patch -Patch19: 0019-Ticket-50053-Subtree-password-policy-overrides-a-use.patch -Patch20: 0020-Ticket-49866-Add-passwordSendExpiringTime-to-objectc.patch -Patch21: 0021-Ticket-50013-Log-warn-instead-of-ERR-when-aci-target.patch -Patch22: 0022-Ticket-49997-RFE-ds-replcheck-could-validate-suffix-.patch -Patch23: 0023-Ticket-50363-ds-replcheck-incorrectly-reports-error-.patch -Patch24: 0024-Ticket-50370-CleanAllRUV-task-crashing-during-server.patch -Patch25: 0025-Ticket-50378-ACI-s-with-IPv4-and-IPv6-bind-rules-do-.patch -Patch26: 0026-Ticket-50396-Crash-in-PAM-plugin-when-user-does-not-.patch -Patch27: 0027-Ticket-50393-maxlogsperdir-accepting-negative-values.patch -Patch28: 0028-Issue-49754-Instance-created-using-dscreate-can-t-be.patch -Patch29: 0029-Ticket-50413-ds-replcheck-Always-display-the-Result-.patch -Patch30: 0030-Ticket-50389-ns-slapd-craches-while-two-threads-are-.patch -Patch31: 0031-Issue-50123-with_tmpfiles_d-is-associated-with-syste.patch -Patch32: 0032-Issue-50426-nsSSL3Ciphers-is-limited-to-1024-charact.patch -Patch33: 0033-Ticket-50329-2nd-Possible-Security-Issue-DOS-due-to-.patch -Patch34: 0034-CVE-deref-plugin-displays-restricted-attributes.patch -Patch35: 0035-Issue-49624-modrdn-silently-fails-if-DB-deadlock-occ.patch -Patch36: 0036-Issue-50536-Audit-log-heading-written-to-log-after-e.patch -Patch37: 0037-Issue-50636-Crash-during-sasl-bind.patch -Patch38: 0038-Issue-49850-ldbm_get_nonleaf_ids-slow-for-databases-.patch -Patch39: 0039-Ticket-49850-cont-fix-crash-in-ldbm_non_leaf.patch -Patch40: 0040-Issue-50538-cleanAllRUV-task-limit-is-not-enforced-f.patch -Patch41: 0041-Fix-cherry-pick-error-for-cleanAllRUV-issue.patch -Patch42: 0042-Ticket-50736-RetroCL-trimming-may-crash-at-shutdown-.patch -Patch43: 0043-Issue-50529-LDAP-server-returning-PWP-controls-in-di.patch -Patch44: 0044-Issue-50572-After-running-cl-dump-dbdir-cldb-ldif.do.patch -Patch45: 0045-Issue-50655-access-log-etime-is-not-properly-formatt.patch -Patch46: 0046-Issue-50834-Incorrectly-setting-the-NSS-default-SSL-.patch -Patch47: 0047-Ticket-50428-Log-the-actual-base-DN-when-the-search-.patch -Patch48: 0048-Issue-50530-Directory-Server-not-RFC-4511-compliant-.patch +Patch00: 0000-CVE-2019-14824-BZ-1748199-deref-plugin-displays-rest.patch +Patch01: 0001-Issue-50525-nsslapd-defaultnamingcontext-does-not-ch.patch +Patch02: 0002-Issue-50530-Directory-Server-not-RFC-4511-compliant-.patch +Patch03: 0003-Issue-50529-LDAP-server-returning-PWP-controls-in-di.patch +Patch04: 0004-Issue-50538-cleanAllRUV-task-limit-is-not-enforced-f.patch +Patch05: 0005-Issue-49624-modrdn-silently-fails-if-DB-deadlock-occ.patch +Patch06: 0006-Issue-50572-After-running-cl-dump-dbdir-cldb-ldif.do.patch +Patch07: 0007-Issue-50538-Fix-cherry-pick-error.patch +Patch08: 0008-Issue-50646-Improve-task-handling-during-shutdowns.patch +Patch09: 0009-Issue-50653-objectclass-parsing-fails-to-log-error-m.patch +Patch10: 0010-Issue-50655-access-log-etime-is-not-properly-formatt.patch +Patch11: 0011-Issue-49850-ldbm_get_nonleaf_ids-slow-for-databases-.patch +Patch12: 0012-Issue-50536-Audit-log-heading-written-to-log-after-e.patch +Patch13: 0013-Issue-50636-Crash-during-sasl-bind.patch +Patch14: 0014-Ticket-49850-cont-fix-crash-in-ldbm_non_leaf.patch +Patch15: 0015-Ticket-49624-cont-DB-Deadlock-on-modrdn-appears-to-c.patch %description 389 Directory Server is an LDAPv3 compliant server. The base package includes @@ -546,28 +513,39 @@ fi %{_sysconfdir}/%{pkgname}/dirsrvtests %changelog -* Wed Feb 12 2020 Mark Reynolds - 1.3.9.1-13 -- Bump version to 1.3.9.1-13 -- Resolves: Bug 1801693 - ns-slapd is crashing while restarting ipactl -- Resolves: Bug 1801695 - LDAP server returning controltype in different sequence -- Resolves: Bug 1801700 - After running cl-dump dbdir/cldb/*ldif.done are not deleted -- Resolves: Bug 1801701 - etime displayed has an order of magnitude 10 times smaller than it should be -- Resolves: Bug 1801702 - Regression: NSS has interop problems as server when using limited cipher list -- Resolves: Bug 1801704 - Log the actual base DN when the search fails with "invalid attribute request" -- Resolves: Bug 1801705 - Directory Server 10 not RFC 4511 compliant -- Resolves: Bug 1801706 - Replace error by warning in the state machine defined in repl5_inc_run - -* Fri Nov 1 2019 Mark Reynolds - 1.3.9.1-12 -- Bump version to 1.3.9.1-12 -- Resolves: Bug 1767622 - CleanAllRUV task limit not enforced - -* Mon Oct 28 2019 Mark Reynolds - 1.3.9.1-11 -- Bump version to 1.3.9.1-11 -- Resolves: Bug 1748198 - EMBARGOED CVE-2019-14824 389-ds-base: Read permission check bypass via the deref plugin -- Resolves: Bug 1754831 - After audit log file is rotated, DS version string is logged after each update -- Resolves: Bug 1763622 - Extremely slow LDIF import with ldif2db -- Resolves: Bug 1763627 - ns-slapd crash on concurrent SASL BINDs, connection_call_io_layer_callbacks must hold hold c_mutex -- Resolves: Bug 1749289 - DB Deadlock on modrdn appears to corrupt database and entry cache +* Fri Feb 7 2020 Mark Reynolds - 1.3.10.1-5 +- Bump version to 1.3.10.1-5 +- Resolves: Bug 1744623 - DB Deadlock on modrdn appears to corrupt database and entry cache(cont) + +* Fri Oct 25 2019 Mark Reynolds - 1.3.10.1-4 +- Bump version to 1.3.10.1-4 +- Resolves: Bug 1765106 - ipa-server-install is failing with ipapython.admintool: ERROR failed to create DS instance Command + +* Thu Oct 17 2019 Mark Reynolds - 1.3.10.1-3 +- Bump version to 1.3.10.1-3 +- Resolves: Bug 1756182 - ns-slapd crash on concurrent SASL BINDs, connection_call_io_layer_callbacks must hold hold c_mutex +- Resolves: Bug 1749236 - etime displayed has an order of magnitude 10 times smaller than it should be +- Resolves: Bug 1758109 - AddressSanitizer: heap-use-after-free in import_free_job +- Resolves: Bug 1676948 - After audit log file is rotated, DS version string is logged after each update +- Resolves: Bug 1749595 - Extremely slow LDIF import with ldif2db + +* Tue Sep 3 2019 Mark Reynolds - 1.3.10.1-2 +- Bump version to 1.3.10.1-2 +- Resolves: Bug 1748199 - EMBARGOED CVE-2019-14824 389-ds-base: 389-ds and IDM: allows authenticated unprivileged user to retrieve content of userPassword field for any user +- Resolves: Bug 1610234 - nsslapd-defaultnamingcontext does not change when the assigned suffix got deleted +- Resolves: Bug 1723545 - Directory Server 10 not RFC 4511 compliant +- Resolves: Bug 1724914 - LDAP server returning controltype in different sequence +- Resolves: Bug 1739182 - CleanAllRUV task limit not enforced +- Resolves: Bug 1744623 - DB Deadlock on modrdn appears to corrupt database and entry cache +- Resolves: Bug 1685059 - After running cl-dump dbdir/cldb/*ldif.done are not deleted + +* Wed Jul 31 2019 Mark Reynolds - 1.3.10.1-1 +- Bump version to 1.3.10.1-1 +- Resolves: Bug 1639342 - Replace error by warning in the state machine defined in repl5_inc_run +- Resolves: Bug 1691931 - memory leak in automember plugin +- Resolves: Bug 1662461 - Log the actual base DN when the search fails with "invalid attribute request" +- Resolves: Bug 1732053 - etime can contain invalid nanosecond value +- Resolves: Bug 1546739 - consistency in the replication error codes while setting nsds5replicaid=65535 * Thu Jun 13 2019 Mark Reynolds - 1.3.9.1-10 - Bump version to 1.3.9.1-10