import 389-ds-base-1.3.6.1-19.el7_4

This commit is contained in:
CentOS Sources 2017-09-05 03:18:30 -04:00
parent 74ca47f593
commit 1c155e2849
7 changed files with 1794 additions and 43 deletions

View file

@ -0,0 +1,47 @@
From 0fc3c803c34311eb05c5c7a7e710c8591b592649 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Thu, 27 Jul 2017 18:10:05 +0200
Subject: [PATCH] Ticket 49313 - Change the retrochangelog default cache size
Bug Description:
Default retroCL backend entry cache size is 2Mb.
It has been reported in many deployments that DB corruption could
be prevented by increasing entry cache to 200Mb.
There is no identified reproducible steps to debug this DB corruption.
So to prevent this problem we are increasing the entry cache
Fix Description:
Set default cn=changelog cache to 200Mb (based on production cases)
An other option would be to set a maximum number of entries but
as we do not know if it works to prevent DB corruption, let's prefere
entry cache size
https://pagure.io/389-ds-base/issue/49313
Reviewed by: William Brown
Platforms tested: F23
Flag Day: no
Doc impact: no
---
ldap/servers/plugins/retrocl/retrocl.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ldap/servers/plugins/retrocl/retrocl.h b/ldap/servers/plugins/retrocl/retrocl.h
index 6963d4b..eef1a17 100644
--- a/ldap/servers/plugins/retrocl/retrocl.h
+++ b/ldap/servers/plugins/retrocl/retrocl.h
@@ -58,7 +58,7 @@ typedef struct _cnumRet {
#else
#define RETROCL_DLL_DEFAULT_THREAD_STACKSIZE 131072L
#endif
-#define RETROCL_BE_CACHEMEMSIZE "2097152"
+#define RETROCL_BE_CACHEMEMSIZE "209715200"
#define RETROCL_BE_CACHESIZE "-1"
#define RETROCL_PLUGIN_NAME "DSRetroclPlugin"
--
2.9.4

View file

@ -0,0 +1,795 @@
From 6b5aa0e288f1ea5553d4dd5d220d4e5daf50a247 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 31 Jul 2017 14:45:50 -0400
Subject: [PATCH] Ticket 49287 - v3 extend csnpl handling to multiple backends
The csn pending list mechanism failed if internal operation affected multiple backends
This fix is an extension to the fix in ticket 49008, the thread local data now also contains
a list of all affected replicas.
http://www.port389.org/docs/389ds/design/csn-pending-lists-and-ruv-update.html
Reviewed by: William, Thierry - thanks
---
ldap/servers/plugins/replication/csnpl.c | 85 ++++++++--
ldap/servers/plugins/replication/csnpl.h | 8 +-
ldap/servers/plugins/replication/repl5.h | 22 ++-
ldap/servers/plugins/replication/repl5_init.c | 48 +++++-
ldap/servers/plugins/replication/repl5_plugins.c | 16 +-
ldap/servers/plugins/replication/repl5_replica.c | 18 ++-
ldap/servers/plugins/replication/repl5_ruv.c | 191 ++++++++++++++---------
ldap/servers/plugins/replication/repl5_ruv.h | 6 +-
ldap/servers/slapd/slapi-private.h | 2 +-
9 files changed, 283 insertions(+), 113 deletions(-)
diff --git a/ldap/servers/plugins/replication/csnpl.c b/ldap/servers/plugins/replication/csnpl.c
index 4a0f5f5..12a0bb8 100644
--- a/ldap/servers/plugins/replication/csnpl.c
+++ b/ldap/servers/plugins/replication/csnpl.c
@@ -14,7 +14,6 @@
#include "csnpl.h"
#include "llist.h"
-#include "repl_shared.h"
struct csnpl
{
@@ -22,13 +21,17 @@ struct csnpl
Slapi_RWLock* csnLock; /* lock to serialize access to PL */
};
+
typedef struct _csnpldata
{
PRBool committed; /* True if CSN committed */
CSN *csn; /* The actual CSN */
+ Replica * prim_replica; /* The replica where the prom csn was generated */
const CSN *prim_csn; /* The primary CSN of an operation consising of multiple sub ops*/
} csnpldata;
+static PRBool csn_primary_or_nested(csnpldata *csn_data, const CSNPL_CTX *csn_ctx);
+
/* forward declarations */
#ifdef DEBUG
static void _csnplDumpContentNoLock(CSNPL *csnpl, const char *caller);
@@ -104,7 +107,7 @@ void csnplFree (CSNPL **csnpl)
* 1 if the csn has already been seen
* -1 for any other kind of errors
*/
-int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn)
+int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSNPL_CTX *prim_csn)
{
int rc;
csnpldata *csnplnode;
@@ -129,10 +132,13 @@ int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn)
return 1;
}
- csnplnode = (csnpldata *)slapi_ch_malloc(sizeof(csnpldata));
+ csnplnode = (csnpldata *)slapi_ch_calloc(1, sizeof(csnpldata));
csnplnode->committed = PR_FALSE;
csnplnode->csn = csn_dup(csn);
- csnplnode->prim_csn = prim_csn;
+ if (prim_csn) {
+ csnplnode->prim_csn = prim_csn->prim_csn;
+ csnplnode->prim_replica = prim_csn->prim_repl;
+ }
csn_as_string(csn, PR_FALSE, csn_str);
rc = llistInsertTail (csnpl->csnList, csn_str, csnplnode);
@@ -187,8 +193,58 @@ int csnplRemove (CSNPL *csnpl, const CSN *csn)
return 0;
}
+PRBool csn_primary(Replica *replica, const CSN *csn, const CSNPL_CTX *csn_ctx)
+{
+ if (csn_ctx == NULL)
+ return PR_FALSE;
+
+ if (replica != csn_ctx->prim_repl) {
+ /* The CSNs are not from the same replication topology
+ * so even if the csn values are equal they are not related
+ * to the same operation
+ */
+ return PR_FALSE;
+ }
+
+ /* Here the two CSNs belong to the same replication topology */
+
+ /* check if the CSN identifies the primary update */
+ if (csn_is_equal(csn, csn_ctx->prim_csn)) {
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+
+static PRBool csn_primary_or_nested(csnpldata *csn_data, const CSNPL_CTX *csn_ctx)
+{
+ if ((csn_data == NULL) || (csn_ctx == NULL))
+ return PR_FALSE;
+
+ if (csn_data->prim_replica != csn_ctx->prim_repl) {
+ /* The CSNs are not from the same replication topology
+ * so even if the csn values are equal they are not related
+ * to the same operation
+ */
+ return PR_FALSE;
+ }
+
+ /* Here the two CSNs belong to the same replication topology */
+
+ /* First check if the CSN identifies the primary update */
+ if (csn_is_equal(csn_data->csn, csn_ctx->prim_csn)) {
+ return PR_TRUE;
+ }
+
+ /* Second check if the CSN identifies a nested update */
+ if (csn_is_equal(csn_data->prim_csn, csn_ctx->prim_csn)) {
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
-int csnplRemoveAll (CSNPL *csnpl, const CSN *csn)
+int csnplRemoveAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx)
{
csnpldata *data;
void *iterator;
@@ -197,8 +253,7 @@ int csnplRemoveAll (CSNPL *csnpl, const CSN *csn)
data = (csnpldata *)llistGetFirst(csnpl->csnList, &iterator);
while (NULL != data)
{
- if (csn_is_equal(data->csn, csn) ||
- csn_is_equal(data->prim_csn, csn)) {
+ if (csn_primary_or_nested(data, csn_ctx)) {
csnpldata_free(&data);
data = (csnpldata *)llistRemoveCurrentAndGetNext(csnpl->csnList, &iterator);
} else {
@@ -213,13 +268,13 @@ int csnplRemoveAll (CSNPL *csnpl, const CSN *csn)
}
-int csnplCommitAll (CSNPL *csnpl, const CSN *csn)
+int csnplCommitAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx)
{
csnpldata *data;
void *iterator;
char csn_str[CSN_STRSIZE];
- csn_as_string(csn, PR_FALSE, csn_str);
+ csn_as_string(csn_ctx->prim_csn, PR_FALSE, csn_str);
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
"csnplCommitALL: committing all csns for csn %s\n", csn_str);
slapi_rwlock_wrlock (csnpl->csnLock);
@@ -229,8 +284,7 @@ int csnplCommitAll (CSNPL *csnpl, const CSN *csn)
csn_as_string(data->csn, PR_FALSE, csn_str);
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
"csnplCommitALL: processing data csn %s\n", csn_str);
- if (csn_is_equal(data->csn, csn) ||
- csn_is_equal(data->prim_csn, csn)) {
+ if (csn_primary_or_nested(data, csn_ctx)) {
data->committed = PR_TRUE;
}
data = (csnpldata *)llistGetNext (csnpl->csnList, &iterator);
@@ -395,7 +449,12 @@ static void _csnplDumpContentNoLock(CSNPL *csnpl, const char *caller)
/* wrapper around csn_free, to satisfy NSPR thread context API */
void
-csnplFreeCSN (void *arg)
+csnplFreeCSNPL_CTX (void *arg)
{
- csn_free((CSN **)&arg);
+ CSNPL_CTX *csnpl_ctx = (CSNPL_CTX *)arg;
+ csn_free(&csnpl_ctx->prim_csn);
+ if (csnpl_ctx->sec_repl) {
+ slapi_ch_free((void **)&csnpl_ctx->sec_repl);
+ }
+ slapi_ch_free((void **)&csnpl_ctx);
}
diff --git a/ldap/servers/plugins/replication/csnpl.h b/ldap/servers/plugins/replication/csnpl.h
index 594c8f2..1036c62 100644
--- a/ldap/servers/plugins/replication/csnpl.h
+++ b/ldap/servers/plugins/replication/csnpl.h
@@ -17,15 +17,17 @@
#define CSNPL_H
#include "slapi-private.h"
+#include "repl5.h"
typedef struct csnpl CSNPL;
CSNPL* csnplNew(void);
void csnplFree (CSNPL **csnpl);
-int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn);
+int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSNPL_CTX *prim_csn);
int csnplRemove (CSNPL *csnpl, const CSN *csn);
-int csnplRemoveAll (CSNPL *csnpl, const CSN *csn);
-int csnplCommitAll (CSNPL *csnpl, const CSN *csn);
+int csnplRemoveAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx);
+int csnplCommitAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx);
+PRBool csn_primary(Replica *replica, const CSN *csn, const CSNPL_CTX *csn_ctx);
CSN* csnplGetMinCSN (CSNPL *csnpl, PRBool *committed);
int csnplCommit (CSNPL *csnpl, const CSN *csn);
CSN *csnplRollUp(CSNPL *csnpl, CSN ** first);
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 1d8989c..718f64e 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -228,12 +228,27 @@ int multimaster_be_betxnpostop_delete (Slapi_PBlock *pb);
int multimaster_be_betxnpostop_add (Slapi_PBlock *pb);
int multimaster_be_betxnpostop_modify (Slapi_PBlock *pb);
+/* In repl5_replica.c */
+typedef struct replica Replica;
+
+/* csn pending lists */
+#define CSNPL_CTX_REPLCNT 4
+typedef struct CSNPL_CTX
+{
+ CSN *prim_csn;
+ size_t repl_alloc; /* max number of replicas */
+ size_t repl_cnt; /* number of replicas affected by operation */
+ Replica *prim_repl; /* pirmary replica */
+ Replica **sec_repl; /* additional replicas affected */
+} CSNPL_CTX;
+
/* In repl5_init.c */
extern int repl5_is_betxn;
char* get_thread_private_agmtname(void);
void set_thread_private_agmtname (const char *agmtname);
-void set_thread_primary_csn (const CSN *prim_csn);
-CSN* get_thread_primary_csn(void);
+void set_thread_primary_csn (const CSN *prim_csn, Replica *repl);
+void add_replica_to_primcsn(CSNPL_CTX *prim_csn, Replica *repl);
+CSNPL_CTX* get_thread_primary_csn(void);
void* get_thread_private_cache(void);
void set_thread_private_cache (void *buf);
char* get_repl_session_id (Slapi_PBlock *pb, char *id, CSN **opcsn);
@@ -302,7 +317,6 @@ typedef struct repl_bos Repl_Bos;
/* In repl5_agmt.c */
typedef struct repl5agmt Repl_Agmt;
-typedef struct replica Replica;
#define TRANSPORT_FLAG_SSL 1
#define TRANSPORT_FLAG_TLS 2
@@ -629,6 +643,8 @@ PRUint64 replica_get_precise_purging(Replica *r);
void replica_set_precise_purging(Replica *r, PRUint64 on_off);
PRBool ignore_error_and_keep_going(int error);
void replica_check_release_timeout(Replica *r, Slapi_PBlock *pb);
+void replica_lock_replica(Replica *r);
+void replica_unlock_replica(Replica *r);
/* The functions below handles the state flag */
/* Current internal state flags */
diff --git a/ldap/servers/plugins/replication/repl5_init.c b/ldap/servers/plugins/replication/repl5_init.c
index edffb84..b0bc515 100644
--- a/ldap/servers/plugins/replication/repl5_init.c
+++ b/ldap/servers/plugins/replication/repl5_init.c
@@ -154,26 +154,62 @@ set_thread_private_agmtname(const char *agmtname)
PR_SetThreadPrivate(thread_private_agmtname, (void *)agmtname);
}
-CSN*
+CSNPL_CTX*
get_thread_primary_csn(void)
{
- CSN *prim_csn = NULL;
+ CSNPL_CTX *prim_csn = NULL;
if (thread_primary_csn)
- prim_csn = (CSN *)PR_GetThreadPrivate(thread_primary_csn);
+ prim_csn = (CSNPL_CTX *)PR_GetThreadPrivate(thread_primary_csn);
+
return prim_csn;
}
void
-set_thread_primary_csn(const CSN *prim_csn)
+set_thread_primary_csn (const CSN *prim_csn, Replica *repl)
{
if (thread_primary_csn) {
if (prim_csn) {
- PR_SetThreadPrivate(thread_primary_csn, (void *)csn_dup(prim_csn));
+ CSNPL_CTX *csnpl_ctx = (CSNPL_CTX *)slapi_ch_calloc(1,sizeof(CSNPL_CTX));
+ csnpl_ctx->prim_csn = csn_dup(prim_csn);
+ /* repl_alloc, repl_cnt and sec_repl are 0 by calloc */
+ csnpl_ctx->prim_repl = repl;
+ PR_SetThreadPrivate(thread_primary_csn, (void *)csnpl_ctx);
} else {
PR_SetThreadPrivate(thread_primary_csn, NULL);
}
}
}
+void
+add_replica_to_primcsn(CSNPL_CTX *csnpl_ctx, Replica *repl)
+{
+ size_t found = 0;
+ size_t it = 0;
+
+ if (repl == csnpl_ctx->prim_repl) return;
+
+ while (it < csnpl_ctx->repl_cnt) {
+ if (csnpl_ctx->sec_repl[it] == repl) {
+ found = 1;
+ break;
+ }
+ it++;
+ }
+ if (found) return;
+
+ if (csnpl_ctx->repl_cnt < csnpl_ctx->repl_alloc) {
+ csnpl_ctx->sec_repl[csnpl_ctx->repl_cnt++] = repl;
+ return;
+ }
+ csnpl_ctx->repl_alloc += CSNPL_CTX_REPLCNT;
+ if (csnpl_ctx->repl_cnt == 0) {
+ csnpl_ctx->sec_repl = (Replica **)slapi_ch_calloc(csnpl_ctx->repl_alloc, sizeof(Replica *));
+ } else {
+ csnpl_ctx->sec_repl = (Replica **)slapi_ch_realloc((char *)csnpl_ctx->sec_repl, csnpl_ctx->repl_alloc * sizeof(Replica *));
+ }
+ csnpl_ctx->sec_repl[csnpl_ctx->repl_cnt++] = repl;
+ return;
+}
+
void*
get_thread_private_cache ()
{
@@ -740,7 +776,7 @@ multimaster_start( Slapi_PBlock *pb )
/* Initialize thread private data for logging. Ignore if fails */
PR_NewThreadPrivateIndex (&thread_private_agmtname, NULL);
PR_NewThreadPrivateIndex (&thread_private_cache, NULL);
- PR_NewThreadPrivateIndex (&thread_primary_csn, csnplFreeCSN);
+ PR_NewThreadPrivateIndex (&thread_primary_csn, csnplFreeCSNPL_CTX);
/* Decode the command line args to see if we're dumping to LDIF */
is_ldif_dump = check_for_ldif_dump(pb);
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index 9ef06af..c31d9d5 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -45,6 +45,7 @@
#include "repl.h"
#include "cl5_api.h"
#include "urp.h"
+#include "csnpl.h"
static char *local_purl = NULL;
static char *purl_attrs[] = {"nsslapd-localhost", "nsslapd-port", "nsslapd-secureport", NULL};
@@ -1034,7 +1035,7 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
{
Slapi_Operation *op = NULL;
CSN *opcsn;
- CSN *prim_csn;
+ CSNPL_CTX *prim_csn;
int rc;
slapi_operation_parameters *op_params = NULL;
Object *repl_obj = NULL;
@@ -1070,14 +1071,15 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
if (repl_obj == NULL)
return return_value;
+ r = (Replica*)object_get_data (repl_obj);
+ PR_ASSERT (r);
+
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
if (rc) { /* op failed - just return */
cancel_opcsn(pb);
goto common_return;
}
- r = (Replica*)object_get_data (repl_obj);
- PR_ASSERT (r);
replica_check_release_timeout(r, pb);
@@ -1223,12 +1225,12 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
common_return:
opcsn = operation_get_csn(op);
prim_csn = get_thread_primary_csn();
- if (csn_is_equal(opcsn, prim_csn)) {
+ if (csn_primary(r, opcsn, prim_csn)) {
if (return_value == 0) {
/* the primary csn was succesfully committed
* unset it in the thread local data
*/
- set_thread_primary_csn(NULL);
+ set_thread_primary_csn(NULL, NULL);
}
}
if (repl_obj) {
@@ -1430,7 +1432,7 @@ cancel_opcsn (Slapi_PBlock *pb)
ruv_obj = replica_get_ruv (r);
PR_ASSERT (ruv_obj);
- ruv_cancel_csn_inprogress ((RUV*)object_get_data (ruv_obj), opcsn, replica_get_rid(r));
+ ruv_cancel_csn_inprogress (r, (RUV*)object_get_data (ruv_obj), opcsn, replica_get_rid(r));
object_release (ruv_obj);
}
@@ -1491,7 +1493,7 @@ process_operation (Slapi_PBlock *pb, const CSN *csn)
ruv = (RUV*)object_get_data (ruv_obj);
PR_ASSERT (ruv);
- rc = ruv_add_csn_inprogress (ruv, csn);
+ rc = ruv_add_csn_inprogress (r, ruv, csn);
object_release (ruv_obj);
object_release (r_obj);
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 1bdc138..7927ac3 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -923,7 +923,7 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
}
}
/* Update max csn for local and remote replicas */
- rc = ruv_update_ruv (ruv, updated_csn, replica_purl, r->repl_rid);
+ rc = ruv_update_ruv (ruv, updated_csn, replica_purl, r, r->repl_rid);
if (RUV_COVERS_CSN == rc)
{
slapi_log_err(SLAPI_LOG_REPL,
@@ -3663,7 +3663,7 @@ assign_csn_callback(const CSN *csn, void *data)
}
}
- ruv_add_csn_inprogress (ruv, csn);
+ ruv_add_csn_inprogress (r, ruv, csn);
replica_unlock(r->repl_lock);
@@ -3692,13 +3692,13 @@ abort_csn_callback(const CSN *csn, void *data)
{
int rc = csnplRemove(r->min_csn_pl, csn);
if (rc) {
- slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "abort_csn_callback - csnplRemove failed");
+ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "abort_csn_callback - csnplRemove failed\n");
replica_unlock(r->repl_lock);
return;
}
}
- ruv_cancel_csn_inprogress (ruv, csn, replica_get_rid(r));
+ ruv_cancel_csn_inprogress (r, ruv, csn, replica_get_rid(r));
replica_unlock(r->repl_lock);
object_release (ruv_obj);
@@ -4489,3 +4489,13 @@ replica_check_release_timeout(Replica *r, Slapi_PBlock *pb)
}
replica_unlock(r->repl_lock);
}
+void
+replica_lock_replica(Replica *r)
+{
+ replica_lock(r->repl_lock);
+}
+void
+replica_unlock_replica(Replica *r)
+{
+ replica_unlock(r->repl_lock);
+}
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
index d59e6d2..39449b6 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -77,7 +77,7 @@ static char *get_replgen_from_berval(const struct berval *bval);
static const char * const prefix_replicageneration = "{replicageneration}";
static const char * const prefix_ruvcsn = "{replica "; /* intentionally missing '}' */
-static int ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSN *csn, const char *replica_purl, PRBool isLocal);
+static int ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSNPL_CTX *prim_csn, const char *replica_purl, PRBool isLocal);
/* API implementation */
@@ -1599,13 +1599,13 @@ ruv_dump(const RUV *ruv, char *ruv_name, PRFileDesc *prFile)
/* this function notifies the ruv that there are operations in progress so that
they can be added to the pending list for the appropriate client. */
-int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
+int ruv_add_csn_inprogress (void *repl, RUV *ruv, const CSN *csn)
{
RUVElement* replica;
char csn_str[CSN_STRSIZE];
int rc = RUV_SUCCESS;
int rid = csn_get_replicaid (csn);
- CSN *prim_csn;
+ CSNPL_CTX *prim_csn;
PR_ASSERT (ruv && csn);
@@ -1645,8 +1645,13 @@ int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
}
prim_csn = get_thread_primary_csn();
if (prim_csn == NULL) {
- set_thread_primary_csn(csn);
+ set_thread_primary_csn(csn, (Replica *)repl);
prim_csn = get_thread_primary_csn();
+ } else {
+ /* the prim csn data already exist, need to check if
+ * current replica is already present
+ */
+ add_replica_to_primcsn(prim_csn, (Replica *)repl);
}
rc = csnplInsert (replica->csnpl, csn, prim_csn);
if (rc == 1) /* we already seen this csn */
@@ -1656,7 +1661,7 @@ int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
"The csn %s has already be seen - ignoring\n",
csn_as_string (csn, PR_FALSE, csn_str));
}
- set_thread_primary_csn(NULL);
+ set_thread_primary_csn(NULL, NULL);
rc = RUV_COVERS_CSN;
}
else if(rc != 0)
@@ -1681,11 +1686,13 @@ done:
return rc;
}
-int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId local_rid)
+int ruv_cancel_csn_inprogress (void *repl, RUV *ruv, const CSN *csn, ReplicaId local_rid)
{
- RUVElement* replica;
+ RUVElement* repl_ruv;
int rc = RUV_SUCCESS;
- CSN *prim_csn = NULL;
+ CSNPL_CTX *prim_csn = NULL;
+ Replica *repl_it;
+ size_t it;
PR_ASSERT (ruv && csn);
@@ -1693,29 +1700,53 @@ int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId local_rid)
prim_csn = get_thread_primary_csn();
/* locate ruvElement */
slapi_rwlock_wrlock (ruv->lock);
- replica = ruvGetReplica (ruv, csn_get_replicaid (csn));
- if (replica == NULL) {
+ repl_ruv = ruvGetReplica (ruv, csn_get_replicaid (csn));
+ if (repl_ruv == NULL) {
/* ONREPL - log error */
rc = RUV_NOTFOUND;
goto done;
}
- if (csn_is_equal(csn, prim_csn)) {
- /* the prim csn is cancelled, lets remove all dependent csns */
- ReplicaId prim_rid = csn_get_replicaid (csn);
- replica = ruvGetReplica (ruv, prim_rid);
- rc = csnplRemoveAll (replica->csnpl, prim_csn);
- if (prim_rid != local_rid) {
- if( local_rid != READ_ONLY_REPLICA_ID) {
- replica = ruvGetReplica (ruv, local_rid);
- if (replica) {
- rc = csnplRemoveAll (replica->csnpl, prim_csn);
- } else {
- rc = RUV_NOTFOUND;
- }
- }
- }
+ if (csn_primary(repl, csn, prim_csn)) {
+ /* the prim csn is cancelled, lets remove all dependent csns */
+ /* for the primary replica we can have modifications for two RIDS:
+ * - the local RID for direct or internal operations
+ * - a remote RID if the primary csn is for a replciated op.
+ */
+ ReplicaId prim_rid = csn_get_replicaid(csn);
+ repl_ruv = ruvGetReplica(ruv, prim_rid);
+ if (!repl_ruv) {
+ rc = RUV_NOTFOUND;
+ goto done;
+ }
+ rc = csnplRemoveAll(repl_ruv->csnpl, prim_csn);
+
+ if (prim_rid != local_rid && local_rid != READ_ONLY_REPLICA_ID) {
+ repl_ruv = ruvGetReplica(ruv, local_rid);
+ if (!repl_ruv) {
+ rc = RUV_NOTFOUND;
+ goto done;
+ }
+ rc = csnplRemoveAll(repl_ruv->csnpl, prim_csn);
+ }
+
+ for (it = 0; it < prim_csn->repl_cnt; it++) {
+ repl_it = prim_csn->sec_repl[it];
+ replica_lock_replica(repl_it);
+ local_rid = replica_get_rid(repl_it);
+ if (local_rid != READ_ONLY_REPLICA_ID) {
+ Object *ruv_obj = replica_get_ruv(repl_it);
+ RUV *ruv_it = object_get_data(ruv_obj);
+ repl_ruv = ruvGetReplica(ruv_it, local_rid);
+ if (repl_ruv) {
+ rc = csnplRemoveAll(repl_ruv->csnpl, prim_csn);
+ } else {
+ rc = RUV_NOTFOUND;
+ }
+ }
+ replica_unlock_replica(repl_it);
+ }
} else {
- rc = csnplRemove (replica->csnpl, csn);
+ rc = csnplRemove (repl_ruv->csnpl, csn);
}
if (rc != 0)
rc = RUV_NOTFOUND;
@@ -1727,86 +1758,100 @@ done:
return rc;
}
-int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, ReplicaId local_rid)
+int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, void *replica, ReplicaId local_rid)
{
int rc=RUV_SUCCESS;
- RUVElement *replica;
+ RUVElement *repl_ruv;
ReplicaId prim_rid;
+ Replica *repl_it = NULL;
+ size_t it = 0;
- CSN *prim_csn = get_thread_primary_csn();
+ CSNPL_CTX *prim_csn = get_thread_primary_csn();
- if (! csn_is_equal(csn, prim_csn)) {
+ if (! csn_primary(replica, csn, prim_csn)) {
/* not a primary csn, nothing to do */
return rc;
}
- slapi_rwlock_wrlock (ruv->lock);
+
+ /* first handle primary replica
+ * there can be two ruv elements affected
+ */
prim_rid = csn_get_replicaid (csn);
- replica = ruvGetReplica (ruv, local_rid);
- rc = ruv_update_ruv_element(ruv, replica, csn, replica_purl, PR_TRUE);
- if ( rc || local_rid == prim_rid) goto done;
- replica = ruvGetReplica (ruv, prim_rid);
- rc = ruv_update_ruv_element(ruv, replica, csn, replica_purl, PR_FALSE);
-done:
+ slapi_rwlock_wrlock (ruv->lock);
+ if ( local_rid != prim_rid) {
+ repl_ruv = ruvGetReplica (ruv, prim_rid);
+ rc = ruv_update_ruv_element(ruv, repl_ruv, prim_csn, replica_purl, PR_FALSE);
+ }
+ repl_ruv = ruvGetReplica (ruv, local_rid);
+ rc = ruv_update_ruv_element(ruv, repl_ruv, prim_csn, replica_purl, PR_TRUE);
slapi_rwlock_unlock (ruv->lock);
+ if (rc) return rc;
+
+ /* now handle secondary replicas */
+ for (it=0; it<prim_csn->repl_cnt; it++) {
+ repl_it = prim_csn->sec_repl[it];
+ replica_lock_replica(repl_it);
+ Object *ruv_obj = replica_get_ruv (repl_it);
+ RUV *ruv_it = object_get_data (ruv_obj);
+ slapi_rwlock_wrlock (ruv_it->lock);
+ repl_ruv = ruvGetReplica (ruv_it, replica_get_rid(repl_it));
+ rc = ruv_update_ruv_element(ruv_it, repl_ruv, prim_csn, replica_purl, PR_TRUE);
+ slapi_rwlock_unlock (ruv_it->lock);
+ replica_unlock_replica(repl_it);
+ if (rc) break;
+ }
return rc;
}
+
static int
-ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSN *csn, const char *replica_purl, PRBool isLocal)
+ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSNPL_CTX *prim_csn, const char *replica_purl, PRBool isLocal)
{
int rc=RUV_SUCCESS;
char csn_str[CSN_STRSIZE];
CSN *max_csn;
CSN *first_csn = NULL;
- if (replica == NULL)
- {
+ if (replica == NULL) {
/* we should have a ruv element at this point because it would have
been added by ruv_add_inprogress function */
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - "
- "Can't locate RUV element for replica %d\n", csn_get_replicaid (csn));
+ "Can't locate RUV element for replica %d\n", csn_get_replicaid (prim_csn->prim_csn));
goto done;
}
- if (csnplCommitAll(replica->csnpl, csn) != 0)
- {
- slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "ruv_update_ruv - Cannot commit csn %s\n",
- csn_as_string(csn, PR_FALSE, csn_str));
+ if (csnplCommitAll(replica->csnpl, prim_csn) != 0) {
+ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "ruv_update_ruv - Cannot commit csn %s\n",
+ csn_as_string(prim_csn->prim_csn, PR_FALSE, csn_str));
rc = RUV_CSNPL_ERROR;
goto done;
- }
- else
- {
+ } else {
if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - "
- "Successfully committed csn %s\n", csn_as_string(csn, PR_FALSE, csn_str));
+ "Successfully committed csn %s\n", csn_as_string(prim_csn->prim_csn, PR_FALSE, csn_str));
}
}
- if ((max_csn = csnplRollUp(replica->csnpl, &first_csn)) != NULL)
- {
-#ifdef DEBUG
- slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - Rolled up to csn %s\n",
- csn_as_string(max_csn, PR_FALSE, csn_str)); /* XXXggood remove debugging */
-#endif
+ if ((max_csn = csnplRollUp(replica->csnpl, &first_csn)) != NULL) {
+ slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - Rolled up to csn %s\n",
+ csn_as_string(max_csn, PR_FALSE, csn_str)); /* XXXggood remove debugging */
/* replica object sets min csn for local replica */
- if (!isLocal && replica->min_csn == NULL) {
- /* bug 559223 - it seems that, under huge stress, a server might pass
- * through this code when more than 1 change has already been sent and commited into
- * the pending lists... Therefore, as we are trying to set the min_csn ever
- * generated by this replica, we need to set the first_csn as the min csn in the
- * ruv */
- set_min_csn_nolock(ruv, first_csn, replica_purl);
- }
- /* only update the max_csn in the RUV if it is greater than the existing one */
- rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */);
- /* It is possible that first_csn points to max_csn.
- We need to free it once */
- if (max_csn != first_csn) {
- csn_free(&first_csn);
- }
- csn_free(&max_csn);
- }
-
+ if (!isLocal && replica->min_csn == NULL) {
+ /* bug 559223 - it seems that, under huge stress, a server might pass
+ * through this code when more than 1 change has already been sent and commited into
+ * the pending lists... Therefore, as we are trying to set the min_csn ever
+ * generated by this replica, we need to set the first_csn as the min csn in the
+ * ruv */
+ set_min_csn_nolock(ruv, first_csn, replica_purl);
+ }
+ /* only update the max_csn in the RUV if it is greater than the existing one */
+ rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */);
+ /* It is possible that first_csn points to max_csn.
+ We need to free it once */
+ if (max_csn != first_csn) {
+ csn_free(&first_csn);
+ }
+ csn_free(&max_csn);
+ }
done:
return rc;
diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h
index c8960fd..f3cd38b 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.h
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
@@ -108,9 +108,9 @@ int ruv_to_bervals(const RUV *ruv, struct berval ***bvals);
PRInt32 ruv_replica_count (const RUV *ruv);
char **ruv_get_referrals(const RUV *ruv);
void ruv_dump(const RUV *ruv, char *ruv_name, PRFileDesc *prFile);
-int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn);
-int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId rid);
-int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, ReplicaId local_rid);
+int ruv_add_csn_inprogress (void *repl, RUV *ruv, const CSN *csn);
+int ruv_cancel_csn_inprogress (void *repl, RUV *ruv, const CSN *csn, ReplicaId rid);
+int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, void *replica, ReplicaId local_rid);
int ruv_move_local_supplier_to_first(RUV *ruv, ReplicaId rid);
int ruv_get_first_id_and_purl(RUV *ruv, ReplicaId *rid, char **replica_purl );
int ruv_local_contains_supplier(RUV *ruv, ReplicaId rid);
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 0836d66..3910dbe 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -193,7 +193,7 @@ const CSN *csn_max(const CSN *csn1,const CSN *csn2);
a csn from the set.*/
int csn_increment_subsequence (CSN *csn);
-void csnplFreeCSN (void *arg);
+void csnplFreeCSNPL_CTX (void *arg);
/*
* csnset.c
*/
--
2.9.4

