import 389-ds-base-1.4.3.23-7.module+el8.5.0+11979+655d714b

This commit is contained in:
CentOS Sources 2021-08-16 19:11:09 +00:00 committed by Andrew Lukoshko
parent 3e0d9e8a55
commit 9ad1a01ffd
18 changed files with 3019 additions and 2 deletions

View File

@ -1,2 +1,3 @@
c69c175a2f27053dffbfefac9c84ff16c7ff4cbf SOURCES/389-ds-base-1.4.3.23.tar.bz2
9e06b5cc57fd185379d007696da153893cf73e30 SOURCES/jemalloc-5.2.1.tar.bz2
22b1ef11852864027e184bb4bee56286b855b703 SOURCES/vendor-1.4.3.23-2.tar.gz

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
SOURCES/389-ds-base-1.4.3.23.tar.bz2
SOURCES/jemalloc-5.2.1.tar.bz2
SOURCES/vendor-1.4.3.23-2.tar.gz

View File

@ -0,0 +1,52 @@
From bc41bbb89405b2059b80e344b2d4c59ae39aabe6 Mon Sep 17 00:00:00 2001
From: tbordaz <tbordaz@redhat.com>
Date: Thu, 10 Jun 2021 15:03:27 +0200
Subject: [PATCH 1/3] Issue 4797 - ACL IP ADDRESS evaluation may corrupt
c_isreplication_session connection flags (#4799)
Bug description:
The fix for ticket #3764 was broken with a missing break in a
switch. The consequence is that while setting the client IP
address in the pblock (SLAPI_CONN_CLIENTNETADDR_ACLIP), the
connection is erroneously set as replication connection.
This can lead to crash or failure of testcase
test_access_from_certain_network_only_ip.
This bug was quite hidden until the fix for #4764 is
showing it more frequently
Fix description:
Add the missing break
relates: https://github.com/389ds/389-ds-base/issues/4797
Reviewed by: Mark Reynolds
Platforms tested: F33
---
ldap/servers/slapd/pblock.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index fcac53839..a64986aeb 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -2595,7 +2595,7 @@ slapi_pblock_set(Slapi_PBlock *pblock, int arg, void *value)
pblock->pb_conn->c_authtype = slapi_ch_strdup((char *)value);
pthread_mutex_unlock(&(pblock->pb_conn->c_mutex));
break;
- case SLAPI_CONN_CLIENTNETADDR_ACLIP:
+ case SLAPI_CONN_CLIENTNETADDR_ACLIP:
if (pblock->pb_conn == NULL) {
break;
}
@@ -2603,6 +2603,7 @@ slapi_pblock_set(Slapi_PBlock *pblock, int arg, void *value)
slapi_ch_free((void **)&pblock->pb_conn->cin_addr_aclip);
pblock->pb_conn->cin_addr_aclip = (PRNetAddr *)value;
pthread_mutex_unlock(&(pblock->pb_conn->c_mutex));
+ break;
case SLAPI_CONN_IS_REPLICATION_SESSION:
if (pblock->pb_conn == NULL) {
slapi_log_err(SLAPI_LOG_ERR,
--
2.31.1

View File

@ -0,0 +1,79 @@
From b3170e39519530c39d59202413b20e6bd466224d Mon Sep 17 00:00:00 2001
From: James Chapman <jachapma@redhat.com>
Date: Wed, 27 Jan 2021 09:56:38 +0000
Subject: [PATCH 2/3] Issue 4396 - Minor memory leak in backend (#4558) (#4572)
Bug Description: As multiple suffixes per backend were no longer used, this
functionality has been replaced with a single suffix per backend. Legacy
code remains that adds multiple suffixes to the dse internal backend,
resulting in memory allocations that are lost.
Also a minor typo is corrected in backend.c
Fix Description: Calls to be_addsuffix on the DSE backend are removed
as they are never used.
Fixes: https://github.com/389ds/389-ds-base/issues/4396
Reviewed by: mreynolds389, Firstyear, droideck (Thank you)
---
ldap/servers/slapd/backend.c | 2 +-
ldap/servers/slapd/fedse.c | 12 +++---------
2 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/ldap/servers/slapd/backend.c b/ldap/servers/slapd/backend.c
index bc52b4643..5707504a9 100644
--- a/ldap/servers/slapd/backend.c
+++ b/ldap/servers/slapd/backend.c
@@ -42,7 +42,7 @@ be_init(Slapi_Backend *be, const char *type, const char *name, int isprivate, in
}
be->be_monitordn = slapi_create_dn_string("cn=monitor,cn=%s,cn=%s,cn=plugins,cn=config",
name, type);
- if (NULL == be->be_configdn) {
+ if (NULL == be->be_monitordn) {
slapi_log_err(SLAPI_LOG_ERR,
"be_init", "Failed create instance monitor dn for "
"plugin %s, instance %s\n",
diff --git a/ldap/servers/slapd/fedse.c b/ldap/servers/slapd/fedse.c
index 0d645f909..7b820b540 100644
--- a/ldap/servers/slapd/fedse.c
+++ b/ldap/servers/slapd/fedse.c
@@ -2827,7 +2827,7 @@ search_snmp(Slapi_PBlock *pb __attribute__((unused)),
}
/*
- * Called from config.c to install the internal backends
+ * Called from main.c to install the internal backends
*/
int
setup_internal_backends(char *configdir)
@@ -2846,7 +2846,6 @@ setup_internal_backends(char *configdir)
Slapi_DN counters;
Slapi_DN snmp;
Slapi_DN root;
- Slapi_Backend *be;
Slapi_DN encryption;
Slapi_DN saslmapping;
Slapi_DN plugins;
@@ -2895,16 +2894,11 @@ setup_internal_backends(char *configdir)
dse_register_callback(pfedse, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, &saslmapping, LDAP_SCOPE_SUBTREE, "(objectclass=nsSaslMapping)", sasl_map_config_add, NULL, NULL);
dse_register_callback(pfedse, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, &plugins, LDAP_SCOPE_SUBTREE, "(objectclass=nsSlapdPlugin)", check_plugin_path, NULL, NULL);
- be = be_new_internal(pfedse, "DSE", DSE_BACKEND, &fedse_plugin);
- be_addsuffix(be, &root);
- be_addsuffix(be, &monitor);
- be_addsuffix(be, &config);
+ be_new_internal(pfedse, "DSE", DSE_BACKEND, &fedse_plugin);
/*
- * Now that the be's are in place, we can
- * setup the mapping tree.
+ * Now that the be's are in place, we can setup the mapping tree.
*/
-
if (mapping_tree_init()) {
slapi_log_err(SLAPI_LOG_EMERG, "setup_internal_backends", "Failed to init mapping tree\n");
exit(1);
--
2.31.1

View File

@ -0,0 +1,66 @@
From 8d06fdf44b0d337f1e321e61ee1b22972ddea917 Mon Sep 17 00:00:00 2001
From: tbordaz <tbordaz@redhat.com>
Date: Fri, 2 Apr 2021 14:05:41 +0200
Subject: [PATCH 3/3] Issue 4700 - Regression in winsync replication agreement
(#4712)
Bug description:
#4396 fixes a memory leak but did not set 'cn=config' as
DSE backend.
It had no signicant impact unless with sidgen IPA plugin
Fix description:
revert the portion of the #4364 patch that set be_suffix
in be_addsuffix, free the suffix before setting it
relates: https://github.com/389ds/389-ds-base/issues/4700
Reviewed by: Pierre Rogier (thanks !)
Platforms tested: F33
---
ldap/servers/slapd/backend.c | 3 ++-
ldap/servers/slapd/fedse.c | 6 +++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/ldap/servers/slapd/backend.c b/ldap/servers/slapd/backend.c
index 5707504a9..5db706841 100644
--- a/ldap/servers/slapd/backend.c
+++ b/ldap/servers/slapd/backend.c
@@ -173,7 +173,8 @@ void
be_addsuffix(Slapi_Backend *be, const Slapi_DN *suffix)
{
if (be->be_state != BE_STATE_DELETED) {
- be->be_suffix = slapi_sdn_dup(suffix);;
+ slapi_sdn_free(&be->be_suffix);
+ be->be_suffix = slapi_sdn_dup(suffix);
}
}
diff --git a/ldap/servers/slapd/fedse.c b/ldap/servers/slapd/fedse.c
index 7b820b540..44159c991 100644
--- a/ldap/servers/slapd/fedse.c
+++ b/ldap/servers/slapd/fedse.c
@@ -2846,6 +2846,7 @@ setup_internal_backends(char *configdir)
Slapi_DN counters;
Slapi_DN snmp;
Slapi_DN root;
+ Slapi_Backend *be;
Slapi_DN encryption;
Slapi_DN saslmapping;
Slapi_DN plugins;
@@ -2894,7 +2895,10 @@ setup_internal_backends(char *configdir)
dse_register_callback(pfedse, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, &saslmapping, LDAP_SCOPE_SUBTREE, "(objectclass=nsSaslMapping)", sasl_map_config_add, NULL, NULL);
dse_register_callback(pfedse, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, &plugins, LDAP_SCOPE_SUBTREE, "(objectclass=nsSlapdPlugin)", check_plugin_path, NULL, NULL);
- be_new_internal(pfedse, "DSE", DSE_BACKEND, &fedse_plugin);
+ be = be_new_internal(pfedse, "DSE", DSE_BACKEND, &fedse_plugin);
+ be_addsuffix(be, &root);
+ be_addsuffix(be, &monitor);
+ be_addsuffix(be, &config);
/*
* Now that the be's are in place, we can setup the mapping tree.
--
2.31.1

View File

@ -0,0 +1,88 @@
From 7345c51c68dfd90a704ccbb0e5b1e736af80f146 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Mon, 17 May 2021 16:10:22 +0200
Subject: [PATCH] Issue 4725 - Fix compiler warnings
---
ldap/servers/slapd/proto-slap.h | 2 +-
ldap/servers/slapd/pw.c | 9 ++++-----
ldap/servers/slapd/pw_retry.c | 2 --
3 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 6ff178127..2768d5a1d 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1012,7 +1012,7 @@ int add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e);
* pw_retry.c
*/
int update_pw_retry(Slapi_PBlock *pb);
-int update_trp_pw_usecount(Slapi_PBlock *pb, Slapi_Entry *e, int32_t use_count);
+int update_tpr_pw_usecount(Slapi_PBlock *pb, Slapi_Entry *e, int32_t use_count);
void pw_apply_mods(const Slapi_DN *sdn, Slapi_Mods *mods);
void pw_set_componentID(struct slapi_componentid *cid);
struct slapi_componentid *pw_get_componentID(void);
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index d98422513..2a167c8f1 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -2622,7 +2622,6 @@ int
slapi_check_tpr_limits(Slapi_PBlock *pb, Slapi_Entry *bind_target_entry, int send_result) {
passwdPolicy *pwpolicy = NULL;
char *dn = NULL;
- int tpr_maxuse;
char *value;
time_t cur_time;
char *cur_time_str = NULL;
@@ -2638,7 +2637,7 @@ slapi_check_tpr_limits(Slapi_PBlock *pb, Slapi_Entry *bind_target_entry, int sen
return 0;
}
- if (slapi_entry_attr_hasvalue(bind_target_entry, "pwdTPRReset", "TRUE") == NULL) {
+ if (!slapi_entry_attr_hasvalue(bind_target_entry, "pwdTPRReset", "TRUE")) {
/* the password was not reset by an admin while a TRP pwp was set, just returned */
return 0;
}
@@ -2646,7 +2645,7 @@ slapi_check_tpr_limits(Slapi_PBlock *pb, Slapi_Entry *bind_target_entry, int sen
/* Check entry TPR max use */
if (pwpolicy->pw_tpr_maxuse >= 0) {
uint use_count;
- value = slapi_entry_attr_get_ref(bind_target_entry, "pwdTPRUseCount");
+ value = (char *) slapi_entry_attr_get_ref(bind_target_entry, "pwdTPRUseCount");
if (value) {
/* max Use is enforced */
use_count = strtoull(value, 0, 0);
@@ -2681,7 +2680,7 @@ slapi_check_tpr_limits(Slapi_PBlock *pb, Slapi_Entry *bind_target_entry, int sen
/* Check entry TPR expiration at a specific time */
if (pwpolicy->pw_tpr_delay_expire_at >= 0) {
- value = slapi_entry_attr_get_ref(bind_target_entry, "pwdTPRExpireAt");
+ value = (char *) slapi_entry_attr_get_ref(bind_target_entry, "pwdTPRExpireAt");
if (value) {
/* max Use is enforced */
if (difftime(parse_genTime(cur_time_str), parse_genTime(value)) >= 0) {
@@ -2709,7 +2708,7 @@ slapi_check_tpr_limits(Slapi_PBlock *pb, Slapi_Entry *bind_target_entry, int sen
/* Check entry TPR valid after a specific time */
if (pwpolicy->pw_tpr_delay_valid_from >= 0) {
- value = slapi_entry_attr_get_ref(bind_target_entry, "pwdTPRValidFrom");
+ value = (char *) slapi_entry_attr_get_ref(bind_target_entry, "pwdTPRValidFrom");
if (value) {
/* validity after a specific time is enforced */
if (difftime(parse_genTime(value), parse_genTime(cur_time_str)) >= 0) {
diff --git a/ldap/servers/slapd/pw_retry.c b/ldap/servers/slapd/pw_retry.c
index 5d13eb636..af54aa19d 100644
--- a/ldap/servers/slapd/pw_retry.c
+++ b/ldap/servers/slapd/pw_retry.c
@@ -163,8 +163,6 @@ set_retry_cnt_and_time(Slapi_PBlock *pb, int count, time_t cur_time)
int
set_tpr_usecount_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count)
{
- char *timestr;
- time_t unlock_time;
char retry_cnt[16] = {0}; /* 1-65535 */
const char *dn = NULL;
Slapi_DN *sdn = NULL;
--
2.31.1

View File

@ -0,0 +1,202 @@
From 59266365eda8130abf6901263efae4c87586376a Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Mon, 28 Jun 2021 16:40:15 +0200
Subject: [PATCH] Issue 4814 - _cl5_get_tod_expiration may crash at startup
Bug description:
This bug exist only in 1.4.3 branch
In 1.4.3, CL open as a separated database so
compaction mechanism is started along a CL
mechanism (CL trimming).
The problem is that the configuration of the CL
compaction is done after the compaction mechanism
(is started). Depending on thread scheduling it
crashes
Fix description:
Make sure configuration of compaction thread is
taken into account (cl5ConfigSetCompaction) before
the compaction thread starts (cl5open)
relates: https://github.com/389ds/389-ds-base/issues/4814
Reviewed by: Mark Reynolds, Simon Pichugin (thanks !)
Platforms tested: 8.5
---
ldap/servers/plugins/replication/cl5_api.c | 24 ++++++++++++-------
ldap/servers/plugins/replication/cl5_api.h | 10 +++++++-
ldap/servers/plugins/replication/cl5_config.c | 8 +++++--
ldap/servers/plugins/replication/cl5_init.c | 4 +++-
ldap/servers/plugins/replication/cl5_test.c | 2 +-
.../servers/plugins/replication/repl_shared.h | 2 +-
6 files changed, 35 insertions(+), 15 deletions(-)
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 4c5077b48..954b6b9e3 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -1016,6 +1016,20 @@ cl5GetState()
return s_cl5Desc.dbState;
}
+void
+cl5ConfigSetCompaction(int compactInterval, char *compactTime)
+{
+
+ if (compactInterval != CL5_NUM_IGNORE) {
+ s_cl5Desc.dbTrim.compactInterval = compactInterval;
+ }
+
+ if (strcmp(compactTime, CL5_STR_IGNORE) != 0) {
+ s_cl5Desc.dbTrim.compactTime = slapi_ch_strdup(compactTime);
+ }
+
+}
+
/* Name: cl5ConfigTrimming
Description: sets changelog trimming parameters; changelog must be open.
Parameters: maxEntries - maximum number of entries in the chnagelog (in all files);
@@ -1026,7 +1040,7 @@ cl5GetState()
CL5_BAD_STATE if changelog is not open
*/
int
-cl5ConfigTrimming(int maxEntries, const char *maxAge, int compactInterval, char *compactTime, int trimInterval)
+cl5ConfigTrimming(int maxEntries, const char *maxAge, int trimInterval)
{
if (s_cl5Desc.dbState == CL5_STATE_NONE) {
slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
@@ -1058,14 +1072,6 @@ cl5ConfigTrimming(int maxEntries, const char *maxAge, int compactInterval, char
s_cl5Desc.dbTrim.maxEntries = maxEntries;
}
- if (compactInterval != CL5_NUM_IGNORE) {
- s_cl5Desc.dbTrim.compactInterval = compactInterval;
- }
-
- if (strcmp(compactTime, CL5_STR_IGNORE) != 0) {
- s_cl5Desc.dbTrim.compactTime = slapi_ch_strdup(compactTime);
- }
-
if (trimInterval != CL5_NUM_IGNORE) {
s_cl5Desc.dbTrim.trimInterval = trimInterval;
}
diff --git a/ldap/servers/plugins/replication/cl5_api.h b/ldap/servers/plugins/replication/cl5_api.h
index 11db771f2..6aa48aec4 100644
--- a/ldap/servers/plugins/replication/cl5_api.h
+++ b/ldap/servers/plugins/replication/cl5_api.h
@@ -227,6 +227,14 @@ int cl5ImportLDIF(const char *clDir, const char *ldifFile, Replica **replicas);
int cl5GetState(void);
+/* Name: cl5ConfigSetCompaction
+ * Description: sets the database compaction parameters
+ * Parameters: compactInterval - Interval for compaction default is 30days
+ * compactTime - Compact time default is 23:59
+ * Return: void
+ */
+void cl5ConfigSetCompaction(int compactInterval, char *compactTime);
+
/* Name: cl5ConfigTrimming
Description: sets changelog trimming parameters
Parameters: maxEntries - maximum number of entries in the log;
@@ -236,7 +244,7 @@ int cl5GetState(void);
Return: CL5_SUCCESS if successful;
CL5_BAD_STATE if changelog has not been open
*/
-int cl5ConfigTrimming(int maxEntries, const char *maxAge, int compactInterval, char *compactTime, int trimInterval);
+int cl5ConfigTrimming(int maxEntries, const char *maxAge, int trimInterval);
void cl5DestroyIterator(void *iterator);
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index b32686788..a43534c9b 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -197,6 +197,8 @@ changelog5_config_add(Slapi_PBlock *pb __attribute__((unused)),
goto done;
}
+ /* Set compaction parameters */
+ cl5ConfigSetCompaction(config.compactInterval, config.compactTime);
/* start the changelog */
rc = cl5Open(config.dir, &config.dbconfig);
@@ -212,7 +214,7 @@ changelog5_config_add(Slapi_PBlock *pb __attribute__((unused)),
}
/* set trimming parameters */
- rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.compactInterval, config.compactTime, config.trimInterval);
+ rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.trimInterval);
if (rc != CL5_SUCCESS) {
*returncode = 1;
if (returntext) {
@@ -548,6 +550,8 @@ changelog5_config_modify(Slapi_PBlock *pb,
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
"changelog5_config_modify - Deleted the changelog at %s\n", currentDir);
}
+ /* Set compaction parameters */
+ cl5ConfigSetCompaction(config.compactInterval, config.compactTime);
rc = cl5Open(config.dir, &config.dbconfig);
if (rc != CL5_SUCCESS) {
@@ -575,7 +579,7 @@ changelog5_config_modify(Slapi_PBlock *pb,
if (config.maxEntries != CL5_NUM_IGNORE ||
config.trimInterval != CL5_NUM_IGNORE ||
strcmp(config.maxAge, CL5_STR_IGNORE) != 0) {
- rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.compactInterval, config.compactTime, config.trimInterval);
+ rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.trimInterval);
if (rc != CL5_SUCCESS) {
*returncode = 1;
if (returntext) {
diff --git a/ldap/servers/plugins/replication/cl5_init.c b/ldap/servers/plugins/replication/cl5_init.c
index 251859714..567e0274c 100644
--- a/ldap/servers/plugins/replication/cl5_init.c
+++ b/ldap/servers/plugins/replication/cl5_init.c
@@ -45,6 +45,8 @@ changelog5_init()
rc = 0; /* OK */
goto done;
}
+ /* Set compaction parameters */
+ cl5ConfigSetCompaction(config.compactInterval, config.compactTime);
/* start changelog */
rc = cl5Open(config.dir, &config.dbconfig);
@@ -57,7 +59,7 @@ changelog5_init()
}
/* set trimming parameters */
- rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.compactInterval, config.compactTime, config.trimInterval);
+ rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.trimInterval);
if (rc != CL5_SUCCESS) {
slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
"changelog5_init: failed to configure changelog trimming\n");
diff --git a/ldap/servers/plugins/replication/cl5_test.c b/ldap/servers/plugins/replication/cl5_test.c
index d6656653c..efb8c543a 100644
--- a/ldap/servers/plugins/replication/cl5_test.c
+++ b/ldap/servers/plugins/replication/cl5_test.c
@@ -281,7 +281,7 @@ testTrimming()
rc = populateChangelog(300, NULL);
if (rc == 0)
- rc = cl5ConfigTrimming(300, "1d", CHANGELOGDB_COMPACT_INTERVAL, CHANGELOGDB_TRIM_INTERVAL);
+ rc = cl5ConfigTrimming(300, "1d", CHANGELOGDB_TRIM_INTERVAL);
interval = PR_SecondsToInterval(300); /* 5 min is default trimming interval */
slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
diff --git a/ldap/servers/plugins/replication/repl_shared.h b/ldap/servers/plugins/replication/repl_shared.h
index 6708e12f7..b59b2bd27 100644
--- a/ldap/servers/plugins/replication/repl_shared.h
+++ b/ldap/servers/plugins/replication/repl_shared.h
@@ -26,7 +26,7 @@
#define CHANGELOGDB_TRIM_INTERVAL 300 /* 5 minutes */
#define CHANGELOGDB_COMPACT_INTERVAL 2592000 /* 30 days */
-#define CHANGELOGDB_COMPACT_TIME "23:55" /* 30 days */
+#define CHANGELOGDB_COMPACT_TIME "23:59" /* around midnight */
#define CONFIG_CHANGELOG_DIR_ATTRIBUTE "nsslapd-changelogdir"
#define CONFIG_CHANGELOG_MAXENTRIES_ATTRIBUTE "nsslapd-changelogmaxentries"
--
2.31.1

View File

@ -0,0 +1,51 @@
From e7fdfe527a5f72674fe4b577a0555cabf8ec73a5 Mon Sep 17 00:00:00 2001
From: tbordaz <tbordaz@redhat.com>
Date: Mon, 7 Jun 2021 11:23:35 +0200
Subject: [PATCH] Issue 4789 - Temporary password rules are not enforce with
local password policy (#4790)
Bug description:
When allocating a password policy structure (new_passwdPolicy)
it is initialized with the local policy definition or
the global one. If it exists a local policy entry, the TPR
attributes (passwordTPRMaxUse, passwordTPRDelayValidFrom and
passwordTPRDelayExpireAt) are not taken into account.
Fix description:
Take into account TPR attributes to initialize the policy
relates: https://github.com/389ds/389-ds-base/issues/4789
Reviewed by: Simon Pichugin, William Brown
Platforms tested: F34
---
ldap/servers/slapd/pw.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 2a167c8f1..7680df41d 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -2356,6 +2356,18 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
if ((sval = attr_get_present_values(attr))) {
pwdpolicy->pw_dict_path = (char *)slapi_value_get_string(*sval);
}
+ } else if (!strcasecmp(attr_name, CONFIG_PW_TPR_MAXUSE)) {
+ if ((sval = attr_get_present_values(attr))) {
+ pwdpolicy->pw_tpr_maxuse = slapi_value_get_int(*sval);
+ }
+ } else if (!strcasecmp(attr_name, CONFIG_PW_TPR_DELAY_EXPIRE_AT)) {
+ if ((sval = attr_get_present_values(attr))) {
+ pwdpolicy->pw_tpr_delay_expire_at = slapi_value_get_int(*sval);
+ }
+ } else if (!strcasecmp(attr_name, CONFIG_PW_TPR_DELAY_VALID_FROM)) {
+ if ((sval = attr_get_present_values(attr))) {
+ pwdpolicy->pw_tpr_delay_valid_from = slapi_value_get_int(*sval);
+ }
}
} /* end of for() loop */
if (pw_entry) {
--
2.31.1

View File

@ -0,0 +1,350 @@
From 6a741b3ef50babf2ac2479437a38829204ffd438 Mon Sep 17 00:00:00 2001
From: tbordaz <tbordaz@redhat.com>
Date: Thu, 17 Jun 2021 16:22:09 +0200
Subject: [PATCH] Issue 4788 - CLI should support Temporary Password Rules
attributes (#4793)
Bug description:
Since #4725, password policy support temporary password rules.
CLI (dsconf) does not support this RFE and only direct ldap
operation can configure global/local password policy
Fix description:
Update dsconf to support this new RFE.
To run successfully the testcase it relies on #4788
relates: #4788
Reviewed by: Simon Pichugin (thanks !!)
Platforms tested: F34
---
.../password/pwdPolicy_attribute_test.py | 172 ++++++++++++++++--
src/lib389/lib389/cli_conf/pwpolicy.py | 5 +-
src/lib389/lib389/pwpolicy.py | 5 +-
3 files changed, 165 insertions(+), 17 deletions(-)
diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
index aee3a91ad..085d0a373 100644
--- a/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
+++ b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
@@ -34,7 +34,7 @@ log = logging.getLogger(__name__)
@pytest.fixture(scope="module")
-def create_user(topology_st, request):
+def test_user(topology_st, request):
"""User for binding operation"""
topology_st.standalone.config.set('nsslapd-auditlog-logging-enabled', 'on')
log.info('Adding test user {}')
@@ -56,10 +56,11 @@ def create_user(topology_st, request):
topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
request.addfinalizer(fin)
+ return user
@pytest.fixture(scope="module")
-def password_policy(topology_st, create_user):
+def password_policy(topology_st, test_user):
"""Set up password policy for subtree and user"""
pwp = PwPolicyManager(topology_st.standalone)
@@ -71,7 +72,7 @@ def password_policy(topology_st, create_user):
pwp.create_user_policy(TEST_USER_DN, policy_props)
@pytest.mark.skipif(ds_is_older('1.4.3.3'), reason="Not implemented")
-def test_pwd_reset(topology_st, create_user):
+def test_pwd_reset(topology_st, test_user):
"""Test new password policy attribute "pwdReset"
:id: 03db357b-4800-411e-a36e-28a534293004
@@ -124,7 +125,7 @@ def test_pwd_reset(topology_st, create_user):
[('on', 'off', ldap.UNWILLING_TO_PERFORM),
('off', 'off', ldap.UNWILLING_TO_PERFORM),
('off', 'on', False), ('on', 'on', False)])
-def test_change_pwd(topology_st, create_user, password_policy,
+def test_change_pwd(topology_st, test_user, password_policy,
subtree_pwchange, user_pwchange, exception):
"""Verify that 'passwordChange' attr works as expected
User should have a priority over a subtree.
@@ -184,7 +185,7 @@ def test_change_pwd(topology_st, create_user, password_policy,
user.reset_password(TEST_USER_PWD)
-def test_pwd_min_age(topology_st, create_user, password_policy):
+def test_pwd_min_age(topology_st, test_user, password_policy):
"""If we set passwordMinAge to some value, for example to 10, then it
should not allow the user to change the password within 10 seconds after
his previous change.
@@ -257,7 +258,7 @@ def test_pwd_min_age(topology_st, create_user, password_policy):
topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
user.reset_password(TEST_USER_PWD)
-def test_global_tpr_maxuse_1(topology_st, create_user, request):
+def test_global_tpr_maxuse_1(topology_st, test_user, request):
"""Test global TPR policy : passwordTPRMaxUse
Test that after passwordTPRMaxUse failures to bind
additional bind with valid password are failing with CONSTRAINT_VIOLATION
@@ -374,7 +375,7 @@ def test_global_tpr_maxuse_1(topology_st, create_user, request):
request.addfinalizer(fin)
-def test_global_tpr_maxuse_2(topology_st, create_user, request):
+def test_global_tpr_maxuse_2(topology_st, test_user, request):
"""Test global TPR policy : passwordTPRMaxUse
Test that after less than passwordTPRMaxUse failures to bind
additional bind with valid password are successfull
@@ -474,7 +475,7 @@ def test_global_tpr_maxuse_2(topology_st, create_user, request):
request.addfinalizer(fin)
-def test_global_tpr_maxuse_3(topology_st, create_user, request):
+def test_global_tpr_maxuse_3(topology_st, test_user, request):
"""Test global TPR policy : passwordTPRMaxUse
Test that after less than passwordTPRMaxUse failures to bind
A bind with valid password is successfull but passwordMustChange
@@ -587,7 +588,7 @@ def test_global_tpr_maxuse_3(topology_st, create_user, request):
request.addfinalizer(fin)
-def test_global_tpr_maxuse_4(topology_st, create_user, request):
+def test_global_tpr_maxuse_4(topology_st, test_user, request):
"""Test global TPR policy : passwordTPRMaxUse
Test that a TPR attribute passwordTPRMaxUse
can be updated by DM but not the by user itself
@@ -701,7 +702,148 @@ def test_global_tpr_maxuse_4(topology_st, create_user, request):
request.addfinalizer(fin)
-def test_global_tpr_delayValidFrom_1(topology_st, create_user, request):
+def test_local_tpr_maxuse_5(topology_st, test_user, request):
+ """Test TPR local policy overpass global one: passwordTPRMaxUse
+ Test that after passwordTPRMaxUse failures to bind
+ additional bind with valid password are failing with CONSTRAINT_VIOLATION
+
+ :id: c3919707-d804-445a-8754-8385b1072c42
+ :customerscenario: False
+ :setup: Standalone instance
+ :steps:
+ 1. Global password policy Enable passwordMustChange
+ 2. Global password policy Set passwordTPRMaxUse=5
+ 3. Global password policy Set passwordMaxFailure to a higher value to not disturb the test
+ 4. Local password policy Enable passwordMustChange
+ 5. Local password policy Set passwordTPRMaxUse=10 (higher than global)
+ 6. Bind with a wrong password 10 times and check INVALID_CREDENTIALS
+ 7. Check that passwordTPRUseCount got to the limit (5)
+ 8. Bind with a wrong password (CONSTRAINT_VIOLATION)
+ and check passwordTPRUseCount overpass the limit by 1 (11)
+ 9. Bind with a valid password 10 times and check CONSTRAINT_VIOLATION
+ and check passwordTPRUseCount increases
+ 10. Reset password policy configuration and remove local password from user
+ :expected results:
+ 1. Success
+ 2. Success
+ 3. Success
+ 4. Success
+ 5. Success
+ 6. Success
+ 7. Success
+ 8. Success
+ 9. Success
+ 10. Success
+ """
+
+ global_tpr_maxuse = 5
+ # Set global password policy config, passwordMaxFailure being higher than
+ # passwordTPRMaxUse so that TPR is enforced first
+ topology_st.standalone.config.replace('passwordMustChange', 'on')
+ topology_st.standalone.config.replace('passwordMaxFailure', str(global_tpr_maxuse + 20))
+ topology_st.standalone.config.replace('passwordTPRMaxUse', str(global_tpr_maxuse))
+ time.sleep(.5)
+
+ local_tpr_maxuse = global_tpr_maxuse + 5
+ # Reset user's password with a local password policy
+ # that has passwordTPRMaxUse higher than global
+ #our_user = UserAccount(topology_st.standalone, TEST_USER_DN)
+ subprocess.call(['%s/dsconf' % topology_st.standalone.get_sbin_dir(),
+ 'slapd-standalone1',
+ 'localpwp',
+ 'adduser',
+ test_user.dn])
+ subprocess.call(['%s/dsconf' % topology_st.standalone.get_sbin_dir(),
+ 'slapd-standalone1',
+ 'localpwp',
+ 'set',
+ '--pwptprmaxuse',
+ str(local_tpr_maxuse),
+ '--pwdmustchange',
+ 'on',
+ test_user.dn])
+ test_user.replace('userpassword', PASSWORD)
+ time.sleep(.5)
+
+ # look up to passwordTPRMaxUse with failing
+ # bind to check that the limits of TPR are enforced
+ for i in range(local_tpr_maxuse):
+ # Bind as user with a wrong password
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
+ test_user.rebind('wrong password')
+ time.sleep(.5)
+
+ # Check that pwdReset is TRUE
+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+ #assert test_user.get_attr_val_utf8('pwdReset') == 'TRUE'
+
+ # Check that pwdTPRReset is TRUE
+ assert test_user.get_attr_val_utf8('pwdTPRReset') == 'TRUE'
+ assert test_user.get_attr_val_utf8('pwdTPRUseCount') == str(i+1)
+ log.info("%dth failing bind (INVALID_CREDENTIALS) => pwdTPRUseCount = %d" % (i+1, i+1))
+
+
+ # Now the #failures reached passwordTPRMaxUse
+ # Check that pwdReset is TRUE
+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ # Check that pwdTPRReset is TRUE
+ assert test_user.get_attr_val_utf8('pwdTPRReset') == 'TRUE'
+ assert test_user.get_attr_val_utf8('pwdTPRUseCount') == str(local_tpr_maxuse)
+ log.info("last failing bind (INVALID_CREDENTIALS) => pwdTPRUseCount = %d" % (local_tpr_maxuse))
+
+ # Bind as user with wrong password --> ldap.CONSTRAINT_VIOLATION
+ with pytest.raises(ldap.CONSTRAINT_VIOLATION):
+ test_user.rebind("wrong password")
+ time.sleep(.5)
+
+ # Check that pwdReset is TRUE
+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ # Check that pwdTPRReset is TRUE
+ assert test_user.get_attr_val_utf8('pwdTPRReset') == 'TRUE'
+ assert test_user.get_attr_val_utf8('pwdTPRUseCount') == str(local_tpr_maxuse + 1)
+ log.info("failing bind (CONSTRAINT_VIOLATION) => pwdTPRUseCount = %d" % (local_tpr_maxuse + i))
+
+ # Now check that all next attempts with correct password are all in LDAP_CONSTRAINT_VIOLATION
+ # and passwordTPRRetryCount remains unchanged
+ # account is now similar to locked
+ for i in range(10):
+ # Bind as user with valid password
+ with pytest.raises(ldap.CONSTRAINT_VIOLATION):
+ test_user.rebind(PASSWORD)
+ time.sleep(.5)
+
+ # Check that pwdReset is TRUE
+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ # Check that pwdTPRReset is TRUE
+ # pwdTPRUseCount keeps increasing
+ assert test_user.get_attr_val_utf8('pwdTPRReset') == 'TRUE'
+ assert test_user.get_attr_val_utf8('pwdTPRUseCount') == str(local_tpr_maxuse + i + 2)
+ log.info("Rejected bind (CONSTRAINT_VIOLATION) => pwdTPRUseCount = %d" % (local_tpr_maxuse + i + 2))
+
+
+ def fin():
+ topology_st.standalone.restart()
+ # Reset password policy config
+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topology_st.standalone.config.replace('passwordMustChange', 'off')
+
+ # Remove local password policy from that entry
+ subprocess.call(['%s/dsconf' % topology_st.standalone.get_sbin_dir(),
+ 'slapd-standalone1',
+ 'localpwp',
+ 'remove',
+ test_user.dn])
+
+ # Reset user's password
+ test_user.replace('userpassword', TEST_USER_PWD)
+
+
+ request.addfinalizer(fin)
+
+def test_global_tpr_delayValidFrom_1(topology_st, test_user, request):
"""Test global TPR policy : passwordTPRDelayValidFrom
Test that a TPR password is not valid before reset time +
passwordTPRDelayValidFrom
@@ -766,7 +908,7 @@ def test_global_tpr_delayValidFrom_1(topology_st, create_user, request):
request.addfinalizer(fin)
-def test_global_tpr_delayValidFrom_2(topology_st, create_user, request):
+def test_global_tpr_delayValidFrom_2(topology_st, test_user, request):
"""Test global TPR policy : passwordTPRDelayValidFrom
Test that a TPR password is valid after reset time +
passwordTPRDelayValidFrom
@@ -838,7 +980,7 @@ def test_global_tpr_delayValidFrom_2(topology_st, create_user, request):
request.addfinalizer(fin)
-def test_global_tpr_delayValidFrom_3(topology_st, create_user, request):
+def test_global_tpr_delayValidFrom_3(topology_st, test_user, request):
"""Test global TPR policy : passwordTPRDelayValidFrom
Test that a TPR attribute passwordTPRDelayValidFrom
can be updated by DM but not the by user itself
@@ -940,7 +1082,7 @@ def test_global_tpr_delayValidFrom_3(topology_st, create_user, request):
request.addfinalizer(fin)
-def test_global_tpr_delayExpireAt_1(topology_st, create_user, request):
+def test_global_tpr_delayExpireAt_1(topology_st, test_user, request):
"""Test global TPR policy : passwordTPRDelayExpireAt
Test that a TPR password is not valid after reset time +
passwordTPRDelayExpireAt
@@ -1010,7 +1152,7 @@ def test_global_tpr_delayExpireAt_1(topology_st, create_user, request):
request.addfinalizer(fin)
-def test_global_tpr_delayExpireAt_2(topology_st, create_user, request):
+def test_global_tpr_delayExpireAt_2(topology_st, test_user, request):
"""Test global TPR policy : passwordTPRDelayExpireAt
Test that a TPR password is valid before reset time +
passwordTPRDelayExpireAt
@@ -1082,7 +1224,7 @@ def test_global_tpr_delayExpireAt_2(topology_st, create_user, request):
request.addfinalizer(fin)
-def test_global_tpr_delayExpireAt_3(topology_st, create_user, request):
+def test_global_tpr_delayExpireAt_3(topology_st, test_user, request):
"""Test global TPR policy : passwordTPRDelayExpireAt
Test that a TPR attribute passwordTPRDelayExpireAt
can be updated by DM but not the by user itself
diff --git a/src/lib389/lib389/cli_conf/pwpolicy.py b/src/lib389/lib389/cli_conf/pwpolicy.py
index 2838afcb8..26af6e7ec 100644
--- a/src/lib389/lib389/cli_conf/pwpolicy.py
+++ b/src/lib389/lib389/cli_conf/pwpolicy.py
@@ -255,6 +255,9 @@ def create_parser(subparsers):
set_parser.add_argument('--pwpinheritglobal', help="Set to \"on\" to allow local policies to inherit the global policy")
set_parser.add_argument('--pwddictcheck', help="Set to \"on\" to enforce CrackLib dictionary checking")
set_parser.add_argument('--pwddictpath', help="Filesystem path to specific/custom CrackLib dictionary files")
+ set_parser.add_argument('--pwptprmaxuse', help="Number of times a reset password can be used for authentication")
+ set_parser.add_argument('--pwptprdelayexpireat', help="Number of seconds after which a reset password expires")
+ set_parser.add_argument('--pwptprdelayvalidfrom', help="Number of seconds to wait before using a reset password to authenticated")
# delete local password policy
del_parser = local_subcommands.add_parser('remove', help='Remove a local password policy')
del_parser.set_defaults(func=del_local_policy)
@@ -291,4 +294,4 @@ def create_parser(subparsers):
#############################################
set_parser.add_argument('DN', nargs=1, help='Set the local policy for this entry DN')
add_subtree_parser.add_argument('DN', nargs=1, help='Add/replace the subtree policy for this entry DN')
- add_user_parser.add_argument('DN', nargs=1, help='Add/replace the local password policy for this entry DN')
\ No newline at end of file
+ add_user_parser.add_argument('DN', nargs=1, help='Add/replace the local password policy for this entry DN')
diff --git a/src/lib389/lib389/pwpolicy.py b/src/lib389/lib389/pwpolicy.py
index 8653cb195..d2427933b 100644
--- a/src/lib389/lib389/pwpolicy.py
+++ b/src/lib389/lib389/pwpolicy.py
@@ -65,7 +65,10 @@ class PwPolicyManager(object):
'pwddictcheck': 'passworddictcheck',
'pwddictpath': 'passworddictpath',
'pwdallowhash': 'nsslapd-allow-hashed-passwords',
- 'pwpinheritglobal': 'nsslapd-pwpolicy-inherit-global'
+ 'pwpinheritglobal': 'nsslapd-pwpolicy-inherit-global',
+ 'pwptprmaxuse': 'passwordTPRMaxUse',
+ 'pwptprdelayexpireat': 'passwordTPRDelayExpireAt',
+ 'pwptprdelayvalidfrom': 'passwordTPRDelayValidFrom'
}
def is_subtree_policy(self, dn):
--
2.31.1

View File

@ -0,0 +1,179 @@
From 7b7217538908ae58df864ef5cd82e1d3303c189f Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 7 Jun 2021 12:58:42 -0400
Subject: [PATCH] Issue 4447 - Crash when the Referential Integrity log is
manually edited
Bug Description: If the referint log is manually edited with a string
that is not a DN the server will crash when processing
the log.
Fix Description: Check for NULL pointers when strtoking the file line.
relates: https://github.com/389ds/389-ds-base/issues/4447
Reviewed by: firstyear(Thanks!)
---
.../tests/suites/plugins/referint_test.py | 72 +++++++++++++++----
ldap/servers/plugins/referint/referint.c | 7 ++
src/lib389/lib389/plugins.py | 15 ++++
3 files changed, 80 insertions(+), 14 deletions(-)
diff --git a/dirsrvtests/tests/suites/plugins/referint_test.py b/dirsrvtests/tests/suites/plugins/referint_test.py
index 02b985767..fda602545 100644
--- a/dirsrvtests/tests/suites/plugins/referint_test.py
+++ b/dirsrvtests/tests/suites/plugins/referint_test.py
@@ -1,5 +1,5 @@
# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2016 Red Hat, Inc.
+# Copyright (C) 2021 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
@@ -12,13 +12,11 @@ Created on Dec 12, 2019
@author: tbordaz
'''
import logging
-import subprocess
import pytest
from lib389 import Entry
-from lib389.utils import *
-from lib389.plugins import *
-from lib389._constants import *
-from lib389.idm.user import UserAccounts, UserAccount
+from lib389.plugins import ReferentialIntegrityPlugin
+from lib389._constants import DEFAULT_SUFFIX
+from lib389.idm.user import UserAccounts
from lib389.idm.group import Groups
from lib389.topologies import topology_st as topo
@@ -29,21 +27,27 @@ log = logging.getLogger(__name__)
ESCAPED_RDN_BASE = "foo\\,oo"
def _user_get_dn(no):
uid = '%s%d' % (ESCAPED_RDN_BASE, no)
- dn = 'uid=%s,%s' % (uid, SUFFIX)
+ dn = 'uid=%s,%s' % (uid, DEFAULT_SUFFIX)
return (uid, dn)
def add_escaped_user(server, no):
(uid, dn) = _user_get_dn(no)
log.fatal('Adding user (%s): ' % dn)
- server.add_s(Entry((dn, {'objectclass': ['top', 'person', 'organizationalPerson', 'inetOrgPerson'],
- 'uid': [uid],
- 'sn' : [uid],
- 'cn' : [uid]})))
+ users = UserAccounts(server, DEFAULT_SUFFIX, None)
+ user_properties = {
+ 'objectclass': ['top', 'person', 'organizationalPerson', 'inetOrgPerson', 'posixAccount'],
+ 'uid': uid,
+ 'cn' : uid,
+ 'sn' : uid,
+ 'uidNumber' : '1000',
+ 'gidNumber' : '2000',
+ 'homeDirectory' : '/home/testuser',
+ }
+ users.create(properties=user_properties)
return dn
-@pytest.mark.ds50020
def test_referential_false_failure(topo):
- """On MODRDN referential integrity can erronously fail
+ """On MODRDN referential integrity can erroneously fail
:id: f77aeb80-c4c4-471b-8c1b-4733b714778b
:setup: Standalone Instance
@@ -100,6 +104,46 @@ def test_referential_false_failure(topo):
inst.restart()
# Here if the bug is fixed, referential is able to update the member value
- inst.rename_s(user1.dn, 'uid=new_test_user_1001', newsuperior=SUFFIX, delold=0)
+ user1.rename('uid=new_test_user_1001', newsuperior=DEFAULT_SUFFIX, deloldrdn=False)
+def test_invalid_referint_log(topo):
+ """If there is an invalid log line in the referint log, make sure the server
+ does not crash at startup
+
+ :id: 34807b5a-ab17-4281-ae48-4e3513e19145
+ :setup: Standalone Instance
+ :steps:
+ 1. Set the referint log delay
+ 2. Create invalid log
+ 3. Start the server (no crash)
+ :expectedresults:
+ 1. Success
+ 2. Success
+ 3. Success
+ """
+
+ inst = topo.standalone
+
+ # Set delay - required for log parsing at server startup
+ plugin = ReferentialIntegrityPlugin(inst)
+ plugin.enable()
+ plugin.set_update_delay('2')
+ logfile = plugin.get_log_file()
+ inst.restart()
+
+ # Create invalid log
+ inst.stop()
+ with open(logfile, 'w') as log_fh:
+ log_fh.write("CRASH\n")
+
+ # Start the instance
+ inst.start()
+ assert inst.status()
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
diff --git a/ldap/servers/plugins/referint/referint.c b/ldap/servers/plugins/referint/referint.c
index fd5356d72..28240c1f6 100644
--- a/ldap/servers/plugins/referint/referint.c
+++ b/ldap/servers/plugins/referint/referint.c
@@ -1447,6 +1447,13 @@ referint_thread_func(void *arg __attribute__((unused)))
sdn = slapi_sdn_new_normdn_byref(ptoken);
ptoken = ldap_utf8strtok_r(NULL, delimiter, &iter);
+ if (ptoken == NULL) {
+ /* Invalid line in referint log, skip it */
+ slapi_log_err(SLAPI_LOG_ERR, REFERINT_PLUGIN_SUBSYSTEM,
+ "Skipping invalid referint log line: (%s)\n", thisline);
+ slapi_sdn_free(&sdn);
+ continue;
+ }
if (!strcasecmp(ptoken, "NULL")) {
tmprdn = NULL;
} else {
diff --git a/src/lib389/lib389/plugins.py b/src/lib389/lib389/plugins.py
index 2d88e60bd..b07e80022 100644
--- a/src/lib389/lib389/plugins.py
+++ b/src/lib389/lib389/plugins.py
@@ -518,6 +518,21 @@ class ReferentialIntegrityPlugin(Plugin):
self.set('referint-update-delay', str(value))
+ def get_log_file(self):
+ """Get referint log file"""
+
+ return self.get_attr_val_utf8('referint-logfile')
+
+ def get_log_file_formatted(self):
+ """Get referint log file"""
+
+ return self.display_attr('referint-logfile')
+
+ def set_log_file(self, value):
+ """Set referint log file"""
+
+ self.set('referint-logfile', value)
+
def get_membership_attr(self, formatted=False):
"""Get referint-membership-attr attribute"""
--
2.31.1

View File

@ -0,0 +1,114 @@
From 964a153b420b26140e0bbddfbebb4a51aaa0e4ea Mon Sep 17 00:00:00 2001
From: James Chapman <jachapma@redhat.com>
Date: Thu, 3 Jun 2021 15:16:22 +0000
Subject: [PATCH 1/7] Issue 4791 - Missing dependency for RetroCL RFE
Description: The RetroCL exclude attribute RFE is dependent on functionality of the
EntryUUID bug fix, that didn't make into the latest build. This breaks the
RetroCL exclude attr feature so we need to provide a workaround.
Fixes: https://github.com/389ds/389-ds-base/issues/4791
Relates: https://github.com/389ds/389-ds-base/pull/4723
Relates: https://github.com/389ds/389-ds-base/issues/4224
Reviewed by: tbordaz, droideck (Thank you)
---
.../tests/suites/retrocl/basic_test.py | 6 ++--
.../lib389/cli_conf/plugins/retrochangelog.py | 35 +++++++++++++++++--
2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/dirsrvtests/tests/suites/retrocl/basic_test.py b/dirsrvtests/tests/suites/retrocl/basic_test.py
index 112c73cb9..f3bc50f29 100644
--- a/dirsrvtests/tests/suites/retrocl/basic_test.py
+++ b/dirsrvtests/tests/suites/retrocl/basic_test.py
@@ -17,7 +17,7 @@ from lib389.utils import *
from lib389.tasks import *
from lib389.cli_base import FakeArgs, connect_instance, disconnect_instance
from lib389.cli_base.dsrc import dsrc_arg_concat
-from lib389.cli_conf.plugins.retrochangelog import retrochangelog_add
+from lib389.cli_conf.plugins.retrochangelog import retrochangelog_add_attr
from lib389.idm.user import UserAccount, UserAccounts, nsUserAccounts
pytestmark = pytest.mark.tier1
@@ -122,7 +122,7 @@ def test_retrocl_exclude_attr_add(topology_st):
args.bindpw = None
args.prompt = False
args.exclude_attrs = ATTR_HOMEPHONE
- args.func = retrochangelog_add
+ args.func = retrochangelog_add_attr
dsrc_inst = dsrc_arg_concat(args, None)
inst = connect_instance(dsrc_inst, False, args)
result = args.func(inst, None, log, args)
@@ -255,7 +255,7 @@ def test_retrocl_exclude_attr_mod(topology_st):
args.bindpw = None
args.prompt = False
args.exclude_attrs = ATTR_CARLICENSE
- args.func = retrochangelog_add
+ args.func = retrochangelog_add_attr
dsrc_inst = dsrc_arg_concat(args, None)
inst = connect_instance(dsrc_inst, False, args)
result = args.func(inst, None, log, args)
diff --git a/src/lib389/lib389/cli_conf/plugins/retrochangelog.py b/src/lib389/lib389/cli_conf/plugins/retrochangelog.py
index 9940c6532..160fbb82d 100644
--- a/src/lib389/lib389/cli_conf/plugins/retrochangelog.py
+++ b/src/lib389/lib389/cli_conf/plugins/retrochangelog.py
@@ -6,8 +6,13 @@
# See LICENSE for details.
# --- END COPYRIGHT BLOCK ---
+# JC Work around for missing dependency on https://github.com/389ds/389-ds-base/pull/4344
+import ldap
+
from lib389.plugins import RetroChangelogPlugin
-from lib389.cli_conf import add_generic_plugin_parsers, generic_object_edit
+# JC Work around for missing dependency https://github.com/389ds/389-ds-base/pull/4344
+# from lib389.cli_conf import add_generic_plugin_parsers, generic_object_edit, generic_object_add_attr
+from lib389.cli_conf import add_generic_plugin_parsers, generic_object_edit, _args_to_attrs
arg_to_attr = {
'is_replicated': 'isReplicated',
@@ -18,12 +23,38 @@ arg_to_attr = {
'exclude_attrs': 'nsslapd-exclude-attrs'
}
-
def retrochangelog_edit(inst, basedn, log, args):
log = log.getChild('retrochangelog_edit')
plugin = RetroChangelogPlugin(inst)
generic_object_edit(plugin, log, args, arg_to_attr)
+# JC Work around for missing dependency https://github.com/389ds/389-ds-base/pull/4344
+def retrochangelog_add_attr(inst, basedn, log, args):
+ log = log.getChild('retrochangelog_add_attr')
+ plugin = RetroChangelogPlugin(inst)
+ generic_object_add_attr(plugin, log, args, arg_to_attr)
+
+# JC Work around for missing dependency https://github.com/389ds/389-ds-base/pull/4344
+def generic_object_add_attr(dsldap_object, log, args, arg_to_attr):
+ """Add an attribute to the entry. This differs to 'edit' as edit uses replace,
+ and this allows multivalues to be added.
+
+ dsldap_object should be a single instance of DSLdapObject with a set dn
+ """
+ log = log.getChild('generic_object_add_attr')
+ # Gather the attributes
+ attrs = _args_to_attrs(args, arg_to_attr)
+
+ modlist = []
+ for attr, value in attrs.items():
+ if not isinstance(value, list):
+ value = [value]
+ modlist.append((ldap.MOD_ADD, attr, value))
+ if len(modlist) > 0:
+ dsldap_object.apply_mods(modlist)
+ log.info("Successfully changed the %s", dsldap_object.dn)
+ else:
+ raise ValueError("There is nothing to set in the %s plugin entry" % dsldap_object.dn)
def _add_parser_args(parser):
parser.add_argument('--is-replicated', choices=['TRUE', 'FALSE'], type=str.upper,
--
2.31.1

View File

@ -0,0 +1,642 @@
From d2ac7e98d53cfe6c74c99ddf3504b1072418f05a Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 11 Mar 2021 10:12:46 -0500
Subject: [PATCH] Issue 4656 - remove problematic language from ds-replcheck
Description: remove master from ds-replcheck and replace it with supplier
relates: https://github.com/389ds/389-ds-base/issues/4656
Reviewed by: mreynolds
e with '#' will be ignored, and an empty message aborts the commit.
---
ldap/admin/src/scripts/ds-replcheck | 202 ++++++++++++++--------------
1 file changed, 101 insertions(+), 101 deletions(-)
diff --git a/ldap/admin/src/scripts/ds-replcheck b/ldap/admin/src/scripts/ds-replcheck
index 169496e8f..f411f357a 100755
--- a/ldap/admin/src/scripts/ds-replcheck
+++ b/ldap/admin/src/scripts/ds-replcheck
@@ -1,7 +1,7 @@
#!/usr/bin/python3
# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2020 Red Hat, Inc.
+# Copyright (C) 2021 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
@@ -63,7 +63,7 @@ def remove_entry(rentries, dn):
def get_ruv_time(ruv, rid):
"""Take a RUV element (nsds50ruv attribute) and extract the timestamp from maxcsn
:param ruv - A lsit of RUV elements
- :param rid - The rid of the master to extractthe maxcsn time from
+ :param rid - The rid of the supplier to extract the maxcsn time from
:return: The time in seconds of the maxcsn, or 0 if there is no maxcsn, or -1 if
the rid was not found
"""
@@ -213,22 +213,22 @@ def get_ruv_state(opts):
:param opts - all the script options
:return - A text description of the replicaton state
"""
- mtime = get_ruv_time(opts['master_ruv'], opts['rid'])
+ mtime = get_ruv_time(opts['supplier_ruv'], opts['rid'])
rtime = get_ruv_time(opts['replica_ruv'], opts['rid'])
if mtime == -1:
- repl_state = "Replication State: Replica ID ({}) not found in Master's RUV".format(opts['rid'])
+ repl_state = "Replication State: Replica ID ({}) not found in Supplier's RUV".format(opts['rid'])
elif rtime == -1:
repl_state = "Replication State: Replica ID ({}) not found in Replica's RUV (not initialized?)".format(opts['rid'])
elif mtime == 0:
- repl_state = "Replication State: Master has not seen any updates"
+ repl_state = "Replication State: Supplier has not seen any updates"
elif rtime == 0:
- repl_state = "Replication State: Replica has not seen any changes from the Master"
+ repl_state = "Replication State: Replica has not seen any changes from the Supplier"
elif mtime > rtime:
- repl_state = "Replication State: Replica is behind Master by: {} seconds".format(mtime - rtime)
+ repl_state = "Replication State: Replica is behind Supplier by: {} seconds".format(mtime - rtime)
elif mtime < rtime:
- repl_state = "Replication State: Replica is ahead of Master by: {} seconds".format(rtime - mtime)
+ repl_state = "Replication State: Replica is ahead of Supplier by: {} seconds".format(rtime - mtime)
else:
- repl_state = "Replication State: Master and Replica are in perfect synchronization"
+ repl_state = "Replication State: Supplier and Replica are in perfect synchronization"
return repl_state
@@ -238,11 +238,11 @@ def get_ruv_report(opts):
:param opts - all the script options
:return - A text blob to display in the report
"""
- opts['master_ruv'].sort()
+ opts['supplier_ruv'].sort()
opts['replica_ruv'].sort()
- report = "Master RUV:\n"
- for element in opts['master_ruv']:
+ report = "Supplier RUV:\n"
+ for element in opts['supplier_ruv']:
report += " %s\n" % (element)
report += "\nReplica RUV:\n"
for element in opts['replica_ruv']:
@@ -521,7 +521,7 @@ def get_ldif_ruv(LDIF, opts):
def cmp_entry(mentry, rentry, opts):
"""Compare the two entries, and return a "diff map"
- :param mentry - A Master entry
+ :param mentry - A Supplier entry
:param rentry - A Replica entry
:param opts - A Dict of the scripts options
:return - A Dict of the differences in the entry, or None
@@ -536,7 +536,7 @@ def cmp_entry(mentry, rentry, opts):
mlist = list(mentry.data.keys())
#
- # Check master
+ # Check Supplier
#
for mattr in mlist:
if mattr in opts['ignore']:
@@ -555,7 +555,7 @@ def cmp_entry(mentry, rentry, opts):
if not found:
diff['missing'].append("")
found = True
- diff['missing'].append(" - Master's State Info: %s" % (val))
+ diff['missing'].append(" - Supplier's State Info: %s" % (val))
diff['missing'].append(" - Date: %s\n" % (time.ctime(extract_time(val))))
else:
# No state info, just move on
@@ -566,18 +566,18 @@ def cmp_entry(mentry, rentry, opts):
if report_conflict(rentry, mattr, opts) and report_conflict(mentry, mattr, opts):
diff['diff'].append(" - Attribute '%s' is different:" % mattr)
if 'nscpentrywsi' in mentry.data:
- # Process Master
+ # Process Supplier
found = False
for val in mentry.data['nscpentrywsi']:
if val.lower().startswith(mattr + ';'):
if not found:
- diff['diff'].append(" Master:")
+ diff['diff'].append(" Supplier:")
diff['diff'].append(" - Value: %s" % (val.split(':')[1].lstrip()))
diff['diff'].append(" - State Info: %s" % (val))
diff['diff'].append(" - Date: %s\n" % (time.ctime(extract_time(val))))
found = True
if not found:
- diff['diff'].append(" Master: ")
+ diff['diff'].append(" Supplier: ")
for val in mentry.data[mattr]:
# This is an "origin" value which means it's never been
# updated since replication was set up. So its the
@@ -605,7 +605,7 @@ def cmp_entry(mentry, rentry, opts):
diff['diff'].append("")
else:
# no state info, report what we got
- diff['diff'].append(" Master: ")
+ diff['diff'].append(" Supplier: ")
for val in mentry.data[mattr]:
diff['diff'].append(" - %s: %s" % (mattr, val))
diff['diff'].append(" Replica: ")
@@ -622,9 +622,9 @@ def cmp_entry(mentry, rentry, opts):
continue
if rattr not in mlist:
- # Master is missing the attribute
+ # Supplier is missing the attribute
if report_conflict(rentry, rattr, opts):
- diff['missing'].append(" - Master missing attribute: \"%s\"" % (rattr))
+ diff['missing'].append(" - Supplier missing attribute: \"%s\"" % (rattr))
diff_count += 1
if 'nscpentrywsi' in rentry.data:
found = False
@@ -663,7 +663,7 @@ def do_offline_report(opts, output_file=None):
try:
MLDIF = open(opts['mldif'], "r")
except Exception as e:
- print('Failed to open Master LDIF: ' + str(e))
+ print('Failed to open Supplier LDIF: ' + str(e))
return
try:
@@ -676,10 +676,10 @@ def do_offline_report(opts, output_file=None):
# Verify LDIF Files
try:
if opts['verbose']:
- print("Validating Master ldif file ({})...".format(opts['mldif']))
+ print("Validating Supplier ldif file ({})...".format(opts['mldif']))
LDIFRecordList(MLDIF).parse()
except ValueError:
- print('Master LDIF file in invalid, aborting...')
+ print('Supplier LDIF file in invalid, aborting...')
MLDIF.close()
RLDIF.close()
return
@@ -696,34 +696,34 @@ def do_offline_report(opts, output_file=None):
# Get all the dn's, and entry counts
if opts['verbose']:
print ("Gathering all the DN's...")
- master_dns = get_dns(MLDIF, opts['mldif'], opts)
+ supplier_dns = get_dns(MLDIF, opts['mldif'], opts)
replica_dns = get_dns(RLDIF, opts['rldif'], opts)
- if master_dns is None or replica_dns is None:
+ if supplier_dns is None or replica_dns is None:
print("Aborting scan...")
MLDIF.close()
RLDIF.close()
sys.exit(1)
- m_count = len(master_dns)
+ m_count = len(supplier_dns)
r_count = len(replica_dns)
# Get DB RUV
if opts['verbose']:
print ("Gathering the database RUV's...")
- opts['master_ruv'] = get_ldif_ruv(MLDIF, opts)
+ opts['supplier_ruv'] = get_ldif_ruv(MLDIF, opts)
opts['replica_ruv'] = get_ldif_ruv(RLDIF, opts)
- """ Compare the master entries with the replica's. Take our list of dn's from
- the master ldif and get that entry( dn) from the master and replica ldif. In
+ """ Compare the Supplier entries with the replica's. Take our list of dn's from
+ the Supplier ldif and get that entry( dn) from the Supplier and replica ldif. In
this phase we keep keep track of conflict/tombstone counts, and we check for
missing entries and entry differences. We only need to do the entry diff
checking in this phase - we do not need to do it when process the replica dn's
because if the entry exists in both LDIF's then we already checked or diffs
- while processing the master dn's.
+ while processing the Supplier dn's.
"""
if opts['verbose']:
- print ("Comparing Master to Replica...")
+ print ("Comparing Supplier to Replica...")
missing = False
- for dn in master_dns:
+ for dn in supplier_dns:
mresult = ldif_search(MLDIF, dn)
if mresult['entry'] is None and mresult['conflict'] is None and not mresult['tombstone']:
# Try from the beginning
@@ -736,7 +736,7 @@ def do_offline_report(opts, output_file=None):
rresult['conflict'] is not None or rresult['tombstone']):
""" We can safely remove this DN from the replica dn list as it
does not need to be checked again. This also speeds things up
- when doing the replica vs master phase.
+ when doing the replica vs Supplier phase.
"""
replica_dns.remove(dn)
@@ -766,7 +766,7 @@ def do_offline_report(opts, output_file=None):
missing_report += (' Entries missing on Replica:\n')
missing = True
if mresult['entry'] and 'createtimestamp' in mresult['entry'].data:
- missing_report += (' - %s (Created on Master at: %s)\n' %
+ missing_report += (' - %s (Created on Supplier at: %s)\n' %
(dn, convert_timestamp(mresult['entry'].data['createtimestamp'][0])))
else:
missing_report += (' - %s\n' % dn)
@@ -791,7 +791,7 @@ def do_offline_report(opts, output_file=None):
remaining conflict & tombstone entries as well.
"""
if opts['verbose']:
- print ("Comparing Replica to Master...")
+ print ("Comparing Replica to Supplier...")
MLDIF.seek(0)
RLDIF.seek(0)
missing = False
@@ -811,7 +811,7 @@ def do_offline_report(opts, output_file=None):
if mresult['entry'] is None and mresult['glue'] is None:
MLDIF.seek(rresult['idx']) # Set the LDIF cursor/index to the last good line
if not missing:
- missing_report += (' Entries missing on Master:\n')
+ missing_report += (' Entries missing on Supplier:\n')
missing = True
if rresult['entry'] and 'createtimestamp' in rresult['entry'].data:
missing_report += (' - %s (Created on Replica at: %s)\n' %
@@ -837,12 +837,12 @@ def do_offline_report(opts, output_file=None):
final_report += get_ruv_report(opts)
final_report += ('Entry Counts\n')
final_report += ('=====================================================\n\n')
- final_report += ('Master: %d\n' % (m_count))
+ final_report += ('Supplier: %d\n' % (m_count))
final_report += ('Replica: %d\n\n' % (r_count))
final_report += ('\nTombstones\n')
final_report += ('=====================================================\n\n')
- final_report += ('Master: %d\n' % (mtombstones))
+ final_report += ('Supplier: %d\n' % (mtombstones))
final_report += ('Replica: %d\n' % (rtombstones))
final_report += get_conflict_report(mconflicts, rconflicts, opts['conflicts'])
@@ -859,9 +859,9 @@ def do_offline_report(opts, output_file=None):
final_report += ('\nResult\n')
final_report += ('=====================================================\n\n')
if missing_report == "" and len(diff_report) == 0:
- final_report += ('No replication differences between Master and Replica\n')
+ final_report += ('No replication differences between Supplier and Replica\n')
else:
- final_report += ('There are replication differences between Master and Replica\n')
+ final_report += ('There are replication differences between Supplier and Replica\n')
if output_file:
output_file.write(final_report)
@@ -871,8 +871,8 @@ def do_offline_report(opts, output_file=None):
def check_for_diffs(mentries, mglue, rentries, rglue, report, opts):
"""Online mode only - Check for diffs, return the updated report
- :param mentries - Master entries
- :param mglue - Master glue entries
+ :param mentries - Supplier entries
+ :param mglue - Supplier glue entries
:param rentries - Replica entries
:param rglue - Replica glue entries
:param report - A Dict of the entire report
@@ -947,8 +947,8 @@ def validate_suffix(ldapnode, suffix, hostname):
# Check suffix is replicated
try:
replica_filter = "(&(objectclass=nsds5replica)(nsDS5ReplicaRoot=%s))" % suffix
- master_replica = ldapnode.search_s("cn=config",ldap.SCOPE_SUBTREE,replica_filter)
- if (len(master_replica) != 1):
+ supplier_replica = ldapnode.search_s("cn=config",ldap.SCOPE_SUBTREE,replica_filter)
+ if (len(supplier_replica) != 1):
print("Error: Failed to validate suffix in {}. {} is not replicated.".format(hostname, suffix))
return False
except ldap.LDAPError as e:
@@ -969,7 +969,7 @@ def connect_to_replicas(opts):
muri = "%s://%s" % (opts['mprotocol'], opts['mhost'].replace("/", "%2f"))
else:
muri = "%s://%s:%s/" % (opts['mprotocol'], opts['mhost'], opts['mport'])
- master = SimpleLDAPObject(muri)
+ supplier = SimpleLDAPObject(muri)
if opts['rprotocol'].lower() == 'ldapi':
ruri = "%s://%s" % (opts['rprotocol'], opts['rhost'].replace("/", "%2f"))
@@ -978,23 +978,23 @@ def connect_to_replicas(opts):
replica = SimpleLDAPObject(ruri)
# Set timeouts
- master.set_option(ldap.OPT_NETWORK_TIMEOUT, opts['timeout'])
- master.set_option(ldap.OPT_TIMEOUT, opts['timeout'])
+ supplier.set_option(ldap.OPT_NETWORK_TIMEOUT, opts['timeout'])
+ supplier.set_option(ldap.OPT_TIMEOUT, opts['timeout'])
replica.set_option(ldap.OPT_NETWORK_TIMEOUT, opts['timeout'])
replica.set_option(ldap.OPT_TIMEOUT, opts['timeout'])
# Setup Secure Connection
if opts['certdir'] is not None:
- # Setup Master
+ # Setup Supplier
if opts['mprotocol'] != LDAPI:
- master.set_option(ldap.OPT_X_TLS_CACERTDIR, opts['certdir'])
- master.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_HARD)
+ supplier.set_option(ldap.OPT_X_TLS_CACERTDIR, opts['certdir'])
+ supplier.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_HARD)
if opts['mprotocol'] == LDAP:
# Do StartTLS
try:
- master.start_tls_s()
+ supplier.start_tls_s()
except ldap.LDAPError as e:
- print('TLS negotiation failed on Master: {}'.format(str(e)))
+ print('TLS negotiation failed on Supplier: {}'.format(str(e)))
exit(1)
# Setup Replica
@@ -1006,17 +1006,17 @@ def connect_to_replicas(opts):
try:
replica.start_tls_s()
except ldap.LDAPError as e:
- print('TLS negotiation failed on Master: {}'.format(str(e)))
+ print('TLS negotiation failed on Supplier: {}'.format(str(e)))
exit(1)
- # Open connection to master
+ # Open connection to Supplier
try:
- master.simple_bind_s(opts['binddn'], opts['bindpw'])
+ supplier.simple_bind_s(opts['binddn'], opts['bindpw'])
except ldap.SERVER_DOWN as e:
print(f"Cannot connect to {muri} ({str(e)})")
sys.exit(1)
except ldap.LDAPError as e:
- print("Error: Failed to authenticate to Master: ({}). "
+ print("Error: Failed to authenticate to Supplier: ({}). "
"Please check your credentials and LDAP urls are correct.".format(str(e)))
sys.exit(1)
@@ -1034,7 +1034,7 @@ def connect_to_replicas(opts):
# Validate suffix
if opts['verbose']:
print ("Validating suffix ...")
- if not validate_suffix(master, opts['suffix'], opts['mhost']):
+ if not validate_suffix(supplier, opts['suffix'], opts['mhost']):
sys.exit(1)
if not validate_suffix(replica,opts['suffix'], opts['rhost']):
@@ -1042,16 +1042,16 @@ def connect_to_replicas(opts):
# Get the RUVs
if opts['verbose']:
- print ("Gathering Master's RUV...")
+ print ("Gathering Supplier's RUV...")
try:
- master_ruv = master.search_s(opts['suffix'], ldap.SCOPE_SUBTREE, RUV_FILTER, ['nsds50ruv'])
- if len(master_ruv) > 0:
- opts['master_ruv'] = ensure_list_str(master_ruv[0][1]['nsds50ruv'])
+ supplier_ruv = supplier.search_s(opts['suffix'], ldap.SCOPE_SUBTREE, RUV_FILTER, ['nsds50ruv'])
+ if len(supplier_ruv) > 0:
+ opts['supplier_ruv'] = ensure_list_str(supplier_ruv[0][1]['nsds50ruv'])
else:
- print("Error: Master does not have an RUV entry")
+ print("Error: Supplier does not have an RUV entry")
sys.exit(1)
except ldap.LDAPError as e:
- print("Error: Failed to get Master RUV entry: {}".format(str(e)))
+ print("Error: Failed to get Supplier RUV entry: {}".format(str(e)))
sys.exit(1)
if opts['verbose']:
@@ -1067,12 +1067,12 @@ def connect_to_replicas(opts):
print("Error: Failed to get Replica RUV entry: {}".format(str(e)))
sys.exit(1)
- # Get the master RID
+ # Get the Supplier RID
if opts['verbose']:
- print("Getting Master's replica ID")
+ print("Getting Supplier's replica ID")
try:
search_filter = "(&(objectclass=nsds5Replica)(nsDS5ReplicaRoot={})(nsDS5ReplicaId=*))".format(opts['suffix'])
- replica_entry = master.search_s("cn=config", ldap.SCOPE_SUBTREE, search_filter)
+ replica_entry = supplier.search_s("cn=config", ldap.SCOPE_SUBTREE, search_filter)
if len(replica_entry) > 0:
opts['rid'] = ensure_int(replica_entry[0][1]['nsDS5ReplicaId'][0])
else:
@@ -1081,7 +1081,7 @@ def connect_to_replicas(opts):
print("Error: Failed to get Replica entry: {}".format(str(e)))
sys.exit(1)
- return (master, replica, opts)
+ return (supplier, replica, opts)
def print_online_report(report, opts, output_file):
@@ -1104,11 +1104,11 @@ def print_online_report(report, opts, output_file):
final_report += get_ruv_report(opts)
final_report += ('Entry Counts\n')
final_report += ('=====================================================\n\n')
- final_report += ('Master: %d\n' % (report['m_count']))
+ final_report += ('Supplier: %d\n' % (report['m_count']))
final_report += ('Replica: %d\n\n' % (report['r_count']))
final_report += ('\nTombstones\n')
final_report += ('=====================================================\n\n')
- final_report += ('Master: %d\n' % (report['mtombstones']))
+ final_report += ('Supplier: %d\n' % (report['mtombstones']))
final_report += ('Replica: %d\n' % (report['rtombstones']))
final_report += report['conflict']
missing = False
@@ -1121,7 +1121,7 @@ def print_online_report(report, opts, output_file):
final_report += (' Entries missing on Replica:\n')
for entry in report['r_missing']:
if 'createtimestamp' in entry.data:
- final_report += (' - %s (Created on Master at: %s)\n' %
+ final_report += (' - %s (Created on Supplier at: %s)\n' %
(entry.dn, convert_timestamp(entry.data['createtimestamp'][0])))
else:
final_report += (' - %s\n' % (entry.dn))
@@ -1129,7 +1129,7 @@ def print_online_report(report, opts, output_file):
if m_missing > 0:
if r_missing > 0:
final_report += ('\n')
- final_report += (' Entries missing on Master:\n')
+ final_report += (' Entries missing on Supplier:\n')
for entry in report['m_missing']:
if 'createtimestamp' in entry.data:
final_report += (' - %s (Created on Replica at: %s)\n' %
@@ -1146,9 +1146,9 @@ def print_online_report(report, opts, output_file):
final_report += ('\nResult\n')
final_report += ('=====================================================\n\n')
if not missing and len(report['diff']) == 0:
- final_report += ('No replication differences between Master and Replica\n')
+ final_report += ('No replication differences between Supplier and Replica\n')
else:
- final_report += ('There are replication differences between Master and Replica\n')
+ final_report += ('There are replication differences between Supplier and Replica\n')
if output_file:
output_file.write(final_report)
@@ -1170,7 +1170,7 @@ def remove_state_info(entry):
def get_conflict_report(mentries, rentries, verbose):
"""Gather the conflict entry dn's for each replica
- :param mentries - Master entries
+ :param mentries - Supplier entries
:param rentries - Replica entries
:param verbose - verbose logging
:return - A text blob to dispaly in the report
@@ -1197,7 +1197,7 @@ def get_conflict_report(mentries, rentries, verbose):
report = "\n\nConflict Entries\n"
report += "=====================================================\n\n"
if len(m_conflicts) > 0:
- report += ('Master Conflict Entries: %d\n' % (len(m_conflicts)))
+ report += ('Supplier Conflict Entries: %d\n' % (len(m_conflicts)))
if verbose:
for entry in m_conflicts:
report += ('\n - %s\n' % (entry['dn']))
@@ -1239,8 +1239,8 @@ def do_online_report(opts, output_file=None):
rconflicts = []
mconflicts = []
- # Fire off paged searches on Master and Replica
- master, replica, opts = connect_to_replicas(opts)
+ # Fire off paged searches on Supplier and Replica
+ supplier, replica, opts = connect_to_replicas(opts)
if opts['verbose']:
print('Start searching and comparing...')
@@ -1248,12 +1248,12 @@ def do_online_report(opts, output_file=None):
controls = [paged_ctrl]
req_pr_ctrl = controls[0]
try:
- master_msgid = master.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
- "(|(objectclass=*)(objectclass=ldapsubentry)(objectclass=nstombstone))",
- ['*', 'createtimestamp', 'nscpentrywsi', 'nsds5replconflict'],
- serverctrls=controls)
+ supplier_msgid = supplier.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
+ "(|(objectclass=*)(objectclass=ldapsubentry)(objectclass=nstombstone))",
+ ['*', 'createtimestamp', 'nscpentrywsi', 'nsds5replconflict'],
+ serverctrls=controls)
except ldap.LDAPError as e:
- print("Error: Failed to get Master entries: %s", str(e))
+ print("Error: Failed to get Supplier entries: %s", str(e))
sys.exit(1)
try:
replica_msgid = replica.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
@@ -1268,11 +1268,11 @@ def do_online_report(opts, output_file=None):
while not m_done or not r_done:
try:
if not m_done:
- m_rtype, m_rdata, m_rmsgid, m_rctrls = master.result3(master_msgid)
+ m_rtype, m_rdata, m_rmsgid, m_rctrls = supplier.result3(supplier_msgid)
elif not r_done:
m_rdata = []
except ldap.LDAPError as e:
- print("Error: Problem getting the results from the master: %s", str(e))
+ print("Error: Problem getting the results from the Supplier: %s", str(e))
sys.exit(1)
try:
if not r_done:
@@ -1299,7 +1299,7 @@ def do_online_report(opts, output_file=None):
report, opts)
if not m_done:
- # Master
+ # Supplier
m_pctrls = [
c
for c in m_rctrls
@@ -1310,11 +1310,11 @@ def do_online_report(opts, output_file=None):
try:
# Copy cookie from response control to request control
req_pr_ctrl.cookie = m_pctrls[0].cookie
- master_msgid = master.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
+ supplier_msgid = supplier.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
"(|(objectclass=*)(objectclass=ldapsubentry))",
['*', 'createtimestamp', 'nscpentrywsi', 'conflictcsn', 'nsds5replconflict'], serverctrls=controls)
except ldap.LDAPError as e:
- print("Error: Problem searching the master: %s", str(e))
+ print("Error: Problem searching the Supplier: %s", str(e))
sys.exit(1)
else:
m_done = True # No more pages available
@@ -1354,7 +1354,7 @@ def do_online_report(opts, output_file=None):
print_online_report(report, opts, output_file)
# unbind
- master.unbind_s()
+ supplier.unbind_s()
replica.unbind_s()
@@ -1367,18 +1367,18 @@ def init_online_params(args):
# Make sure the URLs are different
if args.murl == args.rurl:
- print("Master and Replica LDAP URLs are the same, they must be different")
+ print("Supplier and Replica LDAP URLs are the same, they must be different")
sys.exit(1)
- # Parse Master url
+ # Parse Supplier url
if not ldapurl.isLDAPUrl(args.murl):
- print("Master LDAP URL is invalid")
+ print("Supplier LDAP URL is invalid")
sys.exit(1)
murl = ldapurl.LDAPUrl(args.murl)
if murl.urlscheme in VALID_PROTOCOLS:
opts['mprotocol'] = murl.urlscheme
else:
- print('Unsupported ldap url protocol (%s) for Master, please use "ldaps" or "ldap"' %
+ print('Unsupported ldap url protocol (%s) for Supplier, please use "ldaps" or "ldap"' %
murl.urlscheme)
sys.exit(1)
@@ -1520,7 +1520,7 @@ def offline_report(args):
print ("LDIF file ({}) is empty".format(ldif_dir))
sys.exit(1)
if opts['mldif'] == opts['rldif']:
- print("The Master and Replica LDIF files must be different")
+ print("The Supplier and Replica LDIF files must be different")
sys.exit(1)
OUTPUT_FILE = None
@@ -1547,7 +1547,7 @@ def get_state(args):
"""Just do the RUV comparision
"""
opts = init_online_params(args)
- master, replica, opts = connect_to_replicas(opts)
+ supplier, replica, opts = connect_to_replicas(opts)
print(get_ruv_state(opts))
@@ -1569,10 +1569,10 @@ def main():
# Get state
state_parser = subparsers.add_parser('state', help="Get the current replicaton state between two replicas")
state_parser.set_defaults(func=get_state)
- state_parser.add_argument('-m', '--master-url', help='The LDAP URL for the Master server',
- dest='murl', default=None, required=True)
+ state_parser.add_argument('-m', '--supplier-url', help='The LDAP URL for the Supplier server',
+ dest='murl', default=None, required=True)
state_parser.add_argument('-r', '--replica-url', help='The LDAP URL for the Replica server',
- dest='rurl', required=True, default=None)
+ dest='rurl', required=True, default=None)
state_parser.add_argument('-b', '--suffix', help='Replicated suffix', dest='suffix', required=True)
state_parser.add_argument('-D', '--bind-dn', help='The Bind DN', required=True, dest='binddn', default=None)
state_parser.add_argument('-w', '--bind-pw', help='The Bind password', dest='bindpw', default=None)
@@ -1586,7 +1586,7 @@ def main():
# Online mode
online_parser = subparsers.add_parser('online', help="Compare two online replicas for differences")
online_parser.set_defaults(func=online_report)
- online_parser.add_argument('-m', '--master-url', help='The LDAP URL for the Master server (REQUIRED)',
+ online_parser.add_argument('-m', '--supplier-url', help='The LDAP URL for the Supplier server (REQUIRED)',
dest='murl', default=None, required=True)
online_parser.add_argument('-r', '--replica-url', help='The LDAP URL for the Replica server (REQUIRED)',
dest='rurl', required=True, default=None)
@@ -1612,12 +1612,12 @@ def main():
# Offline LDIF mode
offline_parser = subparsers.add_parser('offline', help="Compare two replication LDIF files for differences (LDIF file generated by 'db2ldif -r')")
offline_parser.set_defaults(func=offline_report)
- offline_parser.add_argument('-m', '--master-ldif', help='Master LDIF file',
+ offline_parser.add_argument('-m', '--supplier-ldif', help='Supplier LDIF file',
dest='mldif', default=None, required=True)
offline_parser.add_argument('-r', '--replica-ldif', help='Replica LDIF file',
dest='rldif', default=None, required=True)
offline_parser.add_argument('--rid', dest='rid', default=None, required=True,
- help='The Replica Identifer (rid) for the "Master" server')
+ help='The Replica Identifier (rid) for the "Supplier" server')
offline_parser.add_argument('-b', '--suffix', help='Replicated suffix', dest='suffix', required=True)
offline_parser.add_argument('-c', '--conflicts', help='Display verbose conflict information', action='store_true',
dest='conflicts', default=False)
--
2.31.1

View File

@ -0,0 +1,373 @@
From 55a47c1bfe1ce1c27e470384c4f1d50895db25f7 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 13 Jul 2021 14:18:03 -0400
Subject: [PATCH] Issue 4443 - Internal unindexed searches in syncrepl/retro
changelog
Bug Description:
When a non-system index is added to a backend it is
disabled until the database is initialized or reindexed.
So in the case of the retro changelog the changenumber index
is alway disabled by default since it is never initialized.
This leads to unexpected unindexed searches of the retro
changelog.
Fix Description:
If an index has "nsSystemIndex" set to "true" then enable it
immediately.
relates: https://github.com/389ds/389-ds-base/issues/4443
Reviewed by: spichugi & tbordaz(Thanks!!)
---
.../tests/suites/retrocl/basic_test.py | 53 ++++++++-------
.../suites/retrocl/retrocl_indexing_test.py | 68 +++++++++++++++++++
ldap/servers/plugins/retrocl/retrocl_create.c | 2 +-
.../slapd/back-ldbm/ldbm_index_config.c | 25 +++++--
src/lib389/lib389/_mapped_object.py | 13 ++++
5 files changed, 130 insertions(+), 31 deletions(-)
create mode 100644 dirsrvtests/tests/suites/retrocl/retrocl_indexing_test.py
diff --git a/dirsrvtests/tests/suites/retrocl/basic_test.py b/dirsrvtests/tests/suites/retrocl/basic_test.py
index f3bc50f29..84d513829 100644
--- a/dirsrvtests/tests/suites/retrocl/basic_test.py
+++ b/dirsrvtests/tests/suites/retrocl/basic_test.py
@@ -8,7 +8,6 @@
import logging
import ldap
-import time
import pytest
from lib389.topologies import topology_st
from lib389.plugins import RetroChangelogPlugin
@@ -18,7 +17,8 @@ from lib389.tasks import *
from lib389.cli_base import FakeArgs, connect_instance, disconnect_instance
from lib389.cli_base.dsrc import dsrc_arg_concat
from lib389.cli_conf.plugins.retrochangelog import retrochangelog_add_attr
-from lib389.idm.user import UserAccount, UserAccounts, nsUserAccounts
+from lib389.idm.user import UserAccount, UserAccounts
+from lib389._mapped_object import DSLdapObjects
pytestmark = pytest.mark.tier1
@@ -82,7 +82,7 @@ def test_retrocl_exclude_attr_add(topology_st):
log.info('Adding user1')
try:
- user1 = users.create(properties={
+ users.create(properties={
'sn': '1',
'cn': 'user 1',
'uid': 'user1',
@@ -97,17 +97,18 @@ def test_retrocl_exclude_attr_add(topology_st):
except ldap.ALREADY_EXISTS:
pass
except ldap.LDAPError as e:
- log.error("Failed to add user1")
+ log.error("Failed to add user1: " + str(e))
log.info('Verify homePhone and carLicense attrs are in the changelog changestring')
try:
- cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER1_DN)
+ retro_changelog_suffix = DSLdapObjects(st, basedn=RETROCL_SUFFIX)
+ cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
except ldap.LDAPError as e:
- log.fatal("Changelog search failed, error: " +str(e))
+ log.fatal("Changelog search failed, error: " + str(e))
assert False
assert len(cllist) > 0
- if cllist[0].hasAttr('changes'):
- clstr = (cllist[0].getValue('changes')).decode()
+ if cllist[0].present('changes'):
+ clstr = str(cllist[0].get_attr_vals_utf8('changes'))
assert ATTR_HOMEPHONE in clstr
assert ATTR_CARLICENSE in clstr
@@ -134,7 +135,7 @@ def test_retrocl_exclude_attr_add(topology_st):
log.info('Adding user2')
try:
- user2 = users.create(properties={
+ users.create(properties={
'sn': '2',
'cn': 'user 2',
'uid': 'user2',
@@ -149,18 +150,18 @@ def test_retrocl_exclude_attr_add(topology_st):
except ldap.ALREADY_EXISTS:
pass
except ldap.LDAPError as e:
- log.error("Failed to add user2")
+ log.error("Failed to add user2: " + str(e))
log.info('Verify homePhone attr is not in the changelog changestring')
try:
- cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER2_DN)
+ cllist = retro_changelog_suffix.filter(f'(targetDn={USER2_DN})')
assert len(cllist) > 0
- if cllist[0].hasAttr('changes'):
- clstr = (cllist[0].getValue('changes')).decode()
+ if cllist[0].present('changes'):
+ clstr = str(cllist[0].get_attr_vals_utf8('changes'))
assert ATTR_HOMEPHONE not in clstr
assert ATTR_CARLICENSE in clstr
except ldap.LDAPError as e:
- log.fatal("Changelog search failed, error: " +str(e))
+ log.fatal("Changelog search failed, error: " + str(e))
assert False
def test_retrocl_exclude_attr_mod(topology_st):
@@ -228,19 +229,20 @@ def test_retrocl_exclude_attr_mod(topology_st):
'homeDirectory': '/home/user1',
'userpassword': USER_PW})
except ldap.ALREADY_EXISTS:
- pass
+ user1 = UserAccount(st, dn=USER1_DN)
except ldap.LDAPError as e:
- log.error("Failed to add user1")
+ log.error("Failed to add user1: " + str(e))
log.info('Verify homePhone and carLicense attrs are in the changelog changestring')
try:
- cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER1_DN)
+ retro_changelog_suffix = DSLdapObjects(st, basedn=RETROCL_SUFFIX)
+ cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
except ldap.LDAPError as e:
- log.fatal("Changelog search failed, error: " +str(e))
+ log.fatal("Changelog search failed, error: " + str(e))
assert False
assert len(cllist) > 0
- if cllist[0].hasAttr('changes'):
- clstr = (cllist[0].getValue('changes')).decode()
+ if cllist[0].present('changes'):
+ clstr = str(cllist[0].get_attr_vals_utf8('changes'))
assert ATTR_HOMEPHONE in clstr
assert ATTR_CARLICENSE in clstr
@@ -267,24 +269,25 @@ def test_retrocl_exclude_attr_mod(topology_st):
log.info('Modify user1 carLicense attribute')
try:
- st.modify_s(USER1_DN, [(ldap.MOD_REPLACE, ATTR_CARLICENSE, b"123WX321")])
+ user1.replace(ATTR_CARLICENSE, "123WX321")
except ldap.LDAPError as e:
log.fatal('test_retrocl_exclude_attr_mod: Failed to update user1 attribute: error ' + e.message['desc'])
assert False
log.info('Verify carLicense attr is not in the changelog changestring')
try:
- cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER1_DN)
+ cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
assert len(cllist) > 0
# There will be 2 entries in the changelog for this user, we are only
#interested in the second one, the modify operation.
- if cllist[1].hasAttr('changes'):
- clstr = (cllist[1].getValue('changes')).decode()
+ if cllist[1].present('changes'):
+ clstr = str(cllist[1].get_attr_vals_utf8('changes'))
assert ATTR_CARLICENSE not in clstr
except ldap.LDAPError as e:
- log.fatal("Changelog search failed, error: " +str(e))
+ log.fatal("Changelog search failed, error: " + str(e))
assert False
+
if __name__ == '__main__':
# Run isolated
# -s for DEBUG mode
diff --git a/dirsrvtests/tests/suites/retrocl/retrocl_indexing_test.py b/dirsrvtests/tests/suites/retrocl/retrocl_indexing_test.py
new file mode 100644
index 000000000..b1dfe962c
--- /dev/null
+++ b/dirsrvtests/tests/suites/retrocl/retrocl_indexing_test.py
@@ -0,0 +1,68 @@
+import logging
+import pytest
+import os
+from lib389._constants import RETROCL_SUFFIX, DEFAULT_SUFFIX
+from lib389.topologies import topology_st as topo
+from lib389.plugins import RetroChangelogPlugin
+from lib389.idm.user import UserAccounts
+from lib389._mapped_object import DSLdapObjects
+log = logging.getLogger(__name__)
+
+
+def test_indexing_is_online(topo):
+ """Test that the changenmumber index is online right after enabling the plugin
+
+ :id: 16f4c001-9e0c-4448-a2b3-08ac1e85d40f
+ :setup: Standalone Instance
+ :steps:
+ 1. Enable retro cl
+ 2. Perform some updates
+ 3. Search for "(changenumber>=-1)", and it is not partially unindexed
+ 4. Search for "(&(changenumber>=-1)(targetuniqueid=*))", and it is not partially unindexed
+ :expectedresults:
+ 1. Success
+ 2. Success
+ 3. Success
+ 4. Success
+ """
+
+ # Enable plugin
+ topo.standalone.config.set('nsslapd-accesslog-logbuffering', 'off')
+ plugin = RetroChangelogPlugin(topo.standalone)
+ plugin.enable()
+ topo.standalone.restart()
+
+ # Do a bunch of updates
+ users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
+ user_entry = users.create(properties={
+ 'sn': '1',
+ 'cn': 'user 1',
+ 'uid': 'user1',
+ 'uidNumber': '11',
+ 'gidNumber': '111',
+ 'givenname': 'user1',
+ 'homePhone': '0861234567',
+ 'carLicense': '131D16674',
+ 'mail': 'user1@whereever.com',
+ 'homeDirectory': '/home'
+ })
+ for count in range(0, 10):
+ user_entry.replace('mail', f'test{count}@test.com')
+
+ # Search the retro cl, and check for error messages
+ filter_simple = '(changenumber>=-1)'
+ filter_compound = '(&(changenumber>=-1)(targetuniqueid=*))'
+ retro_changelog_suffix = DSLdapObjects(topo.standalone, basedn=RETROCL_SUFFIX)
+ retro_changelog_suffix.filter(filter_simple)
+ assert not topo.standalone.searchAccessLog('Partially Unindexed Filter')
+
+ # Search the retro cl again with compound filter
+ retro_changelog_suffix.filter(filter_compound)
+ assert not topo.standalone.searchAccessLog('Partially Unindexed Filter')
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main(["-s", CURRENT_FILE])
diff --git a/ldap/servers/plugins/retrocl/retrocl_create.c b/ldap/servers/plugins/retrocl/retrocl_create.c
index 571e6899f..5bfde7831 100644
--- a/ldap/servers/plugins/retrocl/retrocl_create.c
+++ b/ldap/servers/plugins/retrocl/retrocl_create.c
@@ -133,7 +133,7 @@ retrocl_create_be(const char *bedir)
val.bv_len = strlen(val.bv_val);
slapi_entry_add_values(e, "cn", vals);
- val.bv_val = "false";
+ val.bv_val = "true"; /* enables the index */
val.bv_len = strlen(val.bv_val);
slapi_entry_add_values(e, "nssystemindex", vals);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_index_config.c b/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
index 9722d0ce7..38e7368e1 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
@@ -25,7 +25,7 @@ int ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb, Slapi_Entry *en
#define INDEXTYPE_NONE 1
static int
-ldbm_index_parse_entry(ldbm_instance *inst, Slapi_Entry *e, const char *trace_string, char **index_name, char *err_buf)
+ldbm_index_parse_entry(ldbm_instance *inst, Slapi_Entry *e, const char *trace_string, char **index_name, PRBool *is_system_index, char *err_buf)
{
Slapi_Attr *attr;
const struct berval *attrValue;
@@ -78,6 +78,15 @@ ldbm_index_parse_entry(ldbm_instance *inst, Slapi_Entry *e, const char *trace_st
}
}
+ *is_system_index = PR_FALSE;
+ if (0 == slapi_entry_attr_find(e, "nsSystemIndex", &attr)) {
+ slapi_attr_first_value(attr, &sval);
+ attrValue = slapi_value_get_berval(sval);
+ if (strcasecmp(attrValue->bv_val, "true") == 0) {
+ *is_system_index = PR_TRUE;
+ }
+ }
+
/* ok the entry is good to process, pass it to attr_index_config */
if (attr_index_config(inst->inst_be, (char *)trace_string, 0, e, 0, 0, err_buf)) {
slapi_ch_free_string(index_name);
@@ -101,9 +110,10 @@ ldbm_index_init_entry_callback(Slapi_PBlock *pb __attribute__((unused)),
void *arg)
{
ldbm_instance *inst = (ldbm_instance *)arg;
+ PRBool is_system_index = PR_FALSE;
returntext[0] = '\0';
- *returncode = ldbm_index_parse_entry(inst, e, "from ldbm instance init", NULL, NULL);
+ *returncode = ldbm_index_parse_entry(inst, e, "from ldbm instance init", NULL, &is_system_index /* not used */, NULL);
if (*returncode == LDAP_SUCCESS) {
return SLAPI_DSE_CALLBACK_OK;
} else {
@@ -126,17 +136,21 @@ ldbm_instance_index_config_add_callback(Slapi_PBlock *pb __attribute__((unused))
{
ldbm_instance *inst = (ldbm_instance *)arg;
char *index_name = NULL;
+ PRBool is_system_index = PR_FALSE;
returntext[0] = '\0';
- *returncode = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name, returntext);
+ *returncode = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name, &is_system_index, returntext);
if (*returncode == LDAP_SUCCESS) {
struct attrinfo *ai = NULL;
/* if the index is a "system" index, we assume it's being added by
* by the server, and it's okay for the index to go online immediately.
* if not, we set the index "offline" so it won't actually be used
* until someone runs db2index on it.
+ * If caller wants to add an index that they want to be online
+ * immediately they can also set "nsSystemIndex" to "true" in the
+ * index config entry (e.g. is_system_index).
*/
- if (!ldbm_attribute_always_indexed(index_name)) {
+ if (!is_system_index && !ldbm_attribute_always_indexed(index_name)) {
ainfo_get(inst->inst_be, index_name, &ai);
PR_ASSERT(ai != NULL);
ai->ai_indexmask |= INDEX_OFFLINE;
@@ -386,13 +400,14 @@ ldbm_instance_index_config_enable_index(ldbm_instance *inst, Slapi_Entry *e)
char *index_name = NULL;
int rc = LDAP_SUCCESS;
struct attrinfo *ai = NULL;
+ PRBool is_system_index = PR_FALSE;
index_name = slapi_entry_attr_get_charptr(e, "cn");
if (index_name) {
ainfo_get(inst->inst_be, index_name, &ai);
}
if (!ai) {
- rc = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name, NULL);
+ rc = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name, &is_system_index /* not used */, NULL);
}
if (rc == LDAP_SUCCESS) {
/* Assume the caller knows if it is OK to go online immediately */
diff --git a/src/lib389/lib389/_mapped_object.py b/src/lib389/lib389/_mapped_object.py
index b6d778b01..fe610d175 100644
--- a/src/lib389/lib389/_mapped_object.py
+++ b/src/lib389/lib389/_mapped_object.py
@@ -148,6 +148,19 @@ class DSLdapObject(DSLogging, DSLint):
return True
+ def search(self, scope="subtree", filter='objectclass=*'):
+ search_scope = ldap.SCOPE_SUBTREE
+ if scope == 'base':
+ search_scope = ldap.SCOPE_BASE
+ elif scope == 'one':
+ search_scope = ldap.SCOPE_ONE
+ elif scope == 'subtree':
+ search_scope = ldap.SCOPE_SUBTREE
+ return self._instance.search_ext_s(self._dn, search_scope, filter,
+ serverctrls=self._server_controls,
+ clientctrls=self._client_controls,
+ escapehatch='i am sure')
+
def display(self, attrlist=['*']):
"""Get an entry but represent it as a string LDIF
--
2.31.1

View File

@ -0,0 +1,121 @@
From 2f0218f91d35c83a2aaecb71849a54b2481390ab Mon Sep 17 00:00:00 2001
From: Firstyear <william@blackhats.net.au>
Date: Fri, 9 Jul 2021 11:53:35 +1000
Subject: [PATCH] Issue 4817 - BUG - locked crypt accounts on import may allow
all passwords (#4819)
Bug Description: Due to mishanding of short dbpwd hashes, the
crypt_r algorithm was misused and was only comparing salts
in some cases, rather than checking the actual content
of the password.
Fix Description: Stricter checks on dbpwd lengths to ensure
that content passed to crypt_r has at least 2 salt bytes and
1 hash byte, as well as stricter checks on ct_memcmp to ensure
that compared values are the same length, rather than potentially
allowing overruns/short comparisons.
fixes: https://github.com/389ds/389-ds-base/issues/4817
Author: William Brown <william@blackhats.net.au>
Review by: @mreynolds389
---
.../password/pwd_crypt_asterisk_test.py | 50 +++++++++++++++++++
ldap/servers/plugins/pwdstorage/crypt_pwd.c | 20 +++++---
2 files changed, 64 insertions(+), 6 deletions(-)
create mode 100644 dirsrvtests/tests/suites/password/pwd_crypt_asterisk_test.py
diff --git a/dirsrvtests/tests/suites/password/pwd_crypt_asterisk_test.py b/dirsrvtests/tests/suites/password/pwd_crypt_asterisk_test.py
new file mode 100644
index 000000000..d76614db1
--- /dev/null
+++ b/dirsrvtests/tests/suites/password/pwd_crypt_asterisk_test.py
@@ -0,0 +1,50 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2021 William Brown <william@blackhats.net.au>
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import ldap
+import pytest
+from lib389.topologies import topology_st
+from lib389.idm.user import UserAccounts
+from lib389._constants import (DEFAULT_SUFFIX, PASSWORD)
+
+pytestmark = pytest.mark.tier1
+
+def test_password_crypt_asterisk_is_rejected(topology_st):
+ """It was reported that {CRYPT}* was allowing all passwords to be
+ valid in the bind process. This checks that we should be rejecting
+ these as they should represent locked accounts. Similar, {CRYPT}!
+
+ :id: 0b8f1a6a-f3eb-4443-985e-da14d0939dc3
+ :setup: Single instance
+ :steps: 1. Set a password hash in with CRYPT and the content *
+ 2. Test a bind
+ 3. Set a password hash in with CRYPT and the content !
+ 4. Test a bind
+ :expectedresults:
+ 1. Successfully set the values
+ 2. The bind fails
+ 3. Successfully set the values
+ 4. The bind fails
+ """
+ topology_st.standalone.config.set('nsslapd-allow-hashed-passwords', 'on')
+ topology_st.standalone.config.set('nsslapd-enable-upgrade-hash', 'off')
+
+ users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX)
+ user = users.create_test_user()
+
+ user.set('userPassword', "{CRYPT}*")
+
+ # Attempt to bind with incorrect password.
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
+ badconn = user.bind('badpassword')
+
+ user.set('userPassword', "{CRYPT}!")
+ # Attempt to bind with incorrect password.
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
+ badconn = user.bind('badpassword')
+
diff --git a/ldap/servers/plugins/pwdstorage/crypt_pwd.c b/ldap/servers/plugins/pwdstorage/crypt_pwd.c
index 9031b2199..1b37d41ed 100644
--- a/ldap/servers/plugins/pwdstorage/crypt_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/crypt_pwd.c
@@ -48,15 +48,23 @@ static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
int
crypt_pw_cmp(const char *userpwd, const char *dbpwd)
{
- int rc;
- char *cp;
+ int rc = -1;
+ char *cp = NULL;
+ size_t dbpwd_len = strlen(dbpwd);
struct crypt_data data;
data.initialized = 0;
- /* we use salt (first 2 chars) of encoded password in call to crypt_r() */
- cp = crypt_r(userpwd, dbpwd, &data);
- if (cp) {
- rc = slapi_ct_memcmp(dbpwd, cp, strlen(dbpwd));
+ /*
+ * there MUST be at least 2 chars of salt and some pw bytes, else this is INVALID and will
+ * allow any password to bind as we then only compare SALTS.
+ */
+ if (dbpwd_len >= 3) {
+ /* we use salt (first 2 chars) of encoded password in call to crypt_r() */
+ cp = crypt_r(userpwd, dbpwd, &data);
+ }
+ /* If these are not the same length, we can not proceed safely with memcmp. */
+ if (cp && dbpwd_len == strlen(cp)) {
+ rc = slapi_ct_memcmp(dbpwd, cp, dbpwd_len);
} else {
rc = -1;
}
--
2.31.1

View File

@ -0,0 +1,39 @@
From 31d53e7da585723e66b838dcf34b77ea7c9968c6 Mon Sep 17 00:00:00 2001
From: tbordaz <tbordaz@redhat.com>
Date: Wed, 21 Jul 2021 09:16:30 +0200
Subject: [PATCH] Issue 4837 - persistent search returns entries even when an
error is returned by content-sync-plugin (#4838)
Bug description:
When a ldap client sends a sync request control, the server response may contain a sync state control.
If the server fails to create the control the search should fail.
Fix description:
In case the server fails to create the response control
logs the failure of the pre_search
relates: https://github.com/389ds/389-ds-base/issues/4837
Reviewed by: Simon Pichugin
Platforms tested: RH8.4
---
ldap/servers/plugins/sync/sync_refresh.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/plugins/sync/sync_refresh.c b/ldap/servers/plugins/sync/sync_refresh.c
index 646ff760b..4cbb6a949 100644
--- a/ldap/servers/plugins/sync/sync_refresh.c
+++ b/ldap/servers/plugins/sync/sync_refresh.c
@@ -213,7 +213,7 @@ sync_srch_refresh_pre_entry(Slapi_PBlock *pb)
Slapi_Entry *e;
slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
LDAPControl **ctrl = (LDAPControl **)slapi_ch_calloc(2, sizeof(LDAPControl *));
- sync_create_state_control(e, &ctrl[0], LDAP_SYNC_ADD, NULL);
+ rc = sync_create_state_control(e, &ctrl[0], LDAP_SYNC_ADD, NULL);
slapi_pblock_set(pb, SLAPI_SEARCH_CTRLS, ctrl);
}
return (rc);
--
2.31.1

View File

@ -0,0 +1,49 @@
From 616dc9964a4675dea2ab2c2efb9bd31c3903e29d Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 26 Jul 2021 15:22:08 -0400
Subject: [PATCH] Hardcode gost crypt passsword storage scheme
---
.../plugins/pwdstorage/gost_yescrypt.c | 22 -------------------
1 file changed, 22 deletions(-)
diff --git a/ldap/servers/plugins/pwdstorage/gost_yescrypt.c b/ldap/servers/plugins/pwdstorage/gost_yescrypt.c
index 67b39395e..7b0d1653c 100644
--- a/ldap/servers/plugins/pwdstorage/gost_yescrypt.c
+++ b/ldap/servers/plugins/pwdstorage/gost_yescrypt.c
@@ -11,7 +11,6 @@
#include <crypt.h>
-#ifdef XCRYPT_VERSION_STR
#include <errno.h>
int
gost_yescrypt_pw_cmp(const char *userpwd, const char *dbpwd)
@@ -64,24 +63,3 @@ gost_yescrypt_pw_enc(const char *pwd)
return enc;
}
-#else
-
-/*
- * We do not have xcrypt, so always fail all checks.
- */
-int
-gost_yescrypt_pw_cmp(const char *userpwd __attribute__((unused)), const char *dbpwd __attribute__((unused)))
-{
- slapi_log_err(SLAPI_LOG_ERR, GOST_YESCRYPT_SCHEME_NAME,
- "Unable to use gost_yescrypt_pw_cmp, xcrypt is not available.\n");
- return 1;
-}
-
-char *
-gost_yescrypt_pw_enc(const char *pwd __attribute__((unused)))
-{
- slapi_log_err(SLAPI_LOG_ERR, GOST_YESCRYPT_SCHEME_NAME,
- "Unable to use gost_yescrypt_pw_enc, xcrypt is not available.\n");
- return NULL;
-}
-#endif
--
2.31.1

565
SOURCES/Cargo.lock generated Normal file
View File

@ -0,0 +1,565 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "base64"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cbindgen"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9daec6140ab4dcd38c3dd57e580b59a621172a526ac79f1527af760a55afeafd"
dependencies = [
"clap",
"log",
"proc-macro2",
"quote",
"serde",
"serde_json",
"syn",
"tempfile",
"toml",
]
[[package]]
name = "cc"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "entryuuid"
version = "0.1.0"
dependencies = [
"cc",
"libc",
"paste",
"slapi_r_plugin",
"uuid",
]
[[package]]
name = "entryuuid_syntax"
version = "0.1.0"
dependencies = [
"cc",
"libc",
"paste",
"slapi_r_plugin",
"uuid",
]
[[package]]
name = "fernet"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93804560e638370a8be6d59ce71ed803e55e230abdbf42598e666b41adda9b1f"
dependencies = [
"base64",
"byteorder",
"getrandom",
"openssl",
"zeroize",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "getrandom"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hermit-abi"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
dependencies = [
"libc",
]
[[package]]
name = "itoa"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "jobserver"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd"
dependencies = [
"libc",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
[[package]]
name = "librnsslapd"
version = "0.1.0"
dependencies = [
"cbindgen",
"libc",
"slapd",
]
[[package]]
name = "librslapd"
version = "0.1.0"
dependencies = [
"cbindgen",
"libc",
"slapd",
]
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]]
name = "once_cell"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
[[package]]
name = "openssl"
version = "0.10.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d7830286ad6a3973c0f1d9b73738f69c76b739301d0229c4b96501695cbe4c8"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-sys",
]
[[package]]
name = "openssl-sys"
version = "0.9.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b0d6fb7d80f877617dfcb014e605e2b5ab2fb0afdf27935219bb6bd984cb98"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "paste"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
dependencies = [
"paste-impl",
"proc-macro-hack",
]
[[package]]
name = "paste-impl"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
dependencies = [
"proc-macro-hack",
]
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
dependencies = [
"rand_core",
]
[[package]]
name = "redox_syscall"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
dependencies = [
"bitflags",
]
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "rsds"
version = "0.1.0"
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "serde"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "slapd"
version = "0.1.0"
dependencies = [
"fernet",
]
[[package]]
name = "slapi_r_plugin"
version = "0.1.0"
dependencies = [
"lazy_static",
"libc",
"paste",
"uuid",
]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "syn"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "synstructure"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
dependencies = [
"proc-macro2",
"quote",
"syn",
"unicode-xid",
]
[[package]]
name = "tempfile"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if",
"libc",
"rand",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "toml"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
"serde",
]
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom",
]
[[package]]
name = "vcpkg"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "025ce40a007e1907e58d5bc1a594def78e5573bb0b1160bc389634e8f12e4faa"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "zeroize"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]

View File

@ -16,7 +16,7 @@ ExcludeArch: i686
%global use_Socket6 0
%global use_asan 0
%global use_rust 0
%global use_rust 1
%global use_legacy 1
%global bundle_jemalloc 1
%if %{use_asan}
@ -42,10 +42,13 @@ ExcludeArch: i686
# set PIE flag
%global _hardened_build 1
# Filter argparse-manpage from autogenerated package Requires
%global __requires_exclude ^python.*argparse-manpage
Summary: 389 Directory Server (base)
Name: 389-ds-base
Version: 1.4.3.23
Release: %{?relprefix}2%{?prerel}%{?dist}
Release: %{?relprefix}7%{?prerel}%{?dist}
License: GPLv3+
URL: https://www.port389.org
Group: System Environment/Daemons
@ -246,6 +249,21 @@ Patch09: 0009-Issue-4623-RFE-Monitor-the-current-DB-locks-4762.patch
Patch10: 0010-Issue-4764-replicated-operation-sometime-checks-ACI-.patch
Patch11: 0011-Issue-4778-RFE-Allow-setting-TOD-for-db-compaction-a.patch
Patch12: 0012-Issue-4778-RFE-Add-changelog-compaction-task-in-1.4..patch
Patch13: 0013-Issue-4797-ACL-IP-ADDRESS-evaluation-may-corrupt-c_i.patch
Patch14: 0014-Issue-4396-Minor-memory-leak-in-backend-4558-4572.patch
Patch15: 0015-Issue-4700-Regression-in-winsync-replication-agreeme.patch
Patch16: 0016-Issue-4725-Fix-compiler-warnings.patch
Patch17: 0017-Issue-4814-_cl5_get_tod_expiration-may-crash-at-star.patch
Patch18: 0018-Issue-4789-Temporary-password-rules-are-not-enforce-.patch
Patch19: 0019-Issue-4788-CLI-should-support-Temporary-Password-Rul.patch
Patch20: 0020-Issue-4447-Crash-when-the-Referential-Integrity-log-.patch
Patch21: 0021-Issue-4791-Missing-dependency-for-RetroCL-RFE.patch
Patch22: 0022-Issue-4656-remove-problematic-language-from-ds-replc.patch
Patch23: 0023-Issue-4443-Internal-unindexed-searches-in-syncrepl-r.patch
Patch24: 0024-Issue-4817-BUG-locked-crypt-accounts-on-import-may-a.patch
Patch25: 0025-Issue-4837-persistent-search-returns-entries-even-wh.patch
Patch26: 0026-Hardcode-gost-crypt-passsword-storage-scheme.patch
%description
389 Directory Server is an LDAPv3 compliant server. The base package includes
@ -864,6 +882,33 @@ exit 0
%doc README.md
%changelog
* Mon Jul 26 2021 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.23-7
- Bump version to 1.4.3.23-7
- Resolves: Bug 1983921 - persistent search returns entries even when an error is returned by content-sync-plugin
* Fri Jul 16 2021 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.23-6
- Bump version to 1.4.3.23-6
- Resolves: Bug 1982787 - CRYPT password hash with asterisk allows any bind attempt to succeed
* Thu Jul 15 2021 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.23-5
- Bump version to 1.4.3.23-5
- Resolves: Bug 1951020 - Internal unindexed searches in syncrepl
- Resolves: Bug 1978279 - ds-replcheck state output message has 'Master' instead of 'Supplier'
* Tue Jun 29 2021 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.23-4
- Bump version to 1.4.3.23-4
- Resolves: Bug 1976906 - Instance crash at restart after changelog configuration
- Resolves: Bug 1480323 - ns-slapd crash at startup - Segmentation fault in strcmpi_fast() when the Referential Integrity log is manually edited
- Resolves: Bug 1967596 - Temporary password - add CLI and fix compiler errors
* Thu Jun 17 2021 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.23-3
- Bump version to 1.4.3.23-3
- Resolves: Bug 1944494 - support for RFC 4530 entryUUID attribute
- Resolves: Bug 1967839 - ACIs are being evaluated against the Replication Manager account in a replication context
- Resolves: Bug 1970259 - A connection can be erroneously flagged as replication conn during evaluation of an aci with ip bind rule
- Resolves: Bug 1972590 - Large updates can reset the CLcache to the beginning of the changelog
- Resolves: Bug 1903221 - Memory leak in 389ds backend (Minor)
* Sun May 30 2021 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.23-2
- Bump version to 1.4.3.23-2
- Resolves: Bug 1812286 - RFE - Monitor the current DB locks ( nsslapd-db-current-locks )