From 99fa9f4cac34668dda164b30fccf12c9c88c256c Mon Sep 17 00:00:00 2001 From: MSVSphere Packaging Team Date: Thu, 23 May 2024 12:01:09 +0300 Subject: [PATCH] import 389-ds-base-1.4.3.39-3.module+el8.10.0+21535+f663b039 --- .389-ds-base.metadata | 4 +- .gitignore | 4 +- ...rt-HAProxy-and-Instance-on-the-same-.patch | 83 ++ ...apd-crashes-at-startup-if-a-backend-.patch | 84 -- ...-when-paged-result-search-are-abando.patch | 389 -------- ...an-memory-leak-in-audit-log-when-add.patch | 119 +++ ...nused-variable-warning-from-previous.patch | 27 + ...-when-paged-result-search-are-abando.patch | 89 -- ...repl-crashes-if-enabled-while-dynami.patch | 147 +++ ...-5547-automember-plugin-improvements.patch | 840 ++++++++++++++++++ ...-1.4.3.37-1.lock => Cargo-1.4.3.39-1.lock} | 262 +++--- SPECS/389-ds-base.spec | 154 ++-- 12 files changed, 1421 insertions(+), 781 deletions(-) create mode 100644 SOURCES/0001-Issue-3527-Support-HAProxy-and-Instance-on-the-same-.patch delete mode 100644 SOURCES/0001-Issue-5870-ns-slapd-crashes-at-startup-if-a-backend-.patch delete mode 100644 SOURCES/0001-Issue-5984-Crash-when-paged-result-search-are-abando.patch create mode 100644 SOURCES/0001-issue-5647-covscan-memory-leak-in-audit-log-when-add.patch create mode 100644 SOURCES/0002-Issue-5647-Fix-unused-variable-warning-from-previous.patch delete mode 100644 SOURCES/0002-Issue-5984-Crash-when-paged-result-search-are-abando.patch create mode 100644 SOURCES/0003-Issue-5407-sync_repl-crashes-if-enabled-while-dynami.patch create mode 100644 SOURCES/0004-Issue-5547-automember-plugin-improvements.patch rename SOURCES/{Cargo-1.4.3.37-1.lock => Cargo-1.4.3.39-1.lock} (75%) diff --git a/.389-ds-base.metadata b/.389-ds-base.metadata index b1cede3..dff35e2 100644 --- a/.389-ds-base.metadata +++ b/.389-ds-base.metadata @@ -1,3 +1,3 @@ -99591fa118addaa5e8eef3445092d0b2d12758ba SOURCES/389-ds-base-1.4.3.37.tar.bz2 +bd9aab32d9cbf9231058d585479813f3420dc872 SOURCES/389-ds-base-1.4.3.39.tar.bz2 1c8f2d0dfbf39fa8cd86363bf3314351ab21f8d4 SOURCES/jemalloc-5.3.0.tar.bz2 -deb3cdc888660e573fe4be992398f35393c2d1d3 SOURCES/vendor-1.4.3.37-1.tar.gz +978b7c5e4a9e5784fddb23ba1abe4dc5a071589f SOURCES/vendor-1.4.3.39-1.tar.gz diff --git a/.gitignore b/.gitignore index 2a6d10d..89f8081 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -SOURCES/389-ds-base-1.4.3.37.tar.bz2 +SOURCES/389-ds-base-1.4.3.39.tar.bz2 SOURCES/jemalloc-5.3.0.tar.bz2 -SOURCES/vendor-1.4.3.37-1.tar.gz +SOURCES/vendor-1.4.3.39-1.tar.gz diff --git a/SOURCES/0001-Issue-3527-Support-HAProxy-and-Instance-on-the-same-.patch b/SOURCES/0001-Issue-3527-Support-HAProxy-and-Instance-on-the-same-.patch new file mode 100644 index 0000000..40dba66 --- /dev/null +++ b/SOURCES/0001-Issue-3527-Support-HAProxy-and-Instance-on-the-same-.patch @@ -0,0 +1,83 @@ +From 7d1bc439a07c51b5f4f37405b6b27a1990b8cb28 Mon Sep 17 00:00:00 2001 +From: Simon Pichugin +Date: Tue, 27 Feb 2024 16:30:47 -0800 +Subject: [PATCH] Issue 3527 - Support HAProxy and Instance on the same machine + configuration (#6107) + +Description: Improve how we handle HAProxy connections to work better when +the DS and HAProxy are on the same machine. +Ensure the client and header destination IPs are checked against the trusted IP list. + +Additionally, this change will also allow configuration having +HAProxy is listening on a different subnet than the one used to forward the request. + +Related: https://github.com/389ds/389-ds-base/issues/3527 + +Reviewed by: @progier389, @jchapma (Thanks!) +--- + ldap/servers/slapd/connection.c | 35 +++++++++++++++++++++++++-------- + 1 file changed, 27 insertions(+), 8 deletions(-) + +diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c +index d28a39bf7..10a8cc577 100644 +--- a/ldap/servers/slapd/connection.c ++++ b/ldap/servers/slapd/connection.c +@@ -1187,6 +1187,8 @@ connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, int * + char str_ip[INET6_ADDRSTRLEN + 1] = {0}; + char str_haproxy_ip[INET6_ADDRSTRLEN + 1] = {0}; + char str_haproxy_destip[INET6_ADDRSTRLEN + 1] = {0}; ++ int trusted_matches_ip_found = 0; ++ int trusted_matches_destip_found = 0; + struct berval **bvals = NULL; + int proxy_connection = 0; + +@@ -1245,21 +1247,38 @@ connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, int * + normalize_IPv4(conn->cin_addr, buf_ip, sizeof(buf_ip), str_ip, sizeof(str_ip)); + normalize_IPv4(&pr_netaddr_dest, buf_haproxy_destip, sizeof(buf_haproxy_destip), + str_haproxy_destip, sizeof(str_haproxy_destip)); ++ size_t ip_len = strlen(buf_ip); ++ size_t destip_len = strlen(buf_haproxy_destip); + + /* Now, reset RC and set it to 0 only if a match is found */ + haproxy_rc = -1; + +- /* Allow only: +- * Trusted IP == Original Client IP == HAProxy Header Destination IP */ ++ /* ++ * We need to allow a configuration where DS instance and HAProxy are on the same machine. ++ * In this case, we need to check if ++ * the HAProxy client IP (which will be a loopback address) matches one of the the trusted IP addresses, ++ * while still checking that ++ * the HAProxy header destination IP address matches one of the trusted IP addresses. ++ * Additionally, this change will also allow configuration having ++ * HAProxy listening on a different subnet than one used to forward the request. ++ */ + for (size_t i = 0; bvals[i] != NULL; ++i) { +- if ((strlen(bvals[i]->bv_val) == strlen(buf_ip)) && +- (strlen(bvals[i]->bv_val) == strlen(buf_haproxy_destip)) && +- (strncasecmp(bvals[i]->bv_val, buf_ip, strlen(buf_ip)) == 0) && +- (strncasecmp(bvals[i]->bv_val, buf_haproxy_destip, strlen(buf_haproxy_destip)) == 0)) { +- haproxy_rc = 0; +- break; ++ size_t bval_len = strlen(bvals[i]->bv_val); ++ ++ /* Check if the Client IP (HAProxy's machine IP) address matches the trusted IP address */ ++ if (!trusted_matches_ip_found) { ++ trusted_matches_ip_found = (bval_len == ip_len) && (strncasecmp(bvals[i]->bv_val, buf_ip, ip_len) == 0); ++ } ++ /* Check if the HAProxy header destination IP address matches the trusted IP address */ ++ if (!trusted_matches_destip_found) { ++ trusted_matches_destip_found = (bval_len == destip_len) && (strncasecmp(bvals[i]->bv_val, buf_haproxy_destip, destip_len) == 0); + } + } ++ ++ if (trusted_matches_ip_found && trusted_matches_destip_found) { ++ haproxy_rc = 0; ++ } ++ + if (haproxy_rc == -1) { + slapi_log_err(SLAPI_LOG_CONNS, "connection_read_operation", "HAProxy header received from unknown source.\n"); + disconnect_server_nomutex(conn, conn->c_connid, -1, SLAPD_DISCONNECT_PROXY_UNKNOWN, EPROTO); +-- +2.43.0 + diff --git a/SOURCES/0001-Issue-5870-ns-slapd-crashes-at-startup-if-a-backend-.patch b/SOURCES/0001-Issue-5870-ns-slapd-crashes-at-startup-if-a-backend-.patch deleted file mode 100644 index bef5e99..0000000 --- a/SOURCES/0001-Issue-5870-ns-slapd-crashes-at-startup-if-a-backend-.patch +++ /dev/null @@ -1,84 +0,0 @@ -From c98a1f0d4ad35778204440a8a5fc497d476621a9 Mon Sep 17 00:00:00 2001 -From: tbordaz -Date: Wed, 2 Aug 2023 14:44:42 +0200 -Subject: [PATCH] Issue 5870 - ns-slapd crashes at startup if a backend has no - suffix (#5871) - -Bug description: - With $5598, the server checks at startup if it exists - some referrals entries in the various backends/suffixes. - If a backend has no defined suffix (not clear how it - occurs except crafting dse.ldif) the checking - triggers a sigsev - -Fix description: - Check it exists a suffix before using it ---- - .../tests/suites/ds_logs/ds_logs_test.py | 29 +++++++++++++++++++ - ldap/servers/slapd/backend.c | 3 +- - 2 files changed, 31 insertions(+), 1 deletion(-) - -diff --git a/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py b/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py -index 1a51ca548..812936c62 100644 ---- a/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py -+++ b/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py -@@ -11,6 +11,8 @@ import os - import time - import logging - import pytest -+import shutil -+from lib389.rootdse import RootDSE - import subprocess - from lib389.referral import Referrals, Referral - from lib389.backend import Backend -@@ -1398,6 +1400,33 @@ def test_referral_subsuffix(topology_st, request): - - request.addfinalizer(fin) - -+def test_missing_backend_suffix(topology_st, request): -+ """Test that the server does not crash if a backend has no suffix -+ -+ :id: 427c9780-4875-4a94-a3e4-afa11be7d1a9 -+ :setup: Standalone instance -+ :steps: -+ 1. Stop the instance -+ 2. remove 'nsslapd-suffix' from the backend (userRoot) -+ 3. start the instance -+ 4. Check it started successfully with SRCH on rootDSE -+ :expectedresults: -+ all steps succeeds -+ """ -+ topology_st.standalone.stop() -+ dse_ldif = topology_st.standalone.confdir + '/dse.ldif' -+ shutil.copy(dse_ldif, dse_ldif + '.correct') -+ os.system('sed -e "/nsslapd-suffix/d" %s > %s' % (dse_ldif + '.correct', dse_ldif)) -+ topology_st.standalone.start() -+ rdse = RootDSE(topology_st.standalone) -+ -+ def fin(): -+ log.info('Restore dse.ldif') -+ topology_st.standalone.stop() -+ shutil.copy(dse_ldif + '.correct', dse_ldif) -+ -+ request.addfinalizer(fin) -+ - if __name__ == '__main__': - # Run isolated - # -s for DEBUG mode -diff --git a/ldap/servers/slapd/backend.c b/ldap/servers/slapd/backend.c -index ea8ccb88d..498f683b1 100644 ---- a/ldap/servers/slapd/backend.c -+++ b/ldap/servers/slapd/backend.c -@@ -222,7 +222,8 @@ slapi_exist_referral(Slapi_Backend *be) - suffix = slapi_sdn_get_dn(slapi_be_getsuffix(be, 0)); - - /* ignore special backends */ -- if ((strcmp(suffix, "cn=schema") == 0) || -+ if ((suffix == NULL) || -+ (strcmp(suffix, "cn=schema") == 0) || - (strcmp(suffix, "cn=config") == 0)) { - return 0; /* it does not mean anything having a referral in those backends */ - } --- -2.41.0 - diff --git a/SOURCES/0001-Issue-5984-Crash-when-paged-result-search-are-abando.patch b/SOURCES/0001-Issue-5984-Crash-when-paged-result-search-are-abando.patch deleted file mode 100644 index f5737eb..0000000 --- a/SOURCES/0001-Issue-5984-Crash-when-paged-result-search-are-abando.patch +++ /dev/null @@ -1,389 +0,0 @@ -From 1fefae50842b6bcdd631b59d91688388e90e0a5c Mon Sep 17 00:00:00 2001 -From: progier389 -Date: Fri, 17 Nov 2023 14:41:51 +0100 -Subject: [PATCH 1/2] Issue 5984 - Crash when paged result search are abandoned - (#5985) - -* Issue 5984 - Crash when paged result search are abandoned - -Problem: - Fix #4551 has changed the lock that protects the paged result data - within a connection. But the abandon operation attempts to free - the paged search result with the connection lock. - This leads to race condition and double free causing an heap - corruption and a SIGSEGV. - - Solution: - - Get a copy of the operation data that needs to be logged. - - Unlock the connection mutex (to avoid deadlock risk) - - Free the paged result while holding the paged result lock. - -Issue: 5984 - -Reviewed by: @tbordaz (Thanks!) - -(cherry picked from commit 06bd0862956672eb76276cab5c1dd906fe5a7eec) ---- - .../paged_results/paged_results_test.py | 110 ++++++++++++++++-- - ldap/servers/slapd/abandon.c | 23 ++-- - ldap/servers/slapd/opshared.c | 4 +- - ldap/servers/slapd/pagedresults.c | 8 +- - ldap/servers/slapd/proto-slap.h | 2 +- - src/lib389/lib389/__init__.py | 27 ++++- - 6 files changed, 152 insertions(+), 22 deletions(-) - -diff --git a/dirsrvtests/tests/suites/paged_results/paged_results_test.py b/dirsrvtests/tests/suites/paged_results/paged_results_test.py -index 893d28a07..2fc418d3f 100644 ---- a/dirsrvtests/tests/suites/paged_results/paged_results_test.py -+++ b/dirsrvtests/tests/suites/paged_results/paged_results_test.py -@@ -7,7 +7,7 @@ - # --- END COPYRIGHT BLOCK --- - # - import socket --from random import sample -+from random import sample, randrange - - import pytest - from ldap.controls import SimplePagedResultsControl, GetEffectiveRightsControl -@@ -17,8 +21,10 @@ from lib389.topologies import topology_st - from lib389._constants import DN_LDBM, DN_DM, DEFAULT_SUFFIX, BACKEND_NAME, PASSWORD - - from lib389._controls import SSSRequestControl -- --from lib389.idm.user import UserAccounts -+from lib389.idm.user import UserAccount, UserAccounts -+from lib389.cli_base import FakeArgs -+from lib389.config import LDBMConfig -+from lib389.dbgen import dbgen_users - from lib389.idm.organization import Organization - from lib389.idm.organizationalunit import OrganizationalUnit - from lib389.backend import Backends -@@ -46,11 +52,56 @@ NEW_BACKEND_1 = 'parent_base' - NEW_BACKEND_2 = 'child_base' - - OLD_HOSTNAME = socket.gethostname() --socket.sethostname('localhost') -+if os.getuid() == 0: -+ socket.sethostname('localhost') - HOSTNAME = socket.gethostname() - IP_ADDRESS = socket.gethostbyname(HOSTNAME) - OLD_IP_ADDRESS = socket.gethostbyname(OLD_HOSTNAME) - -+ -+@pytest.fixture(scope="module") -+def create_40k_users(topology_st, request): -+ inst = topology_st.standalone -+ -+ # Prepare return value -+ retval = FakeArgs() -+ retval.inst = inst -+ retval.bename = '40k' -+ retval.suffix = f'o={retval.bename}' -+ retval.ldif_file = f'{inst.get_ldif_dir()}/{retval.bename}.ldif' -+ -+ # Create new backend -+ bes = Backends(inst) -+ be_1 = bes.create(properties={ -+ 'cn': retval.bename, -+ 'nsslapd-suffix': retval.suffix, -+ }) -+ -+ # Set paged search lookthrough limit -+ ldbmconfig = LDBMConfig(inst) -+ ldbmconfig.replace('nsslapd-pagedlookthroughlimit', b'100000') -+ -+ # Create ldif and import it. -+ dbgen_users(inst, 40000, retval.ldif_file, retval.suffix) -+ # tasks = Tasks(inst) -+ # args = {TASK_WAIT: True} -+ # tasks.importLDIF(retval.suffix, None, retval.ldif_file, args) -+ inst.stop() -+ assert inst.ldif2db(retval.bename, None, None, None, retval.ldif_file, None) -+ inst.start() -+ -+ # And set an aci allowing anonymous read -+ log.info('Adding ACI to allow our test user to search') -+ ACI_TARGET = '(targetattr != "userPassword || aci")' -+ ACI_ALLOW = '(version 3.0; acl "Enable anonymous access";allow (read, search, compare)' -+ ACI_SUBJECT = '(userdn = "ldap:///anyone");)' -+ ACI_BODY = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT -+ o_1 = Organization(inst, retval.suffix) -+ o_1.set('aci', ACI_BODY) -+ -+ return retval -+ -+ - @pytest.fixture(scope="module") - def create_user(topology_st, request): - """User for binding operation""" -@@ -75,8 +126,10 @@ def create_user(topology_st, request): - - def fin(): - log.info('Deleting user simplepaged_test') -- user.delete() -- socket.sethostname(OLD_HOSTNAME) -+ if not DEBUGGING: -+ user.delete() -+ if os.getuid() == 0: -+ socket.sethostname(OLD_HOSTNAME) - - request.addfinalizer(fin) - -@@ -179,7 +232,7 @@ def change_conf_attr(topology_st, suffix, attr_name, attr_value): - return attr_value_bck - - --def paged_search(conn, suffix, controls, search_flt, searchreq_attrlist): -+def paged_search(conn, suffix, controls, search_flt, searchreq_attrlist, abandon_rate=0): - """Search at the DEFAULT_SUFFIX with ldap.SCOPE_SUBTREE - using Simple Paged Control(should the first item in the - list controls. -@@ -199,9 +252,16 @@ def paged_search(conn, suffix, controls, search_flt, searchreq_attrlist): - req_pr_ctrl.size, - str(controls))) - msgid = conn.search_ext(suffix, ldap.SCOPE_SUBTREE, search_flt, searchreq_attrlist, serverctrls=controls) -+ log.info('Getting page %d' % (pages,)) - while True: -- log.info('Getting page %d' % (pages,)) -- rtype, rdata, rmsgid, rctrls = conn.result3(msgid) -+ try: -+ rtype, rdata, rmsgid, rctrls = conn.result3(msgid, timeout=0.001) -+ except ldap.TIMEOUT: -+ if pages > 0 and abandon_rate>0 and randrange(100)c_mutex)); - for (o = pb_conn->c_ops; o != NULL; o = o->o_next) { -- if (o->o_msgid == id && o != pb_op) -+ if (o->o_msgid == id && o != pb_op) { -+ slapi_operation_time_elapsed(o, &o_copy.hr_time_end); -+ o_copy.nentries = o->o_results.r.r_search.nentries; -+ o_copy.opid = o->o_opid; - break; -+ } - } - - if (o != NULL) { -@@ -130,7 +140,8 @@ do_abandon(Slapi_PBlock *pb) - slapi_log_err(SLAPI_LOG_TRACE, "do_abandon", "op not found\n"); - } - -- if (0 == pagedresults_free_one_msgid_nolock(pb_conn, id)) { -+ pthread_mutex_unlock(&(pb_conn->c_mutex)); -+ if (0 == pagedresults_free_one_msgid(pb_conn, id, pageresult_lock_get_addr(pb_conn))) { - slapi_log_access(LDAP_DEBUG_STATS, "conn=%" PRIu64 - " op=%d ABANDON targetop=Simple Paged Results msgid=%d\n", - pb_conn->c_connid, pb_op->o_opid, id); -@@ -143,15 +154,11 @@ do_abandon(Slapi_PBlock *pb) - " targetop=SUPPRESSED-BY-PLUGIN msgid=%d\n", - pb_conn->c_connid, pb_op->o_opid, id); - } else { -- struct timespec o_hr_time_end; -- slapi_operation_time_elapsed(o, &o_hr_time_end); - slapi_log_access(LDAP_DEBUG_STATS, "conn=%" PRIu64 " op=%d ABANDON" - " targetop=%d msgid=%d nentries=%d etime=%" PRId64 ".%010" PRId64 "\n", -- pb_conn->c_connid, pb_op->o_opid, o->o_opid, id, -- o->o_results.r.r_search.nentries, (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec); -+ pb_conn->c_connid, pb_op->o_opid, o_copy.opid, id, -+ o_copy.nentries, (int64_t)o_copy.hr_time_end.tv_sec, (int64_t)o_copy.hr_time_end.tv_nsec); - } -- -- pthread_mutex_unlock(&(pb_conn->c_mutex)); - /* - * Wake up the persistent searches, so they - * can notice if they've been abandoned. -diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c -index 897b9566e..7ab4117cd 100644 ---- a/ldap/servers/slapd/opshared.c -+++ b/ldap/servers/slapd/opshared.c -@@ -922,9 +922,7 @@ op_shared_search(Slapi_PBlock *pb, int send_result) - next_be = NULL; /* to break the loop */ - if (operation->o_status & SLAPI_OP_STATUS_ABANDONED) { - /* It turned out this search was abandoned. */ -- pthread_mutex_lock(pagedresults_mutex); -- pagedresults_free_one_msgid_nolock(pb_conn, operation->o_msgid); -- pthread_mutex_unlock(pagedresults_mutex); -+ pagedresults_free_one_msgid(pb_conn, operation->o_msgid, pagedresults_mutex); - /* paged-results-request was abandoned; making an empty cookie. */ - pagedresults_set_response_control(pb, 0, estimate, -1, pr_idx); - send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL); -diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c -index 01fe3370f..db87e486e 100644 ---- a/ldap/servers/slapd/pagedresults.c -+++ b/ldap/servers/slapd/pagedresults.c -@@ -34,6 +34,10 @@ pageresult_lock_cleanup() - slapi_ch_free((void**)&lock_hash); - } - -+/* Beware to the lock order with c_mutex: -+ * c_mutex is sometime locked while holding pageresult_lock -+ * ==> Do not lock pageresult_lock when holing c_mutex -+ */ - pthread_mutex_t * - pageresult_lock_get_addr(Connection *conn) - { -@@ -350,7 +354,7 @@ pagedresults_free_one(Connection *conn, Operation *op, int index) - * Used for abandoning - pageresult_lock_get_addr(conn) is already locked in do_abandone. - */ - int --pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid) -+pagedresults_free_one_msgid(Connection *conn, ber_int_t msgid, pthread_mutex_t *mutex) - { - int rc = -1; - int i; -@@ -361,6 +365,7 @@ pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid) - } else { - slapi_log_err(SLAPI_LOG_TRACE, - "pagedresults_free_one_msgid_nolock", "=> msgid=%d\n", msgid); -+ pthread_mutex_lock(mutex); - for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) { - if (conn->c_pagedresults.prl_list[i].pr_msgid == msgid) { - PagedResults *prp = conn->c_pagedresults.prl_list + i; -@@ -375,6 +380,7 @@ pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid) - break; - } - } -+ pthread_mutex_unlock(mutex); - slapi_log_err(SLAPI_LOG_TRACE, - "pagedresults_free_one_msgid_nolock", "<= %d\n", rc); - } -diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h -index bb1f8aea2..76b2e3af2 100644 ---- a/ldap/servers/slapd/proto-slap.h -+++ b/ldap/servers/slapd/proto-slap.h -@@ -1587,7 +1587,7 @@ int pagedresults_is_timedout_nolock(Connection *conn); - int pagedresults_reset_timedout_nolock(Connection *conn); - int pagedresults_in_use_nolock(Connection *conn); - int pagedresults_free_one(Connection *conn, Operation *op, int index); --int pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid); -+int pagedresults_free_one_msgid(Connection *conn, ber_int_t msgid, pthread_mutex_t *mutex); - int op_is_pagedresults(Operation *op); - int pagedresults_cleanup_all(Connection *conn, int needlock); - void op_set_pagedresults(Operation *op); -diff --git a/src/lib389/lib389/__init__.py b/src/lib389/lib389/__init__.py -index b8ca7685f..81e41c58b 100644 ---- a/src/lib389/lib389/__init__.py -+++ b/src/lib389/lib389/__init__.py -@@ -1040,6 +1040,24 @@ class DirSrv(SimpleLDAPObject, object): - - self.state = DIRSRV_STATE_OFFLINE - -+ def dump_errorlog(self): -+ ''' -+ Its logs all errors messages within the error log that occured -+ after the last startup. -+ ''' -+ if os.path.isfile(self.errlog): -+ lines = [] -+ with open(self.errlog, 'r') as file: -+ for line in file: -+ if "starting up" in line: -+ lines = [] -+ for key in ( 'DEBUG', 'INFO', 'NOTICE', 'WARN' ): -+ if key in line: -+ lines.append(line) -+ break -+ for line in lines: -+ self.log.error(line) -+ - def start(self, timeout=120, post_open=True): - ''' - It starts an instance and rebind it. Its final state after rebind -@@ -1063,7 +1081,13 @@ class DirSrv(SimpleLDAPObject, object): - if self.with_systemd(): - self.log.debug("systemd status -> True") - # Do systemd things here ... -- subprocess.check_output(["systemctl", "start", "dirsrv@%s" % self.serverid], stderr=subprocess.STDOUT) -+ try: -+ subprocess.check_output(["systemctl", "start", "dirsrv@%s" % self.serverid], stderr=subprocess.STDOUT) -+ except subprocess.CalledProcessError as e: -+ self.dump_errorlog() -+ self.log.error('Failed to start dirsrv@%s: "%s"' % (self.serverid, e.output.decode())) -+ self.log.error(e) -+ raise ValueError('Failed to start DS') - else: - self.log.debug("systemd status -> False") - # Start the process. -@@ -1087,6 +1111,7 @@ class DirSrv(SimpleLDAPObject, object): - self.log.debug("DEBUG: starting with %s" % cmd) - output = subprocess.check_output(*cmd, env=env, stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: -+ self.dump_errorlog() - self.log.error('Failed to start ns-slapd: "%s"' % e.output.decode()) - self.log.error(e) - raise ValueError('Failed to start DS') --- -2.41.0 - diff --git a/SOURCES/0001-issue-5647-covscan-memory-leak-in-audit-log-when-add.patch b/SOURCES/0001-issue-5647-covscan-memory-leak-in-audit-log-when-add.patch new file mode 100644 index 0000000..11a2741 --- /dev/null +++ b/SOURCES/0001-issue-5647-covscan-memory-leak-in-audit-log-when-add.patch @@ -0,0 +1,119 @@ +From dddb14210b402f317e566b6387c76a8e659bf7fa Mon Sep 17 00:00:00 2001 +From: progier389 +Date: Tue, 14 Feb 2023 13:34:10 +0100 +Subject: [PATCH 1/2] issue 5647 - covscan: memory leak in audit log when + adding entries (#5650) + +covscan reported an issue about "vals" variable in auditlog.c:231 and indeed a charray_free is missing. +Issue: 5647 +Reviewed by: @mreynolds389, @droideck +--- + ldap/servers/slapd/auditlog.c | 71 +++++++++++++++++++---------------- + 1 file changed, 38 insertions(+), 33 deletions(-) + +diff --git a/ldap/servers/slapd/auditlog.c b/ldap/servers/slapd/auditlog.c +index 68cbc674d..3128e0497 100644 +--- a/ldap/servers/slapd/auditlog.c ++++ b/ldap/servers/slapd/auditlog.c +@@ -177,6 +177,40 @@ write_auditfail_log_entry(Slapi_PBlock *pb) + slapi_ch_free_string(&audit_config); + } + ++/* ++ * Write the attribute values to the audit log as "comments" ++ * ++ * Slapi_Attr *entry - the attribute begin logged. ++ * char *attrname - the attribute name. ++ * lenstr *l - the audit log buffer ++ * ++ * Resulting output in the log: ++ * ++ * #ATTR: VALUE ++ * #ATTR: VALUE ++ */ ++static void ++log_entry_attr(Slapi_Attr *entry_attr, char *attrname, lenstr *l) ++{ ++ Slapi_Value **vals = attr_get_present_values(entry_attr); ++ for(size_t i = 0; vals && vals[i]; i++) { ++ char log_val[256] = ""; ++ const struct berval *bv = slapi_value_get_berval(vals[i]); ++ if (bv->bv_len >= 256) { ++ strncpy(log_val, bv->bv_val, 252); ++ strcpy(log_val+252, "..."); ++ } else { ++ strncpy(log_val, bv->bv_val, bv->bv_len); ++ log_val[bv->bv_len] = 0; ++ } ++ addlenstr(l, "#"); ++ addlenstr(l, attrname); ++ addlenstr(l, ": "); ++ addlenstr(l, log_val); ++ addlenstr(l, "\n"); ++ } ++} ++ + /* + * Write "requested" attributes from the entry to the audit log as "comments" + * +@@ -212,21 +246,9 @@ add_entry_attrs(Slapi_Entry *entry, lenstr *l) + for (req_attr = ldap_utf8strtok_r(display_attrs, ", ", &last); req_attr; + req_attr = ldap_utf8strtok_r(NULL, ", ", &last)) + { +- char **vals = slapi_entry_attr_get_charray(entry, req_attr); +- for(size_t i = 0; vals && vals[i]; i++) { +- char log_val[256] = {0}; +- +- if (strlen(vals[i]) > 256) { +- strncpy(log_val, vals[i], 252); +- strcat(log_val, "..."); +- } else { +- strcpy(log_val, vals[i]); +- } +- addlenstr(l, "#"); +- addlenstr(l, req_attr); +- addlenstr(l, ": "); +- addlenstr(l, log_val); +- addlenstr(l, "\n"); ++ slapi_entry_attr_find(entry, req_attr, &entry_attr); ++ if (entry_attr) { ++ log_entry_attr(entry_attr, req_attr, l); + } + } + } else { +@@ -234,7 +256,6 @@ add_entry_attrs(Slapi_Entry *entry, lenstr *l) + for (; entry_attr; entry_attr = entry_attr->a_next) { + Slapi_Value **vals = attr_get_present_values(entry_attr); + char *attr = NULL; +- const char *val = NULL; + + slapi_attr_get_type(entry_attr, &attr); + if (strcmp(attr, PSEUDO_ATTR_UNHASHEDUSERPASSWORD) == 0) { +@@ -251,23 +272,7 @@ add_entry_attrs(Slapi_Entry *entry, lenstr *l) + addlenstr(l, ": ****************************\n"); + continue; + } +- +- for(size_t i = 0; vals && vals[i]; i++) { +- char log_val[256] = {0}; +- +- val = slapi_value_get_string(vals[i]); +- if (strlen(val) > 256) { +- strncpy(log_val, val, 252); +- strcat(log_val, "..."); +- } else { +- strcpy(log_val, val); +- } +- addlenstr(l, "#"); +- addlenstr(l, attr); +- addlenstr(l, ": "); +- addlenstr(l, log_val); +- addlenstr(l, "\n"); +- } ++ log_entry_attr(entry_attr, attr, l); + } + } + slapi_ch_free_string(&display_attrs); +-- +2.43.0 + diff --git a/SOURCES/0002-Issue-5647-Fix-unused-variable-warning-from-previous.patch b/SOURCES/0002-Issue-5647-Fix-unused-variable-warning-from-previous.patch new file mode 100644 index 0000000..456ea5c --- /dev/null +++ b/SOURCES/0002-Issue-5647-Fix-unused-variable-warning-from-previous.patch @@ -0,0 +1,27 @@ +From be7c2b82958e91ce08775bf6b5da3c311d3b00e5 Mon Sep 17 00:00:00 2001 +From: progier389 +Date: Mon, 20 Feb 2023 16:14:05 +0100 +Subject: [PATCH 2/2] Issue 5647 - Fix unused variable warning from previous + commit (#5670) + +* issue 5647 - memory leak in audit log when adding entries +* Issue 5647 - Fix unused variable warning from previous commit +--- + ldap/servers/slapd/auditlog.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/ldap/servers/slapd/auditlog.c b/ldap/servers/slapd/auditlog.c +index 3128e0497..0597ecc6f 100644 +--- a/ldap/servers/slapd/auditlog.c ++++ b/ldap/servers/slapd/auditlog.c +@@ -254,7 +254,6 @@ add_entry_attrs(Slapi_Entry *entry, lenstr *l) + } else { + /* Return all attributes */ + for (; entry_attr; entry_attr = entry_attr->a_next) { +- Slapi_Value **vals = attr_get_present_values(entry_attr); + char *attr = NULL; + + slapi_attr_get_type(entry_attr, &attr); +-- +2.43.0 + diff --git a/SOURCES/0002-Issue-5984-Crash-when-paged-result-search-are-abando.patch b/SOURCES/0002-Issue-5984-Crash-when-paged-result-search-are-abando.patch deleted file mode 100644 index 7cbb6d3..0000000 --- a/SOURCES/0002-Issue-5984-Crash-when-paged-result-search-are-abando.patch +++ /dev/null @@ -1,89 +0,0 @@ -From df7dd8320424f7ab616c9ad8086a6874ff8bf859 Mon Sep 17 00:00:00 2001 -From: progier389 -Date: Tue, 21 Nov 2023 11:57:44 +0100 -Subject: [PATCH 2/2] Issue 5984 - Crash when paged result search are abandoned - - fix2 (#5987) - -Chasing several rabbits at the same time is a bad idea ! -and I mixed branches and unwillingly pushed one commit for #5980 in #5984 -just before the PR #5985 merge ! -:( -Hopefully it does not break anything but just logs some useless crap if instance fails to starts. -Anyway This commit reverts the change about __init.py -and also do a minor code cleanup (removed a trailing space) in abandon.c - -Issue #5984 - -Reviewed by: @tbordaz Thanks ! ---- - ldap/servers/slapd/abandon.c | 2 +- - src/lib389/lib389/__init__.py | 27 +-------------------------- - 2 files changed, 2 insertions(+), 27 deletions(-) - -diff --git a/ldap/servers/slapd/abandon.c b/ldap/servers/slapd/abandon.c -index 964d28836..2dd1ee320 100644 ---- a/ldap/servers/slapd/abandon.c -+++ b/ldap/servers/slapd/abandon.c -@@ -43,7 +43,7 @@ do_abandon(Slapi_PBlock *pb) - struct timespec hr_time_end; - int nentries; - int opid; -- } o_copy; -+ } o_copy; - - slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op); - slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn); -diff --git a/src/lib389/lib389/__init__.py b/src/lib389/lib389/__init__.py -index 6a941dbe7..7590ec442 100644 ---- a/src/lib389/lib389/__init__.py -+++ b/src/lib389/lib389/__init__.py -@@ -1048,24 +1048,6 @@ class DirSrv(SimpleLDAPObject, object): - - self.state = DIRSRV_STATE_OFFLINE - -- def dump_errorlog(self): -- ''' -- Its logs all errors messages within the error log that occured -- after the last startup. -- ''' -- if os.path.isfile(self.errlog): -- lines = [] -- with open(self.errlog, 'r') as file: -- for line in file: -- if "starting up" in line: -- lines = [] -- for key in ( 'DEBUG', 'INFO', 'NOTICE', 'WARN' ): -- if key in line: -- lines.append(line) -- break -- for line in lines: -- self.log.error(line) -- - def start(self, timeout=120, post_open=True): - ''' - It starts an instance and rebind it. Its final state after rebind -@@ -1089,13 +1071,7 @@ class DirSrv(SimpleLDAPObject, object): - if self.with_systemd(): - self.log.debug("systemd status -> True") - # Do systemd things here ... -- try: -- subprocess.check_output(["systemctl", "start", "dirsrv@%s" % self.serverid], stderr=subprocess.STDOUT) -- except subprocess.CalledProcessError as e: -- self.dump_errorlog() -- self.log.error('Failed to start dirsrv@%s: "%s"' % (self.serverid, e.output.decode())) -- self.log.error(e) -- raise ValueError('Failed to start DS') -+ subprocess.check_output(["systemctl", "start", "dirsrv@%s" % self.serverid], stderr=subprocess.STDOUT) - else: - self.log.debug("systemd status -> False") - # Start the process. -@@ -1119,7 +1095,6 @@ class DirSrv(SimpleLDAPObject, object): - self.log.debug("DEBUG: starting with %s" % cmd) - output = subprocess.check_output(*cmd, env=env, stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: -- self.dump_errorlog() - self.log.error('Failed to start ns-slapd: "%s"' % e.output.decode()) - self.log.error(e) - raise ValueError('Failed to start DS') --- -2.41.0 - diff --git a/SOURCES/0003-Issue-5407-sync_repl-crashes-if-enabled-while-dynami.patch b/SOURCES/0003-Issue-5407-sync_repl-crashes-if-enabled-while-dynami.patch new file mode 100644 index 0000000..670230c --- /dev/null +++ b/SOURCES/0003-Issue-5407-sync_repl-crashes-if-enabled-while-dynami.patch @@ -0,0 +1,147 @@ +From 692c4cec6cc5c0086cf58f83bcfa690c766c9887 Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Fri, 2 Feb 2024 14:14:28 +0100 +Subject: [PATCH] Issue 5407 - sync_repl crashes if enabled while dynamic + plugin is enabled (#5411) + +Bug description: + When dynamic plugin is enabled, if a MOD enables sync_repl plugin + then sync_repl init function registers the postop callback + that will be called for the MOD itself while the preop + has not been called. + postop expects preop to be called and so primary operation + to be set. When it is not set it crashes + +Fix description: + If the primary operation is not set, just return + +relates: #5407 +--- + .../suites/syncrepl_plugin/basic_test.py | 68 +++++++++++++++++++ + ldap/servers/plugins/sync/sync_persist.c | 23 ++++++- + 2 files changed, 90 insertions(+), 1 deletion(-) + +diff --git a/dirsrvtests/tests/suites/syncrepl_plugin/basic_test.py b/dirsrvtests/tests/suites/syncrepl_plugin/basic_test.py +index eb3770b78..cdf35eeaa 100644 +--- a/dirsrvtests/tests/suites/syncrepl_plugin/basic_test.py ++++ b/dirsrvtests/tests/suites/syncrepl_plugin/basic_test.py +@@ -592,6 +592,74 @@ def test_sync_repl_cenotaph(topo_m2, request): + + request.addfinalizer(fin) + ++def test_sync_repl_dynamic_plugin(topology, request): ++ """Test sync_repl with dynamic plugin ++ ++ :id: d4f84913-c18a-459f-8525-110f610ca9e6 ++ :setup: install a standalone instance ++ :steps: ++ 1. reset instance to standard (no retroCL, no sync_repl, no dynamic plugin) ++ 2. Enable dynamic plugin ++ 3. Enable retroCL/content_sync ++ 4. Establish a sync_repl req ++ :expectedresults: ++ 1. Should succeeds ++ 2. Should succeeds ++ 3. Should succeeds ++ 4. Should succeeds ++ """ ++ ++ # Reset the instance in a default config ++ # Disable content sync plugin ++ topology.standalone.plugins.disable(name=PLUGIN_REPL_SYNC) ++ ++ # Disable retro changelog ++ topology.standalone.plugins.disable(name=PLUGIN_RETRO_CHANGELOG) ++ ++ # Disable dynamic plugins ++ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-dynamic-plugins', b'off')]) ++ topology.standalone.restart() ++ ++ # Now start the test ++ # Enable dynamic plugins ++ try: ++ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-dynamic-plugins', b'on')]) ++ except ldap.LDAPError as e: ++ log.error('Failed to enable dynamic plugin! {}'.format(e.args[0]['desc'])) ++ assert False ++ ++ # Enable retro changelog ++ topology.standalone.plugins.enable(name=PLUGIN_RETRO_CHANGELOG) ++ ++ # Enbale content sync plugin ++ topology.standalone.plugins.enable(name=PLUGIN_REPL_SYNC) ++ ++ # create a sync repl client and wait 5 seconds to be sure it is running ++ sync_repl = Sync_persist(topology.standalone) ++ sync_repl.start() ++ time.sleep(5) ++ ++ # create users ++ users = UserAccounts(topology.standalone, DEFAULT_SUFFIX) ++ users_set = [] ++ for i in range(10001, 10004): ++ users_set.append(users.create_test_user(uid=i)) ++ ++ time.sleep(10) ++ # delete users, that automember/memberof will generate nested updates ++ for user in users_set: ++ user.delete() ++ # stop the server to get the sync_repl result set (exit from while loop). ++ # Only way I found to acheive that. ++ # and wait a bit to let sync_repl thread time to set its result before fetching it. ++ topology.standalone.stop() ++ sync_repl.get_result() ++ sync_repl.join() ++ log.info('test_sync_repl_dynamic_plugin: PASS\n') ++ ++ # Success ++ log.info('Test complete') ++ + def test_sync_repl_invalid_cookie(topology, request): + """Test sync_repl with invalid cookie + +diff --git a/ldap/servers/plugins/sync/sync_persist.c b/ldap/servers/plugins/sync/sync_persist.c +index d2210b64c..283607361 100644 +--- a/ldap/servers/plugins/sync/sync_persist.c ++++ b/ldap/servers/plugins/sync/sync_persist.c +@@ -156,6 +156,17 @@ ignore_op_pl(Slapi_PBlock *pb) + * This is the same for ident + */ + prim_op = get_thread_primary_op(); ++ if (prim_op == NULL) { ++ /* This can happen if the PRE_OP (sync_update_persist_betxn_pre_op) was not called. ++ * The only known case it happens is with dynamic plugin enabled and an ++ * update that enable the sync_repl plugin. In such case sync_repl registers ++ * the postop (sync_update_persist_op) that is called while the preop was not called ++ */ ++ slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, ++ "ignore_op_pl - Operation without primary op set (0x%lx)\n", ++ (ulong) op); ++ return; ++ } + ident = sync_persist_get_operation_extension(pb); + + if (ident) { +@@ -232,8 +243,18 @@ sync_update_persist_op(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eprev, ber + + + prim_op = get_thread_primary_op(); ++ if (prim_op == NULL) { ++ /* This can happen if the PRE_OP (sync_update_persist_betxn_pre_op) was not called. ++ * The only known case it happens is with dynamic plugin enabled and an ++ * update that enable the sync_repl plugin. In such case sync_repl registers ++ * the postop (sync_update_persist_op) that is called while the preop was not called ++ */ ++ slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, ++ "sync_update_persist_op - Operation without primary op set (0x%lx)\n", ++ (ulong) pb_op); ++ return; ++ } + ident = sync_persist_get_operation_extension(pb); +- PR_ASSERT(prim_op); + + if ((ident == NULL) && operation_is_flag_set(pb_op, OP_FLAG_NOOP)) { + /* This happens for URP (add cenotaph, fixup rename, tombstone resurrect) +-- +2.43.0 + diff --git a/SOURCES/0004-Issue-5547-automember-plugin-improvements.patch b/SOURCES/0004-Issue-5547-automember-plugin-improvements.patch new file mode 100644 index 0000000..918945d --- /dev/null +++ b/SOURCES/0004-Issue-5547-automember-plugin-improvements.patch @@ -0,0 +1,840 @@ +From 8dc61a176323f0d41df730abd715ccff3034c2be Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Sun, 27 Nov 2022 09:37:19 -0500 +Subject: [PATCH] Issue 5547 - automember plugin improvements + +Description: + +Rebuild task has the following improvements: + +- Only one task allowed at a time +- Do not cleanup previous members by default. Add new CLI option to intentionally + cleanup memberships before rebuilding from scratch. +- Add better task logging to show fixup progress + +To prevent automember from being called in a nested be_txn loop thread storage is +used to check and skip these loops. + +relates: https://github.com/389ds/389-ds-base/issues/5547 + +Reviewed by: spichugi(Thanks!) +--- + .../automember_plugin/automember_mod_test.py | 43 +++- + ldap/servers/plugins/automember/automember.c | 232 ++++++++++++++---- + ldap/servers/slapd/back-ldbm/ldbm_add.c | 11 +- + ldap/servers/slapd/back-ldbm/ldbm_delete.c | 10 +- + ldap/servers/slapd/back-ldbm/ldbm_modify.c | 11 +- + .../lib389/cli_conf/plugins/automember.py | 10 +- + src/lib389/lib389/plugins.py | 7 +- + src/lib389/lib389/tasks.py | 9 +- + 8 files changed, 250 insertions(+), 83 deletions(-) + +diff --git a/dirsrvtests/tests/suites/automember_plugin/automember_mod_test.py b/dirsrvtests/tests/suites/automember_plugin/automember_mod_test.py +index 8d25384bf..7a0ed3275 100644 +--- a/dirsrvtests/tests/suites/automember_plugin/automember_mod_test.py ++++ b/dirsrvtests/tests/suites/automember_plugin/automember_mod_test.py +@@ -5,12 +5,13 @@ + # License: GPL (version 3 or any later version). + # See LICENSE for details. + # --- END COPYRIGHT BLOCK --- +-# ++import ldap + import logging + import pytest + import os ++import time + from lib389.utils import ds_is_older +-from lib389._constants import * ++from lib389._constants import DEFAULT_SUFFIX + from lib389.plugins import AutoMembershipPlugin, AutoMembershipDefinitions + from lib389.idm.user import UserAccounts + from lib389.idm.group import Groups +@@ -41,6 +42,11 @@ def automember_fixture(topo, request): + user_accts = UserAccounts(topo.standalone, DEFAULT_SUFFIX) + user = user_accts.create_test_user() + ++ # Create extra users ++ users = UserAccounts(topo.standalone, DEFAULT_SUFFIX) ++ for i in range(0, 100): ++ users.create_test_user(uid=i) ++ + # Create automember definitions and regex rules + automember_prop = { + 'cn': 'testgroup_definition', +@@ -59,7 +65,7 @@ def automember_fixture(topo, request): + automemberplugin.enable() + topo.standalone.restart() + +- return (user, groups) ++ return user, groups + + + def test_mods(automember_fixture, topo): +@@ -72,19 +78,21 @@ def test_mods(automember_fixture, topo): + 2. Update user that should add it to group[1] + 3. Update user that should add it to group[2] + 4. Update user that should add it to group[0] +- 5. Test rebuild task correctly moves user to group[1] ++ 5. Test rebuild task adds user to group[1] ++ 6. Test rebuild task cleanups groups and only adds it to group[1] + :expectedresults: + 1. Success + 2. Success + 3. Success + 4. Success + 5. Success ++ 6. Success + """ + (user, groups) = automember_fixture + + # Update user which should go into group[0] + user.replace('cn', 'whatever') +- groups[0].is_member(user.dn) ++ assert groups[0].is_member(user.dn) + if groups[1].is_member(user.dn): + assert False + if groups[2].is_member(user.dn): +@@ -92,7 +100,7 @@ def test_mods(automember_fixture, topo): + + # Update user0 which should go into group[1] + user.replace('cn', 'mark') +- groups[1].is_member(user.dn) ++ assert groups[1].is_member(user.dn) + if groups[0].is_member(user.dn): + assert False + if groups[2].is_member(user.dn): +@@ -100,7 +108,7 @@ def test_mods(automember_fixture, topo): + + # Update user which should go into group[2] + user.replace('cn', 'simon') +- groups[2].is_member(user.dn) ++ assert groups[2].is_member(user.dn) + if groups[0].is_member(user.dn): + assert False + if groups[1].is_member(user.dn): +@@ -108,7 +116,7 @@ def test_mods(automember_fixture, topo): + + # Update user which should go back into group[0] (full circle) + user.replace('cn', 'whatever') +- groups[0].is_member(user.dn) ++ assert groups[0].is_member(user.dn) + if groups[1].is_member(user.dn): + assert False + if groups[2].is_member(user.dn): +@@ -128,12 +136,24 @@ def test_mods(automember_fixture, topo): + automemberplugin.enable() + topo.standalone.restart() + +- # Run rebuild task ++ # Run rebuild task (no cleanup) + task = automemberplugin.fixup(DEFAULT_SUFFIX, "objectclass=posixaccount") ++ with pytest.raises(ldap.UNWILLING_TO_PERFORM): ++ # test only one fixup task is allowed at a time ++ automemberplugin.fixup(DEFAULT_SUFFIX, "objectclass=top") + task.wait() + +- # Test membership +- groups[1].is_member(user.dn) ++ # Test membership (user should still be in groups[0]) ++ assert groups[1].is_member(user.dn) ++ if not groups[0].is_member(user.dn): ++ assert False ++ ++ # Run rebuild task with cleanup ++ task = automemberplugin.fixup(DEFAULT_SUFFIX, "objectclass=posixaccount", cleanup=True) ++ task.wait() ++ ++ # Test membership (user should only be in groups[1]) ++ assert groups[1].is_member(user.dn) + if groups[0].is_member(user.dn): + assert False + if groups[2].is_member(user.dn): +@@ -148,4 +168,3 @@ if __name__ == '__main__': + # -s for DEBUG mode + CURRENT_FILE = os.path.realpath(__file__) + pytest.main(["-s", CURRENT_FILE]) +- +diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c +index 3494d0343..419adb052 100644 +--- a/ldap/servers/plugins/automember/automember.c ++++ b/ldap/servers/plugins/automember/automember.c +@@ -1,5 +1,5 @@ + /** BEGIN COPYRIGHT BLOCK +- * Copyright (C) 2011 Red Hat, Inc. ++ * Copyright (C) 2022 Red Hat, Inc. + * All rights reserved. + * + * License: GPL (version 3 or any later version). +@@ -14,7 +14,7 @@ + * Auto Membership Plug-in + */ + #include "automember.h" +- ++#include + + /* + * Plug-in globals +@@ -22,7 +22,9 @@ + static PRCList *g_automember_config = NULL; + static Slapi_RWLock *g_automember_config_lock = NULL; + static uint64_t abort_rebuild_task = 0; +- ++static pthread_key_t td_automem_block_nested; ++static PRBool fixup_running = PR_FALSE; ++static PRLock *fixup_lock = NULL; + static void *_PluginID = NULL; + static Slapi_DN *_PluginDN = NULL; + static Slapi_DN *_ConfigAreaDN = NULL; +@@ -93,9 +95,43 @@ 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 ++#define FIXUP_PROGRESS_LIMIT 1000 + static uint64_t plugin_do_modify = 0; + static uint64_t plugin_is_betxn = 0; + ++/* automember_plugin fixup task and add operations should block other be_txn ++ * plugins from calling automember_post_op_mod() */ ++static int32_t ++slapi_td_block_nested_post_op(void) ++{ ++ int32_t val = 12345; ++ ++ if (pthread_setspecific(td_automem_block_nested, (void *)&val) != 0) { ++ return PR_FAILURE; ++ } ++ return PR_SUCCESS; ++} ++ ++static int32_t ++slapi_td_unblock_nested_post_op(void) ++{ ++ if (pthread_setspecific(td_automem_block_nested, NULL) != 0) { ++ return PR_FAILURE; ++ } ++ return PR_SUCCESS; ++} ++ ++static int32_t ++slapi_td_is_post_op_nested(void) ++{ ++ int32_t *value = pthread_getspecific(td_automem_block_nested); ++ ++ if (value == NULL) { ++ return 0; ++ } ++ return 1; ++} ++ + /* + * Config cache locking functions + */ +@@ -317,6 +353,14 @@ automember_start(Slapi_PBlock *pb) + return -1; + } + ++ if (fixup_lock == NULL) { ++ if ((fixup_lock = PR_NewLock()) == NULL) { ++ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM, ++ "automember_start - Failed to create fixup lock.\n"); ++ return -1; ++ } ++ } ++ + /* + * Get the plug-in target dn from the system + * and store it for future use. */ +@@ -360,6 +404,11 @@ automember_start(Slapi_PBlock *pb) + } + } + ++ if (pthread_key_create(&td_automem_block_nested, NULL) != 0) { ++ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM, ++ "automember_start - pthread_key_create failed\n"); ++ } ++ + slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM, + "automember_start - ready for service\n"); + slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM, +@@ -394,6 +443,8 @@ automember_close(Slapi_PBlock *pb __attribute__((unused))) + slapi_sdn_free(&_ConfigAreaDN); + slapi_destroy_rwlock(g_automember_config_lock); + g_automember_config_lock = NULL; ++ PR_DestroyLock(fixup_lock); ++ fixup_lock = NULL; + + slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM, + "<-- automember_close\n"); +@@ -1619,7 +1670,6 @@ out: + return rc; + } + +- + /* + * automember_update_member_value() + * +@@ -1634,7 +1684,7 @@ automember_update_member_value(Slapi_Entry *member_e, const char *group_dn, char + LDAPMod *mods[2]; + char *vals[2]; + char *member_value = NULL; +- int rc = 0; ++ int rc = LDAP_SUCCESS; + Slapi_DN *group_sdn; + + /* First thing check that the group still exists */ +@@ -1653,7 +1703,7 @@ automember_update_member_value(Slapi_Entry *member_e, const char *group_dn, char + "automember_update_member_value - group (default or target) can not be retrieved (%s) err=%d\n", + group_dn, rc); + } +- return rc; ++ goto out; + } + + /* If grouping_value is dn, we need to fetch the dn instead. */ +@@ -1879,6 +1929,13 @@ automember_mod_post_op(Slapi_PBlock *pb) + PRCList *list = NULL; + int rc = SLAPI_PLUGIN_SUCCESS; + ++ if (slapi_td_is_post_op_nested()) { ++ /* don't process op twice in the same thread */ ++ return rc; ++ } else { ++ slapi_td_block_nested_post_op(); ++ } ++ + slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM, + "--> automember_mod_post_op\n"); + +@@ -2005,6 +2062,7 @@ automember_mod_post_op(Slapi_PBlock *pb) + } + } + } ++ slapi_td_unblock_nested_post_op(); + + slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM, + "<-- automember_mod_post_op (%d)\n", rc); +@@ -2024,6 +2082,13 @@ automember_add_post_op(Slapi_PBlock *pb) + slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM, + "--> automember_add_post_op\n"); + ++ if (slapi_td_is_post_op_nested()) { ++ /* don't process op twice in the same thread */ ++ return rc; ++ } else { ++ slapi_td_block_nested_post_op(); ++ } ++ + /* Reload config if a config entry was added. */ + if ((sdn = automember_get_sdn(pb))) { + if (automember_dn_is_config(sdn)) { +@@ -2039,7 +2104,7 @@ automember_add_post_op(Slapi_PBlock *pb) + + /* If replication, just bail. */ + if (automember_isrepl(pb)) { +- return SLAPI_PLUGIN_SUCCESS; ++ goto bail; + } + + /* Get the newly added entry. */ +@@ -2052,7 +2117,7 @@ automember_add_post_op(Slapi_PBlock *pb) + tombstone); + slapi_value_free(&tombstone); + if (is_tombstone) { +- return SLAPI_PLUGIN_SUCCESS; ++ goto bail; + } + + /* Check if a config entry applies +@@ -2063,21 +2128,19 @@ automember_add_post_op(Slapi_PBlock *pb) + list = PR_LIST_HEAD(g_automember_config); + while (list != g_automember_config) { + config = (struct configEntry *)list; +- + /* Does the entry meet scope and filter requirements? */ + if (slapi_dn_issuffix(slapi_sdn_get_dn(sdn), config->scope) && +- (slapi_filter_test_simple(e, config->filter) == 0)) { ++ (slapi_filter_test_simple(e, config->filter) == 0)) ++ { + /* Find out what membership changes are needed and make them. */ + if (automember_update_membership(config, e, NULL) == SLAPI_PLUGIN_FAILURE) { + rc = SLAPI_PLUGIN_FAILURE; + break; + } + } +- + list = PR_NEXT_LINK(list); + } + } +- + automember_config_unlock(); + } else { + slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM, +@@ -2098,6 +2161,7 @@ bail: + slapi_pblock_set(pb, SLAPI_RESULT_CODE, &result); + slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, &errtxt); + } ++ slapi_td_unblock_nested_post_op(); + + return rc; + } +@@ -2138,6 +2202,7 @@ typedef struct _task_data + Slapi_DN *base_dn; + char *bind_dn; + int scope; ++ PRBool cleanup; + } task_data; + + static void +@@ -2270,6 +2335,7 @@ automember_task_abort_thread(void *arg) + * basedn: dc=example,dc=com + * filter: (uid=*) + * scope: sub ++ * cleanup: yes/on (default is off) + * + * basedn and filter are required. If scope is omitted, the default is sub + */ +@@ -2284,9 +2350,22 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter __attr + const char *base_dn; + const char *filter; + const char *scope; ++ const char *cleanup_str; ++ PRBool cleanup = PR_FALSE; + + *returncode = LDAP_SUCCESS; + ++ PR_Lock(fixup_lock); ++ if (fixup_running) { ++ PR_Unlock(fixup_lock); ++ *returncode = LDAP_UNWILLING_TO_PERFORM; ++ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM, ++ "automember_task_add - there is already a fixup task running\n"); ++ rv = SLAPI_DSE_CALLBACK_ERROR; ++ goto out; ++ } ++ PR_Unlock(fixup_lock); ++ + /* + * Grab the task params + */ +@@ -2300,6 +2379,12 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter __attr + rv = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } ++ if ((cleanup_str = slapi_entry_attr_get_ref(e, "cleanup"))) { ++ if (strcasecmp(cleanup_str, "yes") == 0 || strcasecmp(cleanup_str, "on")) { ++ cleanup = PR_TRUE; ++ } ++ } ++ + scope = slapi_fetch_attr(e, "scope", "sub"); + /* + * setup our task data +@@ -2315,6 +2400,7 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter __attr + mytaskdata->bind_dn = slapi_ch_strdup(bind_dn); + mytaskdata->base_dn = slapi_sdn_new_dn_byval(base_dn); + mytaskdata->filter_str = slapi_ch_strdup(filter); ++ mytaskdata->cleanup = cleanup; + + if (scope) { + if (strcasecmp(scope, "sub") == 0) { +@@ -2334,6 +2420,9 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter __attr + task = slapi_plugin_new_task(slapi_entry_get_ndn(e), arg); + slapi_task_set_destructor_fn(task, automember_task_destructor); + slapi_task_set_data(task, mytaskdata); ++ PR_Lock(fixup_lock); ++ fixup_running = PR_TRUE; ++ PR_Unlock(fixup_lock); + /* + * Start the task as a separate thread + */ +@@ -2345,6 +2434,9 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter __attr + "automember_task_add - Unable to create task thread!\n"); + *returncode = LDAP_OPERATIONS_ERROR; + slapi_task_finish(task, *returncode); ++ PR_Lock(fixup_lock); ++ fixup_running = PR_FALSE; ++ PR_Unlock(fixup_lock); + rv = SLAPI_DSE_CALLBACK_ERROR; + } else { + rv = SLAPI_DSE_CALLBACK_OK; +@@ -2372,6 +2464,9 @@ automember_rebuild_task_thread(void *arg) + PRCList *list = NULL; + PRCList *include_list = NULL; + int result = 0; ++ int64_t fixup_progress_count = 0; ++ int64_t fixup_progress_elapsed = 0; ++ int64_t fixup_start_time = 0; + size_t i = 0; + + /* Reset abort flag */ +@@ -2380,6 +2475,7 @@ automember_rebuild_task_thread(void *arg) + if (!task) { + return; /* no task */ + } ++ + slapi_task_inc_refcount(task); + slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM, + "automember_rebuild_task_thread - Refcount incremented.\n"); +@@ -2393,9 +2489,11 @@ automember_rebuild_task_thread(void *arg) + slapi_task_log_status(task, "Automember rebuild task starting (base dn: (%s) filter (%s)...", + slapi_sdn_get_dn(td->base_dn), td->filter_str); + /* +- * Set the bind dn in the local thread data ++ * Set the bind dn in the local thread data, and block post op mods + */ + slapi_td_set_dn(slapi_ch_strdup(td->bind_dn)); ++ slapi_td_block_nested_post_op(); ++ fixup_start_time = slapi_current_rel_time_t(); + /* + * Take the config lock now and search the database + */ +@@ -2426,6 +2524,21 @@ automember_rebuild_task_thread(void *arg) + * Loop over the entries + */ + for (i = 0; entries && (entries[i] != NULL); i++) { ++ fixup_progress_count++; ++ if (fixup_progress_count % FIXUP_PROGRESS_LIMIT == 0 ) { ++ slapi_task_log_notice(task, ++ "Processed %ld entries in %ld seconds (+%ld seconds)", ++ fixup_progress_count, ++ slapi_current_rel_time_t() - fixup_start_time, ++ slapi_current_rel_time_t() - fixup_progress_elapsed); ++ slapi_task_log_status(task, ++ "Processed %ld entries in %ld seconds (+%ld seconds)", ++ fixup_progress_count, ++ slapi_current_rel_time_t() - fixup_start_time, ++ slapi_current_rel_time_t() - fixup_progress_elapsed); ++ slapi_task_inc_progress(task); ++ fixup_progress_elapsed = slapi_current_rel_time_t(); ++ } + if (slapi_atomic_load_64(&abort_rebuild_task, __ATOMIC_ACQUIRE) == 1) { + /* The task was aborted */ + slapi_task_log_notice(task, "Automember rebuild task was intentionally aborted"); +@@ -2443,48 +2556,66 @@ automember_rebuild_task_thread(void *arg) + if (slapi_dn_issuffix(slapi_entry_get_dn(entries[i]), config->scope) && + (slapi_filter_test_simple(entries[i], config->filter) == 0)) + { +- /* First clear out all the defaults groups */ +- for (size_t ii = 0; config->default_groups && config->default_groups[ii]; ii++) { +- if ((result = automember_update_member_value(entries[i], config->default_groups[ii], +- config->grouping_attr, config->grouping_value, NULL, DEL_MEMBER))) +- { +- slapi_task_log_notice(task, "Automember rebuild membership task unable to delete " +- "member from default group (%s) error (%d)", +- config->default_groups[ii], result); +- slapi_task_log_status(task, "Automember rebuild membership task unable to delete " +- "member from default group (%s) error (%d)", +- config->default_groups[ii], result); +- slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM, +- "automember_rebuild_task_thread - Unable to unable to delete from (%s) error (%d)\n", +- config->default_groups[ii], result); +- goto out; +- } +- } +- +- /* Then clear out the non-default group */ +- if (config->inclusive_rules && !PR_CLIST_IS_EMPTY((PRCList *)config->inclusive_rules)) { +- include_list = PR_LIST_HEAD((PRCList *)config->inclusive_rules); +- while (include_list != (PRCList *)config->inclusive_rules) { +- struct automemberRegexRule *curr_rule = (struct automemberRegexRule *)include_list; +- if ((result = automember_update_member_value(entries[i], slapi_sdn_get_dn(curr_rule->target_group_dn), +- config->grouping_attr, config->grouping_value, NULL, DEL_MEMBER))) ++ if (td->cleanup) { ++ ++ slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM, ++ "automember_rebuild_task_thread - Cleaning up groups (config %s)\n", ++ config->dn); ++ /* First clear out all the defaults groups */ ++ for (size_t ii = 0; config->default_groups && config->default_groups[ii]; ii++) { ++ if ((result = automember_update_member_value(entries[i], ++ config->default_groups[ii], ++ config->grouping_attr, ++ config->grouping_value, ++ NULL, DEL_MEMBER))) + { + slapi_task_log_notice(task, "Automember rebuild membership task unable to delete " +- "member from group (%s) error (%d)", +- slapi_sdn_get_dn(curr_rule->target_group_dn), result); ++ "member from default group (%s) error (%d)", ++ config->default_groups[ii], result); + slapi_task_log_status(task, "Automember rebuild membership task unable to delete " +- "member from group (%s) error (%d)", +- slapi_sdn_get_dn(curr_rule->target_group_dn), result); ++ "member from default group (%s) error (%d)", ++ config->default_groups[ii], result); + slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM, + "automember_rebuild_task_thread - Unable to unable to delete from (%s) error (%d)\n", +- slapi_sdn_get_dn(curr_rule->target_group_dn), result); ++ config->default_groups[ii], result); + goto out; + } +- include_list = PR_NEXT_LINK(include_list); + } ++ ++ /* Then clear out the non-default group */ ++ if (config->inclusive_rules && !PR_CLIST_IS_EMPTY((PRCList *)config->inclusive_rules)) { ++ include_list = PR_LIST_HEAD((PRCList *)config->inclusive_rules); ++ while (include_list != (PRCList *)config->inclusive_rules) { ++ struct automemberRegexRule *curr_rule = (struct automemberRegexRule *)include_list; ++ if ((result = automember_update_member_value(entries[i], ++ slapi_sdn_get_dn(curr_rule->target_group_dn), ++ config->grouping_attr, ++ config->grouping_value, ++ NULL, DEL_MEMBER))) ++ { ++ slapi_task_log_notice(task, "Automember rebuild membership task unable to delete " ++ "member from group (%s) error (%d)", ++ slapi_sdn_get_dn(curr_rule->target_group_dn), result); ++ slapi_task_log_status(task, "Automember rebuild membership task unable to delete " ++ "member from group (%s) error (%d)", ++ slapi_sdn_get_dn(curr_rule->target_group_dn), result); ++ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM, ++ "automember_rebuild_task_thread - Unable to unable to delete from (%s) error (%d)\n", ++ slapi_sdn_get_dn(curr_rule->target_group_dn), result); ++ goto out; ++ } ++ include_list = PR_NEXT_LINK(include_list); ++ } ++ } ++ slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM, ++ "automember_rebuild_task_thread - Finished cleaning up groups (config %s)\n", ++ config->dn); + } + + /* Update the memberships for this entries */ ++ slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM, ++ "automember_rebuild_task_thread - Updating membership (config %s)\n", ++ config->dn); + if (slapi_is_shutting_down() || + automember_update_membership(config, entries[i], NULL) == SLAPI_PLUGIN_FAILURE) + { +@@ -2508,15 +2639,22 @@ out: + slapi_task_log_notice(task, "Automember rebuild task aborted. Error (%d)", result); + slapi_task_log_status(task, "Automember rebuild task aborted. Error (%d)", result); + } else { +- slapi_task_log_notice(task, "Automember rebuild task finished. Processed (%d) entries.", (int32_t)i); +- slapi_task_log_status(task, "Automember rebuild task finished. Processed (%d) entries.", (int32_t)i); ++ slapi_task_log_notice(task, "Automember rebuild task finished. Processed (%ld) entries in %ld seconds", ++ (int64_t)i, slapi_current_rel_time_t() - fixup_start_time); ++ slapi_task_log_status(task, "Automember rebuild task finished. Processed (%ld) entries in %ld seconds", ++ (int64_t)i, slapi_current_rel_time_t() - fixup_start_time); + } + slapi_task_inc_progress(task); + slapi_task_finish(task, result); + slapi_task_dec_refcount(task); + slapi_atomic_store_64(&abort_rebuild_task, 0, __ATOMIC_RELEASE); ++ slapi_td_unblock_nested_post_op(); ++ PR_Lock(fixup_lock); ++ fixup_running = PR_FALSE; ++ PR_Unlock(fixup_lock); ++ + slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM, +- "automember_rebuild_task_thread - Refcount decremented.\n"); ++ "automember_rebuild_task_thread - task finished, refcount decremented.\n"); + } + + /* +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c +index ba2d73a84..ce4c314a1 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c +@@ -1,6 +1,6 @@ + /** BEGIN COPYRIGHT BLOCK + * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. +- * Copyright (C) 2005 Red Hat, Inc. ++ * Copyright (C) 2022 Red Hat, Inc. + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. + * All rights reserved. + * +@@ -1264,10 +1264,6 @@ ldbm_back_add(Slapi_PBlock *pb) + goto common_return; + + error_return: +- /* Revert the caches if this is the parent operation */ +- if (parent_op && betxn_callback_fails) { +- revert_cache(inst, &parent_time); +- } + if (addingentry_id_assigned) { + next_id_return(be, addingentry->ep_id); + } +@@ -1376,6 +1372,11 @@ diskfull_return: + if (!not_an_error) { + rc = SLAPI_FAIL_GENERAL; + } ++ ++ /* Revert the caches if this is the parent operation */ ++ if (parent_op && betxn_callback_fails) { ++ revert_cache(inst, &parent_time); ++ } + } + + common_return: +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +index de23190c3..27f0ac58a 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +@@ -1407,11 +1407,6 @@ commit_return: + goto common_return; + + error_return: +- /* Revert the caches if this is the parent operation */ +- if (parent_op && betxn_callback_fails) { +- 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. */ +@@ -1496,6 +1491,11 @@ error_return: + conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry, myrc); + } + ++ /* Revert the caches if this is the parent operation */ ++ if (parent_op && betxn_callback_fails) { ++ revert_cache(inst, &parent_time); ++ } ++ + common_return: + if (orig_entry) { + /* NOTE: #define SLAPI_DELETE_BEPREOP_ENTRY SLAPI_ENTRY_PRE_OP */ +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c +index 537369055..64b293001 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c +@@ -1,6 +1,6 @@ + /** BEGIN COPYRIGHT BLOCK + * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. +- * Copyright (C) 2005 Red Hat, Inc. ++ * Copyright (C) 2022 Red Hat, Inc. + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. + * All rights reserved. + * +@@ -1043,11 +1043,6 @@ ldbm_back_modify(Slapi_PBlock *pb) + goto common_return; + + error_return: +- /* Revert the caches if this is the parent operation */ +- if (parent_op && betxn_callback_fails) { +- revert_cache(inst, &parent_time); +- } +- + if (postentry != NULL) { + slapi_entry_free(postentry); + postentry = NULL; +@@ -1103,6 +1098,10 @@ error_return: + if (!not_an_error) { + rc = SLAPI_FAIL_GENERAL; + } ++ /* Revert the caches if this is the parent operation */ ++ if (parent_op && betxn_callback_fails) { ++ revert_cache(inst, &parent_time); ++ } + } + + /* if ec is in cache, remove it, then add back e if we still have it */ +diff --git a/src/lib389/lib389/cli_conf/plugins/automember.py b/src/lib389/lib389/cli_conf/plugins/automember.py +index 15b00c633..568586ad8 100644 +--- a/src/lib389/lib389/cli_conf/plugins/automember.py ++++ b/src/lib389/lib389/cli_conf/plugins/automember.py +@@ -155,7 +155,7 @@ def fixup(inst, basedn, log, args): + log.info('Attempting to add task entry... This will fail if Automembership plug-in is not enabled.') + if not plugin.status(): + log.error("'%s' is disabled. Rebuild membership task can't be executed" % plugin.rdn) +- fixup_task = plugin.fixup(args.DN, args.filter) ++ fixup_task = plugin.fixup(args.DN, args.filter, args.cleanup) + if args.wait: + log.info(f'Waiting for fixup task "{fixup_task.dn}" to complete. You can safely exit by pressing Control C ...') + fixup_task.wait(timeout=args.timeout) +@@ -225,8 +225,8 @@ def create_parser(subparsers): + subcommands = automember.add_subparsers(help='action') + add_generic_plugin_parsers(subcommands, AutoMembershipPlugin) + +- list = subcommands.add_parser('list', help='List Automembership definitions or regex rules.') +- subcommands_list = list.add_subparsers(help='action') ++ automember_list = subcommands.add_parser('list', help='List Automembership definitions or regex rules.') ++ subcommands_list = automember_list.add_subparsers(help='action') + list_definitions = subcommands_list.add_parser('definitions', help='Lists Automembership definitions.') + list_definitions.set_defaults(func=definition_list) + list_regexes = subcommands_list.add_parser('regexes', help='List Automembership regex rules.') +@@ -269,6 +269,8 @@ def create_parser(subparsers): + fixup_task.add_argument('-f', '--filter', required=True, help='Sets the LDAP filter for entries to fix up') + fixup_task.add_argument('-s', '--scope', required=True, choices=['sub', 'base', 'one'], type=str.lower, + help='Sets the LDAP search scope for entries to fix up') ++ fixup_task.add_argument('--cleanup', action='store_true', ++ help="Clean up previous group memberships before rebuilding") + fixup_task.add_argument('--wait', action='store_true', + help="Wait for the task to finish, this could take a long time") + fixup_task.add_argument('--timeout', default=0, type=int, +@@ -279,7 +281,7 @@ def create_parser(subparsers): + fixup_status.add_argument('--dn', help="The task entry's DN") + fixup_status.add_argument('--show-log', action='store_true', help="Display the task log") + fixup_status.add_argument('--watch', action='store_true', +- help="Watch the task's status and wait for it to finish") ++ help="Watch the task's status and wait for it to finish") + + abort_fixup = subcommands.add_parser('abort-fixup', help='Abort the rebuild membership task.') + abort_fixup.set_defaults(func=abort) +diff --git a/src/lib389/lib389/plugins.py b/src/lib389/lib389/plugins.py +index 52691a44c..a1ad0a45b 100644 +--- a/src/lib389/lib389/plugins.py ++++ b/src/lib389/lib389/plugins.py +@@ -1141,13 +1141,15 @@ class AutoMembershipPlugin(Plugin): + def __init__(self, instance, dn="cn=Auto Membership Plugin,cn=plugins,cn=config"): + super(AutoMembershipPlugin, self).__init__(instance, dn) + +- def fixup(self, basedn, _filter=None): ++ def fixup(self, basedn, _filter=None, cleanup=False): + """Create an automember rebuild membership task + + :param basedn: Basedn to fix up + :type basedn: str + :param _filter: a filter for entries to fix up + :type _filter: str ++ :param cleanup: cleanup old group memberships ++ :type cleanup: boolean + + :returns: an instance of Task(DSLdapObject) + """ +@@ -1156,6 +1158,9 @@ class AutoMembershipPlugin(Plugin): + task_properties = {'basedn': basedn} + if _filter is not None: + task_properties['filter'] = _filter ++ if cleanup: ++ task_properties['cleanup'] = "yes" ++ + task.create(properties=task_properties) + + return task +diff --git a/src/lib389/lib389/tasks.py b/src/lib389/lib389/tasks.py +index 1a16bbb83..193805780 100644 +--- a/src/lib389/lib389/tasks.py ++++ b/src/lib389/lib389/tasks.py +@@ -1006,12 +1006,13 @@ class Tasks(object): + return exitCode + + def automemberRebuild(self, suffix=DEFAULT_SUFFIX, scope='sub', +- filterstr='objectclass=top', args=None): ++ filterstr='objectclass=top', cleanup=False, args=None): + ''' +- @param suffix - The suffix the task should examine - defualt is ++ @param suffix - The suffix the task should examine - default is + "dc=example,dc=com" + @param scope - The scope of the search to find entries +- @param fitlerstr - THe search filter to find entries ++ @param fitlerstr - The search filter to find entries ++ @param cleanup - reset/clear the old group mmeberships prior to rebuilding + @param args - is a dictionary that contains modifier of the task + wait: True/[False] - If True, waits for the completion of + the task before to return +@@ -1027,6 +1028,8 @@ class Tasks(object): + entry.setValues('basedn', suffix) + entry.setValues('filter', filterstr) + entry.setValues('scope', scope) ++ if cleanup: ++ entry.setValues('cleanup', 'yes') + + # start the task and possibly wait for task completion + try: +-- +2.43.0 + diff --git a/SOURCES/Cargo-1.4.3.37-1.lock b/SOURCES/Cargo-1.4.3.39-1.lock similarity index 75% rename from SOURCES/Cargo-1.4.3.37-1.lock rename to SOURCES/Cargo-1.4.3.39-1.lock index 6ace601..4667a17 100644 --- a/SOURCES/Cargo-1.4.3.37-1.lock +++ b/SOURCES/Cargo-1.4.3.39-1.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ "getrandom", "once_cell", @@ -56,9 +56,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -83,15 +83,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cbindgen" @@ -112,9 +112,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", "libc", @@ -160,11 +160,10 @@ dependencies = [ [[package]] name = "crossbeam" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ - "cfg-if", "crossbeam-channel", "crossbeam-deque", "crossbeam-epoch", @@ -174,56 +173,46 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "entryuuid" @@ -249,30 +238,19 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "errno-dragonfly", "libc", "windows-sys", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fernet" @@ -304,9 +282,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -315,9 +293,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "hashbrown" @@ -348,24 +326,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] [[package]] name = "libc" -version = "0.2.147" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "librnsslapd" @@ -388,15 +366,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -404,9 +382,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lru" @@ -419,18 +397,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "miniz_oxide" @@ -443,26 +412,26 @@ dependencies = [ [[package]] name = "object" -version = "0.31.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.56" +version = "0.10.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" +checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -479,14 +448,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.48", ] [[package]] name = "openssl-sys" -version = "0.9.91" +version = "0.9.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" +checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" dependencies = [ "cc", "libc", @@ -540,15 +509,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" [[package]] name = "ppv-lite86" @@ -564,9 +533,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -586,9 +555,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.32" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -634,9 +603,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] @@ -653,11 +622,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.7" +version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", @@ -666,9 +635,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "scopeguard" @@ -678,29 +647,29 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.183" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.183" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.48", ] [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", @@ -725,9 +694,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e" [[package]] name = "strsim" @@ -748,9 +717,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.28" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -759,13 +728,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.7.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "rustix", "windows-sys", ] @@ -781,11 +750,10 @@ dependencies = [ [[package]] name = "tokio" -version = "1.29.1" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ - "autocfg", "backtrace", "pin-project-lite", "tokio-macros", @@ -793,13 +761,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.48", ] [[package]] @@ -813,15 +781,15 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uuid" @@ -880,18 +848,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -904,51 +872,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] @@ -961,5 +929,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.48", ] diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec index ce77d30..903fcf4 100644 --- a/SPECS/389-ds-base.spec +++ b/SPECS/389-ds-base.spec @@ -47,8 +47,8 @@ ExcludeArch: i686 Summary: 389 Directory Server (base) Name: 389-ds-base -Version: 1.4.3.37 -Release: %{?relprefix}2%{?prerel}%{?dist} +Version: 1.4.3.39 +Release: %{?relprefix}3%{?prerel}%{?dist} License: GPLv3+ and (ASL 2.0 or MIT) URL: https://www.port389.org Group: System Environment/Daemons @@ -58,96 +58,93 @@ Obsoletes: %{name} <= 1.4.0.9 Provides: ldif2ldbm >= 0 ##### Bundled cargo crates list - START ##### -Provides: bundled(crate(addr2line)) = 0.20.0 +Provides: bundled(crate(addr2line)) = 0.21.0 Provides: bundled(crate(adler)) = 1.0.2 -Provides: bundled(crate(ahash)) = 0.7.6 +Provides: bundled(crate(ahash)) = 0.7.7 Provides: bundled(crate(ansi_term)) = 0.12.1 Provides: bundled(crate(atty)) = 0.2.14 Provides: bundled(crate(autocfg)) = 1.1.0 -Provides: bundled(crate(backtrace)) = 0.3.68 +Provides: bundled(crate(backtrace)) = 0.3.69 Provides: bundled(crate(base64)) = 0.13.1 Provides: bundled(crate(bitflags)) = 1.3.2 -Provides: bundled(crate(byteorder)) = 1.4.3 +Provides: bundled(crate(bitflags)) = 2.4.1 +Provides: bundled(crate(byteorder)) = 1.5.0 Provides: bundled(crate(cbindgen)) = 0.9.1 -Provides: bundled(crate(cc)) = 1.0.79 +Provides: bundled(crate(cc)) = 1.0.83 Provides: bundled(crate(cfg-if)) = 1.0.0 Provides: bundled(crate(clap)) = 2.34.0 Provides: bundled(crate(concread)) = 0.2.21 -Provides: bundled(crate(crossbeam)) = 0.8.2 -Provides: bundled(crate(crossbeam-channel)) = 0.5.8 -Provides: bundled(crate(crossbeam-deque)) = 0.8.3 -Provides: bundled(crate(crossbeam-epoch)) = 0.9.15 -Provides: bundled(crate(crossbeam-queue)) = 0.3.8 -Provides: bundled(crate(crossbeam-utils)) = 0.8.16 +Provides: bundled(crate(crossbeam)) = 0.8.4 +Provides: bundled(crate(crossbeam-channel)) = 0.5.11 +Provides: bundled(crate(crossbeam-deque)) = 0.8.5 +Provides: bundled(crate(crossbeam-epoch)) = 0.9.18 +Provides: bundled(crate(crossbeam-queue)) = 0.3.11 +Provides: bundled(crate(crossbeam-utils)) = 0.8.19 Provides: bundled(crate(entryuuid)) = 0.1.0 Provides: bundled(crate(entryuuid_syntax)) = 0.1.0 -Provides: bundled(crate(errno)) = 0.3.1 -Provides: bundled(crate(errno-dragonfly)) = 0.1.2 -Provides: bundled(crate(fastrand)) = 1.9.0 +Provides: bundled(crate(errno)) = 0.3.8 +Provides: bundled(crate(fastrand)) = 2.0.1 Provides: bundled(crate(fernet)) = 0.1.4 Provides: bundled(crate(foreign-types)) = 0.3.2 Provides: bundled(crate(foreign-types-shared)) = 0.1.1 -Provides: bundled(crate(getrandom)) = 0.2.10 -Provides: bundled(crate(gimli)) = 0.27.3 +Provides: bundled(crate(getrandom)) = 0.2.12 +Provides: bundled(crate(gimli)) = 0.28.1 Provides: bundled(crate(hashbrown)) = 0.12.3 Provides: bundled(crate(hermit-abi)) = 0.1.19 -Provides: bundled(crate(hermit-abi)) = 0.3.2 Provides: bundled(crate(instant)) = 0.1.12 -Provides: bundled(crate(io-lifetimes)) = 1.0.11 -Provides: bundled(crate(itoa)) = 1.0.8 -Provides: bundled(crate(jobserver)) = 0.1.26 -Provides: bundled(crate(libc)) = 0.2.147 +Provides: bundled(crate(itoa)) = 1.0.10 +Provides: bundled(crate(jobserver)) = 0.1.27 +Provides: bundled(crate(libc)) = 0.2.152 Provides: bundled(crate(librnsslapd)) = 0.1.0 Provides: bundled(crate(librslapd)) = 0.1.0 -Provides: bundled(crate(linux-raw-sys)) = 0.3.8 -Provides: bundled(crate(lock_api)) = 0.4.10 -Provides: bundled(crate(log)) = 0.4.19 +Provides: bundled(crate(linux-raw-sys)) = 0.4.12 +Provides: bundled(crate(lock_api)) = 0.4.11 +Provides: bundled(crate(log)) = 0.4.20 Provides: bundled(crate(lru)) = 0.7.8 -Provides: bundled(crate(memchr)) = 2.5.0 -Provides: bundled(crate(memoffset)) = 0.9.0 +Provides: bundled(crate(memchr)) = 2.7.1 Provides: bundled(crate(miniz_oxide)) = 0.7.1 -Provides: bundled(crate(object)) = 0.31.1 -Provides: bundled(crate(once_cell)) = 1.18.0 -Provides: bundled(crate(openssl)) = 0.10.55 +Provides: bundled(crate(object)) = 0.32.2 +Provides: bundled(crate(once_cell)) = 1.19.0 +Provides: bundled(crate(openssl)) = 0.10.62 Provides: bundled(crate(openssl-macros)) = 0.1.1 -Provides: bundled(crate(openssl-sys)) = 0.9.90 +Provides: bundled(crate(openssl-sys)) = 0.9.98 Provides: bundled(crate(parking_lot)) = 0.11.2 Provides: bundled(crate(parking_lot_core)) = 0.8.6 Provides: bundled(crate(paste)) = 0.1.18 Provides: bundled(crate(paste-impl)) = 0.1.18 -Provides: bundled(crate(pin-project-lite)) = 0.2.10 -Provides: bundled(crate(pkg-config)) = 0.3.27 +Provides: bundled(crate(pin-project-lite)) = 0.2.13 +Provides: bundled(crate(pkg-config)) = 0.3.28 Provides: bundled(crate(ppv-lite86)) = 0.2.17 Provides: bundled(crate(proc-macro-hack)) = 0.5.20+deprecated -Provides: bundled(crate(proc-macro2)) = 1.0.64 +Provides: bundled(crate(proc-macro2)) = 1.0.76 Provides: bundled(crate(pwdchan)) = 0.1.0 -Provides: bundled(crate(quote)) = 1.0.29 +Provides: bundled(crate(quote)) = 1.0.35 Provides: bundled(crate(rand)) = 0.8.5 Provides: bundled(crate(rand_chacha)) = 0.3.1 Provides: bundled(crate(rand_core)) = 0.6.4 Provides: bundled(crate(redox_syscall)) = 0.2.16 -Provides: bundled(crate(redox_syscall)) = 0.3.5 +Provides: bundled(crate(redox_syscall)) = 0.4.1 Provides: bundled(crate(rsds)) = 0.1.0 Provides: bundled(crate(rustc-demangle)) = 0.1.23 -Provides: bundled(crate(rustix)) = 0.37.23 -Provides: bundled(crate(ryu)) = 1.0.14 -Provides: bundled(crate(scopeguard)) = 1.1.0 -Provides: bundled(crate(serde)) = 1.0.171 -Provides: bundled(crate(serde_derive)) = 1.0.171 -Provides: bundled(crate(serde_json)) = 1.0.100 +Provides: bundled(crate(rustix)) = 0.38.30 +Provides: bundled(crate(ryu)) = 1.0.16 +Provides: bundled(crate(scopeguard)) = 1.2.0 +Provides: bundled(crate(serde)) = 1.0.195 +Provides: bundled(crate(serde_derive)) = 1.0.195 +Provides: bundled(crate(serde_json)) = 1.0.111 Provides: bundled(crate(slapd)) = 0.1.0 Provides: bundled(crate(slapi_r_plugin)) = 0.1.0 -Provides: bundled(crate(smallvec)) = 1.11.0 +Provides: bundled(crate(smallvec)) = 1.12.0 Provides: bundled(crate(strsim)) = 0.8.0 Provides: bundled(crate(syn)) = 1.0.109 -Provides: bundled(crate(syn)) = 2.0.25 -Provides: bundled(crate(tempfile)) = 3.6.0 +Provides: bundled(crate(syn)) = 2.0.48 +Provides: bundled(crate(tempfile)) = 3.9.0 Provides: bundled(crate(textwrap)) = 0.11.0 -Provides: bundled(crate(tokio)) = 1.29.1 -Provides: bundled(crate(tokio-macros)) = 2.1.0 +Provides: bundled(crate(tokio)) = 1.35.1 +Provides: bundled(crate(tokio-macros)) = 2.2.0 Provides: bundled(crate(toml)) = 0.5.11 -Provides: bundled(crate(unicode-ident)) = 1.0.10 -Provides: bundled(crate(unicode-width)) = 0.1.10 +Provides: bundled(crate(unicode-ident)) = 1.0.12 +Provides: bundled(crate(unicode-width)) = 0.1.11 Provides: bundled(crate(uuid)) = 0.8.2 Provides: bundled(crate(vcpkg)) = 0.2.15 Provides: bundled(crate(vec_map)) = 0.8.2 @@ -156,16 +153,16 @@ Provides: bundled(crate(wasi)) = 0.11.0+wasi_snapshot_preview1 Provides: bundled(crate(winapi)) = 0.3.9 Provides: bundled(crate(winapi-i686-pc-windows-gnu)) = 0.4.0 Provides: bundled(crate(winapi-x86_64-pc-windows-gnu)) = 0.4.0 -Provides: bundled(crate(windows-sys)) = 0.48.0 -Provides: bundled(crate(windows-targets)) = 0.48.1 -Provides: bundled(crate(windows_aarch64_gnullvm)) = 0.48.0 -Provides: bundled(crate(windows_aarch64_msvc)) = 0.48.0 -Provides: bundled(crate(windows_i686_gnu)) = 0.48.0 -Provides: bundled(crate(windows_i686_msvc)) = 0.48.0 -Provides: bundled(crate(windows_x86_64_gnu)) = 0.48.0 -Provides: bundled(crate(windows_x86_64_gnullvm)) = 0.48.0 -Provides: bundled(crate(windows_x86_64_msvc)) = 0.48.0 -Provides: bundled(crate(zeroize)) = 1.6.0 +Provides: bundled(crate(windows-sys)) = 0.52.0 +Provides: bundled(crate(windows-targets)) = 0.52.0 +Provides: bundled(crate(windows_aarch64_gnullvm)) = 0.52.0 +Provides: bundled(crate(windows_aarch64_msvc)) = 0.52.0 +Provides: bundled(crate(windows_i686_gnu)) = 0.52.0 +Provides: bundled(crate(windows_i686_msvc)) = 0.52.0 +Provides: bundled(crate(windows_x86_64_gnu)) = 0.52.0 +Provides: bundled(crate(windows_x86_64_gnullvm)) = 0.52.0 +Provides: bundled(crate(windows_x86_64_msvc)) = 0.52.0 +Provides: bundled(crate(zeroize)) = 1.7.0 Provides: bundled(crate(zeroize_derive)) = 1.4.2 ##### Bundled cargo crates list - END ##### @@ -296,9 +293,11 @@ Source4: vendor-%{version}-1.tar.gz Source5: Cargo-%{version}-1.lock %endif -Patch01: 0001-Issue-5870-ns-slapd-crashes-at-startup-if-a-backend-.patch -Patch02: 0001-Issue-5984-Crash-when-paged-result-search-are-abando.patch -Patch03: 0002-Issue-5984-Crash-when-paged-result-search-are-abando.patch +Patch01: 0001-issue-5647-covscan-memory-leak-in-audit-log-when-add.patch +Patch02: 0002-Issue-5647-Fix-unused-variable-warning-from-previous.patch +Patch03: 0003-Issue-5407-sync_repl-crashes-if-enabled-while-dynami.patch +Patch04: 0004-Issue-5547-automember-plugin-improvements.patch +Patch05: 0001-Issue-3527-Support-HAProxy-and-Instance-on-the-same-.patch %description 389 Directory Server is an LDAPv3 compliant server. The base package includes @@ -920,13 +919,32 @@ exit 0 %doc README.md %changelog -* Sun Dec 03 2023 James Chapman - 1.4.3.37-2 -- Bump version to 1.4.3.37-2 -- Resolves: RHEL-12710 bdb_start - Detected Disorderly Shutdown directory server is not starting -- Resolves: RHEL-16822 ns-slapd crash in slapi_attr_basetype +* Thu Mar 14 2024 Simon Pichugin - 1.4.3.39-3 +- Bump version to 1.4.3.39-3 +- Resolves: RHEL-19240 - RFE Add PROXY protocol support to 389-ds-base via confiuration item - similar to Postfix + +* Mon Feb 05 2024 Thierry Bordaz - 1.4.3.39-2 +- Bump version to 1.4.3.39-2 +- Resolves: RHEL-23209 - CVE-2024-1062 389-ds:1.4/389-ds-base: a heap overflow leading to denail-of-servce while writing a value larger than 256 chars (in log_entry_attr) +- Resolves: RHEL-5390 - schema-compat-plugin expensive with automember rebuild +- Resolves: RHEL-5135 - crash in sync_update_persist_op() of content sync plugin + +* Tue Jan 16 2024 Simon Pichugin - 1.4.3.39-1 +- Bump version to 1.4.3.39-1 +- Resolves: RHEL-19028 - Rebase 389-ds-base in RHEL 8.10 to 1.4.3.39 +- Resolves: RHEL-19240 - [RFE] Add PROXY protocol support to 389-ds-base +- Resolves: RHEL-5143 - SELinux labeling for dirsrv files seen during ipa install/uninstall should be moved to DEBUG. +- Resolves: RHEL-5107 - bdb_start - Detected Disorderly Shutdown directory server is not starting +- Resolves: RHEL-16338 - ns-slapd crash in slapi_attr_basetype +- Resolves: RHEL-14025 - After an upgrade the LDAP server won't start if nsslapd-conntablesize is present in the dse.ldif file. + + +* Fri Dec 08 2023 James Chapman - 1.4.3.38-1 +- Bump version to 1.4.3.38-1 +- Resolves: RHEL-19028 - Rebase 389-ds-base in RHEL 8.10 to 1.4.3.38 * Wed Aug 16 2023 Mark Reynolds - 1.4.3.37-1 -- Bump version to 1.4.3.37-1 +- Bump versionto 1.4.3.37-1 - Resolves: rhbz#2224505 - Paged search impacts performance - Resolves: rhbz#2220890 - healthcheck tool needs to be updates for new default password storage scheme - Resolves: rhbz#2218235 - python3-lib389: Python tarfile extraction needs change to avoid a warning