View file

@ -0,0 +1,201 @@
From 95b39e29361812a62f2e038c89a88d717c82794e Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Mon, 31 Jul 2017 14:13:49 +1000
Subject: [PATCH] Ticket 49336 - SECURITY: Locked account provides different
return code
Bug Description: The directory server password lockout policy prevents binds
from operating once a threshold of failed passwords has been met. During
this lockout, if you bind with a successful password, a different error code
is returned. This means that an attacker has no ratelimit or penalty during
an account lock, and can continue to attempt passwords via bruteforce, using
the change in return code to ascertain a sucessful password auth.
Fix Description: Move the account lock check *before* the password bind
check. If the account is locked, we do not mind disclosing this as the
attacker will either ignore it (and will not bind anyway), or they will
be forced to back off as the attack is not working preventing the
bruteforce.
https://pagure.io/389-ds-base/issue/49336
Author: wibrown
Review by: tbordaz (Thanks!)
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
---
.../suites/password/pwd_lockout_bypass_test.py | 55 ++++++++++++++++++++++
ldap/servers/slapd/bind.c | 29 ++++++++----
ldap/servers/slapd/pw_verify.c | 15 +++---
3 files changed, 84 insertions(+), 15 deletions(-)
create mode 100644 dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
diff --git a/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py b/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
new file mode 100644
index 0000000..e4add72
--- /dev/null
+++ b/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
@@ -0,0 +1,55 @@
+# --- 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
+from lib389.tasks import *
+from lib389.utils import *
+from lib389.topologies import topology_st
+from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES
+import ldap
+
+# The irony of these names is not lost on me.
+GOOD_PASSWORD = 'password'
+BAD_PASSWORD = 'aontseunao'
+
+logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+def test_lockout_bypass(topology_st):
+ inst = topology_st.standalone
+
+ # Configure the lock policy
+ inst.config.set('passwordMaxFailure', '1')
+ inst.config.set('passwordLockoutDuration', '99999')
+ inst.config.set('passwordLockout', 'on')
+
+ # Create the account
+ users = UserAccounts(inst, DEFAULT_SUFFIX)
+ testuser = users.create(properties=TEST_USER_PROPERTIES)
+ testuser.set('userPassword', GOOD_PASSWORD)
+
+ conn = testuser.bind(GOOD_PASSWORD)
+ assert conn != None
+ conn.unbind_s()
+
+ # Bind with bad creds twice
+ # This is the failure.
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
+ conn = testuser.bind(BAD_PASSWORD)
+ # Now we should not be able to ATTEMPT the bind. It doesn't matter that
+ # we disclose that we have hit the rate limit here, what matters is that
+ # it exists.
+ with pytest.raises(ldap.CONSTRAINT_VIOLATION):
+ conn = testuser.bind(BAD_PASSWORD)
+
+ # now bind with good creds
+ # Should be error 19 still.
+ with pytest.raises(ldap.CONSTRAINT_VIOLATION):
+ conn = testuser.bind(GOOD_PASSWORD)
+
+
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index 7f4414f..064ace1 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -662,12 +662,14 @@ do_bind( Slapi_PBlock *pb )
/* We could be serving multiple database backends. Select the appropriate one */
/* pw_verify_be_dn will select the backend we need for us. */
- if (auto_bind) {
- /* We have no password material. We should just check who we are binding as. */
- rc = pw_validate_be_dn(pb, &referral);
- } else {
- rc = pw_verify_be_dn(pb, &referral);
- }
+ /*
+ * WARNING: We have to validate *all* other conditions *first* before
+ * we attempt the bind!
+ *
+ * this is because ldbm_bind.c will SEND THE FAILURE.
+ */
+
+ rc = pw_validate_be_dn(pb, &referral);
if (rc == SLAPI_BIND_NO_BACKEND) {
send_nobackend_ldap_result( pb );
@@ -736,8 +738,18 @@ do_bind( Slapi_PBlock *pb )
myrc = 0;
}
if (!auto_bind) {
- /*
- * There could be a race that bind_target_entry was not added
+ /*
+ * Okay, we've made it here. FINALLY check if the entry really
+ * can bind or not. THIS IS THE PASSWORD CHECK.
+ */
+ rc = pw_verify_be_dn(pb, &referral);
+ if (rc != SLAPI_BIND_SUCCESS) {
+ /* Invalid pass - lets bail ... */
+ goto bind_failed;
+ }
+
+ /*
+ * There could be a race that bind_target_entry was not added
* when bind_target_entry was retrieved before be_bind, but it
* was in be_bind. Since be_bind returned SLAPI_BIND_SUCCESS,
* the entry is in the DS. So, we need to retrieve it once more.
@@ -786,6 +798,7 @@ do_bind( Slapi_PBlock *pb )
}
}
} else { /* if auto_bind || rc == slapi_bind_success | slapi_bind_anonymous */
+ bind_failed:
if (rc == LDAP_OPERATIONS_ERROR) {
send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL );
goto free_and_return;
diff --git a/ldap/servers/slapd/pw_verify.c b/ldap/servers/slapd/pw_verify.c
index 852b027..cb182ed 100644
--- a/ldap/servers/slapd/pw_verify.c
+++ b/ldap/servers/slapd/pw_verify.c
@@ -55,7 +55,7 @@ pw_verify_root_dn(const char *dn, const Slapi_Value *cred)
int
pw_verify_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
{
- int rc = 0;
+ int rc = SLAPI_BIND_SUCCESS;
Slapi_Backend *be = NULL;
if (slapi_mapping_tree_select(pb, &be, referral, NULL, 0) != LDAP_SUCCESS) {
@@ -109,14 +109,10 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
slapi_pblock_get(pb, SLAPI_BIND_CREDENTIALS, &cred);
slapi_pblock_get(pb, SLAPI_BIND_METHOD, &method);
- if (pb_sdn != NULL || cred != NULL) {
+ if (pb_sdn == NULL) {
return LDAP_OPERATIONS_ERROR;
}
- if (*referral) {
- return SLAPI_BIND_REFERRAL;
- }
-
/* We need a slapi_sdn_isanon? */
if (method == LDAP_AUTH_SIMPLE && cred->bv_len == 0) {
return SLAPI_BIND_ANONYMOUS;
@@ -130,7 +126,11 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
if (slapi_mapping_tree_select(pb, &be, referral, NULL, 0) != LDAP_SUCCESS) {
return SLAPI_BIND_NO_BACKEND;
}
- slapi_be_Unlock(be);
+
+ if (*referral) {
+ slapi_be_Unlock(be);
+ return SLAPI_BIND_REFERRAL;
+ }
slapi_pblock_set(pb, SLAPI_BACKEND, be);
slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
@@ -138,6 +138,7 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
set_db_default_result_handlers(pb);
/* The backend associated with this identity is real. */
+ slapi_be_Unlock(be);
return SLAPI_BIND_SUCCESS;
}
--
2.9.4

View file

@ -0,0 +1,177 @@
From ba30cc562f5ebd58955502a19edbf9720a45b655 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 8 Aug 2017 13:02:53 -0400
Subject: [PATCH] Ticket 49298 - force sync() on shutdown
Bug Description: During shutdown on xfs we would occasionally
see a broke dse.ldif (specifically, empty). This happens due to
a bug in xfs where the directory isn't synced on rename().
Fix Description: As we shutdown call sync() to force all our
writes to disk - dse.ldif, logs, db, all of it.
https://pagure.io/389-ds-base/issue/49298
---
ldap/servers/slapd/dse.c | 59 +++++++++++++++++++++++++++++------------------
ldap/servers/slapd/main.c | 9 ++++----
2 files changed, 42 insertions(+), 26 deletions(-)
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
index 5715c83..fa1aacc 100644
--- a/ldap/servers/slapd/dse.c
+++ b/ldap/servers/slapd/dse.c
@@ -40,6 +40,8 @@
#include "slap.h"
#include <pwd.h>
+#include <unistd.h> /* provides fsync/close */
+
/* #define SLAPI_DSE_DEBUG */ /* define this to force trace log */
/* messages to always be logged */
@@ -72,11 +74,11 @@
struct dse_callback
{
int operation;
- int flags;
- Slapi_DN *base;
- int scope;
- char *filter; /* NULL means match all entries */
- Slapi_Filter *slapifilter; /* NULL means match all entries */
+ int flags;
+ Slapi_DN *base;
+ int scope;
+ char *filter; /* NULL means match all entries */
+ Slapi_Filter *slapifilter; /* NULL means match all entries */
int (*fn)(Slapi_PBlock *,Slapi_Entry *,Slapi_Entry *,int*,char*,void *);
void *fn_arg;
struct slapdplugin *plugin;
@@ -89,13 +91,14 @@ struct dse
char *dse_tmpfile; /* and written to when changes are made via LDAP */
char *dse_fileback; /* contain the latest info, just before a new change */
char *dse_filestartOK; /* contain the latest info with which the server has successfully started */
+ char *dse_configdir; /* The location of config files - allows us to fsync the dir post rename */
Avlnode *dse_tree;
struct dse_callback *dse_callback;
Slapi_RWLock *dse_rwlock; /* a read-write lock to protect the whole dse backend */
- char **dse_filelist; /* these are additional read only files used to */
- /* initialize the dse */
- int dse_is_updateable; /* if non-zero, this DSE can be written to */
- int dse_readonly_error_reported; /* used to ensure that read-only errors are logged only once */
+ char **dse_filelist; /* these are additional read only files used to */
+ /* initialize the dse */
+ int dse_is_updateable; /* if non-zero, this DSE can be written to */
+ int dse_readonly_error_reported; /* used to ensure that read-only errors are logged only once */
};
struct dse_node
@@ -361,37 +364,39 @@ dse_new( char *filename, char *tmpfilename, char *backfilename, char *startokfil
if (!strstr(filename, realconfigdir))
{
pdse->dse_filename = slapi_ch_smprintf("%s/%s", realconfigdir, filename );
- }
- else
+ } else {
pdse->dse_filename = slapi_ch_strdup(filename);
+ }
if (!strstr(tmpfilename, realconfigdir)) {
pdse->dse_tmpfile = slapi_ch_smprintf("%s/%s", realconfigdir, tmpfilename );
- }
- else
+ } else {
pdse->dse_tmpfile = slapi_ch_strdup(tmpfilename);
+ }
+
+ pdse->dse_configdir = slapi_ch_strdup(realconfigdir);
if ( backfilename != NULL )
{
if (!strstr(backfilename, realconfigdir)) {
pdse->dse_fileback = slapi_ch_smprintf("%s/%s", realconfigdir, backfilename );
- }
- else
+ } else {
pdse->dse_fileback = slapi_ch_strdup(backfilename);
- }
- else
+ }
+ } else {
pdse->dse_fileback = NULL;
+ }
if ( startokfilename != NULL )
{
if (!strstr(startokfilename, realconfigdir)) {
pdse->dse_filestartOK = slapi_ch_smprintf("%s/%s", realconfigdir, startokfilename );
- }
- else
+ } else {
pdse->dse_filestartOK = slapi_ch_strdup(startokfilename);
- }
- else
+ }
+ } else {
pdse->dse_filestartOK = NULL;
+ }
pdse->dse_tree= NULL;
pdse->dse_callback= NULL;
@@ -440,6 +445,7 @@ dse_destroy(struct dse *pdse)
slapi_ch_free((void **)&(pdse->dse_tmpfile));
slapi_ch_free((void **)&(pdse->dse_fileback));
slapi_ch_free((void **)&(pdse->dse_filestartOK));
+ slapi_ch_free((void **)&(pdse->dse_configdir));
dse_callback_deletelist(&pdse->dse_callback);
charray_free(pdse->dse_filelist);
nentries = avl_free(pdse->dse_tree, dse_internal_delete_entry);
@@ -991,8 +997,9 @@ dse_write_file_nolock(struct dse* pdse)
FPWrapper fpw;
int rc = 0;
- if (dont_ever_write_dse_files)
+ if (dont_ever_write_dse_files) {
return rc;
+ }
fpw.fpw_rc = 0;
fpw.fpw_prfd = NULL;
@@ -1042,6 +1049,14 @@ dse_write_file_nolock(struct dse* pdse)
pdse->dse_tmpfile, pdse->dse_filename,
rc, slapd_system_strerror( rc ));
}
+ /*
+ * We have now written to the tmp location, and renamed it
+ * we need to open and fsync the dir to make the rename stick.
+ */
+ int fp_configdir = open(pdse->dse_configdir, O_PATH | O_DIRECTORY);
+ fsync(fp_configdir);
+ close(fp_configdir);
+
}
}
if (fpw.fpw_prfd)
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
index ba1f5e8..3351464 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -1154,11 +1154,12 @@ cleanup:
ndn_cache_destroy();
NSS_Shutdown();
PR_Cleanup();
-#if defined( hpux )
- exit( return_value );
-#else
+ /*
+ * Server has stopped, lets force everything to disk: logs
+ * db, dse.ldif, all of it.
+ */
+ sync();
return return_value;
-#endif
}
--
2.9.4

