import 389-ds-base-1.3.8.4-15.el7

This commit is contained in:
CentOS Sources 2018-10-30 00:56:24 -04:00
parent 6e88154da0
commit edc5f25778
108 changed files with 811 additions and 22605 deletions

View file

@ -1 +1 @@
77dee99c82e77c3c3c8579b443ebb68e63d51702 SOURCES/389-ds-base-1.3.7.5.tar.bz2
930c13abb2fc444f1dbd0443ed72a5d5b14c48da SOURCES/389-ds-base-1.3.8.4.tar.bz2

2
.gitignore vendored
View file

@ -1 +1 @@
SOURCES/389-ds-base-1.3.7.5.tar.bz2
SOURCES/389-ds-base-1.3.8.4.tar.bz2

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,190 @@
From da5a1bbb4e4352b8df10c84572441d47217b6c2c Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 6 Jul 2018 11:37:56 -0400
Subject: [PATCH] Ticket 49830 - Import fails if backend name is "default"
Bug Description: The server was previously reserving the backend
name "default". If you tried to import on a
backend with this name the import would skip all
child entries
Fix Description: Change the default backend name to something
obscure, instead of "default".
Also improved lib389's dbgen to generate the
correct "dc" attribute value in the root node.
https://pagure.io/389-ds-base/issue/49830
Reviewed by: spichugi(Thanks!)
(cherry picked from commit 8fa838a4ffd4d0c15ae51cb21f246bb1f2dea2a1)
---
.../tests/suites/import/regression_test.py | 46 +++++++++++++++++++
ldap/servers/slapd/defbackend.c | 4 +-
ldap/servers/slapd/mapping_tree.c | 7 ++-
ldap/servers/slapd/slap.h | 3 ++
src/lib389/lib389/dbgen.py | 13 +++++-
5 files changed, 66 insertions(+), 7 deletions(-)
diff --git a/dirsrvtests/tests/suites/import/regression_test.py b/dirsrvtests/tests/suites/import/regression_test.py
index ad51721a1..d83d00323 100644
--- a/dirsrvtests/tests/suites/import/regression_test.py
+++ b/dirsrvtests/tests/suites/import/regression_test.py
@@ -23,6 +23,52 @@ TEST_SUFFIX1 = "dc=importest1,dc=com"
TEST_BACKEND1 = "importest1"
TEST_SUFFIX2 = "dc=importest2,dc=com"
TEST_BACKEND2 = "importest2"
+TEST_DEFAULT_SUFFIX = "dc=default,dc=com"
+TEST_DEFAULT_NAME = "default"
+
+
+def test_import_be_default(topo):
+ """ Create a backend using the name "default". previously this name was
+ used int
+
+ :id: 8e507beb-e917-4330-8cac-1ff0eee10508
+ :feature: Import
+ :setup: Standalone instance
+ :steps:
+ 1. Create a test suffix using the be name of "default"
+ 2. Create an ldif for the "default" backend
+ 3. Import ldif
+ 4. Verify all entries were imported
+ :expectedresults:
+ 1. Success
+ 2. Success
+ 3. Success
+ 4. Success
+ """
+ log.info('Adding suffix:{} and backend: {}...'.format(TEST_DEFAULT_SUFFIX,
+ TEST_DEFAULT_NAME))
+ backends = Backends(topo.standalone)
+ backends.create(properties={BACKEND_SUFFIX: TEST_DEFAULT_SUFFIX,
+ BACKEND_NAME: TEST_DEFAULT_NAME})
+
+ log.info('Create LDIF file and import it...')
+ ldif_dir = topo.standalone.get_ldif_dir()
+ ldif_file = os.path.join(ldif_dir, 'default.ldif')
+ dbgen(topo.standalone, 5, ldif_file, TEST_DEFAULT_SUFFIX)
+
+ log.info('Stopping the server and running offline import...')
+ topo.standalone.stop()
+ assert topo.standalone.ldif2db(TEST_DEFAULT_NAME, None, None,
+ None, ldif_file)
+ topo.standalone.start()
+
+ log.info('Verifying entry count after import...')
+ entries = topo.standalone.search_s(TEST_DEFAULT_SUFFIX,
+ ldap.SCOPE_SUBTREE,
+ "(objectclass=*)")
+ assert len(entries) > 1
+
+ log.info('Test PASSED')
def test_del_suffix_import(topo):
diff --git a/ldap/servers/slapd/defbackend.c b/ldap/servers/slapd/defbackend.c
index aa709da87..b0465e297 100644
--- a/ldap/servers/slapd/defbackend.c
+++ b/ldap/servers/slapd/defbackend.c
@@ -23,8 +23,6 @@
/*
* ---------------- Macros ---------------------------------------------------
*/
-#define DEFBACKEND_TYPE "default"
-
#define DEFBACKEND_OP_NOT_HANDLED 0
#define DEFBACKEND_OP_HANDLED 1
@@ -65,7 +63,7 @@ defbackend_init(void)
/*
* create a new backend
*/
- defbackend_backend = slapi_be_new(DEFBACKEND_TYPE, DEFBACKEND_TYPE, 1 /* Private */, 0 /* Do Not Log Changes */);
+ defbackend_backend = slapi_be_new(DEFBACKEND_TYPE, DEFBACKEND_NAME, 1 /* Private */, 0 /* Do Not Log Changes */);
if ((rc = slapi_pblock_set(pb, SLAPI_BACKEND, defbackend_backend)) != 0) {
errmsg = "slapi_pblock_set SLAPI_BACKEND failed";
goto cleanup_and_return;
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
index 472a2f6aa..834949a67 100644
--- a/ldap/servers/slapd/mapping_tree.c
+++ b/ldap/servers/slapd/mapping_tree.c
@@ -748,7 +748,7 @@ mapping_tree_entry_add(Slapi_Entry *entry, mapping_tree_node **newnodep)
be_names = (char **)slapi_ch_calloc(1, sizeof(char *));
be_states = (int *)slapi_ch_calloc(1, sizeof(int));
- tmp_backend_name = (char *)slapi_ch_strdup("default"); /* "NULL_CONTAINER" */
+ tmp_backend_name = (char *)slapi_ch_strdup(DEFBACKEND_NAME); /* "NULL_CONTAINER" */
(be_names)[be_list_count] = tmp_backend_name;
/* set backend as started by default */
@@ -2250,7 +2250,10 @@ slapi_mapping_tree_select_all(Slapi_PBlock *pb, Slapi_Backend **be_list, Slapi_E
if (ret != LDAP_SUCCESS) {
/* flag we have problems at least on part of the tree */
flag_partial_result = 1;
- } else if ((((!slapi_sdn_issuffix(sdn, slapi_mtn_get_dn(node)) && !slapi_sdn_issuffix(slapi_mtn_get_dn(node), sdn))) || ((node_list == mapping_tree_root) && node->mtn_private && (scope != LDAP_SCOPE_BASE))) && (!be || strncmp(be->be_name, "default", 8))) {
+ } else if ((((!slapi_sdn_issuffix(sdn, slapi_mtn_get_dn(node)) && !slapi_sdn_issuffix(slapi_mtn_get_dn(node), sdn))) ||
+ ((node_list == mapping_tree_root) && node->mtn_private && (scope != LDAP_SCOPE_BASE))) &&
+ (!be || strncmp(be->be_name, DEFBACKEND_NAME, 8)))
+ {
if (be && !be_isdeleted(be)) {
/* wrong backend or referall, ignore it */
slapi_log_err(SLAPI_LOG_ARGS, "slapi_mapping_tree_select_all",
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 7378c2d2a..eb97cdcc4 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -45,6 +45,9 @@ static char ptokPBE[34] = "Internal (Software) Token ";
#define SLAPD_EXEMODE_DBVERIFY 12
#define SLAPD_EXEMODE_UPGRADEDNFORMAT 13
+#define DEFBACKEND_TYPE "default"
+#define DEFBACKEND_NAME "DirectoryServerDefaultBackend"
+
#define LDAP_SYSLOG
#include <syslog.h>
#define RLIM_TYPE int
diff --git a/src/lib389/lib389/dbgen.py b/src/lib389/lib389/dbgen.py
index a0cda9430..68455b480 100644
--- a/src/lib389/lib389/dbgen.py
+++ b/src/lib389/lib389/dbgen.py
@@ -113,8 +113,13 @@ usercertificate;binary:: MIIBvjCCASegAwIBAgIBAjANBgkqhkiG9w0BAQQFADAnMQ8wDQYD
DBGEN_HEADER = """dn: {SUFFIX}
objectClass: top
objectClass: domain
+<<<<<<< HEAD
dc: example
aci: (target=ldap:///{SUFFIX})(targetattr=*)(version 3.0; acl "acl1"; allow(write) userdn = "ldap:///self";)
+=======
+dc: {RDN}
+aci: (target=ldap:///{SUFFIX})(targetattr=*)(version 3.0; acl "acl1"; allow(write) userdn = "ldap:///self";)
+>>>>>>> 8fa838a4f... Ticket 49830 - Import fails if backend name is "default"
aci: (target=ldap:///{SUFFIX})(targetattr=*)(version 3.0; acl "acl2"; allow(write) groupdn = "ldap:///cn=Directory Administrators, {SUFFIX}";)
aci: (target=ldap:///{SUFFIX})(targetattr=*)(version 3.0; acl "acl3"; allow(read, search, compare) userdn = "ldap:///anyone";)
@@ -145,7 +150,7 @@ ou: Payroll
"""
-def dbgen(instance, number, ldif_file, suffix):
+def dbgen(instance, number, ldif_file, suffix, pseudol10n=False):
familyname_file = os.path.join(instance.ds_paths.data_dir, 'dirsrv/data/dbgen-FamilyNames')
givename_file = os.path.join(instance.ds_paths.data_dir, 'dirsrv/data/dbgen-GivenNames')
familynames = []
@@ -156,7 +161,11 @@ def dbgen(instance, number, ldif_file, suffix):
givennames = [n.strip() for n in f]
with open(ldif_file, 'w') as output:
- output.write(DBGEN_HEADER.format(SUFFIX=suffix))
+ rdn = suffix.split(",", 1)[0].split("=", 1)[1]
+ output.write(DBGEN_HEADER.format(SUFFIX=suffix, RDN=rdn))
+ for ou in DBGEN_OUS:
+ ou = pseudolocalize(ou) if pseudol10n else ou
+ output.write(DBGEN_OU_TEMPLATE.format(SUFFIX=suffix, OU=ou))
for i in range(0, number):
# Pick a random ou
ou = random.choice(DBGEN_OUS)
--
2.17.1

View file

@ -0,0 +1,51 @@
From 0ea14f45cbc834e4791fdc393c5a2a042fd08101 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Tue, 10 Jul 2018 12:07:45 +0200
Subject: [PATCH] Ticket 48818 - For a replica bindDNGroup, should be fetched
the first time it is used not when the replica is started
Bug Description:
The fetching of the bindDNGroup is working as designed but this ticket is to make it more flexible
At startup, if the group does not contain the replica_mgr.
No replication session will succeed until bindDnGroupCheckInterval delay.
updatedn_group_last_check is the timestamp of the last fetch. At startup
updatedn_group_last_check is set to the current time. So the next fetch will happen not before
updatedn_group_last_check+bindDnGroupCheckInterval.
If the groupDn is changed after startup, no incoming replication can happen for the first
bindDnGroupCheckInterval seconds
Fix Description:
The fix consist to unset updatedn_group_last_check so that the group will be fetch when the first
incoming replication session will happen.
https://pagure.io/389-ds-base/issue/49818
Reviewed by: Mark Reynolds, Simon Spichugi (thanks !!!)
Platforms tested: F27
Flag Day: no
Doc impact: no
---
ldap/servers/plugins/replication/repl5_replica.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index dee20875e..41cad3bf0 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -2026,7 +2026,7 @@ _replica_init_from_config(Replica *r, Slapi_Entry *e, char *errortext)
/* get replication bind dn groups */
r->updatedn_groups = replica_updatedn_group_new(e);
r->groupdn_list = replica_groupdn_list_new(r->updatedn_groups);
- r->updatedn_group_last_check = time(NULL);
+ r->updatedn_group_last_check = 0;
/* get groupdn check interval */
if ((val = slapi_entry_attr_get_charptr(e, attr_replicaBindDnGroupCheckInterval))) {
if (repl_config_valid_num(attr_replicaBindDnGroupCheckInterval, val, -1, INT_MAX, &rc, errormsg, &interval) != 0) {
--
2.17.1

File diff suppressed because it is too large Load diff

View file

@ -1,286 +0,0 @@
From 8308e20075adacfdf1827aaa3230e503207832bc Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 2 Oct 2017 09:33:29 -0400
Subject: [PATCH] Ticket 49385 - Fix coverity warnings
Description: This fixes coverity issues found from RHEL build of 1.3.7
https://pagure.io/389-ds-base/issue/49385
Reviewed by: lkrispenz(Thanks!)
(cherry picked from commit 805e8f4d3016eb9c7906c1416482047a234d51ba)
---
ldap/servers/plugins/http/http_impl.c | 1 +
ldap/servers/plugins/replication/urp.c | 10 ++++++----
ldap/servers/plugins/syntaxes/string.c | 1 +
ldap/servers/slapd/back-ldbm/dbversion.c | 2 +-
ldap/servers/slapd/back-ldbm/index.c | 1 +
ldap/servers/slapd/conntable.c | 2 +-
ldap/servers/slapd/modify.c | 1 +
ldap/servers/slapd/plugin.c | 3 ++-
ldap/servers/slapd/referral.c | 18 +++++++++---------
ldap/servers/slapd/task.c | 8 ++++++--
ldap/servers/snmp/main.c | 13 +++++++++++--
11 files changed, 40 insertions(+), 20 deletions(-)
diff --git a/ldap/servers/plugins/http/http_impl.c b/ldap/servers/plugins/http/http_impl.c
index d8bbe38..350c839 100644
--- a/ldap/servers/plugins/http/http_impl.c
+++ b/ldap/servers/plugins/http/http_impl.c
@@ -601,6 +601,7 @@ sendPostReq(PRFileDesc *fd, const char *path, httpheader **httpheaderArray, char
if (path) {
path_len = strlen(path);
} else {
+ path = "";
path_len = 0;
}
diff --git a/ldap/servers/plugins/replication/urp.c b/ldap/servers/plugins/replication/urp.c
index 3d63c64..9534c03 100644
--- a/ldap/servers/plugins/replication/urp.c
+++ b/ldap/servers/plugins/replication/urp.c
@@ -856,7 +856,7 @@ urp_post_delete_operation(Slapi_PBlock *pb)
static int
urp_fixup_add_cenotaph (Slapi_PBlock *pb, char *sessionid, CSN *opcsn)
{
- Slapi_PBlock *add_pb = slapi_pblock_new();
+ Slapi_PBlock *add_pb;
Slapi_Entry *cenotaph = NULL;
Slapi_Entry *pre_entry = NULL;
int ret = 0;
@@ -886,6 +886,7 @@ urp_fixup_add_cenotaph (Slapi_PBlock *pb, char *sessionid, CSN *opcsn)
slapi_rdn_remove_attr (rdn, SLAPI_ATTR_UNIQUEID );
slapi_rdn_add(rdn, "cenotaphID", uniqueid);
newdn = slapi_ch_smprintf("%s,%s", slapi_rdn_get_rdn(rdn), parentdn);
+ slapi_rdn_free(&rdn);
slapi_ch_free_string(&parentdn);
/* slapi_sdn_free(&pre_sdn); */
@@ -902,6 +903,7 @@ urp_fixup_add_cenotaph (Slapi_PBlock *pb, char *sessionid, CSN *opcsn)
slapi_log_err(SLAPI_LOG_REPL, sessionid,
"urp_fixup_add_cenotaph - addinng cenotaph: %s \n", newdn);
+ add_pb = slapi_pblock_new();
slapi_pblock_init(add_pb);
slapi_add_entry_internal_set_pb(add_pb,
@@ -1661,8 +1663,8 @@ urp_conflict_to_glue (char *sessionid, const Slapi_Entry *entry, Slapi_DN *paren
"urp_conflict_to_glue failed(%d) - %s --> %s\n", op_result, basedn, newrdn);
rc = 1;
}
- slapi_ch_free ( (void**)&newrdn );
}
+ slapi_rdn_free(&parentrdn);
return rc;
}
/*
@@ -2166,11 +2168,11 @@ mod_objectclass_attr(const char *uniqueid, const Slapi_DN *entrysdn, const Slapi
{
Slapi_Mods smods;
int op_result;
- char csnstr[CSN_STRSIZE+1];
+ char csnstr[CSN_STRSIZE+1] = {0};
slapi_mods_init(&smods, 3);
slapi_mods_add(&smods, LDAP_MOD_ADD, "objectclass", strlen("ldapsubentry"),"ldapsubentry");
- slapi_mods_add(&smods, LDAP_MOD_REPLACE, "conflictcsn", strlen(csnstr),csn_as_string(opcsn, PR_FALSE, csnstr));
+ slapi_mods_add(&smods, LDAP_MOD_REPLACE, "conflictcsn", CSN_STRSIZE, csn_as_string(opcsn, PR_FALSE, csnstr));
op_result = urp_fixup_modify_entry(uniqueid, entrysdn, opcsn, &smods, 0);
slapi_mods_done(&smods);
if (op_result == LDAP_TYPE_OR_VALUE_EXISTS) {
diff --git a/ldap/servers/plugins/syntaxes/string.c b/ldap/servers/plugins/syntaxes/string.c
index f50dc13..e05ca7f 100644
--- a/ldap/servers/plugins/syntaxes/string.c
+++ b/ldap/servers/plugins/syntaxes/string.c
@@ -391,6 +391,7 @@ bailout:
if (free_re) {
slapi_re_free(re);
}
+ slapi_ch_free_string(&alt);
slapi_ch_free((void **)&tmpbuf); /* NULL is fine */
slapi_ch_free((void **)&bigpat); /* NULL is fine */
diff --git a/ldap/servers/slapd/back-ldbm/dbversion.c b/ldap/servers/slapd/back-ldbm/dbversion.c
index 01f86f4..5a77abd 100644
--- a/ldap/servers/slapd/back-ldbm/dbversion.c
+++ b/ldap/servers/slapd/back-ldbm/dbversion.c
@@ -159,7 +159,7 @@ dbversion_read(struct ldbminfo *li, const char *directory, char **ldbmversion, c
}
(void)PR_Close(prfd);
- if (*dataversion == NULL) {
+ if (dataversion == NULL || *dataversion == NULL) {
slapi_log_err(SLAPI_LOG_DEBUG, "dbversion_read", "dataversion not present in \"%s\"\n", filename);
}
if (*ldbmversion == NULL) {
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
index 798480e..58b11ed 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -1063,6 +1063,7 @@ index_read_ext_allids(
/* The database might not exist. We have to assume it means empty set */
slapi_log_err(SLAPI_LOG_TRACE, "index_read_ext_allids", "Failed to access idl index for %s\n", basetype);
slapi_log_err(SLAPI_LOG_TRACE, "index_read_ext_allids", "Assuming %s has no index values\n", basetype);
+ idl_free(&idl);
idl = idl_alloc(0);
break;
} else {
diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c
index c04ca0f..7c57b47 100644
--- a/ldap/servers/slapd/conntable.c
+++ b/ldap/servers/slapd/conntable.c
@@ -347,7 +347,7 @@ connection_table_as_entry(Connection_Table *ct, Slapi_Entry *e)
PR_EnterMonitor(ct->c[i].c_mutex);
if (ct->c[i].c_sd != SLAPD_INVALID_SOCKET) {
- char buf2[20];
+ char buf2[SLAPI_TIMESTAMP_BUFSIZE+1];
size_t lendn = ct->c[i].c_dn ? strlen(ct->c[i].c_dn) : 6; /* "NULLDN" */
size_t lenip = ct->c[i].c_ipaddr ? strlen(ct->c[i].c_ipaddr) : 0;
size_t lenconn = 1;
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
index 4b5a676..6309975 100644
--- a/ldap/servers/slapd/modify.c
+++ b/ldap/servers/slapd/modify.c
@@ -923,6 +923,7 @@ op_shared_modify(Slapi_PBlock *pb, int pw_change, char *old_pw)
if (pw_encodevals_ext(pb, sdn, va)) {
slapi_log_err(SLAPI_LOG_CRIT, "op_shared_modify", "Unable to hash userPassword attribute for %s.\n", slapi_entry_get_dn_const(e));
send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Unable to store attribute \"userPassword\" correctly\n", 0, NULL);
+ valuearray_free(&va);
goto free_and_return;
}
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index f47ff9b..e02133a 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -4242,7 +4242,7 @@ bail:
int
slapi_set_plugin_default_config(const char *type, Slapi_Value *value)
{
- Slapi_PBlock *pb = slapi_pblock_new();
+ Slapi_PBlock *pb;
Slapi_Entry **entries = NULL;
int rc = LDAP_SUCCESS;
char **search_attrs = NULL; /* used by search */
@@ -4251,6 +4251,7 @@ slapi_set_plugin_default_config(const char *type, Slapi_Value *value)
return rc;
}
+ pb = slapi_pblock_new();
charray_add(&search_attrs, slapi_ch_strdup(type));
/* cn=plugin default config,cn=config */
diff --git a/ldap/servers/slapd/referral.c b/ldap/servers/slapd/referral.c
index c5d9ffc..5935820 100644
--- a/ldap/servers/slapd/referral.c
+++ b/ldap/servers/slapd/referral.c
@@ -153,7 +153,7 @@ referrals_free(void)
struct berval **
ref_adjust(Slapi_PBlock *pb, struct berval **urls, const Slapi_DN *refsdn, int is_reference)
{
- int i, len, scope;
+ int i, len, scope = 0;
Slapi_DN *sdn = NULL;
char *p, *opdn_norm;
struct berval **urlscopy;
@@ -195,9 +195,9 @@ ref_adjust(Slapi_PBlock *pb, struct berval **urls, const Slapi_DN *refsdn, int i
for (i = 0; urls[i] != NULL; ++i) {
/*
- * duplicate the URL, stripping off the label if there is one and
- * leaving extra room for "??base" in case we need to append that.
- */
+ * duplicate the URL, stripping off the label if there is one and
+ * leaving extra room for "??base" in case we need to append that.
+ */
urlscopy[i] = (struct berval *)slapi_ch_malloc(
sizeof(struct berval));
if ((p = strchr(urls[i]->bv_val, ' ')) == NULL) {
@@ -210,16 +210,16 @@ ref_adjust(Slapi_PBlock *pb, struct berval **urls, const Slapi_DN *refsdn, int i
urlscopy[i]->bv_val[len] = '\0';
/*
- * adjust the baseDN as needed and set the length
- */
+ * adjust the baseDN as needed and set the length
+ */
adjust_referral_basedn(&urlscopy[i]->bv_val, refsdn,
opdn_norm, is_reference);
urlscopy[i]->bv_len = strlen(urlscopy[i]->bv_val);
/*
- * if we are dealing with a continuation reference that resulted
- * from a one-level search, add a scope of base to the URL.
- */
+ * if we are dealing with a continuation reference that resulted
+ * from a one-level search, add a scope of base to the URL.
+ */
if (is_reference && operation_get_type(op) == SLAPI_OPERATION_SEARCH &&
scope == LDAP_SCOPE_ONELEVEL) {
strcat(urlscopy[i]->bv_val, "??base");
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
index f3d02d9..53a0af5 100644
--- a/ldap/servers/slapd/task.c
+++ b/ldap/servers/slapd/task.c
@@ -278,6 +278,10 @@ slapi_task_log_notice(Slapi_Task *task, char *format, ...)
char buffer[LOG_BUFFER];
size_t len;
+ if (task == NULL) {
+ return;
+ }
+
va_start(ap, format);
PR_vsnprintf(buffer, LOG_BUFFER, format, ap);
va_end(ap);
@@ -1089,11 +1093,11 @@ task_export_thread(void *arg)
slapi_pblock_get(pb, SLAPI_BACKEND_TASK, &task);
g_incr_active_threadcnt();
- for (count = 0, inp = instance_names; *inp; inp++, count++)
+ for (count = 0, inp = instance_names; inp && *inp; inp++, count++)
;
slapi_task_begin(task, count);
- for (inp = instance_names; *inp; inp++) {
+ for (inp = instance_names; inp && *inp; inp++) {
int release_me = 0;
/* lookup the backend */
be = slapi_be_select_by_instance_name((const char *)*inp);
diff --git a/ldap/servers/snmp/main.c b/ldap/servers/snmp/main.c
index 8477831..5bd318d 100644
--- a/ldap/servers/snmp/main.c
+++ b/ldap/servers/snmp/main.c
@@ -21,6 +21,7 @@
#include "ldap.h"
#include "ldif.h"
#include <ctype.h>
+#include <errno.h>
static char *agentx_master = NULL;
static char *agent_logdir = NULL;
@@ -54,9 +55,17 @@ main(int argc, char *argv[])
{
char *s = getenv("DEBUG_SLEEP");
if ((s != NULL) && isdigit(*s)) {
- int secs = atoi(s);
+ char *endp = NULL;
+ long secs;
+ errno = 0;
+
printf("%s pid is %d\n", argv[0], getpid());
- sleep(secs);
+ secs = strtol(s, &endp, 10);
+ if (*endp != '\0' || errno == ERANGE) {
+ sleep(10);
+ } else {
+ sleep(secs);
+ }
}
}
--
2.9.5

View file

@ -0,0 +1,178 @@
From 9f1bbff43c3e6ec01e60d35082b21b83a8795dc2 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 12 Jul 2018 10:48:11 -0400
Subject: [PATCH] Ticket 49546 - Fix issues with MIB file
Description: Change dsMaxThreadsHit to dsMaxThreadsHits, and set the
proper object type for dsIntIndex
https://pagure.io/389-ds-base/issue/49546
Reviewed by: spichugi & firstyear(Thanks!!)
(cherry picked from commit 6d4caac04be4223971de54d292db82734f6d6a44)
---
ldap/servers/slapd/agtmmap.c | 2 +-
ldap/servers/slapd/agtmmap.h | 2 +-
ldap/servers/slapd/connection.c | 2 +-
ldap/servers/slapd/slap.h | 2 +-
ldap/servers/slapd/snmp_collator.c | 6 +++---
ldap/servers/snmp/ldap-agent.c | 4 ++--
ldap/servers/snmp/ldap-agent.h | 2 +-
ldap/servers/snmp/redhat-directory.mib | 8 ++++----
8 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/ldap/servers/slapd/agtmmap.c b/ldap/servers/slapd/agtmmap.c
index fbc730db6..352ccefda 100644
--- a/ldap/servers/slapd/agtmmap.c
+++ b/ldap/servers/slapd/agtmmap.c
@@ -298,7 +298,7 @@ agt_mread_stats(int hdl, struct hdr_stats_t *pHdrInfo, struct ops_stats_t *pDsOp
pDsOpsTbl->dsErrors = pfile_stats->ops_stats.dsErrors;
pDsOpsTbl->dsConnections = pfile_stats->ops_stats.dsConnections;
pDsOpsTbl->dsConnectionsInMaxThreads = pfile_stats->ops_stats.dsConnectionsInMaxThreads;
- pDsOpsTbl->dsMaxThreadsHit = pfile_stats->ops_stats.dsMaxThreadsHit;
+ pDsOpsTbl->dsMaxThreadsHits = pfile_stats->ops_stats.dsMaxThreadsHits;
}
if (pDsEntTbl != NULL) {
diff --git a/ldap/servers/slapd/agtmmap.h b/ldap/servers/slapd/agtmmap.h
index 2397dad3c..fb27ab2c4 100644
--- a/ldap/servers/slapd/agtmmap.h
+++ b/ldap/servers/slapd/agtmmap.h
@@ -102,7 +102,7 @@ struct ops_stats_t
uint64_t dsErrors;
uint64_t dsConnections; /* Number of currently connected clients */
uint64_t dsConnectionSeq; /* Monotonically increasing number bumped on each new conn est */
- uint64_t dsMaxThreadsHit; /* Number of times a connection hit max threads */
+ uint64_t dsMaxThreadsHits; /* Number of times a connection hit max threads */
uint64_t dsConnectionsInMaxThreads; /* current number of connections that are in max threads */
uint64_t dsBytesRecv; /* Count of bytes read from clients */
uint64_t dsBytesSent; /* Count of bytes sent to clients */
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 1dbb49f06..188383b97 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -1911,7 +1911,7 @@ connection_activity(Connection *conn, int maxthreads)
slapi_counter_increment(max_threads_count);
slapi_counter_increment(conns_in_maxthreads);
slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsConnectionsInMaxThreads);
- slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsMaxThreadsHit);
+ slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsMaxThreadsHits);
}
op_stack_obj = connection_get_operation();
connection_add_operation(conn, op_stack_obj->op);
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index eb97cdcc4..a02792648 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1889,7 +1889,7 @@ struct snmp_ops_tbl_t
Slapi_Counter *dsBytesSent; /* Count of bytes sent to clients */
Slapi_Counter *dsEntriesReturned;
Slapi_Counter *dsReferralsReturned;
- Slapi_Counter *dsMaxThreadsHit;
+ Slapi_Counter *dsMaxThreadsHits;
Slapi_Counter *dsConnectionsInMaxThreads;
};
diff --git a/ldap/servers/slapd/snmp_collator.c b/ldap/servers/slapd/snmp_collator.c
index d56379466..1da7ccbb2 100644
--- a/ldap/servers/slapd/snmp_collator.c
+++ b/ldap/servers/slapd/snmp_collator.c
@@ -122,7 +122,7 @@ snmp_collator_init(void)
g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned = slapi_counter_new();
g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned = slapi_counter_new();
g_get_global_snmp_vars()->ops_tbl.dsConnectionsInMaxThreads = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsMaxThreadsHit = slapi_counter_new();
+ g_get_global_snmp_vars()->ops_tbl.dsMaxThreadsHits = slapi_counter_new();
g_get_global_snmp_vars()->entries_tbl.dsMasterEntries = slapi_counter_new();
g_get_global_snmp_vars()->entries_tbl.dsCopyEntries = slapi_counter_new();
g_get_global_snmp_vars()->entries_tbl.dsCacheEntries = slapi_counter_new();
@@ -592,7 +592,7 @@ snmp_update_ops_table(void)
stats->ops_stats.dsConnections = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnections);
stats->ops_stats.dsConnectionSeq = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq);
stats->ops_stats.dsConnectionsInMaxThreads = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionsInMaxThreads);
- stats->ops_stats.dsMaxThreadsHit = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsMaxThreadsHit);
+ stats->ops_stats.dsMaxThreadsHits = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsMaxThreadsHits);
stats->ops_stats.dsBytesRecv = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesRecv);
stats->ops_stats.dsBytesSent = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesSent);
stats->ops_stats.dsEntriesReturned = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned);
@@ -738,7 +738,7 @@ snmp_as_entry(Slapi_Entry *e)
add_counter_to_value(e, "Connections", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnections));
add_counter_to_value(e, "ConnectionSeq", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq));
add_counter_to_value(e, "ConnectionsInMaxThreads", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionsInMaxThreads));
- add_counter_to_value(e, "ConnectionsMaxThreadsCount", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsMaxThreadsHit));
+ add_counter_to_value(e, "ConnectionsMaxThreadsCount", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsMaxThreadsHits));
add_counter_to_value(e, "BytesRecv", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesRecv));
add_counter_to_value(e, "BytesSent", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesSent));
add_counter_to_value(e, "EntriesReturned", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned));
diff --git a/ldap/servers/snmp/ldap-agent.c b/ldap/servers/snmp/ldap-agent.c
index 4393a8956..bd9b8dd9b 100644
--- a/ldap/servers/snmp/ldap-agent.c
+++ b/ldap/servers/snmp/ldap-agent.c
@@ -496,8 +496,8 @@ dsOpsTable_get_value(netsnmp_request_info *request,
the_stat = &context->ops_tbl.dsConnectionsInMaxThreads;
break;
- case COLUMN_DSMAXTHREADSHIT:
- the_stat = &context->ops_tbl.dsMaxThreadsHit;
+ case COLUMN_DSMAXTHREADSHITS:
+ the_stat = &context->ops_tbl.dsMaxThreadsHits;
break;
default: /* We shouldn't get here */
diff --git a/ldap/servers/snmp/ldap-agent.h b/ldap/servers/snmp/ldap-agent.h
index 935d3a611..c98e467dd 100644
--- a/ldap/servers/snmp/ldap-agent.h
+++ b/ldap/servers/snmp/ldap-agent.h
@@ -161,7 +161,7 @@ extern size_t snmptrap_oid_len;
#define COLUMN_DSERRORS 20
#define COLUMN_DSCONNECTIONS 21
#define COLUMN_DSCONNECTIONSINMAXTHREADS 22
-#define COLUMN_DSMAXTHREADSHIT 23
+#define COLUMN_DSMAXTHREADSHITS 23
#define dsOpsTable_COL_MIN 1
#define dsOpsTable_COL_MAX 23
diff --git a/ldap/servers/snmp/redhat-directory.mib b/ldap/servers/snmp/redhat-directory.mib
index c8608972e..579be8ee4 100644
--- a/ldap/servers/snmp/redhat-directory.mib
+++ b/ldap/servers/snmp/redhat-directory.mib
@@ -87,7 +87,7 @@ RHDS-MIB DEFINITIONS ::= BEGIN
dsErrors,
dsConnections,
dsConnectionsInMaxThreads,
- dsMaxThreadsHit,
+ dsMaxThreadsHits,
dsMasterEntries,
dsCopyEntries,
dsCacheEntries,
@@ -190,7 +190,7 @@ RHDS-MIB DEFINITIONS ::= BEGIN
Counter64,
dsConnectionsInMaxThreads
Counter64,
- dsMaxThreadsHit
+ dsMaxThreadsHits
Counter64
}
@@ -472,7 +472,7 @@ RHDS-MIB DEFINITIONS ::= BEGIN
"Redhat defined 1.2."
::= { dsOpsEntry 22 }
- dsMaxThreadsHit OBJECT-TYPE
+ dsMaxThreadsHits OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
@@ -596,7 +596,7 @@ RHDS-MIB DEFINITIONS ::= BEGIN
DsIntEntry ::= SEQUENCE {
dsIntIndex
- INTEGER,
+ Integer32,
dsName
DistinguishedName,
dsTimeOfCreation
--
2.17.1

View file

@ -1,50 +0,0 @@
From 62fbb3423b26426e735e134134ab710945514ca6 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Tue, 26 Sep 2017 15:51:41 +0200
Subject: [PATCH] Ticket: 49180 - errors log filled with attrlist_replace -
attr_replace
Bug: If a RUV contains the same URL with different replica IDs the created referrals contain duplicates
Fix: check duplicate referrals
Reviewed by: Mark, thanks
---
ldap/servers/plugins/replication/repl5_ruv.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
index 40dc0928b..7bfdc3425 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -1386,7 +1386,17 @@ ruv_replica_count(const RUV *ruv)
* Extract all the referral URL's from the RUV (but self URL),
* returning them in an array of strings, that
* the caller must free.
+ * We also check and remove duplicates (caused by unclean RUVs)
*/
+static int
+ruv_referral_exists(unsigned char *purl, char **refs, int count)
+{
+ for (size_t j=0; j<count; j++) {
+ if (0 == slapi_utf8casecmp(purl, (unsigned char *)refs[j]))
+ return 1;
+ }
+ return 0;
+}
char **
ruv_get_referrals(const RUV *ruv)
{
@@ -1407,7 +1417,8 @@ ruv_get_referrals(const RUV *ruv)
/* Add URL into referrals if doesn't match self URL */
if ((replica->replica_purl != NULL) &&
(slapi_utf8casecmp((unsigned char *)replica->replica_purl,
- (unsigned char *)mypurl) != 0)) {
+ (unsigned char *)mypurl) != 0) &&
+ !ruv_referral_exists((unsigned char *)replica->replica_purl, r, i)) {
r[i] = slapi_ch_strdup(replica->replica_purl);
i++;
}
--
2.13.6

View file

@ -0,0 +1,149 @@
From 6361810037bc32c22e3e00a16bc53b34d0b0d610 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 9 Jul 2018 15:50:09 -0400
Subject: [PATCH] Ticket 49840 - ds-replcheck command returns traceback errors
against ldif files having garbage content when run in offline mode
Description: Added a basic check to see if the LDIF files are actually
LDIF files. Also added checks that the database RUV are
present as well.
https://pagure.io/389-ds-base/issue/49840
Reviewed by: spichugi(Thanks!)
(cherry picked from commit 60cb52040704686d9541a2e2eb2765d86cb10af2)
---
ldap/admin/src/scripts/ds-replcheck | 53 +++++++++++++++++++++++------
1 file changed, 43 insertions(+), 10 deletions(-)
diff --git a/ldap/admin/src/scripts/ds-replcheck b/ldap/admin/src/scripts/ds-replcheck
index 62f911034..5c195f983 100755
--- a/ldap/admin/src/scripts/ds-replcheck
+++ b/ldap/admin/src/scripts/ds-replcheck
@@ -10,18 +10,19 @@
#
import os
+import sys
import re
import time
import ldap
import ldapurl
import argparse
import getpass
-
+from ldif import LDIFRecordList
from ldap.ldapobject import SimpleLDAPObject
from ldap.cidict import cidict
from ldap.controls import SimplePagedResultsControl
-VERSION = "1.3"
+VERSION = "1.4"
RUV_FILTER = '(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))'
LDAP = 'ldap'
LDAPS = 'ldaps'
@@ -386,14 +387,17 @@ def ldif_search(LDIF, dn):
return result
-def get_dns(LDIF, opts):
+def get_dns(LDIF, filename, opts):
''' Get all the DN's from an LDIF file
'''
dns = []
found = False
+ found_ruv = False
+ LDIF.seek(0)
for line in LDIF:
if line.startswith('dn: ') and line[4:].startswith('nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff'):
opts['ruv_dn'] = line[4:].lower().strip()
+ found_ruv = True
elif line.startswith('dn: '):
found = True
dn = line[4:].lower().strip()
@@ -407,6 +411,14 @@ def get_dns(LDIF, opts):
found = False
dns.append(dn)
+ if not found_ruv:
+ print('Failed to find the database RUV in the LDIF file: ' + filename + ', the LDIF ' +
+ 'file must contain replication state information.')
+ dns = None
+ else:
+ # All good, reset cursor
+ LDIF.seek(0)
+
return dns
@@ -415,6 +427,7 @@ def get_ldif_ruv(LDIF, opts):
'''
LDIF.seek(0)
result = ldif_search(LDIF, opts['ruv_dn'])
+ LDIF.seek(0) # Reset cursor
return result['entry'].data['nsds50ruv']
@@ -549,6 +562,7 @@ def do_offline_report(opts, output_file=None):
rconflicts = []
rtombstones = 0
mtombstones = 0
+ idx = 0
# Open LDIF files
try:
@@ -561,12 +575,36 @@ def do_offline_report(opts, output_file=None):
RLDIF = open(opts['rldif'], "r")
except Exception as e:
print('Failed to open Replica LDIF: ' + str(e))
+ MLDIF.close()
+ return None
+
+ # Verify LDIF Files
+ try:
+ print("Validating Master ldif file ({})...".format(opts['mldif']))
+ LDIFRecordList(MLDIF).parse()
+ except ValueError:
+ print('Master LDIF file in invalid, aborting...')
+ MLDIF.close()
+ RLDIF.close()
+ return None
+ try:
+ print("Validating Replica ldif file ({})...".format(opts['rldif']))
+ LDIFRecordList(RLDIF).parse()
+ except ValueError:
+ print('Replica LDIF file is invalid, aborting...')
+ MLDIF.close()
+ RLDIF.close()
return None
# Get all the dn's, and entry counts
print ("Gathering all the DN's...")
- master_dns = get_dns(MLDIF, opts)
- replica_dns = get_dns(RLDIF, opts)
+ master_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:
+ print("Aborting scan...")
+ MLDIF.close()
+ RLDIF.close()
+ sys.exit(1)
m_count = len(master_dns)
r_count = len(replica_dns)
@@ -575,11 +613,6 @@ def do_offline_report(opts, output_file=None):
opts['master_ruv'] = get_ldif_ruv(MLDIF, opts)
opts['replica_ruv'] = get_ldif_ruv(RLDIF, opts)
- # Reset the cursors
- idx = 0
- MLDIF.seek(idx)
- RLDIF.seek(idx)
-
""" 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
this phase we keep keep track of conflict/tombstone counts, and we check for
--
2.17.1

View file

@ -1,40 +0,0 @@
From 80631ee86fa951f18ed25f61ca72734931eb5387 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 2 Oct 2017 16:19:47 -0400
Subject: [PATCH] Ticket 49388 - repl-monitor - matches null string many times
in regex
Bug Description: When using a wildcard(*) for the hostname, some of the
regex's for parsing the various configurations throws
out warnings.
Fix Description: When a wildcard is detected reset the hostnode variable
to nothing.
https://pagure.io/389-ds-base/issue/49388
Reviewed by: firstyear(Thanks!)
(cherry picked from commit 4b41a02484db645a593b9d6ac6c4e062dd374395)
---
ldap/admin/src/scripts/repl-monitor.pl.in | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/ldap/admin/src/scripts/repl-monitor.pl.in b/ldap/admin/src/scripts/repl-monitor.pl.in
index a3efa8e6e..97c1462a5 100755
--- a/ldap/admin/src/scripts/repl-monitor.pl.in
+++ b/ldap/admin/src/scripts/repl-monitor.pl.in
@@ -1053,6 +1053,10 @@ sub add_server
# Remove the domain name from the host name
my ($hostnode) = $host;
$hostnode = $1 if $host =~ /^(.+?)\./;
+ if ($hostnode eq "*") {
+ # handle wild card correctly for regex
+ $hostnode = "";
+ }
# new host:port
if (!$binddn || $binddn eq "" || $binddn eq "*" ||
--
2.13.6

View file

@ -1,4 +1,4 @@
From 911038990df1357f452b0e38309261faf1de898f Mon Sep 17 00:00:00 2001
From 83949e7e4f3370f48ea5c5fabdb9af04e3d11c75 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 8 Aug 2018 17:19:27 -0400
Subject: [PATCH] Ticket 49893 - disable nunc-stans by default
@ -15,10 +15,10 @@ Reviewed by: ?
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 3bd5c1826..f8741028d 100644
index 12f6ec396..56b67b79b 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -1681,7 +1681,7 @@ FrontendConfig_init(void)
@@ -1683,7 +1683,7 @@ FrontendConfig_init(void)
cfg->maxbersize = SLAPD_DEFAULT_MAXBERSIZE;
cfg->logging_backend = slapi_ch_strdup(SLAPD_INIT_LOGGING_BACKEND_INTERNAL);
cfg->rootdn = slapi_ch_strdup(SLAPD_DEFAULT_DIRECTORY_MANAGER);

View file

@ -1,257 +0,0 @@
From bb2d74ebe9d725b47e35893a2d8c8bd713d6dd4b Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 3 Oct 2017 17:22:37 -0400
Subject: [PATCH] Ticket 49389 - unable to retrieve specific cosAttribute when
subtree password policy is configured
Bug Description: If indirect cos is being used and a subtree password
policy is added, th orignal COS attributes aren't always
returned. The issue is that when the subtree password
policy attribute was encountered during the virtual
attribute processing it set a flag that said the attribute
was operational (which is correct for the password policy
attr: pwdpolicysubentry).
However, this flag was accidentally carried over to the
following virtual attributes that were being processed.
Which caused those attributes to be seen as operational
which is why it was no longer being returned to the client.
Fix Description: Reset the prop flags before processing the next COS attribute
https://pagure.io/389-ds-base/issue/49389
Reviewed by: firstyear(Thanks!)
(cherry picked from commit 0953e6011368bc29300990e9493ac13e5aba9586)
---
dirsrvtests/tests/suites/cos/__init__.py | 0
dirsrvtests/tests/suites/cos/indirect_cos_test.py | 191 ++++++++++++++++++++++
ldap/servers/plugins/cos/cos_cache.c | 2 +-
3 files changed, 192 insertions(+), 1 deletion(-)
create mode 100644 dirsrvtests/tests/suites/cos/__init__.py
create mode 100644 dirsrvtests/tests/suites/cos/indirect_cos_test.py
diff --git a/dirsrvtests/tests/suites/cos/__init__.py b/dirsrvtests/tests/suites/cos/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/dirsrvtests/tests/suites/cos/indirect_cos_test.py b/dirsrvtests/tests/suites/cos/indirect_cos_test.py
new file mode 100644
index 000000000..1aac6b8ed
--- /dev/null
+++ b/dirsrvtests/tests/suites/cos/indirect_cos_test.py
@@ -0,0 +1,191 @@
+import logging
+import pytest
+import os
+import ldap
+import time
+import subprocess
+
+from lib389 import Entry
+from lib389.idm.user import UserAccounts
+from lib389.topologies import topology_st as topo
+from lib389._constants import (DEFAULT_SUFFIX, DN_DM, PASSWORD, HOST_STANDALONE,
+ SERVERID_STANDALONE, PORT_STANDALONE)
+
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+TEST_USER_DN = "uid=test_user,ou=people,dc=example,dc=com"
+OU_PEOPLE = 'ou=people,{}'.format(DEFAULT_SUFFIX)
+
+PW_POLICY_CONT_PEOPLE = 'cn="cn=nsPwPolicyEntry,' \
+ 'ou=people,dc=example,dc=com",' \
+ 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
+
+PW_POLICY_CONT_PEOPLE2 = 'cn="cn=nsPwPolicyEntry,' \
+ 'dc=example,dc=com",' \
+ 'cn=nsPwPolicyContainerdc=example,dc=com'
+
+
+def check_user(inst):
+ """Search the test user and make sure it has the execpted attrs
+ """
+ try:
+ entries = inst.search_s('dc=example,dc=com', ldap.SCOPE_SUBTREE, "uid=test_user")
+ log.debug('user: \n' + str(entries[0]))
+ assert entries[0].hasAttr('ou'), "Entry is missing ou cos attribute"
+ assert entries[0].hasAttr('x-department'), "Entry is missing description cos attribute"
+ assert entries[0].hasAttr('x-en-ou'), "Entry is missing givenname cos attribute"
+ except ldap.LDAPError as e:
+ log.fatal('Failed to search for user: ' + str(e))
+ raise e
+
+
+def setup_subtree_policy(topo):
+ """Set up subtree password policy
+ """
+ try:
+ topo.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE,
+ 'nsslapd-pwpolicy-local',
+ 'on')])
+ except ldap.LDAPError as e:
+ log.error('Failed to set fine-grained policy: error {}'.format(
+ e.message['desc']))
+ raise e
+
+ log.info('Create password policy for subtree {}'.format(OU_PEOPLE))
+ try:
+ subprocess.call(['%s/ns-newpwpolicy.pl' % topo.standalone.get_sbin_dir(),
+ '-D', DN_DM, '-w', PASSWORD,
+ '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
+ '-S', DEFAULT_SUFFIX, '-Z', SERVERID_STANDALONE])
+ except subprocess.CalledProcessError as e:
+ log.error('Failed to create pw policy policy for {}: error {}'.format(
+ OU_PEOPLE, e.message['desc']))
+ raise e
+
+ log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE))
+ try:
+ topo.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_REPLACE,
+ 'pwdpolicysubentry',
+ PW_POLICY_CONT_PEOPLE2)])
+ except ldap.LDAPError as e:
+ log.error('Failed to pwdpolicysubentry pw policy '
+ 'policy for {}: error {}'.format(OU_PEOPLE, e.message['desc']))
+ raise e
+ time.sleep(1)
+
+
+def setup_indirect_cos(topo):
+ """Setup indirect COS definition and template
+ """
+ cosDef = Entry(('cn=cosDefinition,dc=example,dc=com',
+ {'objectclass': ['top', 'ldapsubentry',
+ 'cossuperdefinition',
+ 'cosIndirectDefinition'],
+ 'cosAttribute': ['ou merge-schemes',
+ 'x-department merge-schemes',
+ 'x-en-ou merge-schemes'],
+ 'cosIndirectSpecifier': 'seeAlso',
+ 'cn': 'cosDefinition'}))
+
+ cosTemplate = Entry(('cn=cosTemplate,dc=example,dc=com',
+ {'objectclass': ['top',
+ 'extensibleObject',
+ 'cosTemplate'],
+ 'ou': 'My COS Org',
+ 'x-department': 'My COS x-department',
+ 'x-en-ou': 'my COS x-en-ou',
+ 'cn': 'cosTemplate'}))
+ try:
+ topo.standalone.add_s(cosDef)
+ topo.standalone.add_s(cosTemplate)
+ except ldap.LDAPError as e:
+ log.fatal('Failed to add cos: error ' + str(e))
+ raise e
+ time.sleep(1)
+
+
+@pytest.fixture(scope="module")
+def setup(topo, request):
+ """Add schema, and test user
+ """
+ log.info('Add custom schema...')
+ try:
+ ATTR_1 = ("( 1.3.6.1.4.1.409.389.2.189 NAME 'x-department' " +
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )")
+ ATTR_2 = ("( 1.3.6.1.4.1.409.389.2.187 NAME 'x-en-ou' " +
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )")
+ OC = ("( xPerson-oid NAME 'xPerson' DESC '' SUP person STRUCTURAL MAY " +
+ "( x-department $ x-en-ou ) X-ORIGIN 'user defined' )")
+ topo.standalone.modify_s("cn=schema", [(ldap.MOD_ADD, 'attributeTypes', ATTR_1),
+ (ldap.MOD_ADD, 'attributeTypes', ATTR_2),
+ (ldap.MOD_ADD, 'objectClasses', OC)])
+ except ldap.LDAPError as e:
+ log.fatal('Failed to add custom schema')
+ raise e
+ time.sleep(1)
+
+ log.info('Add test user...')
+ users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
+
+ user_properties = {
+ 'uid': 'test_user',
+ 'cn': 'test user',
+ 'sn': 'user',
+ 'uidNumber': '1000',
+ 'gidNumber': '2000',
+ 'homeDirectory': '/home/test_user',
+ 'seeAlso': 'cn=cosTemplate,dc=example,dc=com'
+ }
+ users.create(properties=user_properties)
+ try:
+ topo.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_ADD,
+ 'objectclass',
+ 'xPerson')])
+ except ldap.LDAPError as e:
+ log.fatal('Failed to add objectclass to user')
+ raise e
+
+ # Setup COS
+ log.info("Setup indirect COS...")
+ setup_indirect_cos(topo)
+
+
+def test_indirect_cos(topo, setup):
+ """Test indirect cos
+
+ :id: 890d5929-7d52-4a56-956e-129611b4649a
+ :setup: standalone
+ :steps:
+ 1. Test cos is working for test user
+ 2. Add subtree password policy
+ 3. Test cos is working for test user
+ :expectedresults:
+ 1. User has expected cos attrs
+ 2. Substree password policy setup is successful
+ 3 User still has expected cos attrs
+ """
+
+ # Step 1 - Search user and see if the COS attrs are included
+ log.info('Checking user...')
+ check_user(topo.standalone)
+
+ # Step 2 - Add subtree password policy (Second COS - operational attribute)
+ setup_subtree_policy(topo)
+
+ # Step 3 - Check user again now hat we have a mix of vattrs
+ log.info('Checking user...')
+ check_user(topo.standalone)
+
+
+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/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
index c7897ba05..9ae15db15 100644
--- a/ldap/servers/plugins/cos/cos_cache.c
+++ b/ldap/servers/plugins/cos/cos_cache.c
@@ -2094,7 +2094,6 @@ cos_cache_vattr_types(vattr_sp_handle *handle __attribute__((unused)),
int index = 0;
cosCache *pCache;
char *lastattr = "thisisfakeforcos";
- int props = 0;
slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "--> cos_cache_vattr_types\n");
@@ -2105,6 +2104,7 @@ cos_cache_vattr_types(vattr_sp_handle *handle __attribute__((unused)),
}
while (index < pCache->attrCount) {
+ int props = 0;
if (slapi_utf8casecmp(
(unsigned char *)pCache->ppAttrIndex[index]->pAttrName,
(unsigned char *)lastattr)) {
--
2.13.6

View file

@ -1,4 +1,4 @@
From 1013a1bfe0882d213f48e900ab89e00651188489 Mon Sep 17 00:00:00 2001
From a21ba4722268349b9c63000145e5d119e1fddd60 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 9 Aug 2018 15:27:59 -0400
Subject: [PATCH] Ticket 49890 : ldapsearch with server side sort crashes the

View file

@ -1,17 +1,17 @@
From 9d2aa18fb5c48a11300d2309df89213bbdb614e1 Mon Sep 17 00:00:00 2001
From 59071a77774c530f0ab570dda27e23a021d23972 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 23 Aug 2018 13:43:36 -0400
Subject: [PATCH 1/2] Bug 1623247 - Crash in vslapd_log_emergency_error
Date: Thu, 23 Aug 2018 10:09:58 -0400
Subject: [PATCH] Bug 1614820 - Crash in vslapd_log_emergency_error
Description: We were not locking the error log fd before closing and reopening
the log file. This could cause a crash when multiple threads are
trying to log tothe errors log.
Description: We were not locking the error log fd before closing and reopening
the log file. This could cause a crash when multiple threads are
trying to log tothe errors log.
---
ldap/servers/slapd/log.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c
index 998efaef3..90ce6ac0a 100644
index 2e4ee03a8..7dd71541b 100644
--- a/ldap/servers/slapd/log.c
+++ b/ldap/servers/slapd/log.c
@@ -2231,11 +2231,11 @@ vslapd_log_emergency_error(LOGFD fp, const char *msg, int locked)
@ -54,7 +54,7 @@ index 998efaef3..90ce6ac0a 100644
log__error_emergency("Insufficent buffer capacity to fit timestamp and message!", 1, 0);
return -1;
}
@@ -4447,6 +4447,13 @@ log__error_emergency(const char *errstr, int reopen, int locked)
@@ -4486,6 +4486,13 @@ log__error_emergency(const char *errstr, int reopen, int locked)
if (!reopen) {
return;
}
@ -68,7 +68,7 @@ index 998efaef3..90ce6ac0a 100644
if (NULL != loginfo.log_error_fdes) {
LOG_CLOSE(loginfo.log_error_fdes);
}
@@ -4455,7 +4462,10 @@ log__error_emergency(const char *errstr, int reopen, int locked)
@@ -4494,7 +4501,10 @@ log__error_emergency(const char *errstr, int reopen, int locked)
PRErrorCode prerr = PR_GetError();
syslog(LOG_ERR, "Failed to reopen errors log file, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n", prerr, slapd_pr_strerror(prerr));
} else {

View file

@ -1,111 +0,0 @@
From 50d62b6d5ea69e5cad6359dbd1dccb09fcfa1a6b Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 3 Oct 2017 09:51:53 -0400
Subject: [PATCH] Ticket 49320 - Activating already active role returns error
16
Bug Description: ns-activate.pl returns error 16 when trying to activate an
already active role.
Fix Description: Check for error 16 (no such attr), and return error 100.
Also added a "redirect"otion to the ldapmod function to
hide any errors printed to STDERR, so that the script can
display its own error message.
https://pagure.io/389-ds-base/issue/49320
Reviewed by: firstyear(Thanks!)
(cherry picked from commit 406084847f29aa44ffd81de746770aeff6b67c61)
---
ldap/admin/src/scripts/DSUtil.pm.in | 18 +++++++++++-------
ldap/admin/src/scripts/ns-activate.pl.in | 9 ++++++++-
2 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/ldap/admin/src/scripts/DSUtil.pm.in b/ldap/admin/src/scripts/DSUtil.pm.in
index 805a9b91d..791464d0a 100644
--- a/ldap/admin/src/scripts/DSUtil.pm.in
+++ b/ldap/admin/src/scripts/DSUtil.pm.in
@@ -1447,6 +1447,10 @@ sub ldapmod {
close (FILE);
}
+ if ($info{redirect} eq ""){
+ $info{redirect} = "> /dev/null";
+ }
+
#
# Check the protocol, and reset it if it's invalid
#
@@ -1470,9 +1474,9 @@ sub ldapmod {
print "STARTTLS)\n";
}
if($info{openldap} eq "yes"){
- system "ldapmodify -x -ZZ -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" > /dev/null";
+ system "ldapmodify -x -ZZ -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
} else {
- system "ldapmodify -ZZZ -P \"$info{certdir}\" -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" > /dev/null";
+ system "ldapmodify -ZZZ -P \"$info{certdir}\" -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
}
} elsif (($info{security} eq "on" && $info{protocol} eq "") || ($info{security} eq "on" && $info{protocol} =~ m/LDAPS/i) ){
#
@@ -1482,9 +1486,9 @@ sub ldapmod {
print "LDAPS)\n";
}
if($info{openldap} eq "yes"){
- system "ldapmodify -x -H \"ldaps://$info{host}:$info{secure_port}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" > /dev/null";
+ system "ldapmodify -x -H \"ldaps://$info{host}:$info{secure_port}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
} else {
- system "ldapmodify -Z -P \"$info{certdir}\" -p $info{secure_port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" > /dev/null";
+ system "ldapmodify -Z -P \"$info{certdir}\" -p $info{secure_port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
}
} elsif (($info{openldap} eq "yes") && (($info{ldapi} eq "on" && $info{protocol} eq "") || ($info{ldapi} eq "on" && $info{protocol} =~ m/LDAPI/i)) ){
#
@@ -1499,7 +1503,7 @@ sub ldapmod {
if($protocol_error eq "yes"){
print "LDAPI)\n";
}
- system "ldapmodify -x -H \"$info{ldapiURL}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" > /dev/null";
+ system "ldapmodify -x -H \"$info{ldapiURL}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
}
} else {
#
@@ -1509,9 +1513,9 @@ sub ldapmod {
print "LDAP)\n";
}
if($info{openldap} eq "yes"){
- system "ldapmodify -x -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" > /dev/null";
+ system "ldapmodify -x -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
} else {
- system "ldapmodify -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" > /dev/null";
+ system "ldapmodify -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
}
}
unlink ($file);
diff --git a/ldap/admin/src/scripts/ns-activate.pl.in b/ldap/admin/src/scripts/ns-activate.pl.in
index 5922c9aab..bec19c8e7 100644
--- a/ldap/admin/src/scripts/ns-activate.pl.in
+++ b/ldap/admin/src/scripts/ns-activate.pl.in
@@ -731,11 +731,18 @@ if ( $single == 1 ){
}
$info{args} = "-c";
+$info{redirect} = "> /dev/null 2>&1";
DSUtil::ldapmod($record, %info);
if( $? != 0 ){
debug("delete, $entry\n");
$retCode=$?>>8;
- exit $retCode;
+ if ($retCode == "16") { # Error 16 (no such attr) - already activated
+ out("$entry already $state.\n");
+ exit 100;
+ } else {
+ out("Failed to activate $entry, error $retCode\n");
+ exit $retCode;
+ }
}
out("$entry $state.\n");
--
2.13.6

View file

@ -1,914 +0,0 @@
From cbe71d7e4901232eaa423b9dc55dba9401c05bec Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 13 Oct 2017 07:09:08 -0400
Subject: [PATCH] Ticket 48235 - Remove memberOf global lock
Bug Description: The memberOf global lock no longer servers a purpose since
the plugin is BETXN. This was causing potential deadlocks
when multiple backends are used.
Fix Description: Remove the lock, and rework the fixup/ancestors caches/hashtables.
Instead of reusing a single cache, we create a fresh cache
when we copy the plugin config (which only happens at the start
of an operation). Then we destroy the caches when we free
the config.
https://pagure.io/389-ds-base/issue/48235
Reviewed by: firstyear & tbordaz(Thanks!!)
(cherry picked from commit 184b8a164f4ed456c72d58038aa9a0d512be61fa)
---
ldap/servers/plugins/memberof/memberof.c | 326 +++---------------------
ldap/servers/plugins/memberof/memberof.h | 17 ++
ldap/servers/plugins/memberof/memberof_config.c | 166 +++++++++++-
3 files changed, 210 insertions(+), 299 deletions(-)
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
index a0f997ddf..a23c52abe 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -48,14 +48,11 @@ static Slapi_PluginDesc pdesc = {"memberof", VENDOR,
static void *_PluginID = NULL;
static Slapi_DN *_ConfigAreaDN = NULL;
static Slapi_RWLock *config_rwlock = NULL;
-static Slapi_DN *_pluginDN = NULL;
-static PRMonitor *memberof_operation_lock = 0;
+static Slapi_DN* _pluginDN = NULL;
MemberOfConfig *qsortConfig = 0;
static int usetxn = 0;
static int premodfn = 0;
-#define MEMBEROF_HASHTABLE_SIZE 1000
-static PLHashTable *fixup_entry_hashtable = NULL; /* global hash table protected by memberof_lock (memberof_operation_lock) */
-static PLHashTable *group_ancestors_hashtable = NULL; /* global hash table protected by memberof_lock (memberof_operation_lock) */
+
typedef struct _memberofstringll
{
@@ -73,18 +70,6 @@ typedef struct _memberof_get_groups_data
PRBool use_cache;
} memberof_get_groups_data;
-/* The key to access the hash table is the normalized DN
- * The normalized DN is stored in the value because:
- * - It is used in slapi_valueset_find
- * - It is used to fill the memberof_get_groups_data.group_norm_vals
- */
-typedef struct _memberof_cached_value
-{
- char *key;
- char *group_dn_val;
- char *group_ndn_val;
- int valid;
-} memberof_cached_value;
struct cache_stat
{
int total_lookup;
@@ -164,14 +149,9 @@ static int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data);
static int memberof_entry_in_scope(MemberOfConfig *config, Slapi_DN *sdn);
static int memberof_add_objectclass(char *auto_add_oc, const char *dn);
static int memberof_add_memberof_attr(LDAPMod **mods, const char *dn, char *add_oc);
-static PLHashTable *hashtable_new();
-static void fixup_hashtable_empty(char *msg);
-static PLHashTable *hashtable_new();
-static void ancestor_hashtable_empty(char *msg);
-static void ancestor_hashtable_entry_free(memberof_cached_value *entry);
-static memberof_cached_value *ancestors_cache_lookup(const char *ndn);
-static PRBool ancestors_cache_remove(const char *ndn);
-static PLHashEntry *ancestors_cache_add(const void *key, void *value);
+static memberof_cached_value *ancestors_cache_lookup(MemberOfConfig *config, const char *ndn);
+static PRBool ancestors_cache_remove(MemberOfConfig *config, const char *ndn);
+static PLHashEntry *ancestors_cache_add(MemberOfConfig *config, const void *key, void *value);
/*** implementation ***/
@@ -344,11 +324,6 @@ memberof_postop_start(Slapi_PBlock *pb)
slapi_log_err(SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
"--> memberof_postop_start\n");
- memberof_operation_lock = PR_NewMonitor();
- if (0 == memberof_operation_lock) {
- rc = -1;
- goto bail;
- }
if (config_rwlock == NULL) {
if ((config_rwlock = slapi_new_rwlock()) == NULL) {
rc = -1;
@@ -356,9 +331,6 @@ memberof_postop_start(Slapi_PBlock *pb)
}
}
- fixup_entry_hashtable = hashtable_new();
- group_ancestors_hashtable = hashtable_new();
-
/* Set the alternate config area if one is defined. */
slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_AREA, &config_area);
if (config_area) {
@@ -413,13 +385,13 @@ memberof_postop_start(Slapi_PBlock *pb)
goto bail;
}
-/*
+ /*
* TODO: start up operation actor thread
* need to get to a point where server failure
- * or shutdown doesn't hose our operations
- * so we should create a task entry that contains
+ * or shutdown doesn't hose our operations
+ * so we should create a task entry that contains
* all required information to complete the operation
- * then the tasks can be restarted safely if
+ * then the tasks can be restarted safely if
* interrupted
*/
@@ -451,18 +423,7 @@ memberof_postop_close(Slapi_PBlock *pb __attribute__((unused)))
slapi_sdn_free(&_pluginDN);
slapi_destroy_rwlock(config_rwlock);
config_rwlock = NULL;
- PR_DestroyMonitor(memberof_operation_lock);
- memberof_operation_lock = NULL;
-
- if (fixup_entry_hashtable) {
- fixup_hashtable_empty("memberof_postop_close empty fixup_entry_hastable");
- PL_HashTableDestroy(fixup_entry_hashtable);
- }
- if (group_ancestors_hashtable) {
- ancestor_hashtable_empty("memberof_postop_close empty group_ancestors_hashtable");
- PL_HashTableDestroy(group_ancestors_hashtable);
- }
slapi_log_err(SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
"<-- memberof_postop_close\n");
return 0;
@@ -524,7 +485,7 @@ memberof_postop_del(Slapi_PBlock *pb)
{
int ret = SLAPI_PLUGIN_SUCCESS;
MemberOfConfig *mainConfig = NULL;
- MemberOfConfig configCopy = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ MemberOfConfig configCopy = {0};
Slapi_DN *sdn;
void *caller_id = NULL;
@@ -553,9 +514,6 @@ memberof_postop_del(Slapi_PBlock *pb)
memberof_copy_config(&configCopy, memberof_get_config());
memberof_unlock_config();
- /* get the memberOf operation lock */
- memberof_lock();
-
/* remove this DN from the
* membership lists of groups
*/
@@ -563,7 +521,6 @@ memberof_postop_del(Slapi_PBlock *pb)
slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM,
"memberof_postop_del - Error deleting dn (%s) from group. Error (%d)\n",
slapi_sdn_get_dn(sdn), ret);
- memberof_unlock();
goto bail;
}
@@ -583,7 +540,6 @@ memberof_postop_del(Slapi_PBlock *pb)
}
}
}
- memberof_unlock();
bail:
memberof_free_config(&configCopy);
}
@@ -776,7 +732,7 @@ memberof_call_foreach_dn(Slapi_PBlock *pb __attribute__((unused)), Slapi_DN *sdn
memberof_cached_value *ht_grp = NULL;
const char *ndn = slapi_sdn_get_ndn(sdn);
- ht_grp = ancestors_cache_lookup((const void *)ndn);
+ ht_grp = ancestors_cache_lookup(config, (const void *)ndn);
if (ht_grp) {
#if MEMBEROF_CACHE_DEBUG
slapi_log_err(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_call_foreach_dn: Ancestors of %s already cached (%x)\n", ndn, ht_grp);
@@ -918,7 +874,7 @@ memberof_postop_modrdn(Slapi_PBlock *pb)
if (memberof_oktodo(pb)) {
MemberOfConfig *mainConfig = 0;
- MemberOfConfig configCopy = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ MemberOfConfig configCopy = {0};
struct slapi_entry *pre_e = NULL;
struct slapi_entry *post_e = NULL;
Slapi_DN *pre_sdn = 0;
@@ -944,8 +900,6 @@ memberof_postop_modrdn(Slapi_PBlock *pb)
goto bail;
}
- memberof_lock();
-
/* update any downstream members */
if (pre_sdn && post_sdn && configCopy.group_filter &&
0 == slapi_filter_test_simple(post_e, configCopy.group_filter)) {
@@ -1010,7 +964,6 @@ memberof_postop_modrdn(Slapi_PBlock *pb)
}
}
}
- memberof_unlock();
bail:
memberof_free_config(&configCopy);
}
@@ -1166,7 +1119,7 @@ memberof_postop_modify(Slapi_PBlock *pb)
if (memberof_oktodo(pb)) {
int config_copied = 0;
MemberOfConfig *mainConfig = 0;
- MemberOfConfig configCopy = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ MemberOfConfig configCopy = {0};
/* get the mod set */
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
@@ -1209,8 +1162,6 @@ memberof_postop_modify(Slapi_PBlock *pb)
if (interested) {
int op = slapi_mod_get_operation(smod);
- memberof_lock();
-
/* the modify op decides the function */
switch (op & ~LDAP_MOD_BVALUES) {
case LDAP_MOD_ADD: {
@@ -1221,7 +1172,6 @@ memberof_postop_modify(Slapi_PBlock *pb)
"Error (%d)\n",
slapi_sdn_get_dn(sdn), ret);
slapi_mod_done(next_mod);
- memberof_unlock();
goto bail;
}
break;
@@ -1239,7 +1189,6 @@ memberof_postop_modify(Slapi_PBlock *pb)
"Error (%d)\n",
slapi_sdn_get_dn(sdn), ret);
slapi_mod_done(next_mod);
- memberof_unlock();
goto bail;
}
} else {
@@ -1250,7 +1199,6 @@ memberof_postop_modify(Slapi_PBlock *pb)
"Error (%d)\n",
slapi_sdn_get_dn(sdn), ret);
slapi_mod_done(next_mod);
- memberof_unlock();
goto bail;
}
}
@@ -1265,7 +1213,6 @@ memberof_postop_modify(Slapi_PBlock *pb)
"Error (%d)\n",
slapi_sdn_get_dn(sdn), ret);
slapi_mod_done(next_mod);
- memberof_unlock();
goto bail;
}
break;
@@ -1280,8 +1227,6 @@ memberof_postop_modify(Slapi_PBlock *pb)
break;
}
}
-
- memberof_unlock();
}
slapi_mod_done(next_mod);
@@ -1336,7 +1281,7 @@ memberof_postop_add(Slapi_PBlock *pb)
if (memberof_oktodo(pb) && (sdn = memberof_getsdn(pb))) {
struct slapi_entry *e = NULL;
- MemberOfConfig configCopy = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ MemberOfConfig configCopy = {0};
MemberOfConfig *mainConfig;
slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
@@ -1361,8 +1306,6 @@ memberof_postop_add(Slapi_PBlock *pb)
int i = 0;
Slapi_Attr *attr = 0;
- memberof_lock();
-
for (i = 0; configCopy.groupattrs && configCopy.groupattrs[i]; i++) {
if (0 == slapi_entry_attr_find(e, configCopy.groupattrs[i], &attr)) {
if ((ret = memberof_add_attr_list(pb, &configCopy, sdn, attr))) {
@@ -1373,8 +1316,6 @@ memberof_postop_add(Slapi_PBlock *pb)
}
}
}
-
- memberof_unlock();
memberof_free_config(&configCopy);
}
}
@@ -2094,7 +2035,7 @@ dump_cache_entry(memberof_cached_value *double_check, const char *msg)
* the firsts elements of the array has 'valid=1' and the dn/ndn of group it belong to
*/
static void
-cache_ancestors(Slapi_Value **member_ndn_val, memberof_get_groups_data *groups)
+cache_ancestors(MemberOfConfig *config, Slapi_Value **member_ndn_val, memberof_get_groups_data *groups)
{
Slapi_ValueSet *groupvals = *((memberof_get_groups_data *)groups)->groupvals;
Slapi_Value *sval;
@@ -2191,14 +2132,14 @@ cache_ancestors(Slapi_Value **member_ndn_val, memberof_get_groups_data *groups)
#if MEMBEROF_CACHE_DEBUG
dump_cache_entry(cache_entry, key);
#endif
- if (ancestors_cache_add((const void *)key_copy, (void *)cache_entry) == NULL) {
- slapi_log_err(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, "cache_ancestors: Failed to cache ancestor of %s\n", key);
+ if (ancestors_cache_add(config, (const void*) key_copy, (void *) cache_entry) == NULL) {
+ slapi_log_err( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, "cache_ancestors: Failed to cache ancestor of %s\n", key);
ancestor_hashtable_entry_free(cache_entry);
- slapi_ch_free((void **)&cache_entry);
+ slapi_ch_free ((void**)&cache_entry);
return;
}
#if MEMBEROF_CACHE_DEBUG
- if (double_check = ancestors_cache_lookup((const void *)key)) {
+ if (double_check = ancestors_cache_lookup(config, (const void*) key)) {
dump_cache_entry(double_check, "read back");
}
#endif
@@ -2283,8 +2224,7 @@ memberof_get_groups_r(MemberOfConfig *config, Slapi_DN *member_sdn, memberof_get
merge_ancestors(&member_ndn_val, &member_data, data);
if (!cached && member_data.use_cache)
- cache_ancestors(&member_ndn_val, &member_data);
-
+ cache_ancestors(config, &member_ndn_val, &member_data);
slapi_value_free(&member_ndn_val);
slapi_valueset_free(groupvals);
@@ -2825,49 +2765,10 @@ memberof_qsort_compare(const void *a, const void *b)
val1, val2);
}
-/* betxn: This locking mechanism is necessary to guarantee the memberof
- * consistency */
-void
-memberof_lock()
-{
- if (usetxn) {
- PR_EnterMonitor(memberof_operation_lock);
- }
- if (fixup_entry_hashtable) {
- fixup_hashtable_empty("memberof_lock");
- }
- if (group_ancestors_hashtable) {
- ancestor_hashtable_empty("memberof_lock empty group_ancestors_hashtable");
- memset(&cache_stat, 0, sizeof(cache_stat));
- }
-}
-
-void
-memberof_unlock()
-{
- if (group_ancestors_hashtable) {
- ancestor_hashtable_empty("memberof_unlock empty group_ancestors_hashtable");
-#if MEMBEROF_CACHE_DEBUG
- slapi_log_err(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, "cache statistics: total lookup %d (success %d), add %d, remove %d, enum %d\n",
- cache_stat.total_lookup, cache_stat.successfull_lookup,
- cache_stat.total_add, cache_stat.total_remove, cache_stat.total_enumerate);
- slapi_log_err(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, "cache statistics duration: lookup %ld, add %ld, remove %ld, enum %ld\n",
- cache_stat.cumul_duration_lookup, cache_stat.cumul_duration_add,
- cache_stat.cumul_duration_remove, cache_stat.cumul_duration_enumerate);
-#endif
- }
- if (fixup_entry_hashtable) {
- fixup_hashtable_empty("memberof_lock");
- }
- if (usetxn) {
- PR_ExitMonitor(memberof_operation_lock);
- }
-}
-
void
memberof_fixup_task_thread(void *arg)
{
- MemberOfConfig configCopy = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ MemberOfConfig configCopy = {0};
Slapi_Task *task = (Slapi_Task *)arg;
task_data *td = NULL;
int rc = 0;
@@ -2933,9 +2834,6 @@ memberof_fixup_task_thread(void *arg)
/* do real work */
rc = memberof_fix_memberof(&configCopy, task, td);
- /* release the memberOf operation lock */
- memberof_unlock();
-
done:
if (usetxn && fixup_pb) {
if (rc) { /* failed */
@@ -3100,7 +2998,7 @@ memberof_fix_memberof(MemberOfConfig *config, Slapi_Task *task, task_data *td)
}
static memberof_cached_value *
-ancestors_cache_lookup(const char *ndn)
+ancestors_cache_lookup(MemberOfConfig *config, const char *ndn)
{
memberof_cached_value *e;
#if defined(DEBUG) && defined(HAVE_CLOCK_GETTIME)
@@ -3118,7 +3016,7 @@ ancestors_cache_lookup(const char *ndn)
}
#endif
- e = (memberof_cached_value *)PL_HashTableLookupConst(group_ancestors_hashtable, (const void *)ndn);
+ e = (memberof_cached_value *) PL_HashTableLookupConst(config->ancestors_cache, (const void *) ndn);
#if defined(DEBUG) && defined(HAVE_CLOCK_GETTIME)
if (start) {
@@ -3133,7 +3031,7 @@ ancestors_cache_lookup(const char *ndn)
return e;
}
static PRBool
-ancestors_cache_remove(const char *ndn)
+ancestors_cache_remove(MemberOfConfig *config, const char *ndn)
{
PRBool rc;
#if defined(DEBUG) && defined(HAVE_CLOCK_GETTIME)
@@ -3151,7 +3049,8 @@ ancestors_cache_remove(const char *ndn)
}
#endif
- rc = PL_HashTableRemove(group_ancestors_hashtable, (const void *)ndn);
+
+ rc = PL_HashTableRemove(config->ancestors_cache, (const void *)ndn);
#if defined(DEBUG) && defined(HAVE_CLOCK_GETTIME)
if (start) {
@@ -3164,7 +3063,7 @@ ancestors_cache_remove(const char *ndn)
}
static PLHashEntry *
-ancestors_cache_add(const void *key, void *value)
+ancestors_cache_add(MemberOfConfig *config, const void *key, void *value)
{
PLHashEntry *e;
#if defined(DEBUG) && defined(HAVE_CLOCK_GETTIME)
@@ -3181,7 +3080,7 @@ ancestors_cache_add(const void *key, void *value)
}
#endif
- e = PL_HashTableAdd(group_ancestors_hashtable, key, value);
+ e = PL_HashTableAdd(config->ancestors_cache, key, value);
#if defined(DEBUG) && defined(HAVE_CLOCK_GETTIME)
if (start) {
@@ -3211,7 +3110,6 @@ memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
const char *ndn;
char *dn_copy;
-
/*
* If the server is ordered to shutdown, stop the fixup and return an error.
*/
@@ -3222,7 +3120,7 @@ memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
/* Check if the entry has not already been fixed */
ndn = slapi_sdn_get_ndn(sdn);
- if (ndn && fixup_entry_hashtable && PL_HashTableLookupConst(fixup_entry_hashtable, (void *)ndn)) {
+ if (ndn && config->fixup_cache && PL_HashTableLookupConst(config->fixup_cache, (void *)ndn)) {
slapi_log_err(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_fix_memberof_callback: Entry %s already fixed up\n", ndn);
goto bail;
}
@@ -3240,12 +3138,13 @@ memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
* so free this memory
*/
ndn = slapi_sdn_get_ndn(sdn);
+
#if MEMBEROF_CACHE_DEBUG
slapi_log_err(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_fix_memberof_callback: This is NOT a group %s\n", ndn);
#endif
- ht_grp = ancestors_cache_lookup((const void *)ndn);
+ ht_grp = ancestors_cache_lookup(config, (const void *)ndn);
if (ht_grp) {
- if (ancestors_cache_remove((const void *)ndn)) {
+ if (ancestors_cache_remove(config, (const void *)ndn)) {
slapi_log_err(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_fix_memberof_callback: free cached values for %s\n", ndn);
ancestor_hashtable_entry_free(ht_grp);
slapi_ch_free((void **)&ht_grp);
@@ -3297,11 +3196,11 @@ memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
slapi_valueset_free(groups);
/* records that this entry has been fixed up */
- if (fixup_entry_hashtable) {
+ if (config->fixup_cache) {
dn_copy = slapi_ch_strdup(ndn);
- if (PL_HashTableAdd(fixup_entry_hashtable, dn_copy, dn_copy) == NULL) {
+ if (PL_HashTableAdd(config->fixup_cache, dn_copy, dn_copy) == NULL) {
slapi_log_err(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_fix_memberof_callback: "
- "failed to add dn (%s) in the fixup hashtable; NSPR error - %d\n",
+ "failed to add dn (%s) in the fixup hashtable; NSPR error - %d\n",
dn_copy, PR_GetError());
slapi_ch_free((void **)&dn_copy);
/* let consider this as not a fatal error, it just skip an optimization */
@@ -3397,157 +3296,8 @@ memberof_add_objectclass(char *auto_add_oc, const char *dn)
return rc;
}
-static PRIntn
-memberof_hash_compare_keys(const void *v1, const void *v2)
-{
- PRIntn rc;
- if (0 == strcasecmp((const char *)v1, (const char *)v2)) {
- rc = 1;
- } else {
- rc = 0;
- }
- return rc;
-}
-
-static PRIntn
-memberof_hash_compare_values(const void *v1, const void *v2)
-{
- PRIntn rc;
- if ((char *)v1 == (char *)v2) {
- rc = 1;
- } else {
- rc = 0;
- }
- return rc;
-}
-
-/*
- * Hashing function using Bernstein's method
- */
-static PLHashNumber
-memberof_hash_fn(const void *key)
-{
- PLHashNumber hash = 5381;
- unsigned char *x = (unsigned char *)key;
- int c;
-
- while ((c = *x++)) {
- hash = ((hash << 5) + hash) ^ c;
- }
- return hash;
-}
-
-/* allocates the plugin hashtable
- * This hash table is used by operation and is protected from
- * concurrent operations with the memberof_lock (if not usetxn, memberof_lock
- * is not implemented and the hash table will be not used.
- *
- * The hash table contains all the DN of the entries for which the memberof
- * attribute has been computed/updated during the current operation
- *
- * hash table should be empty at the beginning and end of the plugin callback
- */
-static PLHashTable *
-hashtable_new()
-{
- if (!usetxn) {
- return NULL;
- }
-
- return PL_NewHashTable(MEMBEROF_HASHTABLE_SIZE,
- memberof_hash_fn,
- memberof_hash_compare_keys,
- memberof_hash_compare_values, NULL, NULL);
-}
-/* this function called for each hash node during hash destruction */
-static PRIntn
-fixup_hashtable_remove(PLHashEntry *he, PRIntn index __attribute__((unused)), void *arg __attribute__((unused)))
-{
- char *dn_copy;
-
- if (he == NULL) {
- return HT_ENUMERATE_NEXT;
- }
- dn_copy = (char *)he->value;
- slapi_ch_free_string(&dn_copy);
-
- return HT_ENUMERATE_REMOVE;
-}
-
-static void
-fixup_hashtable_empty(char *msg)
-{
- if (fixup_entry_hashtable) {
- PL_HashTableEnumerateEntries(fixup_entry_hashtable, fixup_hashtable_remove, msg);
- }
-}
-
-
-/* allocates the plugin hashtable
- * This hash table is used by operation and is protected from
- * concurrent operations with the memberof_lock (if not usetxn, memberof_lock
- * is not implemented and the hash table will be not used.
- *
- * The hash table contains all the DN of the entries for which the memberof
- * attribute has been computed/updated during the current operation
- *
- * hash table should be empty at the beginning and end of the plugin callback
- */
-
-static void
-ancestor_hashtable_entry_free(memberof_cached_value *entry)
-{
- int i;
- for (i = 0; entry[i].valid; i++) {
- slapi_ch_free((void **)&entry[i].group_dn_val);
- slapi_ch_free((void **)&entry[i].group_ndn_val);
- }
- /* Here we are at the ending element containing the key */
- slapi_ch_free((void **)&entry[i].key);
-}
-/* this function called for each hash node during hash destruction */
-static PRIntn
-ancestor_hashtable_remove(PLHashEntry *he, PRIntn index __attribute__((unused)), void *arg __attribute__((unused)))
-{
- memberof_cached_value *group_ancestor_array;
-
- if (he == NULL) {
- return HT_ENUMERATE_NEXT;
- }
-
-
- group_ancestor_array = (memberof_cached_value *)he->value;
- ancestor_hashtable_entry_free(group_ancestor_array);
- slapi_ch_free((void **)&group_ancestor_array);
-
- return HT_ENUMERATE_REMOVE;
-}
-
-static void
-ancestor_hashtable_empty(char *msg)
+int
+memberof_use_txn()
{
-#if defined(DEBUG) && defined(HAVE_CLOCK_GETTIME)
- long int start;
- struct timespec tsnow;
-#endif
-
- if (group_ancestors_hashtable) {
- cache_stat.total_enumerate++;
-#if defined(DEBUG) && defined(HAVE_CLOCK_GETTIME)
- if (clock_gettime(CLOCK_REALTIME, &tsnow) != 0) {
- start = 0;
- } else {
- start = tsnow.tv_nsec;
- }
-#endif
- PL_HashTableEnumerateEntries(group_ancestors_hashtable, ancestor_hashtable_remove, msg);
-
-#if defined(DEBUG) && defined(HAVE_CLOCK_GETTIME)
- if (start) {
- if (clock_gettime(CLOCK_REALTIME, &tsnow) == 0) {
- cache_stat.cumul_duration_enumerate += (tsnow.tv_nsec - start);
- }
- }
-#endif
- }
+ return usetxn;
}
diff --git a/ldap/servers/plugins/memberof/memberof.h b/ldap/servers/plugins/memberof/memberof.h
index 4833ce221..ba64e9dfa 100644
--- a/ldap/servers/plugins/memberof/memberof.h
+++ b/ldap/servers/plugins/memberof/memberof.h
@@ -64,8 +64,22 @@ typedef struct memberofconfig
int skip_nested;
int fixup_task;
char *auto_add_oc;
+ PLHashTable *ancestors_cache;
+ PLHashTable *fixup_cache;
} MemberOfConfig;
+/* The key to access the hash table is the normalized DN
+ * The normalized DN is stored in the value because:
+ * - It is used in slapi_valueset_find
+ * - It is used to fill the memberof_get_groups_data.group_norm_vals
+ */
+typedef struct _memberof_cached_value
+{
+ char *key;
+ char *group_dn_val;
+ char *group_ndn_val;
+ int valid;
+} memberof_cached_value;
/*
* functions
@@ -89,5 +103,8 @@ int memberof_apply_config(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entr
void *memberof_get_plugin_id(void);
void memberof_release_config(void);
PRUint64 get_plugin_started(void);
+void ancestor_hashtable_entry_free(memberof_cached_value *entry);
+PLHashTable *hashtable_new();
+int memberof_use_txn();
#endif /* _MEMBEROF_H_ */
diff --git a/ldap/servers/plugins/memberof/memberof_config.c b/ldap/servers/plugins/memberof/memberof_config.c
index c5ca4b137..3f22d95d6 100644
--- a/ldap/servers/plugins/memberof/memberof_config.c
+++ b/ldap/servers/plugins/memberof/memberof_config.c
@@ -14,12 +14,12 @@
* memberof_config.c - configuration-related code for memberOf plug-in
*
*/
-
+#include "plhash.h"
#include <plstr.h>
-
#include "memberof.h"
#define MEMBEROF_CONFIG_FILTER "(objectclass=*)"
+#define MEMBEROF_HASHTABLE_SIZE 1000
/*
* The configuration attributes are contained in the plugin entry e.g.
@@ -34,14 +34,16 @@
/*
* function prototypes
*/
-static int memberof_validate_config(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry *e, int *returncode, char *returntext, void *arg);
-static int
-memberof_search(Slapi_PBlock *pb __attribute__((unused)),
- Slapi_Entry *entryBefore __attribute__((unused)),
- Slapi_Entry *e __attribute__((unused)),
- int *returncode __attribute__((unused)),
- char *returntext __attribute__((unused)),
- void *arg __attribute__((unused)))
+static void fixup_hashtable_empty( MemberOfConfig *config, char *msg);
+static void ancestor_hashtable_empty(MemberOfConfig *config, char *msg);
+static int memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
+ int *returncode, char *returntext, void *arg);
+static int memberof_search (Slapi_PBlock *pb __attribute__((unused)),
+ Slapi_Entry* entryBefore __attribute__((unused)),
+ Slapi_Entry* e __attribute__((unused)),
+ int *returncode __attribute__((unused)),
+ char *returntext __attribute__((unused)),
+ void *arg __attribute__((unused)))
{
return SLAPI_DSE_CALLBACK_OK;
}
@@ -52,7 +54,7 @@ memberof_search(Slapi_PBlock *pb __attribute__((unused)),
/* This is the main configuration which is updated from dse.ldif. The
* config will be copied when it is used by the plug-in to prevent it
* being changed out from under a running memberOf operation. */
-static MemberOfConfig theConfig = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static MemberOfConfig theConfig = {0};
static Slapi_RWLock *memberof_config_lock = 0;
static int inited = 0;
@@ -693,6 +695,13 @@ void
memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src)
{
if (dest && src) {
+
+ /* Allocate our caches here since we only copy the config at the start of an op */
+ if (memberof_use_txn() == 1){
+ dest->ancestors_cache = hashtable_new();
+ dest->fixup_cache = hashtable_new();
+ }
+
/* Check if the copy is already up to date */
if (src->groupattrs) {
int i = 0, j = 0;
@@ -787,6 +796,14 @@ memberof_free_config(MemberOfConfig *config)
slapi_ch_free_string(&config->memberof_attr);
memberof_free_scope(&(config->entryScopes), &config->entryScopeCount);
memberof_free_scope(&(config->entryScopeExcludeSubtrees), &config->entryExcludeScopeCount);
+ if (config->fixup_cache) {
+ fixup_hashtable_empty(config, "memberof_free_config empty fixup_entry_hastable");
+ PL_HashTableDestroy(config->fixup_cache);
+ }
+ if (config->ancestors_cache) {
+ ancestor_hashtable_empty(config, "memberof_free_config empty group_ancestors_hashtable");
+ PL_HashTableDestroy(config->ancestors_cache);
+ }
}
}
@@ -982,3 +999,130 @@ bail:
return ret;
}
+
+
+static PRIntn memberof_hash_compare_keys(const void *v1, const void *v2)
+{
+ PRIntn rc;
+ if (0 == strcasecmp((const char *) v1, (const char *) v2)) {
+ rc = 1;
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+static PRIntn memberof_hash_compare_values(const void *v1, const void *v2)
+{
+ PRIntn rc;
+ if ((char *) v1 == (char *) v2) {
+ rc = 1;
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+/*
+ * Hashing function using Bernstein's method
+ */
+static PLHashNumber memberof_hash_fn(const void *key)
+{
+ PLHashNumber hash = 5381;
+ unsigned char *x = (unsigned char *)key;
+ int c;
+
+ while ((c = *x++)){
+ hash = ((hash << 5) + hash) ^ c;
+ }
+ return hash;
+}
+
+/* allocates the plugin hashtable
+ * This hash table is used by operation and is protected from
+ * concurrent operations with the memberof_lock (if not usetxn, memberof_lock
+ * is not implemented and the hash table will be not used.
+ *
+ * The hash table contains all the DN of the entries for which the memberof
+ * attribute has been computed/updated during the current operation
+ *
+ * hash table should be empty at the beginning and end of the plugin callback
+ */
+PLHashTable *hashtable_new(int usetxn)
+{
+ if (!usetxn) {
+ return NULL;
+ }
+
+ return PL_NewHashTable(MEMBEROF_HASHTABLE_SIZE,
+ memberof_hash_fn,
+ memberof_hash_compare_keys,
+ memberof_hash_compare_values, NULL, NULL);
+}
+
+/* this function called for each hash node during hash destruction */
+static PRIntn fixup_hashtable_remove(PLHashEntry *he, PRIntn index __attribute__((unused)), void *arg __attribute__((unused)))
+{
+ char *dn_copy;
+
+ if (he == NULL) {
+ return HT_ENUMERATE_NEXT;
+ }
+ dn_copy = (char*) he->value;
+ slapi_ch_free_string(&dn_copy);
+
+ return HT_ENUMERATE_REMOVE;
+}
+
+static void fixup_hashtable_empty(MemberOfConfig *config, char *msg)
+{
+ if (config->fixup_cache) {
+ PL_HashTableEnumerateEntries(config->fixup_cache, fixup_hashtable_remove, msg);
+ }
+}
+
+
+/* allocates the plugin hashtable
+ * This hash table is used by operation and is protected from
+ * concurrent operations with the memberof_lock (if not usetxn, memberof_lock
+ * is not implemented and the hash table will be not used.
+ *
+ * The hash table contains all the DN of the entries for which the memberof
+ * attribute has been computed/updated during the current operation
+ *
+ * hash table should be empty at the beginning and end of the plugin callback
+ */
+
+void ancestor_hashtable_entry_free(memberof_cached_value *entry)
+{
+ int i;
+
+ for (i = 0; entry[i].valid; i++) {
+ slapi_ch_free((void **) &entry[i].group_dn_val);
+ slapi_ch_free((void **) &entry[i].group_ndn_val);
+ }
+ /* Here we are at the ending element containing the key */
+ slapi_ch_free((void**) &entry[i].key);
+}
+
+/* this function called for each hash node during hash destruction */
+static PRIntn ancestor_hashtable_remove(PLHashEntry *he, PRIntn index __attribute__((unused)), void *arg __attribute__((unused)))
+{
+ memberof_cached_value *group_ancestor_array;
+
+ if (he == NULL) {
+ return HT_ENUMERATE_NEXT;
+ }
+ group_ancestor_array = (memberof_cached_value *) he->value;
+ ancestor_hashtable_entry_free(group_ancestor_array);
+ slapi_ch_free((void **)&group_ancestor_array);
+
+ return HT_ENUMERATE_REMOVE;
+}
+
+static void ancestor_hashtable_empty(MemberOfConfig *config, char *msg)
+{
+ if (config->ancestors_cache) {
+ PL_HashTableEnumerateEntries(config->ancestors_cache, ancestor_hashtable_remove, msg);
+ }
+}
--
2.13.6

View file

@ -1,4 +1,4 @@
From 1bb5fd7fac9c5b93d3dfb8b8a2a648e238a158bc Mon Sep 17 00:00:00 2001
From de03e7456108de3f3d28c6a5d33926525b70557f Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 30 Aug 2018 14:28:10 -0400
Subject: [PATCH] Ticket 49932 - Crash in delete_passwdPolicy when persistent

View file

@ -0,0 +1,99 @@
From ab7848a4a30d79c7433a1689ba1ea18897b73453 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 18 Sep 2018 16:39:26 -0400
Subject: [PATCH] Bug 1624004 - potential denial of service attack
Bug: a search request passing 8MB of NULL bytes as search attributes will
keep one thread busy for a long time.
The reason is that the attr array is copied/normalized to the searchattrs in
the search operation and does this using charray_add() which iterates thru
the array to determine the size of the array and then allocate one element more.
so this means we iterat 8 million times an array with a then average size of
4 million elements.
Fix: We already have traversed the array once and know the size, so we can allocate
the needed size once and only copy the element.
In addition we check for the kind of degenerated attributes "" as used in this
test scenario.
So the fix will reject invalid attr liste and improve performance for valid ones
https://bugzilla.redhat.com/show_bug.cgi?id=1624004
---
ldap/servers/slapd/search.c | 16 ++++++++++++++--
ldap/servers/slapd/unbind.c | 4 ++--
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c
index 731c6519e..dc26fc4d2 100644
--- a/ldap/servers/slapd/search.c
+++ b/ldap/servers/slapd/search.c
@@ -209,6 +209,7 @@ do_search(Slapi_PBlock *pb)
if (attrs != NULL) {
char *normaci = slapi_attr_syntax_normalize("aci");
int replace_aci = 0;
+ int attr_count = 0;
if (!normaci) {
normaci = slapi_ch_strdup("aci");
} else if (strcasecmp(normaci, "aci")) {
@@ -218,9 +219,19 @@ do_search(Slapi_PBlock *pb)
/*
* . store gerattrs if any
* . add "aci" once if "*" is given
+ * . check that attrs are not degenerated
*/
for (i = 0; attrs[i] != NULL; i++) {
char *p = NULL;
+ attr_count++;
+
+ if ( attrs[i][0] == '\0') {
+ log_search_access(pb, base, scope, fstr, "invalid attribute request");
+ send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL);
+ slapi_ch_free_string(&normaci);
+ goto free_and_return;
+ }
+
/* check if @<objectclass> is included */
p = strchr(attrs[i], '@');
if (p) {
@@ -244,6 +255,7 @@ do_search(Slapi_PBlock *pb)
} else if (strcmp(attrs[i], LDAP_ALL_USER_ATTRS /* '*' */) == 0) {
if (!charray_inlist(attrs, normaci)) {
charray_add(&attrs, slapi_ch_strdup(normaci));
+ attr_count++;
}
} else if (replace_aci && (strcasecmp(attrs[i], "aci") == 0)) {
slapi_ch_free_string(&attrs[i]);
@@ -263,13 +275,13 @@ do_search(Slapi_PBlock *pb)
}
} else {
/* return the chopped type, e.g., "sn" */
- operation->o_searchattrs = NULL;
+ operation->o_searchattrs = (char **)slapi_ch_calloc(sizeof(char *), attr_count+1);
for (i = 0; attrs[i] != NULL; i++) {
char *type;
type = slapi_attr_syntax_normalize_ext(attrs[i],
ATTR_SYNTAX_NORM_ORIG_ATTR);
/* attrs[i] is consumed */
- charray_add(&operation->o_searchattrs, attrs[i]);
+ operation->o_searchattrs[i] = attrs[i];
attrs[i] = type;
}
}
diff --git a/ldap/servers/slapd/unbind.c b/ldap/servers/slapd/unbind.c
index 90f7b1546..686e27a8e 100644
--- a/ldap/servers/slapd/unbind.c
+++ b/ldap/servers/slapd/unbind.c
@@ -87,8 +87,8 @@ do_unbind(Slapi_PBlock *pb)
/* pass the unbind to all backends */
be_unbindall(pb_conn, operation);
+free_and_return:;
+
/* close the connection to the client */
disconnect_server(pb_conn, operation->o_connid, operation->o_opid, SLAPD_DISCONNECT_UNBIND, 0);
-
-free_and_return:;
}
--
2.17.1

View file

@ -1,47 +0,0 @@
From 23a82820bce65653f96450fcc410706fa555fbfd Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 16 Oct 2017 10:44:29 -0400
Subject: [PATCH] Ticket 48235 - remove memberof lock (cherry-pick error)
Description: Fix cherry-pick error
https://pagure.io/389-ds-base/issue/48235
Reviewed by: mreynolds(one line commit rule)
(cherry picked from commit 3eb443b0ee11f3cf642ebfbcd135868a72ce39da)
---
ldap/servers/plugins/memberof/memberof.c | 3 ---
ldap/servers/plugins/memberof/memberof.h | 2 --
2 files changed, 5 deletions(-)
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
index a23c52abe..bae242c81 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -2828,9 +2828,6 @@ memberof_fixup_task_thread(void *arg)
}
}
- /* get the memberOf operation lock */
- memberof_lock();
-
/* do real work */
rc = memberof_fix_memberof(&configCopy, task, td);
diff --git a/ldap/servers/plugins/memberof/memberof.h b/ldap/servers/plugins/memberof/memberof.h
index ba64e9dfa..cf028453c 100644
--- a/ldap/servers/plugins/memberof/memberof.h
+++ b/ldap/servers/plugins/memberof/memberof.h
@@ -88,8 +88,6 @@ int memberof_config(Slapi_Entry *config_e, Slapi_PBlock *pb);
void memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src);
void memberof_free_config(MemberOfConfig *config);
MemberOfConfig *memberof_get_config(void);
-void memberof_lock(void);
-void memberof_unlock(void);
void memberof_rlock_config(void);
void memberof_wlock_config(void);
void memberof_unlock_config(void);
--
2.13.6

View file

@ -0,0 +1,43 @@
From 55e961338810d89a6f45f31f27b3fd609535b1da Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 19 Sep 2018 09:26:59 -0400
Subject: [PATCH] Bug 1624004 - fix regression in empty attribute list
https://bugzilla.redhat.com/show_bug.cgi?id=1624004
---
ldap/servers/slapd/search.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c
index dc26fc4d2..7e253f535 100644
--- a/ldap/servers/slapd/search.c
+++ b/ldap/servers/slapd/search.c
@@ -210,6 +210,7 @@ do_search(Slapi_PBlock *pb)
char *normaci = slapi_attr_syntax_normalize("aci");
int replace_aci = 0;
int attr_count = 0;
+ int empty_attrs = 0;
if (!normaci) {
normaci = slapi_ch_strdup("aci");
} else if (strcasecmp(normaci, "aci")) {
@@ -226,10 +227,13 @@ do_search(Slapi_PBlock *pb)
attr_count++;
if ( attrs[i][0] == '\0') {
- log_search_access(pb, base, scope, fstr, "invalid attribute request");
- send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL);
- slapi_ch_free_string(&normaci);
- goto free_and_return;
+ empty_attrs++;
+ if (empty_attrs > 1) {
+ log_search_access(pb, base, scope, fstr, "invalid attribute request");
+ send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL);
+ slapi_ch_free_string(&normaci);
+ goto free_and_return;
+ }
}
/* check if @<objectclass> is included */
--
2.17.1

View file

@ -1,703 +0,0 @@
From 0b58d1a62679c3961bc41e03591c4277fb9f183e Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Thu, 5 Oct 2017 12:50:50 +0200
Subject: [PATCH] Ticket 49394 - slapi_pblock_get may leave unchanged the
provided variable
Bug Description:
Since 1.3.6.4 the pblock struct is a split in sub-structs
(https://pagure.io/389-ds-base/issue/49097)
Before, it was a quite flat calloc struct and any slapi-pblock-get
retrieved the field (NULL if not previously slapi_pblock_set) and
assigned the provided variable.
Now, the sub-struct are allocated on demand (slapi_pblock_set).
If a substruct that contains the requested field is not allocated the
provided variable is unchanged.
This is a change of behavior, because a uninitialized local variable can
get random value (stack) if the lookup field/struct has not been set.
Fix Description:
Update slapi_pblock_set so that it systematically sets the
provided variable when those substructs are NULL
pb_mr
pb_dse
pb_task
pb_misc
pb_intop
pb_intplugin
pb_deprecated
https://pagure.io/389-ds-base/issue/49394
Reviewed by: Mark Reynolds, William Brown
Platforms tested: F23
Flag Day: no
Doc impact: no
---
ldap/servers/slapd/pblock.c | 166 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 165 insertions(+), 1 deletion(-)
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 077684d23..8f87de5b5 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -379,6 +379,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_BACKEND_COUNT:
if (pblock->pb_misc != NULL) {
(*(int *)value) = pblock->pb_misc->pb_backend_count;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_BE_TYPE:
@@ -616,6 +618,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_REQUESTOR_ISROOT:
if (pblock->pb_intop != NULL) {
(*(int *)value) = pblock->pb_intop->pb_requestor_isroot;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_SKIP_MODIFIED_ATTRS:
@@ -657,6 +661,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_DESTROY_CONTENT:
if (pblock->pb_deprecated != NULL) {
(*(int *)value) = pblock->pb_deprecated->pb_destroy_content;
+ } else {
+ (*(int *)value) = 0;
}
break;
@@ -685,16 +691,22 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_PLUGIN_OPRETURN:
if (pblock->pb_intop != NULL) {
(*(int *)value) = pblock->pb_intop->pb_opreturn;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_PLUGIN_OBJECT:
if (pblock->pb_intplugin != NULL) {
(*(void **)value) = pblock->pb_intplugin->pb_object;
+ } else {
+ (*(void **)value) = NULL;
}
break;
case SLAPI_PLUGIN_DESTROY_FN:
if (pblock->pb_intplugin != NULL) {
(*(IFP *)value) = pblock->pb_intplugin->pb_destroy_fn;
+ } else {
+ (*(IFP *)value) = NULL;
}
break;
case SLAPI_PLUGIN_DESCRIPTION:
@@ -703,11 +715,15 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_PLUGIN_IDENTITY:
if (pblock->pb_intplugin != NULL) {
(*(void **)value) = pblock->pb_intplugin->pb_plugin_identity;
+ } else {
+ (*(void **)value) = NULL;
}
break;
case SLAPI_PLUGIN_CONFIG_AREA:
if (pblock->pb_intplugin != NULL) {
(*(char **)value) = pblock->pb_intplugin->pb_plugin_config_area;
+ } else {
+ (*(char **)value) = 0;
}
break;
case SLAPI_PLUGIN_CONFIG_DN:
@@ -718,16 +734,22 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_PLUGIN_INTOP_RESULT:
if (pblock->pb_intop != NULL) {
(*(int *)value) = pblock->pb_intop->pb_internal_op_result;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES:
if (pblock->pb_intop != NULL) {
(*(Slapi_Entry ***)value) = pblock->pb_intop->pb_plugin_internal_search_op_entries;
+ } else {
+ (*(Slapi_Entry ***)value) = NULL;
}
break;
case SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS:
if (pblock->pb_intop != NULL) {
(*(char ***)value) = pblock->pb_intop->pb_plugin_internal_search_op_referrals;
+ } else {
+ (*(char ***)value) = NULL;
}
break;
@@ -1167,11 +1189,15 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_ENTRY_PRE_OP:
if (pblock->pb_intop != NULL) {
(*(Slapi_Entry **)value) = pblock->pb_intop->pb_pre_op_entry;
+ } else {
+ (*(Slapi_Entry **)value) = NULL;
}
break;
case SLAPI_ENTRY_POST_OP:
if (pblock->pb_intop != NULL) {
(*(Slapi_Entry **)value) = pblock->pb_intop->pb_post_op_entry;
+ } else {
+ (*(Slapi_Entry **)value) = NULL;
}
break;
@@ -1419,12 +1445,16 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_CONTROLS_ARG: /* used to pass control argument before operation is created */
if (pblock->pb_intop != NULL) {
(*(LDAPControl ***)value) = pblock->pb_intop->pb_ctrls_arg;
+ } else {
+ (*(LDAPControl ***)value) = NULL;
}
break;
/* notes to be added to the access log RESULT line for this op. */
case SLAPI_OPERATION_NOTES:
if (pblock->pb_intop != NULL) {
(*(unsigned int *)value) = pblock->pb_intop->pb_operation_notes;
+ } else {
+ (*(unsigned int *)value) = 0;
}
break;
@@ -1486,6 +1516,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_SYNTAX_SUBSTRLENS: /* aka SLAPI_MR_SUBSTRLENS */
if (pblock->pb_intplugin != NULL) {
(*(int **)value) = pblock->pb_intplugin->pb_substrlens;
+ } else {
+ (*(int **)value) = NULL;
}
break;
case SLAPI_PLUGIN_SYNTAX_VALIDATE:
@@ -1505,11 +1537,15 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_MANAGEDSAIT:
if (pblock->pb_intop != NULL) {
(*(int *)value) = pblock->pb_intop->pb_managedsait;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_PWPOLICY:
if (pblock->pb_intop != NULL) {
(*(int *)value) = pblock->pb_intop->pb_pwpolicy_ctrl;
+ } else {
+ (*(int *)value) = 0;
}
break;
@@ -1522,11 +1558,15 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_ADD_EXISTING_DN_ENTRY:
if (pblock->pb_intop != NULL) {
(*(Slapi_Entry **)value) = pblock->pb_intop->pb_existing_dn_entry;
+ } else {
+ (*(Slapi_Entry **)value) = NULL;
}
break;
case SLAPI_ADD_EXISTING_UNIQUEID_ENTRY:
if (pblock->pb_intop != NULL) {
(*(Slapi_Entry **)value) = pblock->pb_intop->pb_existing_uniqueid_entry;
+ } else {
+ (*(Slapi_Entry **)value) = NULL;
}
break;
case SLAPI_ADD_PARENT_ENTRY:
@@ -1537,6 +1577,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_ADD_PARENT_UNIQUEID:
if (pblock->pb_op != NULL) {
(*(char **)value) = pblock->pb_op->o_params.p.p_add.parentuniqueid;
+ } else {
+ (*(char **)value) = NULL;
}
break;
@@ -1624,16 +1666,22 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_MODRDN_PARENT_ENTRY:
if (pblock->pb_intop != NULL) {
(*(Slapi_Entry **)value) = pblock->pb_intop->pb_parent_entry;
+ } else {
+ (*(Slapi_Entry **)value) = NULL;
}
break;
case SLAPI_MODRDN_NEWPARENT_ENTRY:
if (pblock->pb_intop != NULL) {
(*(Slapi_Entry **)value) = pblock->pb_intop->pb_newparent_entry;
+ } else {
+ (*(Slapi_Entry **)value) = NULL;
}
break;
case SLAPI_MODRDN_TARGET_ENTRY:
if (pblock->pb_intop != NULL) {
(*(Slapi_Entry **)value) = pblock->pb_intop->pb_target_entry;
+ } else {
+ (*(Slapi_Entry **)value) = NULL;
}
break;
case SLAPI_MODRDN_NEWSUPERIOR_ADDRESS:
@@ -1740,26 +1788,36 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_PLUGIN_MR_FILTER_MATCH_FN:
if (pblock->pb_mr != NULL) {
(*(mrFilterMatchFn *)value) = pblock->pb_mr->filter_match_fn;
+ } else {
+ (*(mrFilterMatchFn *)value) = NULL;
}
break;
case SLAPI_PLUGIN_MR_FILTER_INDEX_FN:
if (pblock->pb_mr != NULL) {
(*(IFP *)value) = pblock->pb_mr->filter_index_fn;
+ } else {
+ (*(IFP *)value) = NULL;
}
break;
case SLAPI_PLUGIN_MR_FILTER_RESET_FN:
if (pblock->pb_mr != NULL) {
(*(IFP *)value) = pblock->pb_mr->filter_reset_fn;
+ } else {
+ (*(IFP *)value) = NULL;
}
break;
case SLAPI_PLUGIN_MR_INDEX_FN:
if (pblock->pb_mr != NULL) {
(*(IFP *)value) = pblock->pb_mr->index_fn;
+ } else {
+ (*(IFP *)value) = NULL;
}
break;
case SLAPI_PLUGIN_MR_INDEX_SV_FN:
if (pblock->pb_mr != NULL) {
(*(IFP *)value) = pblock->pb_mr->index_sv_fn;
+ } else {
+ (*(IFP *)value) = NULL;
}
break;
@@ -1767,41 +1825,57 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_PLUGIN_MR_OID:
if (pblock->pb_mr != NULL) {
(*(char **)value) = pblock->pb_mr->oid;
+ } else {
+ (*(char **)value) = NULL;
}
break;
case SLAPI_PLUGIN_MR_TYPE:
if (pblock->pb_mr != NULL) {
(*(char **)value) = pblock->pb_mr->type;
+ } else {
+ (*(char **)value) = NULL;
}
break;
case SLAPI_PLUGIN_MR_VALUE:
if (pblock->pb_mr != NULL) {
(*(struct berval **)value) = pblock->pb_mr->value;
+ } else {
+ (*(struct berval **)value) = NULL;
}
break;
case SLAPI_PLUGIN_MR_VALUES:
if (pblock->pb_mr != NULL) {
(*(struct berval ***)value) = pblock->pb_mr->values;
+ } else {
+ (*(struct berval ***)value) = NULL;
}
break;
case SLAPI_PLUGIN_MR_KEYS:
if (pblock->pb_mr != NULL) {
(*(struct berval ***)value) = pblock->pb_mr->keys;
+ } else {
+ (*(struct berval ***)value) = NULL;
}
break;
case SLAPI_PLUGIN_MR_FILTER_REUSABLE:
if (pblock->pb_mr != NULL) {
(*(unsigned int *)value) = pblock->pb_mr->filter_reusable;
+ } else {
+ (*(unsigned int *)value) = 0;
}
break;
case SLAPI_PLUGIN_MR_QUERY_OPERATOR:
if (pblock->pb_mr != NULL) {
(*(int *)value) = pblock->pb_mr->query_operator;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_PLUGIN_MR_USAGE:
if (pblock->pb_mr != NULL) {
(*(unsigned int *)value) = pblock->pb_mr->usage;
+ } else {
+ (*(unsigned int *)value) = 0;
}
break;
@@ -1865,16 +1939,22 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_SEQ_TYPE:
if (pblock->pb_task != NULL) {
(*(int *)value) = pblock->pb_task->seq_type;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_SEQ_ATTRNAME:
if (pblock->pb_task != NULL) {
(*(char **)value) = pblock->pb_task->seq_attrname;
+ } else {
+ (*(char **)value) = NULL;
}
break;
case SLAPI_SEQ_VAL:
if (pblock->pb_task != NULL) {
(*(char **)value) = pblock->pb_task->seq_val;
+ } else {
+ (*(char **)value) = NULL;
}
break;
@@ -1882,47 +1962,65 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_LDIF2DB_FILE:
if (pblock->pb_task != NULL) {
(*(char ***)value) = pblock->pb_task->ldif_files;
+ } else {
+ (*(char ***)value) = NULL;
}
break;
case SLAPI_LDIF2DB_REMOVEDUPVALS:
if (pblock->pb_task != NULL) {
(*(int *)value) = pblock->pb_task->removedupvals;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_DB2INDEX_ATTRS:
if (pblock->pb_task != NULL) {
(*(char ***)value) = pblock->pb_task->db2index_attrs;
+ } else {
+ (*(char ***)value) = NULL;
}
break;
case SLAPI_LDIF2DB_NOATTRINDEXES:
if (pblock->pb_task != NULL) {
(*(int *)value) = pblock->pb_task->ldif2db_noattrindexes;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_LDIF2DB_INCLUDE:
if (pblock->pb_task != NULL) {
(*(char ***)value) = pblock->pb_task->ldif_include;
+ } else {
+ (*(char ***)value) = NULL;
}
break;
case SLAPI_LDIF2DB_EXCLUDE:
if (pblock->pb_task != NULL) {
(*(char ***)value) = pblock->pb_task->ldif_exclude;
+ } else {
+ (*(char ***)value) = NULL;
}
break;
case SLAPI_LDIF2DB_GENERATE_UNIQUEID:
if (pblock->pb_task != NULL) {
(*(int *)value) = pblock->pb_task->ldif_generate_uniqueid;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_LDIF2DB_ENCRYPT:
case SLAPI_DB2LDIF_DECRYPT:
if (pblock->pb_task != NULL) {
(*(int *)value) = pblock->pb_task->ldif_encrypt;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_LDIF2DB_NAMESPACEID:
if (pblock->pb_task != NULL) {
(*(char **)value) = pblock->pb_task->ldif_namespaceid;
+ } else {
+ (*(char **)value) = NULL;
}
break;
@@ -1930,16 +2028,22 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_DB2LDIF_PRINTKEY:
if (pblock->pb_task != NULL) {
(*(int *)value) = pblock->pb_task->ldif_printkey;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_DB2LDIF_DUMP_UNIQUEID:
if (pblock->pb_task != NULL) {
(*(int *)value) = pblock->pb_task->ldif_dump_uniqueid;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_DB2LDIF_FILE:
if (pblock->pb_task != NULL) {
(*(char **)value) = pblock->pb_task->ldif_file;
+ } else {
+ (*(char **)value) = NULL;
}
break;
@@ -1947,37 +2051,51 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_BACKEND_INSTANCE_NAME:
if (pblock->pb_task != NULL) {
(*(char **)value) = pblock->pb_task->instance_name;
+ } else {
+ (*(char **)value) = NULL;
}
break;
case SLAPI_BACKEND_TASK:
if (pblock->pb_task != NULL) {
(*(Slapi_Task **)value) = pblock->pb_task->task;
+ } else {
+ (*(Slapi_Task **)value) = NULL;
}
break;
case SLAPI_TASK_FLAGS:
if (pblock->pb_task != NULL) {
(*(int *)value) = pblock->pb_task->task_flags;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_DB2LDIF_SERVER_RUNNING:
if (pblock->pb_task != NULL) {
(*(int *)value) = pblock->pb_task->server_running;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_BULK_IMPORT_ENTRY:
if (pblock->pb_task != NULL) {
(*(Slapi_Entry **)value) = pblock->pb_task->import_entry;
+ } else {
+ (*(Slapi_Entry **)value) = NULL;
}
break;
case SLAPI_BULK_IMPORT_STATE:
if (pblock->pb_task != NULL) {
(*(int *)value) = pblock->pb_task->import_state;
+ } else {
+ (*(int *)value) = 0;
}
break;
/* dbverify */
case SLAPI_DBVERIFY_DBDIR:
if (pblock->pb_task != NULL) {
(*(char **)value) = pblock->pb_task->dbverify_dbdir;
+ } else {
+ (*(char **)value) = NULL;
}
break;
@@ -1993,11 +2111,15 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_TXN:
if (pblock->pb_intop != NULL) {
(*(void **)value) = pblock->pb_intop->pb_txn;
+ } else {
+ (*(void **)value) = NULL;
}
break;
case SLAPI_TXN_RUV_MODS_FN:
if (pblock->pb_intop != NULL) {
(*(IFP *)value) = pblock->pb_intop->pb_txn_ruv_mods_fn;
+ } else {
+ (*(IFP *)value) = NULL;
}
break;
@@ -2052,6 +2174,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_PB_RESULT_TEXT:
if (pblock->pb_intop != NULL) {
*((char **)value) = pblock->pb_intop->pb_result_text;
+ } else {
+ *((char **)value) = NULL;
}
break;
@@ -2059,6 +2183,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_DBSIZE:
if (pblock->pb_misc != NULL) {
(*(unsigned int *)value) = pblock->pb_misc->pb_dbsize;
+ } else {
+ (*(unsigned int *)value) = 0;
}
break;
@@ -2153,11 +2279,15 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_ARGC:
if (pblock->pb_misc != NULL) {
(*(int *)value) = pblock->pb_misc->pb_slapd_argc;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_ARGV:
if (pblock->pb_misc != NULL) {
(*(char ***)value) = pblock->pb_misc->pb_slapd_argv;
+ } else {
+ (*(char ***)value) = NULL;
}
break;
@@ -2165,6 +2295,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_CONFIG_DIRECTORY:
if (pblock->pb_intplugin != NULL) {
(*(char **)value) = pblock->pb_intplugin->pb_slapd_configdir;
+ } else {
+ (*(char **)value) = NULL;
}
break;
@@ -2175,12 +2307,16 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_PLUGIN_PWD_STORAGE_SCHEME_USER_PWD:
if (pblock->pb_deprecated != NULL) {
(*(char **)value) = pblock->pb_deprecated->pb_pwd_storage_scheme_user_passwd;
+ } else {
+ (*(char **)value) = NULL;
}
break;
case SLAPI_PLUGIN_PWD_STORAGE_SCHEME_DB_PWD:
if (pblock->pb_deprecated != NULL) {
(*(char **)value) = pblock->pb_deprecated->pb_pwd_storage_scheme_db_passwd;
+ } else {
+ (*(char **)value) = NULL;
}
break;
@@ -2208,6 +2344,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_PLUGIN_ENABLED:
if (pblock->pb_intplugin != NULL) {
*((int *)value) = pblock->pb_intplugin->pb_plugin_enabled;
+ } else {
+ *((int *)value) = 0;
}
break;
@@ -2215,6 +2353,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_DSE_DONT_WRITE_WHEN_ADDING:
if (pblock->pb_dse != NULL) {
(*(int *)value) = pblock->pb_dse->dont_add_write;
+ } else {
+ (*(int *)value) = 0;
}
break;
@@ -2222,6 +2362,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_DSE_MERGE_WHEN_ADDING:
if (pblock->pb_dse != NULL) {
(*(int *)value) = pblock->pb_dse->add_merge;
+ } else {
+ (*(int *)value) = 0;
}
break;
@@ -2229,6 +2371,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_DSE_DONT_CHECK_DUPS:
if (pblock->pb_dse != NULL) {
(*(int *)value) = pblock->pb_dse->dont_check_dups;
+ } else {
+ (*(int *)value) = 0;
}
break;
@@ -2236,6 +2380,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_DSE_REAPPLY_MODS:
if (pblock->pb_dse != NULL) {
(*(int *)value) = pblock->pb_dse->reapply_mods;
+ } else {
+ (*(int *)value) = 0;
}
break;
@@ -2243,6 +2389,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_DSE_IS_PRIMARY_FILE:
if (pblock->pb_dse != NULL) {
(*(int *)value) = pblock->pb_dse->is_primary_file;
+ } else {
+ (*(int *)value) = 0;
}
break;
@@ -2250,42 +2398,56 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_SCHEMA_FLAGS:
if (pblock->pb_dse != NULL) {
(*(int *)value) = pblock->pb_dse->schema_flags;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_URP_NAMING_COLLISION_DN:
if (pblock->pb_intop != NULL) {
(*(char **)value) = pblock->pb_intop->pb_urp_naming_collision_dn;
+ } else {
+ (*(char **)value) = NULL;
}
break;
case SLAPI_URP_TOMBSTONE_UNIQUEID:
if (pblock->pb_intop != NULL) {
(*(char **)value) = pblock->pb_intop->pb_urp_tombstone_uniqueid;
+ } else {
+ (*(char **)value) = NULL;
}
break;
case SLAPI_URP_TOMBSTONE_CONFLICT_DN:
if (pblock->pb_intop != NULL) {
- (*(char **)value) = pblock->pb_intop->pb_urp_tombstone_conflict_dn;
+ (*(char **)value) = pblock->pb_intop->pb_urp_tombstone_conflict_dn;
+ } else {
+ (*(char **)value) = NULL;
}
break;
case SLAPI_SEARCH_CTRLS:
if (pblock->pb_intop != NULL) {
(*(LDAPControl ***)value) = pblock->pb_intop->pb_search_ctrls;
+ } else {
+ (*(LDAPControl ***)value) = NULL;
}
break;
case SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED:
if (pblock->pb_intplugin != NULL) {
(*(int *)value) = pblock->pb_intplugin->pb_syntax_filter_normalized;
+ } else {
+ (*(int *)value) = 0;
}
break;
case SLAPI_PLUGIN_SYNTAX_FILTER_DATA:
if (pblock->pb_intplugin != NULL) {
(*(void **)value) = pblock->pb_intplugin->pb_syntax_filter_data;
+ } else {
+ (*(void **)value) = NULL;
}
break;
@@ -2311,6 +2473,8 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
case SLAPI_ACI_TARGET_CHECK:
if (pblock->pb_misc != NULL) {
(*(int *)value) = pblock->pb_misc->pb_aci_target_check;
+ } else {
+ (*(int *)value) = 0;
}
break;
--
2.13.6

View file

@ -1,40 +0,0 @@
From 697e01b0ca2d028f0d2cabc47ab2335de93b0491 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 16 Oct 2017 12:52:46 -0400
Subject: [PATCH] Ticket 49402 - Adding a database entry with the same database
name that was deleted hangs server at shutdown
Bug Description: At shutdown, after a backend was deleted, which also had a import
task run, the server hangs at shutdown. The issue is that the
import task destructor used the ldbm inst struct to see if it was
busy, but the inst was freed and the destructor was checking invalid
memory which caused a false positive on the "busy" check.
Fix Description: Do not check if the instance is busy to tell if it's okay to remove
the task, instead just check the task's state.
https://pagure.io/389-ds-base/issue/49402
Reviewed by: lkrispen(Thanks!)
(cherry picked from commit bc6dbf15c160ac7e6c553133b2b936a981cfb7b6)
---
ldap/servers/slapd/back-ldbm/import.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/slapd/back-ldbm/import.c b/ldap/servers/slapd/back-ldbm/import.c
index e8f4a5615..42e2696d3 100644
--- a/ldap/servers/slapd/back-ldbm/import.c
+++ b/ldap/servers/slapd/back-ldbm/import.c
@@ -244,7 +244,7 @@ import_task_destroy(Slapi_Task *task)
return;
}
- while (is_instance_busy(job->inst)) {
+ while (task->task_state == SLAPI_TASK_RUNNING) {
/* wait for the job to finish before freeing it */
DS_Sleep(PR_SecondsToInterval(1));
}
--
2.13.6

View file

@ -1,332 +0,0 @@
From 4af03a6a2a59684950d887d42c6e9d8b027d71f5 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Mon, 16 Oct 2017 11:21:51 +0200
Subject: [PATCH] Ticket 49064 - RFE allow to enable MemberOf plugin in
dedicated consumer
Bug Description:
memberof triggers some internal updates to add/del 'memberof' values.
on a readonly consumer, those updates selects a REFERRAL_ON_UPDATE backend
and that is not followed by internal updates.
At the end of the day, the update is rejected and if memberof plugin is enabled
replication will stuck on that rejected update
Fix Description:
internal updates from memberof need to bypassing referrals.
So they flag internal updates SLAPI_OP_FLAG_BYPASS_REFERRALS, so that mtn_get_be
(mapping tree selection) will not return the referrals.
https://pagure.io/389-ds-base/issue/49064
Reviewed by: Ludwig Krispenz, William Brown (thanks a LOT !)
Platforms tested: F23 (all tickets + basic suite)
Flag Day: no
Doc impact: no
---
dirsrvtests/tests/tickets/ticket49064_test.py | 259 ++++++++++++++++++++++++++
ldap/servers/plugins/memberof/memberof.c | 6 +-
2 files changed, 262 insertions(+), 3 deletions(-)
create mode 100644 dirsrvtests/tests/tickets/ticket49064_test.py
diff --git a/dirsrvtests/tests/tickets/ticket49064_test.py b/dirsrvtests/tests/tickets/ticket49064_test.py
new file mode 100644
index 000000000..b4b6de4b9
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket49064_test.py
@@ -0,0 +1,259 @@
+import logging
+import pytest
+import os
+import time
+import ldap
+import subprocess
+from lib389.utils import ds_is_older
+from lib389.topologies import topology_m1h1c1 as topo
+from lib389._constants import *
+from lib389 import Entry
+
+# Skip on older versions
+pytestmark = pytest.mark.skipif(ds_is_older('1.3.7'), reason="Not implemented")
+
+USER_CN='user_'
+GROUP_CN='group_'
+FIXUP_FILTER = '(objectClass=*)'
+FIXUP_CMD = 'fixup-memberof.pl'
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+def memberof_fixup_task(server):
+ sbin_dir = server.get_sbin_dir()
+ memof_task = os.path.join(sbin_dir, FIXUP_CMD)
+ try:
+ output = subprocess.check_output(
+ [memof_task, '-D', DN_DM, '-w', PASSWORD, '-b', SUFFIX, '-Z', SERVERID_CONSUMER_1, '-f', FIXUP_FILTER])
+ except subprocess.CalledProcessError as err:
+ output = err.output
+ log.info('output: {}'.format(output))
+ expected = "Successfully added task entry"
+ assert expected in output
+
+def config_memberof(server):
+
+ server.plugins.enable(name=PLUGIN_MEMBER_OF)
+ MEMBEROF_PLUGIN_DN = ('cn=' + PLUGIN_MEMBER_OF + ',cn=plugins,cn=config')
+ server.modify_s(MEMBEROF_PLUGIN_DN, [(ldap.MOD_REPLACE,
+ 'memberOfAllBackends',
+ 'on'),
+ (ldap.MOD_REPLACE, 'memberOfAutoAddOC', 'nsMemberOf')])
+ # Configure fractional to prevent total init to send memberof
+ ents = server.agreement.list(suffix=DEFAULT_SUFFIX)
+ for ent in ents:
+ log.info('update %s to add nsDS5ReplicatedAttributeListTotal' % ent.dn)
+ server.modify_s(ent.dn,
+ [(ldap.MOD_REPLACE,
+ 'nsDS5ReplicatedAttributeListTotal',
+ '(objectclass=*) $ EXCLUDE '),
+ (ldap.MOD_REPLACE,
+ 'nsDS5ReplicatedAttributeList',
+ '(objectclass=*) $ EXCLUDE memberOf')])
+
+
+def send_updates_now(server):
+
+ ents = server.agreement.list(suffix=DEFAULT_SUFFIX)
+ for ent in ents:
+ server.agreement.pause(ent.dn)
+ server.agreement.resume(ent.dn)
+
+def add_user(server, no, desc='dummy', sleep=True):
+ cn = '%s%d' % (USER_CN, no)
+ dn = 'cn=%s,ou=people,%s' % (cn, SUFFIX)
+ log.fatal('Adding user (%s): ' % dn)
+ server.add_s(Entry((dn, {'objectclass': ['top', 'person', 'inetuser'],
+ 'sn': ['_%s' % cn],
+ 'description': [desc]})))
+ if sleep:
+ time.sleep(2)
+
+def add_group(server, nr, sleep=True):
+ cn = '%s%d' % (GROUP_CN, nr)
+ dn = 'cn=%s,ou=groups,%s' % (cn, SUFFIX)
+ server.add_s(Entry((dn, {'objectclass': ['top', 'groupofnames'],
+ 'description': 'group %d' % nr})))
+ if sleep:
+ time.sleep(2)
+
+def update_member(server, member_dn, group_dn, op, sleep=True):
+ mod = [(op, 'member', member_dn)]
+ server.modify_s(group_dn, mod)
+ if sleep:
+ time.sleep(2)
+
+def _find_memberof(server, member_dn, group_dn, find_result=True):
+ ent = server.getEntry(member_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
+ found = False
+ if ent.hasAttr('memberof'):
+
+ for val in ent.getValues('memberof'):
+ server.log.info("!!!!!!! %s: memberof->%s" % (member_dn, val))
+ server.log.info("!!!!!!! %s" % (val))
+ server.log.info("!!!!!!! %s" % (group_dn))
+ if val.lower() == group_dn.lower():
+ found = True
+ break
+
+ if find_result:
+ assert (found)
+ else:
+ assert (not found)
+
+
+def test_ticket49064(topo):
+ """Specify a test case purpose or name here
+
+ :id: 60c11636-55a1-4704-9e09-2c6bcc828de4
+ :setup: 1 Master - 1 Hub - 1 Consumer
+ :steps:
+ 1. Configure replication to EXCLUDE memberof
+ 2. Enable memberof plugin
+ 3. Create users/groups
+ 4. make user_1 member of group_1
+ 5. Checks that user_1 is memberof group_1 on M,H,C
+ 6. make group_1 member of group_2 (nest group)
+ 7. Checks that user_1 is memberof group_1 and group_2 on M,H,C
+ 8. Check group_1 is memberof group_2 on M,H,C
+ 9. remove group_1 from group_2
+ 10. Check group_1 and user_1 are NOT memberof group_2 on M,H,C
+ 11. remove user_1 from group_1
+ 12. Check user_1 is NOT memberof group_1 and group_2 on M,H,C
+ 13. Disable memberof on C1
+ 14. make user_1 member of group_1
+ 15. Checks that user is memberof group_1 on M,H but not on C
+ 16. Enable memberof on C1
+ 17. Checks that user is memberof group_1 on M,H but not on C
+ 18. Run memberof fixup task
+ 19. Checks that user is memberof group_1 on M,H,C
+
+
+ :expectedresults:
+ no assert for membership check
+ """
+
+
+ M1 = topo.ms["master1"]
+ H1 = topo.hs["hub1"]
+ C1 = topo.cs["consumer1"]
+
+ # Step 1 & 2
+ M1.config.enable_log('audit')
+ config_memberof(M1)
+ M1.restart()
+
+ H1.config.enable_log('audit')
+ config_memberof(H1)
+ H1.restart()
+
+ C1.config.enable_log('audit')
+ config_memberof(C1)
+ C1.restart()
+
+ # Step 3
+ for i in range(10):
+ add_user(M1, i, desc='add on m1')
+ for i in range(3):
+ add_group(M1, i)
+
+ # Step 4
+ member_dn = 'cn=%s%d,ou=people,%s' % (USER_CN, 1, SUFFIX)
+ group_dn = 'cn=%s%d,ou=groups,%s' % (GROUP_CN, 1, SUFFIX)
+ update_member(M1, member_dn, group_dn, ldap.MOD_ADD, sleep=True)
+
+ # Step 5
+ for i in [M1, H1, C1]:
+ _find_memberof(i, member_dn, group_dn, find_result=True)
+
+
+ # Step 6
+ user_dn = 'cn=%s%d,ou=people,%s' % (USER_CN, 1, SUFFIX)
+ grp1_dn = 'cn=%s%d,ou=groups,%s' % (GROUP_CN, 1, SUFFIX)
+ grp2_dn = 'cn=%s%d,ou=groups,%s' % (GROUP_CN, 2, SUFFIX)
+ update_member(M1, grp1_dn, grp2_dn, ldap.MOD_ADD, sleep=True)
+
+ # Step 7
+ for i in [grp1_dn, grp2_dn]:
+ for inst in [M1, H1, C1]:
+ _find_memberof(inst, user_dn, i, find_result=True)
+
+ # Step 8
+ for i in [M1, H1, C1]:
+ _find_memberof(i, grp1_dn, grp2_dn, find_result=True)
+
+ # Step 9
+ user_dn = 'cn=%s%d,ou=people,%s' % (USER_CN, 1, SUFFIX)
+ grp1_dn = 'cn=%s%d,ou=groups,%s' % (GROUP_CN, 1, SUFFIX)
+ grp2_dn = 'cn=%s%d,ou=groups,%s' % (GROUP_CN, 2, SUFFIX)
+ update_member(M1, grp1_dn, grp2_dn, ldap.MOD_DELETE, sleep=True)
+
+ # Step 10
+ for inst in [M1, H1, C1]:
+ for i in [grp1_dn, user_dn]:
+ _find_memberof(inst, i, grp2_dn, find_result=False)
+
+ # Step 11
+ member_dn = 'cn=%s%d,ou=people,%s' % (USER_CN, 1, SUFFIX)
+ group_dn = 'cn=%s%d,ou=groups,%s' % (GROUP_CN, 1, SUFFIX)
+ update_member(M1, member_dn, group_dn, ldap.MOD_DELETE, sleep=True)
+
+ # Step 12
+ for inst in [M1, H1, C1]:
+ for grp in [grp1_dn, grp2_dn]:
+ _find_memberof(inst, member_dn, grp, find_result=False)
+
+ # Step 13
+ C1.plugins.disable(name=PLUGIN_MEMBER_OF)
+ C1.restart()
+
+ # Step 14
+ member_dn = 'cn=%s%d,ou=people,%s' % (USER_CN, 1, SUFFIX)
+ group_dn = 'cn=%s%d,ou=groups,%s' % (GROUP_CN, 1, SUFFIX)
+ update_member(M1, member_dn, group_dn, ldap.MOD_ADD, sleep=True)
+
+ # Step 15
+ for i in [M1, H1]:
+ _find_memberof(i, member_dn, group_dn, find_result=True)
+ _find_memberof(C1, member_dn, group_dn, find_result=False)
+
+ # Step 16
+ C1.plugins.enable(name=PLUGIN_MEMBER_OF)
+ C1.restart()
+
+ # Step 17
+ for i in [M1, H1]:
+ _find_memberof(i, member_dn, group_dn, find_result=True)
+ _find_memberof(C1, member_dn, group_dn, find_result=False)
+
+ # Step 18
+ memberof_fixup_task(C1)
+ time.sleep(5)
+
+ # Step 19
+ for i in [M1, H1, C1]:
+ _find_memberof(i, member_dn, group_dn, find_result=True)
+
+ # If you need any test suite initialization,
+ # please, write additional fixture for that (including finalizer).
+ # Topology for suites are predefined in lib389/topologies.py.
+
+ # If you need host, port or any other data about instance,
+ # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
+
+ if DEBUGGING:
+ # Add debugging steps(if any)...
+ pass
+
+
+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/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
index bae242c81..44b52edbb 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -609,7 +609,7 @@ memberof_del_dn_type_callback(Slapi_Entry *e, void *callback_data)
slapi_modify_internal_set_pb_ext(
mod_pb, slapi_entry_get_sdn(e),
mods, 0, 0,
- memberof_get_plugin_id(), 0);
+ memberof_get_plugin_id(), SLAPI_OP_FLAG_BYPASS_REFERRALS);
slapi_modify_internal_pb(mod_pb);
@@ -3224,7 +3224,7 @@ memberof_add_memberof_attr(LDAPMod **mods, const char *dn, char *add_oc)
mod_pb = slapi_pblock_new();
slapi_modify_internal_set_pb(
mod_pb, dn, mods, 0, 0,
- memberof_get_plugin_id(), 0);
+ memberof_get_plugin_id(), SLAPI_OP_FLAG_BYPASS_REFERRALS);
slapi_modify_internal_pb(mod_pb);
slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
@@ -3279,7 +3279,7 @@ memberof_add_objectclass(char *auto_add_oc, const char *dn)
slapi_modify_internal_set_pb(
mod_pb, dn, mods, 0, 0,
- memberof_get_plugin_id(), 0);
+ memberof_get_plugin_id(), SLAPI_OP_FLAG_BYPASS_REFERRALS);
slapi_modify_internal_pb(mod_pb);
slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
--
2.13.6

View file

@ -1,48 +0,0 @@
From 82e092e9debce16f048b4fe0f38265bc8d80f63d Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Thu, 28 Sep 2017 09:11:00 +1000
Subject: [PATCH] Ticket 49378 server init fails
Bug Description: We used our own target for DS installation, but
we should just use multi-user like anything else.
Fix Description: Change service template to multi-user. This should
be a seamless upgrade to most consumers.
https://pagure.io/389-ds-base/issue/49378
Author: wibrown
Review by: mreynolds (Thanks!)
(cherry picked from commit e9ad5f5aca64f65fa2c9b2dc5132b0dacf131c99)
---
wrappers/systemd.template.asan.service.in | 2 +-
wrappers/systemd.template.service.in | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/wrappers/systemd.template.asan.service.in b/wrappers/systemd.template.asan.service.in
index 1fe321ccb..52681f632 100644
--- a/wrappers/systemd.template.asan.service.in
+++ b/wrappers/systemd.template.asan.service.in
@@ -36,5 +36,5 @@ ExecStart=@sbindir@/ns-slapd -D @instconfigdir@/slapd-%i -i @localstatedir@/run/
.include @initconfigdir@/@package_name@.systemd
[Install]
-WantedBy=dirsrv.target
+WantedBy=multi-user.target
diff --git a/wrappers/systemd.template.service.in b/wrappers/systemd.template.service.in
index 30b9e4b78..0d88900b6 100644
--- a/wrappers/systemd.template.service.in
+++ b/wrappers/systemd.template.service.in
@@ -40,5 +40,5 @@ ExecStart=@sbindir@/ns-slapd -D @instconfigdir@/slapd-%i -i @localstatedir@/run/
.include @initconfigdir@/@package_name@.systemd
[Install]
-WantedBy=dirsrv.target
+WantedBy=multi-user.target
--
2.13.6

View file

@ -1,50 +0,0 @@
From 9369164f45ba19519158286590aaefae1c64ef05 Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Thu, 5 Oct 2017 09:54:48 +1000
Subject: [PATCH] Ticket 49392 - memavailable not available
Bug Description: On certain linux platforms memAvailable is
not actually available! This means that the value was 0, so
cgroup max was read instead, setting the system ram to:
9223372036854771712
That's a bit excessive, and can cause memory allocations to fail.
Fix Description: If memavail can't be found, fall back to
memtotal instead.
https://pagure.io/389-ds-base/issue/49392
Author: wibrown
Review by: mreynolds (Thanks!)
---
ldap/servers/slapd/slapi_pal.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/ldap/servers/slapd/slapi_pal.c b/ldap/servers/slapd/slapi_pal.c
index 38c178cfa..600d03d4d 100644
--- a/ldap/servers/slapd/slapi_pal.c
+++ b/ldap/servers/slapd/slapi_pal.c
@@ -155,7 +155,16 @@ spal_meminfo_get()
/* Both memtotal and memavail are in kb */
memtotal = memtotal * 1024;
- memavail = memavail * 1024;
+
+ /*
+ * Oracle Enterprise Linux doesn't provide a valid memavail value, so fall
+ * back to 80% of memtotal.
+ */
+ if (memavail == 0) {
+ memavail = memtotal * 0.8;
+ } else {
+ memavail = memavail * 1024;
+ }
/* If it's possible, get our cgroup info */
uint64_t cg_mem_soft = 0;
--
2.13.6

View file

@ -1,91 +0,0 @@
From 73c72aba0ab31f9d16cdfd8879e9da5f3fb985e0 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 17 Oct 2017 12:39:18 -0400
Subject: [PATCH] Ticket 48006 - Missing warning for invalid replica backoff
configuration
Description: Add warning if you try to set a min backoff time that is
greater than the configured maximum, or the max time that
is less than the minimum.
Also fixed compiler warning in ldbm_config.c
https://pagure.io/389-ds-base/issue/48006
Reviewed by: firstyear(Thanks!)
(cherry picked from commit e123acb6987c75f6d7282b32c4f279b976eb6f5e)
---
.../plugins/replication/repl5_replica_config.c | 24 ++++++++++++++++++++--
ldap/servers/slapd/back-ldbm/ldbm_config.c | 2 +-
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index f28044c19..22d766143 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -465,7 +465,8 @@ replica_config_modify(Slapi_PBlock *pb,
}
} else if (strcasecmp(config_attr, type_replicaBackoffMin) == 0) {
if (apply_mods) {
- PRUint64 val = atoll(config_attr_value);
+ uint64_t val = atoll(config_attr_value);
+ uint64_t max;
if (val <= 0) {
*returncode = LDAP_UNWILLING_TO_PERFORM;
@@ -475,11 +476,21 @@ replica_config_modify(Slapi_PBlock *pb,
slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_modify - %s\n", errortext);
break;
}
+ max = replica_get_backoff_max(r);
+ if (val > max){
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf(errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "Attribute %s value (%s) is invalid, must be a number less than the max backoff time (%d).\n",
+ config_attr, config_attr_value, (int)max);
+ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_modify - %s\n", errortext);
+ break;
+ }
replica_set_backoff_min(r, val);
}
} else if (strcasecmp(config_attr, type_replicaBackoffMax) == 0) {
if (apply_mods) {
- PRUint64 val = atoll(config_attr_value);
+ uint64_t val = atoll(config_attr_value);
+ uint64_t min;
if (val <= 0) {
*returncode = LDAP_UNWILLING_TO_PERFORM;
@@ -490,6 +501,15 @@ replica_config_modify(Slapi_PBlock *pb,
errortext);
break;
}
+ min = replica_get_backoff_min(r);
+ if (val < min) {
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf(errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "Attribute %s value (%s) is invalid, must be a number more than the min backoff time (%d).\n",
+ config_attr, config_attr_value, (int)min);
+ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_modify - %s\n", errortext);
+ break;
+ }
replica_set_backoff_max(r, val);
}
} else if (strcasecmp(config_attr, type_replicaPrecisePurge) == 0) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c
index 2ef4652ce..feb993366 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c
@@ -388,7 +388,7 @@ ldbm_config_directory_set(void *arg, void *value, char *errorbuf, int phase, int
goto done;
}
slapi_pblock_destroy(search_pb);
- if (NULL == s || '\0' == s || 0 == PL_strcmp(s, "(null)")) {
+ if (NULL == s || '\0' == *s || 0 == PL_strcmp(s, "(null)")) {
slapi_log_err(SLAPI_LOG_ERR,
"ldbm_config_directory_set", "db directory is not set; check %s in the db config: %s\n",
CONFIG_DIRECTORY, CONFIG_LDBM_DN);
--
2.13.6

View file

@ -1,43 +0,0 @@
From 4569da8f2c55d54a34f31312ee5756c70a7f463c Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 19 Oct 2017 17:33:10 -0400
Subject: [PATCH] Ticket 49408 - Server allows to set any nsds5replicaid in the
existing replica entry
Description: There was no value validation for replica ID. Now there is.
https://pagure.io/389-ds-base/issue/49408
Reviewed by: tbordaz(Thanks!)
(cherry picked from commit 296f0abb78b7ec82580d039d9c505506f6ce07be)
---
ldap/servers/plugins/replication/repl5_replica_config.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 22d766143..7477a292c 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -411,6 +411,18 @@ replica_config_modify(Slapi_PBlock *pb,
slapi_ch_free_string(&new_repl_type);
new_repl_type = slapi_ch_strdup(config_attr_value);
} else if (strcasecmp(config_attr, attr_replicaId) == 0) {
+ char *endp = NULL;
+ int64_t rid = 0;
+ errno = 0;
+ rid = strtoll(config_attr_value, &endp, 10);
+ if (*endp != '\0' || rid > 65535 || rid < 1 || errno == ERANGE) {
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ PR_snprintf(errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "Attribute %s value (%s) is invalid, must be a number between 1 and 65535.\n",
+ config_attr, config_attr_value);
+ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_config_modify - %s\n", errortext);
+ break;
+ }
slapi_ch_free_string(&new_repl_id);
new_repl_id = slapi_ch_strdup(config_attr_value);
} else if (strcasecmp(config_attr, attr_flags) == 0) {
--
2.13.6

View file

@ -1,45 +0,0 @@
From 70d236dedadc030fd2b450d7607b395b50523538 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 19 Oct 2017 17:02:20 -0400
Subject: [PATCH] Ticket 49407 - status-dirsrv shows ellipsed lines
Bug Description: To show the full output you have to pass "-l" to systemctl,
but there is no way to use this option with the current design.
Fix Description: Just show the full lines by default, as adding options can break
the script's current usage.
https://pagure.io/389-ds-base/issue/49407
Reviewed by: tbordaz(Thanks!)
(cherry picked from commit 45d2fd4b50227687ad042a0e17d8dcd9e4cd3023)
---
ldap/admin/src/scripts/status-dirsrv.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ldap/admin/src/scripts/status-dirsrv.in b/ldap/admin/src/scripts/status-dirsrv.in
index 90428990b..8e492c115 100755
--- a/ldap/admin/src/scripts/status-dirsrv.in
+++ b/ldap/admin/src/scripts/status-dirsrv.in
@@ -37,7 +37,7 @@ status_instance() {
# Use systemctl if available.
#
if [ -d "@systemdsystemunitdir@" ] && [ $(id -u) -eq 0 ];then
- @bindir@/systemctl status @package_name@@$SERV_ID.service
+ @bindir@/systemctl status @package_name@@$SERV_ID.service -l
rv=$?
if [ $rv -ne 0 ]; then
return 1
@@ -65,7 +65,7 @@ found=0
if [ $# -eq 0 ]; then
# We're reporting the status of all instances.
ret=0
- @bindir@/systemctl status @package_name@.target
+ @bindir@/systemctl status @package_name@.target -l
initfiles=`get_initconfig_files $initconfig_dir` || { echo No instances found in $initconfig_dir ; exit 1 ; }
for i in $initfiles; do
inst=`normalize_server_id $i`
--
2.13.6

View file

@ -1,37 +0,0 @@
From b7cca69de5f6cda32bc38504a7aa7e5bc786bbe6 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 19 Oct 2017 14:44:38 -0400
Subject: [PATCH] Ticket 48681 - Use of uninitialized value in string ne at
/usr/bin/logconv.pl line 2565, <$LOGFH> line 4
Bug description: The original fix for 48681 added a regression in regards to perl
warning everytime you ran the script. That was due to a new hash
for sasl binds that was not initialized.
Fix Description: Check is the saslbind hash "exists" before checking its value.
https://pagure.io/389-ds-base/issue/48681
Reviewed by: mreynolds (one line fix)
(cherry picked from commit e46749b77d95ad8fedf07d38890573b2862badf7)
---
ldap/admin/src/logconv.pl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl
index 4932db42e..473c71f21 100755
--- a/ldap/admin/src/logconv.pl
+++ b/ldap/admin/src/logconv.pl
@@ -2562,7 +2562,7 @@ sub parseLineNormal
if ($_ =~ /conn= *([0-9A-Z]+) +op= *([0-9\-]+)/i){
$conn = $1;
$op = $2;
- if ($hashes->{saslconnop}->{$conn-$op} ne ""){
+ if (exists $hashes->{saslconnop}->{$conn-$op} && $hashes->{saslconnop}->{$conn-$op} ne ""){
# This was a SASL BIND - record the dn
if ($binddn ne ""){
if($binddn eq $rootDN){ $rootDNBindCount++; }
--
2.13.6

View file

@ -1,132 +0,0 @@
From 4ecec8dac601b77a25ebc390f138aad1ee48d805 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 19 Oct 2017 12:20:48 -0400
Subject: [PATCH] Ticket 49374 - server fails to start because maxdisksize is
recognized incorrectly
Bug Description: When directly editting dse.ldif, the server had a check
when setting the log maxdiskspace vs maxlogsize. If the
maxlogsize is processed first and it is higher than the
default maxdisksspace then it throw an error and the server
fails to start.
If you attempt this same operation using ldapmodify it
works as "live" updates check all the mods first, so the
order of the attributes does not matter.
Fix description: Remove the size checks from the attribute set function.
It is technically redundant since it is correctly checked
by the configdse code.
https://pagure.io/389-ds-base/issue/49374
Reviewed by: tbordaz(Thanks!)
(cherry picked from commit 63a0a59c9b09af08151831209ee6711b4363aee2)
---
ldap/servers/slapd/log.c | 60 ++++++++++++------------------------------------
1 file changed, 15 insertions(+), 45 deletions(-)
diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c
index e16d89cc5..998efaef3 100644
--- a/ldap/servers/slapd/log.c
+++ b/ldap/servers/slapd/log.c
@@ -960,7 +960,6 @@ int
log_set_logsize(const char *attrname, char *logsize_str, int logtype, char *returntext, int apply)
{
int rv = LDAP_SUCCESS;
- PRInt64 mdiskspace = 0; /* in bytes */
PRInt64 max_logsize; /* in bytes */
int logsize; /* in megabytes */
slapdFrontendConfig_t *fe_cfg = getFrontendConfig();
@@ -979,72 +978,43 @@ log_set_logsize(const char *attrname, char *logsize_str, int logtype, char *retu
switch (logtype) {
case SLAPD_ACCESS_LOG:
- LOG_ACCESS_LOCK_WRITE();
- mdiskspace = loginfo.log_access_maxdiskspace;
- break;
- case SLAPD_ERROR_LOG:
- LOG_ERROR_LOCK_WRITE();
- mdiskspace = loginfo.log_error_maxdiskspace;
- break;
- case SLAPD_AUDIT_LOG:
- LOG_AUDIT_LOCK_WRITE();
- mdiskspace = loginfo.log_audit_maxdiskspace;
- break;
- case SLAPD_AUDITFAIL_LOG:
- LOG_AUDITFAIL_LOCK_WRITE();
- mdiskspace = loginfo.log_auditfail_maxdiskspace;
- break;
- default:
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "%s: invalid logtype %d", attrname, logtype);
- rv = LDAP_OPERATIONS_ERROR;
- }
-
- if ((max_logsize > mdiskspace) && (mdiskspace != -1)) {
- rv = 2;
- }
-
- switch (logtype) {
- case SLAPD_ACCESS_LOG:
- if (!rv && apply) {
+ if (apply) {
+ LOG_ACCESS_LOCK_WRITE();
loginfo.log_access_maxlogsize = max_logsize;
fe_cfg->accesslog_maxlogsize = logsize;
+ LOG_ACCESS_UNLOCK_WRITE();
}
- LOG_ACCESS_UNLOCK_WRITE();
break;
case SLAPD_ERROR_LOG:
- if (!rv && apply) {
+ if (apply) {
+ LOG_ERROR_LOCK_WRITE();
loginfo.log_error_maxlogsize = max_logsize;
fe_cfg->errorlog_maxlogsize = logsize;
+ LOG_ERROR_UNLOCK_WRITE();
}
- LOG_ERROR_UNLOCK_WRITE();
break;
case SLAPD_AUDIT_LOG:
- if (!rv && apply) {
+ if (apply) {
+ LOG_AUDIT_LOCK_WRITE();
loginfo.log_audit_maxlogsize = max_logsize;
fe_cfg->auditlog_maxlogsize = logsize;
+ LOG_AUDIT_UNLOCK_WRITE();
}
- LOG_AUDIT_UNLOCK_WRITE();
break;
case SLAPD_AUDITFAIL_LOG:
- if (!rv && apply) {
+ if (apply) {
+ LOG_AUDITFAIL_LOCK_WRITE();
loginfo.log_auditfail_maxlogsize = max_logsize;
fe_cfg->auditfaillog_maxlogsize = logsize;
+ LOG_AUDITFAIL_UNLOCK_WRITE();
}
- LOG_AUDITFAIL_UNLOCK_WRITE();
break;
default:
- rv = 1;
- }
- /* logsize is in MB */
- if (rv == 2) {
- slapi_log_err(SLAPI_LOG_ERR, "log_set_logsize",
- "Invalid value for Maximum log size:"
- "Maxlogsize:%d (MB) exceeds Maxdisksize:%ld (MB)\n",
- logsize, (long int)(mdiskspace / LOG_MB_IN_BYTES));
-
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "%s: invalid logtype %d", attrname, logtype);
rv = LDAP_OPERATIONS_ERROR;
}
+
return rv;
}
--
2.13.6

View file

@ -1,66 +0,0 @@
From ef4ac2d45c9ea99fbb1ae6cee97745161f193bf9 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 25 Oct 2017 10:53:28 -0400
Subject: [PATCH] Ticket 48681 - Use of uninitialized value in string ne at
/usr/bin/logconv.pl
Bug Description: ldapi connections were not properly porcessed by the
connection parsing code which lead to uninitialized errors.
Fix Description: Modify the connection IP address regex's to include "local"
https://pagure.io/389-ds-base/issue/48681
Reviewd by: mreynolds (one line commit rule)
(cherry picked from commit 6098e7b927b64ba300567e71ea611140c47676a1)
---
ldap/admin/src/logconv.pl | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl
index 473c71f21..e36386e11 100755
--- a/ldap/admin/src/logconv.pl
+++ b/ldap/admin/src/logconv.pl
@@ -809,9 +809,9 @@ if ($totalTimeInNsecs == 0){
print "Restarts: $serverRestartCount\n";
if(%cipher){
- print " Secure Protocol Versions:\n";
+ print "Secure Protocol Versions:\n";
foreach my $key (sort { $b cmp $a } keys %cipher) {
- print " - $key - $cipher{$key}\n";
+ print " - $key ($cipher{$key} connections)\n";
}
print "\n";
}
@@ -1754,7 +1754,7 @@ parseLineBind {
($end) = $endTime =~ /\D*(\S*)/;
}
}
- if ($_ =~ /connection from *([0-9A-Fa-f\.\:]+)/i ) {
+ if ($_ =~ /connection from *([0-9A-Za-z\.\:]+)/i ) {
my $skip = "yes";
for (my $excl =0; $excl < $#excludeIP; $excl++){
if ($excludeIP[$excl] eq $1){
@@ -2085,7 +2085,7 @@ sub parseLineNormal
}
if (m/ connection from/){
my $ip;
- if ($_ =~ /connection from *([0-9A-Fa-f\.\:]+)/i ){
+ if ($_ =~ /connection from *([0-9A-Za-z\.\:]+)/i ){
$ip = $1;
for (my $xxx =0; $xxx < $#excludeIP; $xxx++){
if ($excludeIP[$xxx] eq $ip){$exc = "yes";}
@@ -2253,7 +2253,7 @@ sub parseLineNormal
}
if ($usage =~ /g/ || $usage =~ /c/ || $usage =~ /i/ || $usage =~ /f/ || $usage =~ /u/ || $usage =~ /U/ || $verb eq "yes"){
$exc = "no";
- if ($_ =~ /connection from *([0-9A-fa-f\.\:]+)/i ) {
+ if ($_ =~ /connection from *([0-9A-Za-z\.\:]+)/i ) {
for (my $xxx = 0; $xxx < $#excludeIP; $xxx++){
if ($1 eq $excludeIP[$xxx]){
$exc = "yes";
--
2.13.6

View file

@ -1,250 +0,0 @@
From a59b2f4129565dbfa1b63899dd550e9c22b02923 Mon Sep 17 00:00:00 2001
From: Mohammad Nweider <nweiderm@amazon.com>
Date: Wed, 18 Oct 2017 13:02:15 +0000
Subject: [PATCH] Ticket 49401 - improve valueset sorted performance on delete
Bug Description: valueset sorted maintains a list of syntax sorted
references to the attributes of the entry. During addition these are
modified and added properly, so they stay sorted.
However, in the past to maintain the sorted property, during a delete
we would need to remove the vs->sorted array, and recreate it via qsort,
While this was an improvement from past (where we would removed
vs->sorted during an attr delete), it still has performance implications
on very very large datasets, IE 50,000 member groups with
addition/deletion, large entry caches and replication.
Fix Description: Implement a new algorithm that is able to maintain
existing sort data in a near linear time.
https://pagure.io/389-ds-base/issue/49401
Author: nweiderm, wibrown
Review by: wibrown, lkrispen, tbordaz (Thanks nweiderm!)
(cherry picked from commit a43a8efc7907116146b505ac40f18fac71f474b0)
---
ldap/servers/slapd/valueset.c | 171 +++++++++++++++++++++++++-----------------
1 file changed, 103 insertions(+), 68 deletions(-)
diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c
index d2c67d2fb..1c1bc150a 100644
--- a/ldap/servers/slapd/valueset.c
+++ b/ldap/servers/slapd/valueset.c
@@ -677,100 +677,136 @@ valueset_array_purge(const Slapi_Attr *a, Slapi_ValueSet *vs, const CSN *csn)
size_t i = 0;
size_t j = 0;
int nextValue = 0;
+ int nv = 0;
int numValues = 0;
+ Slapi_Value **va2 = NULL;
+ int *sorted2 = NULL;
/* Loop over all the values freeing the old ones. */
- for (i = 0; i < vs->num; i++) {
+ for(i = 0; i < vs->num; i++)
+ {
/* If we have the sorted array, find the va array ref by it. */
if (vs->sorted) {
j = vs->sorted[i];
} else {
j = i;
}
- csnset_purge(&(vs->va[j]->v_csnset), csn);
- if (vs->va[j]->v_csnset == NULL) {
- slapi_value_free(&vs->va[j]);
- vs->va[j] = NULL;
- } else if (vs->va[j] != NULL) {
- /* This value survived, we should count it. */
- numValues++;
+ if (vs->va[j]) {
+ csnset_purge(&(vs->va[j]->v_csnset),csn);
+ if (vs->va[j]->v_csnset == NULL) {
+ slapi_value_free(&vs->va[j]);
+ /* Set the removed value to NULL so we know later to skip it */
+ vs->va[j] = NULL;
+ if (vs->sorted) {
+ /* Mark the value in sorted for removal */
+ vs->sorted[i] = -1;
+ }
+ } else {
+ /* This value survived, we should count it. */
+ numValues++;
+ }
}
}
- /* Now compact the value/sorted list. */
+ /* Compact vs->va and vs->sorted only when there're
+ * remaining values ie: numValues is greater than 0 */
/*
- * Because we want to preserve the sorted array, this is complicated.
+ * Algorithm explination: We start with a pair of arrays - the attrs, and the sorted array that provides
+ * a lookup into it:
+ *
+ * va: [d e a c b] sorted: [2 4 3 0 1]
+ *
+ * When we remove the element b, we NULL it, and we have to mark the place where it "was" as a -1 to
+ * flag it's removal.
+ *
+ * va: [d e a c NULL] sorted: [2 -1 3 0 1]
+ *
+ * Now a second va is created with the reduced allocation,
+ *
+ * va2: [ X X X X ] ....
+ *
+ * Now we loop over sorted, skipping -1 that we find. In a new counter we create new sorted
+ * references, and move the values compacting them in the process.
+ * va: [d e a c NULL]
+ * va2: [a x x x]
+ * sorted: [_0 -1 3 0 1]
+ *
+ * Looping a few more times would yield:
*
- * We have an array of values:
- * [ b, a, c, NULL, e, NULL, NULL, d]
- * And an array of indicies that are sorted.
- * [ 1, 0, 2, 7, 4, 3, 5, 6 ]
- * Were we to iterate over the sorted array, we get refs to the values in
- * some order.
- * The issue is now we must *remove* from both the values *and* the sorted.
+ * va2: [a c x x]
+ * sorted: [_0 _1 3 0 1]
*
- * Previously, we just discarded this, because too hard. Now we try to keep
- * it. The issue is that this is surprisingly hard to actually keep in
- * sync.
+ * va2: [a c d x]
+ * sorted: [_0 _1 _2 0 1]
*
- * We can't just blindly move the values down: That breaks the sorted array
- * and we would need to iterate over the sorted array multiple times to
- * achieve this.
+ * va2: [a c d e]
+ * sorted: [_0 _1 _2 _3 1]
+ *
+ * Not only does this sort va, but with sorted, we have a faster lookup, and it will benefit cache
+ * lookup.
*
- * It's actually going to be easier to just ditch the sorted, compact vs
- * and then qsort the array.
*/
+ if (numValues > 0) {
+ if(vs->sorted) {
+ /* Let's allocate va2 and sorted2 */
+ va2 = (Slapi_Value **) slapi_ch_malloc( (numValues + 1) * sizeof(Slapi_Value *));
+ sorted2 = (int *) slapi_ch_malloc( (numValues + 1)* sizeof(int));
+ }
- j = 0;
- while (nextValue < numValues && j < vs->num) {
- /* nextValue is what we are looking at now
- * j tracks along the array getting next elements.
- *
- * [ b, a, c, NULL, e, NULL, NULL, d]
- * ^nv ^j
- * [ b, a, c, e, NULL, NULL, NULL, d]
- * ^nv ^j
- * [ b, a, c, e, NULL, NULL, NULL, d]
- * ^nv ^j
- * [ b, a, c, e, NULL, NULL, NULL, d]
- * ^nv ^j
- * [ b, a, c, e, NULL, NULL, NULL, d]
- * ^nv ^j
- * [ b, a, c, e, d, NULL, NULL, NULL]
- * ^nv ^j
- */
- if (vs->va[nextValue] == NULL) {
- /* Advance j till we find something */
- while (vs->va[j] == NULL) {
- j++;
+ /* I is the index for the *new* va2 array */
+ for(i=0; i<vs->num; i++) {
+ if (vs->sorted) {
+ /* Skip any removed values from the index */
+ while((nv < vs->num) && (-1 == vs->sorted[nv])) {
+ nv++;
+ }
+ /* We have a remaining value, add it to the va */
+ if(nv < vs->num) {
+ va2[i] = vs->va[vs->sorted[nv]];
+ sorted2[i] = i;
+ nv++;
+ }
+ } else {
+ while((nextValue < vs->num) && (NULL == vs->va[nextValue])) {
+ nextValue++;
+ }
+
+ if(nextValue < vs->num) {
+ vs->va[i] = vs->va[nextValue];
+ nextValue++;
+ } else {
+ break;
+ }
}
- /* We have something! */
- vs->va[nextValue] = vs->va[j];
- vs->va[j] = NULL;
}
- nextValue++;
- }
- /* Fix up the number of values */
- vs->num = numValues;
- /* Should we re-alloc values to be smaller? */
- /* Other parts of DS are lazy. Lets clean our list */
- for (j = vs->num; j < vs->max; j++) {
- vs->va[j] = NULL;
- }
- /* All the values were deleted, we can discard the whole array. */
- if (vs->num == 0) {
if (vs->sorted) {
+ /* Finally replace the valuearray and adjust num, max */
+ slapi_ch_free((void **)&vs->va);
slapi_ch_free((void **)&vs->sorted);
+ vs->va = va2;
+ vs->sorted = sorted2;
+ vs->num = numValues;
+ vs->max = vs->num + 1;
+ } else {
+ vs->num = numValues;
}
- slapi_ch_free((void **)&vs->va);
- vs->va = NULL;
- vs->max = 0;
- } else if (vs->sorted != NULL) {
- /* We still have values! rebuild the sorted array */
- valueset_array_to_sorted(a, vs);
+
+ for (j = vs->num; j < vs->max; j++) {
+ vs->va[j] = NULL;
+ if (vs->sorted) {
+ vs->sorted[j] = -1;
+ }
+ }
+ } else {
+ slapi_valueset_done(vs);
}
+ /* We still have values but not sorted array! rebuild it */
+ if(vs->num > VALUESET_ARRAY_SORT_THRESHOLD && vs->sorted == NULL) {
+ vs->sorted = (int *) slapi_ch_malloc( vs->max* sizeof(int));
+ valueset_array_to_sorted(a, vs);
+ }
#ifdef DEBUG
PR_ASSERT(vs->num == 0 || (vs->num > 0 && vs->va[0] != NULL));
size_t index = 0;
@@ -781,7 +817,6 @@ valueset_array_purge(const Slapi_Attr *a, Slapi_ValueSet *vs, const CSN *csn)
PR_ASSERT(vs->va[index] == NULL);
}
#endif
-
/* return the number of remaining values */
return numValues;
}
--
2.13.6

View file

@ -1,54 +0,0 @@
From 308691e03cc6312bde3409b346df3156d34db0fe Mon Sep 17 00:00:00 2001
From: Mohammad Nweider <nweiderm@amazon.com>
Date: Wed, 25 Oct 2017 16:26:54 +0000
Subject: [PATCH] Ticket 49401 - Fix compiler incompatible-pointer-types
warnings
Bug Description: vs->sorted was integer pointer in older versions,
but now it's size_t pointer, this is causing compiler warnings
during the build
Fix Description: use size_t pointers instead of integer pointers for vs->sorted and sorted2
Review By: mreynolds
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
(cherry picked from commit 52ba2aba49935989152010aee0d40b01d7a78432)
---
ldap/servers/slapd/valueset.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c
index 1c1bc150a..dc0360738 100644
--- a/ldap/servers/slapd/valueset.c
+++ b/ldap/servers/slapd/valueset.c
@@ -680,7 +680,7 @@ valueset_array_purge(const Slapi_Attr *a, Slapi_ValueSet *vs, const CSN *csn)
int nv = 0;
int numValues = 0;
Slapi_Value **va2 = NULL;
- int *sorted2 = NULL;
+ size_t *sorted2 = NULL;
/* Loop over all the values freeing the old ones. */
for(i = 0; i < vs->num; i++)
@@ -750,7 +750,7 @@ valueset_array_purge(const Slapi_Attr *a, Slapi_ValueSet *vs, const CSN *csn)
if(vs->sorted) {
/* Let's allocate va2 and sorted2 */
va2 = (Slapi_Value **) slapi_ch_malloc( (numValues + 1) * sizeof(Slapi_Value *));
- sorted2 = (int *) slapi_ch_malloc( (numValues + 1)* sizeof(int));
+ sorted2 = (size_t *) slapi_ch_malloc( (numValues + 1)* sizeof(size_t));
}
/* I is the index for the *new* va2 array */
@@ -804,7 +804,7 @@ valueset_array_purge(const Slapi_Attr *a, Slapi_ValueSet *vs, const CSN *csn)
/* We still have values but not sorted array! rebuild it */
if(vs->num > VALUESET_ARRAY_SORT_THRESHOLD && vs->sorted == NULL) {
- vs->sorted = (int *) slapi_ch_malloc( vs->max* sizeof(int));
+ vs->sorted = (size_t *) slapi_ch_malloc( vs->max* sizeof(size_t));
valueset_array_to_sorted(a, vs);
}
#ifdef DEBUG
--
2.13.6

View file

@ -1,39 +0,0 @@
From dba89dd23d2d62686de192e0986eba65270a62c7 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 26 Oct 2017 10:03:39 -0400
Subject: [PATCH] Ticket 48894 - harden valueset_array_to_sorted_quick valueset
access
Description: It's possible during the sorting of a valueset to access an
array element past the allocated size, and also go below the index 0.
https://pagure.io/389-ds-base/issue/48894
Reviewed by: nweiderm (Thanks!)
(cherry picked from commit 2086d052e338ddcbcf6bd3222617991641573a12)
---
ldap/servers/slapd/valueset.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c
index dc0360738..14ebc48e6 100644
--- a/ldap/servers/slapd/valueset.c
+++ b/ldap/servers/slapd/valueset.c
@@ -1019,11 +1019,11 @@ valueset_array_to_sorted_quick(const Slapi_Attr *a, Slapi_ValueSet *vs, size_t l
while (1) {
do {
i++;
- } while (valueset_value_cmp(a, vs->va[vs->sorted[i]], vs->va[pivot]) < 0);
+ } while (i < vs->max && valueset_value_cmp(a, vs->va[vs->sorted[i]], vs->va[pivot]) < 0);
do {
j--;
- } while (valueset_value_cmp(a, vs->va[vs->sorted[j]], vs->va[pivot]) > 0);
+ } while (valueset_value_cmp(a, vs->va[vs->sorted[j]], vs->va[pivot]) > 0 && j > 0);
if (i >= j) {
break;
--
2.13.6

View file

@ -1,176 +0,0 @@
From 5909e20899334816f36cac0e47105e56df52ad3c Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Mon, 30 Oct 2017 12:01:34 +1000
Subject: [PATCH] Ticket 49424 - Resolve csiphash alignment issues
Bug Description: On some platforms, uint64_t is not the same size
as a void * - as well, if the input is not aligned correctly, then
a number of nasty crashes can result
Fix Description: Instead of relying on alignment to be correct,
we should memcpy the data to inputs instead.
https://pagure.io/389-ds-base/issue/49424
Author: wibrown
Review by: lslebodn, cgrzemba, vashirov, mreynolds (Thanks!)
(cherry picked from commit 751446440f5269a246e6e652a64e63aa5933734a)
---
src/libsds/external/csiphash/csiphash.c | 52 +++++++++++++++++++--------------
src/libsds/test/test_sds_csiphash.c | 43 +++++++++++++++++++++------
2 files changed, 64 insertions(+), 31 deletions(-)
diff --git a/src/libsds/external/csiphash/csiphash.c b/src/libsds/external/csiphash/csiphash.c
index 0089c82f7..2351db6cf 100644
--- a/src/libsds/external/csiphash/csiphash.c
+++ b/src/libsds/external/csiphash/csiphash.c
@@ -32,6 +32,9 @@
#include <inttypes.h>
#include <stddef.h> /* for size_t */
+#include <stdlib.h> /* calloc,free */
+#include <string.h> /* memcpy */
+
#include <config.h>
#if defined(HAVE_SYS_ENDIAN_H)
@@ -75,11 +78,24 @@
uint64_t
sds_siphash13(const void *src, size_t src_sz, const char key[16])
{
- const uint64_t *_key = (uint64_t *)key;
+ uint64_t _key[2] = {0};
+ memcpy(_key, key, 16);
uint64_t k0 = _le64toh(_key[0]);
uint64_t k1 = _le64toh(_key[1]);
uint64_t b = (uint64_t)src_sz << 56;
- const uint64_t *in = (uint64_t *)src;
+
+ size_t input_sz = (src_sz / sizeof(uint64_t)) + 1;
+
+ /* Account for non-uint64_t alligned input */
+ /* Could make this stack allocation */
+ uint64_t *in = calloc(1, input_sz * sizeof(uint64_t));
+ /*
+ * Because all crypto code sucks, they modify *in
+ * during operation, so we stash a copy of the ptr here.
+ * alternately, we could use stack allocated array, but gcc
+ * will complain about the vla being unbounded.
+ */
+ uint64_t *in_ptr = memcpy(in, src, src_sz);
uint64_t v0 = k0 ^ 0x736f6d6570736575ULL;
uint64_t v1 = k1 ^ 0x646f72616e646f6dULL;
@@ -96,27 +112,15 @@ sds_siphash13(const void *src, size_t src_sz, const char key[16])
v0 ^= mi;
}
+ /*
+ * Because we allocate in as size + 1, we can over-read 0
+ * for this buffer to be padded correctly. in here is a pointer to the
+ * excess data because the while loop above increments the in pointer
+ * to point to the excess once src_sz drops < 8.
+ */
uint64_t t = 0;
- uint8_t *pt = (uint8_t *)&t;
- uint8_t *m = (uint8_t *)in;
-
- switch (src_sz) {
- case 7:
- pt[6] = m[6]; /* FALLTHRU */
- case 6:
- pt[5] = m[5]; /* FALLTHRU */
- case 5:
- pt[4] = m[4]; /* FALLTHRU */
- case 4:
- *((uint32_t *)&pt[0]) = *((uint32_t *)&m[0]);
- break;
- case 3:
- pt[2] = m[2]; /* FALLTHRU */
- case 2:
- pt[1] = m[1]; /* FALLTHRU */
- case 1:
- pt[0] = m[0]; /* FALLTHRU */
- }
+ memcpy(&t, in, sizeof(uint64_t));
+
b |= _le64toh(t);
v3 ^= b;
@@ -126,5 +130,9 @@ sds_siphash13(const void *src, size_t src_sz, const char key[16])
v2 ^= 0xff;
// dround
dROUND(v0, v1, v2, v3);
+
+ free(in_ptr);
+
return (v0 ^ v1) ^ (v2 ^ v3);
}
+
diff --git a/src/libsds/test/test_sds_csiphash.c b/src/libsds/test/test_sds_csiphash.c
index cdb6b7f46..cc9a6b2b5 100644
--- a/src/libsds/test/test_sds_csiphash.c
+++ b/src/libsds/test/test_sds_csiphash.c
@@ -25,23 +25,48 @@
static void
test_siphash(void **state __attribute__((unused)))
{
-
- //
uint64_t value = 0;
uint64_t hashout = 0;
char key[16] = {0};
- uint64_t test_a = 15794382300316794652U;
- uint64_t test_b = 13042610424265326907U;
+ uint64_t test_simple = 15794382300316794652U;
- // Initial simple test
+ /* Initial simple test */
value = htole64(5);
hashout = sds_siphash13(&value, sizeof(uint64_t), key);
- assert_true(hashout == test_a);
+ assert_int_equal(hashout, test_simple);
+
+ /* Test a range of input sizes to check endianness behaviour */
+
+ hashout = sds_siphash13("a", 1, key);
+ assert_int_equal(hashout, 0x407448d2b89b1813U);
+
+ hashout = sds_siphash13("aa", 2, key);
+ assert_int_equal(hashout, 0x7910e0436ed8d1deU);
+
+ hashout = sds_siphash13("aaa", 3, key);
+ assert_int_equal(hashout, 0xf752893a6c769652U);
+
+ hashout = sds_siphash13("aaaa", 4, key);
+ assert_int_equal(hashout, 0x8b02350718d87164U);
+
+ hashout = sds_siphash13("aaaaa", 5, key);
+ assert_int_equal(hashout, 0x92a991474c7eef2U);
+
+ hashout = sds_siphash13("aaaaaa", 6, key);
+ assert_int_equal(hashout, 0xf0ab815a640277ccU);
+
+ hashout = sds_siphash13("aaaaaaa", 7, key);
+ assert_int_equal(hashout, 0x33f3c6d7dbc82c0dU);
+
+ hashout = sds_siphash13("aaaaaaaa", 8, key);
+ assert_int_equal(hashout, 0xc501b12e18428c92U);
+
+ hashout = sds_siphash13("aaaaaaaabbbb", 12, key);
+ assert_int_equal(hashout, 0xcddca673069ade64U);
- char *test = "abc";
- hashout = sds_siphash13(test, 4, key);
- assert_true(hashout == test_b);
+ hashout = sds_siphash13("aaaaaaaabbbbbbbb", 16, key);
+ assert_int_equal(hashout, 0xdc54f0bfc0e1deb0U);
}
int
--
2.13.6

View file

@ -1,258 +0,0 @@
From dcf75750dff23e848cde2ae63a0778b123de6dd7 Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Thu, 2 Nov 2017 13:32:41 +1000
Subject: [PATCH] Ticket 49436 - double free in COS in some conditions
Bug Description: virtualattrs and COS have some serious memory
ownership issues. What was happening is that COS with multiple
attributes using the same sp_handle would cause a structure
to be registered twice. During shutdown we would then trigger
a double free in the process.
Fix Description: Change the behaviour of sp_handles to use a
handle *per* attribute we register to guarantee the assocation
between them.
https://pagure.io/389-ds-base/issue/49436
Author: wibrown
Review by: mreynolds, vashirov (Thanks!)
(cherry pick from commit ee4428a3f5d2d8e37a7107c7dce9d622fc17d41c)
---
dirsrvtests/tests/suites/cos/indirect_cos_test.py | 43 +++++++----------------
ldap/servers/plugins/cos/cos_cache.c | 32 +++++++++--------
ldap/servers/plugins/roles/roles_cache.c | 8 ++---
ldap/servers/slapd/vattr.c | 28 +++++++++------
4 files changed, 51 insertions(+), 60 deletions(-)
diff --git a/dirsrvtests/tests/suites/cos/indirect_cos_test.py b/dirsrvtests/tests/suites/cos/indirect_cos_test.py
index 1aac6b8ed..452edcdf8 100644
--- a/dirsrvtests/tests/suites/cos/indirect_cos_test.py
+++ b/dirsrvtests/tests/suites/cos/indirect_cos_test.py
@@ -7,6 +7,7 @@ import subprocess
from lib389 import Entry
from lib389.idm.user import UserAccounts
+from lib389.idm.domain import Domain
from lib389.topologies import topology_st as topo
from lib389._constants import (DEFAULT_SUFFIX, DN_DM, PASSWORD, HOST_STANDALONE,
SERVERID_STANDALONE, PORT_STANDALONE)
@@ -48,14 +49,8 @@ def check_user(inst):
def setup_subtree_policy(topo):
"""Set up subtree password policy
"""
- try:
- topo.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE,
- 'nsslapd-pwpolicy-local',
- 'on')])
- except ldap.LDAPError as e:
- log.error('Failed to set fine-grained policy: error {}'.format(
- e.message['desc']))
- raise e
+
+ topo.standalone.config.set('nsslapd-pwpolicy-local', 'on')
log.info('Create password policy for subtree {}'.format(OU_PEOPLE))
try:
@@ -68,15 +63,9 @@ def setup_subtree_policy(topo):
OU_PEOPLE, e.message['desc']))
raise e
- log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE))
- try:
- topo.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_REPLACE,
- 'pwdpolicysubentry',
- PW_POLICY_CONT_PEOPLE2)])
- except ldap.LDAPError as e:
- log.error('Failed to pwdpolicysubentry pw policy '
- 'policy for {}: error {}'.format(OU_PEOPLE, e.message['desc']))
- raise e
+ domain = Domain(topo.standalone, DEFAULT_SUFFIX)
+ domain.replace('pwdpolicysubentry', PW_POLICY_CONT_PEOPLE2)
+
time.sleep(1)
@@ -116,12 +105,9 @@ def setup(topo, request):
"""
log.info('Add custom schema...')
try:
- ATTR_1 = ("( 1.3.6.1.4.1.409.389.2.189 NAME 'x-department' " +
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )")
- ATTR_2 = ("( 1.3.6.1.4.1.409.389.2.187 NAME 'x-en-ou' " +
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )")
- OC = ("( xPerson-oid NAME 'xPerson' DESC '' SUP person STRUCTURAL MAY " +
- "( x-department $ x-en-ou ) X-ORIGIN 'user defined' )")
+ ATTR_1 = (b"( 1.3.6.1.4.1.409.389.2.189 NAME 'x-department' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )")
+ ATTR_2 = (b"( 1.3.6.1.4.1.409.389.2.187 NAME 'x-en-ou' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )")
+ OC = (b"( xPerson-oid NAME 'xPerson' DESC '' SUP person STRUCTURAL MAY ( x-department $ x-en-ou ) X-ORIGIN 'user defined' )")
topo.standalone.modify_s("cn=schema", [(ldap.MOD_ADD, 'attributeTypes', ATTR_1),
(ldap.MOD_ADD, 'attributeTypes', ATTR_2),
(ldap.MOD_ADD, 'objectClasses', OC)])
@@ -142,14 +128,9 @@ def setup(topo, request):
'homeDirectory': '/home/test_user',
'seeAlso': 'cn=cosTemplate,dc=example,dc=com'
}
- users.create(properties=user_properties)
- try:
- topo.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_ADD,
- 'objectclass',
- 'xPerson')])
- except ldap.LDAPError as e:
- log.fatal('Failed to add objectclass to user')
- raise e
+ user = users.create(properties=user_properties)
+
+ user.add('objectClass', 'xPerson')
# Setup COS
log.info("Setup indirect COS...")
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
index 9ae15db15..662dace35 100644
--- a/ldap/servers/plugins/cos/cos_cache.c
+++ b/ldap/servers/plugins/cos/cos_cache.c
@@ -109,9 +109,6 @@ void *cos_get_plugin_identity(void);
#define COSTYPE_INDIRECT 3
#define COS_DEF_ERROR_NO_TEMPLATES -2
-/* the global plugin handle */
-static volatile vattr_sp_handle *vattr_handle = NULL;
-
/* both variables are protected by change_lock */
static int cos_cache_notify_flag = 0;
static PRBool cos_cache_at_work = PR_FALSE;
@@ -323,16 +320,6 @@ cos_cache_init(void)
views_api = 0;
}
- if (slapi_vattrspi_register((vattr_sp_handle **)&vattr_handle,
- cos_cache_vattr_get,
- cos_cache_vattr_compare,
- cos_cache_vattr_types) != 0) {
- slapi_log_err(SLAPI_LOG_ERR, COS_PLUGIN_SUBSYSTEM,
- "cos_cache_init - Cannot register as service provider\n");
- ret = -1;
- goto out;
- }
-
if (PR_CreateThread(PR_USER_THREAD,
cos_cache_wait_on_change,
NULL,
@@ -860,8 +847,23 @@ cos_dn_defs_cb(Slapi_Entry *e, void *callback_data)
dnVals[valIndex]->bv_val);
}
- slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle,
- dnVals[valIndex]->bv_val, NULL, NULL);
+ /*
+ * Each SP_handle is associated to one and only one vattr.
+ * We could consider making this a single function rather
+ * than the double-call.
+ */
+
+ vattr_sp_handle *vattr_handle = NULL;
+
+ if (slapi_vattrspi_register((vattr_sp_handle **)&vattr_handle,
+ cos_cache_vattr_get,
+ cos_cache_vattr_compare,
+ cos_cache_vattr_types) != 0) {
+ slapi_log_err(SLAPI_LOG_ERR, COS_PLUGIN_SUBSYSTEM, "cos_cache_init - Cannot register as service provider for %s\n", dnVals[valIndex]->bv_val);
+ } else {
+ slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle, dnVals[valIndex]->bv_val, NULL, NULL);
+ }
+
} /* if(attrType is cosAttribute) */
/*
diff --git a/ldap/servers/plugins/roles/roles_cache.c b/ldap/servers/plugins/roles/roles_cache.c
index 59f5a6081..1e5865af8 100644
--- a/ldap/servers/plugins/roles/roles_cache.c
+++ b/ldap/servers/plugins/roles/roles_cache.c
@@ -47,9 +47,6 @@ static char *allUserAttributes[] = {
/* views scoping */
static void **views_api;
-/* Service provider handler */
-static vattr_sp_handle *vattr_handle = NULL;
-
/* List of nested roles */
typedef struct _role_object_nested
{
@@ -224,6 +221,10 @@ roles_cache_init()
so that we update the corresponding cache */
slapi_register_backend_state_change(NULL, roles_cache_trigger_update_suffix);
+ /* Service provider handler - only used once! and freed by vattr! */
+ vattr_sp_handle *vattr_handle = NULL;
+
+
if (slapi_vattrspi_register((vattr_sp_handle **)&vattr_handle,
roles_sp_get_value,
roles_sp_compare_value,
@@ -622,7 +623,6 @@ roles_cache_stop()
current_role = next_role;
}
slapi_rwlock_unlock(global_lock);
- slapi_ch_free((void **)&vattr_handle);
roles_list = NULL;
slapi_log_err(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_stop\n");
diff --git a/ldap/servers/slapd/vattr.c b/ldap/servers/slapd/vattr.c
index 82deb41fe..432946c79 100644
--- a/ldap/servers/slapd/vattr.c
+++ b/ldap/servers/slapd/vattr.c
@@ -1864,7 +1864,12 @@ vattr_map_create(void)
void
vattr_map_entry_free(vattr_map_entry *vae)
{
- slapi_ch_free((void **)&(vae->sp_list));
+ vattr_sp_handle *list_entry = vae->sp_list;
+ while (list_entry != NULL) {
+ vattr_sp_handle *next_entry = list_entry->next;
+ slapi_ch_free((void **)&list_entry);
+ list_entry = next_entry;
+ }
slapi_ch_free_string(&(vae->type_name));
slapi_ch_free((void **)&vae);
}
@@ -2143,16 +2148,9 @@ slapi_vattr_schema_check_type(Slapi_Entry *e, char *type)
vattr_map_entry *
vattr_map_entry_new(char *type_name, vattr_sp_handle *sph, void *hint)
{
- vattr_map_entry *result = NULL;
- vattr_sp_handle *sp_copy = NULL;
-
- sp_copy = (vattr_sp_handle *)slapi_ch_calloc(1, sizeof(vattr_sp_handle));
- sp_copy->sp = sph->sp;
- sp_copy->hint = hint;
-
- result = (vattr_map_entry *)slapi_ch_calloc(1, sizeof(vattr_map_entry));
+ vattr_map_entry *result = (vattr_map_entry *)slapi_ch_calloc(1, sizeof(vattr_map_entry));
result->type_name = slapi_ch_strdup(type_name);
- result->sp_list = sp_copy;
+ result->sp_list = sph;
/* go get schema */
result->objectclasses = vattr_map_entry_build_schema(type_name);
@@ -2273,6 +2271,16 @@ we'd need to hold a lock on the read path, which we don't want to do.
So any SP which relinquishes its need to handle a type needs to continue
to handle the calls on it, but return nothing */
/* DBDB need to sort out memory ownership here, it's not quite right */
+/*
+ * This function was inconsistent. We would allocated and "kind of",
+ * copy the sp_handle here for the vattr_map_entry_new path. But we
+ * would "take ownership" for the existing entry and the list addition
+ * path. Instead now, EVERY sp_handle we take, we take ownership of
+ * and the CALLER must allocate a new one each time.
+ *
+ * Better idea, is that regattr should just take the fn pointers
+ * and callers never *see* the sp_handle structure at all.
+ */
int
vattr_map_sp_insert(char *type_to_add, vattr_sp_handle *sp, void *hint)
--
2.13.6

View file

@ -1,169 +0,0 @@
From 403c5b61efb5aca3cbea31170d13dfba190ef355 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 2 Nov 2017 12:55:11 -0400
Subject: [PATCH] Ticket 49439 - cleanallruv is not logging information
Bug Description: During the logging refector effro from ticket 48978
a mistake was made and cleanruv_log() was using
LOG_NOTICE (which is not a true log level), it was
supposed to be SLAPI_LOG_NOTICE.
We also use DEBUG defines to contorl the logging for
debug builds
Fix Description: Remove the LDAP_DEBUG defines in cleanruv_log, and set
the correct logging severity level.
https://pagure.io/389-ds-base/issue/49439
Reviewed by: firstyear(Thanks!)
(cherry picked from commit e1f866a5e3ccce8e061e361c0e3dd11175a8acf2)
---
.../plugins/replication/repl5_replica_config.c | 30 ++++++++++------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 9c3c75458..9c8d6adbb 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1783,7 +1783,7 @@ replica_cleanallruv_thread(void *arg)
/*
* need to sleep between passes
*/
- cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, LOG_NOTICE, "Not all replicas have received the "
+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE, "Not all replicas have received the "
"cleanallruv extended op, retrying in %d seconds",
interval);
if (!slapi_is_shutting_down()) {
@@ -1825,7 +1825,7 @@ replica_cleanallruv_thread(void *arg)
found_dirty_rid = 0;
} else {
found_dirty_rid = 1;
- cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, LOG_NOTICE, "Replica is not cleaned yet (%s)",
+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE, "Replica is not cleaned yet (%s)",
agmt_get_long_name(agmt));
break;
}
@@ -1843,7 +1843,7 @@ replica_cleanallruv_thread(void *arg)
* Need to sleep between passes unless we are shutting down
*/
if (!slapi_is_shutting_down()) {
- cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, LOG_NOTICE, "Replicas have not been cleaned yet, "
+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE, "Replicas have not been cleaned yet, "
"retrying in %d seconds",
interval);
PR_Lock(notify_lock);
@@ -1883,10 +1883,10 @@ done:
* Shutdown or abort
*/
if (!is_task_aborted(data->rid) || slapi_is_shutting_down()) {
- cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, LOG_NOTICE,
+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE,
"Server shutting down. Process will resume at server startup");
} else {
- cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, LOG_NOTICE, "Task aborted for rid(%d).", data->rid);
+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE, "Task aborted for rid(%d).", data->rid);
delete_cleaned_rid_config(data);
remove_cleaned_rid(data->rid);
}
@@ -2053,7 +2053,7 @@ check_replicas_are_done_cleaning(cleanruv_data *data)
break;
}
- cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, LOG_NOTICE,
+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE,
"Not all replicas finished cleaning, retrying in %d seconds",
interval);
if (!slapi_is_shutting_down()) {
@@ -2163,7 +2163,7 @@ check_replicas_are_done_aborting(cleanruv_data *data)
if (not_all_aborted == 0) {
break;
}
- cleanruv_log(data->task, data->rid, ABORT_CLEANALLRUV_ID, LOG_NOTICE,
+ cleanruv_log(data->task, data->rid, ABORT_CLEANALLRUV_ID, SLAPI_LOG_NOTICE,
"Not all replicas finished aborting, retrying in %d seconds", interval);
if (!slapi_is_shutting_down()) {
PR_Lock(notify_lock);
@@ -2210,7 +2210,7 @@ check_agmts_are_caught_up(cleanruv_data *data, char *maxcsn)
not_all_caughtup = 0;
} else {
not_all_caughtup = 1;
- cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, LOG_NOTICE,
+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE,
"Replica not caught up (%s)", agmt_get_long_name(agmt));
break;
}
@@ -2220,7 +2220,7 @@ check_agmts_are_caught_up(cleanruv_data *data, char *maxcsn)
if (not_all_caughtup == 0 || is_task_aborted(data->rid)) {
break;
}
- cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, LOG_NOTICE,
+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE,
"Not all replicas caught up, retrying in %d seconds", interval);
if (!slapi_is_shutting_down()) {
PR_Lock(notify_lock);
@@ -2270,7 +2270,7 @@ check_agmts_are_alive(Replica *replica, ReplicaId rid, Slapi_Task *task)
not_all_alive = 0;
} else {
not_all_alive = 1;
- cleanruv_log(task, rid, CLEANALLRUV_ID, LOG_NOTICE, "Replica not online (%s)",
+ cleanruv_log(task, rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE, "Replica not online (%s)",
agmt_get_long_name(agmt));
break;
}
@@ -2280,7 +2280,7 @@ check_agmts_are_alive(Replica *replica, ReplicaId rid, Slapi_Task *task)
if (not_all_alive == 0 || is_task_aborted(rid)) {
break;
}
- cleanruv_log(task, rid, CLEANALLRUV_ID, LOG_NOTICE, "Not all replicas online, retrying in %d seconds...",
+ cleanruv_log(task, rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE, "Not all replicas online, retrying in %d seconds...",
interval);
if (!slapi_is_shutting_down()) {
@@ -3063,7 +3063,7 @@ replica_abort_task_thread(void *arg)
* Need to sleep between passes. unless we are shutting down
*/
if (!slapi_is_shutting_down()) {
- cleanruv_log(data->task, data->rid, ABORT_CLEANALLRUV_ID, LOG_NOTICE, "Retrying in %d seconds", interval);
+ cleanruv_log(data->task, data->rid, ABORT_CLEANALLRUV_ID, SLAPI_LOG_NOTICE, "Retrying in %d seconds", interval);
PR_Lock(notify_lock);
PR_WaitCondVar(notify_cvar, PR_SecondsToInterval(interval));
PR_Unlock(notify_lock);
@@ -3184,7 +3184,7 @@ replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *clean_data, int che
/* extop was accepted */
rc = 0;
} else {
- cleanruv_log(clean_data->task, clean_data->rid, CLEANALLRUV_ID, LOG_NOTICE,
+ cleanruv_log(clean_data->task, clean_data->rid, CLEANALLRUV_ID, SLAPI_LOG_NOTICE,
"Replica %s does not support the CLEANALLRUV task. "
"Sending replica CLEANRUV task...",
slapi_sdn_get_dn(agmt_get_dn_byref(ra)));
@@ -3352,7 +3352,7 @@ replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *basedn, char *rid_text,
csn_init_by_string(repl_max, remote_maxcsn);
if (csn_compare(repl_max, max) < 0) {
/* we are not caught up yet, free, and return */
- cleanruv_log(task, atoi(rid_text), CLEANALLRUV_ID, LOG_NOTICE,
+ cleanruv_log(task, atoi(rid_text), CLEANALLRUV_ID, SLAPI_LOG_NOTICE,
"Replica maxcsn (%s) is not caught up with deleted replica's maxcsn(%s)",
remote_maxcsn, maxcsn);
rc = -1;
@@ -3525,7 +3525,6 @@ stop_ruv_cleaning()
void
cleanruv_log(Slapi_Task *task, int rid, char *task_type, int sev_level, char *fmt, ...)
{
-#ifdef LDAP_DEBUG
va_list ap1;
va_list ap2;
va_list ap3;
@@ -3550,7 +3549,6 @@ cleanruv_log(Slapi_Task *task, int rid, char *task_type, int sev_level, char *fm
va_end(ap2);
va_end(ap3);
va_end(ap4);
-#endif
}
char *
--
2.13.6

View file

@ -1,32 +0,0 @@
From 3d045a240bb32b66e15401bf89eff5b980420b24 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 3 Nov 2017 12:18:26 -0400
Subject: [PATCH] Ticket 48393 - fix copy and paste error
Description: Copy and paste error when validating repl agmt
https://pagure.io/389-ds-base/issue/48393
Reviewed by: mreynolds(one line commit rule)
(cherry picked from commit 431647039c5e6d860d8866542050d456f69bb600)
---
ldap/servers/plugins/replication/repl5_agmt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index 78fb91ae6..ee396c8ef 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -339,7 +339,7 @@ agmt_new_from_entry(Slapi_Entry *e)
ra->flowControlWindow = DEFAULT_FLOWCONTROL_WINDOW;
if ((val = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaFlowControlWindow))){
int64_t flow;
- if (repl_config_valid_num(type_nsds5ReplicaTimeout, val, 0, INT_MAX, &rc, errormsg, &flow) != 0) {
+ if (repl_config_valid_num(type_nsds5ReplicaFlowControlWindow, val, 0, INT_MAX, &rc, errormsg, &flow) != 0) {
goto loser;
}
slapi_ch_free_string(&val);
--
2.13.6

View file

@ -1,57 +0,0 @@
From 2b5b09a7a871d626bb45888f948126732d0893f3 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 4 Oct 2017 12:55:30 -0400
Subject: [PATCH] Ticket 49038 - remove legacy replication - change cleanup
script precedence
Description: Bump the cleanup scripts precendance so it happens after the
main plugin upgrade scripts are called.
https://pagure.io/389-ds-base/issue/49038
Reviewed by: firstyear(Thanks!)
(cherry picked from commit 1fe2c761103c36090ab67df0271dfdb3012037fb)
---
Makefile.am | 2 +-
...{50removeLegacyReplication.ldif => 60removeLegacyReplication.ldif} | 0
rpm/389-ds-base.spec.in | 4 ++--
3 files changed, 3 insertions(+), 3 deletions(-)
rename ldap/admin/src/scripts/{50removeLegacyReplication.ldif => 60removeLegacyReplication.ldif} (100%)
diff --git a/Makefile.am b/Makefile.am
index 09a6bc296..8834a7819 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -942,7 +942,7 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \
ldap/admin/src/scripts/50telexnumbersyntaxplugin.ldif \
ldap/admin/src/scripts/50guidesyntaxplugin.ldif \
ldap/admin/src/scripts/50targetuniqueid.ldif \
- ldap/admin/src/scripts/50removeLegacyReplication.ldif \
+ ldap/admin/src/scripts/60removeLegacyReplication.ldif \
ldap/admin/src/scripts/50linkedattrsplugin.ldif \
ldap/admin/src/scripts/50usnplugin.ldif \
ldap/admin/src/scripts/50smd5pwdstorageplugin.ldif \
diff --git a/ldap/admin/src/scripts/50removeLegacyReplication.ldif b/ldap/admin/src/scripts/60removeLegacyReplication.ldif
similarity index 100%
rename from ldap/admin/src/scripts/50removeLegacyReplication.ldif
rename to ldap/admin/src/scripts/60removeLegacyReplication.ldif
diff --git a/rpm/389-ds-base.spec.in b/rpm/389-ds-base.spec.in
index 1e5c2cfd3..30a1d7d9a 100644
--- a/rpm/389-ds-base.spec.in
+++ b/rpm/389-ds-base.spec.in
@@ -395,9 +395,9 @@ echo remove pid files . . . >> $output 2>&1 || :
echo upgrading instances . . . >> $output 2>&1 || :
DEBUGPOSTSETUPOPT=`/usr/bin/echo $DEBUGPOSTSETUP | /usr/bin/sed -e "s/[^d]//g"`
if [ -n "$DEBUGPOSTSETUPOPT" ] ; then
- %{_sbindir}/setup-ds.pl -l $output2 -$DEBUGPOSTSETUPOPT -u -s General.UpdateMode=offline >> $output 2>&1 || :
+ %{_sbindir}/setup-ds.pl -$DEBUGPOSTSETUPOPT -u -s General.UpdateMode=offline >> $output 2>&1 || :
else
- %{_sbindir}/setup-ds.pl -l $output2 -u -s General.UpdateMode=offline >> $output 2>&1 || :
+ %{_sbindir}/setup-ds.pl -u -s General.UpdateMode=offline >> $output 2>&1 || :
fi
# restart instances that require it
--
2.13.6

View file

@ -1,88 +0,0 @@
From b1dfe53aaf7cb0260286423b9abf7d71f8edd421 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 15 Nov 2017 13:27:58 -0500
Subject: [PATCH] Ticket 49454 - SSL Client Authentication breaks in FIPS mode
Bug Description: Replication using SSL Client Auth breaks when FIPS
is enabled. This is because FIPS mode changes the
internal certificate token name.
Fix Description: If FIPS is enabled grab the token name from the internal
slot instead of using the default hardcoded internal
token name.
https://pagure.io/389-ds-base/issue/49454
Reviewed by: firstyear(Thanks!)
(cherry picked from commit 6e794a8eff213d49c933f781006e234984160db2)
---
ldap/servers/slapd/proto-slap.h | 1 +
ldap/servers/slapd/security_wrappers.c | 6 ++++++
ldap/servers/slapd/ssl.c | 24 +++++++++++++++++-------
3 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 4a30def8b..3b7ab53b2 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1130,6 +1130,7 @@ PRBool slapd_pk11_DoesMechanism(PK11SlotInfo *slot, CK_MECHANISM_TYPE type);
PK11SymKey *slapd_pk11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags, PRBool isPerm);
PK11SymKey *slapd_pk11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx);
CK_MECHANISM_TYPE slapd_PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **params, SECItem *pwitem);
+char *slapd_PK11_GetTokenName(PK11SlotInfo *slot);
/*
* start_tls_extop.c
diff --git a/ldap/servers/slapd/security_wrappers.c b/ldap/servers/slapd/security_wrappers.c
index bec28d2f3..41fe03608 100644
--- a/ldap/servers/slapd/security_wrappers.c
+++ b/ldap/servers/slapd/security_wrappers.c
@@ -401,3 +401,9 @@ slapd_PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **params, SECIte
{
return PK11_GetPBECryptoMechanism(algid, params, pwitem);
}
+
+char *
+slapd_PK11_GetTokenName(PK11SlotInfo *slot)
+{
+ return PK11_GetTokenName(slot);
+}
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index efe32d5d0..52ac7ea9f 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -2365,13 +2365,23 @@ slapd_SSL_client_auth(LDAP *ld)
ssltoken = slapi_entry_attr_get_charptr(entry, "nsssltoken");
if (ssltoken && personality) {
if (!PL_strcasecmp(ssltoken, "internal") ||
- !PL_strcasecmp(ssltoken, "internal (software)")) {
-
- /* Translate config internal name to more
- * readable form. Certificate name is just
- * the personality for internal tokens.
- */
- token = slapi_ch_strdup(internalTokenName);
+ !PL_strcasecmp(ssltoken, "internal (software)"))
+ {
+ if ( slapd_pk11_isFIPS() ) {
+ /*
+ * FIPS mode changes the internal token name, so we need to
+ * grab the new token name from the internal slot.
+ */
+ PK11SlotInfo *slot = slapd_pk11_getInternalSlot();
+ token = slapi_ch_strdup(slapd_PK11_GetTokenName(slot));
+ PK11_FreeSlot(slot);
+ } else {
+ /*
+ * Translate config internal name to more readable form.
+ * Certificate name is just the personality for internal tokens.
+ */
+ token = slapi_ch_strdup(internalTokenName);
+ }
#if defined(USE_OPENLDAP)
/* openldap needs tokenname:certnick */
PR_snprintf(cert_name, sizeof(cert_name), "%s:%s", token, personality);
--
2.13.6

View file

@ -1,84 +0,0 @@
From 11cea14acfc11d0328013b61a3e1396e97dfe577 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Tue, 14 Nov 2017 16:29:03 +0100
Subject: [PATCH] Ticket 49410 - opened connection can remain no longer poll,
like hanging
Bug Description:
Some opened connection are no longer poll.
Those connections has 'gettingber' toggle set although there is
no more worker thread reading it.
The reason they have gettingber set is that the last
operation had 'persistent search' flag. With such flag
gettingber is not reset.
persistent flag is set even when no persistent search/sync_repl
was received on the connection.
The problem is that the flag is tested on the wrong operation.
The tested operation can be
- the first operation when the connection entered in turbo mode
- the previous operation if several ops PDUs were read on the network
- accessing random memory
In theory testing the flag can lead to sigsev even
if it never crash
Fix Description:
The fix is to use the operation that is in the pblock
In such case pb_op is no longer used, so we can get rid of it.
In addition make pb_conn a local variable where it is used
https://pagure.io/389-ds-base/issue/49410
Reviewed by: Ludwig Krispenz, Mark Reynolds
Platforms tested: F26
Flag Day: no
Doc impact: no
---
ldap/servers/slapd/connection.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 24a7a1c05..3f19b9765 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -1498,8 +1498,6 @@ connection_threadmain()
int maxthreads = 0;
int enable_nunc_stans = 0;
long bypasspollcnt = 0;
- Connection *pb_conn = NULL;
- Operation *pb_op = NULL;
enable_nunc_stans = config_get_enable_nunc_stans();
#if defined(hpux)
@@ -1520,6 +1518,8 @@ connection_threadmain()
}
if (!thread_turbo_flag && !more_data) {
+ Connection *pb_conn = NULL;
+
/* If more data is left from the previous connection_read_operation,
we should finish the op now. Client might be thinking it's
done sending the request and wait for the response forever.
@@ -1530,7 +1530,6 @@ connection_threadmain()
* Connection wait for new work provides the conn and op for us.
*/
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
- slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
switch (ret) {
case CONN_NOWORK:
@@ -1786,7 +1785,7 @@ connection_threadmain()
/* total number of ops for the server */
slapi_counter_increment(ops_completed);
/* If this op isn't a persistent search, remove it */
- if (pb_op->o_flags & OP_FLAG_PS) {
+ if (op->o_flags & OP_FLAG_PS) {
PR_EnterMonitor(conn->c_mutex);
connection_release_nolock(conn); /* psearch acquires ref to conn - release this one now */
PR_ExitMonitor(conn->c_mutex);
--
2.13.6

View file

@ -1,35 +0,0 @@
From 5f38be985bc98969b0fdaa6ece8f84b11bdddc2f Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Thu, 9 Nov 2017 10:20:44 +0100
Subject: [PATCH] Ticket 49443 - scope one searches in 1.3.7 give incorrect
results
Bug: if a onelevel search is done for an unidexed attribute, the filter test is skipped
and all children of the search base are returned
Fix: enforce filter test if allids
Reviewed by: Mark, thanks
---
ldap/servers/slapd/back-ldbm/idl_set.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/ldap/servers/slapd/back-ldbm/idl_set.c b/ldap/servers/slapd/back-ldbm/idl_set.c
index ba39ff03f..b68e7ab76 100644
--- a/ldap/servers/slapd/back-ldbm/idl_set.c
+++ b/ldap/servers/slapd/back-ldbm/idl_set.c
@@ -349,6 +349,11 @@ idl_set_intersect(IDListSet *idl_set, backend *be)
{
IDList *result_list = NULL;
+ if (idl_set->allids) {
+ /* if any component was allids we have to apply the filtertest */
+ slapi_be_set_flag(be, SLAPI_BE_FLAG_DONT_BYPASS_FILTERTEST);
+ }
+
if (idl_set->allids != 0 && idl_set->count == 0) {
/*
* We only have allids, so must be allids.
--
2.13.6

View file

@ -1,43 +0,0 @@
From 2c868707b3ae1a4255ea33610b177f8a98f4a3f3 Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Tue, 7 Nov 2017 17:09:18 +1000
Subject: [PATCH] Ticket 49441 - Import crashes - oneline fix
Bug Description: index.c fails to compile.
Fix Description: Excess braces due to copy paste issue.
https://pagure.io/389-ds-base/issue/49441
Author: wibrown
Review by: oneline rule
(cherry picked from commit be4d7e5a82c1616317fa52968d2814e3f922254c)
---
ldap/servers/slapd/back-ldbm/index.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
index a565db87b..587f4d991 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -1778,7 +1778,6 @@ addordel_values(
key.flags = DB_DBT_USERMEM;
key.ulen = tmpbuflen;
if (slapi_is_loglevel_set(LDAP_DEBUG_TRACE)) {
- {
char encbuf[BUFSIZ];
slapi_log_err(SLAPI_LOG_TRACE, "addordel_values", "%s_value(\"%s\")\n",
@@ -1943,7 +1942,6 @@ addordel_values_sv(
key.ulen = tmpbuflen;
if (slapi_is_loglevel_set(LDAP_DEBUG_TRACE)) {
- {
char encbuf[BUFSIZ];
slapi_log_err(SLAPI_LOG_TRACE, "addordel_values_sv", "%s_value(\"%s\")\n",
--
2.13.6

View file

@ -1,44 +0,0 @@
From 40811ab7571ddf0a6905b3b019229bdb555bd04d Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Tue, 7 Nov 2017 12:42:11 +1000
Subject: [PATCH] Ticket 49377 - Incoming BER too large with TLS on plain port
Bug Description: When doing TLS to a plain port, a message of
"ber element 3 bytes too large for max ber" when max ber > 3.
Fix Description: When ber_len < maxber, report that the request
may be misformed instead of "oversize" instead. This can lead
to a better diagnosis.
https://pagure.io/389-ds-base/issue/49377
Author: wibrown
Review by: mreynolds (thanks!)
Cherry picked from commit b3629af054760d9421a41d63b8b8ed513bb6944d
---
ldap/servers/slapd/connection.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 3f19b9765..8ef115691 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -2176,6 +2176,13 @@ log_ber_too_big_error(const Connection *conn, ber_len_t ber_len, ber_len_t maxbe
" is %" BERLEN_T " bytes. Change the nsslapd-maxbersize attribute in"
" cn=config to increase.\n",
conn->c_connid, conn->c_sd, maxbersize);
+ } else if (ber_len < maxbersize) {
+ /* This means the request was misformed, not too large. */
+ slapi_log_err(SLAPI_LOG_ERR, "log_ber_too_big_error",
+ "conn=%" PRIu64 " fd=%d Incoming BER Element may be misformed. "
+ "This may indicate an attempt to use TLS on a plaintext port, "
+ "IE ldaps://localhost:389. Check your client LDAP_URI settings.\n",
+ conn->c_connid, conn->c_sd);
} else {
slapi_log_err(SLAPI_LOG_ERR, "log_ber_too_big_error",
"conn=%" PRIu64 " fd=%d Incoming BER Element was %" BERLEN_T " bytes, max allowable"
--
2.13.6

View file

@ -1,244 +0,0 @@
From 127e0d954eb7741c4afdc0305f7970b7ea164e8d Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Thu, 9 Nov 2017 11:28:34 +0100
Subject: [PATCH] Ticket 48118 - At startup, changelog can be erronously
rebuilt after a normal shutdown
Problem: There are two problems that can lead to inconsistent database and changelog maxruv:
1] the database ruv is written periodically in th ehouskeeping thread and at shutdown. It
relies on teh ruv_dirty flag, but due to a race condition this can be reset befor writing
the ruv
2] the changelog max ruv is updated whenever an operation is commutted, but in case of internal
operations inside the txn for a client operation, if the operation is aborted the cl maxruv
is not reset. Since it is only written at shutdown this normally is no problem, but if the
aborted operation is the last before shutdown or is aborted by shutdown the cl ruv is incorrect
Fix: the fix is in two parts:
1] remove the use of the dirty flag, ensure that the ruv is always written. The overhead for writing
a database ruv that has not changed is minimal
2] when writing the changelog maxruv check if the macsns it contains are really present in the
changelog. If not the maxruv is not written, it will be reconstructed at the next startup
Reviewed by: William,Thierry - Thanks
---
ldap/servers/plugins/replication/cl5_api.c | 39 ++++++++++++++++++++++
ldap/servers/plugins/replication/repl5.h | 1 -
ldap/servers/plugins/replication/repl5_replica.c | 32 +-----------------
.../plugins/replication/repl5_replica_config.c | 2 --
4 files changed, 40 insertions(+), 34 deletions(-)
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index ec648c014..55032dfb0 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -250,6 +250,8 @@ static void _cl5ReadBerval(struct berval *bv, char **buff);
static void _cl5WriteBerval(struct berval *bv, char **buff);
static int _cl5ReadBervals(struct berval ***bv, char **buff, unsigned int size);
static int _cl5WriteBervals(struct berval **bv, char **buff, u_int32_t *size);
+static int64_t _cl5CheckMaxRUV(CL5DBFile *file, RUV *maxruv);
+static int64_t _cl5CheckCSNinCL(const ruv_enum_data *element, void *arg);
/* replay iteration */
#ifdef FOR_DEBUGGING
@@ -2716,6 +2718,36 @@ _cl5WriteBervals(struct berval **bv, char **buff, u_int32_t *size)
return CL5_SUCCESS;
}
+static int64_t
+_cl5CheckCSNinCL(const ruv_enum_data *element, void *arg)
+{
+ CL5DBFile *file = (CL5DBFile *)arg;
+ int rc = 0;
+
+ DBT key = {0}, data = {0};
+ char csnStr[CSN_STRSIZE];
+
+ /* construct the key */
+ key.data = csn_as_string(element->csn, PR_FALSE, csnStr);
+ key.size = CSN_STRSIZE;
+
+ data.flags = DB_DBT_MALLOC;
+
+ rc = file->db->get(file->db, NULL /*txn*/, &key, &data, 0);
+
+ slapi_ch_free(&(data.data));
+ return rc;
+}
+
+static int64_t
+_cl5CheckMaxRUV(CL5DBFile *file, RUV *maxruv)
+{
+ int rc = 0;
+
+ rc = ruv_enumerate_elements(maxruv, _cl5CheckCSNinCL, (void *)file);
+
+ return rc;
+}
/* upgrade from db33 to db41
* 1. Run recovery on the database environment using the DB_ENV->open method
* 2. Remove any Berkeley DB environment using the DB_ENV->remove method
@@ -4010,6 +4042,13 @@ _cl5WriteRUV(CL5DBFile *file, PRBool purge)
rc = ruv_to_bervals(file->maxRUV, &vals);
}
+ if (!purge && _cl5CheckMaxRUV(file, file->maxRUV)) {
+ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
+ "_cl5WriteRUV - changelog maxRUV not found in changelog for file %s\n",
+ file->name);
+ return CL5_DB_ERROR;
+ }
+
key.size = CSN_STRSIZE;
rc = _cl5WriteBervals(vals, &buff, &data.size);
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index c6e79b7e2..4e206a0fc 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -725,7 +725,6 @@ Object *replica_get_for_backend(const char *be_name);
void replica_set_purge_delay(Replica *r, uint32_t purge_delay);
void replica_set_tombstone_reap_interval(Replica *r, long interval);
void replica_update_ruv_consumer(Replica *r, RUV *supplier_ruv);
-void replica_set_ruv_dirty(Replica *r);
Slapi_Entry *get_in_memory_ruv(Slapi_DN *suffix_sdn);
int replica_write_ruv(Replica *r);
char *replica_get_dn(Replica *r);
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index e5296bf1c..77f4f18e4 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -41,7 +41,6 @@ struct replica
ReplicaType repl_type; /* is this replica read-only ? */
ReplicaId repl_rid; /* replicaID */
Object *repl_ruv; /* replica update vector */
- PRBool repl_ruv_dirty; /* Dirty flag for ruv */
CSNPL *min_csn_pl; /* Pending list for minimal CSN */
void *csn_pl_reg_id; /* registration assignment for csn callbacks */
unsigned long repl_state_flags; /* state flags */
@@ -788,7 +787,6 @@ replica_set_ruv(Replica *r, RUV *ruv)
}
r->repl_ruv = object_new((void *)ruv, (FNFree)ruv_destroy);
- r->repl_ruv_dirty = PR_TRUE;
replica_unlock(r->repl_lock);
}
@@ -860,9 +858,6 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
"to update RUV for replica %s, csn = %s\n",
slapi_sdn_get_dn(r->repl_root),
csn_as_string(updated_csn, PR_FALSE, csn_str));
- } else {
- /* RUV updated - mark as dirty */
- r->repl_ruv_dirty = PR_TRUE;
}
} else {
slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name,
@@ -1347,8 +1342,6 @@ replica_dump(Replica *r)
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "\tupdate dn: %s\n",
updatedn_list ? updatedn_list : "not configured");
slapi_ch_free_string(&updatedn_list);
- slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "\truv: %s configured and is %sdirty\n",
- r->repl_ruv ? "" : "not", r->repl_ruv_dirty ? "" : "not ");
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "\tCSN generator: %s configured\n",
r->repl_csngen ? "" : "not");
/* JCMREPL - Dump Referrals */
@@ -1675,7 +1668,6 @@ replica_check_for_data_reload(Replica *r, void *arg __attribute__((unused)))
ruv_force_csn_update_from_ruv(upper_bound_ruv, r_ruv,
"Force update of database RUV (from CL RUV) -> ", SLAPI_LOG_NOTICE);
- replica_set_ruv_dirty(r);
}
} else {
@@ -2778,11 +2770,6 @@ replica_write_ruv(Replica *r)
replica_lock(r->repl_lock);
- if (!r->repl_ruv_dirty) {
- replica_unlock(r->repl_lock);
- return rc;
- }
-
PR_ASSERT(r->repl_ruv);
ruv_to_smod((RUV *)object_get_data(r->repl_ruv), &smod);
@@ -2817,14 +2804,10 @@ replica_write_ruv(Replica *r)
/* ruv does not exist - create one */
replica_lock(r->repl_lock);
- if (rc == LDAP_SUCCESS) {
- r->repl_ruv_dirty = PR_FALSE;
- } else if (rc == LDAP_NO_SUCH_OBJECT) {
+ if (rc == LDAP_NO_SUCH_OBJECT) {
/* this includes an internal operation - but since this only happens
during server startup - its ok that we have lock around it */
rc = _replica_configure_ruv(r, PR_TRUE);
- if (rc == 0)
- r->repl_ruv_dirty = PR_FALSE;
} else /* error */
{
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
@@ -3325,7 +3308,6 @@ replica_create_ruv_tombstone(Replica *r)
if (ruv_init_new(csnstr, r->repl_rid, purl, &ruv) == RUV_SUCCESS) {
r->repl_ruv = object_new((void *)ruv, (FNFree)ruv_destroy);
- r->repl_ruv_dirty = PR_TRUE;
return_value = LDAP_SUCCESS;
} else {
slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_create_ruv_tombstone - "
@@ -3365,8 +3347,6 @@ replica_create_ruv_tombstone(Replica *r)
slapi_add_internal_pb(pb);
e = NULL; /* add consumes e, upon success or failure */
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &return_value);
- if (return_value == LDAP_SUCCESS)
- r->repl_ruv_dirty = PR_FALSE;
done:
slapi_entry_free(e);
@@ -3630,7 +3610,6 @@ replica_strip_cleaned_rids(Replica *r)
ruv_get_cleaned_rids(ruv, rid);
while (rid[i] != 0) {
ruv_delete_replica(ruv, rid[i]);
- replica_set_ruv_dirty(r);
if (replica_write_ruv(r)) {
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
"replica_strip_cleaned_rids - Failed to write RUV\n");
@@ -3744,15 +3723,6 @@ replica_update_ruv_consumer(Replica *r, RUV *supplier_ruv)
}
}
-void
-replica_set_ruv_dirty(Replica *r)
-{
- PR_ASSERT(r);
- replica_lock(r->repl_lock);
- r->repl_ruv_dirty = PR_TRUE;
- replica_unlock(r->repl_lock);
-}
-
PRBool
replica_is_state_flag_set(Replica *r, int32_t flag)
{
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 9c8d6adbb..e025f34d8 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -937,7 +937,6 @@ replica_config_change_type_and_id(Replica *r, const char *new_type, const char *
replica_reset_csn_pl(r);
}
ruv_delete_replica(ruv, oldrid);
- replica_set_ruv_dirty(r);
cl5CleanRUV(oldrid);
replica_set_csn_assigned(r);
}
@@ -1323,7 +1322,6 @@ replica_execute_cleanruv_task(Object *r, ReplicaId rid, char *returntext __attri
return LDAP_UNWILLING_TO_PERFORM;
}
rc = ruv_delete_replica(local_ruv, rid);
- replica_set_ruv_dirty(replica);
if (replica_write_ruv(replica)) {
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task - Could not write RUV\n");
}
--
2.13.6

View file

@ -1,45 +0,0 @@
From fd06b282ffd06a5b3807c0396bff442f0c7568b1 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Wed, 15 Nov 2017 13:17:00 +0100
Subject: [PATCH] Ticket 48118 - fix compiler warning for incorrect return type
---
ldap/servers/plugins/replication/cl5_api.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 55032dfb0..721013abf 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -250,8 +250,8 @@ static void _cl5ReadBerval(struct berval *bv, char **buff);
static void _cl5WriteBerval(struct berval *bv, char **buff);
static int _cl5ReadBervals(struct berval ***bv, char **buff, unsigned int size);
static int _cl5WriteBervals(struct berval **bv, char **buff, u_int32_t *size);
-static int64_t _cl5CheckMaxRUV(CL5DBFile *file, RUV *maxruv);
-static int64_t _cl5CheckCSNinCL(const ruv_enum_data *element, void *arg);
+static int32_t _cl5CheckMaxRUV(CL5DBFile *file, RUV *maxruv);
+static int32_t _cl5CheckCSNinCL(const ruv_enum_data *element, void *arg);
/* replay iteration */
#ifdef FOR_DEBUGGING
@@ -2718,7 +2718,7 @@ _cl5WriteBervals(struct berval **bv, char **buff, u_int32_t *size)
return CL5_SUCCESS;
}
-static int64_t
+static int32_t
_cl5CheckCSNinCL(const ruv_enum_data *element, void *arg)
{
CL5DBFile *file = (CL5DBFile *)arg;
@@ -2739,7 +2739,7 @@ _cl5CheckCSNinCL(const ruv_enum_data *element, void *arg)
return rc;
}
-static int64_t
+static int32_t
_cl5CheckMaxRUV(CL5DBFile *file, RUV *maxruv)
{
int rc = 0;
--
2.13.6

View file

@ -1,210 +0,0 @@
From e3dea0043973faf42f7756d840bc55aa8f143eb1 Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Wed, 15 Nov 2017 13:44:02 +1000
Subject: [PATCH] Ticket 49298 - Correct error codes with config restore.
Bug Description: The piece of code uses 0 as an error - not 1,
and in some cases did not even check the codes or use the
correct logic.
Fix Description: Cleanup dse_check_file to better check the
content of files and communicate issues to the admin. Correct
slapd_bootstrap_config to correctly handle the cases of removal
and restore.
https://pagure.io/389-ds-base/issue/49298
Author: wibrown
Review by: mreynoolds & spichugi
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
(cherry picked from commit 75e55e26579955adf058e8adcba9a28779583b7b)
---
.../suites/config/removed_config_49298_test.py | 81 ++++++++++++++++++++++
ldap/servers/slapd/config.c | 15 ++--
ldap/servers/slapd/dse.c | 42 ++++++++---
3 files changed, 119 insertions(+), 19 deletions(-)
create mode 100644 dirsrvtests/tests/suites/config/removed_config_49298_test.py
diff --git a/dirsrvtests/tests/suites/config/removed_config_49298_test.py b/dirsrvtests/tests/suites/config/removed_config_49298_test.py
new file mode 100644
index 000000000..e65236924
--- /dev/null
+++ b/dirsrvtests/tests/suites/config/removed_config_49298_test.py
@@ -0,0 +1,81 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2017 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import pytest
+import os
+import logging
+import subprocess
+
+from lib389.topologies import topology_st as topo
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+def test_restore_config(topo):
+ """
+ Check that if a dse.ldif and backup are removed, that the server still starts.
+
+ :id: e1c38fa7-30bc-46f2-a934-f8336f387581
+ :setup: Standalone instance
+ :steps:
+ 1. Stop the instance
+ 2. Delete 'dse.ldif'
+ 3. Start the instance
+ :expectedresults:
+ 1. Steps 1 and 2 succeed.
+ 2. Server will succeed to start with restored cfg.
+ """
+ topo.standalone.stop()
+
+ dse_path = topo.standalone.get_config_dir()
+
+ log.info(dse_path)
+
+ for i in ('dse.ldif', 'dse.ldif.startOK'):
+ p = os.path.join(dse_path, i)
+ os.remove(p)
+
+ # This will pass.
+ topo.standalone.start()
+
+def test_removed_config(topo):
+ """
+ Check that if a dse.ldif and backup are removed, that the server
+ exits better than "segfault".
+
+ :id: b45272d1-c197-473e-872f-07257fcb2ec0
+ :setup: Standalone instance
+ :steps:
+ 1. Stop the instance
+ 2. Delete 'dse.ldif', 'dse.ldif.bak', 'dse.ldif.startOK'
+ 3. Start the instance
+ :expectedresults:
+ 1. Steps 1 and 2 succeed.
+ 2. Server will fail to start, but will not crash.
+ """
+ topo.standalone.stop()
+
+ dse_path = topo.standalone.get_config_dir()
+
+ log.info(dse_path)
+
+ for i in ('dse.ldif', 'dse.ldif.bak', 'dse.ldif.startOK'):
+ p = os.path.join(dse_path, i)
+ os.remove(p)
+
+ # We actually can't check the log output, because it can't read dse.ldif,
+ # don't know where to write it yet! All we want is the server fail to
+ # start here, rather than infinite run + segfault.
+ with pytest.raises(subprocess.CalledProcessError):
+ topo.standalone.start()
+
+
diff --git a/ldap/servers/slapd/config.c b/ldap/servers/slapd/config.c
index afe07df84..c8d57e747 100644
--- a/ldap/servers/slapd/config.c
+++ b/ldap/servers/slapd/config.c
@@ -121,14 +121,13 @@ slapd_bootstrap_config(const char *configdir)
"Passed null config directory\n");
return rc; /* Fail */
}
- PR_snprintf(configfile, sizeof(configfile), "%s/%s", configdir,
- CONFIG_FILENAME);
- PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.tmp", configdir,
- CONFIG_FILENAME);
- if ((rc = dse_check_file(configfile, tmpfile)) == 0) {
- PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.bak", configdir,
- CONFIG_FILENAME);
- rc = dse_check_file(configfile, tmpfile);
+ PR_snprintf(configfile, sizeof(configfile), "%s/%s", configdir, CONFIG_FILENAME);
+ PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.bak", configdir, CONFIG_FILENAME);
+ rc = dse_check_file(configfile, tmpfile);
+ if (rc == 0) {
+ /* EVERYTHING IS GOING WRONG, ARRGHHHHHH */
+ slapi_log_err(SLAPI_LOG_ERR, "slapd_bootstrap_config", "No valid configurations can be accessed! You must restore %s from backup!\n", configfile);
+ return 0;
}
if ((rc = PR_GetFileInfo64(configfile, &prfinfo)) != PR_SUCCESS) {
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
index 420248c24..653009f53 100644
--- a/ldap/servers/slapd/dse.c
+++ b/ldap/servers/slapd/dse.c
@@ -609,29 +609,49 @@ dse_check_file(char *filename, char *backupname)
if (PR_GetFileInfo64(filename, &prfinfo) == PR_SUCCESS) {
if (prfinfo.size > 0) {
- return (1);
+ /* File exists and has content. */
+ return 1;
} else {
+ slapi_log_err(SLAPI_LOG_INFO, "dse_check_file",
+ "The config %s has zero length. Attempting restore ... \n", filename, rc);
rc = PR_Delete(filename);
}
+ } else {
+ slapi_log_err(SLAPI_LOG_INFO, "dse_check_file",
+ "The config %s can not be accessed. Attempting restore ... (reason: %d)\n", filename, rc);
}
if (backupname) {
+
+ if (PR_GetFileInfo64(backupname, &prfinfo) != PR_SUCCESS) {
+ slapi_log_err(SLAPI_LOG_INFO, "dse_check_file",
+ "The backup %s can not be accessed. Check it exists and permissions.\n", backupname);
+ return 0;
+ }
+
+ if (prfinfo.size <= 0) {
+ slapi_log_err(SLAPI_LOG_ERR, "dse_check_file",
+ "The backup file %s has zero length, refusing to restore it.\n", backupname);
+ return 0;
+ }
+
rc = PR_Rename(backupname, filename);
- } else {
- return (0);
- }
+ if (rc != PR_SUCCESS) {
+ slapi_log_err(SLAPI_LOG_INFO, "dse_check_file",
+ "The configuration file %s was NOT able to be restored from %s, error %d\n", filename, backupname, rc);
+ return 0;
+ }
- if (PR_GetFileInfo64(filename, &prfinfo) == PR_SUCCESS && prfinfo.size > 0) {
slapi_log_err(SLAPI_LOG_INFO, "dse_check_file",
- "The configuration file %s was restored from backup %s\n", filename, backupname);
- return (1);
+ "The configuration file %s was restored from backup %s\n", filename, backupname);
+ return 1;
+
} else {
- slapi_log_err(SLAPI_LOG_ERR, "dse_check_file",
- "The configuration file %s was not restored from backup %s, error %d\n",
- filename, backupname, rc);
- return (0);
+ slapi_log_err(SLAPI_LOG_INFO, "dse_check_file", "No backup filename provided.\n");
+ return 0;
}
}
+
static int
dse_read_one_file(struct dse *pdse, const char *filename, Slapi_PBlock *pb, int primary_file)
{
--
2.13.6

View file

@ -1,99 +0,0 @@
From bfaf5b56bb1a416c5e058a9925642098c87e0330 Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Thu, 30 Nov 2017 14:06:59 +0100
Subject: [PATCH] Ticket 49474 - sasl allow mechs does not operate correctly
Bug Description: In a fix to sasl allowed mechs, the logic
was not properly configured.
Fix Description: Alter the ids_sasl_supported_mech to be
clearer and simpler in it's design.
https://pagure.io/389-ds-base/issue/49474
Author: wibrown
Review by: tbordaz (Thank you!)
Cherry picked from f75cfbce07b79272a7f1a2e387dc232d45c169f5
---
ldap/servers/slapd/saslbind.c | 49 ++++++++-----------------------------------
1 file changed, 9 insertions(+), 40 deletions(-)
diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c
index 6734c32a7..67da97148 100644
--- a/ldap/servers/slapd/saslbind.c
+++ b/ldap/servers/slapd/saslbind.c
@@ -835,52 +835,21 @@ ids_sasl_listmech(Slapi_PBlock *pb)
static int
ids_sasl_mech_supported(Slapi_PBlock *pb, const char *mech)
{
- int i, ret = 0;
- char **mechs;
- char **allowed_mechs = NULL;
- char *dupstr;
- const char *str;
- int sasl_result = 0;
- Connection *pb_conn = NULL;
-
- slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
- sasl_conn_t *sasl_conn = (sasl_conn_t *)pb_conn->c_sasl_conn;
slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_mech_supported", "=>\n");
- /* sasl_listmech is not thread-safe - caller must lock pb_conn */
- sasl_result = sasl_listmech(sasl_conn,
- NULL, /* username */
- "", ",", "",
- &str, NULL, NULL);
- if (sasl_result != SASL_OK) {
- return 0;
- }
-
- dupstr = slapi_ch_strdup(str);
- mechs = slapi_str2charray(dupstr, ",");
- allowed_mechs = config_get_allowed_sasl_mechs_array();
+ char **allowed_mechs = ids_sasl_listmech(pb);
- for (i = 0; mechs[i] != NULL; i++) {
- if (strcasecmp(mech, mechs[i]) == 0) {
- if (allowed_mechs) {
- if (charray_inlist(allowed_mechs, (char *)mech) == 0) {
- ret = 1;
- }
- break;
- } else {
- ret = 1;
- break;
- }
- }
+ /* 0 indicates "now allowed" */
+ int allowed_mech_present = 0;
+ if (allowed_mechs != NULL) {
+ /* Returns 1 if present and allowed. */
+ allowed_mech_present = charray_inlist(allowed_mechs, (char *)mech);
+ charray_free(allowed_mechs);
}
- charray_free(allowed_mechs);
- charray_free(mechs);
- slapi_ch_free((void **)&dupstr);
-
slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_mech_supported", "<=\n");
- return ret;
+ return allowed_mech_present;
}
/*
@@ -944,7 +913,7 @@ ids_sasl_check_bind(Slapi_PBlock *pb)
* different error code to SASL_NOMECH. Must be called
* while holding the pb_conn lock
*/
- if (!ids_sasl_mech_supported(pb, mech)) {
+ if (ids_sasl_mech_supported(pb, mech) == 0) {
rc = SASL_NOMECH;
goto sasl_check_result;
}
--
2.13.6

View file

@ -1,78 +0,0 @@
From 30fa0e4c993d4a91a90327329b50f02e637fe049 Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Tue, 28 Nov 2017 15:31:25 +0100
Subject: [PATCH] Ticket 49470 - overflow in pblock_get
Bug Description: While getting the connection id we used an int
not a uint64_t
Fix Description: Make the stack size uint64_t instead.
https://pagure.io/389-ds-base/issue/49470
Author: wibrown
Review by: tbordaz
---
ldap/servers/slapd/modify.c | 5 +++--
ldap/servers/slapd/pblock.c | 4 ++--
ldap/servers/slapd/slap.h | 2 +-
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
index 6309975ae..0dcac646b 100644
--- a/ldap/servers/slapd/modify.c
+++ b/ldap/servers/slapd/modify.c
@@ -281,11 +281,12 @@ do_modify(Slapi_PBlock *pb)
if (ignored_some_mods && (0 == smods.num_elements)) {
if (pb_conn->c_isreplication_session) {
- int connid, opid;
+ uint64_t connid;
+ int32_t opid;
slapi_pblock_get(pb, SLAPI_CONN_ID, &connid);
slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opid);
slapi_log_err(SLAPI_LOG_ERR, "do_modify",
- "Rejecting replicated password policy operation(conn=%d op=%d) for "
+ "Rejecting replicated password policy operation(conn=%"PRIu64" op=%d) for "
"entry %s. To allow these changes to be accepted, set passwordIsGlobalPolicy to 'on' in "
"cn=config.\n",
connid, opid, rawdn);
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 8f87de5b5..4514c3ce6 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -412,7 +412,7 @@ slapi_pblock_get(Slapi_PBlock *pblock, int arg, void *value)
"slapi_pblock_get", "Connection is NULL and hence cannot access SLAPI_CONN_ID \n");
return (-1);
}
- (*(PRUint64 *)value) = pblock->pb_conn->c_connid;
+ (*(uint64_t *)value) = pblock->pb_conn->c_connid;
break;
case SLAPI_CONN_DN:
/*
@@ -2538,7 +2538,7 @@ slapi_pblock_set(Slapi_PBlock *pblock, int arg, void *value)
"slapi_pblock_set", "Connection is NULL and hence cannot access SLAPI_CONN_ID \n");
return (-1);
}
- pblock->pb_conn->c_connid = *((PRUint64 *)value);
+ pblock->pb_conn->c_connid = *((uint64_t *)value);
break;
case SLAPI_CONN_DN:
/*
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 44632580a..830944f72 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1604,7 +1604,7 @@ typedef struct conn
int c_gettingber; /* in the middle of ber_get_next */
BerElement *c_currentber; /* ber we're getting */
time_t c_starttime; /* when the connection was opened */
- PRUint64 c_connid; /* id of this connection for stats*/
+ uint64_t c_connid; /* id of this connection for stats*/
PRUint64 c_maxthreadscount; /* # of times a conn hit max threads */
PRUint64 c_maxthreadsblocked; /* # of operations blocked by maxthreads */
int c_opsinitiated; /* # ops initiated/next op id */
--
2.13.6

View file

@ -1,161 +0,0 @@
From 25844922007eea26f78d18171e51be3aa7b5e949 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Wed, 6 Dec 2017 15:14:57 +0100
Subject: [PATCH] Ticket 49471 - heap-buffer-overflow in ss_unescape
Bug Description:
Two problems here
- when searching for wildcard and escape char, ss_unescape assumes the string
is at least 3 chars longs. So memcmp can overflow a shorter string
- while splitting a string into substring pattern, it loops over
wildcard and can overpass the string end
Fix Description:
For the first problem, it checks the string size is long enough to memcmp
a wildcard or an escape
For the second it exits from the loop as soon as the end of the string is reached
https://pagure.io/389-ds-base/issue/49471
Reviewed by: William Brown
Platforms tested: F23
Flag Day: no
Doc impact: no
(cherry picked from commit 5991388ce75fba8885579b769711d57acfd43cd3)
---
dirsrvtests/tests/tickets/ticket49471_test.py | 79 +++++++++++++++++++++++++++
ldap/servers/plugins/collation/orfilter.c | 14 +++--
2 files changed, 87 insertions(+), 6 deletions(-)
create mode 100644 dirsrvtests/tests/tickets/ticket49471_test.py
diff --git a/dirsrvtests/tests/tickets/ticket49471_test.py b/dirsrvtests/tests/tickets/ticket49471_test.py
new file mode 100644
index 000000000..0456a5182
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket49471_test.py
@@ -0,0 +1,79 @@
+import logging
+import pytest
+import os
+import time
+import ldap
+from lib389._constants import *
+from lib389.topologies import topology_st as topo
+from lib389 import Entry
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+
+USER_CN='user_'
+def _user_get_dn(no):
+ cn = '%s%d' % (USER_CN, no)
+ dn = 'cn=%s,ou=people,%s' % (cn, SUFFIX)
+ return (cn, dn)
+
+def add_user(server, no, desc='dummy', sleep=True):
+ (cn, dn) = _user_get_dn(no)
+ log.fatal('Adding user (%s): ' % dn)
+ server.add_s(Entry((dn, {'objectclass': ['top', 'person', 'inetuser', 'userSecurityInformation'],
+ 'cn': [cn],
+ 'description': [desc],
+ 'sn': [cn],
+ 'description': ['add on that host']})))
+ if sleep:
+ time.sleep(2)
+
+def test_ticket49471(topo):
+ """Specify a test case purpose or name here
+
+ :id: 457ab172-9455-4eb2-89a0-150e3de5993f
+ :setup: Fill in set up configuration here
+ :steps:
+ 1. Fill in test case steps here
+ 2. And indent them like this (RST format requirement)
+ :expectedresults:
+ 1. Fill in the result that is expected
+ 2. For each test step
+ """
+
+ # If you need any test suite initialization,
+ # please, write additional fixture for that (including finalizer).
+ # Topology for suites are predefined in lib389/topologies.py.
+
+ # If you need host, port or any other data about instance,
+ # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
+
+ S1 = topo.standalone
+ add_user(S1, 1)
+
+ Filter = "(description:2.16.840.1.113730.3.3.2.1.1.6:=\*on\*)"
+ ents = S1.search_s(SUFFIX, ldap.SCOPE_SUBTREE, Filter)
+ assert len(ents) == 1
+
+ #
+ # The following is for the test 49491
+ # skipped here else it crashes in ASAN
+ #Filter = "(description:2.16.840.1.113730.3.3.2.1.1.6:=\*host)"
+ #ents = S1.search_s(SUFFIX, ldap.SCOPE_SUBTREE, Filter)
+ #assert len(ents) == 1
+
+ if DEBUGGING:
+ # Add debugging steps(if any)...
+ pass
+
+
+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/collation/orfilter.c b/ldap/servers/plugins/collation/orfilter.c
index 5a2d8a0ab..a98d90219 100644
--- a/ldap/servers/plugins/collation/orfilter.c
+++ b/ldap/servers/plugins/collation/orfilter.c
@@ -313,12 +313,12 @@ ss_unescape(struct berval *val)
char *t = s;
char *limit = s + val->bv_len;
while (s < limit) {
- if (!memcmp(s, "\\2a", 3) ||
- !memcmp(s, "\\2A", 3)) {
+ if (((limit - s) >= 3) &&
+ (!memcmp(s, "\\2a", 3) || !memcmp(s, "\\2A", 3))) {
*t++ = WILDCARD;
s += 3;
- } else if (!memcmp(s, "\\5c", 3) ||
- !memcmp(s, "\\5C", 3)) {
+ } else if ((limit - s) >= 3 &&
+ (!memcmp(s, "\\5c", 3) || !memcmp(s, "\\5C", 3))) {
*t++ = '\\';
s += 3;
} else {
@@ -409,13 +409,15 @@ ss_filter_values(struct berval *pattern, int *query_op)
switch (*p) {
case WILDCARD:
result[n++] = ss_filter_value(s, p - s, &val);
- while (++p != plimit && *p == WILDCARD)
- ;
+ while (p != plimit && *p == WILDCARD) p++;
s = p;
break;
default:
break;
}
+ if (p >= plimit) {
+ break;
+ }
}
if (p != s || s == plimit) {
result[n++] = ss_filter_value(s, p - s, &val);
--
2.13.6

View file

@ -1,34 +0,0 @@
From 189c3ce4d5b5c9341a60d4056dad26133d9607ca Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Fri, 17 Nov 2017 11:43:36 +1000
Subject: [PATCH] Ticket 49298 - fix complier warn
Bug Description: Extra argument to error log in dse.c
Fix Description: Remove extra argument.
https://pagure.io/389-ds-base/issue/49298
Author: wibrown
Review by: oneline rule.
---
ldap/servers/slapd/dse.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
index 653009f53..662e91aa7 100644
--- a/ldap/servers/slapd/dse.c
+++ b/ldap/servers/slapd/dse.c
@@ -613,7 +613,7 @@ dse_check_file(char *filename, char *backupname)
return 1;
} else {
slapi_log_err(SLAPI_LOG_INFO, "dse_check_file",
- "The config %s has zero length. Attempting restore ... \n", filename, rc);
+ "The config %s has zero length. Attempting restore ... \n", filename);
rc = PR_Delete(filename);
}
} else {
--
2.13.6

View file

@ -1,153 +0,0 @@
From 2c56e7dc08a41fc1dfa6a79213e93686f553847c Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Mon, 11 Dec 2017 15:48:24 +0100
Subject: [PATCH] Ticket 49495 - Fix memory management is vattr.
Bug Description: During the fix for
https://pagure.io/389-ds-base/issue/49436 a issue was exposed
in how registration of attributes to cos work. With the change
to handle -> attr link, this exposed that cos treats each attribute
and template pair as a new type for the handle. As aresult, this
caused the sp_list to create a long linked list of M*N entries
for each attr - template value. Obviously, this is extremely
slow to traverse during a search!
Fix Description: Undo part of the SLL next change and convert
to reference counting. The issue remains that there is a defect
in how cos handles attribute registration, but this can not be
resolved without a significant rearchitecture of the code
related to virtual attributes.
https://pagure.io/389-ds-base/issue/49495
Author: wibrown
Review by: tbordaz, lkrispen (Thanks!)
---
ldap/servers/plugins/cos/cos_cache.c | 28 +++++++++++-----------------
ldap/servers/slapd/vattr.c | 23 +++++++++++++++++++++--
2 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
index 662dace35..3b3c05783 100644
--- a/ldap/servers/plugins/cos/cos_cache.c
+++ b/ldap/servers/plugins/cos/cos_cache.c
@@ -275,7 +275,7 @@ static Slapi_Mutex *start_lock;
static Slapi_Mutex *stop_lock;
static Slapi_CondVar *something_changed = NULL;
static Slapi_CondVar *start_cond = NULL;
-
+static vattr_sp_handle *vattr_handle = NULL;
/*
cos_cache_init
@@ -314,6 +314,15 @@ cos_cache_init(void)
goto out;
}
+ if (slapi_vattrspi_register((vattr_sp_handle **)&vattr_handle,
+ cos_cache_vattr_get,
+ cos_cache_vattr_compare,
+ cos_cache_vattr_types) != 0) {
+ slapi_log_err(SLAPI_LOG_ERR, COS_PLUGIN_SUBSYSTEM, "cos_cache_init - Cannot register as service provider\n");
+ ret = -1;
+ goto out;
+ }
+
/* grab the views interface */
if (slapi_apib_get_interface(Views_v1_0_GUID, &views_api)) {
/* lets be tolerant if views is disabled */
@@ -847,22 +856,7 @@ cos_dn_defs_cb(Slapi_Entry *e, void *callback_data)
dnVals[valIndex]->bv_val);
}
- /*
- * Each SP_handle is associated to one and only one vattr.
- * We could consider making this a single function rather
- * than the double-call.
- */
-
- vattr_sp_handle *vattr_handle = NULL;
-
- if (slapi_vattrspi_register((vattr_sp_handle **)&vattr_handle,
- cos_cache_vattr_get,
- cos_cache_vattr_compare,
- cos_cache_vattr_types) != 0) {
- slapi_log_err(SLAPI_LOG_ERR, COS_PLUGIN_SUBSYSTEM, "cos_cache_init - Cannot register as service provider for %s\n", dnVals[valIndex]->bv_val);
- } else {
- slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle, dnVals[valIndex]->bv_val, NULL, NULL);
- }
+ slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle, dnVals[valIndex]->bv_val, NULL, NULL);
} /* if(attrType is cosAttribute) */
diff --git a/ldap/servers/slapd/vattr.c b/ldap/servers/slapd/vattr.c
index 432946c79..13e527188 100644
--- a/ldap/servers/slapd/vattr.c
+++ b/ldap/servers/slapd/vattr.c
@@ -1544,6 +1544,7 @@ struct _vattr_sp_handle
vattr_sp *sp;
struct _vattr_sp_handle *next; /* So we can link them together in the map */
void *hint; /* Hint to the SP */
+ uint64_t rc;
};
/* Calls made by Service Providers */
@@ -1770,7 +1771,7 @@ is a separate thing in the insterests of stability.
*/
-#define VARRT_MAP_HASHTABLE_SIZE 10
+#define VARRT_MAP_HASHTABLE_SIZE 32
/* Attribute map oject */
/* Needs to contain: a linked list of pointers to provider handles handles,
@@ -1867,7 +1868,10 @@ vattr_map_entry_free(vattr_map_entry *vae)
vattr_sp_handle *list_entry = vae->sp_list;
while (list_entry != NULL) {
vattr_sp_handle *next_entry = list_entry->next;
- slapi_ch_free((void **)&list_entry);
+ if (slapi_atomic_decr_64(&(list_entry->rc), __ATOMIC_RELAXED) == 0) {
+ /* Only free on RC 0 */
+ slapi_ch_free((void **)&list_entry);
+ }
list_entry = next_entry;
}
slapi_ch_free_string(&(vae->type_name));
@@ -2280,6 +2284,17 @@ to handle the calls on it, but return nothing */
*
* Better idea, is that regattr should just take the fn pointers
* and callers never *see* the sp_handle structure at all.
+ *
+ * This leaves us with some quirks today. First: if you have plugin A
+ * and B, A registers attr 1 and B 1 and 2, it's possible that if you
+ * register A1 first, then B1, you have B->A in next. Then when you
+ * register B2, because we take 0==result from map_lookup, we add sp
+ * "as is" to the map. This means that B2 now has the same next to A1
+ * handle. This won't add a bug, because A1 won't be able to service the
+ * attr, but it could cause some head scratching ...
+ *
+ * Again, to fix this, the whole vattr external interface needs a
+ * redesign ... :(
*/
int
@@ -2304,11 +2319,15 @@ vattr_map_sp_insert(char *type_to_add, vattr_sp_handle *sp, void *hint)
if (found) {
return 0;
}
+ /* Increase the ref count of the sphandle */
+ slapi_atomic_incr_64(&(sp->rc), __ATOMIC_RELAXED);
/* We insert the SP handle into the linked list at the head */
sp->next = map_entry->sp_list;
map_entry->sp_list = sp;
} else {
/* If not, add it */
+ /* Claim a reference on the sp ... */
+ slapi_atomic_incr_64(&(sp->rc), __ATOMIC_RELAXED);
map_entry = vattr_map_entry_new(type_to_add, sp, hint);
if (NULL == map_entry) {
return ENOMEM;
--
2.13.6

View file

@ -1,215 +0,0 @@
From 0c1fbfaf77d6f7b2a6628deaf309bbe1c3e7a8e8 Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Tue, 28 Nov 2017 13:39:19 +0100
Subject: [PATCH] Ticket 48184 - close connections at shutdown cleanly.
Bug Description: During shutdown we would not close connections.
In the past this may have just been an annoyance, but now with the way
nunc-stans works, io events can still trigger on open xeisting connectinos
during shutdown.
Fix Description: Close connections during shutdown rather than
leaving them alive.
https://pagure.io/389-ds-base/issue/48184
Author: wibrown
Review by: lkrispen, vashirov (Thank you!)
---
ldap/servers/slapd/conntable.c | 13 +++++++
ldap/servers/slapd/daemon.c | 77 ++++++++++++++++++++++++++----------------
ldap/servers/slapd/fe.h | 1 +
ldap/servers/slapd/slap.h | 1 +
4 files changed, 63 insertions(+), 29 deletions(-)
diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c
index 7c57b47cd..f2f763dfa 100644
--- a/ldap/servers/slapd/conntable.c
+++ b/ldap/servers/slapd/conntable.c
@@ -91,6 +91,19 @@ connection_table_abandon_all_operations(Connection_Table *ct)
}
}
+void
+connection_table_disconnect_all(Connection_Table *ct)
+{
+ for (size_t i = 0; i < ct->size; i++) {
+ if (ct->c[i].c_mutex) {
+ Connection *c = &(ct->c[i]);
+ PR_EnterMonitor(c->c_mutex);
+ disconnect_server_nomutex(c, c->c_connid, -1, SLAPD_DISCONNECT_ABORT, ECANCELED);
+ PR_ExitMonitor(c->c_mutex);
+ }
+ }
+}
+
/* Given a file descriptor for a socket, this function will return
* a slot in the connection table to use.
*
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 4e0466ab3..c245a4d4e 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1176,6 +1176,30 @@ slapd_daemon(daemon_ports_t *ports, ns_thrpool_t *tp)
housekeeping_stop(); /* Run this after op_thread_cleanup() logged sth */
disk_monitoring_stop();
+ /*
+ * Now that they are abandonded, we need to mark them as done.
+ * In NS while it's safe to allow excess jobs to be cleaned by
+ * by the walk and ns_job_done of remaining queued events, the
+ * issue is that if we allow something to live past this point
+ * the CT is freed from underneath, and bad things happen (tm).
+ *
+ * NOTE: We do this after we stop psearch, because there could
+ * be a race between flagging the psearch done, and users still
+ * try to send on the connection. Similar with op_threads.
+ */
+ connection_table_disconnect_all(the_connection_table);
+
+ /*
+ * WARNING: Normally we should close the tp in main
+ * but because of issues in the current connection design
+ * we need to close it here to guarantee events won't fire!
+ *
+ * All the connection close jobs "should" complete before
+ * shutdown at least.
+ */
+ ns_thrpool_shutdown(tp);
+ ns_thrpool_wait(tp);
+
threads = g_get_active_threadcnt();
if (threads > 0) {
slapi_log_err(SLAPI_LOG_INFO, "slapd_daemon",
@@ -1628,23 +1652,18 @@ ns_handle_closure(struct ns_job_t *job)
Connection *c = (Connection *)ns_job_get_data(job);
int do_yield = 0;
-/* this function must be called from the event loop thread */
-#ifdef DEBUG
- PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
-#else
- /* This doesn't actually confirm it's in the event loop thread, but it's a start */
- if (NS_JOB_IS_THREAD(ns_job_get_type(job)) != 0) {
- slapi_log_err(SLAPI_LOG_ERR, "ns_handle_closure", "Attempt to close outside of event loop thread %" PRIu64 " for fd=%d\n",
- c->c_connid, c->c_sd);
- return;
- }
-#endif
PR_EnterMonitor(c->c_mutex);
+ /* Assert we really have the right job state. */
+ PR_ASSERT(job == c->c_job);
+
connection_release_nolock_ext(c, 1); /* release ref acquired for event framework */
PR_ASSERT(c->c_ns_close_jobs == 1); /* should be exactly 1 active close job - this one */
c->c_ns_close_jobs--; /* this job is processing closure */
+ /* Because handle closure will add a new job, we need to detach our current one. */
+ c->c_job = NULL;
do_yield = ns_handle_closure_nomutex(c);
PR_ExitMonitor(c->c_mutex);
+ /* Remove this task now. */
ns_job_done(job);
if (do_yield) {
/* closure not done - another reference still outstanding */
@@ -1667,6 +1686,14 @@ ns_connection_post_io_or_closing(Connection *conn)
return;
}
+ /*
+ * Cancel any existing ns jobs we have registered.
+ */
+ if (conn->c_job != NULL) {
+ ns_job_done(conn->c_job);
+ conn->c_job = NULL;
+ }
+
if (CONN_NEEDS_CLOSING(conn)) {
/* there should only ever be 0 or 1 active closure jobs */
PR_ASSERT((conn->c_ns_close_jobs == 0) || (conn->c_ns_close_jobs == 1));
@@ -1676,13 +1703,10 @@ ns_connection_post_io_or_closing(Connection *conn)
conn->c_connid, conn->c_sd);
return;
} else {
- /* just make sure we schedule the event to be closed in a timely manner */
- tv.tv_sec = 0;
- tv.tv_usec = slapd_wakeup_timer * 1000;
conn->c_ns_close_jobs++; /* now 1 active closure job */
connection_acquire_nolock_ext(conn, 1 /* allow acquire even when closing */); /* event framework now has a reference */
- ns_result_t job_result = ns_add_timeout_job(conn->c_tp, &tv, NS_JOB_TIMER,
- ns_handle_closure, conn, NULL);
+ /* Close the job asynchronously. Why? */
+ ns_result_t job_result = ns_add_job(conn->c_tp, NS_JOB_TIMER, ns_handle_closure, conn, &(conn->c_job));
if (job_result != NS_SUCCESS) {
if (job_result == NS_SHUTDOWN) {
slapi_log_err(SLAPI_LOG_INFO, "ns_connection_post_io_or_closing", "post closure job "
@@ -1726,7 +1750,7 @@ ns_connection_post_io_or_closing(Connection *conn)
#endif
ns_result_t job_result = ns_add_io_timeout_job(conn->c_tp, conn->c_prfd, &tv,
NS_JOB_READ | NS_JOB_PRESERVE_FD,
- ns_handle_pr_read_ready, conn, NULL);
+ ns_handle_pr_read_ready, conn, &(conn->c_job));
if (job_result != NS_SUCCESS) {
if (job_result == NS_SHUTDOWN) {
slapi_log_err(SLAPI_LOG_INFO, "ns_connection_post_io_or_closing", "post I/O job for "
@@ -1755,19 +1779,13 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
int maxthreads = config_get_maxthreadsperconn();
Connection *c = (Connection *)ns_job_get_data(job);
-/* this function must be called from the event loop thread */
-#ifdef DEBUG
- PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
-#else
- /* This doesn't actually confirm it's in the event loop thread, but it's a start */
- if (NS_JOB_IS_THREAD(ns_job_get_type(job)) != 0) {
- slapi_log_err(SLAPI_LOG_ERR, "ns_handle_pr_read_ready", "Attempt to handle read ready outside of event loop thread %" PRIu64 " for fd=%d\n",
- c->c_connid, c->c_sd);
- return;
- }
-#endif
-
PR_EnterMonitor(c->c_mutex);
+ /* Assert we really have the right job state. */
+ PR_ASSERT(job == c->c_job);
+
+ /* On all code paths we remove the job, so set it null now */
+ c->c_job = NULL;
+
slapi_log_err(SLAPI_LOG_CONNS, "ns_handle_pr_read_ready", "activity on conn %" PRIu64 " for fd=%d\n",
c->c_connid, c->c_sd);
/* if we were called due to some i/o event, see what the state of the socket is */
@@ -1826,6 +1844,7 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
slapi_log_err(SLAPI_LOG_CONNS, "ns_handle_pr_read_ready", "queued conn %" PRIu64 " for fd=%d\n",
c->c_connid, c->c_sd);
}
+ /* Since we call done on the job, we need to remove it here. */
PR_ExitMonitor(c->c_mutex);
ns_job_done(job);
return;
diff --git a/ldap/servers/slapd/fe.h b/ldap/servers/slapd/fe.h
index 4d25a9fb8..f47bb6145 100644
--- a/ldap/servers/slapd/fe.h
+++ b/ldap/servers/slapd/fe.h
@@ -100,6 +100,7 @@ extern Connection_Table *the_connection_table; /* JCM - Exported from globals.c
Connection_Table *connection_table_new(int table_size);
void connection_table_free(Connection_Table *ct);
void connection_table_abandon_all_operations(Connection_Table *ct);
+void connection_table_disconnect_all(Connection_Table *ct);
Connection *connection_table_get_connection(Connection_Table *ct, int sd);
int connection_table_move_connection_out_of_active_list(Connection_Table *ct, Connection *c);
void connection_table_move_connection_on_to_active_list(Connection_Table *ct, Connection *c);
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 830944f72..08754d8fb 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1644,6 +1644,7 @@ typedef struct conn
void *c_io_layer_cb_data; /* callback data */
struct connection_table *c_ct; /* connection table that this connection belongs to */
ns_thrpool_t *c_tp; /* thread pool for this connection */
+ struct ns_job_t *c_job; /* If it exists, the current ns_job_t */
int c_ns_close_jobs; /* number of current close jobs */
char *c_ipaddr; /* ip address str - used by monitor */
} Connection;
--
2.13.6

View file

@ -1,239 +0,0 @@
From 8d79d7c81157e77f4da595a723a6ed10a8e9789b Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Thu, 11 Jan 2018 18:52:43 +0100
Subject: [PATCH] Ticket 49509 - Indexing of internationalized matching rules
is failing
Bug Description:
Indexing of the internationalized matching rules tests if a
matching rule indexer handle or not a given OID.
A side effect of https://pagure.io/389-ds-base/issue/49097 is that
the returned indexing callbacks are lost.
Indeed, the indexing callbacks (and potentially others fields) were
stored in the temporary pblock that was memcpy to the provided
pblock in case of success
Fix Description:
The fix basically restores the previous behavior but do not
memcpy pblock. It read/store the pblock fields that are
inputs/outputs of slapi_mr_indexer_create.
https://pagure.io/389-ds-base/issue/49509
Reviewed by: Ludwig Krispenz
Platforms tested: F23
Flag Day: no
Doc impact: no
---
ldap/servers/slapd/plugin_mr.c | 148 ++++++++++++++++++++++++++++-------------
1 file changed, 103 insertions(+), 45 deletions(-)
diff --git a/ldap/servers/slapd/plugin_mr.c b/ldap/servers/slapd/plugin_mr.c
index bd2baff6c..ca4fe00e1 100644
--- a/ldap/servers/slapd/plugin_mr.c
+++ b/ldap/servers/slapd/plugin_mr.c
@@ -143,6 +143,82 @@ plugin_mr_bind(char *oid, struct slapdplugin *plugin)
slapi_log_err(SLAPI_LOG_FILTER, "plugin_mr_bind", "<=\n");
}
+void
+mr_indexer_init_pb(Slapi_PBlock* src_pb, Slapi_PBlock* dst_pb)
+{
+ char* oid;
+ char *type;
+ uint32_t usage;
+ void *object;
+ IFP destroyFn;
+ IFP indexFn, indexSvFn;
+
+ /* matching rule plugin arguments */
+ slapi_pblock_get(src_pb, SLAPI_PLUGIN_MR_OID, &oid);
+ slapi_pblock_get(src_pb, SLAPI_PLUGIN_MR_TYPE, &type);
+ slapi_pblock_get(src_pb, SLAPI_PLUGIN_MR_USAGE, &usage);
+
+ slapi_pblock_set(dst_pb, SLAPI_PLUGIN_MR_OID, oid);
+ slapi_pblock_set(dst_pb, SLAPI_PLUGIN_MR_TYPE, type);
+ slapi_pblock_set(dst_pb, SLAPI_PLUGIN_MR_USAGE, &usage);
+
+ /* matching rule plugin functions */
+ slapi_pblock_get(src_pb, SLAPI_PLUGIN_MR_INDEX_FN, &indexFn);
+ slapi_pblock_get(src_pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, &indexSvFn);
+
+ slapi_pblock_set(dst_pb, SLAPI_PLUGIN_MR_INDEX_FN, indexFn);
+ slapi_pblock_set(dst_pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, indexSvFn);
+
+ /* common */
+ slapi_pblock_get(src_pb, SLAPI_PLUGIN_OBJECT, &object);
+ slapi_pblock_get(src_pb, SLAPI_PLUGIN_DESTROY_FN, &destroyFn);
+
+ slapi_pblock_set(dst_pb, SLAPI_PLUGIN_OBJECT, object);
+ slapi_pblock_set(dst_pb, SLAPI_PLUGIN_DESTROY_FN, destroyFn);
+
+
+}
+
+/*
+ * Retrieves the matching rule plugin able to index/sort the provided OID/type
+ *
+ * The Matching rules able to index/sort a given OID are stored in a global list: global_mr_oids
+ *
+ * The retrieval is done in 3 phases:
+ * - It first searches (in global_mr_oids) for the already bound OID->MR
+ * - Else, look first in old style MR plugin
+ * for each registered 'syntax' and 'matchingrule' plugins having a
+ * SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, it binds (plugin_mr_bind) the first
+ * plugin that support the OID
+ * - Else, look in new style MR plugin
+ * for each registered 'syntax' and 'matchingrule' plugins, it binds (plugin_mr_bind) the first
+ * plugin that contains OID in its plg_mr_names
+ *
+ * Inputs:
+ * SLAPI_PLUGIN_MR_OID
+ * should contain the OID of the matching rule that you want used for indexing or sorting.
+ * SLAPI_PLUGIN_MR_TYPE
+ * should contain the attribute type that you want used for indexing or sorting.
+ * SLAPI_PLUGIN_MR_USAGE
+ * should specify if the indexer will be used for indexing (SLAPI_PLUGIN_MR_USAGE_INDEX)
+ * or for sorting (SLAPI_PLUGIN_MR_USAGE_SORT)
+ *
+ *
+ * Output:
+ *
+ * SLAPI_PLUGIN_MR_OID
+ * contain the OFFICIAL OID of the matching rule that you want used for indexing or sorting.
+ * SLAPI_PLUGIN_MR_INDEX_FN
+ * specifies the indexer function responsible for indexing or sorting of struct berval **
+ * SLAPI_PLUGIN_MR_INDEX_SV_FN
+ * specifies the indexer function responsible for indexing or sorting of Slapi_Value **
+ * SLAPI_PLUGIN_OBJECT
+ * contain any information that you want passed to the indexer function.
+ * SLAPI_PLUGIN_DESTROY_FN
+ * specifies the function responsible for freeing any memory allocated by this indexer factory function.
+ * For example, memory allocated for a structure that you pass to the indexer function using SLAPI_PLUGIN_OBJECT.
+ *
+ */
int /* an LDAP error code, hopefully LDAP_SUCCESS */
slapi_mr_indexer_create(Slapi_PBlock *opb)
{
@@ -152,28 +228,33 @@ int /* an LDAP error code, hopefully LDAP_SUCCESS */
IFP createFn = NULL;
struct slapdplugin *mrp = plugin_mr_find_registered(oid);
if (mrp != NULL) {
+ /* Great the matching OID -> MR plugin was already found, just reuse it */
if (!(rc = slapi_pblock_set(opb, SLAPI_PLUGIN, mrp)) &&
!(rc = slapi_pblock_get(opb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, &createFn)) &&
createFn != NULL) {
rc = createFn(opb);
}
} else {
- /* call each plugin, until one is able to handle this request. */
+ /* We need to find in the MR plugins list, the MR plugin that will be able to handle OID
+ *
+ * It can be "old style" MR plugin (i.e. collation) that define indexer
+ *
+ * It can be "now style" MR plugin that contain OID string in 'plg_mr_names'
+ * (ie. ces, cis, bin...) where plg_mr_names is defined in 'mr_plugin_table' in each file
+ * ces.c, cis.c...
+ * New style MR plugin have NULL indexer create function but rather use a default indexer
+ */
+
+ /* Look for a old syntax-style mr plugin
+ * call each plugin, until one is able to handle this request.
+ */
rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
- // We need to get the type and usage from the caller.
- char *type;
- uint32_t usage;
- slapi_pblock_get(opb, SLAPI_PLUGIN_MR_TYPE, &type);
- slapi_pblock_get(opb, SLAPI_PLUGIN_MR_USAGE, &usage);
+
for (mrp = get_plugin_list(PLUGIN_LIST_MATCHINGRULE); mrp != NULL; mrp = mrp->plg_next) {
Slapi_PBlock *pb = slapi_pblock_new();
+ mr_indexer_init_pb(opb, pb);
slapi_pblock_set(pb, SLAPI_PLUGIN, mrp);
- /* From filtercmp.c and matchrule.c, these are the values we need to set. into pb */
- slapi_pblock_set(pb, SLAPI_PLUGIN_MR_OID, oid);
- slapi_pblock_set(pb, SLAPI_PLUGIN_MR_TYPE, type);
- slapi_pblock_set(pb, SLAPI_PLUGIN_MR_USAGE, &usage);
-
/* This is associated with the pb_plugin struct, so it comes with mrp */
if (slapi_pblock_get(pb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, &createFn)) {
/* plugin not a matchingrule type */
@@ -185,14 +266,11 @@ int /* an LDAP error code, hopefully LDAP_SUCCESS */
IFP indexFn = NULL;
IFP indexSvFn = NULL;
/* These however, are in the pblock direct, so we need to copy them. */
- slapi_pblock_get(opb, SLAPI_PLUGIN_MR_INDEX_FN, &indexFn);
- slapi_pblock_get(opb, SLAPI_PLUGIN_MR_INDEX_SV_FN, &indexSvFn);
- slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_FN, indexFn);
- slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, indexSvFn);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_MR_INDEX_FN, &indexFn);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, &indexSvFn);
if (indexFn || indexSvFn) {
/* Success: this plugin can handle it. */
- /* call create on the opb? */
- createFn(opb);
+ mr_indexer_init_pb(pb, opb);
plugin_mr_bind(oid, mrp); /* for future reference */
rc = 0; /* success */
slapi_pblock_destroy(pb);
@@ -205,37 +283,12 @@ int /* an LDAP error code, hopefully LDAP_SUCCESS */
/* look for a new syntax-style mr plugin */
struct slapdplugin *pi = plugin_mr_find(oid);
if (pi) {
- Slapi_PBlock *pb = slapi_pblock_new();
- slapi_pblock_set(pb, SLAPI_PLUGIN_MR_OID, oid);
- slapi_pblock_set(pb, SLAPI_PLUGIN_MR_TYPE, type);
- slapi_pblock_set(pb, SLAPI_PLUGIN_MR_USAGE, &usage);
- slapi_pblock_set(pb, SLAPI_PLUGIN, pi);
- rc = default_mr_indexer_create(pb);
+ slapi_pblock_set(opb, SLAPI_PLUGIN, pi);
+ rc = default_mr_indexer_create(opb);
if (!rc) {
- /* On success, copy the needed values in. These are added by default_mr_indexer_create */
- void *pb_object = NULL;
- IFP destroy_fn = NULL;
- IFP index_fn = NULL;
- IFP index_sv_fn = NULL;
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &pb_object);
- slapi_pblock_get(pb, SLAPI_PLUGIN_DESTROY_FN, &destroy_fn);
- slapi_pblock_get(pb, SLAPI_PLUGIN_MR_INDEX_FN, &index_fn);
- slapi_pblock_get(pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, &index_sv_fn);
-
- /* SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, and SLAPI_PLUGIN_MR_FILTER_CREATE_FN, are part of pb_plugin */
- slapi_pblock_set(opb, SLAPI_PLUGIN, pi);
- slapi_pblock_set(opb, SLAPI_PLUGIN_MR_OID, oid);
- slapi_pblock_set(opb, SLAPI_PLUGIN_MR_TYPE, type);
- slapi_pblock_set(opb, SLAPI_PLUGIN_MR_USAGE, &usage);
- slapi_pblock_set(opb, SLAPI_PLUGIN_OBJECT, pb_object);
- slapi_pblock_set(opb, SLAPI_PLUGIN_DESTROY_FN, destroy_fn);
- slapi_pblock_set(opb, SLAPI_PLUGIN_MR_INDEX_FN, index_fn);
- slapi_pblock_set(opb, SLAPI_PLUGIN_MR_INDEX_SV_FN, index_sv_fn);
-
plugin_mr_bind(oid, pi); /* for future reference */
}
- slapi_pblock_destroy(pb);
+ slapi_pblock_set(opb, SLAPI_PLUGIN, NULL);
}
}
}
@@ -706,6 +759,11 @@ default_mr_indexer_create(Slapi_PBlock *pb)
slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_FN, mr_wrap_mr_index_fn);
slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, mr_wrap_mr_index_sv_fn);
slapi_pblock_set(pb, SLAPI_PLUGIN_DESTROY_FN, default_mr_indexer_destroy);
+
+ /* Note the two following setting are in the slapdplugin struct SLAPI_PLUGIN
+ * so they are not really output of the function but will just
+ * be stored in the bound (OID <--> plugin) list (plugin_mr_find_registered/plugin_mr_bind)
+ */
slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, default_mr_indexer_create);
slapi_pblock_set(pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN, default_mr_filter_create);
rc = 0;
--
2.13.6

View file

@ -1,155 +0,0 @@
From a7a0db402b32dcec7fc93bcbef42174163ae9c12 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Tue, 12 Dec 2017 12:46:37 +0100
Subject: [PATCH] Ticket 49493 - heap use after free in csn_as_string
Bug: If write_changlog_and_ruv failed teh csn pending list was not properly
cleand and references to the prim csn were kept, but the prim csn was reset
Fix: check the return code for the mmr postop plugin and aset error codes properly
that will triger cancel_opcsn
Reviewed by: Thierry, thanks
Tested by: Viktor, thanks
---
ldap/servers/slapd/back-ldbm/ldbm_add.c | 22 +---------------------
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 4 ++++
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 4 ++++
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 4 ++++
ldap/servers/slapd/back-ldbm/misc.c | 18 ++++++++++++++++++
ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 1 +
6 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index b7e17ad50..f29945a7e 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -22,7 +22,6 @@ extern char *hassubordinates;
static void delete_update_entrydn_operational_attributes(struct backentry *ep);
-static int set_error(Slapi_PBlock *pb, int retval, int ldap_result_code, char **ldap_result_message);
#define ADD_SET_ERROR(rc, error, count) \
{ \
(rc) = (error); \
@@ -1201,7 +1200,7 @@ ldbm_back_add(Slapi_PBlock *pb)
retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_ADD_FN);
if (retval) {
- set_error(pb, retval, ldap_result_code, &ldap_result_message);
+ ldbm_set_error(pb, retval, &ldap_result_code, &ldap_result_message);
goto error_return;
}
@@ -1471,22 +1470,3 @@ delete_update_entrydn_operational_attributes(struct backentry *ep)
slapi_entry_attr_delete(ep->ep_entry, LDBM_ENTRYDN_STR);
}
-static int
-set_error(Slapi_PBlock *pb, int retval, int ldap_result_code, char **ldap_result_message)
-{
- int opreturn = 0;
- if (!ldap_result_code) {
- slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
- }
- if (!ldap_result_code) {
- ldap_result_code = LDAP_OPERATIONS_ERROR;
- slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
- }
- slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
- if (!opreturn) {
- slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval);
- }
- slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
-
- return opreturn;
-}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index db463c18c..be0db1bd0 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -1276,6 +1276,10 @@ replace_entry:
}
retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN);
+ if (retval) {
+ ldbm_set_error(pb, retval, &ldap_result_code, &ldap_result_message);
+ goto error_return;
+ }
commit_return:
/* Release SERIAL LOCK */
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index 7ee796fd2..cc4319e5f 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -867,6 +867,10 @@ ldbm_back_modify(Slapi_PBlock *pb)
goto error_return;
}
retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN);
+ if (retval) {
+ ldbm_set_error(pb, retval, &ldap_result_code, &ldap_result_message);
+ goto error_return;
+ }
/* Release SERIAL LOCK */
retval = dblayer_txn_commit(be, &txn);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index 2c0cb074e..93fb77dc9 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -1211,6 +1211,10 @@ ldbm_back_modrdn(Slapi_PBlock *pb)
goto error_return;
}
retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN);
+ if (retval) {
+ ldbm_set_error(pb, retval, &ldap_result_code, &ldap_result_message);
+ goto error_return;
+ }
/* Release SERIAL LOCK */
retval = dblayer_txn_commit(be, &txn);
diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c
index df1afdfb1..c52e58a4a 100644
--- a/ldap/servers/slapd/back-ldbm/misc.c
+++ b/ldap/servers/slapd/back-ldbm/misc.c
@@ -16,6 +16,24 @@
#include "back-ldbm.h"
+void
+ldbm_set_error(Slapi_PBlock *pb, int retval, int *ldap_result_code, char **ldap_result_message)
+{
+ int opreturn = 0;
+ if (!(*ldap_result_code)) {
+ slapi_pblock_get(pb, SLAPI_RESULT_CODE, ldap_result_code);
+ }
+ if (!(*ldap_result_code)) {
+ *ldap_result_code = LDAP_OPERATIONS_ERROR;
+ slapi_pblock_set(pb, SLAPI_RESULT_CODE, ldap_result_code);
+ }
+ slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
+ if (!opreturn) {
+ slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, *ldap_result_code ? ldap_result_code : &retval);
+ }
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, ldap_result_message);
+}
+
/* Takes a return code supposed to be errno or from lidb
which we don't expect to see and prints a handy log message */
void
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
index 0cee3df62..da3eef18b 100644
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -379,6 +379,7 @@ int ldbm_txn_ruv_modify_context(Slapi_PBlock *pb, modify_context *mc);
int get_value_from_string(const char *string, char *type, char **value);
int get_values_from_string(const char *string, char *type, char ***valuearray);
void normalize_dir(char *dir);
+void ldbm_set_error(Slapi_PBlock *pb, int retval, int *ldap_result_code, char **ldap_result_message);
/*
* nextid.c
--
2.13.6

View file

@ -1,133 +0,0 @@
From a85f64d2c4fa2718748a205d4ae0ebab47513199 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 8 Jan 2018 11:34:02 -0500
Subject: [PATCH] Ticket 49524 - Password policy: minimum token length fails
when the token length is equal to attribute length
Bug Description: The token checking breaks when the password is the
exact value of the entry attribute.
Fix Description: Remove the "equal" part of the string comparisons.
https://pagure.io/389-ds-base/issue/49524
Reviewed by: firstyear & spichugi(Thanks!!)
(cherry picked from commit 790be09fc434d394239bf2486d01f212b36cf0e3)
---
.../tests/suites/password/pwdPolicy_token_test.py | 75 ++++++++++++++++++++++
ldap/servers/slapd/pw.c | 2 +-
ldap/servers/slapd/utf8.c | 2 +-
3 files changed, 77 insertions(+), 2 deletions(-)
create mode 100644 dirsrvtests/tests/suites/password/pwdPolicy_token_test.py
diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_token_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_token_test.py
new file mode 100644
index 000000000..7a4de9c85
--- /dev/null
+++ b/dirsrvtests/tests/suites/password/pwdPolicy_token_test.py
@@ -0,0 +1,75 @@
+import logging
+import pytest
+import os
+import time
+import ldap
+from lib389._constants import *
+from lib389.idm.user import UserAccounts
+from lib389.topologies import topology_st as topo
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+USER_DN = 'uid=Test_user1,ou=People,dc=example,dc=com'
+TOKEN = 'test_user1'
+
+user_properties = {
+ 'uid': 'Test_user1',
+ 'cn': 'test_user1',
+ 'sn': 'test_user1',
+ 'uidNumber': '1001',
+ 'gidNumber': '2001',
+ 'userpassword': PASSWORD,
+ 'description': 'userdesc',
+ 'homeDirectory': '/home/{}'.format('test_user')}
+
+
+def pwd_setup(topo):
+ topo.standalone.config.replace_many(('passwordCheckSyntax', 'on'),
+ ('passwordMinLength', '4'),
+ ('passwordMinCategories', '1'))
+ users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
+ return users.create(properties=user_properties)
+
+
+def test_token_lengths(topo):
+ """Test that password token length is enforced for various lengths including
+ the same length as the attribute being checked by the policy.
+
+ :id: dae9d916-2a03-4707-b454-9e901d295b13
+ :setup: Standalone instance
+ :steps:
+ 1. Test token length rejects password of the same length as rdn value
+ :expectedresults:
+ 1. Passwords are rejected
+ """
+ user = pwd_setup(topo)
+ for length in ['4', '6', '10']:
+ topo.standalone.simple_bind_s(DN_DM, PASSWORD)
+ topo.standalone.config.set('passwordMinTokenLength', length)
+ topo.standalone.simple_bind_s(USER_DN, PASSWORD)
+ time.sleep(1)
+
+ try:
+ passwd = TOKEN[:int(length)]
+ log.info("Testing password len {} token ({})".format(length, passwd))
+ user.replace('userpassword', passwd)
+ log.fatal('Password incorrectly allowed!')
+ assert False
+ except ldap.CONSTRAINT_VIOLATION as e:
+ log.info('Password correctly rejected: ' + str(e))
+ except ldap.LDAPError as e:
+ log.fatal('Unexpected failure ' + str(e))
+ assert False
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
+
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index e625962e8..0cf795b41 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -1465,7 +1465,7 @@ check_trivial_words(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Value **vals, char *
sp = slapi_ch_strdup(slapi_value_get_string(valp));
ep = sp + strlen(sp);
ep = ldap_utf8prevn(sp, ep, toklen);
- if (!ep || (sp >= ep)) {
+ if (!ep || (sp > ep)) {
slapi_ch_free_string(&sp);
continue;
}
diff --git a/ldap/servers/slapd/utf8.c b/ldap/servers/slapd/utf8.c
index b0667c636..4538625b3 100644
--- a/ldap/servers/slapd/utf8.c
+++ b/ldap/servers/slapd/utf8.c
@@ -152,7 +152,7 @@ ldap_utf8prevn(char *s, char *from, int n)
}
for (; n > 0; --n) {
prev = ldap_utf8prev(prev);
- if ((prev <= s) && (n > 0)) {
+ if ((n > 0) && (prev < s)) {
return NULL;
}
}
--
2.13.6

View file

@ -1,41 +0,0 @@
From 7fa2f146c80ed64217bb0c1022c99bd1948cdc7c Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Thu, 11 Jan 2018 15:56:21 +0100
Subject: [PATCH] Ticket 49446 - cleanallruv should ignore cleaned replica Id
in processing changelog if in force mode
Bug: If the startcsn is calculated based on a cleaned rid, it could be missing from the changelog.
Fix: In force mode we do not care that the topology gets in sync for the cleaned RID, so we can ignore it
in an earlier stage, instead of setting it to precleane only.
Reviewed by: Thierry, thanks
---
ldap/servers/plugins/replication/repl5_replica_config.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index e025f34d8..005528a41 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1688,9 +1688,15 @@ replica_cleanallruv_thread(void *arg)
}
/*
* Presetting the rid prevents duplicate thread creation, but allows the db and changelog to still
- * process updates from the rid. set_cleaned_rid() blocks updates, so we don't want to do that... yet.
+ * process updates from the rid.
+ * set_cleaned_rid() blocks updates, so we don't want to do that... yet unless we are in force mode.
+ * If we are forcing a clean independent of state of other servers for this RID we can set_cleaned_rid()
*/
- preset_cleaned_rid(data->rid);
+ if (data->force) {
+ set_cleaned_rid(data->rid);
+ } else {
+ preset_cleaned_rid(data->rid);
+ }
rid_text = slapi_ch_smprintf("%d", data->rid);
csn_as_string(data->maxcsn, PR_FALSE, csnstr);
/*
--
2.13.6

View file

@ -1,41 +0,0 @@
From 7cb2e56db2da439c90bbfd35f132a85708942490 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Tue, 14 Nov 2017 11:25:18 +0100
Subject: [PATCH] Ticket 49413 - Changelog trimming ignores disabled
replica-agreement
Bug: if a replication agreement is disabled it is not taken into account when
changelog trimming determines where to stop.
If the agreement is reenabled later replication can fail
Fix: do not ignore disabled agreements in changelog trimming
Reviewed by: Thierry, thanks
---
ldap/servers/plugins/replication/cl5_api.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 721013abf..dc2857910 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -4283,12 +4283,10 @@ _cl5GetRUV2Purge2(Object *fileObj, RUV **ruv)
while (agmtObj) {
agmt = (Repl_Agmt *)object_get_data(agmtObj);
PR_ASSERT(agmt);
-
- if (!agmt_is_enabled(agmt)) {
- agmtObj = agmtlist_get_next_agreement_for_replica(r, agmtObj);
- continue;
- }
-
+ /* we need to handle all agreements, also if they are not enabled
+ * if they will be later enabled and changes are trimmed
+ * replication can fail
+ */
consRUVObj = agmt_get_consumer_ruv(agmt);
if (consRUVObj) {
consRUV = (RUV *)object_get_data(consRUVObj);
--
2.13.6

View file

@ -1,330 +0,0 @@
From 6e00c3bac13811bc6d94b810b17a59f9428c29f6 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Thu, 11 Jan 2018 15:17:56 +0100
Subject: [PATCH] Ticket 49278 - GetEffectiveRights gives false-negative
Bug: If geteffective rights was issued for an non existing entry the
mechanism to genrate a template entry no longer worked and no results were
returned.
Fix: Improve the handling in itreating the result set, so that template entries (if
requested) are genereated and are not applied to existing entries.
Also some code cleanup in iterate()
Reviewed by: Thierry, thanks
---
ldap/servers/slapd/opshared.c | 239 ++++++++++++++++++++----------------------
1 file changed, 114 insertions(+), 125 deletions(-)
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index 24157120e..46dcf6fba 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -33,6 +33,7 @@ static char *pwpolicy_lock_attrs_all[] = {"passwordRetryCount",
static void compute_limits(Slapi_PBlock *pb);
static int send_results_ext(Slapi_PBlock *pb, int send_result, int *nentries, int pagesize, unsigned int *pr_stat);
static int process_entry(Slapi_PBlock *pb, Slapi_Entry *e, int send_result);
+static void send_entry(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Operation *operation, char **attrs, int attrsonly, int *pnentries);
int
op_shared_is_allowed_attr(const char *attr_name, int replicated_op)
@@ -1040,6 +1041,31 @@ process_entry(Slapi_PBlock *pb, Slapi_Entry *e, int send_result)
return 0;
}
+static void
+send_entry(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Operation *operation, char **attrs, int attrsonly, int *pnentries)
+{
+ /*
+ * It's a regular entry, or it's a referral and
+ * managedsait control is on. In either case, send
+ * the entry.
+ */
+ switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly)) {
+ case 0: /* entry sent ok */
+ (*pnentries)++;
+ slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
+ break;
+ case 1: /* entry not sent */
+ break;
+ case -1: /* connection closed */
+ /*
+ * mark the operation as abandoned so the backend
+ * next entry function gets called again and has
+ * a chance to clean things up.
+ */
+ operation->o_status = SLAPI_OP_STATUS_ABANDONED;
+ break;
+ }
+}
#if 0
/* Loops through search entries and sends them to the client.
@@ -1214,7 +1240,7 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries, in
*pnentries = 0;
while (!done) {
- Slapi_Entry *gerentry = NULL;
+ Slapi_Entry *ger_template_entry = NULL;
Slapi_Operation *operation;
slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
@@ -1236,57 +1262,57 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries, in
slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
/* Check for possible get_effective_rights control */
- if (e) {
- if (operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS) {
- char *errbuf = NULL;
+ if (operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS) {
+ char *errbuf = NULL;
+
+ if (PAGEDRESULTS_PAGE_END == pr_stat) {
+ /*
+ * read ahead -- there is at least more entry.
+ * undo it and return the PAGE_END
+ */
+ be->be_prev_search_results(pb);
+ done = 1;
+ continue;
+ }
+ if ( e == NULL ) {
char **gerattrs = NULL;
char **gerattrsdup = NULL;
char **gap = NULL;
char *gapnext = NULL;
-
- if (PAGEDRESULTS_PAGE_END == pr_stat) {
- /*
- * read ahead -- there is at least more entry.
- * undo it and return the PAGE_END
+ /* we have no more entries
+ * but we might create a template entry for GER
+ * so we need to continue, but make sure to stop
+ * after handling the template entry.
+ * the template entry is a temporary entry returned by the acl
+ * plugin in the pblock and will be freed
*/
- be->be_prev_search_results(pb);
- done = 1;
- continue;
- }
+ done = 1;
+ pr_stat = PAGEDRESULTS_SEARCH_END;
slapi_pblock_get(pb, SLAPI_SEARCH_GERATTRS, &gerattrs);
gerattrsdup = cool_charray_dup(gerattrs);
gap = gerattrsdup;
- do {
+ while (gap && *gap) {
gapnext = NULL;
- if (gap) {
- if (*gap && *(gap + 1)) {
- gapnext = *(gap + 1);
- *(gap + 1) = NULL;
- }
- slapi_pblock_set(pb, SLAPI_SEARCH_GERATTRS, gap);
- rc = plugin_call_acl_plugin(pb, e, attrs, NULL,
- SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
- &errbuf);
- if (NULL != gapnext) {
- *(gap + 1) = gapnext;
- }
- } else if (NULL != e) {
- rc = plugin_call_acl_plugin(pb, e, attrs, NULL,
- SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
- &errbuf);
+ if (*(gap + 1)) {
+ gapnext = *(gap + 1);
+ *(gap + 1) = NULL;
+ }
+ slapi_pblock_set(pb, SLAPI_SEARCH_GERATTRS, gap);
+ rc = plugin_call_acl_plugin(pb, e, attrs, NULL,
+ SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
+ &errbuf);
+ if (NULL != gapnext) {
+ *(gap + 1) = gapnext;
}
+ gap++;
+ /* get the template entry, if any */
+ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
if (NULL == e) {
- /* get the template entry, if any */
- slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
- if (NULL == e) {
- /* everything is ok - don't send the result */
- pr_stat = PAGEDRESULTS_SEARCH_END;
- done = 1;
- continue;
- }
- gerentry = e;
+ /* everything is ok - don't send the result */
+ continue;
}
+ ger_template_entry = e;
if (rc != LDAP_SUCCESS) {
/* Send error result and
abort op if the control is critical */
@@ -1294,65 +1320,53 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries, in
"Failed to get effective rights for entry (%s), rc=%d\n",
slapi_entry_get_dn_const(e), rc);
send_ldap_result(pb, rc, NULL, errbuf, 0, NULL);
- slapi_ch_free((void **)&errbuf);
- if (gerentry) {
- slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
- slapi_entry_free(gerentry);
- gerentry = e = NULL;
- }
- pr_stat = PAGEDRESULTS_SEARCH_END;
rval = -1;
- done = 1;
- continue;
- }
- slapi_ch_free((void **)&errbuf);
- if (process_entry(pb, e, send_result)) {
- /* shouldn't send this entry */
- if (gerentry) {
- slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
- slapi_entry_free(gerentry);
- gerentry = e = NULL;
+ } else {
+ if (!process_entry(pb, e, send_result)) {
+ /* should send this entry now*/
+ send_entry(pb, e, operation, attrs, attrsonly, pnentries);
}
- continue;
}
- /*
- * It's a regular entry, or it's a referral and
- * managedsait control is on. In either case, send
- * the entry.
- */
- switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly)) {
- case 0: /* entry sent ok */
- (*pnentries)++;
- slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
- break;
- case 1: /* entry not sent */
- break;
- case -1: /* connection closed */
- /*
- * mark the operation as abandoned so the backend
- * next entry function gets called again and has
- * a chance to clean things up.
- */
- operation->o_status = SLAPI_OP_STATUS_ABANDONED;
- break;
- }
- if (gerentry) {
+ slapi_ch_free((void **)&errbuf);
+ if (ger_template_entry) {
slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
- slapi_entry_free(gerentry);
- gerentry = e = NULL;
+ slapi_entry_free(ger_template_entry);
+ ger_template_entry = e = NULL;
}
- } while (gap && ++gap && *gap);
+ } /* while ger template */
slapi_pblock_set(pb, SLAPI_SEARCH_GERATTRS, gerattrs);
cool_charray_free(gerattrsdup);
- if (pagesize == *pnentries) {
- /* PAGED RESULTS: reached the pagesize */
- /* We don't set "done = 1" here.
- * We read ahead next entry to check whether there is
- * more entries to return or not. */
- pr_stat = PAGEDRESULTS_PAGE_END;
+ } else {
+ /* we are processing geteffective rights for an existing entry */
+ rc = plugin_call_acl_plugin(pb, e, attrs, NULL,
+ SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
+ &errbuf);
+ if (rc != LDAP_SUCCESS) {
+ /* Send error result and
+ abort op if the control is critical */
+ slapi_log_err(SLAPI_LOG_ERR, "iterate",
+ "Failed to get effective rights for entry (%s), rc=%d\n",
+ slapi_entry_get_dn_const(e), rc);
+ send_ldap_result(pb, rc, NULL, errbuf, 0, NULL);
+ rval = -1;
+ } else {
+ if (!process_entry(pb, e, send_result)) {
+ /* should send this entry now*/
+ send_entry(pb, e, operation, attrs, attrsonly, pnentries);
+ if (pagesize == *pnentries) {
+ /* PAGED RESULTS: reached the pagesize */
+ /* We don't set "done = 1" here.
+ * We read ahead next entry to check whether there is
+ * more entries to return or not. */
+ pr_stat = PAGEDRESULTS_PAGE_END;
+ }
+ }
}
- } else { /* not GET_EFFECTIVE_RIGHTS */
+ slapi_ch_free((void **)&errbuf);
+ }
+ /* not GET_EFFECTIVE_RIGHTS */
+ } else if (e) {
if (PAGEDRESULTS_PAGE_END == pr_stat) {
/*
* read ahead -- there is at least more entry.
@@ -1364,46 +1378,21 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries, in
}
/* Adding shadow password attrs. */
add_shadow_ext_password_attrs(pb, &e);
- if (process_entry(pb, e, send_result)) {
- /* shouldn't send this entry */
- struct slapi_entry *pb_pw_entry = slapi_pblock_get_pw_entry(pb);
- slapi_entry_free(pb_pw_entry);
- slapi_pblock_set_pw_entry(pb, NULL);
- continue;
- }
-
- /*
- * It's a regular entry, or it's a referral and
- * managedsait control is on. In either case, send
- * the entry.
- */
- switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly)) {
- case 0: /* entry sent ok */
- (*pnentries)++;
- slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
- break;
- case 1: /* entry not sent */
- break;
- case -1: /* connection closed */
- /*
- * mark the operation as abandoned so the backend
- * next entry function gets called again and has
- * a chance to clean things up.
- */
- operation->o_status = SLAPI_OP_STATUS_ABANDONED;
- break;
+ if (!process_entry(pb, e, send_result)) {
+ /*this entry was not sent, do it now*/
+ send_entry(pb, e, operation, attrs, attrsonly, pnentries);
+ if (pagesize == *pnentries) {
+ /* PAGED RESULTS: reached the pagesize */
+ /* We don't set "done = 1" here.
+ * We read ahead next entry to check whether there is
+ * more entries to return or not. */
+ pr_stat = PAGEDRESULTS_PAGE_END;
+ }
}
+ /* cleanup pw entry . sent or not */
struct slapi_entry *pb_pw_entry = slapi_pblock_get_pw_entry(pb);
slapi_entry_free(pb_pw_entry);
slapi_pblock_set_pw_entry(pb, NULL);
- if (pagesize == *pnentries) {
- /* PAGED RESULTS: reached the pagesize */
- /* We don't set "done = 1" here.
- * We read ahead next entry to check whether there is
- * more entries to return or not. */
- pr_stat = PAGEDRESULTS_PAGE_END;
- }
- }
} else {
/* no more entries */
done = 1;
--
2.13.6

View file

@ -1,56 +0,0 @@
From 7acfb18228322ab2e331720bd7fe083da04625a2 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 12 Jan 2018 09:50:34 -0500
Subject: [PATCH] Ticket 49531 - coverity issues - fix memory leaks
Description: There were two false positives around pwpolicy struct
being leaked, but it is freed when the pblock is
destroyed. The other two leaks were real, but they
only occurred during error conditions.
https://pagure.io/389-ds-base/issue/49531
Reviewed by: lkrispen (Thanks!)
(cherry picked from commit 700d7422e6309d2d405961abbb805fbfe852e53c)
---
ldap/servers/plugins/replication/cl5_api.c | 1 +
ldap/servers/plugins/replication/urp.c | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index dc2857910..89ae9956c 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -4046,6 +4046,7 @@ _cl5WriteRUV(CL5DBFile *file, PRBool purge)
slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
"_cl5WriteRUV - changelog maxRUV not found in changelog for file %s\n",
file->name);
+ ber_bvecfree(vals);
return CL5_DB_ERROR;
}
diff --git a/ldap/servers/plugins/replication/urp.c b/ldap/servers/plugins/replication/urp.c
index 9534c0322..d4556d7fd 100644
--- a/ldap/servers/plugins/replication/urp.c
+++ b/ldap/servers/plugins/replication/urp.c
@@ -861,7 +861,7 @@ urp_fixup_add_cenotaph (Slapi_PBlock *pb, char *sessionid, CSN *opcsn)
Slapi_Entry *pre_entry = NULL;
int ret = 0;
Slapi_DN *pre_sdn = NULL;
- Slapi_RDN *rdn = slapi_rdn_new();
+ Slapi_RDN *rdn = NULL;
char *parentdn = NULL;
char *newdn;
const char *entrydn;
@@ -882,6 +882,7 @@ urp_fixup_add_cenotaph (Slapi_PBlock *pb, char *sessionid, CSN *opcsn)
entrydn = slapi_entry_get_ndn (pre_entry);*/
uniqueid = slapi_entry_get_uniqueid (pre_entry);
parentdn = slapi_dn_parent(entrydn);
+ rdn = slapi_rdn_new();
slapi_sdn_get_rdn(pre_sdn, rdn);
slapi_rdn_remove_attr (rdn, SLAPI_ATTR_UNIQUEID );
slapi_rdn_add(rdn, "cenotaphID", uniqueid);
--
2.13.6

View file

@ -1,503 +0,0 @@
From 0b5cbcf45f3fb4b03a1f762c5704183787d30696 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 12 Jan 2018 08:38:22 -0500
Subject: [PATCH] Ticket 49529 - Fix Coverity warnings: invalid deferences
Description: So many of the warnings were false positives, but
I "fixed" 90% of them anyway for these two reasons:
One, it's possible that a future change could actually
result in a NULL pointer being referenced.
Two, it would be nice to stop these coverity warnings
so we can focus on real warnings. Auto waivers also
don't always work as the surrounding code changes.
https://pagure.io/389-ds-base/issue/49529
Reviewed by: firstyear (Thanks!)
(cherry picked from commit 7e27face5ef021d883a44d70bb3e9732b115016f)
---
ldap/servers/slapd/abandon.c | 10 ++++++++--
ldap/servers/slapd/add.c | 18 +++++++++++++++---
ldap/servers/slapd/bind.c | 20 +++++++++++++++-----
ldap/servers/slapd/compare.c | 17 +++++++++++++----
ldap/servers/slapd/connection.c | 19 +++++++++++++------
ldap/servers/slapd/delete.c | 4 ++--
ldap/servers/slapd/dn.c | 7 +++++++
ldap/servers/slapd/entry.c | 10 +++++++++-
ldap/servers/slapd/extendop.c | 7 +++++++
ldap/servers/slapd/filter.c | 6 +++++-
ldap/servers/slapd/modify.c | 18 ++++++++++++++++--
ldap/servers/slapd/passwd_extop.c | 4 ++++
ldap/servers/slapd/psearch.c | 13 +++++++++----
ldap/servers/slapd/result.c | 14 +++++++++++++-
ldap/servers/slapd/search.c | 5 ++++-
ldap/servers/slapd/task.c | 5 +++++
16 files changed, 145 insertions(+), 32 deletions(-)
diff --git a/ldap/servers/slapd/abandon.c b/ldap/servers/slapd/abandon.c
index 5c30c972d..e2237e5fc 100644
--- a/ldap/servers/slapd/abandon.c
+++ b/ldap/servers/slapd/abandon.c
@@ -42,10 +42,16 @@ do_abandon(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
- BerElement *ber = pb_op->o_ber;
-
slapi_log_err(SLAPI_LOG_TRACE, "do_abandon", "->\n");
+ if (pb_op == NULL || pb_conn == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "do_abandon", "NULL param: pb_conn (0x%p) pb_op (0x%p)\n",
+ pb_conn, pb_op);
+ return;
+ }
+
+ BerElement *ber = pb_op->o_ber;
+
/*
* Parse the abandon request. It looks like this:
*
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 0a4a5d7b2..8f2fdeac8 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -66,6 +66,14 @@ do_add(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
+
+
+ if (operation == NULL || pb_conn == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "do_add", "NULL param: pb_conn (0x%p) pb_op (0x%p)\n",
+ pb_conn, operation);
+ send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, "param error", 0, NULL);
+ return;
+ }
ber = operation->o_ber;
/* count the add request */
@@ -450,8 +458,8 @@ op_shared_add(Slapi_PBlock *pb)
if (!internal_op) {
slapi_log_access(LDAP_DEBUG_STATS, "conn=%" PRIu64 " op=%d ADD dn=\"%s\"%s\n",
- pb_conn->c_connid,
- operation->o_opid,
+ pb_conn ? pb_conn->c_connid : -1,
+ operation ? operation->o_opid: -1,
slapi_entry_get_dn_const(e),
proxystr ? proxystr : "");
} else {
@@ -865,7 +873,11 @@ handle_fast_add(Slapi_PBlock *pb, Slapi_Entry *entry)
int ret;
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
-
+ if (pb_conn == NULL){
+ slapi_log_err(SLAPI_LOG_ERR, "handle_fast_add", "NULL param: pb_conn (0x%p)\n", pb_conn);
+ send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, "param error", 0, NULL);
+ return;
+ }
be = pb_conn->c_bi_backend;
if ((be == NULL) || (be->be_wire_import == NULL)) {
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index 4a8e4deaf..a34a21a77 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -54,11 +54,7 @@ do_bind(Slapi_PBlock *pb)
{
Operation *pb_op = NULL;
Connection *pb_conn = NULL;
-
- slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
- slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
-
- BerElement *ber = pb_op->o_ber;
+ BerElement *ber;
int err, isroot;
ber_tag_t method = LBER_DEFAULT;
ber_int_t version = -1;
@@ -83,6 +79,16 @@ do_bind(Slapi_PBlock *pb)
slapi_log_err(SLAPI_LOG_TRACE, "do_bind", "=>\n");
+ slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
+ slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+ if (pb_op == NULL || pb_conn == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "do_bind", "NULL param: pb_conn (0x%p) pb_op (0x%p)\n",
+ pb_conn, pb_op);
+ send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL);
+ goto free_and_return;
+ }
+ ber = pb_op->o_ber;
+
/*
* Parse the bind request. It looks like this:
*
@@ -856,6 +862,10 @@ log_bind_access(
slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+ if (pb_op == NULL || pb_conn == NULL) {
+ return;
+ }
+
if (method == LDAP_AUTH_SASL && saslmech && msg) {
slapi_log_access(LDAP_DEBUG_STATS,
"conn=%" PRIu64 " op=%d BIND dn=\"%s\" "
diff --git a/ldap/servers/slapd/compare.c b/ldap/servers/slapd/compare.c
index 9bc6b693a..2626d91d0 100644
--- a/ldap/servers/slapd/compare.c
+++ b/ldap/servers/slapd/compare.c
@@ -35,10 +35,7 @@ do_compare(Slapi_PBlock *pb)
{
Operation *pb_op = NULL;
Connection *pb_conn = NULL;
- slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
- slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
-
- BerElement *ber = pb_op->o_ber;
+ BerElement *ber;
char *rawdn = NULL;
const char *dn = NULL;
struct ava ava = {0};
@@ -50,6 +47,18 @@ do_compare(Slapi_PBlock *pb)
slapi_log_err(SLAPI_LOG_TRACE, "do_compare", "=>\n");
+ slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
+ slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+
+ if (pb_op == NULL || pb_conn == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "do_compare", "NULL param: pb_conn (0x%p) pb_op (0x%p)\n",
+ pb_conn, pb_op);
+ send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL);
+ goto free_and_return;
+ }
+
+ ber = pb_op->o_ber;
+
/* count the compare request */
slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsCompareOps);
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 8ef115691..fa24ec040 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -1518,7 +1518,7 @@ connection_threadmain()
}
if (!thread_turbo_flag && !more_data) {
- Connection *pb_conn = NULL;
+ Connection *pb_conn = NULL;
/* If more data is left from the previous connection_read_operation,
we should finish the op now. Client might be thinking it's
@@ -1530,6 +1530,13 @@ connection_threadmain()
* Connection wait for new work provides the conn and op for us.
*/
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+ if (pb_conn == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "connection_threadmain",
+ "pb_conn is NULL\n");
+ slapi_pblock_destroy(pb);
+ g_decr_active_threadcnt();
+ return;
+ }
switch (ret) {
case CONN_NOWORK:
@@ -1702,11 +1709,11 @@ connection_threadmain()
* so need locking from here on */
signal_listner();
/* with nunc-stans, I see an enormous amount of time spent in the poll() in
- * connection_read_operation() when the below code is enabled - not sure why
- * nunc-stans makes such a huge difference - for now, just disable this code
- * when using nunc-stans - it is supposed to be an optimization but turns out
- * to not be the opposite with nunc-stans
- */
+ * connection_read_operation() when the below code is enabled - not sure why
+ * nunc-stans makes such a huge difference - for now, just disable this code
+ * when using nunc-stans - it is supposed to be an optimization but turns out
+ * to not be the opposite with nunc-stans
+ */
} else if (!enable_nunc_stans) { /* more data in conn - just put back on work_q - bypass poll */
bypasspollcnt++;
PR_EnterMonitor(conn->c_mutex);
diff --git a/ldap/servers/slapd/delete.c b/ldap/servers/slapd/delete.c
index ba238b18f..49cdab138 100644
--- a/ldap/servers/slapd/delete.c
+++ b/ldap/servers/slapd/delete.c
@@ -262,8 +262,8 @@ op_shared_delete(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
slapi_log_access(LDAP_DEBUG_STATS, "conn=%" PRIu64 " op=%d DEL dn=\"%s\"%s\n",
- pb_conn->c_connid,
- pb_op->o_opid,
+ pb_conn ? pb_conn->c_connid : -1,
+ pb_op ? pb_op->o_opid : -1,
slapi_sdn_get_dn(sdn),
proxystr ? proxystr : "");
} else {
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c
index afca37214..abc155533 100644
--- a/ldap/servers/slapd/dn.c
+++ b/ldap/servers/slapd/dn.c
@@ -2477,6 +2477,13 @@ slapi_sdn_copy(const Slapi_DN *from, Slapi_DN *to)
{
SDN_DUMP(from, "slapi_sdn_copy from");
SDN_DUMP(to, "slapi_sdn_copy to");
+
+ if (to == NULL || from == NULL){
+ slapi_log_err(SLAPI_LOG_ERR, "slapi_sdn_copy",
+ "NULL param: from (0x%p) to (0x%p)\n", from, to);
+ return;
+ }
+
slapi_sdn_done(to);
if (from->udn) {
to->flag = slapi_setbit_uchar(to->flag, FLAG_UDN);
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index fbbc8faa0..32828b4e2 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -1998,6 +1998,10 @@ slapi_entry_dup(const Slapi_Entry *e)
struct attrs_in_extension *aiep;
PR_ASSERT(NULL != e);
+ if (e == NULL){
+ slapi_log_err(SLAPI_LOG_ERR, "slapi_entry_dup", "entry is NULL\n");
+ return NULL;
+ }
ec = slapi_entry_alloc();
@@ -3660,7 +3664,11 @@ delete_values_sv_internal(
Slapi_Attr *a;
int retVal = LDAP_SUCCESS;
-/*
+ if (e == NULL){
+ slapi_log_err(SLAPI_LOG_ERR, "delete_values_sv_internal", "entry is NULL\n");
+ return LDAP_OPERATIONS_ERROR;
+ }
+ /*
* If type is in the protected_attrs_all list, we could ignore the failure,
* as the attribute could only exist in the entry in the memory when the
* add/mod operation is done, while the retried entry from the db does not
diff --git a/ldap/servers/slapd/extendop.c b/ldap/servers/slapd/extendop.c
index 1594a8c9c..815949be6 100644
--- a/ldap/servers/slapd/extendop.c
+++ b/ldap/servers/slapd/extendop.c
@@ -219,6 +219,13 @@ do_extended(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+ if (pb_conn == NULL || pb_op == NULL) {
+ send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, "param error", 0, NULL);
+ slapi_log_err(SLAPI_LOG_ERR, "do_extended",
+ "NULL param error: conn (0x%p) op (0x%p)\n", pb_conn, pb_op);
+ goto free_and_return;
+ }
+
/*
* Parse the extended request. It looks like this:
*
diff --git a/ldap/servers/slapd/filter.c b/ldap/servers/slapd/filter.c
index fe3525f34..ef975e679 100644
--- a/ldap/servers/slapd/filter.c
+++ b/ldap/servers/slapd/filter.c
@@ -292,7 +292,11 @@ get_filter_internal(Connection *conn, BerElement *ber, struct slapi_filter **fil
case LDAP_FILTER_EXTENDED:
slapi_log_err(SLAPI_LOG_FILTER, "get_filter_internal", "EXTENDED\n");
- if (conn->c_ldapversion < 3) {
+ if (conn == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "get_filter_internal",
+ "NULL param: conn (0x%p)\n", conn);
+ err = LDAP_OPERATIONS_ERROR;
+ } else if (conn->c_ldapversion < 3) {
slapi_log_err(SLAPI_LOG_ERR, "get_filter_internal",
"Extensible filter received from v2 client\n");
err = LDAP_PROTOCOL_ERROR;
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
index 0dcac646b..10d263159 100644
--- a/ldap/servers/slapd/modify.c
+++ b/ldap/servers/slapd/modify.c
@@ -122,9 +122,16 @@ do_modify(Slapi_PBlock *pb)
slapi_log_err(SLAPI_LOG_TRACE, "do_modify", "=>\n");
slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
- ber = operation->o_ber;
-
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+ if (operation == NULL) {
+ send_ldap_result(pb, LDAP_OPERATIONS_ERROR,
+ NULL, "operation is NULL parameter", 0, NULL);
+ slapi_log_err(SLAPI_LOG_ERR, "do_modify",
+ "NULL param: pb_conn (0x%p) operation (0x%p)\n", pb_conn, operation);
+ return;
+ }
+
+ ber = operation->o_ber;
/* count the modify request */
slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps);
@@ -1165,6 +1172,13 @@ op_shared_allow_pw_change(Slapi_PBlock *pb, LDAPMod *mod, char **old_pw, Slapi_M
internal_op = operation_is_flag_set(operation, OP_FLAG_INTERNAL);
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+ if (pb_conn == NULL || operation == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "op_shared_allow_pw_change",
+ "NULL param error: conn (0x%p) op (0x%p)\n", pb_conn, operation);
+ rc = -1;
+ goto done;
+ }
+
slapi_sdn_init_dn_byref(&sdn, dn);
pwpolicy = new_passwdPolicy(pb, (char *)slapi_sdn_get_ndn(&sdn));
diff --git a/ldap/servers/slapd/passwd_extop.c b/ldap/servers/slapd/passwd_extop.c
index 54a9a6716..40145af2e 100644
--- a/ldap/servers/slapd/passwd_extop.c
+++ b/ldap/servers/slapd/passwd_extop.c
@@ -486,6 +486,10 @@ passwd_modify_extop(Slapi_PBlock *pb)
/* Allow password modify only for SSL/TLS established connections and
* connections using SASL privacy layers */
slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
+ if (conn == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "passwd_modify_extop", "conn is NULL");
+ goto free_and_return;
+ }
if (slapi_pblock_get(pb, SLAPI_CONN_SASL_SSF, &sasl_ssf) != 0) {
errMesg = "Could not get SASL SSF from connection\n";
rc = LDAP_OPERATIONS_ERROR;
diff --git a/ldap/servers/slapd/psearch.c b/ldap/servers/slapd/psearch.c
index e0dd2bf89..1bf062954 100644
--- a/ldap/servers/slapd/psearch.c
+++ b/ldap/servers/slapd/psearch.c
@@ -271,6 +271,11 @@ ps_send_results(void *arg)
slapi_pblock_get(ps->ps_pblock, SLAPI_CONNECTION, &pb_conn);
slapi_pblock_get(ps->ps_pblock, SLAPI_OPERATION, &pb_op);
+ if (pb_conn == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "ps_send_results", "pb_conn is NULL\n");
+ return;
+ }
+
/* need to acquire a reference to this connection so that it will not
be released or cleaned up out from under us */
PR_EnterMonitor(pb_conn->c_mutex);
@@ -280,7 +285,7 @@ ps_send_results(void *arg)
if (conn_acq_flag) {
slapi_log_err(SLAPI_LOG_CONNS, "ps_send_results",
"conn=%" PRIu64 " op=%d Could not acquire the connection - psearch aborted\n",
- pb_conn->c_connid, pb_op->o_opid);
+ pb_conn->c_connid, pb_op ? pb_op->o_opid : -1);
}
PR_Lock(psearch_list->pl_cvarlock);
@@ -290,7 +295,7 @@ ps_send_results(void *arg)
if (pb_op == NULL || slapi_op_abandoned(ps->ps_pblock)) {
slapi_log_err(SLAPI_LOG_CONNS, "ps_send_results",
"conn=%" PRIu64 " op=%d The operation has been abandoned\n",
- pb_conn->c_connid, pb_op->o_opid);
+ pb_conn->c_connid, pb_op ? pb_op->o_opid : -1);
break;
}
if (NULL == ps->ps_eq_head) {
@@ -532,7 +537,7 @@ ps_service_persistent_searches(Slapi_Entry *e, Slapi_Entry *eprev, ber_int_t chg
slapi_log_err(SLAPI_LOG_CONNS, "ps_service_persistent_searches",
"conn=%" PRIu64 " op=%d entry %s with chgtype %d "
"matches the ps changetype %d\n",
- pb_conn->c_connid,
+ pb_conn ? pb_conn->c_connid : -1,
pb_op->o_opid,
edn, chgtype, ps->ps_changetypes);
@@ -609,7 +614,7 @@ ps_service_persistent_searches(Slapi_Entry *e, Slapi_Entry *eprev, ber_int_t chg
/* Turn 'em loose */
ps_wakeup_all();
slapi_log_err(SLAPI_LOG_TRACE, "ps_service_persistent_searches", "Enqueued entry "
- "\"%s\" on %d persistent search lists\n",
+ "\"%s\" on %d persistent search lists\n",
slapi_entry_get_dn_const(e), matched);
} else {
slapi_log_err(SLAPI_LOG_TRACE, "ps_service_persistent_searches",
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index 2302ae96b..ce394d948 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -396,7 +396,7 @@ send_ldap_result_ext(
break;
case LDAP_REFERRAL:
- if (conn->c_ldapversion > LDAP_VERSION2) {
+ if (conn && conn->c_ldapversion > LDAP_VERSION2) {
tag = LDAP_TAG_REFERRAL;
break;
}
@@ -645,6 +645,11 @@ process_read_entry_controls(Slapi_PBlock *pb, char *oid)
BerElement *req_ber = NULL;
Operation *op = NULL;
slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ if (op == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "process_read_entry_controls", "op is NULL\n");
+ rc = -1;
+ goto done;
+ }
if (strcmp(oid, LDAP_CONTROL_PRE_READ_ENTRY) == 0) {
/* first verify this is the correct operation for a pre-read entry control */
@@ -2145,6 +2150,13 @@ encode_read_entry(Slapi_PBlock *pb, Slapi_Entry *e, char **attrs, int alluseratt
slapi_pblock_get(pb, SLAPI_OPERATION, &op);
slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
+ if (conn == NULL || op == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "encode_read_entry",
+ "NULL param error: conn (0x%p) op (0x%p)\n", conn, op);
+ rc = -1;
+ goto cleanup;
+ }
+
/* Start the ber encoding with the DN */
rc = ber_printf(ber, "t{s{", LDAP_RES_SEARCH_ENTRY, slapi_entry_get_dn_const(e));
if (rc == -1) {
diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c
index 5e3413245..731c6519e 100644
--- a/ldap/servers/slapd/search.c
+++ b/ldap/servers/slapd/search.c
@@ -125,7 +125,10 @@ do_search(Slapi_PBlock *pb)
goto free_and_return;
}
- slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+ if (slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn) != 0 || pb_conn == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "do_search", "pb_conn is NULL\n");
+ goto free_and_return;
+ }
/*
* If nsslapd-minssf-exclude-rootdse is on, the minssf check has been
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
index 53a0af52d..002083c04 100644
--- a/ldap/servers/slapd/task.c
+++ b/ldap/servers/slapd/task.c
@@ -199,6 +199,11 @@ slapi_task_log_status(Slapi_Task *task, char *format, ...)
{
va_list ap;
+ if (task == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "slapi_task_log_status",
+ "Slapi_Task is NULL, can not log status\n");
+ return;
+ }
if (!task->task_status)
task->task_status = (char *)slapi_ch_malloc(10 * LOG_BUFFER);
if (!task->task_status)
--
2.13.6

View file

@ -1,286 +0,0 @@
From 0ac68e15a9a4048d3c1ad4519000996cd65fdefb Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Fri, 1 Dec 2017 16:23:11 +0100
Subject: [PATCH] Ticket 49463 - After cleanALLruv, there is a flow of keep
alive DEL
Bug Description:
When cleanAllRuv is launched, it spawn cleanAllRuv on all replicas.
Each replica will clean its changelog and database RUV AND in addition
will DEL the keep alive entry of the target ReplicaID.
So for the same entry (keep alive) there will be as many DEL as there are replicas
This flow of DEL is useless as only one DEL is enough.
In addition because of https://pagure.io/389-ds-base/issue/49466, replication may
loop on each of those DELs.
Fix Description:
The fix is only to prevent the flow of DEL.
It adds a flag ('original_task') in the task payload.
The server receiving the task (replica_execute_cleanall_ruv_task) flags the
task as 'original_task'.
In the opposite, the propagated cleanAllRuv (multimaster_extop_cleanruv) does
not flag the task as 'original_task'
Only original task does the DEL of the keep alive entry.
Note the propageted payload (extop) is not changed. In a mixed version
environment "old" servers will DEL the keep alive and flow can still happen
https://pagure.io/389-ds-base/issue/49466
Reviewed by: Ludwig Krispenz
Platforms tested: F23
Flag Day: no
Doc impact: no
---
ldap/servers/plugins/replication/repl5.h | 49 ++++++++++++----------
ldap/servers/plugins/replication/repl5_replica.c | 21 ++++++++++
.../plugins/replication/repl5_replica_config.c | 32 +++++++++++---
ldap/servers/plugins/replication/repl_extop.c | 2 +
4 files changed, 76 insertions(+), 28 deletions(-)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 4e206a0fc..e08fec752 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -783,12 +783,37 @@ void multimaster_mtnode_construct_replicas(void);
void multimaster_be_state_change(void *handle, char *be_name, int old_be_state, int new_be_state);
+#define CLEANRIDSIZ 64 /* maximum number for concurrent CLEANALLRUV tasks */
+
+typedef struct _cleanruv_data
+{
+ Object *repl_obj;
+ Replica *replica;
+ ReplicaId rid;
+ Slapi_Task *task;
+ struct berval *payload;
+ CSN *maxcsn;
+ char *repl_root;
+ Slapi_DN *sdn;
+ char *certify;
+ char *force;
+ PRBool original_task;
+} cleanruv_data;
+
+typedef struct _cleanruv_purge_data
+{
+ int cleaned_rid;
+ const Slapi_DN *suffix_sdn;
+ char *replName;
+ char *replGen;
+} cleanruv_purge_data;
+
/* In repl5_replica_config.c */
int replica_config_init(void);
void replica_config_destroy(void);
int get_replica_type(Replica *r);
int replica_execute_cleanruv_task_ext(Object *r, ReplicaId rid);
-void add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn, char *forcing);
+void add_cleaned_rid(cleanruv_data *data, char *maxcsn);
int is_cleaned_rid(ReplicaId rid);
int replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int *returncode, char *returntext, void *arg);
void replica_cleanallruv_thread_ext(void *arg);
@@ -808,29 +833,7 @@ void set_cleaned_rid(ReplicaId rid);
void cleanruv_log(Slapi_Task *task, int rid, char *task_type, int sev_level, char *fmt, ...);
char *replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn);
-#define CLEANRIDSIZ 64 /* maximum number for concurrent CLEANALLRUV tasks */
-typedef struct _cleanruv_data
-{
- Object *repl_obj;
- Replica *replica;
- ReplicaId rid;
- Slapi_Task *task;
- struct berval *payload;
- CSN *maxcsn;
- char *repl_root;
- Slapi_DN *sdn;
- char *certify;
- char *force;
-} cleanruv_data;
-
-typedef struct _cleanruv_purge_data
-{
- int cleaned_rid;
- const Slapi_DN *suffix_sdn;
- char *replName;
- char *replGen;
-} cleanruv_purge_data;
/* replutil.c */
LDAPControl *create_managedsait_control(void);
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 77f4f18e4..e75807a62 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -2120,6 +2120,7 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e)
char csnstr[CSN_STRSIZE];
char *token = NULL;
char *forcing;
+ PRBool original_task;
char *csnpart;
char *ridstr;
char *iter = NULL;
@@ -2151,8 +2152,15 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e)
csn_init_by_string(maxcsn, csnpart);
csn_as_string(maxcsn, PR_FALSE, csnstr);
forcing = ldap_utf8strtok_r(iter, ":", &iter);
+ original_task = PR_TRUE;
if (forcing == NULL) {
forcing = "no";
+ } else if (!strcasecmp(forcing, "yes") || !strcasecmp(forcing, "no")) {
+ /* forcing was correctly set, lets try to read the original task flag */
+ token = ldap_utf8strtok_r(iter, ":", &iter);
+ if (token && !atoi(token)) {
+ original_task = PR_FALSE;
+ }
}
slapi_log_err(SLAPI_LOG_NOTICE, repl_plugin_name, "CleanAllRUV Task - cleanAllRUV task found, "
@@ -2190,6 +2198,13 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e)
data->force = slapi_ch_strdup(forcing);
data->repl_root = NULL;
+ /* This is a corner case, a cleanAllRuv task was interrupted by a shutdown or a crash
+ * We retrieved from type_replicaCleanRUV if the cleanAllRuv request
+ * was received from a direct task ADD or if was received via
+ * the cleanAllRuv extop.
+ */
+ data->original_task = original_task;
+
thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_thread_ext,
(void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
@@ -2284,6 +2299,12 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e)
data->sdn = slapi_sdn_dup(r->repl_root);
data->certify = slapi_ch_strdup(certify);
+ /* This is a corner case, a cleanAllRuv task was interrupted by a shutdown or a crash
+ * Let's assum this replica was the original receiver of the task.
+ * This flag has no impact on Abort cleanAllRuv
+ */
+ data->original_task = PR_TRUE;
+
thread = PR_CreateThread(PR_USER_THREAD, replica_abort_task_thread,
(void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 005528a41..95b933bb8 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1573,6 +1573,11 @@ replica_execute_cleanall_ruv_task(Object *r, ReplicaId rid, Slapi_Task *task, co
data->repl_root = slapi_ch_strdup(basedn);
data->force = slapi_ch_strdup(force_cleaning);
+ /* It is either a consequence of a direct ADD cleanAllRuv task
+ * or modify of the replica to add nsds5task: cleanAllRuv
+ */
+ data->original_task = PR_TRUE;
+
thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_thread,
(void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
@@ -1702,7 +1707,7 @@ replica_cleanallruv_thread(void *arg)
/*
* Add the cleanallruv task to the repl config - so we can handle restarts
*/
- add_cleaned_rid(data->rid, data->replica, csnstr, data->force); /* marks config that we started cleaning a rid */
+ add_cleaned_rid(data, csnstr); /* marks config that we started cleaning a rid */
cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Cleaning rid (%d)...", data->rid);
/*
* First, wait for the maxcsn to be covered
@@ -1878,7 +1883,13 @@ done:
*/
delete_cleaned_rid_config(data);
check_replicas_are_done_cleaning(data);
- remove_keep_alive_entry(data->task, data->rid, data->repl_root);
+ if (data->original_task) {
+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Original task deletes Keep alive entry (%d).", data->rid);
+ remove_keep_alive_entry(data->task, data->rid, data->repl_root);
+ } else {
+ cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Propagated task does not delete Keep alive entry (%d).", data->rid);
+ }
+
clean_agmts(data);
remove_cleaned_rid(data->rid);
cleanruv_log(data->task, data->rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Successfully cleaned rid(%d).", data->rid);
@@ -2029,7 +2040,7 @@ check_replicas_are_done_cleaning(cleanruv_data *data)
"Waiting for all the replicas to finish cleaning...");
csn_as_string(data->maxcsn, PR_FALSE, csnstr);
- filter = PR_smprintf("(%s=%d:%s:%s)", type_replicaCleanRUV, (int)data->rid, csnstr, data->force);
+ filter = PR_smprintf("(%s=%d:%s:%s:%d)", type_replicaCleanRUV, (int)data->rid, csnstr, data->force, data->original_task ? 1 : 0);
while (not_all_cleaned && !is_task_aborted(data->rid) && !slapi_is_shutting_down()) {
agmt_obj = agmtlist_get_first_agreement_for_replica(data->replica);
if (agmt_obj == NULL) {
@@ -2502,7 +2513,7 @@ set_cleaned_rid(ReplicaId rid)
* Add the rid and maxcsn to the repl config (so we can resume after a server restart)
*/
void
-add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn, char *forcing)
+add_cleaned_rid(cleanruv_data *cleanruv_data, char *maxcsn)
{
Slapi_PBlock *pb;
struct berval *vals[2];
@@ -2512,6 +2523,16 @@ add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn, char *forcing)
char data[CSN_STRSIZE + 10];
char *dn;
int rc;
+ ReplicaId rid;
+ Replica *r;
+ char *forcing;
+
+ if (data == NULL) {
+ return;
+ }
+ rid = cleanruv_data->rid;
+ r = cleanruv_data->replica;
+ forcing = cleanruv_data->force;
if (r == NULL || maxcsn == NULL) {
return;
@@ -2519,7 +2540,7 @@ add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn, char *forcing)
/*
* Write the rid & maxcsn to the config entry
*/
- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s", rid, maxcsn, forcing);
+ val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s:%d", rid, maxcsn, forcing, cleanruv_data->original_task ? 1 : 0);
dn = replica_get_dn(r);
pb = slapi_pblock_new();
mod.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
@@ -2961,6 +2982,7 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb __attribute__((unused)),
data->repl_root = slapi_ch_strdup(base_dn);
data->sdn = NULL;
data->certify = slapi_ch_strdup(certify_all);
+ data->original_task = PR_TRUE;
thread = PR_CreateThread(PR_USER_THREAD, replica_abort_task_thread,
(void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index c49c6bd8d..68e2544b4 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -1412,6 +1412,7 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb)
data->rid = rid;
data->repl_root = slapi_ch_strdup(repl_root);
data->certify = slapi_ch_strdup(certify_all);
+ data->original_task = PR_FALSE;
/*
* Set the aborted rid and stop the cleaning
*/
@@ -1555,6 +1556,7 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb)
data->payload = slapi_ch_bvdup(extop_payload);
data->force = slapi_ch_strdup(force);
data->repl_root = slapi_ch_strdup(repl_root);
+ data->original_task = PR_FALSE;
thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_thread_ext,
(void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
--
2.13.6

View file

@ -1,75 +0,0 @@
From cfa194289ee0c9d26d5775f0b67cf9b481bf357f Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 12 Jan 2018 10:37:18 -0500
Subject: [PATCH] Ticket 49532 - coverity issues - fix compiler warnings &
clang issues
Description: Fixed all the warnings
https://pagure.io/389-ds-base/issue/49532
Reviewed by: tbordaz(Thanks!)
(cherry picked from commit 05907ae05c8a88a64b86747879c002d55d356673)
---
ldap/servers/slapd/back-ldbm/idl_set.c | 4 ++--
ldap/servers/slapd/control.c | 2 +-
src/nunc-stans/ns/ns_thrpool.c | 7 ++++++-
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/ldap/servers/slapd/back-ldbm/idl_set.c b/ldap/servers/slapd/back-ldbm/idl_set.c
index b68e7ab76..f9a900f1f 100644
--- a/ldap/servers/slapd/back-ldbm/idl_set.c
+++ b/ldap/servers/slapd/back-ldbm/idl_set.c
@@ -270,7 +270,7 @@ idl_set_union(IDListSet *idl_set, backend *be)
* Allocate a new set based on the size of our sets.
*/
IDList *result_list = idl_alloc(idl_set->total_size);
- IDList *idl = idl_set->head;
+ IDList *idl = NULL;
IDList *idl_del = NULL;
IDList *prev_idl = NULL;
NIDS last_min = 0;
@@ -398,7 +398,7 @@ idl_set_intersect(IDListSet *idl_set, backend *be)
* we don't care if we have allids here, because we'll ignore it anyway.
*/
result_list = idl_alloc(idl_set->minimum->b_nids);
- IDList *idl = idl_set->head;
+ IDList *idl = NULL;
/* The previous value we inserted. */
NIDS last_min = 0;
diff --git a/ldap/servers/slapd/control.c b/ldap/servers/slapd/control.c
index 91d8abb95..366ec7897 100644
--- a/ldap/servers/slapd/control.c
+++ b/ldap/servers/slapd/control.c
@@ -337,7 +337,7 @@ get_ldapmessage_controls_ext(
slapi_pblock_set(pb, SLAPI_MANAGEDSAIT, &ctrl_not_found);
slapi_pblock_set(pb, SLAPI_PWPOLICY, &ctrl_not_found);
slapi_log_err(SLAPI_LOG_CONNS, "get_ldapmessage_controls_ext", "Warning: conn=%" PRIu64 " op=%d contains an empty list of controls\n",
- pb_conn->c_connid, pb_op->o_opid);
+ pb_conn ? pb_conn->c_connid : -1, pb_op ? pb_op->o_opid : -1);
} else {
/* len, ber_len_t is uint, not int, cannot be != -1, may be better to remove this check. */
if ((tag != LBER_END_OF_SEQORSET) && (len != -1)) {
diff --git a/src/nunc-stans/ns/ns_thrpool.c b/src/nunc-stans/ns/ns_thrpool.c
index 1d8bb03f1..d95b0c38b 100644
--- a/src/nunc-stans/ns/ns_thrpool.c
+++ b/src/nunc-stans/ns/ns_thrpool.c
@@ -1587,7 +1587,12 @@ ns_thrpool_shutdown(struct ns_thrpool_t *tp)
*/
for (size_t i = 0; i < tp->thread_count; i++) {
ns_result_t result = ns_add_shutdown_job(tp);
- PR_ASSERT(result == NS_SUCCESS);
+ if (result != NS_SUCCESS) {
+#ifdef DEBUG
+ ns_log(LOG_DEBUG, "ns_thrpool_shutdown - Failed to add shutdown job: error (%d)\n", result);
+#endif
+ PR_ASSERT(0);
+ }
}
/* Make sure all threads are woken up to their shutdown jobs. */
pthread_mutex_lock(&(tp->work_q_lock));
--
2.13.6

View file

@ -1,225 +0,0 @@
From 60198729ba59f673aae2ae1db1d9668b674ad429 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Fri, 5 Jan 2018 15:31:44 +0100
Subject: [PATCH] Ticket 49523 - memberof: schema violation error message is
confusing as memberof will likely repair target entry
Bug Description:
When memberof is enabled it adds 'memberof' attribute to members entries.
If a member entry has not the appropriate objectclass to support 'memberof' attribute an ERR is logged.
ERR - oc_check_allowed_sv - Entry "cn=user_1,ou=People,dc=example,dc=com" -- attribute "memberOf" not allowed
This is confusing because memberof will catch this violation and may try to repair it.
So although this message is alarming, the target entry may finally have the 'memberof' attribute.
This is especially confusing since https://pagure.io/389-ds-base/issue/48985 where the repair operation
is done by default (if schema is violated)
We can not (and should not) eliminate the schema violation message.
But memberof should log a additional warning (beside the schema violation msg) stating it repaired the violation.
Fix Description:
Add a warning message upon repair operation
ERR - oc_check_allowed_sv - Entry "<entry_dn>" -- attribute "memberOf" not allowed
WARN - memberof-plugin - Entry <entry_dn> - schema violation caught - repair operation succeeded
https://pagure.io/389-ds-base/issue/49523
Reviewed by: Mark Reynolds
Platforms tested: F26
Flag Day: no
Doc impact: no
---
dirsrvtests/tests/tickets/ticket49523_test.py | 154 ++++++++++++++++++++++++++
ldap/servers/plugins/memberof/memberof.c | 8 +-
2 files changed, 161 insertions(+), 1 deletion(-)
create mode 100644 dirsrvtests/tests/tickets/ticket49523_test.py
diff --git a/dirsrvtests/tests/tickets/ticket49523_test.py b/dirsrvtests/tests/tickets/ticket49523_test.py
new file mode 100644
index 000000000..c3296ef07
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket49523_test.py
@@ -0,0 +1,154 @@
+import logging
+import pytest
+import os
+import ldap
+import time
+import re
+from lib389.plugins import MemberOfPlugin
+from lib389._constants import *
+from lib389.topologies import topology_st as topo
+from lib389 import Entry
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+
+USER_CN='user_'
+GROUP_CN='group_'
+def _user_get_dn(no):
+ cn = '%s%d' % (USER_CN, no)
+ dn = 'cn=%s,ou=people,%s' % (cn, SUFFIX)
+ return (cn, dn)
+
+def add_user(server, no, desc='dummy', sleep=True):
+ (cn, dn) = _user_get_dn(no)
+ log.fatal('Adding user (%s): ' % dn)
+ server.add_s(Entry((dn, {'objectclass': ['top', 'person'],
+ 'cn': [cn],
+ 'description': [desc],
+ 'sn': [cn],
+ 'description': ['add on that host']})))
+ if sleep:
+ time.sleep(2)
+
+def add_group(server, nr, sleep=True):
+ cn = '%s%d' % (GROUP_CN, nr)
+ dn = 'cn=%s,ou=groups,%s' % (cn, SUFFIX)
+ server.add_s(Entry((dn, {'objectclass': ['top', 'groupofnames'],
+ 'description': 'group %d' % nr})))
+ if sleep:
+ time.sleep(2)
+
+def update_member(server, member_dn, group_dn, op, sleep=True):
+ mod = [(op, 'member', member_dn)]
+ server.modify_s(group_dn, mod)
+ if sleep:
+ time.sleep(2)
+
+def _find_memberof(server, member_dn, group_dn, find_result=True):
+ ent = server.getEntry(member_dn, ldap.SCOPE_BASE, "(objectclass=*)", ['memberof'])
+ found = False
+ if ent.hasAttr('memberof'):
+
+ for val in ent.getValues('memberof'):
+ server.log.info("!!!!!!! %s: memberof->%s" % (member_dn, val))
+ server.log.info("!!!!!!! %s" % (val))
+ server.log.info("!!!!!!! %s" % (group_dn))
+ if val.lower() == group_dn.lower():
+ found = True
+ break
+
+ if find_result:
+ assert (found)
+ else:
+ assert (not found)
+
+def pattern_accesslog(server, log_pattern):
+ file_obj = open(server.accesslog, "r")
+
+ found = False
+ # Use a while true iteration because 'for line in file: hit a
+ while True:
+ line = file_obj.readline()
+ found = log_pattern.search(line)
+ if ((line == '') or (found)):
+ break
+
+ return found
+
+def pattern_errorlog(server, log_pattern):
+ file_obj = open(server.errlog, "r")
+
+ found = None
+ # Use a while true iteration because 'for line in file: hit a
+ while True:
+ line = file_obj.readline()
+ found = log_pattern.search(line)
+ server.log.fatal("%s --> %s" % (line, found))
+ if ((line == '') or (found)):
+ break
+
+ return found
+
+def test_ticket49523(topo):
+ """Specify a test case purpose or name here
+
+ :id: e2af0aaa-447e-4e85-a5ce-57ae66260d0b
+ :setup: Fill in set up configuration here
+ :steps:
+ 1. Fill in test case steps here
+ 2. And indent them like this (RST format requirement)
+ :expectedresults:
+ 1. Fill in the result that is expected
+ 2. For each test step
+ """
+
+ # If you need any test suite initialization,
+ # please, write additional fixture for that (including finalizer).
+ # Topology for suites are predefined in lib389/topologies.py.
+
+ # If you need host, port or any other data about instance,
+ # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
+ inst = topo.standalone
+ memberof = MemberOfPlugin(inst)
+ memberof.enable()
+ memberof.set_autoaddoc('nsMemberOf')
+ inst.restart()
+
+ # Step 2
+ for i in range(10):
+ add_user(inst, i, desc='add user')
+
+ add_group(inst, 1)
+
+ group_parent_dn = 'ou=groups,%s' % (SUFFIX)
+ group_rdn = 'cn=%s%d' % (GROUP_CN, 1)
+ group_dn = '%s,%s' % (group_rdn, group_parent_dn)
+ (member_cn, member_dn) = _user_get_dn(1)
+ update_member(inst, member_dn, group_dn, ldap.MOD_ADD, sleep=False)
+
+ _find_memberof(inst, member_dn, group_dn, find_result=True)
+
+ pattern = ".*oc_check_allowed_sv - Entry.*cn=%s.* -- attribute.*not allowed.*" % member_cn
+ log.fatal("pattern = %s" % pattern)
+ regex = re.compile(pattern)
+ assert pattern_errorlog(inst, regex)
+
+ regex = re.compile(".*schema violation caught - repair operation.*")
+ assert pattern_errorlog(inst, regex)
+
+ if DEBUGGING:
+ # Add debugging steps(if any)...
+ pass
+
+
+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/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
index 44b52edbb..fcfa7817d 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -3236,8 +3236,14 @@ memberof_add_memberof_attr(LDAPMod **mods, const char *dn, char *add_oc)
*/
break;
}
- if (memberof_add_objectclass(add_oc, dn)) {
+ rc = memberof_add_objectclass(add_oc, dn);
+ slapi_log_err(SLAPI_LOG_WARNING, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "Entry %s - schema violation caught - repair operation %s\n",
+ dn ? dn : "unknown",
+ rc ? "failed" : "succeeded");
+ if (rc) {
/* Failed to add objectclass */
+ rc = LDAP_OBJECT_CLASS_VIOLATION;
break;
}
added_oc = 1;
--
2.13.6

View file

@ -1,288 +0,0 @@
From 86efa0314c59550f0660c8d143a52a57b1dffb96 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 18 Jan 2018 09:56:17 -0500
Subject: [PATCH] Ticket 49370 - Add all the password policy defaults to a new
local policy
Bug Description: When processing a local password policy we were not pulling
in the defaults for the "on/off" settings. This patch
addresses that.
Fix Description: Create common default init functions for all password policies
https://pagure.io/389-ds-base/issue/49370
Reviewed by: tbordaz, wibrown, and spichugi (Thanks!!!)
(cherry picked from commit c8b388bf9f5269e1e1dc8c7c70ec8e58e825204a)
---
.../tests/suites/password/regression_test.py | 58 +++++++++++++--
ldap/servers/slapd/libglobs.c | 84 ++++++++++++++--------
ldap/servers/slapd/pw.c | 29 ++------
ldap/servers/slapd/slap.h | 2 +
4 files changed, 113 insertions(+), 60 deletions(-)
diff --git a/dirsrvtests/tests/suites/password/regression_test.py b/dirsrvtests/tests/suites/password/regression_test.py
index f6ee16773..800294057 100644
--- a/dirsrvtests/tests/suites/password/regression_test.py
+++ b/dirsrvtests/tests/suites/password/regression_test.py
@@ -6,9 +6,10 @@
# --- END COPYRIGHT BLOCK ---
#
import pytest
-from lib389._constants import SUFFIX, PASSWORD
+import time
+from lib389._constants import SUFFIX, PASSWORD, DN_DM
from lib389.idm.user import UserAccounts
-from lib389.utils import ldap, os, logging
+from lib389.utils import ldap, os, logging, ensure_bytes
from lib389.topologies import topology_st as topo
DEBUGGING = os.getenv("DEBUGGING", default=False)
@@ -20,6 +21,7 @@ log = logging.getLogger(__name__)
user_data = {'cn': 'CNpwtest1', 'sn': 'SNpwtest1', 'uid': 'UIDpwtest1', 'mail': 'MAILpwtest1@redhat.com',
'givenname': 'GNpwtest1'}
+
TEST_PASSWORDS = list(user_data.values())
# Add substring/token values of "CNpwtest1"
TEST_PASSWORDS += ['CNpwtest1ZZZZ', 'ZZZZZCNpwtest1',
@@ -37,13 +39,20 @@ def passw_policy(topo, request):
"""Configure password policy with PasswordCheckSyntax attribute set to on"""
log.info('Configure Pwpolicy with PasswordCheckSyntax and nsslapd-pwpolicy-local set to on')
+ topo.standalone.simple_bind_s(DN_DM, PASSWORD)
topo.standalone.config.set('PasswordExp', 'on')
topo.standalone.config.set('PasswordCheckSyntax', 'off')
topo.standalone.config.set('nsslapd-pwpolicy-local', 'on')
subtree = 'ou=people,{}'.format(SUFFIX)
log.info('Configure subtree password policy for {}'.format(subtree))
- topo.standalone.subtreePwdPolicy(subtree, {'passwordchange': 'on', 'passwordCheckSyntax': 'on'})
+ topo.standalone.subtreePwdPolicy(subtree, {'passwordchange': ensure_bytes('on'),
+ 'passwordCheckSyntax': ensure_bytes('on'),
+ 'passwordLockout': ensure_bytes('on'),
+ 'passwordResetFailureCount': ensure_bytes('3'),
+ 'passwordLockoutDuration': ensure_bytes('3'),
+ 'passwordMaxFailure': ensure_bytes('2')})
+ time.sleep(1)
def fin():
log.info('Reset pwpolicy configuration settings')
@@ -76,6 +85,47 @@ def test_user(topo, request):
return tuser
+def test_pwp_local_unlock(topo, passw_policy, test_user):
+ """Test subtree policies use the same global default for passwordUnlock
+
+ :id: 741a8417-5f65-4012-b9ed-87987ce3ca1b
+ :setup: Standalone instance
+ :steps:
+ 1. Test user can bind
+ 2. Bind with bad passwords to lockout account, and verify account is locked
+ 3. Wait for lockout interval, and bind with valid password
+ :expectedresults:
+ 1. Bind successful
+ 2. Entry is locked
+ 3. Entry can bind with correct password
+ """
+
+ log.info("Verify user can bind...")
+ test_user.bind(PASSWORD)
+
+ log.info('Test passwordUnlock default - user should be able to reset password after lockout')
+ for i in range(0,2):
+ try:
+ test_user.bind("bad-password")
+ except ldap.INVALID_CREDENTIALS:
+ # expected
+ pass
+ except ldap.LDAPError as e:
+ log.fatal("Got unexpected failure: " + atr(e))
+ raise e
+
+
+ log.info('Verify account is locked')
+ with pytest.raises(ldap.CONSTRAINT_VIOLATION):
+ test_user.bind(PASSWORD)
+
+ log.info('Wait for lockout duration...')
+ time.sleep(4)
+
+ log.info('Check if user can now bind with correct password')
+ test_user.bind(PASSWORD)
+
+
@pytest.mark.bz1465600
@pytest.mark.parametrize("user_pasw", TEST_PASSWORDS)
def test_trivial_passw_check(topo, passw_policy, test_user, user_pasw):
@@ -143,4 +193,4 @@ if __name__ == '__main__':
# Run isolated
# -s for DEBUG mode
CURRENT_FILE = os.path.realpath(__file__)
- pytest.main("-s {}".format(CURRENT_FILE))
+ pytest.main(["-s", CURRENT_FILE])
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 1ba30002f..c1a765aca 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -1401,6 +1401,56 @@ getFrontendConfig(void)
*/
void
+pwpolicy_init_defaults (passwdPolicy *pw_policy)
+{
+ pw_policy->pw_change = LDAP_ON;
+ pw_policy->pw_must_change = LDAP_OFF;
+ pw_policy->pw_syntax = LDAP_OFF;
+ pw_policy->pw_exp = LDAP_OFF;
+ pw_policy->pw_send_expiring = LDAP_OFF;
+ pw_policy->pw_minlength = SLAPD_DEFAULT_PW_MINLENGTH;
+ pw_policy->pw_mindigits = SLAPD_DEFAULT_PW_MINDIGITS;
+ pw_policy->pw_minalphas = SLAPD_DEFAULT_PW_MINALPHAS;
+ pw_policy->pw_minuppers = SLAPD_DEFAULT_PW_MINUPPERS;
+ pw_policy->pw_minlowers = SLAPD_DEFAULT_PW_MINLOWERS;
+ pw_policy->pw_minspecials = SLAPD_DEFAULT_PW_MINSPECIALS;
+ pw_policy->pw_min8bit = SLAPD_DEFAULT_PW_MIN8BIT;
+ pw_policy->pw_maxrepeats = SLAPD_DEFAULT_PW_MAXREPEATS;
+ pw_policy->pw_mincategories = SLAPD_DEFAULT_PW_MINCATEGORIES;
+ pw_policy->pw_mintokenlength = SLAPD_DEFAULT_PW_MINTOKENLENGTH;
+ pw_policy->pw_maxage = SLAPD_DEFAULT_PW_MAXAGE;
+ pw_policy->pw_minage = SLAPD_DEFAULT_PW_MINAGE;
+ pw_policy->pw_warning = SLAPD_DEFAULT_PW_WARNING;
+ pw_policy->pw_history = LDAP_OFF;
+ pw_policy->pw_inhistory = SLAPD_DEFAULT_PW_INHISTORY;
+ pw_policy->pw_lockout = LDAP_OFF;
+ pw_policy->pw_maxfailure = SLAPD_DEFAULT_PW_MAXFAILURE;
+ pw_policy->pw_unlock = LDAP_ON;
+ pw_policy->pw_lockduration = SLAPD_DEFAULT_PW_LOCKDURATION;
+ pw_policy->pw_resetfailurecount = SLAPD_DEFAULT_PW_RESETFAILURECOUNT;
+ pw_policy->pw_gracelimit = SLAPD_DEFAULT_PW_GRACELIMIT;
+ pw_policy->pw_admin = NULL;
+ pw_policy->pw_admin_user = NULL;
+ pw_policy->pw_is_legacy = LDAP_ON;
+ pw_policy->pw_track_update_time = LDAP_OFF;
+}
+
+static void
+pwpolicy_fe_init_onoff(passwdPolicy *pw_policy)
+{
+ init_pw_change = pw_policy->pw_change;
+ init_pw_must_change = pw_policy->pw_must_change;
+ init_pw_syntax = pw_policy->pw_syntax;
+ init_pw_exp = pw_policy->pw_exp;
+ init_pw_send_expiring = pw_policy->pw_send_expiring;
+ init_pw_history = pw_policy->pw_history;
+ init_pw_lockout = pw_policy->pw_lockout;
+ init_pw_unlock = pw_policy->pw_unlock;
+ init_pw_is_legacy = pw_policy->pw_is_legacy;
+ init_pw_track_update_time = pw_policy->pw_track_update_time;
+}
+
+void
FrontendConfig_init(void)
{
slapdFrontendConfig_t *cfg = getFrontendConfig();
@@ -1511,41 +1561,13 @@ FrontendConfig_init(void)
* let clients abide by the LDAP standards and send us a SASL/EXTERNAL bind
* if that's what they want to do */
init_force_sasl_external = cfg->force_sasl_external = LDAP_OFF;
-
init_readonly = cfg->readonly = LDAP_OFF;
+
+ pwpolicy_init_defaults(&cfg->pw_policy);
+ pwpolicy_fe_init_onoff(&cfg->pw_policy);
init_pwpolicy_local = cfg->pwpolicy_local = LDAP_OFF;
init_pwpolicy_inherit_global = cfg->pwpolicy_inherit_global = LDAP_OFF;
- init_pw_change = cfg->pw_policy.pw_change = LDAP_ON;
- init_pw_must_change = cfg->pw_policy.pw_must_change = LDAP_OFF;
init_allow_hashed_pw = cfg->allow_hashed_pw = LDAP_OFF;
- init_pw_syntax = cfg->pw_policy.pw_syntax = LDAP_OFF;
- init_pw_exp = cfg->pw_policy.pw_exp = LDAP_OFF;
- init_pw_send_expiring = cfg->pw_policy.pw_send_expiring = LDAP_OFF;
- cfg->pw_policy.pw_minlength = SLAPD_DEFAULT_PW_MINLENGTH;
- cfg->pw_policy.pw_mindigits = SLAPD_DEFAULT_PW_MINDIGITS;
- cfg->pw_policy.pw_minalphas = SLAPD_DEFAULT_PW_MINALPHAS;
- cfg->pw_policy.pw_minuppers = SLAPD_DEFAULT_PW_MINUPPERS;
- cfg->pw_policy.pw_minlowers = SLAPD_DEFAULT_PW_MINLOWERS;
- cfg->pw_policy.pw_minspecials = SLAPD_DEFAULT_PW_MINSPECIALS;
- cfg->pw_policy.pw_min8bit = SLAPD_DEFAULT_PW_MIN8BIT;
- cfg->pw_policy.pw_maxrepeats = SLAPD_DEFAULT_PW_MAXREPEATS;
- cfg->pw_policy.pw_mincategories = SLAPD_DEFAULT_PW_MINCATEGORIES;
- cfg->pw_policy.pw_mintokenlength = SLAPD_DEFAULT_PW_MINTOKENLENGTH;
- cfg->pw_policy.pw_maxage = SLAPD_DEFAULT_PW_MAXAGE;
- cfg->pw_policy.pw_minage = SLAPD_DEFAULT_PW_MINAGE;
- cfg->pw_policy.pw_warning = SLAPD_DEFAULT_PW_WARNING;
- init_pw_history = cfg->pw_policy.pw_history = LDAP_OFF;
- cfg->pw_policy.pw_inhistory = SLAPD_DEFAULT_PW_INHISTORY;
- init_pw_lockout = cfg->pw_policy.pw_lockout = LDAP_OFF;
- cfg->pw_policy.pw_maxfailure = SLAPD_DEFAULT_PW_MAXFAILURE;
- init_pw_unlock = cfg->pw_policy.pw_unlock = LDAP_ON;
- cfg->pw_policy.pw_lockduration = SLAPD_DEFAULT_PW_LOCKDURATION;
- cfg->pw_policy.pw_resetfailurecount = SLAPD_DEFAULT_PW_RESETFAILURECOUNT;
- cfg->pw_policy.pw_gracelimit = SLAPD_DEFAULT_PW_GRACELIMIT;
- cfg->pw_policy.pw_admin = NULL;
- cfg->pw_policy.pw_admin_user = NULL;
- init_pw_is_legacy = cfg->pw_policy.pw_is_legacy = LDAP_ON;
- init_pw_track_update_time = cfg->pw_policy.pw_track_update_time = LDAP_OFF;
init_pw_is_global_policy = cfg->pw_is_global_policy = LDAP_OFF;
init_accesslog_logging_enabled = cfg->accesslog_logging_enabled = LDAP_ON;
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 53464c64a..3a545e12e 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -1730,32 +1730,11 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
goto done;
}
- /* Set the default values */
- pwdpolicy->pw_mintokenlength = SLAPD_DEFAULT_PW_MINTOKENLENGTH;
- pwdpolicy->pw_minlength = SLAPD_DEFAULT_PW_MINLENGTH;
- pwdpolicy->pw_mindigits = SLAPD_DEFAULT_PW_MINDIGITS;
- pwdpolicy->pw_minalphas = SLAPD_DEFAULT_PW_MINALPHAS;
- pwdpolicy->pw_minuppers = SLAPD_DEFAULT_PW_MINUPPERS;
- pwdpolicy->pw_minlowers = SLAPD_DEFAULT_PW_MINLOWERS;
- pwdpolicy->pw_minspecials = SLAPD_DEFAULT_PW_MINSPECIALS;
- pwdpolicy->pw_min8bit = SLAPD_DEFAULT_PW_MIN8BIT;
- pwdpolicy->pw_maxrepeats = SLAPD_DEFAULT_PW_MAXREPEATS;
- pwdpolicy->pw_mincategories = SLAPD_DEFAULT_PW_MINCATEGORIES;
- pwdpolicy->pw_maxage = SLAPD_DEFAULT_PW_MAXAGE;
- pwdpolicy->pw_minage = SLAPD_DEFAULT_PW_MINAGE;
- pwdpolicy->pw_warning = SLAPD_DEFAULT_PW_WARNING;
- pwdpolicy->pw_inhistory = SLAPD_DEFAULT_PW_INHISTORY;
- pwdpolicy->pw_maxfailure = SLAPD_DEFAULT_PW_MAXFAILURE;
- pwdpolicy->pw_lockduration = SLAPD_DEFAULT_PW_LOCKDURATION;
- pwdpolicy->pw_resetfailurecount = SLAPD_DEFAULT_PW_RESETFAILURECOUNT;
- pwdpolicy->pw_gracelimit = SLAPD_DEFAULT_PW_GRACELIMIT;
-
- /* set the default passwordLegacyPolicy setting */
- pwdpolicy->pw_is_legacy = 1;
-
- /* set passwordTrackUpdateTime */
- pwdpolicy->pw_track_update_time = slapdFrontendConfig->pw_policy.pw_track_update_time;
+ /* Set the default values (from libglobs.c) */
+ pwpolicy_init_defaults(pwdpolicy);
+ pwdpolicy->pw_storagescheme = slapdFrontendConfig->pw_storagescheme;
+ /* Set the defined values now */
for (slapi_entry_first_attr(pw_entry, &attr); attr;
slapi_entry_next_attr(pw_entry, attr, &attr)) {
slapi_attr_get_type(attr, &attr_name);
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 08754d8fb..f6fc374a4 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1773,6 +1773,8 @@ typedef struct passwordpolicyarray
Slapi_DN **pw_admin_user;
} passwdPolicy;
+void pwpolicy_init_defaults (passwdPolicy *pw_policy);
+
Slapi_PBlock *slapi_pblock_clone(Slapi_PBlock *pb); /* deprecated */
passwdPolicy *slapi_pblock_get_pwdpolicy(Slapi_PBlock *pb);
--
2.13.6

View file

@ -1,74 +0,0 @@
From 38ca528af83f1874a79ad6744215bd4af1404414 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 18 Jan 2018 13:17:08 -0500
Subject: [PATCH] Ticket 49541 - repl config should not allow rid 65535 for
masters
Description: Reject adding a replica config entry with a rid of 65535 or higher,
and prevent setting master's rid to 65535 or higher.
https://pagure.io/389-ds-base/issue/49541
Reviewed by: mreynolds(one line commit rule)
(cherry picked from commit ebb00a4180693225cf3c2f4aced54dc33141fa77)
---
dirsrvtests/tests/suites/replication/replica_config_test.py | 9 +++++----
ldap/servers/plugins/replication/repl5_replica.c | 2 +-
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/dirsrvtests/tests/suites/replication/replica_config_test.py b/dirsrvtests/tests/suites/replication/replica_config_test.py
index 50ea2ece9..143a12479 100644
--- a/dirsrvtests/tests/suites/replication/replica_config_test.py
+++ b/dirsrvtests/tests/suites/replication/replica_config_test.py
@@ -24,7 +24,7 @@ replica_dict = {'objectclass': 'top nsDS5Replica'.split(),
'nsDS5ReplicaRoot': 'dc=example,dc=com',
'nsDS5ReplicaType': '3',
'nsDS5Flags': '1',
- 'nsDS5ReplicaId': '65535',
+ 'nsDS5ReplicaId': '65534',
'nsds5ReplicaPurgeDelay': '604800',
'nsDS5ReplicaBindDN': 'cn=u',
'cn': 'replica'}
@@ -42,7 +42,7 @@ agmt_dict = {'objectClass': 'top nsDS5ReplicationAgreement'.split(),
repl_add_attrs = [('nsDS5ReplicaType', '-1', '4', overflow, notnum, '1'),
('nsDS5Flags', '-1', '2', overflow, notnum, '1'),
- ('nsDS5ReplicaId', '0', '65536', overflow, notnum, '1'),
+ ('nsDS5ReplicaId', '0', '65535', overflow, notnum, '1'),
('nsds5ReplicaPurgeDelay', '-2', too_big, overflow, notnum, '1'),
('nsDS5ReplicaBindDnGroupCheckInterval', '-2', too_big, overflow, notnum, '1'),
('nsds5ReplicaTombstonePurgeInterval', '-2', too_big, overflow, notnum, '1'),
@@ -60,7 +60,8 @@ repl_mod_attrs = [('nsDS5Flags', '-1', '2', overflow, notnum, '1'),
('nsds5ReplicaBackoffMin', '0', too_big, overflow, notnum, '3'),
('nsds5ReplicaBackoffMax', '0', too_big, overflow, notnum, '6')]
-agmt_attrs = [('nsds5ReplicaPort', '0', '65536', overflow, notnum, '389'),
+agmt_attrs = [
+ ('nsds5ReplicaPort', '0', '65535', overflow, notnum, '389'),
('nsds5ReplicaTimeout', '-1', too_big, overflow, notnum, '6'),
('nsds5ReplicaBusyWaitTime', '-1', too_big, overflow, notnum, '6'),
('nsds5ReplicaSessionPauseTime', '-1', too_big, overflow, notnum, '6'),
@@ -393,5 +394,5 @@ if __name__ == '__main__':
# Run isolated
# -s for DEBUG mode
CURRENT_FILE = os.path.realpath(__file__)
- pytest.main("-s %s" % CURRENT_FILE)
+ pytest.main(["-s", CURRENT_FILE])
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index e75807a62..bdb8a5167 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -1988,7 +1988,7 @@ _replica_init_from_config(Replica *r, Slapi_Entry *e, char *errortext)
r->repl_type == REPLICA_TYPE_PRIMARY) {
if ((val = slapi_entry_attr_get_charptr(e, attr_replicaId))) {
int64_t rid;
- if (repl_config_valid_num(attr_replicaId, val, 1, 65535, &rc, errormsg, &rid) != 0) {
+ if (repl_config_valid_num(attr_replicaId, val, 1, 65534, &rc, errormsg, &rid) != 0) {
slapi_ch_free_string(&val);
return -1;
}
--
2.13.6

View file

@ -1,111 +0,0 @@
From cb008bcace2510f157ccec2df4e5ff254513b7c4 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Mon, 15 Jan 2018 10:24:41 +0100
Subject: [PATCH] CVE 2017-15134 - crash in slapi_filter_sprintf
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
---
ldap/servers/slapd/util.c | 36 +++++++++++++++++++++++++++++++-----
1 file changed, 31 insertions(+), 5 deletions(-)
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index a72de9b07..ddb2cc899 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -238,9 +238,10 @@ escape_string_for_filename(const char *str, char buf[BUFSIZ])
struct filter_ctx
{
char *buf;
- char attr[ATTRSIZE];
+ char *attr;
int attr_position;
int attr_found;
+ size_t attr_size;
int buf_size;
int buf_len;
int next_arg_needs_esc_norm;
@@ -279,7 +280,7 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen)
* Start collecting the attribute name so we can use the correct
* syntax normalization func.
*/
- if (ctx->attr_found == 0 && ctx->attr_position < (ATTRSIZE - 1)) {
+ if (ctx->attr_found == 0 && ctx->attr_position < (ctx->attr_size - 1)) {
if (ctx->attr[0] == '\0') {
if (strstr(val, "=")) {
/* we have an attr we need to record */
@@ -293,6 +294,14 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen)
* attr with val. The next pass should be '=', otherwise we will
* reset it.
*/
+ if (slen > ctx->attr_size) {
+ if (ctx->attr_size == ATTRSIZE) {
+ ctx->attr = slapi_ch_calloc(sizeof(char), slen+1);
+ } else {
+ ctx->attr = slapi_ch_realloc(ctx->attr, sizeof(char) * (slen+1));
+ }
+ ctx->attr_size = slen+1;
+ }
memcpy(ctx->attr, val, slen);
ctx->attr_position = slen;
}
@@ -302,9 +311,20 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen)
} else {
if (special_attr_char(val[0])) {
/* this is not an attribute, we should not be collecting this, reset everything */
- memset(ctx->attr, '\0', ATTRSIZE);
+ memset(ctx->attr, '\0', ctx->attr_size);
ctx->attr_position = 0;
} else {
+ /* we can be adding char by char and overrun allocated size */
+ if (ctx->attr_position >= ctx->attr_size) {
+ if (ctx->attr_size == ATTRSIZE) {
+ char *ctxattr = slapi_ch_calloc(sizeof(char), ctx->attr_size + ATTRSIZE);
+ memcpy(ctxattr, ctx->attr, ctx->attr_size);
+ ctx->attr = ctxattr;
+ } else {
+ ctx->attr = slapi_ch_realloc(ctx->attr, sizeof(char) * (ctx->attr_size + ATTRSIZE));
+ }
+ ctx->attr_size = ctx->attr_size + ATTRSIZE;
+ }
memcpy(ctx->attr + ctx->attr_position, val, 1);
ctx->attr_position++;
}
@@ -377,7 +397,7 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen)
ctx->next_arg_needs_esc_norm = 0;
ctx->attr_found = 0;
ctx->attr_position = 0;
- memset(ctx->attr, '\0', ATTRSIZE);
+ memset(ctx->attr, '\0', ctx->attr_size);
slapi_ch_free_string(&buf);
return filter_len;
@@ -416,12 +436,14 @@ slapi_filter_sprintf(const char *fmt, ...)
{
struct filter_ctx ctx = {0};
va_list args;
+ char attr_static[ATTRSIZE] = {0};
char *buf;
int rc;
buf = slapi_ch_calloc(sizeof(char), FILTER_BUF + 1);
ctx.buf = buf;
- memset(ctx.attr, '\0', ATTRSIZE);
+ ctx.attr = attr_static;
+ ctx.attr_size = ATTRSIZE;
ctx.attr_position = 0;
ctx.attr_found = 0;
ctx.buf_len = FILTER_BUF;
@@ -438,6 +460,10 @@ slapi_filter_sprintf(const char *fmt, ...)
}
va_end(args);
+ if (ctx.attr_size > ATTRSIZE) {
+ slapi_ch_free_string(&ctx.attr);
+ }
+
return ctx.buf;
}
--
2.13.6

View file

@ -1,37 +0,0 @@
From 3c605035eff49e603c8e4a4c0886499913924529 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 24 Jan 2018 14:24:08 -0500
Subject: [PATCH] Ticket 49534 - Fix coverity regression
Description: In automembers plugin a free was in the wrong spot
which later led to a double free for the "rule".
https://pagure.io/389-ds-base/issue/49534
Reviewed by: mreynolds (one line commit rule)
(cherry picked from commit b3768e602fdfc2ea1fc645b17ad61c8592ab87fa)
---
ldap/servers/plugins/automember/automember.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
index cbd25915a..c91aa4e8e 100644
--- a/ldap/servers/plugins/automember/automember.c
+++ b/ldap/servers/plugins/automember/automember.c
@@ -1117,11 +1117,11 @@ automember_parse_regex_entry(struct configEntry *config, Slapi_Entry *e)
break;
}
}
+ automember_free_regex_rule(rule);
} else {
/* Add to head of list */
PR_INSERT_LINK(&(rule->list), (PRCList *)config->exclusive_rules);
}
- automember_free_regex_rule(rule);
} else {
slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
"automember_parse_regex_entry - Skipping invalid exclusive "
--
2.13.6

View file

@ -1,31 +0,0 @@
From d39be97021f273548957a9f26ca35d5faab20318 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 29 Jan 2018 21:13:16 -0500
Subject: [PATCH] Ticket 49541 - Replica ID config validation fix
Description: Is is possible to set the replica ID to 65535 with a modify
operation, which is reserved for hubs/consumers.
https://pagure.io/389-ds-base/issue/49541
Reviewed by: mreynolds (one line commit rule)
---
ldap/servers/plugins/replication/repl5_replica_config.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index bda333362..ea430d9a4 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -421,7 +421,7 @@ replica_config_modify(Slapi_PBlock *pb,
}
} else if (strcasecmp(config_attr, attr_replicaId) == 0) {
int64_t rid = 0;
- if (repl_config_valid_num(config_attr, config_attr_value, 1, 65535, returncode, errortext, &rid) == 0) {
+ if (repl_config_valid_num(config_attr, config_attr_value, 1, 65534, returncode, errortext, &rid) == 0) {
slapi_ch_free_string(&new_repl_id);
new_repl_id = slapi_ch_strdup(config_attr_value);
} else {
--
2.13.6

View file

@ -1,109 +0,0 @@
From 3bdd7b5cccd2993c5ae5b9d893be15c71373aaf8 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 29 Jan 2018 11:53:33 -0500
Subject: [PATCH] Ticket 49370 - Crash when using a global and local pw
policies
Description: This a regression from the previous patch. We were
accidently using a reference to the global pw policy
password storage scheme, which was getting freed after
pblock was done from an operation. The next operation
then used(and double freed) this memory on the next
operation.
https://pagure.io/389-ds-base/issue/49370
Reviewed by: tbordaz (Thanks!)
(cherry picked from commit d86e0f9634e694feb378ee335d29b2e89fd27e2c)
---
ldap/servers/slapd/pw.c | 32 +++++++++++++++++---------------
1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 3a545e12e..451be364d 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -209,7 +209,7 @@ pw_name2scheme(char *name)
struct pw_scheme *pwsp;
struct slapdplugin *p;
- if ((p = plugin_get_pwd_storage_scheme(name, strlen(name), PLUGIN_LIST_PWD_STORAGE_SCHEME)) != NULL) {
+ if (name != NULL && (p = plugin_get_pwd_storage_scheme(name, strlen(name), PLUGIN_LIST_PWD_STORAGE_SCHEME)) != NULL) {
pwsp = (struct pw_scheme *)slapi_ch_malloc(sizeof(struct pw_scheme));
if (pwsp != NULL) {
typedef int (*CMPFP)(char *, char *);
@@ -1612,18 +1612,18 @@ pw_get_admin_users(passwdPolicy *pwp)
passwdPolicy *
new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
{
+ slapdFrontendConfig_t *slapdFrontendConfig = NULL;
Slapi_ValueSet *values = NULL;
+ Slapi_Value **sval = NULL;
Slapi_Entry *e = NULL, *pw_entry = NULL;
- int type_name_disposition = 0;
+ passwdPolicy *pwdpolicy = NULL;
+ Slapi_Attr *attr = NULL;
+ char *pwscheme_name = NULL;
+ char *attr_name = NULL;
char *actual_type_name = NULL;
+ int type_name_disposition = 0;
int attr_free_flags = 0;
int rc = 0;
- passwdPolicy *pwdpolicy = NULL;
- struct pw_scheme *pwdscheme = NULL;
- Slapi_Attr *attr;
- char *attr_name;
- Slapi_Value **sval;
- slapdFrontendConfig_t *slapdFrontendConfig;
int optype = -1;
/* If we already allocated a pw policy, return it */
@@ -1717,9 +1717,7 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
pw_entry = get_entry(pb, bvp->bv_val);
}
}
-
slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags);
-
slapi_entry_free(e);
if (pw_entry == NULL) {
@@ -1732,7 +1730,11 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
/* Set the default values (from libglobs.c) */
pwpolicy_init_defaults(pwdpolicy);
- pwdpolicy->pw_storagescheme = slapdFrontendConfig->pw_storagescheme;
+
+ /* Set the current storage scheme */
+ pwscheme_name = config_get_pw_storagescheme();
+ pwdpolicy->pw_storagescheme = pw_name2scheme(pwscheme_name);
+ slapi_ch_free_string(&pwscheme_name);
/* Set the defined values now */
for (slapi_entry_first_attr(pw_entry, &attr); attr;
@@ -1865,6 +1867,7 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
}
} else if (!strcasecmp(attr_name, "passwordstoragescheme")) {
if ((sval = attr_get_present_values(attr))) {
+ free_pw_scheme(pwdpolicy->pw_storagescheme);
pwdpolicy->pw_storagescheme =
pw_name2scheme((char *)slapi_value_get_string(*sval));
}
@@ -1924,10 +1927,9 @@ done:
* structure from slapdFrontendconfig
*/
*pwdpolicy = slapdFrontendConfig->pw_policy;
- pwdscheme = (struct pw_scheme *)slapi_ch_calloc(1, sizeof(struct pw_scheme));
- *pwdscheme = *slapdFrontendConfig->pw_storagescheme;
- pwdscheme->pws_name = strdup(slapdFrontendConfig->pw_storagescheme->pws_name);
- pwdpolicy->pw_storagescheme = pwdscheme;
+ pwscheme_name = config_get_pw_storagescheme();
+ pwdpolicy->pw_storagescheme = pw_name2scheme(pwscheme_name);
+ slapi_ch_free_string(&pwscheme_name);
pwdpolicy->pw_admin = slapi_sdn_dup(slapdFrontendConfig->pw_policy.pw_admin);
pw_get_admin_users(pwdpolicy);
if (pb) {
--
2.13.6

View file

@ -1,320 +0,0 @@
From 656b141630c5f37a953a75ff05d3a1a30b14eef1 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 1 Feb 2018 14:28:24 -0500
Subject: [PATCH] Ticket 49557 - Add config option for checking CRL on outbound
SSL Connections
Bug Description: There are cases where a CRL is not available during an outbound
replication connection. This is seen as an error by openldap,
and the connection fails.
Fix Description: Add on/off option for checking the CRL. The default is not to
check the CRL.
https://pagure.io/389-ds-base/issue/49557
Reviewed by: wibrown, Ludwig Krispenz, Thierry Bordaz
---
dirsrvtests/tests/suites/{ssl => tls}/__init__.py | 0
dirsrvtests/tests/suites/tls/tls_check_crl_test.py | 52 +++++++++++++++++
ldap/schema/01core389.ldif | 1 +
ldap/servers/slapd/ldaputil.c | 9 ++-
ldap/servers/slapd/libglobs.c | 66 +++++++++++++++++++++-
ldap/servers/slapd/proto-slap.h | 2 +
ldap/servers/slapd/slap.h | 10 +++-
7 files changed, 135 insertions(+), 5 deletions(-)
rename dirsrvtests/tests/suites/{ssl => tls}/__init__.py (100%)
create mode 100644 dirsrvtests/tests/suites/tls/tls_check_crl_test.py
diff --git a/dirsrvtests/tests/suites/ssl/__init__.py b/dirsrvtests/tests/suites/tls/__init__.py
similarity index 100%
rename from dirsrvtests/tests/suites/ssl/__init__.py
rename to dirsrvtests/tests/suites/tls/__init__.py
diff --git a/dirsrvtests/tests/suites/tls/tls_check_crl_test.py b/dirsrvtests/tests/suites/tls/tls_check_crl_test.py
new file mode 100644
index 000000000..8b4d07f94
--- /dev/null
+++ b/dirsrvtests/tests/suites/tls/tls_check_crl_test.py
@@ -0,0 +1,52 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2018 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+
+
+import pytest
+import ldap
+from lib389.topologies import topology_st
+
+def test_tls_check_crl(topology_st):
+ """Test that TLS check_crl configurations work as expected.
+
+ :id:
+ :steps:
+ 1. Enable TLS
+ 2. Set invalid value
+ 3. Set valid values
+ 4. Check config reset
+ :expectedresults:
+ 1. TlS is setup
+ 2. The invalid value is rejected
+ 3. The valid values are used
+ 4. The value can be reset
+ """
+ standalone = topology_st.standalone
+ # Enable TLS
+ standalone.enable_tls()
+ # Check all the valid values.
+ assert(standalone.config.get_attr_val_utf8('nsslapd-tls-check-crl') == 'none')
+ with pytest.raises(ldap.OPERATIONS_ERROR):
+ standalone.config.set('nsslapd-tls-check-crl', 'tnhoeutnoeutn')
+ assert(standalone.config.get_attr_val_utf8('nsslapd-tls-check-crl') == 'none')
+
+ standalone.config.set('nsslapd-tls-check-crl', 'peer')
+ assert(standalone.config.get_attr_val_utf8('nsslapd-tls-check-crl') == 'peer')
+
+ standalone.config.set('nsslapd-tls-check-crl', 'none')
+ assert(standalone.config.get_attr_val_utf8('nsslapd-tls-check-crl') == 'none')
+
+ standalone.config.set('nsslapd-tls-check-crl', 'all')
+ assert(standalone.config.get_attr_val_utf8('nsslapd-tls-check-crl') == 'all')
+
+ standalone.config.remove_all('nsslapd-tls-check-crl')
+ assert(standalone.config.get_attr_val_utf8('nsslapd-tls-check-crl') == 'none')
+
+
+
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index ab124c86c..c7f9fef2b 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -304,6 +304,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2332 NAME 'allowWeakDHParam' DESC 'Netsc
attributeTypes: ( 2.16.840.1.113730.3.1.2333 NAME 'nsds5ReplicaReleaseTimeout' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2335 NAME 'nsds5ReplicaIgnoreMissingChange' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2336 NAME 'nsDS5ReplicaBindDnGroupCheckInterval' DESC 'Replication configuration setting for controlling the bind dn group check interval' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2344 NAME 'nsslapd-tls-check-crl' DESC 'Check CRL when opening outbound TLS connections. Valid options are none, peer, all.' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN '389 Directory Server' )
#
# objectclasses
#
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index fa9d276a3..2fc2f0615 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -570,6 +570,7 @@ slapi_ldif_parse_line(
}
#if defined(USE_OPENLDAP)
+
static int
setup_ol_tls_conn(LDAP *ld, int clientauth)
{
@@ -602,7 +603,13 @@ setup_ol_tls_conn(LDAP *ld, int clientauth)
}
}
if (slapi_client_uses_openssl(ld)) {
- const int crlcheck = LDAP_OPT_X_TLS_CRL_ALL;
+ int32_t crlcheck = LDAP_OPT_X_TLS_CRL_NONE;
+ tls_check_crl_t tls_check_state = config_get_tls_check_crl();
+ if (tls_check_state == TLS_CHECK_PEER) {
+ crlcheck = LDAP_OPT_X_TLS_CRL_PEER;
+ } else if (tls_check_state == TLS_CHECK_ALL) {
+ crlcheck = LDAP_OPT_X_TLS_CRL_ALL;
+ }
/* Sets the CRL evaluation strategy. */
rc = ldap_set_option(ld, LDAP_OPT_X_TLS_CRLCHECK, &crlcheck);
if (rc) {
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index c1a765aca..eb6552af1 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -157,7 +157,8 @@ typedef enum {
CONFIG_STRING_OR_EMPTY, /* use an empty string */
CONFIG_SPECIAL_ANON_ACCESS_SWITCH, /* maps strings to an enumeration */
CONFIG_SPECIAL_VALIDATE_CERT_SWITCH, /* maps strings to an enumeration */
- CONFIG_SPECIAL_UNHASHED_PW_SWITCH /* unhashed pw: on/off/nolog */
+ CONFIG_SPECIAL_UNHASHED_PW_SWITCH, /* unhashed pw: on/off/nolog */
+ CONFIG_SPECIAL_TLS_CHECK_CRL, /* maps enum tls_check_crl_t to char * */
} ConfigVarType;
static int32_t config_set_onoff(const char *attrname, char *value, int32_t *configvalue, char *errorbuf, int apply);
@@ -1173,7 +1174,15 @@ static struct config_get_and_set
{CONFIG_LOGGING_BACKEND, NULL,
log_set_backend, 0,
(void **)&global_slapdFrontendConfig.logging_backend,
- CONFIG_STRING_OR_EMPTY, NULL, SLAPD_INIT_LOGGING_BACKEND_INTERNAL}};
+ CONFIG_STRING_OR_EMPTY, NULL, SLAPD_INIT_LOGGING_BACKEND_INTERNAL},
+ {CONFIG_TLS_CHECK_CRL_ATTRIBUTE, config_set_tls_check_crl,
+ NULL, 0,
+ (void **)&global_slapdFrontendConfig.tls_check_crl,
+ CONFIG_SPECIAL_TLS_CHECK_CRL, (ConfigGetFunc)config_get_tls_check_crl,
+ "none" /* Allow reset to this value */}
+
+ /* End config */
+ };
/*
* hashNocaseString - used for case insensitive hash lookups
@@ -1506,7 +1515,6 @@ FrontendConfig_init(void)
cfg->maxdescriptors = SLAPD_DEFAULT_MAXDESCRIPTORS;
cfg->groupevalnestlevel = SLAPD_DEFAULT_GROUPEVALNESTLEVEL;
cfg->snmp_index = SLAPD_DEFAULT_SNMP_INDEX;
-
cfg->SSLclientAuth = SLAPD_DEFAULT_SSLCLIENTAUTH;
#ifdef USE_SYSCONF
@@ -1524,6 +1532,7 @@ FrontendConfig_init(void)
#endif
init_security = cfg->security = LDAP_OFF;
init_ssl_check_hostname = cfg->ssl_check_hostname = LDAP_ON;
+ cfg->tls_check_crl = TLS_CHECK_NONE;
init_return_exact_case = cfg->return_exact_case = LDAP_ON;
init_result_tweak = cfg->result_tweak = LDAP_OFF;
init_attrname_exceptions = cfg->attrname_exceptions = LDAP_OFF;
@@ -2042,6 +2051,7 @@ config_set_port(const char *attrname, char *port, char *errorbuf, int apply)
return retVal;
}
+
int
config_set_secureport(const char *attrname, char *port, char *errorbuf, int apply)
{
@@ -2073,6 +2083,33 @@ config_set_secureport(const char *attrname, char *port, char *errorbuf, int appl
}
+int32_t
+config_set_tls_check_crl(const char *attrname, char *value, char *errorbuf, int apply)
+{
+ int32_t retVal = LDAP_SUCCESS;
+ /* Default */
+ tls_check_crl_t state = TLS_CHECK_NONE;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ if (strcasecmp(value, "none") == 0) {
+ state = TLS_CHECK_NONE;
+ } else if (strcasecmp(value, "peer") == 0) {
+ state = TLS_CHECK_PEER;
+ } else if (strcasecmp(value, "all") == 0) {
+ state = TLS_CHECK_ALL;
+ } else {
+ retVal = LDAP_OPERATIONS_ERROR;
+ slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: unsupported value: %s", attrname, value);
+ }
+
+ if (retVal == LDAP_SUCCESS && apply) {
+ slapi_atomic_store_32((int32_t *)&(slapdFrontendConfig->tls_check_crl), state, __ATOMIC_RELEASE);
+ }
+
+ return retVal;
+}
+
+
int
config_set_SSLclientAuth(const char *attrname, char *value, char *errorbuf, int apply)
{
@@ -4591,6 +4628,12 @@ config_set_versionstring(const char *attrname __attribute__((unused)), char *ver
#define config_copy_strval(s) s ? slapi_ch_strdup(s) : NULL;
+tls_check_crl_t
+config_get_tls_check_crl() {
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ return (tls_check_crl_t)slapi_atomic_load_32((int32_t *)&(slapdFrontendConfig->tls_check_crl), __ATOMIC_ACQUIRE);
+}
+
int
config_get_port()
{
@@ -7439,6 +7482,23 @@ config_set_value(
slapi_entry_attr_set_int(e, cgas->attr_name, ival);
break;
+ case CONFIG_SPECIAL_TLS_CHECK_CRL:
+ if (!value) {
+ slapi_entry_attr_set_charptr(e, cgas->attr_name, (char *)cgas->initvalue);
+ break;
+ }
+ tls_check_crl_t state = *(tls_check_crl_t *)value;
+
+ if (state == TLS_CHECK_ALL) {
+ sval = "all";
+ } else if (state == TLS_CHECK_PEER) {
+ sval = "peer";
+ } else {
+ sval = "none";
+ }
+ slapi_entry_attr_set_charptr(e, cgas->attr_name, sval);
+ break;
+
case CONFIG_SPECIAL_SSLCLIENTAUTH:
if (!value) {
slapi_entry_attr_set_charptr(e, cgas->attr_name, "off");
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 3b7ab53b2..b13334ad1 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -236,6 +236,7 @@ int config_set_port(const char *attrname, char *port, char *errorbuf, int apply)
int config_set_secureport(const char *attrname, char *port, char *errorbuf, int apply);
int config_set_SSLclientAuth(const char *attrname, char *value, char *errorbuf, int apply);
int config_set_ssl_check_hostname(const char *attrname, char *value, char *errorbuf, int apply);
+int32_t config_set_tls_check_crl(const char *attrname, char *value, char *errorbuf, int apply);
int config_set_SSL3ciphers(const char *attrname, char *value, char *errorbuf, int apply);
int config_set_localhost(const char *attrname, char *value, char *errorbuf, int apply);
int config_set_listenhost(const char *attrname, char *value, char *errorbuf, int apply);
@@ -397,6 +398,7 @@ void log_disable_hr_timestamps(void);
int config_get_SSLclientAuth(void);
int config_get_ssl_check_hostname(void);
+tls_check_crl_t config_get_tls_check_crl(void);
char *config_get_SSL3ciphers(void);
char *config_get_localhost(void);
char *config_get_listenhost(void);
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 216d94afd..443d90094 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -443,6 +443,13 @@ typedef void (*VFPV)(); /* takes undefined arguments */
typedef int32_t slapi_onoff_t;
typedef int32_t slapi_int_t;
+typedef enum _tls_check_crl_t {
+ TLS_CHECK_NONE = 0,
+ TLS_CHECK_PEER = 1,
+ TLS_CHECK_ALL = 2,
+} tls_check_crl_t;
+
+
struct subfilt
{
char *sf_type;
@@ -2151,6 +2158,7 @@ typedef struct _slapdEntryPoints
#define CONFIG_RUNDIR_ATTRIBUTE "nsslapd-rundir"
#define CONFIG_SSLCLIENTAUTH_ATTRIBUTE "nsslapd-SSLclientAuth"
#define CONFIG_SSL_CHECK_HOSTNAME_ATTRIBUTE "nsslapd-ssl-check-hostname"
+#define CONFIG_TLS_CHECK_CRL_ATTRIBUTE "nsslapd-tls-check-crl"
#define CONFIG_HASH_FILTERS_ATTRIBUTE "nsslapd-hash-filters"
#define CONFIG_OUTBOUND_LDAP_IO_TIMEOUT_ATTRIBUTE "nsslapd-outbound-ldap-io-timeout"
#define CONFIG_FORCE_SASL_EXTERNAL_ATTRIBUTE "nsslapd-force-sasl-external"
@@ -2263,6 +2271,7 @@ typedef struct _slapdFrontendConfig
slapi_onoff_t security;
int SSLclientAuth;
slapi_onoff_t ssl_check_hostname;
+ tls_check_crl_t tls_check_crl;
int validate_cert;
int sizelimit;
int SNMPenabled;
@@ -2294,7 +2303,6 @@ typedef struct _slapdFrontendConfig
slapi_onoff_t plugin_track;
slapi_onoff_t moddn_aci;
struct pw_scheme *pw_storagescheme;
-
slapi_onoff_t pwpolicy_local;
slapi_onoff_t pw_is_global_policy;
slapi_onoff_t pwpolicy_inherit_global;
--
2.13.6

View file

@ -1,120 +0,0 @@
From 10ec64288dcc25fd855bc05601bc4794ecea2003 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Tue, 6 Feb 2018 19:49:22 +0100
Subject: [PATCH] Ticket 49560 - nsslapd-extract-pemfiles should be enabled by
default as openldap is moving to openssl
Bug Description:
Due to a change in the OpenLDAP client libraries (switching from NSS to OpenSSL),
the TLS options LDAP_OPT_X_TLS_CACERTFILE, LDAP_OPT_X_TLS_KEYFILE, LDAP_OPT_X_TLS_CERTFILE,
need to specify path to PEM files.
Those PEM files are extracted from the key/certs from the NSS db in /etc/dirsrv/slapd-xxx
Those files are extracted if the option (under 'cn=config') nsslapd-extract-pemfiles is set to 'on'.
The default value is 'off', that prevent secure outgoing connection.
Fix Description:
Enable nsslapd-extract-pemfiles by default
Then when establishing an outgoing connection, if it is not using NSS crypto layer
and the pem files have been extracted then use the PEM files
https://pagure.io/389-ds-base/issue/49560
Reviewed by: mreynolds & mhonek
Platforms tested: RHEL 7.5
Flag Day: no
Doc impact: no
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
(cherry picked from commit 8304caec593b591558c9c18de9bcb6b2f23db5b6)
---
ldap/servers/slapd/ldaputil.c | 32 ++++++++++++++++----------------
ldap/servers/slapd/libglobs.c | 2 +-
ldap/servers/slapd/ssl.c | 2 +-
3 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index 2fc2f0615..fcf22e632 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -591,7 +591,7 @@ setup_ol_tls_conn(LDAP *ld, int clientauth)
slapi_log_err(SLAPI_LOG_ERR, "setup_ol_tls_conn",
"failed: unable to set REQUIRE_CERT option to %d\n", ssl_strength);
}
- if (slapi_client_uses_non_nss(ld)) {
+ if (slapi_client_uses_non_nss(ld) && config_get_extract_pem()) {
cacert = slapi_get_cacertfile();
if (cacert) {
/* CA Cert PEM file exists. Set the path to openldap option. */
@@ -602,21 +602,21 @@ setup_ol_tls_conn(LDAP *ld, int clientauth)
cacert, rc, ldap_err2string(rc));
}
}
- if (slapi_client_uses_openssl(ld)) {
- int32_t crlcheck = LDAP_OPT_X_TLS_CRL_NONE;
- tls_check_crl_t tls_check_state = config_get_tls_check_crl();
- if (tls_check_state == TLS_CHECK_PEER) {
- crlcheck = LDAP_OPT_X_TLS_CRL_PEER;
- } else if (tls_check_state == TLS_CHECK_ALL) {
- crlcheck = LDAP_OPT_X_TLS_CRL_ALL;
- }
- /* Sets the CRL evaluation strategy. */
- rc = ldap_set_option(ld, LDAP_OPT_X_TLS_CRLCHECK, &crlcheck);
- if (rc) {
- slapi_log_err(SLAPI_LOG_ERR, "setup_ol_tls_conn",
- "Could not set CRLCHECK [%d]: %d:%s\n",
- crlcheck, rc, ldap_err2string(rc));
- }
+ }
+ if (slapi_client_uses_openssl(ld)) {
+ int32_t crlcheck = LDAP_OPT_X_TLS_CRL_NONE;
+ tls_check_crl_t tls_check_state = config_get_tls_check_crl();
+ if (tls_check_state == TLS_CHECK_PEER) {
+ crlcheck = LDAP_OPT_X_TLS_CRL_PEER;
+ } else if (tls_check_state == TLS_CHECK_ALL) {
+ crlcheck = LDAP_OPT_X_TLS_CRL_ALL;
+ }
+ /* Sets the CRL evaluation strategy. */
+ rc = ldap_set_option(ld, LDAP_OPT_X_TLS_CRLCHECK, &crlcheck);
+ if (rc) {
+ slapi_log_err(SLAPI_LOG_ERR, "setup_ol_tls_conn",
+ "Could not set CRLCHECK [%d]: %d:%s\n",
+ crlcheck, rc, ldap_err2string(rc));
}
}
/* tell it where our cert db/file is */
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index eb6552af1..3bd5c1826 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -1688,7 +1688,7 @@ FrontendConfig_init(void)
init_malloc_mmap_threshold = cfg->malloc_mmap_threshold = DEFAULT_MALLOC_UNSET;
#endif
- init_extract_pem = cfg->extract_pem = LDAP_OFF;
+ init_extract_pem = cfg->extract_pem = LDAP_ON;
/* Done, unlock! */
CFG_UNLOCK_WRITE(cfg);
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index 52ac7ea9f..36b09fd16 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -2462,7 +2462,7 @@ slapd_SSL_client_auth(LDAP *ld)
errorCode, slapd_pr_strerror(errorCode));
} else {
#if defined(USE_OPENLDAP)
- if (slapi_client_uses_non_nss(ld)) {
+ if (slapi_client_uses_non_nss(ld) && config_get_extract_pem()) {
char *certdir = config_get_certdir();
char *keyfile = NULL;
char *certfile = NULL;
--
2.13.6

View file

@ -1,286 +0,0 @@
From 40fcaabfaa2c865471cc5fb1fab04106bc3ec611 Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Thu, 18 Jan 2018 11:27:58 +1000
Subject: [PATCH] Ticket bz1525628 - invalid password migration causes unauth
bind
Bug Description: Slapi_ct_memcmp expects both inputs to be
at LEAST size n. If they are not, we only compared UP to n.
Invalid migrations of passwords (IE {CRYPT}XX) would create
a pw which is just salt and no hash. ct_memcmp would then
only verify the salt bits and would allow the authentication.
This relies on an administrative mistake both of allowing
password migration (nsslapd-allow-hashed-passwords) and then
subsequently migrating an INVALID password to the server.
Fix Description: slapi_ct_memcmp now access n1, n2 size
and will FAIL if they are not the same, but will still compare
n bytes, where n is the "longest" memory, to the first byte
of the other to prevent length disclosure of the shorter
value (generally the mis-migrated password)
https://bugzilla.redhat.com/show_bug.cgi?id=1525628
Author: wibrown
Review by: ???
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
---
.../bz1525628_ct_memcmp_invalid_hash_test.py | 56 ++++++++++++++++++++++
ldap/servers/plugins/pwdstorage/clear_pwd.c | 4 +-
ldap/servers/plugins/pwdstorage/crypt_pwd.c | 4 +-
ldap/servers/plugins/pwdstorage/md5_pwd.c | 4 +-
ldap/servers/plugins/pwdstorage/sha_pwd.c | 16 +++++--
ldap/servers/plugins/pwdstorage/smd5_pwd.c | 2 +-
ldap/servers/slapd/ch_malloc.c | 36 ++++++++++++--
ldap/servers/slapd/slapi-plugin.h | 2 +-
8 files changed, 108 insertions(+), 16 deletions(-)
create mode 100644 dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py
diff --git a/dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py b/dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py
new file mode 100644
index 000000000..2f38384a1
--- /dev/null
+++ b/dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py
@@ -0,0 +1,56 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2018 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+
+import ldap
+import pytest
+import logging
+from lib389.topologies import topology_st
+from lib389._constants import PASSWORD, DEFAULT_SUFFIX
+
+from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+def test_invalid_hash_fails(topology_st):
+ """When given a malformed hash from userpassword migration
+ slapi_ct_memcmp would check only to the length of the shorter
+ field. This affects some values where it would ONLY verify
+ the salt is valid, and thus would allow any password to bind.
+
+ :id: 8131c029-7147-47db-8d03-ec5db2a01cfb
+ :setup: Standalone Instance
+ :steps:
+ 1. Create a user
+ 2. Add an invalid password hash (truncated)
+ 3. Attempt to bind
+ :expectedresults:
+ 1. User is added
+ 2. Invalid pw hash is added
+ 3. Bind fails
+ """
+ log.info("Running invalid hash test")
+
+ # Allow setting raw password hashes for migration.
+ topology_st.standalone.config.set('nsslapd-allow-hashed-passwords', 'on')
+
+ users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX)
+ user = users.create(properties=TEST_USER_PROPERTIES)
+ user.set('userPassword', '{CRYPT}XX')
+
+ # Attempt to bind. This should fail.
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
+ user.bind(PASSWORD)
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
+ user.bind('XX')
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
+ user.bind('{CRYPT}XX')
+
+ log.info("PASSED")
+
diff --git a/ldap/servers/plugins/pwdstorage/clear_pwd.c b/ldap/servers/plugins/pwdstorage/clear_pwd.c
index f5e6f9d4c..3d340752d 100644
--- a/ldap/servers/plugins/pwdstorage/clear_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/clear_pwd.c
@@ -39,7 +39,7 @@ clear_pw_cmp(const char *userpwd, const char *dbpwd)
* However, even if the first part of userpw matches dbpwd, but len !=, we
* have already failed anyawy. This prevents substring matching.
*/
- if (slapi_ct_memcmp(userpwd, dbpwd, len_dbp) != 0) {
+ if (slapi_ct_memcmp(userpwd, dbpwd, len_user, len_dbp) != 0) {
result = 1;
}
} else {
@@ -51,7 +51,7 @@ clear_pw_cmp(const char *userpwd, const char *dbpwd)
* dbpwd to itself. We have already got result == 1 if we are here, so we are
* just trying to take up time!
*/
- if (slapi_ct_memcmp(dbpwd, dbpwd, len_dbp)) {
+ if (slapi_ct_memcmp(dbpwd, dbpwd, len_dbp, len_dbp)) {
/* Do nothing, we have the if to fix a coverity check. */
}
}
diff --git a/ldap/servers/plugins/pwdstorage/crypt_pwd.c b/ldap/servers/plugins/pwdstorage/crypt_pwd.c
index 3bd226581..0dccd1b51 100644
--- a/ldap/servers/plugins/pwdstorage/crypt_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/crypt_pwd.c
@@ -65,13 +65,13 @@ crypt_close(Slapi_PBlock *pb __attribute__((unused)))
int
crypt_pw_cmp(const char *userpwd, const char *dbpwd)
{
- int rc;
+ int32_t rc;
char *cp;
PR_Lock(cryptlock);
/* we use salt (first 2 chars) of encoded password in call to crypt() */
cp = crypt(userpwd, dbpwd);
if (cp) {
- rc = slapi_ct_memcmp(dbpwd, cp, strlen(dbpwd));
+ rc = slapi_ct_memcmp(dbpwd, cp, strlen(dbpwd), strlen(cp));
} else {
rc = -1;
}
diff --git a/ldap/servers/plugins/pwdstorage/md5_pwd.c b/ldap/servers/plugins/pwdstorage/md5_pwd.c
index 1e2cf58e7..2c2aacaa6 100644
--- a/ldap/servers/plugins/pwdstorage/md5_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/md5_pwd.c
@@ -30,7 +30,7 @@
int
md5_pw_cmp(const char *userpwd, const char *dbpwd)
{
- int rc = -1;
+ int32_t rc = -1;
char *bver;
PK11Context *ctx = NULL;
unsigned int outLen;
@@ -57,7 +57,7 @@ md5_pw_cmp(const char *userpwd, const char *dbpwd)
bver = NSSBase64_EncodeItem(NULL, (char *)b2a_out, sizeof b2a_out, &binary_item);
/* bver points to b2a_out upon success */
if (bver) {
- rc = slapi_ct_memcmp(bver, dbpwd, strlen(dbpwd));
+ rc = slapi_ct_memcmp(bver, dbpwd, strlen(dbpwd), strlen(bver));
} else {
slapi_log_err(SLAPI_LOG_PLUGIN, MD5_SUBSYSTEM_NAME,
"Could not base64 encode hashed value for password compare");
diff --git a/ldap/servers/plugins/pwdstorage/sha_pwd.c b/ldap/servers/plugins/pwdstorage/sha_pwd.c
index 1fbe0bc82..381b31d7c 100644
--- a/ldap/servers/plugins/pwdstorage/sha_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/sha_pwd.c
@@ -49,7 +49,7 @@ sha_pw_cmp(const char *userpwd, const char *dbpwd, unsigned int shaLen)
char userhash[MAX_SHA_HASH_SIZE];
char quick_dbhash[MAX_SHA_HASH_SIZE + SHA_SALT_LENGTH + 3];
char *dbhash = quick_dbhash;
- struct berval salt;
+ struct berval salt = {0};
PRUint32 hash_len;
unsigned int secOID;
char *schemeName;
@@ -122,9 +122,19 @@ sha_pw_cmp(const char *userpwd, const char *dbpwd, unsigned int shaLen)
/* the proof is in the comparison... */
if (hash_len >= shaLen) {
- result = slapi_ct_memcmp(userhash, dbhash, shaLen);
+ /*
+ * This say "if the hash has a salt IE >, OR if they are equal, check the hash component ONLY.
+ * This is why we repeat shaLen twice, even though it seems odd. If you have a dbhast of ssha
+ * it's len is 28, and the userpw is 20, but 0 - 20 is the sha, and 21-28 is the salt, which
+ * has already been processed into userhash.
+ * The case where dbpwd is truncated is handled above in "invalid base64" arm.
+ */
+ result = slapi_ct_memcmp(userhash, dbhash, shaLen, shaLen);
} else {
- result = slapi_ct_memcmp(userhash, dbhash + OLD_SALT_LENGTH, hash_len - OLD_SALT_LENGTH);
+ /* This case is for if the salt is at the START, which only applies to DS40B1 case.
+ * May never be a valid check...
+ */
+ result = slapi_ct_memcmp(userhash, dbhash + OLD_SALT_LENGTH, shaLen, hash_len - OLD_SALT_LENGTH);
}
loser:
diff --git a/ldap/servers/plugins/pwdstorage/smd5_pwd.c b/ldap/servers/plugins/pwdstorage/smd5_pwd.c
index a83ac6fa4..cbfc74ff3 100644
--- a/ldap/servers/plugins/pwdstorage/smd5_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/smd5_pwd.c
@@ -82,7 +82,7 @@ smd5_pw_cmp(const char *userpwd, const char *dbpwd)
PK11_DestroyContext(ctx, 1);
/* Compare everything up to the salt. */
- rc = slapi_ct_memcmp(userhash, dbhash, MD5_LENGTH);
+ rc = slapi_ct_memcmp(userhash, dbhash, MD5_LENGTH, MD5_LENGTH);
loser:
if (dbhash && dbhash != quick_dbhash)
diff --git a/ldap/servers/slapd/ch_malloc.c b/ldap/servers/slapd/ch_malloc.c
index ef436b3e8..90a2b2c1a 100644
--- a/ldap/servers/slapd/ch_malloc.c
+++ b/ldap/servers/slapd/ch_malloc.c
@@ -336,8 +336,8 @@ slapi_ch_smprintf(const char *fmt, ...)
/* Constant time memcmp. Does not shortcircuit on failure! */
/* This relies on p1 and p2 both being size at least n! */
-int
-slapi_ct_memcmp(const void *p1, const void *p2, size_t n)
+int32_t
+slapi_ct_memcmp(const void *p1, const void *p2, size_t n1, size_t n2)
{
int result = 0;
const unsigned char *_p1 = (const unsigned char *)p1;
@@ -347,9 +347,35 @@ slapi_ct_memcmp(const void *p1, const void *p2, size_t n)
return 2;
}
- for (size_t i = 0; i < n; i++) {
- if (_p1[i] ^ _p2[i]) {
- result = 1;
+ if (n1 == n2) {
+ for (size_t i = 0; i < n1; i++) {
+ if (_p1[i] ^ _p2[i]) {
+ result = 1;
+ }
+ }
+ } else {
+ const unsigned char *_pa;
+ const unsigned char *_pb;
+ size_t nl;
+ if (n2 > n1) {
+ _pa = _p2;
+ _pb = _p2;
+ nl = n2;
+ } else {
+ _pa = _p1;
+ _pb = _p1;
+ nl = n1;
+ }
+ /* We already fail as n1 != n2 */
+ result = 3;
+ for (size_t i = 0; i < nl; i++) {
+ if (_pa[i] ^ _pb[i]) {
+ /*
+ * If we don't mutate result here, dead code elimination
+ * we remove for loop.
+ */
+ result = 4;
+ }
}
}
return result;
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 4566202d3..95cdcc0da 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5862,7 +5862,7 @@ char *slapi_ch_smprintf(const char *fmt, ...)
* \param n length in bytes of the content of p1 AND p2.
* \return 0 on match. 1 on non-match. 2 on presence of NULL pointer in p1 or p2.
*/
-int slapi_ct_memcmp(const void *p1, const void *p2, size_t n);
+int32_t slapi_ct_memcmp(const void *p1, const void *p2, size_t n1, size_t n2);
/*
* syntax plugin routines
--
2.13.6

View file

@ -1,74 +0,0 @@
From 183517787fe86c1bc2359ad807318b8bca573d17 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Fri, 19 Jan 2018 16:34:36 +0100
Subject: [PATCH] Ticket 49545 - final substring extended filter search returns
invalid result
Bug Description:
During a search (using extended filter with final substring), the server
checks the filter before returning the matching entries.
When checking the attribute value against the filter, it
uses the wrong value.
Fix Description:
Make suree it uses the right portion of the attribute value, in order
to generate the keys to compare.
https://pagure.io/389-ds-base/issue/49545
Reviewed by: Ludwig Krispenz
Platforms tested: F26
Flag Day: no
Doc impact: no
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
---
ldap/servers/plugins/collation/orfilter.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/ldap/servers/plugins/collation/orfilter.c b/ldap/servers/plugins/collation/orfilter.c
index a98d90219..672ee7b19 100644
--- a/ldap/servers/plugins/collation/orfilter.c
+++ b/ldap/servers/plugins/collation/orfilter.c
@@ -182,17 +182,33 @@ ss_filter_match(or_filter_t * or, struct berval **vals)
} else { /* final */
auto size_t attempts = MAX_CHAR_COMBINING;
auto char *limit = v.bv_val;
+ auto char *end;
auto struct berval **vkeys;
auto struct berval *vals[2];
auto struct berval key;
+
rc = -1;
vals[0] = &v;
vals[1] = NULL;
key.bv_val = (*k)->bv_val;
key.bv_len = (*k)->bv_len - 1;
- v.bv_val = (*vals)->bv_val + (*vals)->bv_len;
+ /* In the following lines it will loop to find
+ * if the end of the attribute value matches the 'final' of the filter
+ * Short summary:
+ * vals contains the attribute value :for example "hello world"
+ * key contain the key generated from the indexing of final part of the filter.
+ * for example filter=(<attribut>=*ld), so key contains the indexing("ld").
+ *
+ * The loop will iterate over the attribute value (vals) from the end of string
+ * to the begining. So it will try to index('d'), index('ld'), index('rld'), index('orld')...
+ *
+ * At each iteration if the key generated from indexing the portion of vals, matches
+ * the key generate from the final part of the filter, then the loop stops => we are done
+ */
+ end = v.bv_val + v.bv_len - 1;
+ v.bv_val = end;
while (1) {
- v.bv_len = (*vals)->bv_len - (v.bv_val - (*vals)->bv_val);
+ v.bv_len = end - v.bv_val + 1;
vkeys = ix->ix_index(ix, vals, NULL);
if (vkeys && vkeys[0]) {
auto const struct berval *vkey = vkeys[0];
--
2.13.6

View file

@ -1,296 +0,0 @@
From 233b64f26df76aa50f4b37aaf6b3804d208fdc1b Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Mon, 12 Feb 2018 09:24:25 +0100
Subject: [PATCH] Ticket 49551 - v3 - correct handling of numsubordinates for
cenotaphs and tombstone delete
Bug: The ticket exposed several problems with tombstone handling.
- tombstone entries of conflicts were not purged in tombstone purging
- cenotaphs are tombstone, but the subordinate count was not managed properly
- direct delete of tombstones failed with err=1
- delete of entry with only conflict children failed correctly, but gave no hint why
Fix: update the correct numsobordinates attribut for cenotaphs
set proper flag in directly deleting a tombstone
change search filter for tombstone purging to include ldapsubentries
check for conflict children if a delete is rejected and add a message to the response
Reviewed by; Thierry, William - thanks
---
ldap/servers/plugins/replication/repl5_replica.c | 14 +++++++++--
ldap/servers/plugins/replication/urp.c | 8 +++---
ldap/servers/slapd/back-ldbm/ldbm_add.c | 8 +++---
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 14 ++++++++---
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 3 ++-
ldap/servers/slapd/back-ldbm/parents.c | 12 ++++++---
ldap/servers/slapd/entry.c | 31 ++++++++++++++++++++++++
ldap/servers/slapd/slapi-plugin.h | 2 ++
ldap/servers/slapd/slapi-private.h | 1 +
ldap/servers/slapd/task.c | 4 +--
10 files changed, 78 insertions(+), 19 deletions(-)
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index bdb8a5167..628fb9ceb 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -3017,6 +3017,16 @@ process_reap_entry(Slapi_Entry *entry, void *cb_data)
search in the future, see _replica_reap_tombstones below and add more to the
attrs array */
deletion_csn = entry_get_deletion_csn(entry);
+ if (deletion_csn == NULL) {
+ /* this might be a tombstone which was directly added, eg a cenotaph
+ * check if a tombstonecsn exist and use it
+ */
+ char *tombstonecsn = slapi_entry_attr_get_charptr(entry, SLAPI_ATTR_TOMBSTONE_CSN);
+ if (tombstonecsn) {
+ deletion_csn = csn_new_by_string(tombstonecsn);
+ slapi_ch_free_string(&tombstonecsn);
+ }
+ }
if ((NULL == deletion_csn || csn_compare(deletion_csn, purge_csn) < 0) &&
(!is_ruv_tombstone_entry(entry))) {
@@ -3116,11 +3126,11 @@ _replica_reap_tombstones(void *arg)
*/
csn_as_string(purge_csn, PR_FALSE, deletion_csn_str);
PR_snprintf(tombstone_filter, 128,
- "(&(%s<=%s)(objectclass=nsTombstone))", SLAPI_ATTR_TOMBSTONE_CSN,
+ "(&(%s<=%s)(objectclass=nsTombstone)(|(objectclass=*)(objectclass=ldapsubentry)))", SLAPI_ATTR_TOMBSTONE_CSN,
csn_as_string(purge_csn, PR_FALSE, deletion_csn_str));
} else {
/* Use the old inefficient filter */
- PR_snprintf(tombstone_filter, 128, "(objectclass=nsTombstone)");
+ PR_snprintf(tombstone_filter, 128, "(&(objectclass=nsTombstone)(|(objectclass=*)(objectclass=ldapsubentry)))");
}
/* we just need the objectclass - for the deletion csn
diff --git a/ldap/servers/plugins/replication/urp.c b/ldap/servers/plugins/replication/urp.c
index d4556d7fd..11c5da7cf 100644
--- a/ldap/servers/plugins/replication/urp.c
+++ b/ldap/servers/plugins/replication/urp.c
@@ -911,7 +911,7 @@ urp_fixup_add_cenotaph (Slapi_PBlock *pb, char *sessionid, CSN *opcsn)
cenotaph,
NULL,
repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
- OP_FLAG_REPL_FIXUP|OP_FLAG_NOOP);
+ OP_FLAG_REPL_FIXUP|OP_FLAG_NOOP|OP_FLAG_CENOTAPH_ENTRY);
slapi_add_internal_pb(add_pb);
slapi_pblock_get(add_pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
@@ -1922,7 +1922,7 @@ done:
newpb = NULL;
slapi_log_err(SLAPI_LOG_REPL, sessionid,
- "urp_get_min_naming_conflict_entry - Found %d entries\n", i);
+ "urp_get_min_naming_conflict_entry - Found %d entries\n", min_csn?1:0);
return min_naming_conflict_entry;
}
@@ -2172,8 +2172,8 @@ mod_objectclass_attr(const char *uniqueid, const Slapi_DN *entrysdn, const Slapi
char csnstr[CSN_STRSIZE+1] = {0};
slapi_mods_init(&smods, 3);
- slapi_mods_add(&smods, LDAP_MOD_ADD, "objectclass", strlen("ldapsubentry"),"ldapsubentry");
- slapi_mods_add(&smods, LDAP_MOD_REPLACE, "conflictcsn", CSN_STRSIZE, csn_as_string(opcsn, PR_FALSE, csnstr));
+ slapi_mods_add_string(&smods, LDAP_MOD_ADD, "objectclass", "ldapsubentry");
+ slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "conflictcsn", csn_as_string(opcsn, PR_FALSE, csnstr));
op_result = urp_fixup_modify_entry(uniqueid, entrysdn, opcsn, &smods, 0);
slapi_mods_done(&smods);
if (op_result == LDAP_TYPE_OR_VALUE_EXISTS) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index c93d44a65..f0a3262ec 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -81,6 +81,7 @@ ldbm_back_add(Slapi_PBlock *pb)
Slapi_Operation *operation;
int is_replicated_operation = 0;
int is_resurect_operation = 0;
+ int is_cenotaph_operation = 0;
int is_tombstone_operation = 0;
int is_fixup_operation = 0;
int is_remove_from_cache = 0;
@@ -116,6 +117,7 @@ ldbm_back_add(Slapi_PBlock *pb)
}
is_resurect_operation = operation_is_flag_set(operation, OP_FLAG_RESURECT_ENTRY);
+ is_cenotaph_operation = operation_is_flag_set(operation, OP_FLAG_CENOTAPH_ENTRY);
is_tombstone_operation = operation_is_flag_set(operation, OP_FLAG_TOMBSTONE_ENTRY);
is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
@@ -846,9 +848,9 @@ ldbm_back_add(Slapi_PBlock *pb)
the in-memory state of the parent to reflect the new child (update
subordinate count specifically */
if (parententry) {
- retval = parent_update_on_childchange(&parent_modify_c,
- is_resurect_operation ? PARENTUPDATE_RESURECT : PARENTUPDATE_ADD,
- NULL);
+ int op = is_resurect_operation ? PARENTUPDATE_RESURECT : PARENTUPDATE_ADD;
+ if (is_cenotaph_operation ) op |= PARENTUPDATE_CREATE_TOMBSTONE;
+ retval = parent_update_on_childchange(&parent_modify_c, op, NULL);
slapi_log_err(SLAPI_LOG_BACKLDBM, "ldbm_back_add",
"conn=%lu op=%d parent_update_on_childchange: old_entry=0x%p, new_entry=0x%p, rc=%d\n",
conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry, retval);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index be0db1bd0..bc0a3654e 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -291,9 +291,16 @@ replace_entry:
retval = slapi_entry_has_children(e->ep_entry);
if (retval && !is_replicated_operation) {
ldap_result_code= LDAP_NOT_ALLOWED_ON_NONLEAF;
- slapi_log_err(SLAPI_LOG_BACKLDBM, "ldbm_back_delete",
- "conn=%lu op=%d Deleting entry %s has %d children.\n",
- conn_id, op_id, slapi_entry_get_dn(e->ep_entry), retval);
+ if (slapi_entry_has_conflict_children(e->ep_entry, (void *)li->li_identity) > 0) {
+ ldap_result_message = "Entry has replication conflicts as children";
+ slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_delete",
+ "conn=%lu op=%d Deleting entry %s has replication conflicts as children.\n",
+ conn_id, op_id, slapi_entry_get_dn(e->ep_entry));
+ } else {
+ slapi_log_err(SLAPI_LOG_BACKLDBM, "ldbm_back_delete",
+ "conn=%lu op=%d Deleting entry %s has %d children.\n",
+ conn_id, op_id, slapi_entry_get_dn(e->ep_entry), retval);
+ }
retval = -1;
goto error_return;
}
@@ -431,6 +438,7 @@ replace_entry:
slapi_log_err(SLAPI_LOG_WARNING, "ldbm_back_delete",
"Attempt to Tombstone again a tombstone entry %s\n", dn);
delete_tombstone_entry = 1;
+ operation_set_flag(operation, OP_FLAG_TOMBSTONE_ENTRY);
}
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
index b41a2d241..5797dd779 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
@@ -2824,7 +2824,8 @@ _entryrdn_delete_key(backend *be,
break;
}
childelem = (rdn_elem *)dataret.data;
- if (!slapi_is_special_rdn(childelem->rdn_elem_nrdn_rdn, RDN_IS_TOMBSTONE)) {
+ if (!slapi_is_special_rdn(childelem->rdn_elem_nrdn_rdn, RDN_IS_TOMBSTONE) &&
+ !strcasestr(childelem->rdn_elem_nrdn_rdn, "cenotaphid")) {
/* there's at least one live child */
slapi_log_err(SLAPI_LOG_ERR, "_entryrdn_delete_key",
"Failed to remove %s; has a child %s\n", nrdn,
diff --git a/ldap/servers/slapd/back-ldbm/parents.c b/ldap/servers/slapd/back-ldbm/parents.c
index 79e66451e..1afc795c0 100644
--- a/ldap/servers/slapd/back-ldbm/parents.c
+++ b/ldap/servers/slapd/back-ldbm/parents.c
@@ -89,7 +89,11 @@ parent_update_on_childchange(modify_context *mc, int op, size_t *new_sub_count)
}
}
- if (PARENTUPDATE_DELETE_TOMBSTONE != repl_op) {
+ if ((PARENTUPDATE_ADD == op) && (PARENTUPDATE_CREATE_TOMBSTONE == repl_op)) {
+ /* we are directly adding a tombstone entry, only need to
+ * update the tombstone subordinates
+ */
+ } else if (PARENTUPDATE_DELETE_TOMBSTONE != repl_op) {
/* are we adding ? */
if (((PARENTUPDATE_ADD == op) || (PARENTUPDATE_RESURECT == op)) && !already_present) {
/* If so, and the parent entry does not already have a subcount
@@ -136,10 +140,10 @@ parent_update_on_childchange(modify_context *mc, int op, size_t *new_sub_count)
}
}
- /* tombstoneNumSubordinates is needed only when this is repl op
- * and a child is being deleted */
+ /* tombstoneNumSubordinates has to be updated if a tombstone child has been
+ * deleted or a tombstone has been directly added (cenotaph) */
current_sub_count = LDAP_MAXINT;
- if ((repl_op && (PARENTUPDATE_DEL == op)) || (PARENTUPDATE_RESURECT == op)) {
+ if (repl_op) {
ret = slapi_entry_attr_find(mc->old_entry->ep_entry,
tombstone_numsubordinates, &read_attr);
if (0 == ret) {
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 32828b4e2..b85e9f5b0 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -3238,6 +3238,37 @@ slapi_entry_has_children(const Slapi_Entry *entry)
return slapi_entry_has_children_ext(entry, 0);
}
+int
+slapi_entry_has_conflict_children(const Slapi_Entry *entry, void *plg_id)
+{
+ Slapi_PBlock *search_pb = NULL;
+ Slapi_Entry **entries;
+ int rc = 0;
+
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(search_pb, slapi_entry_get_dn_const(entry),
+ LDAP_SCOPE_ONELEVEL,
+ "(&(objectclass=ldapsubentry)(nsds5ReplConflict=namingConflict*))",
+ NULL, 0, NULL, NULL, plg_id, 0);
+ slapi_search_internal_pb(search_pb);
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+ if (rc) {
+ rc = -1;
+ } else {
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if (entries && entries[0]) {
+ /* we found at least one conflict entry */
+ rc = 1;
+ } else {
+ rc = 0;
+ }
+ slapi_free_search_results_internal(search_pb);
+ }
+ slapi_pblock_destroy(search_pb);
+
+ return rc;
+}
+
/*
* Renames an entry to simulate a MODRDN operation
*/
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 95cdcc0da..6978e258f 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -2000,6 +2000,8 @@ int slapi_entry_has_children(const Slapi_Entry *e);
*/
int slapi_entry_has_children_ext(const Slapi_Entry *e, int include_tombstone);
+int slapi_entry_has_conflict_children(const Slapi_Entry *e, void *plg_id);
+
/**
* This function determines if an entry is the root DSE.
*
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 548d5cabb..b08c0d7ce 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -403,6 +403,7 @@ char *slapi_filter_to_string_internal(const struct slapi_filter *f, char *buf, s
#define OP_FLAG_NEVER_CHAIN SLAPI_OP_FLAG_NEVER_CHAIN /* 0x000800 */
#define OP_FLAG_TOMBSTONE_ENTRY SLAPI_OP_FLAG_TOMBSTONE_ENTRY /* 0x001000 */
#define OP_FLAG_RESURECT_ENTRY 0x002000
+#define OP_FLAG_CENOTAPH_ENTRY 0x004000
#define OP_FLAG_ACTION_NOLOG 0x008000 /* Do not log the entry in \
* audit log or change log \
*/
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
index 4bd8895ff..3f9d5d995 100644
--- a/ldap/servers/slapd/task.c
+++ b/ldap/servers/slapd/task.c
@@ -2352,10 +2352,10 @@ task_fixup_tombstone_thread(void *arg)
if (task_data->stripcsn) {
/* find tombstones with nsTombstoneCSN */
- filter = "(&(nstombstonecsn=*)(objectclass=nsTombstone))";
+ filter = "(&(nstombstonecsn=*)(objectclass=nsTombstone)(|(objectclass=*)(objectclass=ldapsubentry)))";
} else {
/* find tombstones missing nsTombstoneCSN */
- filter = "(&(!(nstombstonecsn=*))(objectclass=nsTombstone))";
+ filter = "(&(!(nstombstonecsn=*))(objectclass=nsTombstone)(|(objectclass=*)(objectclass=ldapsubentry)))";
}
/* Okay check the specified backends only */
--
2.13.6

View file

@ -1,42 +0,0 @@
From a88eea7e06a8e0a7367b2d266f9db37f6d5bbb4a Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Mon, 12 Feb 2018 16:27:03 +0100
Subject: [PATCH] Ticket 49551 - fix memory leak found by coverity
---
ldap/servers/plugins/replication/repl5_replica.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 628fb9ceb..e3ddd783d 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -3002,6 +3002,7 @@ process_reap_entry(Slapi_Entry *entry, void *cb_data)
if the value is set in the replica, we will know about it immediately */
PRBool *tombstone_reap_stop = ((reap_callback_data *)cb_data)->tombstone_reap_stop;
const CSN *deletion_csn = NULL;
+ int deletion_csn_free = 0;
int rc = -1;
/* abort reaping if we've been told to stop or we're shutting down */
@@ -3024,6 +3025,7 @@ process_reap_entry(Slapi_Entry *entry, void *cb_data)
char *tombstonecsn = slapi_entry_attr_get_charptr(entry, SLAPI_ATTR_TOMBSTONE_CSN);
if (tombstonecsn) {
deletion_csn = csn_new_by_string(tombstonecsn);
+ deletion_csn_free = 1;
slapi_ch_free_string(&tombstonecsn);
}
}
@@ -3056,6 +3058,9 @@ process_reap_entry(Slapi_Entry *entry, void *cb_data)
/* Don't update the count for the database tombstone entry */
(*num_entriesp)++;
}
+ if (deletion_csn_free) {
+ csn_free(&deletion_csn);
+ }
return 0;
}
--
2.13.6

View file

@ -1,204 +0,0 @@
From 7d5ae77d840afda65020237f87a4535f09f0b462 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 29 Mar 2018 13:24:47 -0400
Subject: [PATCH] Ticket 48184 - revert previous patch around unuc-stans
shutdown crash
https://pagure.io/389-ds-base/issue/48184
---
ldap/servers/slapd/conntable.c | 13 --------
ldap/servers/slapd/daemon.c | 76 +++++++++++++++++-------------------------
ldap/servers/slapd/fe.h | 1 -
ldap/servers/slapd/slap.h | 1 -
4 files changed, 30 insertions(+), 61 deletions(-)
diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c
index f2f763dfa..7c57b47cd 100644
--- a/ldap/servers/slapd/conntable.c
+++ b/ldap/servers/slapd/conntable.c
@@ -91,19 +91,6 @@ connection_table_abandon_all_operations(Connection_Table *ct)
}
}
-void
-connection_table_disconnect_all(Connection_Table *ct)
-{
- for (size_t i = 0; i < ct->size; i++) {
- if (ct->c[i].c_mutex) {
- Connection *c = &(ct->c[i]);
- PR_EnterMonitor(c->c_mutex);
- disconnect_server_nomutex(c, c->c_connid, -1, SLAPD_DISCONNECT_ABORT, ECANCELED);
- PR_ExitMonitor(c->c_mutex);
- }
- }
-}
-
/* Given a file descriptor for a socket, this function will return
* a slot in the connection table to use.
*
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index c245a4d4e..fcc461a90 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1176,30 +1176,6 @@ slapd_daemon(daemon_ports_t *ports, ns_thrpool_t *tp)
housekeeping_stop(); /* Run this after op_thread_cleanup() logged sth */
disk_monitoring_stop();
- /*
- * Now that they are abandonded, we need to mark them as done.
- * In NS while it's safe to allow excess jobs to be cleaned by
- * by the walk and ns_job_done of remaining queued events, the
- * issue is that if we allow something to live past this point
- * the CT is freed from underneath, and bad things happen (tm).
- *
- * NOTE: We do this after we stop psearch, because there could
- * be a race between flagging the psearch done, and users still
- * try to send on the connection. Similar with op_threads.
- */
- connection_table_disconnect_all(the_connection_table);
-
- /*
- * WARNING: Normally we should close the tp in main
- * but because of issues in the current connection design
- * we need to close it here to guarantee events won't fire!
- *
- * All the connection close jobs "should" complete before
- * shutdown at least.
- */
- ns_thrpool_shutdown(tp);
- ns_thrpool_wait(tp);
-
threads = g_get_active_threadcnt();
if (threads > 0) {
slapi_log_err(SLAPI_LOG_INFO, "slapd_daemon",
@@ -1652,18 +1628,25 @@ ns_handle_closure(struct ns_job_t *job)
Connection *c = (Connection *)ns_job_get_data(job);
int do_yield = 0;
+/* this function must be called from the event loop thread */
+#ifdef DEBUG
+ PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
+#else
+ /* This doesn't actually confirm it's in the event loop thread, but it's a start */
+ if (NS_JOB_IS_THREAD(ns_job_get_type(job)) != 0) {
+ slapi_log_err(SLAPI_LOG_ERR, "ns_handle_closure", "Attempt to close outside of event loop thread %" PRIu64 " for fd=%d\n",
+ c->c_connid, c->c_sd);
+ return;
+ }
+#endif
+
PR_EnterMonitor(c->c_mutex);
- /* Assert we really have the right job state. */
- PR_ASSERT(job == c->c_job);
connection_release_nolock_ext(c, 1); /* release ref acquired for event framework */
PR_ASSERT(c->c_ns_close_jobs == 1); /* should be exactly 1 active close job - this one */
c->c_ns_close_jobs--; /* this job is processing closure */
- /* Because handle closure will add a new job, we need to detach our current one. */
- c->c_job = NULL;
do_yield = ns_handle_closure_nomutex(c);
PR_ExitMonitor(c->c_mutex);
- /* Remove this task now. */
ns_job_done(job);
if (do_yield) {
/* closure not done - another reference still outstanding */
@@ -1686,14 +1669,6 @@ ns_connection_post_io_or_closing(Connection *conn)
return;
}
- /*
- * Cancel any existing ns jobs we have registered.
- */
- if (conn->c_job != NULL) {
- ns_job_done(conn->c_job);
- conn->c_job = NULL;
- }
-
if (CONN_NEEDS_CLOSING(conn)) {
/* there should only ever be 0 or 1 active closure jobs */
PR_ASSERT((conn->c_ns_close_jobs == 0) || (conn->c_ns_close_jobs == 1));
@@ -1703,10 +1678,13 @@ ns_connection_post_io_or_closing(Connection *conn)
conn->c_connid, conn->c_sd);
return;
} else {
+ /* just make sure we schedule the event to be closed in a timely manner */
+ tv.tv_sec = 0;
+ tv.tv_usec = slapd_wakeup_timer * 1000;
conn->c_ns_close_jobs++; /* now 1 active closure job */
connection_acquire_nolock_ext(conn, 1 /* allow acquire even when closing */); /* event framework now has a reference */
- /* Close the job asynchronously. Why? */
- ns_result_t job_result = ns_add_job(conn->c_tp, NS_JOB_TIMER, ns_handle_closure, conn, &(conn->c_job));
+ ns_result_t job_result = ns_add_timeout_job(conn->c_tp, &tv, NS_JOB_TIMER,
+ ns_handle_closure, conn, NULL);
if (job_result != NS_SUCCESS) {
if (job_result == NS_SHUTDOWN) {
slapi_log_err(SLAPI_LOG_INFO, "ns_connection_post_io_or_closing", "post closure job "
@@ -1750,7 +1728,7 @@ ns_connection_post_io_or_closing(Connection *conn)
#endif
ns_result_t job_result = ns_add_io_timeout_job(conn->c_tp, conn->c_prfd, &tv,
NS_JOB_READ | NS_JOB_PRESERVE_FD,
- ns_handle_pr_read_ready, conn, &(conn->c_job));
+ ns_handle_pr_read_ready, conn, NULL);
if (job_result != NS_SUCCESS) {
if (job_result == NS_SHUTDOWN) {
slapi_log_err(SLAPI_LOG_INFO, "ns_connection_post_io_or_closing", "post I/O job for "
@@ -1779,12 +1757,19 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
int maxthreads = config_get_maxthreadsperconn();
Connection *c = (Connection *)ns_job_get_data(job);
- PR_EnterMonitor(c->c_mutex);
- /* Assert we really have the right job state. */
- PR_ASSERT(job == c->c_job);
+/* this function must be called from the event loop thread */
+#ifdef DEBUG
+ PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
+#else
+ /* This doesn't actually confirm it's in the event loop thread, but it's a start */
+ if (NS_JOB_IS_THREAD(ns_job_get_type(job)) != 0) {
+ slapi_log_err(SLAPI_LOG_ERR, "ns_handle_pr_read_ready", "Attempt to handle read ready outside of event loop thread %" PRIu64 " for fd=%d\n",
+ c->c_connid, c->c_sd);
+ return;
+ }
+#endif
- /* On all code paths we remove the job, so set it null now */
- c->c_job = NULL;
+ PR_EnterMonitor(c->c_mutex);
slapi_log_err(SLAPI_LOG_CONNS, "ns_handle_pr_read_ready", "activity on conn %" PRIu64 " for fd=%d\n",
c->c_connid, c->c_sd);
@@ -1844,7 +1829,6 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
slapi_log_err(SLAPI_LOG_CONNS, "ns_handle_pr_read_ready", "queued conn %" PRIu64 " for fd=%d\n",
c->c_connid, c->c_sd);
}
- /* Since we call done on the job, we need to remove it here. */
PR_ExitMonitor(c->c_mutex);
ns_job_done(job);
return;
diff --git a/ldap/servers/slapd/fe.h b/ldap/servers/slapd/fe.h
index f47bb6145..4d25a9fb8 100644
--- a/ldap/servers/slapd/fe.h
+++ b/ldap/servers/slapd/fe.h
@@ -100,7 +100,6 @@ extern Connection_Table *the_connection_table; /* JCM - Exported from globals.c
Connection_Table *connection_table_new(int table_size);
void connection_table_free(Connection_Table *ct);
void connection_table_abandon_all_operations(Connection_Table *ct);
-void connection_table_disconnect_all(Connection_Table *ct);
Connection *connection_table_get_connection(Connection_Table *ct, int sd);
int connection_table_move_connection_out_of_active_list(Connection_Table *ct, Connection *c);
void connection_table_move_connection_on_to_active_list(Connection_Table *ct, Connection *c);
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 443d90094..9b10aa19e 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1651,7 +1651,6 @@ typedef struct conn
void *c_io_layer_cb_data; /* callback data */
struct connection_table *c_ct; /* connection table that this connection belongs to */
ns_thrpool_t *c_tp; /* thread pool for this connection */
- struct ns_job_t *c_job; /* If it exists, the current ns_job_t */
int c_ns_close_jobs; /* number of current close jobs */
char *c_ipaddr; /* ip address str - used by monitor */
} Connection;
--
2.13.6

View file

@ -1,59 +0,0 @@
From d606691d341dfffee0b02fc55fb29f74f975e775 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Wed, 21 Mar 2018 18:26:16 +0100
Subject: [PATCH] Ticket 49619 - adjustment of csn_generator can fail so next
generated csn can be equal to the most recent one received
Bug Description:
On consumer side csn_generator ajustment occurs (let CSN = highest known csn)
when a replication session starts
when a csn is generated locally and than csn is <= CSN
During adjustment, in the case
there is no remote/local offset (time change)
the current_time on the consumer is identical to CSN
Then next locally generated csn will only differ with seqnum
The seqnum of the csn_generator is increased only if CSN.seqnum is larger
than the csn_generator one.
In case of egality, it remains unchanged.
The consequence is that the next locally generated csn will be identical to CSN (except for the RID).
So even after csn_generator adjustment, csn_generator may create csn that are not larger than the CSN
Fix Description:
compare the new generated timestamp (time+offsets) with adjustment one.
If the new is greater or EQUAL, make sure the local seqnum is ahead the remote one
https://pagure.io/389-ds-base/issue/49619
Reviewed by: Mark Reynolds
Platforms tested: F27
Flag Day: no
Doc impact: no
---
ldap/servers/slapd/csngen.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/slapd/csngen.c b/ldap/servers/slapd/csngen.c
index 287ea847e..4ac45acf0 100644
--- a/ldap/servers/slapd/csngen.c
+++ b/ldap/servers/slapd/csngen.c
@@ -331,7 +331,7 @@ csngen_adjust_time(CSNGen *gen, const CSN *csn)
/* let's revisit the seq num - if the new time is > the old
tiem, we should reset the seq number to remote + 1 if
this won't cause a wrap around */
- if (new_time > cur_time) {
+ if (new_time >= cur_time) {
/* just set seq_num regardless of whether the current one
is < or > than the remote one - the goal of this function
is to make sure we generate CSNs > the remote CSN - if
--
2.13.6

View file

@ -1,34 +0,0 @@
From 293361f34d935080c1d8d0e73b4355b48faebe2a Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Tue, 27 Feb 2018 13:56:14 +0100
Subject: [PATCH] Ticket 49161 - memberof fails if group is moved into scope
if the DEL part of the replace of memberof fails because it does not exist
just add the new memberof values
Reviwed by: Mark, thanks
---
ldap/servers/plugins/memberof/memberof.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
index fcfa7817d..2f46167dc 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -1710,6 +1710,13 @@ memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config, int mod_o
replace_mod.mod_values = replace_val;
}
rc = memberof_add_memberof_attr(mods, op_to, config->auto_add_oc);
+ if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
+ /* the memberof values to be replaced do not exist
+ * just add the new values */
+ mods[0] = mods[1];
+ mods[1] = NULL;
+ rc = memberof_add_memberof_attr(mods, op_to, config->auto_add_oc);
+ }
}
}
--
2.13.6

View file

@ -1,101 +0,0 @@
From dd12327d1523f3ff9d6ae8b44b640fb9d0d2d53b Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 19 Feb 2018 10:44:36 -0500
Subject: [PATCH] Ticket 49296 - Fix race condition in connection code with
anonymous limits
Bug Description: When a connection first comes in we set the anonymous
resource limits (if set) before we do anything else. The
way we check if the connection is "new" was flawed. It
assumed the connection was new if no operations were
completed yet, but there was a small window between sending
the result and setting that the operation completed in the
connection struct.
So on a connection that binds and then does a search, when
the server sends the bind result the client sends the search,
but the search op/activity can be picked up before we set
c_opscompleted. This opens a window where the code thinks
the search op is the first op(new connection), and it incorrectly
sets the anonymous limits for the bind dn.
Fix description: Do not use c_opscompleted to determine if a connection is new,
instead use a new flag to set the connection "initialized",
which prevents the race condition.
https://pagure.io/389-ds-base/issue/49296
Reviewed by: firstyear(Thanks!)
(cherry picked from commit 0d5214d08e6b5b39fb9d5ef5cf3d8834574954f1)
---
ldap/servers/slapd/connection.c | 12 +++++++++++-
ldap/servers/slapd/slap.h | 7 +++----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 5d2b64ed2..5ca32a333 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -217,6 +217,7 @@ connection_cleanup(Connection *conn)
conn->c_connid = 0;
conn->c_opsinitiated = 0;
conn->c_opscompleted = 0;
+ conn->c_anonlimits_set = 0;
conn->c_threadnumber = 0;
conn->c_refcnt = 0;
conn->c_idlesince = 0;
@@ -1549,7 +1550,9 @@ connection_threadmain()
g_decr_active_threadcnt();
return;
}
- if (pb_conn->c_opscompleted == 0) {
+
+ PR_EnterMonitor(pb_conn->c_mutex);
+ if (pb_conn->c_anonlimits_set == 0) {
/*
* We have a new connection, set the anonymous reslimit idletimeout
* if applicable.
@@ -1568,7 +1571,14 @@ connection_threadmain()
}
}
slapi_ch_free_string(&anon_dn);
+ /*
+ * Set connection as initialized to avoid setting anonymous limits
+ * multiple times on the same connection
+ */
+ pb_conn->c_anonlimits_set = 1;
}
+ PR_ExitMonitor(pb_conn->c_mutex);
+
if (connection_call_io_layer_callbacks(pb_conn)) {
slapi_log_err(SLAPI_LOG_ERR, "connection_threadmain",
"Could not add/remove IO layers from connection\n");
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 9b10aa19e..03355f5fe 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1616,6 +1616,7 @@ typedef struct conn
PRUint64 c_maxthreadsblocked; /* # of operations blocked by maxthreads */
int c_opsinitiated; /* # ops initiated/next op id */
PRInt32 c_opscompleted; /* # ops completed */
+ uint64_t c_anonlimits_set; /* default anon limits are set */
PRInt32 c_threadnumber; /* # threads used in this conn */
int c_refcnt; /* # ops refering to this conn */
PRMonitor *c_mutex; /* protect each conn structure; need to be re-entrant */
@@ -1623,10 +1624,8 @@ typedef struct conn
time_t c_idlesince; /* last time of activity on conn */
int c_idletimeout; /* local copy of idletimeout */
int c_idletimeout_handle; /* the resource limits handle */
- Conn_private *c_private; /* data which is not shared outside*/
- /* connection.c */
- int c_flags; /* Misc flags used only for SSL */
- /* status currently */
+ Conn_private *c_private; /* data which is not shared outside connection.c */
+ int c_flags; /* Misc flags used only for SSL status currently */
int c_needpw; /* need new password */
CERTCertificate *c_client_cert; /* Client's Cert */
PRFileDesc *c_prfd; /* NSPR 2.1 FileDesc */
--
2.13.6

View file

@ -1,206 +0,0 @@
From 3dac3503087b6bae9e6e3d63a8214e8be65a145b Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Fri, 19 Jan 2018 17:50:59 +0100
Subject: [PATCH 05/10] Ticket 49540 - Indexing task is reported finished too
early regarding the backend status
Bug Description:
If a task complete successfully, its status is updated before the backend
can receive update.
Fix Description:
postpone the task status update after backend is reenabled
https://pagure.io/389-ds-base/issue/49540
Reviewed by: Ludwig Krispenz
Platforms tested: F26
Flag Day: no
Doc impact: no
---
dirsrvtests/tests/tickets/ticket49540_test.py | 135 ++++++++++++++++++++++++++
ldap/servers/slapd/back-ldbm/ldif2ldbm.c | 16 +--
2 files changed, 145 insertions(+), 6 deletions(-)
create mode 100644 dirsrvtests/tests/tickets/ticket49540_test.py
diff --git a/dirsrvtests/tests/tickets/ticket49540_test.py b/dirsrvtests/tests/tickets/ticket49540_test.py
new file mode 100644
index 000000000..1fbfde2c5
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket49540_test.py
@@ -0,0 +1,135 @@
+import logging
+import pytest
+import os
+import ldap
+import time
+import re
+from lib389._constants import *
+from lib389.tasks import *
+from lib389.topologies import topology_st as topo
+from lib389.idm.user import UserAccount, UserAccounts, TEST_USER_PROPERTIES
+from lib389 import Entry
+
+
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+HOMEDIRECTORY_INDEX = 'cn=homeDirectory,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config'
+HOMEDIRECTORY_CN = "homedirectory"
+MATCHINGRULE = 'nsMatchingRule'
+USER_CN = 'user_'
+
+def create_index_entry(topo):
+ log.info("\n\nindex homeDirectory")
+ try:
+ ent = topo.getEntry(HOMEDIRECTORY_INDEX, ldap.SCOPE_BASE)
+ except ldap.NO_SUCH_OBJECT:
+ topo.add_s(Entry((HOMEDIRECTORY_INDEX, {
+ 'objectclass': "top nsIndex".split(),
+ 'cn': HOMEDIRECTORY_CN,
+ 'nsSystemIndex': 'false',
+ MATCHINGRULE: ['caseIgnoreIA5Match', 'caseExactIA5Match' ],
+ 'nsIndexType': ['eq', 'sub', 'pres']})))
+
+
+def provision_users(topo):
+ test_users = []
+ homeValue = b'x' * (32 * 1024) # just to slow down indexing
+ for i in range(100):
+ CN = '%s%d' % (USER_CN, i)
+ users = UserAccounts(topo, SUFFIX)
+ user_props = TEST_USER_PROPERTIES.copy()
+ user_props.update({'uid': CN, 'cn': CN, 'sn': '_%s' % CN, HOMEDIRECTORY_CN: homeValue})
+ testuser = users.create(properties=user_props)
+ test_users.append(testuser)
+ return test_users
+
+def start_start_status(server):
+ args = {TASK_WAIT: False}
+ indexTask = Tasks(server)
+ indexTask.reindex(suffix=SUFFIX, attrname='homeDirectory', args=args)
+ return indexTask
+
+def check_task_status(server, indexTask, test_entry):
+ finish_pattern = re.compile(".*Finished indexing.*")
+ mod = [(ldap.MOD_REPLACE, 'sn', b'foo')]
+ for i in range(10):
+ log.info("check_task_status =========> %d th loop" % i)
+ try:
+ ent = server.getEntry(indexTask.dn, ldap.SCOPE_BASE)
+ if ent.hasAttr('nsTaskStatus'):
+ value = str(ent.getValue('nsTaskStatus'))
+ finish = finish_pattern.search(value)
+ log.info("%s ---> %s" % (indexTask.dn, value))
+ else:
+ finish = None
+ log.info("%s ---> NO STATUS" % (indexTask.dn))
+
+ if not finish:
+ # This is not yet finished try an update
+ try:
+ server.modify_s(test_entry, mod)
+
+ # weird, may be indexing just complete
+ ent = server.getEntry(indexTask.dn, ldap.SCOPE_BASE, ['nsTaskStatus'])
+ assert (ent.hasAttr('nsTaskStatus') and regex.search(ent.getValue('nsTaskStatus')))
+ log.info("Okay, it just finished so the MOD was successful")
+ except ldap.UNWILLING_TO_PERFORM:
+ log.info("=========> Great it was expected in the middle of index")
+ else:
+ # The update should be successful
+ server.modify_s(test_entry, mod)
+
+ except ldap.NO_SUCH_OBJECT:
+ log.info("%s: no found" % (indexTask.dn))
+
+ time.sleep(1)
+
+def test_ticket49540(topo):
+ """Specify a test case purpose or name here
+
+ :id: 1df16d5a-1b92-46b7-8435-876b87545748
+ :setup: Standalone Instance
+ :steps:
+ 1. Create homeDirectory index (especially with substring)
+ 2. Creates 100 users with large homeDirectory value => long to index
+ 3. Start an indexing task WITHOUT waiting for its completion
+ 4. Monitor that until task.status = 'Finish', any update -> UNWILLING to perform
+ :expectedresults:
+ 1. Index configuration succeeds
+ 2. users entry are successfully created
+ 3. Indexing task is started
+ 4. If the task.status does not contain 'Finished indexing', any update should return UNWILLING_TO_PERFORM
+ When it contains 'Finished indexing', updates should be successful
+ """
+
+ server = topo.standalone
+ create_index_entry(server)
+ test_users = provision_users(server)
+
+ indexTask = start_start_status(server)
+ check_task_status(server, indexTask, test_users[0].dn)
+
+ # If you need any test suite initialization,
+ # please, write additional fixture for that (including finalizer).
+ # Topology for suites are predefined in lib389/topologies.py.
+
+ # If you need host, port or any other data about instance,
+ # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
+
+ if DEBUGGING:
+ # Add debugging steps(if any)...
+ pass
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main(["-s", CURRENT_FILE])
+
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
index 4347c1721..16b87ee6b 100644
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
@@ -2562,12 +2562,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
vlvIndex_go_online(pvlv[vlvidx], be);
}
- if (task) {
- slapi_task_log_status(task, "%s: Finished indexing.",
- inst->inst_name);
- slapi_task_log_notice(task, "%s: Finished indexing.",
- inst->inst_name);
- }
+ /* if it was a task, its status will be updated later after backend is ready for update */
slapi_log_err(SLAPI_LOG_INFO, "ldbm_back_ldbm2index", "%s: Finished indexing.\n",
inst->inst_name);
return_value = 0; /* success */
@@ -2591,6 +2586,15 @@ err_min:
dblayer_release_id2entry(be, db); /* nope */
instance_set_not_busy(inst);
+ if (return_value == 0) {
+ if (task) {
+ slapi_task_log_status(task, "%s: Finished indexing.",
+ inst->inst_name);
+ slapi_task_log_notice(task, "%s: Finished indexing.",
+ inst->inst_name);
+ }
+ }
+
if (run_from_cmdline) {
dblayer_instance_close(be);
if (0 != dblayer_close(li, DBLAYER_INDEX_MODE)) {
--
2.13.6

View file

@ -1,157 +0,0 @@
From 22cf575ae7aea204c3e3974c645725a25f4e09e6 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 14 Feb 2018 20:25:34 -0500
Subject: [PATCH] Ticket 49566 - ds-replcheck needs to work with hidden
conflict entries
Description: Conflict entries are now hidden and the tool needs to account
for it. The filter needs to include "objectclass=ldapsubentry"
Added option to prompt for password, and cleaned up man page.
https://pagure.io/389-ds-base/issue/49566
Reviewed by: spichugi(Thanks!)
(cherry picked from commit 9e2009ae7105dda5493d4d60b20f15ffb369ab26)
---
ldap/admin/src/scripts/ds-replcheck | 23 ++++++++++++++++-------
man/man1/ds-replcheck.1 | 14 +++++++++++---
2 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/ldap/admin/src/scripts/ds-replcheck b/ldap/admin/src/scripts/ds-replcheck
index 0b7e70ee8..45c4670a3 100755
--- a/ldap/admin/src/scripts/ds-replcheck
+++ b/ldap/admin/src/scripts/ds-replcheck
@@ -14,6 +14,7 @@ import time
import ldap
import ldapurl
import argparse
+import getpass
from ldap.ldapobject import SimpleLDAPObject
from ldap.cidict import cidict
@@ -878,14 +879,16 @@ 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=*",
+ master_msgid = master.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
+ "(|(objectclass=*)(objectclass=ldapsubentry))",
['*', 'createtimestamp', 'nscpentrywsi', 'nsds5replconflict'],
serverctrls=controls)
except ldap.LDAPError as e:
print("Error: Failed to get Master entries: %s", str(e))
exit(1)
try:
- replica_msgid = replica.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE, "objectclass=*",
+ replica_msgid = replica.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
+ "(|(objectclass=*)(objectclass=ldapsubentry))",
['*', 'createtimestamp', 'nscpentrywsi', 'nsds5replconflict'],
serverctrls=controls)
except ldap.LDAPError as e:
@@ -928,7 +931,8 @@ def do_online_report(opts, output_file=None):
if m_pctrls[0].cookie:
# 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, "objectclass=*",
+ master_msgid = master.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
+ "(|(objectclass=*)(objectclass=ldapsubentry))",
['*', 'createtimestamp', 'nscpentrywsi', 'nsds5replconflict'], serverctrls=controls)
else:
m_done = True # No more pages available
@@ -947,7 +951,8 @@ def do_online_report(opts, output_file=None):
if r_pctrls[0].cookie:
# Copy cookie from response control to request control
req_pr_ctrl.cookie = r_pctrls[0].cookie
- replica_msgid = replica.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE, "objectclass=*",
+ replica_msgid = replica.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
+ "(|(objectclass=*)(objectclass=ldapsubentry))",
['*', 'createtimestamp', 'nscpentrywsi', 'nsds5replconflict'], serverctrls=controls)
else:
r_done = True # No more pages available
@@ -976,8 +981,9 @@ def main():
parser = argparse.ArgumentParser(description=desc)
parser.add_argument('-v', '--verbose', help='Verbose output', action='store_true', default=False, dest='verbose')
parser.add_argument('-o', '--outfile', help='The output file', dest='file', default=None)
- parser.add_argument('-D', '--binddn', help='The Bind DN', dest='binddn', default="")
- parser.add_argument('-w', '--bindpw', help='The Bind password', dest='bindpw', default="")
+ parser.add_argument('-D', '--binddn', help='The Bind DN', dest='binddn', default=None)
+ parser.add_argument('-w', '--bindpw', help='The Bind password', dest='bindpw', default=None)
+ parser.add_argument('-W', '--prompt', help='Prompt for the bind password', action='store_true', dest='prompt', default=False)
parser.add_argument('-m', '--master_url', help='The LDAP URL for the Master server (REQUIRED)',
dest='murl', default=None)
parser.add_argument('-r', '--replica_url', help='The LDAP URL for the Replica server (REQUIRED)',
@@ -1012,7 +1018,7 @@ def main():
elif (args.mldif is None and
(args.suffix is None or
args.binddn is None or
- args.bindpw is None or
+ (args.bindpw is None and args.prompt is False) or
args.murl is None or
args.rurl is None)):
print("\n-------> Missing required options for online mode!\n")
@@ -1098,6 +1104,9 @@ def main():
print("Can't open file: " + args.file)
exit(1)
+ if args.prompt:
+ opts['bindpw'] = getpass.getpass('Enter password:')
+
if opts['mldif'] is not None and opts['rldif'] is not None:
print ("Performing offline report...")
do_offline_report(opts, OUTPUT_FILE)
diff --git a/man/man1/ds-replcheck.1 b/man/man1/ds-replcheck.1
index 21b4802a5..3f14e11c8 100644
--- a/man/man1/ds-replcheck.1
+++ b/man/man1/ds-replcheck.1
@@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
-.TH DS-REPLCHECK 1 "May 2, 2017"
+.TH DS-REPLCHECK 1 "Feb 14, 2018"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@@ -19,7 +19,7 @@
ds-replcheck - Performs replication synchronization report between two replicas
.SH SYNOPSIS
-ds-replcheck [-h] [-o FILE] [-D BINDDN] [-w BINDPW] [-m MURL]
+ds-replcheck [-h] [-o FILE] [-D BINDDN] [[-w BINDPW] [-W]] [-m MURL]
[-r RURL] [-b SUFFIX] [-l LAG] [-Z CERTDIR]
[-i IGNORE] [-p PAGESIZE] [-M MLDIF] [-R RLDIF]
@@ -41,6 +41,10 @@ The Directory Manager DN, or root DN.a (online mode)
.B \fB\-w\fR \fIPASSWORD\fR
The Directory Manager password (online mode)
.TP
+.B \fB\-W\fR
+.br
+Prompt for the Directory Manager password (online mode)
+.TP
.B \fB\-m\fR \fILDAP_URL\fR
The LDAP Url for the first replica (online mode)
.TP
@@ -59,6 +63,10 @@ The directory containing a certificate database for StartTLS/SSL connections. (
.B \fB\-i\fR \fIIGNORE LIST\fR
Comma separated list of attributes to ignore in the report (online & offline)
.TP
+.B \fB\-c\fR
+.br
+Display verbose conflict entry information
+.TP
.B \fB\-M\fR \fILDIF FILE\fR
The LDIF file for the first replica (offline mode)
.TP
@@ -81,5 +89,5 @@ ds-replcheck was written by the 389 Project.
.SH "REPORTING BUGS"
Report bugs to https://pagure.io/389-ds-base/new_issue
.SH COPYRIGHT
-Copyright \(co 2017 Red Hat, Inc.
+Copyright \(co 2018 Red Hat, Inc.
--
2.13.6

View file

@ -1,169 +0,0 @@
From a0c4a8d69735cb37e5b52b195ec632ce6d1f028f Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Tue, 21 Nov 2017 17:23:29 +0100
Subject: [PATCH] Ticket 49460 - replica_write_ruv log a failure even when it
succeeds
Bug Description:
Minor issue
If the update of the DB RUV returns a success LDAP_SUCCESS (internal modify),
it however logs an error as if it failed
side effect of https://pagure.io/389-ds-base/issue/48118
Fix Description:
Log a message only on failure
https://pagure.io/389-ds-base/issue/49460
Reviewed by: Ludwig Krispenz, William Brown
Platforms tested: F23
Flag Day: no
Doc impact: no
---
dirsrvtests/tests/tickets/ticket49460_test.py | 115 +++++++++++++++++++++++
ldap/servers/plugins/replication/repl5_replica.c | 3 +-
2 files changed, 116 insertions(+), 2 deletions(-)
create mode 100644 dirsrvtests/tests/tickets/ticket49460_test.py
diff --git a/dirsrvtests/tests/tickets/ticket49460_test.py b/dirsrvtests/tests/tickets/ticket49460_test.py
new file mode 100644
index 000000000..296b3c9aa
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket49460_test.py
@@ -0,0 +1,115 @@
+import time
+import ldap
+import logging
+import pytest
+import os
+import re
+from lib389._constants import *
+from lib389.config import Config
+from lib389 import DirSrv, Entry
+from lib389.topologies import topology_m3 as topo
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+USER_CN="user"
+
+def add_user(server, no, desc='dummy', sleep=True):
+ cn = '%s%d' % (USER_CN, no)
+ dn = 'cn=%s,ou=people,%s' % (cn, SUFFIX)
+ log.fatal('Adding user (%s): ' % dn)
+ server.add_s(Entry((dn, {'objectclass': ['top', 'person', 'inetuser', 'userSecurityInformation'],
+ 'sn': ['_%s' % cn],
+ 'description': [desc]})))
+ time.sleep(1)
+
+def check_user(server, no, timeout=10):
+
+ cn = '%s%d' % (USER_CN, no)
+ dn = 'cn=%s,ou=people,%s' % (cn, SUFFIX)
+ found = False
+ cpt = 0
+ while cpt < timeout:
+ try:
+ server.getEntry(dn, ldap.SCOPE_BASE, "(objectclass=*)")
+ found = True
+ break
+ except ldap.NO_SUCH_OBJECT:
+ time.sleep(1)
+ cpt += 1
+ return found
+
+def pattern_errorlog(server, log_pattern):
+ file_obj = open(server.errlog, "r")
+
+ found = None
+ # Use a while true iteration because 'for line in file: hit a
+ while True:
+ line = file_obj.readline()
+ found = log_pattern.search(line)
+ if ((line == '') or (found)):
+ break
+
+ return found
+
+def test_ticket_49460(topo):
+ """Specify a test case purpose or name here
+
+ :id: d1aa2e8b-e6ab-4fc6-9c63-c6f622544f2d
+ :setup: Fill in set up configuration here
+ :steps:
+ 1. Enable replication logging
+ 2. Do few updates to generatat RUV update
+ :expectedresults:
+ 1. No report of failure when the RUV is updated
+ """
+
+ M1 = topo.ms["master1"]
+ M2 = topo.ms["master2"]
+ M3 = topo.ms["master3"]
+
+ for i in (M1, M2, M3):
+ i.config.loglevel(vals=[256 + 4], service='access')
+ i.config.loglevel(vals=[LOG_REPLICA, LOG_DEFAULT], service='error')
+
+ add_user(M1, 11, desc="add to M1")
+ add_user(M2, 21, desc="add to M2")
+ add_user(M3, 31, desc="add to M3")
+
+ for i in (M1, M2, M3):
+ assert check_user(i, 11)
+ assert check_user(i, 21)
+ assert check_user(i, 31)
+
+ time.sleep(10)
+
+ #M1.tasks.cleanAllRUV(suffix=SUFFIX, replicaid='3',
+ # force=False, args={TASK_WAIT: True})
+ #time.sleep(10)
+ regex = re.compile(".*Failed to update RUV tombstone.*LDAP error - 0")
+ assert not pattern_errorlog(M1, regex)
+ assert not pattern_errorlog(M2, regex)
+ assert not pattern_errorlog(M3, regex)
+
+ # If you need any test suite initialization,
+ # please, write additional fixture for that (including finalizer).
+ # Topology for suites are predefined in lib389/topologies.py.
+
+ # If you need host, port or any other data about instance,
+ # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
+
+ if DEBUGGING:
+ # Add debugging steps(if any)...
+ pass
+
+
+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/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index e3ddd783d..c6d6ee746 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -2829,8 +2829,7 @@ replica_write_ruv(Replica *r)
/* this includes an internal operation - but since this only happens
during server startup - its ok that we have lock around it */
rc = _replica_configure_ruv(r, PR_TRUE);
- } else /* error */
- {
+ } else if (rc != LDAP_SUCCESS) { /* error */
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
"replica_write_ruv - Failed to update RUV tombstone for %s; "
"LDAP error - %d\n",
--
2.13.6

View file

@ -1,37 +0,0 @@
From 9c929dbfcd1687ba43b2b2ee649c0e6522365fad Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Wed, 4 Apr 2018 08:59:15 +0200
Subject: [PATCH] Ticket 49631 - same csn generated twice
Bug: if in the csn adjustment the local time was less or equal than the remote time
the sequence number has always been adjusted to remote++
but if the csn time was equal and the local seq number was larger the effect
was a reset of the csn generato.
Fix: correctly handles seqnum in csn adjustment
Reviewed by: Mark, thanks
---
ldap/servers/slapd/csngen.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/ldap/servers/slapd/csngen.c b/ldap/servers/slapd/csngen.c
index 4ac45acf0..3afc9176b 100644
--- a/ldap/servers/slapd/csngen.c
+++ b/ldap/servers/slapd/csngen.c
@@ -338,7 +338,11 @@ csngen_adjust_time(CSNGen *gen, const CSN *csn)
we have increased the time, we can decrease the seqnum
and still guarantee that any new CSNs generated will be
> any current CSNs we have generated */
- gen->state.seq_num = remote_seqnum + 1;
+ if (remote_seqnum < gen->state.seq_num) {
+ gen->state.seq_num ++;
+ } else {
+ gen->state.seq_num = remote_seqnum + 1;
+ }
}
if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
slapi_log_err(SLAPI_LOG_REPL, "csngen_adjust_time",
--
2.13.6

View file

@ -1,81 +0,0 @@
From 71b87e678bcc03bb9a0802f7dffc97cf354ee69a Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 5 Apr 2018 14:52:34 -0400
Subject: [PATCH] CVE-2018-1089 - Crash from long search filter
---
ldap/servers/slapd/filter.c | 8 ++++----
ldap/servers/slapd/util.c | 10 +++++-----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/ldap/servers/slapd/filter.c b/ldap/servers/slapd/filter.c
index 2ac3d2cd8..393a4dcee 100644
--- a/ldap/servers/slapd/filter.c
+++ b/ldap/servers/slapd/filter.c
@@ -472,7 +472,7 @@ get_substring_filter(
f->f_sub_initial = val;
eval = (char *)slapi_escape_filter_value(val, -1);
if (eval) {
- if (fstr_len < strlen(*fstr) + strlen(eval) + 1) {
+ if (fstr_len <= strlen(*fstr) + strlen(eval) + 1) {
fstr_len += (strlen(eval) + 1) * 2;
*fstr = slapi_ch_realloc(*fstr, fstr_len);
}
@@ -486,7 +486,7 @@ get_substring_filter(
charray_add(&f->f_sub_any, val);
eval = (char *)slapi_escape_filter_value(val, -1);
if (eval) {
- if (fstr_len < strlen(*fstr) + strlen(eval) + 1) {
+ if (fstr_len <= strlen(*fstr) + strlen(eval) + 1) {
fstr_len += (strlen(eval) + 1) * 2;
*fstr = slapi_ch_realloc(*fstr, fstr_len);
}
@@ -504,7 +504,7 @@ get_substring_filter(
f->f_sub_final = val;
eval = (char *)slapi_escape_filter_value(val, -1);
if (eval) {
- if (fstr_len < strlen(*fstr) + strlen(eval) + 1) {
+ if (fstr_len <= strlen(*fstr) + strlen(eval) + 1) {
fstr_len += (strlen(eval) + 1) * 2;
*fstr = slapi_ch_realloc(*fstr, fstr_len);
}
@@ -530,7 +530,7 @@ get_substring_filter(
}
filter_compute_hash(f);
- if (fstr_len < strlen(*fstr) + 3) {
+ if (fstr_len <= strlen(*fstr) + 3) {
fstr_len += 3;
*fstr = slapi_ch_realloc(*fstr, fstr_len);
}
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index ddb2cc899..cb46efb3d 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -161,6 +161,11 @@ do_escape_string(
break;
}
do {
+ if (bufSpace < 4) {
+ memcpy(bufNext, "..", 2);
+ bufNext += 2;
+ goto bail;
+ }
if (esc == UTIL_ESCAPE_BACKSLASH) {
/* *s is '\\' */
/* If *(s+1) and *(s+2) are both hex digits,
@@ -179,11 +184,6 @@ do_escape_string(
*bufNext++ = '\\';
--bufSpace;
}
- if (bufSpace < 3) {
- memcpy(bufNext, "..", 2);
- bufNext += 2;
- goto bail;
- }
PR_snprintf(bufNext, 3, "%02x", *(unsigned char *)s);
bufNext += 2;
bufSpace -= 2;
--
2.13.6

View file

@ -1,40 +0,0 @@
From e4d51884e3ca36b8256c33936dc31e77e0ad4736 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 8 May 2018 12:35:43 -0400
Subject: [PATCH] Ticket 49649
Description: Fix crpyt.h include
https://pagure.io/389-ds-base/issue/49649
Reviewed by: mreynolds(one line commit rule)
(cherry picked from commit 2817f0c49401056835a79aafd8f8d4edc9113d1d)
---
ldap/servers/plugins/pwdstorage/crypt_pwd.c | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/ldap/servers/plugins/pwdstorage/crypt_pwd.c b/ldap/servers/plugins/pwdstorage/crypt_pwd.c
index 0dccd1b51..19894bd80 100644
--- a/ldap/servers/plugins/pwdstorage/crypt_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/crypt_pwd.c
@@ -20,15 +20,7 @@
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
-#if defined(hpux) || defined(LINUX) || defined(__FreeBSD__)
-#ifndef __USE_XOPEN
-#define __USE_XOPEN /* linux */
-#endif /* __USE_XOPEN */
-#include <unistd.h>
-#else /* hpux */
-#include <crypt.h>
-#endif /* hpux */
-
+#include <crypt.h> /* for crypt_r */
#include "pwdstorage.h"
static PRLock *cryptlock = NULL; /* Some implementations of crypt are not thread safe. ie. ours & Irix */
--
2.13.6

View file

@ -1,53 +0,0 @@
From a13a83465c685d6ec8d47b6f10646986ded16a68 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 9 May 2018 16:36:48 -0400
Subject: [PATCH] Ticket 49665 - Upgrade script doesn't enable PBKDF2 password
storage plug-in
Description: There is no upgrade script to add the PBKDF2 plugin, this
fix adds the script.
https://pagure.io/389-ds-base/issue/49665
Reviewed by: ?
(cherry picked from commit dc690dd231a626b3b6a2019fee51e3cb15db7962)
---
Makefile.am | 1 +
ldap/admin/src/scripts/50pbkdf2pwdstorageplugin.ldif | 12 ++++++++++++
2 files changed, 13 insertions(+)
create mode 100644 ldap/admin/src/scripts/50pbkdf2pwdstorageplugin.ldif
diff --git a/Makefile.am b/Makefile.am
index 8834a7819..055d480aa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -949,6 +949,7 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \
ldap/admin/src/scripts/50refintprecedence.ldif \
ldap/admin/src/scripts/50retroclprecedence.ldif \
ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif \
+ ldap/admin/src/scripts/50pbkdf2pwdstorageplugin.ldif \
ldap/admin/src/scripts/50contentsync.ldif \
ldap/admin/src/scripts/60upgradeschemafiles.pl \
ldap/admin/src/scripts/60upgradeconfigfiles.pl \
diff --git a/ldap/admin/src/scripts/50pbkdf2pwdstorageplugin.ldif b/ldap/admin/src/scripts/50pbkdf2pwdstorageplugin.ldif
new file mode 100644
index 000000000..462d5534a
--- /dev/null
+++ b/ldap/admin/src/scripts/50pbkdf2pwdstorageplugin.ldif
@@ -0,0 +1,12 @@
+dn: cn=PBKDF2_SHA256,cn=Password Storage Schemes,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+cn: PBKDF2_SHA256
+nsslapd-pluginpath: libpwdstorage-plugin
+nsslapd-plugininitfunc: pbkdf2_sha256_pwd_storage_scheme_init
+nsslapd-plugintype: pwdstoragescheme
+nsslapd-pluginenabled: on
+nsslapd-pluginDescription: DESC
+nsslapd-pluginVersion: PACKAGE_VERSION
+nsslapd-pluginVendor: VENDOR
+nsslapd-pluginid: ID
--
2.13.6

View file

@ -1,79 +0,0 @@
From 1c077cff1ce49f5380192325a6947c623019c365 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 9 May 2018 16:39:23 -0400
Subject: [PATCH] Ticket 49665 - Upgrade script doesn't enable CRYPT password
storage plug-in
Description: There is no upgrade script to add the new CRYPT plugins, this
fix adds the script.
https://pagure.io/389-ds-base/issue/49665
Reviewed by: vashirov(Thanks!)
(cherry picked from commit 91dc832411a1bb6e8bf62bb72c36777ddc63770f)
---
Makefile.am | 1 +
.../admin/src/scripts/50cryptpwdstorageplugin.ldif | 38 ++++++++++++++++++++++
2 files changed, 39 insertions(+)
create mode 100644 ldap/admin/src/scripts/50cryptpwdstorageplugin.ldif
diff --git a/Makefile.am b/Makefile.am
index 055d480aa..4f62a899b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -950,6 +950,7 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \
ldap/admin/src/scripts/50retroclprecedence.ldif \
ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif \
ldap/admin/src/scripts/50pbkdf2pwdstorageplugin.ldif \
+ ldap/admin/src/scripts/50cryptpwdstorageplugin.ldif \
ldap/admin/src/scripts/50contentsync.ldif \
ldap/admin/src/scripts/60upgradeschemafiles.pl \
ldap/admin/src/scripts/60upgradeconfigfiles.pl \
diff --git a/ldap/admin/src/scripts/50cryptpwdstorageplugin.ldif b/ldap/admin/src/scripts/50cryptpwdstorageplugin.ldif
new file mode 100644
index 000000000..0a4a50776
--- /dev/null
+++ b/ldap/admin/src/scripts/50cryptpwdstorageplugin.ldif
@@ -0,0 +1,38 @@
+dn: cn=CRYPT-MD5,cn=Password Storage Schemes,cn=plugins,cn=config
+objectClass: top
+objectClass: nsSlapdPlugin
+cn: CRYPT-MD5
+nsslapd-pluginPath: libpwdstorage-plugin
+nsslapd-pluginInitfunc: crypt_md5_pwd_storage_scheme_init
+nsslapd-pluginType: pwdstoragescheme
+nsslapd-pluginEnabled: on
+nsslapd-pluginId: ID
+nsslapd-pluginVersion: PACKAGE_VERSION
+nsslapd-pluginVendor: VENDOR
+nsslapd-pluginDescription: DESC
+
+dn: cn=CRYPT-SHA256,cn=Password Storage Schemes,cn=plugins,cn=config
+objectClass: top
+objectClass: nsSlapdPlugin
+cn: CRYPT-SHA256
+nsslapd-pluginPath: libpwdstorage-plugin
+nsslapd-pluginInitfunc: crypt_sha256_pwd_storage_scheme_init
+nsslapd-pluginType: pwdstoragescheme
+nsslapd-pluginEnabled: on
+nsslapd-pluginId: ID
+nsslapd-pluginVersion: PACKAGE_VERSION
+nsslapd-pluginVendor: VENDOR
+nsslapd-pluginDescription: DESC
+
+dn: cn=CRYPT-SHA512,cn=Password Storage Schemes,cn=plugins,cn=config
+objectClass: top
+objectClass: nsSlapdPlugin
+cn: CRYPT-SHA512
+nsslapd-pluginPath: libpwdstorage-plugin
+nsslapd-pluginInitfunc: crypt_sha512_pwd_storage_scheme_init
+nsslapd-pluginType: pwdstoragescheme
+nsslapd-pluginEnabled: on
+nsslapd-pluginId: ID
+nsslapd-pluginVersion: PACKAGE_VERSION
+nsslapd-pluginVendor: VENDOR
+nsslapd-pluginDescription: DESC
--
2.13.6

View file

@ -1,205 +0,0 @@
From 279489884f56cfc97d1ad9afdf92da3ad3b05b70 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 11 May 2018 10:53:06 -0400
Subject: [PATCH] Ticket 49671 - Readonly replicas should not write internal
ops to changelog
Bug Description: When a hub receives an update that triggers the memberOf
plugin, but that interal operation has no csn and that
causes the update to the changelog to fail and break
replication.
Fix Description: Do not write internal updates with no csns to the changelog
on read-only replicas.
https://pagure.io/389-ds-base/issue/49671
Reviewed by: simon, tbordaz, and lkrispen (Thanks!!!)
(cherry picked from commit afb755bd95f1643665ea34c5a5fa2bb26bfa21b9)
---
.../tests/suites/replication/cascading_test.py | 150 +++++++++++++++++++++
ldap/servers/plugins/replication/repl5_plugins.c | 10 ++
2 files changed, 160 insertions(+)
create mode 100644 dirsrvtests/tests/suites/replication/cascading_test.py
diff --git a/dirsrvtests/tests/suites/replication/cascading_test.py b/dirsrvtests/tests/suites/replication/cascading_test.py
new file mode 100644
index 000000000..7331f20e9
--- /dev/null
+++ b/dirsrvtests/tests/suites/replication/cascading_test.py
@@ -0,0 +1,150 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2018 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import logging
+import pytest
+import os
+import ldap
+from lib389._constants import *
+from lib389.replica import ReplicationManager
+from lib389.plugins import MemberOfPlugin
+from lib389.agreement import Agreements
+from lib389.idm.user import UserAccount, TEST_USER_PROPERTIES
+from lib389.idm.group import Groups
+from lib389.topologies import topology_m1h1c1 as topo
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+BIND_DN = 'uid=tuser1,ou=People,dc=example,dc=com'
+BIND_RDN = 'tuser1'
+
+
+def config_memberof(server):
+ """Configure memberOf plugin and configure fractional
+ to prevent total init to send memberof
+ """
+
+ memberof = MemberOfPlugin(server)
+ memberof.enable()
+ memberof.set_autoaddoc('nsMemberOf')
+ server.restart()
+ agmts = Agreements(server)
+ for agmt in agmts.list():
+ log.info('update %s to add nsDS5ReplicatedAttributeListTotal' % agmt.dn)
+ agmt.replace_many(('nsDS5ReplicatedAttributeListTotal', '(objectclass=*) $ EXCLUDE '),
+ ('nsDS5ReplicatedAttributeList', '(objectclass=*) $ EXCLUDE memberOf'))
+
+
+def test_basic_with_hub(topo):
+ """Check that basic operations work in cascading replication, this includes
+ testing plugins that perform internal operatons, and replicated password
+ policy state attributes.
+
+ :id: 4ac85552-45bc-477b-89a4-226dfff8c6cc
+ :setup: 1 master, 1 hub, 1 consumer
+ :steps:
+ 1. Enable memberOf plugin and set password account lockout settings
+ 2. Restart the instance
+ 3. Add a user
+ 4. Add a group
+ 5. Test that the replication works
+ 6. Add the user as a member to the group
+ 7. Test that the replication works
+ 8. Issue bad binds to update passwordRetryCount
+ 9. Test that replicaton works
+ 10. Check that passwordRetyCount was replicated
+ :expectedresults:
+ 1. Should be a success
+ 2. Should be a success
+ 3. Should be a success
+ 4. Should be a success
+ 5. Should be a success
+ 6. Should be a success
+ 7. Should be a success
+ 8. Should be a success
+ 9. Should be a success
+ 10. Should be a success
+ """
+
+ repl_manager = ReplicationManager(DEFAULT_SUFFIX)
+ master = topo.ms["master1"]
+ consumer = topo.cs["consumer1"]
+ hub = topo.hs["hub1"]
+
+ for inst in topo:
+ config_memberof(inst)
+ inst.config.set('passwordlockout', 'on')
+ inst.config.set('passwordlockoutduration', '60')
+ inst.config.set('passwordmaxfailure', '3')
+ inst.config.set('passwordIsGlobalPolicy', 'on')
+
+ # Create user
+ user1 = UserAccount(master, BIND_DN)
+ user_props = TEST_USER_PROPERTIES.copy()
+ user_props.update({'sn': BIND_RDN,
+ 'cn': BIND_RDN,
+ 'uid': BIND_RDN,
+ 'inetUserStatus': '1',
+ 'objectclass': 'extensibleObject',
+ 'userpassword': PASSWORD})
+ user1.create(properties=user_props, basedn=SUFFIX)
+
+ # Create group
+ groups = Groups(master, DEFAULT_SUFFIX)
+ group = groups.create(properties={'cn': 'group'})
+
+ # Test replication
+ repl_manager.test_replication(master, consumer)
+
+ # Trigger memberOf plugin by adding user to group
+ group.replace('member', user1.dn)
+
+ # Test replication once more
+ repl_manager.test_replication(master, consumer)
+
+ # Issue bad password to update passwordRetryCount
+ try:
+ master.simple_bind_s(user1.dn, "badpassword")
+ except:
+ pass
+
+ # Test replication one last time
+ master.simple_bind_s(DN_DM, PASSWORD)
+ repl_manager.test_replication(master, consumer)
+
+ # Finally check if passwordRetyCount was replicated to the hub and consumer
+ user1 = UserAccount(hub, BIND_DN)
+ count = user1.get_attr_val_int('passwordRetryCount')
+ if count is None:
+ log.fatal('PasswordRetyCount was not replicated to hub')
+ assert False
+ if int(count) != 1:
+ log.fatal('PasswordRetyCount has unexpected value: {}'.format(count))
+ assert False
+
+ user1 = UserAccount(consumer, BIND_DN)
+ count = user1.get_attr_val_int('passwordRetryCount')
+ if count is None:
+ log.fatal('PasswordRetyCount was not replicated to consumer')
+ assert False
+ if int(count) != 1:
+ log.fatal('PasswordRetyCount has unexpected value: {}'.format(count))
+ assert False
+
+
+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/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index 0aee8829a..324e38263 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -1059,6 +1059,16 @@ write_changelog_and_ruv(Slapi_PBlock *pb)
goto common_return;
}
+ /* Skip internal operations with no op csn if this is a read-only replica */
+ if (op_params->csn == NULL &&
+ operation_is_flag_set(op, OP_FLAG_INTERNAL) &&
+ replica_get_type(r) == REPLICA_TYPE_READONLY)
+ {
+ slapi_log_err(SLAPI_LOG_REPL, "write_changelog_and_ruv",
+ "Skipping internal operation on read-only replica\n");
+ goto common_return;
+ }
+
/* we might have stripped all the mods - in that case we do not
log the operation */
if (op_params->operation_type != SLAPI_OPERATION_MODIFY ||
--
2.13.6

View file

@ -1,48 +0,0 @@
From f0b41ec12f957612c69ae5be3bbbb6e2d6db2530 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Thu, 17 May 2018 10:31:58 +0200
Subject: [PATCH] Ticket 49696: replicated operations should be serialized
Bug: there was a scenario where two threads could process replication operations in parallel.
The reason was that for a new repl start request the repl conn flag is not set and the
connection is made readable.
When the start repl op is finished, the flagi set, but in a small window the supplier could
already have sent updates and more_data would trigger this thread also to continue to process
repl operations.
Fix: In the situation where a thread successfully processed a start repl request and just set the repl_conn
flag do not use more_data.
Reviewed by: Thierry, thanks
---
ldap/servers/slapd/connection.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 5ca32a333..b5030f0cb 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -1822,9 +1822,17 @@ connection_threadmain()
/* If we're in turbo mode, we keep our reference to the connection alive */
/* can't use the more_data var because connection could have changed in another thread */
- more_data = conn_buffered_data_avail_nolock(conn, &conn_closed) ? 1 : 0;
- slapi_log_err(SLAPI_LOG_CONNS, "connection_threadmain", "conn %" PRIu64 " check more_data %d thread_turbo_flag %d\n",
- conn->c_connid, more_data, thread_turbo_flag);
+ slapi_log_err(SLAPI_LOG_CONNS, "connection_threadmain", "conn %" PRIu64 " check more_data %d thread_turbo_flag %d"
+ "repl_conn_bef %d, repl_conn_now %d\n",
+ conn->c_connid, more_data, thread_turbo_flag,
+ replication_connection, conn->c_isreplication_session);
+ if (!replication_connection && conn->c_isreplication_session) {
+ /* it a connection that was just flagged as replication connection */
+ more_data = 0;
+ } else {
+ /* normal connection or already established replication connection */
+ more_data = conn_buffered_data_avail_nolock(conn, &conn_closed) ? 1 : 0;
+ }
if (!more_data) {
if (!thread_turbo_flag) {
/*
--
2.13.6

View file

@ -1,335 +0,0 @@
From 5a5d3dffd0b36edb543fd31fa53d7128dd5161c2 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Fri, 18 May 2018 10:13:46 +0200
Subject: [PATCH] Ticket 48184 - clean up and delete connections at shutdown
(2nd try)
Bug description:
During shutdown we would not close connections.
In the past this may have just been an annoyance, but now with the way
nunc-stans works, io events can still trigger on open xeisting connectinos
during shutdown.
Because of NS dynamic it can happen that several jobs wants to work on the
same connection. In such case (a job is already set in c_job) we delay the
new job that will retry.
In addition:
- some call needed c_mutex
- test uninitialized nunc-stans in case of shutdown while startup is not completed
Fix Description: Close connections during shutdown rather than
leaving them alive.
https://pagure.io/389-ds-base/issue/48184
Reviewed by:
Original was Ludwig and Viktor
Second fix reviewed by Mark
Platforms tested: F26
Flag Day: no
Doc impact: no
(cherry picked from commit e562157ca3e97867d902996cc18fb04f90dc10a8)
---
ldap/servers/slapd/connection.c | 2 +
ldap/servers/slapd/conntable.c | 13 ++++
ldap/servers/slapd/daemon.c | 131 ++++++++++++++++++++++++++++------------
ldap/servers/slapd/fe.h | 1 +
ldap/servers/slapd/slap.h | 1 +
5 files changed, 108 insertions(+), 40 deletions(-)
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index b5030f0cb..76e83112b 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -1716,7 +1716,9 @@ connection_threadmain()
if ((tag != LDAP_REQ_UNBIND) && !thread_turbo_flag && !replication_connection) {
if (!more_data) {
conn->c_flags &= ~CONN_FLAG_MAX_THREADS;
+ PR_EnterMonitor(conn->c_mutex);
connection_make_readable_nolock(conn);
+ PR_ExitMonitor(conn->c_mutex);
/* once the connection is readable, another thread may access conn,
* so need locking from here on */
signal_listner();
diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c
index 7c57b47cd..f2f763dfa 100644
--- a/ldap/servers/slapd/conntable.c
+++ b/ldap/servers/slapd/conntable.c
@@ -91,6 +91,19 @@ connection_table_abandon_all_operations(Connection_Table *ct)
}
}
+void
+connection_table_disconnect_all(Connection_Table *ct)
+{
+ for (size_t i = 0; i < ct->size; i++) {
+ if (ct->c[i].c_mutex) {
+ Connection *c = &(ct->c[i]);
+ PR_EnterMonitor(c->c_mutex);
+ disconnect_server_nomutex(c, c->c_connid, -1, SLAPD_DISCONNECT_ABORT, ECANCELED);
+ PR_ExitMonitor(c->c_mutex);
+ }
+ }
+}
+
/* Given a file descriptor for a socket, this function will return
* a slot in the connection table to use.
*
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index fcc461a90..50e67474e 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1087,12 +1087,18 @@ slapd_daemon(daemon_ports_t *ports, ns_thrpool_t *tp)
/* we have exited from ns_thrpool_wait. This means we are shutting down! */
/* Please see https://firstyear.fedorapeople.org/nunc-stans/md_docs_job-safety.html */
/* tldr is shutdown needs to run first to allow job_done on an ARMED job */
- for (size_t i = 0; i < listeners; i++) {
- PRStatus shutdown_status = ns_job_done(listener_idxs[i].ns_job);
- if (shutdown_status != PR_SUCCESS) {
- slapi_log_err(SLAPI_LOG_CRIT, "ns_set_shutdown", "Failed to shutdown listener idx %" PRIu64 " !\n", i);
+ for (uint64_t i = 0; i < listeners; i++) {
+ PRStatus shutdown_status;
+
+ if (listener_idxs[i].ns_job) {
+ shutdown_status = ns_job_done(listener_idxs[i].ns_job);
+ if (shutdown_status != PR_SUCCESS) {
+ slapi_log_err(SLAPI_LOG_CRIT, "ns_set_shutdown", "Failed to shutdown listener idx %" PRIu64 " !\n", i);
+ }
+ PR_ASSERT(shutdown_status == PR_SUCCESS);
+ } else {
+ slapi_log_err(SLAPI_LOG_CRIT, "slapd_daemon", "Listeners uninitialized. Possibly the server was shutdown while starting\n");
}
- PR_ASSERT(shutdown_status == PR_SUCCESS);
listener_idxs[i].ns_job = NULL;
}
} else {
@@ -1176,6 +1182,32 @@ slapd_daemon(daemon_ports_t *ports, ns_thrpool_t *tp)
housekeeping_stop(); /* Run this after op_thread_cleanup() logged sth */
disk_monitoring_stop();
+ /*
+ * Now that they are abandonded, we need to mark them as done.
+ * In NS while it's safe to allow excess jobs to be cleaned by
+ * by the walk and ns_job_done of remaining queued events, the
+ * issue is that if we allow something to live past this point
+ * the CT is freed from underneath, and bad things happen (tm).
+ *
+ * NOTE: We do this after we stop psearch, because there could
+ * be a race between flagging the psearch done, and users still
+ * try to send on the connection. Similar with op_threads.
+ */
+ connection_table_disconnect_all(the_connection_table);
+
+ /*
+ * WARNING: Normally we should close the tp in main
+ * but because of issues in the current connection design
+ * we need to close it here to guarantee events won't fire!
+ *
+ * All the connection close jobs "should" complete before
+ * shutdown at least.
+ */
+ if (enable_nunc_stans) {
+ ns_thrpool_shutdown(tp);
+ ns_thrpool_wait(tp);
+ }
+
threads = g_get_active_threadcnt();
if (threads > 0) {
slapi_log_err(SLAPI_LOG_INFO, "slapd_daemon",
@@ -1628,25 +1660,18 @@ ns_handle_closure(struct ns_job_t *job)
Connection *c = (Connection *)ns_job_get_data(job);
int do_yield = 0;
-/* this function must be called from the event loop thread */
-#ifdef DEBUG
- PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
-#else
- /* This doesn't actually confirm it's in the event loop thread, but it's a start */
- if (NS_JOB_IS_THREAD(ns_job_get_type(job)) != 0) {
- slapi_log_err(SLAPI_LOG_ERR, "ns_handle_closure", "Attempt to close outside of event loop thread %" PRIu64 " for fd=%d\n",
- c->c_connid, c->c_sd);
- return;
- }
-#endif
-
PR_EnterMonitor(c->c_mutex);
+ /* Assert we really have the right job state. */
+ PR_ASSERT(job == c->c_job);
connection_release_nolock_ext(c, 1); /* release ref acquired for event framework */
PR_ASSERT(c->c_ns_close_jobs == 1); /* should be exactly 1 active close job - this one */
c->c_ns_close_jobs--; /* this job is processing closure */
+ /* Because handle closure will add a new job, we need to detach our current one. */
+ c->c_job = NULL;
do_yield = ns_handle_closure_nomutex(c);
PR_ExitMonitor(c->c_mutex);
+ /* Remove this task now. */
ns_job_done(job);
if (do_yield) {
/* closure not done - another reference still outstanding */
@@ -1659,14 +1684,25 @@ ns_handle_closure(struct ns_job_t *job)
/**
* Schedule more I/O for this connection, or make sure that it
* is closed in the event loop.
+ * caller must hold c_mutex
+ * It returns
+ * 0 on success
+ * 1 on need to retry
*/
-void
-ns_connection_post_io_or_closing(Connection *conn)
+static int
+ns_connection_post_io_or_closing_try(Connection *conn)
{
struct timeval tv;
if (!enable_nunc_stans) {
- return;
+ return 0;
+ }
+
+ /*
+ * Cancel any existing ns jobs we have registered.
+ */
+ if (conn->c_job != NULL) {
+ return 1;
}
if (CONN_NEEDS_CLOSING(conn)) {
@@ -1676,15 +1712,12 @@ ns_connection_post_io_or_closing(Connection *conn)
slapi_log_err(SLAPI_LOG_CONNS, "ns_connection_post_io_or_closing", "Already a close "
"job in progress on conn %" PRIu64 " for fd=%d\n",
conn->c_connid, conn->c_sd);
- return;
+ return 0;
} else {
- /* just make sure we schedule the event to be closed in a timely manner */
- tv.tv_sec = 0;
- tv.tv_usec = slapd_wakeup_timer * 1000;
conn->c_ns_close_jobs++; /* now 1 active closure job */
connection_acquire_nolock_ext(conn, 1 /* allow acquire even when closing */); /* event framework now has a reference */
- ns_result_t job_result = ns_add_timeout_job(conn->c_tp, &tv, NS_JOB_TIMER,
- ns_handle_closure, conn, NULL);
+ /* Close the job asynchronously. Why? */
+ ns_result_t job_result = ns_add_job(conn->c_tp, NS_JOB_TIMER, ns_handle_closure, conn, &(conn->c_job));
if (job_result != NS_SUCCESS) {
if (job_result == NS_SHUTDOWN) {
slapi_log_err(SLAPI_LOG_INFO, "ns_connection_post_io_or_closing", "post closure job "
@@ -1723,12 +1756,12 @@ ns_connection_post_io_or_closing(Connection *conn)
* The error occurs when we get a connection in a closing state.
* For now we return, but there is probably a better way to handle the error case.
*/
- return;
+ return 0;
}
#endif
ns_result_t job_result = ns_add_io_timeout_job(conn->c_tp, conn->c_prfd, &tv,
NS_JOB_READ | NS_JOB_PRESERVE_FD,
- ns_handle_pr_read_ready, conn, NULL);
+ ns_handle_pr_read_ready, conn, &(conn->c_job));
if (job_result != NS_SUCCESS) {
if (job_result == NS_SHUTDOWN) {
slapi_log_err(SLAPI_LOG_INFO, "ns_connection_post_io_or_closing", "post I/O job for "
@@ -1745,6 +1778,28 @@ ns_connection_post_io_or_closing(Connection *conn)
conn->c_connid, conn->c_sd);
}
}
+ return 0;
+}
+void
+ns_connection_post_io_or_closing(Connection *conn)
+{
+ while (ns_connection_post_io_or_closing_try(conn)) {
+ /* we should retry later */
+
+ /* We are not suppose to work immediately on the connection that is taken by
+ * another job
+ * release the lock and give some time
+ */
+
+ if (CONN_NEEDS_CLOSING(conn) && conn->c_ns_close_jobs) {
+ return;
+ } else {
+ PR_ExitMonitor(conn->c_mutex);
+ DS_Sleep(PR_MillisecondsToInterval(100));
+
+ PR_EnterMonitor(conn->c_mutex);
+ }
+ }
}
/* This function must be called without the thread flag, in the
@@ -1757,19 +1812,12 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
int maxthreads = config_get_maxthreadsperconn();
Connection *c = (Connection *)ns_job_get_data(job);
-/* this function must be called from the event loop thread */
-#ifdef DEBUG
- PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
-#else
- /* This doesn't actually confirm it's in the event loop thread, but it's a start */
- if (NS_JOB_IS_THREAD(ns_job_get_type(job)) != 0) {
- slapi_log_err(SLAPI_LOG_ERR, "ns_handle_pr_read_ready", "Attempt to handle read ready outside of event loop thread %" PRIu64 " for fd=%d\n",
- c->c_connid, c->c_sd);
- return;
- }
-#endif
-
PR_EnterMonitor(c->c_mutex);
+ /* Assert we really have the right job state. */
+ PR_ASSERT(job == c->c_job);
+
+ /* On all code paths we remove the job, so set it null now */
+ c->c_job = NULL;
slapi_log_err(SLAPI_LOG_CONNS, "ns_handle_pr_read_ready", "activity on conn %" PRIu64 " for fd=%d\n",
c->c_connid, c->c_sd);
@@ -1829,6 +1877,7 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
slapi_log_err(SLAPI_LOG_CONNS, "ns_handle_pr_read_ready", "queued conn %" PRIu64 " for fd=%d\n",
c->c_connid, c->c_sd);
}
+ /* Since we call done on the job, we need to remove it here. */
PR_ExitMonitor(c->c_mutex);
ns_job_done(job);
return;
@@ -2451,7 +2500,9 @@ ns_handle_new_connection(struct ns_job_t *job)
* that poll() was avoided, even at the expense of putting this new fd back
* in nunc-stans to poll for read ready.
*/
+ PR_EnterMonitor(c->c_mutex);
ns_connection_post_io_or_closing(c);
+ PR_ExitMonitor(c->c_mutex);
return;
}
diff --git a/ldap/servers/slapd/fe.h b/ldap/servers/slapd/fe.h
index 4d25a9fb8..f47bb6145 100644
--- a/ldap/servers/slapd/fe.h
+++ b/ldap/servers/slapd/fe.h
@@ -100,6 +100,7 @@ extern Connection_Table *the_connection_table; /* JCM - Exported from globals.c
Connection_Table *connection_table_new(int table_size);
void connection_table_free(Connection_Table *ct);
void connection_table_abandon_all_operations(Connection_Table *ct);
+void connection_table_disconnect_all(Connection_Table *ct);
Connection *connection_table_get_connection(Connection_Table *ct, int sd);
int connection_table_move_connection_out_of_active_list(Connection_Table *ct, Connection *c);
void connection_table_move_connection_on_to_active_list(Connection_Table *ct, Connection *c);
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 03355f5fe..de4ac35c0 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1650,6 +1650,7 @@ typedef struct conn
void *c_io_layer_cb_data; /* callback data */
struct connection_table *c_ct; /* connection table that this connection belongs to */
ns_thrpool_t *c_tp; /* thread pool for this connection */
+ struct ns_job_t *c_job; /* If it exists, the current ns_job_t */
int c_ns_close_jobs; /* number of current close jobs */
char *c_ipaddr; /* ip address str - used by monitor */
} Connection;
--
2.13.6

View file

@ -1,938 +0,0 @@
From 19945c4807f6b3269fb65100ddaea5f596f68e72 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 18 May 2018 07:29:11 -0400
Subject: [PATCH 1/6] Ticket 49576 - Update ds-replcheck for new conflict
entries
Description: This patch addresses the recvent changes to conflict
entries and tombstones.
https://pagure.io/389-ds-base/issue/49576
Reviewed by: tbordaz(Thanks!)
(cherry picked from commit 53e58cdbfb2a2672ac21cd9b6d59f8b345478324)
---
ldap/admin/src/scripts/ds-replcheck | 456 +++++++++++++++++++---------
1 file changed, 312 insertions(+), 144 deletions(-)
diff --git a/ldap/admin/src/scripts/ds-replcheck b/ldap/admin/src/scripts/ds-replcheck
index 45c4670a3..b801ccaa8 100755
--- a/ldap/admin/src/scripts/ds-replcheck
+++ b/ldap/admin/src/scripts/ds-replcheck
@@ -1,7 +1,7 @@
#!/usr/bin/python
# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2017 Red Hat, Inc.
+# Copyright (C) 2018 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
@@ -9,6 +9,7 @@
# --- END COPYRIGHT BLOCK ---
#
+import os
import re
import time
import ldap
@@ -20,7 +21,7 @@ from ldap.ldapobject import SimpleLDAPObject
from ldap.cidict import cidict
from ldap.controls import SimplePagedResultsControl
-VERSION = "1.2"
+VERSION = "1.3"
RUV_FILTER = '(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))'
LDAP = 'ldap'
LDAPS = 'ldaps'
@@ -36,6 +37,7 @@ class Entry(object):
''' This is a stripped down version of Entry from python-lib389.
Once python-lib389 is released on RHEL this class will go away.
'''
+
def __init__(self, entrydata):
if entrydata:
self.dn = entrydata[0]
@@ -51,7 +53,7 @@ class Entry(object):
def get_entry(entries, dn):
- ''' Loop over enties looking for a matching dn
+ ''' Loop over a list of enties looking for a matching dn
'''
for entry in entries:
if entry.dn == dn:
@@ -60,7 +62,7 @@ def get_entry(entries, dn):
def remove_entry(rentries, dn):
- ''' Remove an entry from the array of entries
+ ''' Remove an entry from the list of entries
'''
for entry in rentries:
if entry.dn == dn:
@@ -69,7 +71,7 @@ def remove_entry(rentries, dn):
def extract_time(stateinfo):
- ''' Take the nscpEntryWSI attribute and get the most recent timestamp from
+ ''' Take the nscpEntryWSI(state info) attribute and get the most recent timestamp from
one of the csns (vucsn, vdcsn, mdcsn, adcsn)
Return the timestamp in decimal
@@ -87,7 +89,7 @@ def extract_time(stateinfo):
def convert_timestamp(timestamp):
- ''' Convert createtimestamp to ctime: 20170405184656Z -> Wed Apr 5 19:46:56 2017
+ ''' Convert createtimestamp to ctime: 20170405184656Z ----> Wed Apr 5 19:46:56 2017
'''
time_tuple = (int(timestamp[:4]), int(timestamp[4:6]), int(timestamp[6:8]),
int(timestamp[8:10]), int(timestamp[10:12]), int(timestamp[12:14]),
@@ -97,27 +99,43 @@ def convert_timestamp(timestamp):
def convert_entries(entries):
- '''Convert and normalize the ldap entries. Take note of conflicts and tombstones
- '''
+ '''For online report. Convert and normalize the ldap entries. Take note of
+ conflicts and tombstones '''
new_entries = []
conflict_entries = []
+ glue_entries = []
result = {}
tombstones = 0
+
for entry in entries:
new_entry = Entry(entry)
new_entry.data = {k.lower(): v for k, v in list(new_entry.data.items())}
- if 'nsds5replconflict' in new_entry.data:
+ if new_entry.dn.endswith("cn=mapping tree,cn=config"):
+ '''Skip replica entry (ldapsearch brings this in because the filter
+ we use triggers an internal operation to return the config entry - so
+ it must be skipped
+ '''
+ continue
+ if ('nsds5replconflict' in new_entry.data and 'nsTombstone' not in new_entry.data['objectclass'] and
+ 'nstombstone' not in new_entry.data['objectclass']):
+ # This is a conflict entry that is NOT a tombstone entry (should this be reconsidered?)
conflict_entries.append(new_entry)
+ if 'glue' in new_entry.data['objectclass']:
+ # A glue entry here is not necessarily a glue entry there. Keep track of
+ # them for when we check missing entries
+ glue_entries.append(new_entry)
else:
new_entries.append(new_entry)
if 'nstombstonecsn' in new_entry.data:
+ # Maintain tombstone count
tombstones += 1
del entries
result['entries'] = new_entries
result['conflicts'] = conflict_entries
result['tombstones'] = tombstones
+ result['glue'] = glue_entries
return result
@@ -174,20 +192,60 @@ def get_ruv_report(opts):
return report
+def remove_attr_state_info(attr):
+ state_attr = None
+ idx = attr.find(';')
+ if idx > 0:
+ state_attr = attr # preserve state info for diff report
+ if ";deleted" in attr:
+ # Ignore this attribute it was deleted
+ return None, state_attr
+ attr = attr[:idx]
+
+ return attr.lower(), state_attr
+
+def add_attr_entry(entry, val, attr, state_attr):
+ ''' Offline mode (ldif comparision) Add the attr to the entry, and if there
+ is state info add nscpentrywsi attr - we need consistency with online mode
+ to make code simpler '''
+ if attr is not None:
+ if attr in entry:
+ entry[attr].append(val)
+ else:
+ entry[attr] = [val]
+
+ # Handle state info for diff report
+ if state_attr is not None:
+ state_attr = state_attr + ": " + val
+ if 'nscpentrywsi' in entry:
+ entry['nscpentrywsi'].append(state_attr)
+ else:
+ entry['nscpentrywsi'] = [state_attr]
+ val = ""
+
+
#
# Offline mode helper functions
#
-def ldif_search(LDIF, dn, conflicts=False):
- ''' Search ldif by DN
+def ldif_search(LDIF, dn):
+ ''' Offline mode - Search ldif for a single DN. We need to factor in that
+ DN's and attribute values can wrap lines and are identified by a leading
+ white space. So we can't fully process an attribute until we get to the
+ next attribute.
'''
result = {}
data = {}
found_conflict = False
+ found_subentry = False
found_part_dn = False
+ found_part_val = False
+ found_attr = False
+ found_tombstone = False
+ found_glue = False
found = False
- reset_line = False
count = 0
-
+ ignore_list = ['conflictcsn', 'modifytimestamp', 'modifiersname']
+ val = ""
result['entry'] = None
result['conflict'] = None
result['tombstone'] = False
@@ -195,54 +253,132 @@ def ldif_search(LDIF, dn, conflicts=False):
for line in LDIF:
count += 1
line = line.rstrip()
- if reset_line:
- reset_line = False
- line = prev_line
+
if found:
+ # We found our entry, now build up the entry (account from line wrap)
if line == "":
- # End of entry
+ # End of entry - update entry's last attribute value and break out
+ add_attr_entry(data, val, attr, state_attr)
+ val = ""
+ # Done!
break
if line[0] == ' ':
- # continuation line
- prev = data[attr][len(data[attr]) - 1]
- data[attr][len(data[attr]) - 1] = prev + line.strip()
+ # continuation line (wrapped value)
+ val += line[1:]
+ found_part_val = True
continue
+ elif found_part_val:
+ # We have the complete value now (it was wrapped)
+ found_part_val = False
+ found_attr = False
+ add_attr_entry(data, val, attr, state_attr)
+
+ # Now that the value is added to the entry lets process the new attribute...
+ value_set = line.split(":", 1)
+ attr, state_attr = remove_attr_state_info(value_set[0])
+
+ if attr in ignore_list or (attr is None and state_attr is None):
+ # Skip it
+ found_attr = False
+ attr = None
+ continue
- value_set = line.split(":", 1)
- attr = value_set[0].lower()
- if attr.startswith('nsds5replconflict'):
- found_conflict = True
- if attr.startswith('nstombstonecsn'):
- result['tombstone'] = True
-
- if attr in data:
- data[attr].append(value_set[1].strip())
+ val = value_set[1].strip()
+ found_attr = True
+
+ if attr is not None:
+ # Set the entry type flags
+ if attr.startswith('nsds5replconflict'):
+ found_conflict = True
+ if attr.startswith("objectclass") and val == "ldapsubentry":
+ found_subentry = True
+ if attr.startswith('nstombstonecsn'):
+ result['tombstone'] = True
+ found_tombstone = True
+ continue
else:
- data[attr] = [value_set[1].strip()]
+ # New attribute...
+ if found_attr:
+ # But first we have to add the previous complete attr value to the entry data
+ add_attr_entry(data, val, attr, state_attr)
+
+ # Process new attribute
+ value_set = line.split(":", 1)
+ attr, state_attr = remove_attr_state_info(value_set[0])
+ if attr is None or attr in ignore_list:
+ # Skip it (its deleted)
+ found_attr = False
+ attr = None
+ continue
+
+ val = value_set[1].strip()
+ found_attr = True
+
+ # Set the entry type flags
+ if attr.startswith('nsds5replconflict'):
+ found_conflict = True
+ if attr.startswith("objectclass") and (val == "ldapsubentry" or val == "glue"):
+ if val == "glue":
+ found_glue = True
+ found_subentry = True
+ if attr.startswith('nstombstonecsn'):
+ result['tombstone'] = True
+ found_tombstone = True
+ continue
+
elif found_part_dn:
if line[0] == ' ':
+ # DN is still wrapping, keep building up the dn value
part_dn += line[1:].lower()
else:
- # We have the full dn
+ # We now have the full dn
found_part_dn = False
- reset_line = True
- prev_line = line
if part_dn == dn:
+ # We found our entry
found = True
+
+ # But now we have a new attribute to process
+ value_set = line.split(":", 1)
+ attr, state_attr = remove_attr_state_info(value_set[0])
+ if attr is None or attr in ignore_list:
+ # Skip it (its deleted)
+ found_attr = False
+ attr = None
+ continue
+
+ val = value_set[1].strip()
+ found_attr = True
+
+ if attr.startswith('nsds5replconflict'):
+ found_conflict = True
+ if attr.startswith("objectclass") and val == "ldapsubentry":
+ found_subentry = True
+
+ if attr.startswith('nstombstonecsn'):
+ result['tombstone'] = True
+ found_tombstone = True
continue
+
if line.startswith('dn: '):
if line[4:].lower() == dn:
+ # We got our full DN, now process the entry
found = True
continue
else:
+ # DN wraps the line, keep looping until we get the whole value
part_dn = line[4:].lower()
found_part_dn = True
+ # Keep track of entry index - we use this later when searching the LDIF again
result['idx'] = count
- if found_conflict:
+
+ result['glue'] = None
+ if found_conflict and found_subentry and found_tombstone is False:
result['entry'] = None
result['conflict'] = Entry([dn, data])
+ if found_glue:
+ result['glue'] = result['conflict']
elif found:
result['conflict'] = None
result['entry'] = Entry([dn, data])
@@ -251,7 +387,7 @@ def ldif_search(LDIF, dn, conflicts=False):
def get_dns(LDIF, opts):
- ''' Get all the DN's
+ ''' Get all the DN's from an LDIF file
'''
dns = []
found = False
@@ -275,7 +411,7 @@ def get_dns(LDIF, opts):
def get_ldif_ruv(LDIF, opts):
- ''' Search the ldif and get the ruv entry
+ ''' Search the LDIF and get the ruv entry
'''
LDIF.seek(0)
result = ldif_search(LDIF, opts['ruv_dn'])
@@ -283,7 +419,7 @@ def get_ldif_ruv(LDIF, opts):
def cmp_entry(mentry, rentry, opts):
- ''' Compare the two entries, and return a diff map
+ ''' Compare the two entries, and return a "diff map"
'''
diff = {}
diff['dn'] = mentry['dn']
@@ -307,6 +443,7 @@ def cmp_entry(mentry, rentry, opts):
diff['missing'].append(" - Replica missing attribute: \"%s\"" % (mattr))
diff_count += 1
if 'nscpentrywsi' in mentry.data:
+ # Great we have state info so we can provide details about the missing attribute
found = False
for val in mentry.data['nscpentrywsi']:
if val.lower().startswith(mattr + ';'):
@@ -316,6 +453,7 @@ def cmp_entry(mentry, rentry, opts):
diff['missing'].append(" - Master's State Info: %s" % (val))
diff['missing'].append(" - Date: %s\n" % (time.ctime(extract_time(val))))
else:
+ # No state info, just move on
diff['missing'].append("")
elif mentry.data[mattr] != rentry.data[mattr]:
@@ -335,6 +473,9 @@ def cmp_entry(mentry, rentry, opts):
if not found:
diff['diff'].append(" Master: ")
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
+ # original value
diff['diff'].append(" - Origin value: %s" % (val))
diff['diff'].append("")
@@ -350,10 +491,13 @@ def cmp_entry(mentry, rentry, opts):
if not found:
diff['diff'].append(" Replica: ")
for val in rentry.data[mattr]:
+ # This is an "origin" value which means it's never been
+ # updated since replication was set up. So its the
+ # original value
diff['diff'].append(" - Origin value: %s" % (val))
diff['diff'].append("")
else:
- # no state info
+ # no state info, report what we got
diff['diff'].append(" Master: ")
for val in mentry.data[mattr]:
diff['diff'].append(" - %s: %s" % (mattr, val))
@@ -436,40 +580,62 @@ def do_offline_report(opts, output_file=None):
MLDIF.seek(idx)
RLDIF.seek(idx)
- # Compare the master entries with the replica's
+ """ 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
+ 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.
+ """
print ("Comparing Master to Replica...")
missing = False
for dn in master_dns:
- mresult = ldif_search(MLDIF, dn, True)
- rresult = ldif_search(RLDIF, dn, True)
+ mresult = ldif_search(MLDIF, dn)
+ rresult = ldif_search(RLDIF, dn)
+
+ if dn in replica_dns:
+ if (rresult['entry'] is not None or rresult['glue'] is not None or
+ 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.
+ """
+ replica_dns.remove(dn)
if mresult['tombstone']:
mtombstones += 1
+ # continue
+ if rresult['tombstone']:
+ rtombstones += 1
if mresult['conflict'] is not None or rresult['conflict'] is not None:
+ # If either entry is a conflict we still process it here
if mresult['conflict'] is not None:
mconflicts.append(mresult['conflict'])
+ if rresult['conflict'] is not None:
+ rconflicts.append(rresult['conflict'])
elif rresult['entry'] is None:
- # missing entry - restart the search from beginning
+ # missing entry - restart the search from beginning in case it got skipped
RLDIF.seek(0)
rresult = ldif_search(RLDIF, dn)
- if rresult['entry'] is None:
- # missing entry in rentries
- RLDIF.seek(mresult['idx']) # Set the cursor to the last good line
+ if rresult['entry'] is None and rresult['glue'] is None:
+ # missing entry in Replica(rentries)
+ RLDIF.seek(mresult['idx']) # Set the LDIF cursor/index to the last good line
if not missing:
- missing_report += ('Replica is missing entries:\n')
+ missing_report += (' Entries missing on Replica:\n')
missing = True
if mresult['entry'] and 'createtimestamp' in mresult['entry'].data:
- missing_report += (' - %s (Master\'s creation date: %s)\n' %
+ missing_report += (' - %s (Created on Master at: %s)\n' %
(dn, convert_timestamp(mresult['entry'].data['createtimestamp'][0])))
else:
missing_report += (' - %s\n' % dn)
- else:
+ elif mresult['tombstone'] is False:
# Compare the entries
diff = cmp_entry(mresult['entry'], rresult['entry'], opts)
if diff:
diff_report.append(format_diff(diff))
- else:
+ elif mresult['tombstone'] is False:
# Compare the entries
diff = cmp_entry(mresult['entry'], rresult['entry'], opts)
if diff:
@@ -478,7 +644,10 @@ def do_offline_report(opts, output_file=None):
if missing:
missing_report += ('\n')
- # Search Replica, and look for missing entries only. Count entries as well
+ """ Search Replica, and look for missing entries only. We already did the
+ diff checking, so its only missing entries we are worried about. Count the
+ remaining conflict & tombstone entries as well.
+ """
print ("Comparing Replica to Master...")
MLDIF.seek(0)
RLDIF.seek(0)
@@ -486,26 +655,26 @@ def do_offline_report(opts, output_file=None):
for dn in replica_dns:
rresult = ldif_search(RLDIF, dn)
mresult = ldif_search(MLDIF, dn)
-
if rresult['tombstone']:
rtombstones += 1
- if mresult['entry'] is not None or rresult['conflict'] is not None:
- if rresult['conflict'] is not None:
- rconflicts.append(rresult['conflict'])
+ # continue
+
+ if rresult['conflict'] is not None:
+ rconflicts.append(rresult['conflict'])
elif mresult['entry'] is None:
# missing entry
MLDIF.seek(0)
mresult = ldif_search(MLDIF, dn)
- if mresult['entry'] is None and mresult['conflict'] is not None:
- MLDIF.seek(rresult['idx']) # Set the cursor to the last good line
+ 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 += ('Master is missing entries:\n')
+ missing_report += (' Entries missing on Master:\n')
missing = True
- if 'createtimestamp' in rresult['entry'].data:
- missing_report += (' - %s (Replica\'s creation date: %s)\n' %
+ if rresult['entry'] and 'createtimestamp' in rresult['entry'].data:
+ missing_report += (' - %s (Created on Replica at: %s)\n' %
(dn, convert_timestamp(rresult['entry'].data['createtimestamp'][0])))
else:
- missing_report += (' - %s\n')
+ missing_report += (' - %s\n' % dn)
if missing:
missing_report += ('\n')
@@ -553,8 +722,8 @@ def do_offline_report(opts, output_file=None):
print(final_report)
-def check_for_diffs(mentries, rentries, report, opts):
- ''' Check for diffs, return the updated report
+def check_for_diffs(mentries, mglue, rentries, rglue, report, opts):
+ ''' Online mode only - Check for diffs, return the updated report
'''
diff_report = []
m_missing = []
@@ -569,18 +738,26 @@ def check_for_diffs(mentries, rentries, report, opts):
for mentry in mentries:
rentry = get_entry(rentries, mentry.dn)
if rentry:
- diff = cmp_entry(mentry, rentry, opts)
- if diff:
- diff_report.append(format_diff(diff))
+ if 'nsTombstone' not in rentry.data['objectclass'] and 'nstombstone' not in rentry.data['objectclass']:
+ diff = cmp_entry(mentry, rentry, opts)
+ if diff:
+ diff_report.append(format_diff(diff))
# Now remove the rentry from the rentries so we can find stragglers
remove_entry(rentries, rentry.dn)
else:
- # Add missing entry in Replica
- r_missing.append(mentry)
+ rentry = get_entry(rglue, mentry.dn)
+ if rentry:
+ # Glue entry nothing to compare
+ remove_entry(rentries, rentry.dn)
+ else:
+ # Add missing entry in Replica
+ r_missing.append(mentry)
for rentry in rentries:
# We should not have any entries if we are sync
- m_missing.append(rentry)
+ mentry = get_entry(mglue, rentry.dn)
+ if mentry is None:
+ m_missing.append(rentry)
if len(diff_report) > 0:
report['diff'] += diff_report
@@ -609,6 +786,12 @@ def connect_to_replicas(opts):
ruri = "%s://%s:%s/" % (opts['rprotocol'], opts['rhost'], opts['rport'])
replica = SimpleLDAPObject(ruri)
+ # Set timeouts
+ master.set_option(ldap.OPT_NETWORK_TIMEOUT,5.0)
+ master.set_option(ldap.OPT_TIMEOUT,5.0)
+ replica.set_option(ldap.OPT_NETWORK_TIMEOUT,5.0)
+ replica.set_option(ldap.OPT_TIMEOUT,5.0)
+
# Setup Secure Conenction
if opts['certdir'] is not None:
# Setup Master
@@ -620,7 +803,7 @@ def connect_to_replicas(opts):
try:
master.start_tls_s()
except ldap.LDAPError as e:
- print('TLS negotiation failed on Master: %s' % str(e))
+ print('TLS negotiation failed on Master: {}'.format(str(e)))
exit(1)
# Setup Replica
@@ -632,7 +815,7 @@ def connect_to_replicas(opts):
try:
replica.start_tls_s()
except ldap.LDAPError as e:
- print('TLS negotiation failed on Master: %s' % str(e))
+ print('TLS negotiation failed on Master: {}'.format(str(e)))
exit(1)
# Open connection to master
@@ -642,7 +825,8 @@ def connect_to_replicas(opts):
print("Cannot connect to %r" % muri)
exit(1)
except ldap.LDAPError as e:
- print("Error: Failed to authenticate to Master: %s", str(e))
+ print("Error: Failed to authenticate to Master: ({}). "
+ "Please check your credentials and LDAP urls are correct.".format(str(e)))
exit(1)
# Open connection to replica
@@ -652,7 +836,8 @@ def connect_to_replicas(opts):
print("Cannot connect to %r" % ruri)
exit(1)
except ldap.LDAPError as e:
- print("Error: Failed to authenticate to Replica: %s", str(e))
+ print("Error: Failed to authenticate to Replica: ({}). "
+ "Please check your credentials and LDAP urls are correct.".format(str(e)))
exit(1)
# Get the RUVs
@@ -665,7 +850,7 @@ def connect_to_replicas(opts):
print("Error: Master does not have an RUV entry")
exit(1)
except ldap.LDAPError as e:
- print("Error: Failed to get Master RUV entry: %s", str(e))
+ print("Error: Failed to get Master RUV entry: {}".format(str(e)))
exit(1)
print ("Gathering Replica's RUV...")
@@ -678,7 +863,7 @@ def connect_to_replicas(opts):
exit(1)
except ldap.LDAPError as e:
- print("Error: Failed to get Replica RUV entry: %s", str(e))
+ print("Error: Failed to get Replica RUV entry: {}".format(str(e)))
exit(1)
return (master, replica, opts)
@@ -687,6 +872,7 @@ def connect_to_replicas(opts):
def print_online_report(report, opts, output_file):
''' Print the online report
'''
+
print ('Preparing final report...')
m_missing = len(report['m_missing'])
r_missing = len(report['r_missing'])
@@ -711,22 +897,23 @@ def print_online_report(report, opts, output_file):
missing = True
final_report += ('\nMissing Entries\n')
final_report += ('=====================================================\n\n')
- if m_missing > 0:
- final_report += (' Entries missing on Master:\n')
- for entry in report['m_missing']:
+
+ if r_missing > 0:
+ final_report += (' Entries missing on Replica:\n')
+ for entry in report['r_missing']:
if 'createtimestamp' in entry.data:
- final_report += (' - %s (Created on Replica at: %s)\n' %
+ final_report += (' - %s (Created on Master at: %s)\n' %
(entry.dn, convert_timestamp(entry.data['createtimestamp'][0])))
else:
final_report += (' - %s\n' % (entry.dn))
- if r_missing > 0:
- if m_missing > 0:
+ if m_missing > 0:
+ if r_missing > 0:
final_report += ('\n')
- final_report += (' Entries missing on Replica:\n')
- for entry in report['r_missing']:
+ final_report += (' Entries missing on Master:\n')
+ for entry in report['m_missing']:
if 'createtimestamp' in entry.data:
- final_report += (' - %s (Created on Master at: %s)\n' %
+ final_report += (' - %s (Created on Replica at: %s)\n' %
(entry.dn, convert_timestamp(entry.data['createtimestamp'][0])))
else:
final_report += (' - %s\n' % (entry.dn))
@@ -751,7 +938,8 @@ def print_online_report(report, opts, output_file):
def remove_state_info(entry):
''' Remove the state info for the attributes used in the conflict report
'''
- attrs = ['objectclass', 'nsds5replconflict', 'createtimestamp']
+ attrs = ['objectclass', 'nsds5replconflict', 'createtimestamp' , 'modifytimestamp']
+ # attrs = ['createtimestamp']
for key, val in list(entry.data.items()):
for attr in attrs:
if key.lower().startswith(attr):
@@ -766,9 +954,6 @@ def get_conflict_report(mentries, rentries, verbose, format_conflicts=False):
r_conflicts = []
for entry in mentries:
- if format_conflicts:
- remove_state_info(entry)
-
if 'glue' in entry.data['objectclass']:
m_conflicts.append({'dn': entry.dn, 'conflict': entry.data['nsds5replconflict'][0],
'date': entry.data['createtimestamp'][0], 'glue': 'yes'})
@@ -776,9 +961,6 @@ def get_conflict_report(mentries, rentries, verbose, format_conflicts=False):
m_conflicts.append({'dn': entry.dn, 'conflict': entry.data['nsds5replconflict'][0],
'date': entry.data['createtimestamp'][0], 'glue': 'no'})
for entry in rentries:
- if format_conflicts:
- remove_state_info(entry)
-
if 'glue' in entry.data['objectclass']:
r_conflicts.append({'dn': entry.dn, 'conflict': entry.data['nsds5replconflict'][0],
'date': entry.data['createtimestamp'][0], 'glue': 'yes'})
@@ -790,7 +972,7 @@ def get_conflict_report(mentries, rentries, verbose, format_conflicts=False):
report = "\n\nConflict Entries\n"
report += "=====================================================\n\n"
if len(m_conflicts) > 0:
- report += ('Master Conflict Entries: %d\n' % (len(m_conflicts)))
+ report += ('Master Conflict Entries: %d\n' % (len(m_conflicts)))
if verbose:
for entry in m_conflicts:
report += ('\n - %s\n' % (entry['dn']))
@@ -799,7 +981,7 @@ def get_conflict_report(mentries, rentries, verbose, format_conflicts=False):
report += (' - Created: %s\n' % (convert_timestamp(entry['date'])))
if len(r_conflicts) > 0:
- if len(m_conflicts) > 0:
+ if len(m_conflicts) > 0 and verbose:
report += "\n" # add spacer
report += ('Replica Conflict Entries: %d\n' % (len(r_conflicts)))
if verbose:
@@ -814,46 +996,6 @@ def get_conflict_report(mentries, rentries, verbose, format_conflicts=False):
return ""
-def get_tombstones(replica, opts):
- ''' Return the number of tombstones
- '''
- paged_ctrl = SimplePagedResultsControl(True, size=opts['pagesize'], cookie='')
- controls = [paged_ctrl]
- req_pr_ctrl = controls[0]
- count = 0
-
- try:
- msgid = replica.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
- '(&(objectclass=nstombstone)(nstombstonecsn=*))',
- ['dn'], serverctrls=controls)
- except ldap.LDAPError as e:
- print("Error: Failed to get tombstone entries: %s", str(e))
- exit(1)
-
- done = False
- while not done:
- rtype, rdata, rmsgid, rctrls = replica.result3(msgid)
- count += len(rdata)
-
- pctrls = [
- c
- for c in rctrls
- if c.controlType == SimplePagedResultsControl.controlType
- ]
- if pctrls:
- if pctrls[0].cookie:
- # Copy cookie from response control to request control
- req_pr_ctrl.cookie = pctrls[0].cookie
- msgid = replica.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
- '(&(objectclass=nstombstone)(nstombstonecsn=*))',
- ['dn'], serverctrls=controls)
- else:
- done = True # No more pages available
- else:
- done = True
- return count
-
-
def do_online_report(opts, output_file=None):
''' Check for differences between two replicas
'''
@@ -880,7 +1022,7 @@ def do_online_report(opts, output_file=None):
req_pr_ctrl = controls[0]
try:
master_msgid = master.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
- "(|(objectclass=*)(objectclass=ldapsubentry))",
+ "(|(objectclass=*)(objectclass=ldapsubentry)(objectclass=nstombstone))",
['*', 'createtimestamp', 'nscpentrywsi', 'nsds5replconflict'],
serverctrls=controls)
except ldap.LDAPError as e:
@@ -888,7 +1030,7 @@ def do_online_report(opts, output_file=None):
exit(1)
try:
replica_msgid = replica.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
- "(|(objectclass=*)(objectclass=ldapsubentry))",
+ "(|(objectclass=*)(objectclass=ldapsubentry)(objectclass=nstombstone))",
['*', 'createtimestamp', 'nscpentrywsi', 'nsds5replconflict'],
serverctrls=controls)
except ldap.LDAPError as e:
@@ -918,7 +1060,9 @@ def do_online_report(opts, output_file=None):
rconflicts += rresult['conflicts']
# Check for diffs
- report = check_for_diffs(mresult['entries'], rresult['entries'], report, opts)
+ report = check_for_diffs(mresult['entries'], mresult['glue'],
+ rresult['entries'], rresult['glue'],
+ report, opts)
if not m_done:
# Master
@@ -933,7 +1077,7 @@ def do_online_report(opts, output_file=None):
req_pr_ctrl.cookie = m_pctrls[0].cookie
master_msgid = master.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
"(|(objectclass=*)(objectclass=ldapsubentry))",
- ['*', 'createtimestamp', 'nscpentrywsi', 'nsds5replconflict'], serverctrls=controls)
+ ['*', 'createtimestamp', 'nscpentrywsi', 'conflictcsn', 'nsds5replconflict'], serverctrls=controls)
else:
m_done = True # No more pages available
else:
@@ -953,7 +1097,7 @@ def do_online_report(opts, output_file=None):
req_pr_ctrl.cookie = r_pctrls[0].cookie
replica_msgid = replica.search_ext(opts['suffix'], ldap.SCOPE_SUBTREE,
"(|(objectclass=*)(objectclass=ldapsubentry))",
- ['*', 'createtimestamp', 'nscpentrywsi', 'nsds5replconflict'], serverctrls=controls)
+ ['*', 'createtimestamp', 'nscpentrywsi', 'conflictcsn', 'nsds5replconflict'], serverctrls=controls)
else:
r_done = True # No more pages available
else:
@@ -961,10 +1105,8 @@ def do_online_report(opts, output_file=None):
# Get conflicts & tombstones
report['conflict'] = get_conflict_report(mconflicts, rconflicts, opts['conflicts'])
- report['mtombstones'] = get_tombstones(master, opts)
- report['rtombstones'] = get_tombstones(replica, opts)
- report['m_count'] += report['mtombstones']
- report['r_count'] += report['rtombstones']
+ report['mtombstones'] = mresult['tombstones']
+ report['rtombstones'] = rresult['tombstones']
# Do the final report
print_online_report(report, opts, output_file)
@@ -1027,11 +1169,16 @@ def main():
# Parse the ldap URLs
if args.murl is not None and args.rurl is not None:
+ # Make sure the URLs are different
+ if args.murl == args.rurl:
+ print("Master and Replica LDAP URLs are the same, they must be different")
+ exit(1)
+
# Parse Master url
- murl = ldapurl.LDAPUrl(args.murl)
if not ldapurl.isLDAPUrl(args.murl):
print("Master LDAP URL is invalid")
exit(1)
+ murl = ldapurl.LDAPUrl(args.murl)
if murl.urlscheme in VALID_PROTOCOLS:
opts['mprotocol'] = murl.urlscheme
else:
@@ -1052,10 +1199,10 @@ def main():
opts['mport'] = parts[1]
# Parse Replica url
- rurl = ldapurl.LDAPUrl(args.rurl)
if not ldapurl.isLDAPUrl(args.rurl):
print("Replica LDAP URL is invalid")
exit(1)
+ rurl = ldapurl.LDAPUrl(args.rurl)
if rurl.urlscheme in VALID_PROTOCOLS:
opts['rprotocol'] = rurl.urlscheme
else:
@@ -1075,11 +1222,19 @@ def main():
opts['rhost'] = parts[0]
opts['rport'] = parts[1]
+ # Validate certdir
+ opts['certdir'] = None
+ if args.certdir:
+ if os.path.exists() and os.path.isdir(certdir):
+ opts['certdir'] = args.certdir
+ else:
+ print("certificate directory ({}) does not exist or is not a directory".format(args.certdir))
+ exit(1)
+
# Initialize the options
opts['binddn'] = args.binddn
opts['bindpw'] = args.bindpw
opts['suffix'] = args.suffix
- opts['certdir'] = args.certdir
opts['starttime'] = int(time.time())
opts['verbose'] = args.verbose
opts['mldif'] = args.mldif
@@ -1109,6 +1264,18 @@ def main():
if opts['mldif'] is not None and opts['rldif'] is not None:
print ("Performing offline report...")
+
+ # Validate LDIF files, must exist and not be empty
+ for ldif_dir in [opts['mldif'], opts['rldif']]:
+ if not os.path.exists(ldif_dir):
+ print ("LDIF file ({}) does not exist".format(ldif_dir))
+ exit(1)
+ if os.path.getsize(ldif_dir) == 0:
+ print ("LDIF file ({}) is empty".format(ldif_dir))
+ exit(1)
+ if opts['mldif'] == opts['rldif']:
+ print("The Master and Replica LDIF files must be different")
+ exit(1)
do_offline_report(opts, OUTPUT_FILE)
else:
print ("Performing online report...")
@@ -1118,5 +1285,6 @@ def main():
print('Finished writing report to "%s"' % (args.file))
OUTPUT_FILE.close()
+
if __name__ == '__main__':
main()
--
2.17.0

View file

@ -1,33 +0,0 @@
From 00ebe4e4298fb19d9b8fc78b16053fb0b92eea9f Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 25 May 2018 09:47:31 -0400
Subject: [PATCH] Ticket 49576 - Add support of ";deletedattribute" in
ds-replcheck
Description: Also need to check for ";deletedattribute" when processing LDIF file
https://pagure.io/389-ds-base/issue/49576
Reviewed by: tbordaz(Thanks!)
(cherry picked from commit 9e046a35a0f771e77c788cddee2cbddee6ae0571)
---
ldap/admin/src/scripts/ds-replcheck | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/admin/src/scripts/ds-replcheck b/ldap/admin/src/scripts/ds-replcheck
index b801ccaa8..661c9e0ce 100755
--- a/ldap/admin/src/scripts/ds-replcheck
+++ b/ldap/admin/src/scripts/ds-replcheck
@@ -197,7 +197,7 @@ def remove_attr_state_info(attr):
idx = attr.find(';')
if idx > 0:
state_attr = attr # preserve state info for diff report
- if ";deleted" in attr:
+ if ";deleted" in attr or ";deletedattribute" in attr:
# Ignore this attribute it was deleted
return None, state_attr
attr = attr[:idx]
--
2.17.0

View file

@ -1,529 +0,0 @@
From b6894f921a0635dba97a0745ce75917284e5e5ff Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Sun, 27 May 2018 10:48:55 -0400
Subject: [PATCH] Ticket 49726 - DS only accepts RSA and Fortezza cipher
families
Bug Description: Currently DS only accepts fortezza and RSA cipher families.
This prevents things like ECC certificates from being used.
Fix Description: Instead of hardcoding the cipher families, just grab the
current type and use it.
Also cleaned up code: removed unncessary "ifdefs", and switched
for loops to use size_t.
https://pagure.io/389-ds-base/issue/49726
Reviewed by: ?
(cherry picked from commit 27a16a068887e5b9fcab3b4507d58a18e6f1d1ec)
---
ldap/servers/slapd/ssl.c | 136 ++++++---------------------------------
1 file changed, 20 insertions(+), 116 deletions(-)
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index 36b09fd16..b8eba2da4 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -31,28 +31,11 @@
#include "fe.h"
#include "certdb.h"
-#if !defined(USE_OPENLDAP)
-#include "ldap_ssl.h"
-#endif
-
/* For IRIX... */
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
-#if NSS_VMAJOR * 100 + NSS_VMINOR >= 315
-/* TLS1.2 is defined in RFC5246. */
-#define NSS_TLS12 1
-#elif NSS_VMAJOR * 100 + NSS_VMINOR >= 314
-/* TLS1.1 is defined in RFC4346. */
-#define NSS_TLS11 1
-#else
-#define NSS_TLS10 1
-#endif
-
-#if NSS_VMAJOR * 100 + NSS_VMINOR >= 320
-#define HAVE_NSS_DHE 1
-#endif
/******************************************************************************
* Default SSL Version Rule
@@ -70,10 +53,9 @@
extern char *slapd_SSL3ciphers;
extern symbol_t supported_ciphers[];
-#if !defined(NSS_TLS10) /* NSS_TLS11 or newer */
static SSLVersionRange enabledNSSVersions;
static SSLVersionRange slapdNSSVersions;
-#endif
+
/* dongle_file_name is set in slapd_nss_init when we set the path for the
key, cert, and secmod files - the dongle file must be in the same directory
@@ -109,12 +91,10 @@ static char *configDN = "cn=encryption,cn=config";
#define CIPHER_SET_DEFAULTWEAKCIPHER 0x10 /* allowWeakCipher is not set in cn=encryption */
#define CIPHER_SET_ALLOWWEAKCIPHER 0x20 /* allowWeakCipher is on */
#define CIPHER_SET_DISALLOWWEAKCIPHER 0x40 /* allowWeakCipher is off */
-
-#ifdef HAVE_NSS_DHE
#define CIPHER_SET_DEFAULTWEAKDHPARAM 0x100 /* allowWeakDhParam is not set in cn=encryption */
#define CIPHER_SET_ALLOWWEAKDHPARAM 0x200 /* allowWeakDhParam is on */
#define CIPHER_SET_DISALLOWWEAKDHPARAM 0x400 /* allowWeakDhParam is off */
-#endif
+
#define CIPHER_SET_ISDEFAULT(flag) \
(((flag)&CIPHER_SET_DEFAULT) ? PR_TRUE : PR_FALSE)
@@ -145,10 +125,7 @@ static char *configDN = "cn=encryption,cn=config";
#define CIPHER_IS_WEAK 0x4
#define CIPHER_IS_DEPRECATED 0x8
-#ifdef HAVE_NSS_DHE
static int allowweakdhparam = CIPHER_SET_DEFAULTWEAKDHPARAM;
-#endif
-
static char **cipher_names = NULL;
static char **enabled_cipher_names = NULL;
@@ -225,12 +202,10 @@ static lookup_cipher _lookup_cipher[] = {
/*{"tls_dhe_dss_1024_des_sha", ""}, */
{"tls_dhe_dss_1024_rc4_sha", "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA"},
{"tls_dhe_dss_rc4_128_sha", "TLS_DHE_DSS_WITH_RC4_128_SHA"},
-#if defined(NSS_TLS12)
/* New in NSS 3.15 */
{"tls_rsa_aes_128_gcm_sha", "TLS_RSA_WITH_AES_128_GCM_SHA256"},
{"tls_dhe_rsa_aes_128_gcm_sha", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"},
{"tls_dhe_dss_aes_128_gcm_sha", NULL}, /* not available */
-#endif
{NULL, NULL}};
/* E.g., "SSL3", "TLS1.2", "Unknown SSL version: 0x0" */
@@ -317,7 +292,6 @@ getSupportedCiphers(void)
SSLCipherSuiteInfo info;
char *sep = "::";
int number_of_ciphers = SSL_NumImplementedCiphers;
- int i;
int idx = 0;
PRBool isFIPS = slapd_pk11_isFIPS();
@@ -325,7 +299,7 @@ getSupportedCiphers(void)
if ((cipher_names == NULL) && (_conf_ciphers)) {
cipher_names = (char **)slapi_ch_calloc((number_of_ciphers + 1), sizeof(char *));
- for (i = 0; _conf_ciphers[i].name != NULL; i++) {
+ for (size_t i = 0; _conf_ciphers[i].name != NULL; i++) {
SSL_GetCipherSuiteInfo((PRUint16)_conf_ciphers[i].num, &info, sizeof(info));
/* only support FIPS approved ciphers in FIPS mode */
if (!isFIPS || info.isFIPS) {
@@ -341,7 +315,6 @@ getSupportedCiphers(void)
return cipher_names;
}
-#ifdef HAVE_NSS_DHE
int
get_allow_weak_dh_param(Slapi_Entry *e)
{
@@ -365,7 +338,6 @@ get_allow_weak_dh_param(Slapi_Entry *e)
slapi_ch_free((void **)&val);
return allow;
}
-#endif
char **
@@ -374,7 +346,6 @@ getEnabledCiphers(void)
SSLCipherSuiteInfo info;
char *sep = "::";
int number_of_ciphers = 0;
- int x;
int idx = 0;
PRBool enabled;
@@ -383,14 +354,14 @@ getEnabledCiphers(void)
return NULL;
}
if ((enabled_cipher_names == NULL) && _conf_ciphers) {
- for (x = 0; _conf_ciphers[x].name; x++) {
+ for (size_t x = 0; _conf_ciphers[x].name; x++) {
SSL_CipherPrefGetDefault(_conf_ciphers[x].num, &enabled);
if (enabled) {
number_of_ciphers++;
}
}
enabled_cipher_names = (char **)slapi_ch_calloc((number_of_ciphers + 1), sizeof(char *));
- for (x = 0; _conf_ciphers[x].name; x++) {
+ for (size_t x = 0; _conf_ciphers[x].name; x++) {
SSL_CipherPrefGetDefault(_conf_ciphers[x].num, &enabled);
if (enabled) {
SSL_GetCipherSuiteInfo((PRUint16)_conf_ciphers[x].num, &info, sizeof(info));
@@ -472,9 +443,6 @@ getSSLVersionRange(char **min, char **max)
}
return -1;
}
-#if defined(NSS_TLS10)
- return -1; /* not supported */
-#else /* NSS_TLS11 or newer */
if (min) {
*min = slapi_getSSLVersion_str(slapdNSSVersions.min, NULL, 0);
}
@@ -482,10 +450,8 @@ getSSLVersionRange(char **min, char **max)
*max = slapi_getSSLVersion_str(slapdNSSVersions.max, NULL, 0);
}
return 0;
-#endif
}
-#if defined(USE_OPENLDAP)
void
getSSLVersionRangeOL(int *min, int *max)
{
@@ -499,10 +465,7 @@ getSSLVersionRangeOL(int *min, int *max)
if (!slapd_ssl_listener_is_initialized()) {
return;
}
-#if defined(NSS_TLS10)
- *max = LDAP_OPT_X_TLS_PROTOCOL_TLS1_0;
- return;
-#else /* NSS_TLS11 or newer */
+
if (min) {
switch (slapdNSSVersions.min) {
case SSL_LIBRARY_VERSION_3_0:
@@ -550,14 +513,11 @@ getSSLVersionRangeOL(int *min, int *max)
}
}
return;
-#endif
}
-#endif /* USE_OPENLDAP */
static void
_conf_init_ciphers(void)
{
- int x;
SECStatus rc;
SSLCipherSuiteInfo info;
const PRUint16 *implementedCiphers = SSL_GetImplementedCiphers();
@@ -568,7 +528,7 @@ _conf_init_ciphers(void)
}
_conf_ciphers = (cipherstruct *)slapi_ch_calloc(SSL_NumImplementedCiphers + 1, sizeof(cipherstruct));
- for (x = 0; implementedCiphers && (x < SSL_NumImplementedCiphers); x++) {
+ for (size_t x = 0; implementedCiphers && (x < SSL_NumImplementedCiphers); x++) {
rc = SSL_GetCipherSuiteInfo(implementedCiphers[x], &info, sizeof info);
if (SECFailure == rc) {
slapi_log_err(SLAPI_LOG_ERR, "Security Initialization",
@@ -598,7 +558,6 @@ _conf_init_ciphers(void)
static void
_conf_setallciphers(int flag, char ***suplist, char ***unsuplist)
{
- int x;
SECStatus rc;
PRBool setdefault = CIPHER_SET_ISDEFAULT(flag);
PRBool enabled = CIPHER_SET_ISALL(flag);
@@ -608,7 +567,7 @@ _conf_setallciphers(int flag, char ***suplist, char ***unsuplist)
_conf_init_ciphers();
- for (x = 0; implementedCiphers && (x < SSL_NumImplementedCiphers); x++) {
+ for (size_t x = 0; implementedCiphers && (x < SSL_NumImplementedCiphers); x++) {
if (_conf_ciphers[x].flags & CIPHER_IS_DEFAULT) {
/* certainly, not the first time. */
setme = PR_TRUE;
@@ -663,11 +622,10 @@ charray2str(char **ary, const char *delim)
void
_conf_dumpciphers(void)
{
- int x;
PRBool enabled;
/* {"SSL3","rc4", SSL_EN_RC4_128_WITH_MD5}, */
slapd_SSL_info("Configured NSS Ciphers");
- for (x = 0; _conf_ciphers[x].name; x++) {
+ for (size_t x = 0; _conf_ciphers[x].name; x++) {
SSL_CipherPrefGetDefault(_conf_ciphers[x].num, &enabled);
if (enabled) {
slapd_SSL_info("\t%s: enabled%s%s%s", _conf_ciphers[x].name,
@@ -687,7 +645,8 @@ char *
_conf_setciphers(char *setciphers, int flags)
{
char *t, err[MAGNUS_ERROR_LEN];
- int x, i, active;
+ int active;
+ size_t x = 0;
char *raw = setciphers;
char **suplist = NULL;
char **unsuplist = NULL;
@@ -772,7 +731,7 @@ _conf_setciphers(char *setciphers, int flags)
}
}
if (lookup) { /* lookup with old cipher name and get NSS cipherSuiteName */
- for (i = 0; _lookup_cipher[i].alias; i++) {
+ for (size_t i = 0; _lookup_cipher[i].alias; i++) {
if (!PL_strcasecmp(setciphers, _lookup_cipher[i].alias)) {
if (enabled && !_lookup_cipher[i].name[0]) {
slapd_SSL_warn("Cipher suite %s is not available in NSS %d.%d. Ignoring %s",
@@ -915,9 +874,8 @@ getChildren(char *dn)
slapi_pblock_get(new_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);
slapi_pblock_get(new_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &e);
if (e != NULL) {
- int i;
list = (char **)slapi_ch_malloc(sizeof(*list) * (nEntries + 1));
- for (i = 0; e[i] != NULL; i++) {
+ for (size_t i = 0; e[i] != NULL; i++) {
list[i] = slapi_ch_strdup(slapi_entry_get_dn(e[i]));
}
list[nEntries] = NULL;
@@ -935,8 +893,7 @@ static void
freeChildren(char **list)
{
if (list != NULL) {
- int i;
- for (i = 0; list[i] != NULL; i++) {
+ for (size_t i = 0; list[i] != NULL; i++) {
slapi_ch_free((void **)(&list[i]));
}
slapi_ch_free((void **)(&list));
@@ -1017,7 +974,6 @@ warn_if_no_key_file(const char *dir, int no_log)
return ret;
}
-#if !defined(NSS_TLS10) /* NSS_TLS11 or newer */
/*
* If non NULL buf and positive bufsize is given,
* the memory is used to store the version string.
@@ -1183,7 +1139,6 @@ restrict_SSLVersionRange(void)
}
}
}
-#endif
/*
* slapd_nss_init() is always called from main(), even if we do not
@@ -1206,7 +1161,6 @@ slapd_nss_init(int init_ssl __attribute__((unused)), int config_available __attr
int create_certdb = 0;
PRUint32 nssFlags = 0;
char *certdir;
-#if !defined(NSS_TLS10) /* NSS_TLS11 or newer */
char emin[VERSION_STR_LENGTH], emax[VERSION_STR_LENGTH];
/* Get the range of the supported SSL version */
SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledNSSVersions);
@@ -1216,7 +1170,6 @@ slapd_nss_init(int init_ssl __attribute__((unused)), int config_available __attr
slapi_log_err(SLAPI_LOG_CONFIG, "Security Initialization",
"slapd_nss_init - Supported range by NSS: min: %s, max: %s\n",
emin, emax);
-#endif
/* set in slapd_bootstrap_config,
thus certdir is available even if config_available is false */
@@ -1385,9 +1338,7 @@ slapd_ssl_init()
char *val = NULL;
PK11SlotInfo *slot;
Slapi_Entry *entry = NULL;
-#ifdef HAVE_NSS_DHE
SECStatus rv = SECFailure;
-#endif
/* Get general information */
@@ -1396,7 +1347,6 @@ slapd_ssl_init()
val = slapi_entry_attr_get_charptr(entry, "nssslSessionTimeout");
ciphers = slapi_entry_attr_get_charptr(entry, "nsssl3ciphers");
-#ifdef HAVE_NSS_DHE
allowweakdhparam = get_allow_weak_dh_param(entry);
if (allowweakdhparam & CIPHER_SET_ALLOWWEAKDHPARAM) {
slapd_SSL_warn("notice, generating new WEAK DH param");
@@ -1405,7 +1355,6 @@ slapd_ssl_init()
slapd_SSL_error("Warning, unable to generate weak dh parameters");
}
}
-#endif
/* We are currently using the value of sslSessionTimeout
for ssl3SessionTimeout, see SSL_ConfigServerSessionIDCache() */
@@ -1527,7 +1476,6 @@ slapd_ssl_init()
return 0;
}
-#if !defined(NSS_TLS10) /* NSS_TLS11 or newer */
/*
* val: sslVersionMin/Max value set in cn=encription,cn=config (INPUT)
* rval: Corresponding value to set SSLVersionRange (OUTPUT)
@@ -1541,7 +1489,7 @@ static int
set_NSS_version(char *val, PRUint16 *rval, int ismin)
{
char *vp, *endp;
- int vnum;
+ int64_t vnum;
char emin[VERSION_STR_LENGTH], emax[VERSION_STR_LENGTH];
if (NULL == rval) {
@@ -1662,7 +1610,6 @@ set_NSS_version(char *val, PRUint16 *rval, int ismin)
}
}
} else if (tlsv < 1.3) { /* TLS1.2 */
-#if defined(NSS_TLS12)
if (ismin) {
if (enabledNSSVersions.min > SSL_LIBRARY_VERSION_TLS_1_2) {
slapd_SSL_warn("The value of sslVersionMin "
@@ -1685,7 +1632,6 @@ set_NSS_version(char *val, PRUint16 *rval, int ismin)
(*rval) = SSL_LIBRARY_VERSION_TLS_1_2;
}
}
-#endif
} else { /* Specified TLS is newer than supported */
if (ismin) {
slapd_SSL_warn("The value of sslVersionMin "
@@ -1720,7 +1666,6 @@ set_NSS_version(char *val, PRUint16 *rval, int ismin)
#undef SSLLEN
#undef TLSSTR
#undef TLSLEN
-#endif
int
slapd_ssl_init2(PRFileDesc **fd, int startTLS)
@@ -1740,12 +1685,10 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
char *tmpDir;
Slapi_Entry *e = NULL;
PRBool fipsMode = PR_FALSE;
-#if !defined(NSS_TLS10) /* NSS_TLS11 or newer */
PRUint16 NSSVersionMin = enabledNSSVersions.min;
PRUint16 NSSVersionMax = enabledNSSVersions.max;
char mymin[VERSION_STR_LENGTH], mymax[VERSION_STR_LENGTH];
char newmax[VERSION_STR_LENGTH];
-#endif
char cipher_string[1024];
int allowweakcipher = CIPHER_SET_DEFAULTWEAKCIPHER;
int_fast16_t renegotiation = (int_fast16_t)SSL_RENEGOTIATE_REQUIRES_XTN;
@@ -1964,15 +1907,13 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
}
if (SECSuccess == rv) {
+ SSLKEAType certKEA;
-#ifdef HAVE_NSS_DHE
- /* Step If we want weak dh params, flag it on the socket now! */
-
+ /* If we want weak dh params, flag it on the socket now! */
rv = SSL_OptionSet(*fd, SSL_ENABLE_SERVER_DHE, PR_TRUE);
if (rv != SECSuccess) {
slapd_SSL_warn("Warning, unable to start DHE");
}
-
if (allowweakdhparam & CIPHER_SET_ALLOWWEAKDHPARAM) {
slapd_SSL_warn("notice, allowing weak parameters on socket.");
rv = SSL_EnableWeakDHEPrimeGroup(*fd, PR_TRUE);
@@ -1980,13 +1921,9 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
slapd_SSL_warn("Warning, unable to allow weak DH params on socket.");
}
}
-#endif
- if (slapd_pk11_fortezzaHasKEA(cert) == PR_TRUE) {
- rv = SSL_ConfigSecureServer(*fd, cert, key, kt_fortezza);
- } else {
- rv = SSL_ConfigSecureServer(*fd, cert, key, kt_rsa);
- }
+ certKEA = NSS_FindCertKEAType(cert);
+ rv = SSL_ConfigSecureServer(*fd, cert, key, certKEA);
if (SECSuccess != rv) {
errorCode = PR_GetError();
slapd_SSL_warn("ConfigSecureServer: "
@@ -2140,7 +2077,6 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
enableTLS1 = PR_TRUE; /* If available, enable TLS1 */
}
slapi_ch_free_string(&val);
-#if !defined(NSS_TLS10) /* NSS_TLS11 or newer */
val = slapi_entry_attr_get_charptr(e, "sslVersionMin");
if (val) {
(void)set_NSS_version(val, &NSSVersionMin, 1);
@@ -2161,9 +2097,8 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
mymax, newmax);
NSSVersionMax = enabledNSSVersions.max;
}
-#endif
}
-#if !defined(NSS_TLS10) /* NSS_TLS11 or newer */
+
if (NSSVersionMin > 0) {
/* Use new NSS API SSL_VersionRangeSet (NSS3.14 or newer) */
slapdNSSVersions.min = NSSVersionMin;
@@ -2183,7 +2118,6 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
mymin, mymax);
}
} else {
-#endif
/* deprecated code */
sslStatus = SSL_OptionSet(pr_sock, SSL_ENABLE_SSL3, enableSSL3);
if (sslStatus != SECSuccess) {
@@ -2202,9 +2136,7 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS)
enableTLS1 ? "enable" : "disable",
errorCode, slapd_pr_strerror(errorCode));
}
-#if !defined(NSS_TLS10) /* NSS_TLS11 or newer */
}
-#endif
val = NULL;
if (e != NULL) {
@@ -2382,12 +2314,8 @@ slapd_SSL_client_auth(LDAP *ld)
*/
token = slapi_ch_strdup(internalTokenName);
}
-#if defined(USE_OPENLDAP)
/* openldap needs tokenname:certnick */
PR_snprintf(cert_name, sizeof(cert_name), "%s:%s", token, personality);
-#else
- PL_strncpyz(cert_name, personality, sizeof(cert_name));
-#endif
slapi_ch_free_string(&ssltoken);
} else {
/* external PKCS #11 token - attach token name */
@@ -2461,7 +2389,6 @@ slapd_SSL_client_auth(LDAP *ld)
"(no password). (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
errorCode, slapd_pr_strerror(errorCode));
} else {
-#if defined(USE_OPENLDAP)
if (slapi_client_uses_non_nss(ld) && config_get_extract_pem()) {
char *certdir = config_get_certdir();
char *keyfile = NULL;
@@ -2532,29 +2459,6 @@ slapd_SSL_client_auth(LDAP *ld)
cert_name);
}
}
-/*
- * not sure what else needs to be done for client auth - don't
- * currently have a way to pass in the password to use to unlock
- * the keydb - nor a way to disable caching
- */
-#else /* !USE_OPENLDAP */
- rc = ldapssl_enable_clientauth(ld, SERVER_KEY_NAME, pw, cert_name);
- if (rc != 0) {
- errorCode = PR_GetError();
- slapd_SSL_error("ldapssl_enable_clientauth(%s, %s) %i (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
- SERVER_KEY_NAME, cert_name, rc,
- errorCode, slapd_pr_strerror(errorCode));
- } else {
- /*
- * We cannot allow NSS to cache outgoing client auth connections -
- * each client auth connection must have it's own non-shared SSL
- * connection to the peer so that it will go through the
- * entire handshake protocol every time including the use of its
- * own unique client cert - see bug 605457
- */
- ldapssl_set_option(ld, SSL_NO_CACHE, PR_TRUE);
- }
-#endif
}
}
--
2.17.0

View file

@ -1,190 +0,0 @@
From 240cfa58c62571b92640a385cfcce6d858cb00dc Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Wed, 30 May 2018 15:48:11 +0200
Subject: [PATCH] Ticket 48184 - clean up and delete connections at shutdown
(3rd)
Bug description:
During shutdown we would not close connections.
In the past this may have just been an annoyance, but now with the way
nunc-stans works, io events can still trigger on open xeisting connectinos
during shutdown.
Fix Description:
Because of NS dynamic it can happen that several jobs wants to work on the
same connection. In such case (a job is already set in c_job) we delay the
new job that will retry.
In addition:
- some call needed c_mutex
- test uninitialized nunc-stans in case of shutdown while startup is not completed
If it is not possible to schedule immediately a job it is sometime useless to wait:
- if the connection is already freed, just cancel the scheduled job
and do not register a new one
- If we are in middle of a shutdown we do not know if the
scheduled job is ns_handle_closure, so cancel the scheduled
job and schedule ns_handle_closure.
https://pagure.io/389-ds-base/issue/48184
Reviewed by:
Original fix reviewed by Ludwig and Viktor
Second fix reviewed by Mark
Third fix reviewed by Mark
Platforms tested: F26
Flag Day: no
Doc impact: no
---
ldap/servers/slapd/connection.c | 10 +++--
ldap/servers/slapd/conntable.c | 2 +-
ldap/servers/slapd/daemon.c | 67 +++++++++++++++++++++++++--------
ldap/servers/slapd/proto-slap.h | 2 +-
4 files changed, 60 insertions(+), 21 deletions(-)
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 76e83112b..c54e7c26c 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -741,14 +741,18 @@ connection_acquire_nolock(Connection *conn)
/* returns non-0 if connection can be reused and 0 otherwise */
int
-connection_is_free(Connection *conn)
+connection_is_free(Connection *conn, int use_lock)
{
int rc;
- PR_EnterMonitor(conn->c_mutex);
+ if (use_lock) {
+ PR_EnterMonitor(conn->c_mutex);
+ }
rc = conn->c_sd == SLAPD_INVALID_SOCKET && conn->c_refcnt == 0 &&
!(conn->c_flags & CONN_FLAG_CLOSING);
- PR_ExitMonitor(conn->c_mutex);
+ if (use_lock) {
+ PR_ExitMonitor(conn->c_mutex);
+ }
return rc;
}
diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c
index f2f763dfa..114871d17 100644
--- a/ldap/servers/slapd/conntable.c
+++ b/ldap/servers/slapd/conntable.c
@@ -129,7 +129,7 @@ connection_table_get_connection(Connection_Table *ct, int sd)
break;
}
- if (connection_is_free(&(ct->c[index]))) {
+ if (connection_is_free(&(ct->c[index]), 1 /*use lock */)) {
break;
}
}
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 50e67474e..35cfe7de0 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1699,7 +1699,8 @@ ns_connection_post_io_or_closing_try(Connection *conn)
}
/*
- * Cancel any existing ns jobs we have registered.
+ * A job was already scheduled.
+ * Let it be dispatched first
*/
if (conn->c_job != NULL) {
return 1;
@@ -1780,25 +1781,59 @@ ns_connection_post_io_or_closing_try(Connection *conn)
}
return 0;
}
+
+/*
+ * Tries to schedule I/O for this connection
+ * If the connection is already busy with a scheduled I/O
+ * it can wait until scheduled I/O is dispatched
+ *
+ * caller must hold c_mutex
+ */
void
ns_connection_post_io_or_closing(Connection *conn)
{
while (ns_connection_post_io_or_closing_try(conn)) {
- /* we should retry later */
-
- /* We are not suppose to work immediately on the connection that is taken by
- * another job
- * release the lock and give some time
- */
-
- if (CONN_NEEDS_CLOSING(conn) && conn->c_ns_close_jobs) {
- return;
- } else {
- PR_ExitMonitor(conn->c_mutex);
- DS_Sleep(PR_MillisecondsToInterval(100));
-
- PR_EnterMonitor(conn->c_mutex);
- }
+ /* Here a job is currently scheduled (c->job is set) and not yet dispatched
+ * Job can be either:
+ * - ns_handle_closure
+ * - ns_handle_pr_read_ready
+ */
+
+ if (connection_is_free(conn, 0)) {
+ PRStatus shutdown_status;
+
+ /* The connection being freed,
+ * It means that ns_handle_closure already completed and the connection
+ * is no longer on the active list.
+ * The scheduled job is useless and scheduling a new one as well
+ */
+ shutdown_status = ns_job_done(conn->c_job);
+ if (shutdown_status != PR_SUCCESS) {
+ slapi_log_err(SLAPI_LOG_CRIT, "ns_connection_post_io_or_closing", "Failed cancel a job on a freed connection %d !\n", conn->c_sd);
+ }
+ conn->c_job = NULL;
+ return;
+ }
+ if (g_get_shutdown() && CONN_NEEDS_CLOSING(conn)) {
+ PRStatus shutdown_status;
+
+ /* This is shutting down cancel any scheduled job to register ns_handle_closure
+ */
+ shutdown_status = ns_job_done(conn->c_job);
+ if (shutdown_status != PR_SUCCESS) {
+ slapi_log_err(SLAPI_LOG_CRIT, "ns_connection_post_io_or_closing", "Failed to cancel a job during shutdown %d !\n", conn->c_sd);
+ }
+ conn->c_job = NULL;
+ continue;
+ }
+
+ /* We are not suppose to work immediately on the connection that is taken by
+ * another job
+ * release the lock and give some time
+ */
+ PR_ExitMonitor(conn->c_mutex);
+ DS_Sleep(PR_MillisecondsToInterval(100));
+ PR_EnterMonitor(conn->c_mutex);
}
}
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index b13334ad1..f54bc6bc5 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -1431,7 +1431,7 @@ int connection_acquire_nolock(Connection *conn);
int connection_acquire_nolock_ext(Connection *conn, int allow_when_closing);
int connection_release_nolock(Connection *conn);
int connection_release_nolock_ext(Connection *conn, int release_only);
-int connection_is_free(Connection *conn);
+int connection_is_free(Connection *conn, int user_lock);
int connection_is_active_nolock(Connection *conn);
#if defined(USE_OPENLDAP)
ber_slen_t openldap_read_function(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len);
--
2.17.0

Some files were not shown because too many files have changed in this diff Show more