From a9870f937ae83728326957c408608eff3b9b7b26 Mon Sep 17 00:00:00 2001
From: Rich Megginson <rmeggins@redhat.com>
Date: Mon, 14 Oct 2013 12:43:51 -0600
Subject: [PATCH 40/41] Ticket #47559 hung server - related to sasl and initialize
https://fedorahosted.org/389/ticket/47559
Reviewed by: nhosoi (Thanks!)
Branch: rhel-7.0
Fix Description: Use a mutex to protect calls to openldap functions that do
anything with crypto - bind, unbind, start_tls, other calls.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit da3e4aa40b04094d0e77052b894b0f0c335ea1ef)
(cherry picked from commit 7b3b2fe9d4a7f73a12b4f2d499b2e6a2f80e454b)
(cherry picked from commit 8a7ee90d6a770f1732bcd03b20471de3a6162b2b)
---
ldap/servers/slapd/ldaputil.c | 51 +++++++++++++++++++++++++++++++++++++---
1 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index edc8267..aa78d3d 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -99,10 +99,16 @@
#if !defined(USE_OPENLDAP)
#include <ldap_ssl.h>
#include <ldappr.h>
+#define BIND_LOCK (void)0
+#define BIND_UNLOCK (void)0
#else
/* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */
static PRCallOnceType ol_init_callOnce = {0,0};
static PRLock *ol_init_lock = NULL;
+/* need mutex around ldap_sasl_bind - see https://fedorahosted.org/389/ticket/47599 */
+static PRLock *ol_bind_lock = NULL;
+#define BIND_LOCK PR_Lock(ol_bind_lock)
+#define BIND_UNLOCK PR_Unlock(ol_bind_lock)
static PRStatus
internal_ol_init_init(void)
@@ -110,12 +116,20 @@ internal_ol_init_init(void)
PR_ASSERT(NULL == ol_init_lock);
if ((ol_init_lock = PR_NewLock()) == NULL) {
PRErrorCode errorCode = PR_GetError();
- slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock failed %d:%s\n",
+ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock init_lock failed %d:%s\n",
errorCode, slapd_pr_strerror(errorCode));
return PR_FAILURE;
}
- return PR_SUCCESS;
+ PR_ASSERT(NULL == ol_bind_lock);
+ if ((ol_bind_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock bind_lock failed %d:%s\n",
+ errorCode, slapd_pr_strerror(errorCode));
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
}
#endif
@@ -145,7 +159,16 @@ void
slapi_ldap_unbind( LDAP *ld )
{
if ( ld != NULL ) {
+#if defined(USE_OPENLDAP)
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_unbind",
+ "Could not perform internal ol_init init\n");
+ return;
+ }
+#endif
+ BIND_LOCK;
ldap_unbind_ext( ld, NULL, NULL );
+ BIND_UNLOCK;
}
}
@@ -1031,11 +1054,22 @@ slapi_ldap_bind(
ldap_controls_free(clientctrls);
ldap_set_option(ld, LDAP_OPT_CLIENT_CONTROLS, NULL);
+#if defined(USE_OPENLDAP)
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
+ "Could not perform internal ol_init init\n");
+ rc = -1;
+ goto done;
+ }
+#endif
+
if ((secure > 0) && mech && !strcmp(mech, LDAP_SASL_EXTERNAL)) {
#if defined(USE_OPENLDAP)
/* we already set up a tls context in slapi_ldap_init_ext() - this will
free those old settings and context and create a new one */
+ PR_Lock(ol_bind_lock);
rc = setup_ol_tls_conn(ld, 1);
+ PR_Unlock(ol_bind_lock);
#else
/* SSL connections will use the server's security context
and cert for client auth */
@@ -1060,7 +1094,9 @@ slapi_ldap_bind(
}
if (secure == 2) { /* send start tls */
+ BIND_LOCK;
rc = ldap_start_tls_s(ld, NULL /* serverctrls?? */, NULL);
+ BIND_UNLOCK;
if (LDAP_SUCCESS != rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
"Error: could not send startTLS request: "
@@ -1082,8 +1118,11 @@ slapi_ldap_bind(
"attempting %s bind with id [%s] creds [%s]\n",
mech ? mech : "SIMPLE",
bindid, creds);
- if ((rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls,
- NULL /* clientctrls */, &mymsgid))) {
+ BIND_LOCK;
+ rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls,
+ NULL /* clientctrls */, &mymsgid);
+ BIND_UNLOCK;
+ if (rc) {
char *myhostname = NULL;
char *copy = NULL;
char *ptr = NULL;
@@ -1139,7 +1178,9 @@ slapi_ldap_bind(
/* take the one provided by the caller. It should be the one defined in the protocol */
bind_timeout = timeout;
}
+ BIND_LOCK;
rc = ldap_result(ld, mymsgid, LDAP_MSG_ALL, bind_timeout, &result);
+ BIND_UNLOCK;
if (-1 == rc) { /* error */
rc = slapi_ldap_get_lderrno(ld, NULL, NULL);
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
@@ -1203,9 +1244,11 @@ slapi_ldap_bind(
ldap_set_option(ld, LDAP_OPT_X_SASL_SSF_MAX, &max_ssf);
}
#endif
+ BIND_LOCK;
rc = slapd_ldap_sasl_interactive_bind(ld, bindid, creds, mech,
serverctrls, returnedctrls,
msgidp);
+ BIND_UNLOCK;
if (LDAP_SUCCESS != rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
"Error: could not perform interactive bind for id "
--
1.7.1