View file

@ -0,0 +1,37 @@
From c903f66194f04e97fc684f5a9654cedb27530931 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Mon, 31 Jul 2017 10:51:08 +0200
Subject: [PATCH 1/3] Ticket 49334 - fix backup restore if changelog exists
The corrcect flag to copy a directory in backup/restore must be passed for the changelog directory
Reviewed by: William, thanks
---
ldap/servers/slapd/back-ldbm/dblayer.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index ff97aa4..3a97f2f 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -6143,7 +6143,7 @@ dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task)
return_value = dblayer_copy_directory(li, task, changelogdir,
changelog_destdir,
0 /* backup */,
- &cnt, 1, 0, 0);
+ &cnt, 0, 0, 1);
if (return_value) {
slapi_log_err(SLAPI_LOG_ERR,
"dblayer_backup", "Error in copying directory "
@@ -6823,7 +6823,7 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char *
*cldirname = '\0';
return_value = dblayer_copy_directory(li, task, filename1,
changelogdir, 1 /* restore */,
- &cnt, 1, 0 ,0);
+ &cnt, 0, 0 ,1);
*cldirname = '/';
if (return_value) {
slapi_log_err(SLAPI_LOG_ERR,
--
2.9.4

View file

@ -0,0 +1,502 @@
From b0954a5df7841330732a5ab532c528a68cf380cf Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
Date: Fri, 18 Aug 2017 13:00:46 +1000
Subject: [PATCH] Ticket 49356 - mapping tree crash can occur during tot init
Bug Description: Two faults were found in the handling of the mapping
tree of 389 directory server. The first fault was that the tree-free
check was not performed atomically and may cause an incorrect operations
error to be returned. The second was that during a total init the referral
would not lock the be, but the pw_verify code assumed a be was locked.
This caused a segfault.
Fix Description: Fix the freed check to use atomics. Fix the pw_verify
to assert be is NULL (which is correct, there is no backend).
https://pagure.io/389-ds-base/issue/49356
Author: wibrown
Review by: mreynolds (THanks!)
---
.../mapping_tree/referral_during_tot_init.py | 57 ++++++++
ldap/servers/slapd/fedse.c | 10 ++
ldap/servers/slapd/main.c | 10 --
ldap/servers/slapd/mapping_tree.c | 150 +++++++++++----------
ldap/servers/slapd/pw_verify.c | 8 +-
5 files changed, 150 insertions(+), 85 deletions(-)
create mode 100644 dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
diff --git a/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py b/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
new file mode 100644
index 0000000..e5aee7d
--- /dev/null
+++ b/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
@@ -0,0 +1,57 @@
+# --- 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 ldap
+import pytest
+from lib389.topologies import topology_m2
+from lib389._constants import (DEFAULT_SUFFIX, HOST_MASTER_2, PORT_MASTER_2, TASK_WAIT)
+
+from lib389.idm.user import (TEST_USER_PROPERTIES, UserAccounts)
+
+def test_referral_during_tot(topology_m2):
+
+ master1 = topology_m2.ms["master1"]
+ master2 = topology_m2.ms["master2"]
+
+ # Create a bunch of entries on master1
+ ldif_dir = master1.get_ldif_dir()
+ import_ldif = ldif_dir + '/ref_during_tot_import.ldif'
+ master1.buildLDIF(10000, import_ldif)
+
+ master1.stop()
+ try:
+ master1.ldif2db(bename=None, excludeSuffixes=None, encrypt=False, suffixes=[DEFAULT_SUFFIX], import_file=import_ldif)
+ except:
+ pass
+ # master1.tasks.importLDIF(suffix=DEFAULT_SUFFIX, input_file=import_ldif, args={TASK_WAIT: True})
+ master1.start()
+ users = UserAccounts(master1, DEFAULT_SUFFIX, rdn='ou=Accounting')
+
+ u = users.create(properties=TEST_USER_PROPERTIES)
+ u.set('userPassword', 'password')
+
+ binddn = u.dn
+ bindpw = 'password'
+
+ # Now export them to master2
+ master1.agreement.init(DEFAULT_SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
+
+ # While that's happening try to bind as a user to master 2
+ # This should trigger the referral code.
+ for i in range(0, 100):
+ conn = ldap.initialize(master2.toLDAPURL())
+ conn.set_option(ldap.OPT_REFERRALS, False)
+ try:
+ conn.simple_bind_s(binddn, bindpw)
+ conn.unbind_s()
+ except ldap.REFERRAL:
+ pass
+
+ # Done.
+
+
diff --git a/ldap/servers/slapd/fedse.c b/ldap/servers/slapd/fedse.c
index 13a3c74..c2a862b 100644
--- a/ldap/servers/slapd/fedse.c
+++ b/ldap/servers/slapd/fedse.c
@@ -1853,6 +1853,16 @@ setup_internal_backends(char *configdir)
be_addsuffix(be,&monitor);
be_addsuffix(be,&config);
+ /*
+ * Now that the be's are in place, we can
+ * setup the mapping tree.
+ */
+
+ if (mapping_tree_init()) {
+ slapi_log_err(SLAPI_LOG_EMERG, "setup_internal_backends", "Failed to init mapping tree\n");
+ exit(1);
+ }
+
add_internal_entries();
add_easter_egg_entry();
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
index 552d54d..1d9afce 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -1034,16 +1034,6 @@ main( int argc, char **argv)
ps_init_psearch_system(); /* must come before plugin_startall() */
- /* Initailize the mapping tree */
-
- if (mapping_tree_init())
- {
- slapi_log_err(SLAPI_LOG_EMERG, "main", "Failed to init mapping tree\n");
- return_value = 1;
- goto cleanup;
- }
-
-
/* initialize UniqueID generator - must be done once backends are started
and event queue is initialized but before plugins are started */
/* Note: This DN is no need to be normalized. */
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
index 1b8d2d9..dfb6584 100644
--- a/ldap/servers/slapd/mapping_tree.c
+++ b/ldap/servers/slapd/mapping_tree.c
@@ -88,13 +88,13 @@ struct mt_node
* release backend lock
*
*/
-static Slapi_RWLock *myLock; /* global lock on the mapping tree structures */
+static Slapi_RWLock *myLock = NULL; /* global lock on the mapping tree structures */
static mapping_tree_node *mapping_tree_root = NULL;
-static int mapping_tree_inited = 0;
-static int mapping_tree_freed = 0;
-static int extension_type = -1; /* type returned from the factory */
+static int32_t mapping_tree_inited = 0;
+static int32_t mapping_tree_freed = 0;
+static int extension_type = -1; /* type returned from the factory */
/* The different states a mapping tree node can be in. */
#define MTN_DISABLED 0 /* The server acts like the node isn't there. */
@@ -1659,22 +1659,24 @@ add_internal_mapping_tree_node(const char *subtree, Slapi_Backend *be, mapping_t
{
Slapi_DN *dn;
mapping_tree_node *node;
- backend ** be_list = (backend **) slapi_ch_malloc(sizeof(backend *));
+ backend **be_list = (backend **)slapi_ch_malloc(sizeof(backend *));
+ int *be_states = (int *)slapi_ch_malloc(sizeof(int));
be_list[0] = be;
+ be_states[0] = SLAPI_BE_STATE_ON;
dn = slapi_sdn_new_dn_byval(subtree);
- node= mapping_tree_node_new(
- dn,
- be_list,
- NULL, /* backend_name */
- NULL,
- 1, /* number of backends at this node */
- 1, /* size of backend list structure */
- NULL, /* referral */
- parent,
- MTN_BACKEND,
- 1, /* The config node is a private node.
+ node = mapping_tree_node_new(
+ dn,
+ be_list,
+ NULL, /* backend_name */
+ be_states, /* be state */
+ 1, /* number of backends at this node */
+ 1, /* size of backend list structure */
+ NULL, /* referral */
+ parent,
+ MTN_BACKEND,
+ 1, /* The config node is a private node.
* People can't see or change it. */
NULL, NULL, NULL, 0); /* no distribution */
return node;
@@ -1722,17 +1724,20 @@ mapping_tree_init()
/* we call this function from a single thread, so it should be ok */
- if(mapping_tree_freed){
- /* shutdown has been detected */
- return 0;
- }
-
- if (mapping_tree_inited)
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+ /* shutdown has been detected */
return 0;
+ }
- /* ONREPL - I have moved this up because otherwise we can endup calling this
+ /* ONREPL - I have moved this up because otherwise we can endup calling this
* function recursively */
+ if (myLock != NULL) {
+ return 0;
+ }
+ myLock = slapi_new_rwlock();
+ slapi_rwlock_wrlock(myLock);
+ /* Should be fenced by the rwlock. */
mapping_tree_inited = 1;
slapi_register_supported_control(MTN_CONTROL_USE_ONE_BACKEND_OID,
@@ -1740,10 +1745,8 @@ mapping_tree_init()
slapi_register_supported_control(MTN_CONTROL_USE_ONE_BACKEND_EXT_OID,
SLAPI_OPERATION_SEARCH);
- myLock = slapi_new_rwlock();
-
- be= slapi_be_select_by_instance_name(DSE_BACKEND);
- mapping_tree_root= add_internal_mapping_tree_node("", be, NULL);
+ be = slapi_be_select_by_instance_name(DSE_BACKEND);
+ mapping_tree_root = add_internal_mapping_tree_node("", be, NULL);
/* We also need to add the config and schema backends to the mapping tree.
* They are special in that users will not know about it's node in the
@@ -1757,17 +1760,23 @@ mapping_tree_init()
node= add_internal_mapping_tree_node("cn=schema", be, mapping_tree_root);
mapping_tree_node_add_child(mapping_tree_root, node);
- /*
+ slapi_rwlock_unlock(myLock);
+
+ /*
* Now we need to look under cn=mapping tree, cn=config to find the rest
* of the mapping tree entries.
* Builds the mapping tree from entries in the DIT. This function just
* calls mapping_tree_node_get_children with the special case for the
* root node.
*/
- if (mapping_tree_node_get_children(mapping_tree_root, 1))
+
+ if (mapping_tree_node_get_children(mapping_tree_root, 1)) {
return -1;
+ }
+ slapi_rwlock_wrlock(myLock);
mtn_create_extension(mapping_tree_root);
+ slapi_rwlock_unlock(myLock);
/* setup the dse callback functions for the ldbm instance config entry */
{
@@ -1840,8 +1849,8 @@ mapping_tree_free ()
*/
slapi_unregister_backend_state_change_all();
/* recursively free tree nodes */
- mtn_free_node (&mapping_tree_root);
- mapping_tree_freed = 1;
+ mtn_free_node(&mapping_tree_root);
+ __atomic_store_4(&mapping_tree_freed, 1, __ATOMIC_RELAXED);
}
/* This function returns the first node to parse when a search is done
@@ -2083,14 +2092,12 @@ int slapi_dn_write_needs_referral(Slapi_DN *target_sdn, Slapi_Entry **referral)
mapping_tree_node *target_node = NULL;
int ret = 0;
- if(mapping_tree_freed){
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
/* shutdown detected */
goto done;
}
- if(!mapping_tree_inited) {
- mapping_tree_init();
- }
+ PR_ASSERT(mapping_tree_inited == 1);
if (target_sdn) {
mtn_lock();
@@ -2157,8 +2164,8 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
int fixup = 0;
- if(mapping_tree_freed){
- /* shutdown detected */
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
+ /* shutdown detected */
return LDAP_OPERATIONS_ERROR;
}
@@ -2175,9 +2182,7 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
target_sdn = operation_get_target_spec (op);
fixup = operation_is_flag_set(op, OP_FLAG_TOMBSTONE_FIXUP);
- if(!mapping_tree_inited) {
- mapping_tree_init();
- }
+ PR_ASSERT(mapping_tree_inited == 1);
be[0] = NULL;
if (referral) {
@@ -2188,8 +2193,9 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
/* Get the mapping tree node that is the best match for the target dn. */
target_node = slapi_get_mapping_tree_node_by_dn(target_sdn);
- if (target_node == NULL)
+ if (target_node == NULL) {
target_node = mapping_tree_root;
+ }
/* The processing of the base scope root DSE search and all other LDAP operations on ""
* will be transferred to the internal DSE backend
@@ -2266,8 +2272,8 @@ int slapi_mapping_tree_select_all(Slapi_PBlock *pb, Slapi_Backend **be_list,
Slapi_DN *sdn = NULL;
int flag_partial_result = 0;
int op_type;
-
- if(mapping_tree_freed){
+
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
return LDAP_OPERATIONS_ERROR;
}
@@ -2287,9 +2293,7 @@ int slapi_mapping_tree_select_all(Slapi_PBlock *pb, Slapi_Backend **be_list,
slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
- if(!mapping_tree_inited){
- mapping_tree_init();
- }
+ PR_ASSERT(mapping_tree_inited == 1);
mtn_lock();
@@ -2448,8 +2452,8 @@ int slapi_mapping_tree_select_and_check(Slapi_PBlock *pb,char *newdn, Slapi_Back
Slapi_Operation *op;
int ret;
int need_unlock = 0;
-
- if(mapping_tree_freed){
+
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
return LDAP_OPERATIONS_ERROR;
}
@@ -2635,7 +2639,7 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
int flag_stop = 0;
struct slapi_componentid *cid = NULL;
- if(mapping_tree_freed){
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
/* shut down detected */
return LDAP_OPERATIONS_ERROR;
}
@@ -2719,21 +2723,22 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
} else {
/* This MTN has not been linked to its backend
* instance yet. */
- target_node->mtn_be[*index] =
- slapi_be_select_by_instance_name(
- target_node->mtn_backend_names[*index]);
- *be = target_node->mtn_be[*index];
- if(*be==NULL) {
- slapi_log_err(SLAPI_LOG_BACKLDBM, "mtn_get_be",
- "Warning: Mapping tree node entry for %s "
- "point to an unknown backend : %s\n",
- slapi_sdn_get_dn(target_node->mtn_subtree),
- target_node->mtn_backend_names[*index]);
- /* Well there's still not backend instance for
- * this MTN, so let's have the default backend
- * deal with this.
- */
- *be = defbackend_get_backend();
+ /* WARNING: internal memory dse backends don't provide NAMES */
+ if (target_node->mtn_backend_names != NULL) {
+ target_node->mtn_be[*index] = slapi_be_select_by_instance_name(target_node->mtn_backend_names[*index]);
+ *be = target_node->mtn_be[*index];
+ if (*be == NULL) {
+ slapi_log_err(SLAPI_LOG_BACKLDBM, "mtn_get_be",
+ "Warning: Mapping tree node entry for %s "
+ "point to an unknown backend : %s\n",
+ slapi_sdn_get_dn(target_node->mtn_subtree),
+ target_node->mtn_backend_names[*index]);
+ /* Well there's still not backend instance for
+ * this MTN, so let's have the default backend
+ * deal with this.
+ */
+ *be = defbackend_get_backend();
+ }
}
}
}
@@ -2745,10 +2750,11 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
result = LDAP_OPERATIONS_ERROR;
*be = defbackend_get_backend();
}
- if (flag_stop)
+ if (flag_stop) {
*index = SLAPI_BE_NO_BACKEND;
- else
+ } else {
(*index)++;
+ }
}
}
} else {
@@ -2822,7 +2828,7 @@ static mapping_tree_node *best_matching_child(mapping_tree_node *parent,
mapping_tree_node *highest_match_node = NULL;
mapping_tree_node *current;
- if(mapping_tree_freed){
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
/* shutdown detected */
return NULL;
}
@@ -2849,7 +2855,7 @@ mtn_get_mapping_tree_node_by_entry(mapping_tree_node* node, const Slapi_DN *dn)
{
mapping_tree_node *found_node = NULL;
- if(mapping_tree_freed){
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
/* shutdown detected */
return NULL;
}
@@ -2895,7 +2901,7 @@ slapi_get_mapping_tree_node_by_dn(const Slapi_DN *dn)
mapping_tree_node *current_best_match = mapping_tree_root;
mapping_tree_node *next_best_match = mapping_tree_root;
- if(mapping_tree_freed){
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
/* shutdown detected */
return NULL;
}
@@ -2929,7 +2935,7 @@ get_mapping_tree_node_by_name(mapping_tree_node * node, char * be_name)
int i;
mapping_tree_node *found_node = NULL;
- if(mapping_tree_freed){
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
/* shutdown detected */
return NULL;
}
@@ -2980,7 +2986,7 @@ slapi_get_mapping_tree_node_configdn (const Slapi_DN *root)
{
char *dn = NULL;
- if(mapping_tree_freed){
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
/* shutdown detected */
return NULL;
}
@@ -3007,7 +3013,7 @@ slapi_get_mapping_tree_node_configsdn (const Slapi_DN *root)
char *dn = NULL;
Slapi_DN *sdn = NULL;
- if(mapping_tree_freed){
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
/* shutdown detected */
return NULL;
}
diff --git a/ldap/servers/slapd/pw_verify.c b/ldap/servers/slapd/pw_verify.c
index cb182ed..1f0c18a 100644
--- a/ldap/servers/slapd/pw_verify.c
+++ b/ldap/servers/slapd/pw_verify.c
@@ -58,12 +58,14 @@ pw_verify_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
int rc = SLAPI_BIND_SUCCESS;
Slapi_Backend *be = NULL;
- if (slapi_mapping_tree_select(pb, &be, referral, NULL, 0) != LDAP_SUCCESS) {
+ int mt_result = slapi_mapping_tree_select(pb, &be, referral, NULL, 0);
+ if (mt_result != LDAP_SUCCESS) {
return SLAPI_BIND_NO_BACKEND;
}
if (*referral) {
- slapi_be_Unlock(be);
+ /* If we have a referral, this is NULL */
+ PR_ASSERT(be == NULL);
return SLAPI_BIND_REFERRAL;
}
@@ -128,7 +130,7 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
}
if (*referral) {
- slapi_be_Unlock(be);
+ PR_ASSERT(be == NULL);
return SLAPI_BIND_REFERRAL;
}
--
2.9.4

View file

@ -7,8 +7,6 @@
# also need the relprefix field for a pre-release e.g. .0 - also comment out for official release
#% global relprefix 0.
%global use_openldap 1
%global use_db4 0
# If perl-Socket-2.000 or newer is available, set 0 to use_Socket6.
%global use_Socket6 0
%global use_nunc_stans 1
@ -32,7 +30,7 @@
Summary: 389 Directory Server (base)
Name: 389-ds-base
Version: 1.3.6.1
Release: %{?relprefix}16%{?prerel}%{?dist}
Release: %{?relprefix}19%{?prerel}%{?dist}
License: GPLv3+
URL: https://www.port389.org/
Group: System Environment/Daemons
@ -43,17 +41,9 @@ Provides: ldif2ldbm >= 0
BuildRequires: nspr-devel
BuildRequires: nss-devel
BuildRequires: svrcore-devel >= 4.1.2
%if %{use_openldap}
BuildRequires: svrcore-devel >= 4.1.3
BuildRequires: openldap-devel
%else
BuildRequires: mozldap-devel
%endif
%if %{use_db4}
BuildRequires: db4-devel
%else
BuildRequires: libdb-devel
%endif
BuildRequires: cyrus-sasl-devel
BuildRequires: icu
BuildRequires: libicu-devel
@ -93,11 +83,7 @@ Requires: libsemanage-python
Requires: selinux-policy >= 3.13.1-137
# the following are needed for some of our scripts
%if %{use_openldap}
Requires: openldap-clients
%else
Requires: mozldap-tools
%endif
# use_openldap assumes perl-Mozilla-LDAP is built with openldap support
Requires: perl-Mozilla-LDAP
@ -112,11 +98,7 @@ Requires: cyrus-sasl-md5
Requires: cyrus-sasl-plain
# this is needed for verify-db.pl
%if %{use_db4}
Requires: db4-utils
%else
Requires: libdb-utils
%endif
# This picks up libperl.so as a Requires, so we add this versioned one
Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
@ -137,7 +119,7 @@ Requires: perl-Socket
%endif
Requires: perl-NetAddr-IP
Requires: systemd-libs
Requires: svrcore >= 4.1.2
Requires: svrcore >= 4.1.3
# upgrade path from monolithic % {name} (including -libs & -devel) to % {name} + % {name}-snmp
Obsoletes: %{name} <= 1.3.5.4
@ -207,6 +189,12 @@ Patch52: 0052-Ticket-49257-Reject-nsslapd-cachememsize-nsslapd-cac.patc
Patch53: 0053-Ticket-49257-Reject-dbcachesize-updates-while-auto-c.patch
Patch54: 0054-Ticket-49184-adjust-logging-level-in-MO-plugin.patch
Patch55: 0055-Ticket-49241-add-symblic-link-location-to-db2bak.pl-.patch
Patch56: 0056-Ticket-49313-Change-the-retrochangelog-default-cache.patch
Patch57: 0057-Ticket-49287-v3-extend-csnpl-handling-to-multiple-ba.patch
Patch58: 0058-Ticket-49336-SECURITY-Locked-account-provides-differ.patch
Patch59: 0059-Ticket-49298-force-sync-on-shutdown.patch
Patch60: 0060-Ticket-49334-fix-backup-restore-if-changelog-exists.patch
Patch61: 0061-Ticket-49356-mapping-tree-crash-can-occur-during-tot.patch
%description
@ -218,17 +206,9 @@ Summary: Core libraries for 389 Directory Server
Group: System Environment/Daemons
BuildRequires: nspr-devel
BuildRequires: nss-devel
BuildRequires: svrcore-devel >= 4.1.2
%if %{use_openldap}
BuildRequires: svrcore-devel >= 4.1.3
BuildRequires: openldap-devel
%else
BuildRequires: mozldap-devel
%endif
%if %{use_db4}
BuildRequires: db4-devel
%else
BuildRequires: libdb-devel
%endif
BuildRequires: cyrus-sasl-devel
BuildRequires: libicu-devel
BuildRequires: pcre-devel
@ -251,12 +231,8 @@ Requires: %{name}-libs = %{version}-%{release}
Requires: pkgconfig
Requires: nspr-devel
Requires: nss-devel
Requires: svrcore-devel >= 4.1.2
%if %{use_openldap}
Requires: svrcore-devel >= 4.1.3
Requires: openldap-devel
%else
Requires: mozldap-devel
%endif
%if %{use_nunc_stans}
Requires: libtalloc
Requires: libevent
@ -345,12 +321,15 @@ cp %{SOURCE2} README.devel
%patch53 -p1
%patch54 -p1
%patch55 -p1
%patch56 -p1
%patch57 -p1
%patch58 -p1
%patch59 -p1
%patch60 -p1
%patch61 -p1
%build
%if %{use_openldap}
OPENLDAP_FLAG="--with-openldap"
%endif
%{?with_tmpfiles_d: TMPFILES_FLAG="--with-tmpfiles-d=%{with_tmpfiles_d}"}
# hack hack hack https://bugzilla.redhat.com/show_bug.cgi?id=833529
NSSARGS="--with-svrcore-inc=%{_includedir} --with-svrcore-lib=%{_libdir} --with-nss-lib=%{_libdir} --with-nss-inc=%{_includedir}/nss3"
@ -442,11 +421,7 @@ HOMEDIR="/usr/share/dirsrv"
getent group $GROUPNAME >/dev/null || /usr/sbin/groupadd -f -g $ALLOCATED_GID -r $GROUPNAME
if ! getent passwd $USERNAME >/dev/null ; then
if ! getent passwd $ALLOCATED_UID >/dev/null ; then
/usr/sbin/useradd -r -u $ALLOCATED_UID -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME
else
/usr/sbin/useradd -r -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME
fi
/usr/sbin/useradd -r -u $ALLOCATED_UID -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME
fi
echo looking for instances in %{_sysconfdir}/%{pkgname} > $output 2>&1 || :
@ -583,6 +558,23 @@ fi
%{_sysconfdir}/%{pkgname}/dirsrvtests
%changelog
* Mon Aug 21 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.19-1
- Bump version to 1.3.6.19-1
- Remove old mozldap and db4 requirements
- Resolves: Bug 1483865 - Crash while binding to a server during replication online init
* Tue Aug 8 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-18
- Bump version to 1.3.6.1-18
- Require srvcore 4.1.3
- Resolves: Bug 1479757 - dse.ldif and fsync
- Resolves: Bug 1479755 - backup fails if changelog is enabled
- Resolves: Bug 1479756 - Locked account provides different return code if password is correct
* Mon Jul 31 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-17
- Bump version to 1.3.6.1-17
- Resolves: Bug 1476161 - replication halt - pending list first CSN not committed, pending list increasing
- Resolves: Bug 1476162 - Change the retrochangelog default cache size
* Tue Jun 6 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-16
- Bump version to 1.3.6.1-16
- Resolves: Bug 1444938 - nsslapd-allowed-sasl-mechanisms doesn't reset to default values without a restart