Ian Kent 1cd346
autofs-5.1.1 - fix sasl connection concurrancy problem
Ian Kent 1cd346
Ian Kent 1cd346
From: Ian Kent <raven@themaw.net>
Ian Kent 1cd346
Ian Kent 1cd346
After using the contributed Cyrus SASL code in autofs for years I've
Ian Kent 1cd346
finally looked at the Cyrus SASL C API RFC only to find that the
Ian Kent 1cd346
library isn't thread safe unless a connection context per thread is
Ian Kent 1cd346
used, similar to the LDAP library.
Ian Kent 1cd346
Ian Kent 1cd346
To be fair this code originated prior to the threaded version of
Ian Kent 1cd346
autofs so it's my bad I didn't check.
Ian Kent 1cd346
Ian Kent 1cd346
But having seen this I have no choice but to make the sasl context
Ian Kent 1cd346
per thread not per autofs lookup context.
Ian Kent 1cd346
Ian Kent 1cd346
Also extend the mutual exclusion even further.
Ian Kent 1cd346
Ian Kent 1cd346
Signed-off-by: Ian Kent <raven@themaw.net>
Ian Kent 1cd346
---
Ian Kent 1cd346
 CHANGELOG             |    1 
Ian Kent 1cd346
 include/lookup_ldap.h |   16 +++-
Ian Kent 1cd346
 modules/cyrus-sasl.c  |   46 ++++++-----
Ian Kent 1cd346
 modules/lookup_ldap.c |  198 +++++++++++++++++++++++++------------------------
Ian Kent 1cd346
 4 files changed, 136 insertions(+), 125 deletions(-)
Ian Kent 1cd346
Ian Kent 1cd346
diff --git a/CHANGELOG b/CHANGELOG
Ian Kent 1cd346
index 83412a3..663b867 100644
Ian Kent 1cd346
--- a/CHANGELOG
Ian Kent 1cd346
+++ b/CHANGELOG
Ian Kent 1cd346
@@ -32,6 +32,7 @@
Ian Kent 1cd346
 - change time() to use monotonic_clock().
Ian Kent 1cd346
 - remove unused function elapsed().
Ian Kent 1cd346
 - fix unbind sasl external mech.
Ian Kent 1cd346
+- fix sasl connection concurrancy problem.
Ian Kent 1cd346
 
Ian Kent 1cd346
 21/04/2015 autofs-5.1.1
Ian Kent 1cd346
 =======================
Ian Kent 1cd346
diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
Ian Kent 1cd346
index be4bc1e..3a7aba7 100644
Ian Kent 1cd346
--- a/include/lookup_ldap.h
Ian Kent 1cd346
+++ b/include/lookup_ldap.h
Ian Kent 1cd346
@@ -34,6 +34,13 @@ struct ldap_searchdn {
Ian Kent 1cd346
 	struct ldap_searchdn *next;
Ian Kent 1cd346
 };
Ian Kent 1cd346
 
Ian Kent 1cd346
+struct ldap_conn {
Ian Kent 1cd346
+	LDAP *ldap;
Ian Kent 1cd346
+#ifdef WITH_SASL
Ian Kent 1cd346
+	sasl_conn_t *sasl_conn;
Ian Kent 1cd346
+#endif
Ian Kent 1cd346
+};
Ian Kent 1cd346
+
Ian Kent 1cd346
 struct lookup_context {
Ian Kent 1cd346
 	char *mapname;
Ian Kent 1cd346
 	unsigned int format;
Ian Kent 1cd346
@@ -86,7 +93,6 @@ struct lookup_context {
Ian Kent 1cd346
 	/* Kerberos */
Ian Kent 1cd346
 	krb5_context krb5ctxt;
Ian Kent 1cd346
 	krb5_ccache  krb5_ccache;
Ian Kent 1cd346
-	sasl_conn_t  *sasl_conn;
Ian Kent 1cd346
 	/* SASL external */
Ian Kent 1cd346
 	char	     *extern_cert;
Ian Kent 1cd346
 	char	     *extern_key;
Ian Kent 1cd346
@@ -113,16 +119,16 @@ struct lookup_context {
Ian Kent 1cd346
 
Ian Kent 1cd346
 /* lookup_ldap.c */
Ian Kent 1cd346
 LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt);
Ian Kent 1cd346
-int unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt);
Ian Kent 1cd346
+int unbind_ldap_connection(unsigned logopt, struct ldap_conn *conn, struct lookup_context *ctxt);
Ian Kent 1cd346
 int authtype_requires_creds(const char *authtype);
Ian Kent 1cd346
 
Ian Kent 1cd346
 #ifdef WITH_SASL
Ian Kent 1cd346
 /* cyrus-sasl.c */
Ian Kent 1cd346
 int autofs_sasl_client_init(unsigned logopt);
Ian Kent 1cd346
 int autofs_sasl_init(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt);
Ian Kent 1cd346
-int autofs_sasl_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt);
Ian Kent 1cd346
-void autofs_sasl_unbind(LDAP *ldap, struct lookup_context *ctxt);
Ian Kent 1cd346
-void autofs_sasl_dispose(LDAP *ldap, struct lookup_context *ctxt);
Ian Kent 1cd346
+int autofs_sasl_bind(unsigned logopt, struct ldap_conn *conn, struct lookup_context *ctxt);
Ian Kent 1cd346
+void autofs_sasl_unbind(struct ldap_conn *conn, struct lookup_context *ctxt);
Ian Kent 1cd346
+void autofs_sasl_dispose(struct ldap_conn *conn, struct lookup_context *ctxt);
Ian Kent 1cd346
 void autofs_sasl_done(void);
Ian Kent 1cd346
 /* cyrus-sasl-extern */
Ian Kent 1cd346
 int do_sasl_extern(LDAP *ldap, struct lookup_context *ctxt);
Ian Kent 1cd346
diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c
Ian Kent 1cd346
index c5e72f7..11a1178 100644
Ian Kent 1cd346
--- a/modules/cyrus-sasl.c
Ian Kent 1cd346
+++ b/modules/cyrus-sasl.c
Ian Kent 1cd346
@@ -885,16 +885,19 @@ sasl_choose_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
  *  Routine called when unbinding an ldap connection.
Ian Kent 1cd346
  */
Ian Kent 1cd346
 void
Ian Kent 1cd346
-autofs_sasl_unbind(LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
+autofs_sasl_unbind(struct ldap_conn *conn, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	if (ctxt->sasl_mech && !strncmp(ctxt->sasl_mech, "EXTERNAL", 8)) {
Ian Kent 1cd346
-		ldap_unbind_s(ldap);
Ian Kent 1cd346
+		if (conn->ldap) {
Ian Kent 1cd346
+			ldap_unbind_s(conn->ldap);
Ian Kent 1cd346
+			conn->ldap = NULL;
Ian Kent 1cd346
+		}
Ian Kent 1cd346
 		return;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
-	if (ctxt->sasl_conn) {
Ian Kent 1cd346
-		sasl_dispose(&ctxt->sasl_conn);
Ian Kent 1cd346
-		ctxt->sasl_conn = NULL;
Ian Kent 1cd346
+	if (conn->sasl_conn) {
Ian Kent 1cd346
+		sasl_dispose(&conn->sasl_conn);
Ian Kent 1cd346
+		conn->sasl_conn = NULL;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
@@ -908,13 +911,10 @@ autofs_sasl_unbind(LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
  * -1  -  Failure
Ian Kent 1cd346
  */
Ian Kent 1cd346
 int
Ian Kent 1cd346
-autofs_sasl_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
+autofs_sasl_bind(unsigned logopt,
Ian Kent 1cd346
+		 struct ldap_conn *conn, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
-	sasl_conn_t *conn = NULL;
Ian Kent 1cd346
-
Ian Kent 1cd346
-	/* If we already have a connection use it */
Ian Kent 1cd346
-	if (ctxt->sasl_conn)
Ian Kent 1cd346
-		return 0;
Ian Kent 1cd346
+	sasl_conn_t *sasl_conn = NULL;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	if (ctxt->sasl_mech && !strncmp(ctxt->sasl_mech, "EXTERNAL", 8)) {
Ian Kent 1cd346
 		int result;
Ian Kent 1cd346
@@ -923,7 +923,7 @@ autofs_sasl_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
 		      "Attempting sasl bind with mechanism %s",
Ian Kent 1cd346
 		      ctxt->sasl_mech);
Ian Kent 1cd346
 
Ian Kent 1cd346
-		result = do_sasl_extern(ldap, ctxt);
Ian Kent 1cd346
+		result = do_sasl_extern(conn->ldap, ctxt);
Ian Kent 1cd346
 		if (result)
Ian Kent 1cd346
 			debug(logopt,
Ian Kent 1cd346
 			      "Failed to authenticate with mech %s",
Ian Kent 1cd346
@@ -953,14 +953,16 @@ autofs_sasl_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
 	 *  auth mechanism.
Ian Kent 1cd346
 	 */
Ian Kent 1cd346
 	if (ctxt->sasl_mech)
Ian Kent 1cd346
-		conn = sasl_bind_mech(logopt, ldap, ctxt, ctxt->sasl_mech);
Ian Kent 1cd346
+		sasl_conn = sasl_bind_mech(logopt,
Ian Kent 1cd346
+					   conn->ldap, ctxt, ctxt->sasl_mech);
Ian Kent 1cd346
 	else
Ian Kent 1cd346
-		conn = sasl_choose_mech(logopt, ldap, ctxt);
Ian Kent 1cd346
+		sasl_conn = sasl_choose_mech(logopt, conn->ldap, ctxt);
Ian Kent 1cd346
 
Ian Kent 1cd346
 	if (!conn)
Ian Kent 1cd346
 		return -1;
Ian Kent 1cd346
 
Ian Kent 1cd346
-	ctxt->sasl_conn = conn;
Ian Kent 1cd346
+	conn->sasl_conn = sasl_conn;
Ian Kent 1cd346
+
Ian Kent 1cd346
 	return 0;
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
@@ -968,19 +970,21 @@ autofs_sasl_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
  *  Destructor routine.  This should be called when finished with an ldap
Ian Kent 1cd346
  *  session.
Ian Kent 1cd346
  */
Ian Kent 1cd346
-void autofs_sasl_dispose(LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
+void autofs_sasl_dispose(struct ldap_conn *conn, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	int status, ret;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	if (ctxt->sasl_mech && !strncmp(ctxt->sasl_mech, "EXTERNAL", 8)) {
Ian Kent 1cd346
-		if (ldap)
Ian Kent 1cd346
-			ldap_unbind_s(ldap);
Ian Kent 1cd346
+		if (conn && conn->ldap) {
Ian Kent 1cd346
+			ldap_unbind_s(conn->ldap);
Ian Kent 1cd346
+			conn->ldap = NULL;
Ian Kent 1cd346
+		}
Ian Kent 1cd346
 		return;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
-	if (ctxt->sasl_conn) {
Ian Kent 1cd346
-		sasl_dispose(&ctxt->sasl_conn);
Ian Kent 1cd346
-		ctxt->sasl_conn = NULL;
Ian Kent 1cd346
+	if (conn && conn->sasl_conn) {
Ian Kent 1cd346
+		sasl_dispose(&conn->sasl_conn);
Ian Kent 1cd346
+		conn->sasl_conn = NULL;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
 	if (ctxt->kinit_successful) {
Ian Kent 1cd346
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
Ian Kent 1cd346
index 7f50c34..959890a 100644
Ian Kent 1cd346
--- a/modules/lookup_ldap.c
Ian Kent 1cd346
+++ b/modules/lookup_ldap.c
Ian Kent 1cd346
@@ -214,7 +214,9 @@ int bind_ldap_simple(unsigned logopt, LDAP *ldap, const char *uri, struct lookup
Ian Kent 1cd346
 	return 0;
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
-int __unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
+int __unbind_ldap_connection(unsigned logopt,
Ian Kent 1cd346
+			     struct ldap_conn *conn,
Ian Kent 1cd346
+			     struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	int rv = LDAP_SUCCESS;
Ian Kent 1cd346
 
Ian Kent 1cd346
@@ -222,30 +224,35 @@ int __unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context
Ian Kent 1cd346
 		ctxt->use_tls = LDAP_TLS_INIT;
Ian Kent 1cd346
 #ifdef WITH_SASL
Ian Kent 1cd346
 	if (ctxt->auth_required & LDAP_NEED_AUTH)
Ian Kent 1cd346
-		autofs_sasl_unbind(ldap, ctxt);
Ian Kent 1cd346
-	else
Ian Kent 1cd346
-		rv = ldap_unbind_ext(ldap, NULL, NULL);
Ian Kent 1cd346
-#else
Ian Kent 1cd346
-	rv = ldap_unbind_ext(ldap, NULL, NULL);
Ian Kent 1cd346
+		autofs_sasl_unbind(conn, ctxt);
Ian Kent 1cd346
+	/* No, sasl_dispose does not release the ldap connection
Ian Kent 1cd346
+	 * unless it's using sasl EXTERNAL
Ian Kent 1cd346
+	 */
Ian Kent 1cd346
 #endif
Ian Kent 1cd346
+	if (conn->ldap) {
Ian Kent 1cd346
+		rv = ldap_unbind_ext(conn->ldap, NULL, NULL);
Ian Kent 1cd346
+		conn->ldap = NULL;
Ian Kent 1cd346
+	}
Ian Kent 1cd346
 	if (rv != LDAP_SUCCESS)
Ian Kent 1cd346
 		error(logopt, "unbind failed: %s", ldap_err2string(rv));
Ian Kent 1cd346
 
Ian Kent 1cd346
 	return rv;
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
-int unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
+int unbind_ldap_connection(unsigned logopt,
Ian Kent 1cd346
+			   struct ldap_conn *conn,
Ian Kent 1cd346
+			   struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	int rv;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	ldapinit_mutex_lock();
Ian Kent 1cd346
-	rv = __unbind_ldap_connection(logopt, ldap, ctxt);
Ian Kent 1cd346
+	rv = __unbind_ldap_connection(logopt, conn, ctxt);
Ian Kent 1cd346
 	ldapinit_mutex_unlock();
Ian Kent 1cd346
 
Ian Kent 1cd346
 	return rv;
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
-LDAP *__init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt)
Ian Kent 1cd346
+LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	LDAP *ldap = NULL;
Ian Kent 1cd346
 	struct timeval timeout     = { ctxt->timeout, 0 };
Ian Kent 1cd346
@@ -313,7 +320,7 @@ LDAP *__init_ldap_connection(unsigned logopt, const char *uri, struct lookup_con
Ian Kent 1cd346
 				return NULL;
Ian Kent 1cd346
 			}
Ian Kent 1cd346
 			ctxt->use_tls = LDAP_TLS_DONT_USE;
Ian Kent 1cd346
-			ldap = __init_ldap_connection(logopt, uri, ctxt);
Ian Kent 1cd346
+			ldap = init_ldap_connection(logopt, uri, ctxt);
Ian Kent 1cd346
 			if (ldap)
Ian Kent 1cd346
 				ctxt->use_tls = LDAP_TLS_INIT;
Ian Kent 1cd346
 			return ldap;
Ian Kent 1cd346
@@ -324,17 +331,6 @@ LDAP *__init_ldap_connection(unsigned logopt, const char *uri, struct lookup_con
Ian Kent 1cd346
 	return ldap;
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
-LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt)
Ian Kent 1cd346
-{
Ian Kent 1cd346
-	LDAP *ldap;
Ian Kent 1cd346
-
Ian Kent 1cd346
-	ldapinit_mutex_lock();
Ian Kent 1cd346
-	ldap = __init_ldap_connection(logopt, uri, ctxt);
Ian Kent 1cd346
-	ldapinit_mutex_unlock();
Ian Kent 1cd346
-
Ian Kent 1cd346
-	return ldap;
Ian Kent 1cd346
-}
Ian Kent 1cd346
-
Ian Kent 1cd346
 static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	char buf[MAX_ERR_BUF];
Ian Kent 1cd346
@@ -574,33 +570,32 @@ static int find_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctx
Ian Kent 1cd346
 	return 0;
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
-static int do_bind(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_context *ctxt)
Ian Kent 1cd346
+static int do_bind(unsigned logopt, struct ldap_conn *conn,
Ian Kent 1cd346
+		   const char *uri, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	char *host = NULL, *nhost;
Ian Kent 1cd346
 	int rv;
Ian Kent 1cd346
 
Ian Kent 1cd346
-	ldapinit_mutex_lock();
Ian Kent 1cd346
 #ifdef WITH_SASL
Ian Kent 1cd346
 	debug(logopt, MODPREFIX "auth_required: %d, sasl_mech %s",
Ian Kent 1cd346
 	      ctxt->auth_required, ctxt->sasl_mech);
Ian Kent 1cd346
 
Ian Kent 1cd346
 	if (ctxt->auth_required & LDAP_NEED_AUTH) {
Ian Kent 1cd346
-		rv = autofs_sasl_bind(logopt, ldap, ctxt);
Ian Kent 1cd346
+		rv = autofs_sasl_bind(logopt, conn, ctxt);
Ian Kent 1cd346
 		debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv);
Ian Kent 1cd346
 	} else {
Ian Kent 1cd346
-		rv = bind_ldap_simple(logopt, ldap, uri, ctxt);
Ian Kent 1cd346
+		rv = bind_ldap_simple(logopt, conn->ldap, uri, ctxt);
Ian Kent 1cd346
 		debug(logopt, MODPREFIX "ldap simple bind returned %d", rv);
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 #else
Ian Kent 1cd346
-	rv = bind_ldap_simple(logopt, ldap, uri, ctxt);
Ian Kent 1cd346
+	rv = bind_ldap_simple(logopt, conn->ldap, uri, ctxt);
Ian Kent 1cd346
 	debug(logopt, MODPREFIX "ldap simple bind returned %d", rv);
Ian Kent 1cd346
 #endif
Ian Kent 1cd346
-	ldapinit_mutex_unlock();
Ian Kent 1cd346
 
Ian Kent 1cd346
 	if (rv != 0)
Ian Kent 1cd346
 		return 0;
Ian Kent 1cd346
 
Ian Kent 1cd346
-	rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host);
Ian Kent 1cd346
+	rv = ldap_get_option(conn->ldap, LDAP_OPT_HOST_NAME, &host);
Ian Kent 1cd346
         if (rv != LDAP_SUCCESS || !host) {
Ian Kent 1cd346
 		debug(logopt, "failed to get hostname for connection");
Ian Kent 1cd346
 		return 0;
Ian Kent 1cd346
@@ -634,15 +629,12 @@ static int do_bind(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_c
Ian Kent 1cd346
 	return 1;
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
-static int do_connect(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
+static int do_connect(unsigned logopt, struct ldap_conn *conn,
Ian Kent 1cd346
 		      const char *uri, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	char *cur_host = NULL;
Ian Kent 1cd346
-	LDAP *handle;
Ian Kent 1cd346
 	int ret = NSS_STATUS_SUCCESS;
Ian Kent 1cd346
 
Ian Kent 1cd346
-	*ldap = NULL;
Ian Kent 1cd346
-
Ian Kent 1cd346
 #ifdef WITH_SASL
Ian Kent 1cd346
 	if (ctxt->extern_cert && ctxt->extern_key) {
Ian Kent 1cd346
 		set_env(logopt, ENV_LDAPTLS_CERT, ctxt->extern_cert);
Ian Kent 1cd346
@@ -650,8 +642,8 @@ static int do_connect(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 #endif
Ian Kent 1cd346
 
Ian Kent 1cd346
-	handle = init_ldap_connection(logopt, uri, ctxt);
Ian Kent 1cd346
-	if (!handle) {
Ian Kent 1cd346
+	conn->ldap = init_ldap_connection(logopt, uri, ctxt);
Ian Kent 1cd346
+	if (!conn->ldap) {
Ian Kent 1cd346
 		ret = NSS_STATUS_UNAVAIL;
Ian Kent 1cd346
 		goto out;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
@@ -661,8 +653,8 @@ static int do_connect(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
 		cur_host = ctxt->cur_host;
Ian Kent 1cd346
 	uris_mutex_unlock(ctxt);
Ian Kent 1cd346
 
Ian Kent 1cd346
-	if (!do_bind(logopt, handle, uri, ctxt)) {
Ian Kent 1cd346
-		unbind_ldap_connection(logopt, handle, ctxt);
Ian Kent 1cd346
+	if (!do_bind(logopt, conn, uri, ctxt)) {
Ian Kent 1cd346
+		__unbind_ldap_connection(logopt, conn, ctxt);
Ian Kent 1cd346
 		ret = NSS_STATUS_UNAVAIL;
Ian Kent 1cd346
 		goto out;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
@@ -673,7 +665,6 @@ static int do_connect(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
 	uris_mutex_lock(ctxt);
Ian Kent 1cd346
 	if (ctxt->schema && ctxt->qdn && (cur_host == ctxt->cur_host)) {
Ian Kent 1cd346
 		uris_mutex_unlock(ctxt);
Ian Kent 1cd346
-		*ldap = handle;
Ian Kent 1cd346
 		goto out;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 	uris_mutex_unlock(ctxt);
Ian Kent 1cd346
@@ -684,8 +675,8 @@ static int do_connect(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
 	 * base dn for searches.
Ian Kent 1cd346
 	 */
Ian Kent 1cd346
 	if (!ctxt->schema) {
Ian Kent 1cd346
-		if (!find_query_dn(logopt, handle, ctxt)) {
Ian Kent 1cd346
-			unbind_ldap_connection(logopt, handle, ctxt);
Ian Kent 1cd346
+		if (!find_query_dn(logopt, conn->ldap, ctxt)) {
Ian Kent 1cd346
+			__unbind_ldap_connection(logopt, conn, ctxt);
Ian Kent 1cd346
 			ret = NSS_STATUS_NOTFOUND;
Ian Kent 1cd346
 			warn(logopt,
Ian Kent 1cd346
 			      MODPREFIX "failed to find valid query dn");
Ian Kent 1cd346
@@ -694,21 +685,21 @@ static int do_connect(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
 	} else if (!(ctxt->format & MAP_FLAG_FORMAT_AMD)) {
Ian Kent 1cd346
 		const char *class = ctxt->schema->map_class;
Ian Kent 1cd346
 		const char *key = ctxt->schema->map_attr;
Ian Kent 1cd346
-		if (!get_query_dn(logopt, handle, ctxt, class, key)) {
Ian Kent 1cd346
-			unbind_ldap_connection(logopt, handle, ctxt);
Ian Kent 1cd346
+		if (!get_query_dn(logopt, conn->ldap, ctxt, class, key)) {
Ian Kent 1cd346
+			__unbind_ldap_connection(logopt, conn, ctxt);
Ian Kent 1cd346
 			ret = NSS_STATUS_NOTFOUND;
Ian Kent 1cd346
 			error(logopt, MODPREFIX "failed to get query dn");
Ian Kent 1cd346
 			goto out;
Ian Kent 1cd346
 		}
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
-	*ldap = handle;
Ian Kent 1cd346
 out:
Ian Kent 1cd346
 	return ret;
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
 static unsigned long get_amd_timestamp(struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
+	struct ldap_conn conn;
Ian Kent 1cd346
 	LDAP *ldap;
Ian Kent 1cd346
 	LDAPMessage *result = NULL, *e;
Ian Kent 1cd346
 	char *query;
Ian Kent 1cd346
@@ -719,9 +710,11 @@ static unsigned long get_amd_timestamp(struct lookup_context *ctxt)
Ian Kent 1cd346
 	unsigned long timestamp = 0;
Ian Kent 1cd346
 	int rv, l, ql;
Ian Kent 1cd346
 
Ian Kent 1cd346
-	rv = do_connect(LOGOPT_ANY, &ldap, ctxt->server, ctxt);
Ian Kent 1cd346
+	memset(&conn, 0, sizeof(struct ldap_conn));
Ian Kent 1cd346
+	rv = do_connect(LOGOPT_ANY, &conn, ctxt->server, ctxt);
Ian Kent 1cd346
 	if (rv != NSS_STATUS_SUCCESS)
Ian Kent 1cd346
 		return 0;
Ian Kent 1cd346
+	ldap = conn.ldap;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	map = amd_timestamp.map_attr;
Ian Kent 1cd346
 	class = amd_timestamp.entry_class;
Ian Kent 1cd346
@@ -758,7 +751,7 @@ static unsigned long get_amd_timestamp(struct lookup_context *ctxt)
Ian Kent 1cd346
 	rv = ldap_search_s(ldap, ctxt->base, scope, query, attrs, 0, &result);
Ian Kent 1cd346
 	if ((rv != LDAP_SUCCESS) || !result) {
Ian Kent 1cd346
 		crit(LOGOPT_ANY, MODPREFIX "timestamp query failed %s", query);
Ian Kent 1cd346
-		unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt);
Ian Kent 1cd346
+		unbind_ldap_connection(LOGOPT_ANY, &conn, ctxt);
Ian Kent 1cd346
 		if (result)
Ian Kent 1cd346
 			ldap_msgfree(result);
Ian Kent 1cd346
 		free(query);
Ian Kent 1cd346
@@ -770,7 +763,7 @@ static unsigned long get_amd_timestamp(struct lookup_context *ctxt)
Ian Kent 1cd346
 		debug(LOGOPT_ANY,
Ian Kent 1cd346
 		     MODPREFIX "got answer, but no entry for timestamp");
Ian Kent 1cd346
 		ldap_msgfree(result);
Ian Kent 1cd346
-		unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt);
Ian Kent 1cd346
+		unbind_ldap_connection(LOGOPT_ANY, &conn, ctxt);
Ian Kent 1cd346
 		free(query);
Ian Kent 1cd346
 		return CHE_MISSING;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
@@ -821,18 +814,18 @@ next:
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
 	ldap_msgfree(result);
Ian Kent 1cd346
-	unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt);
Ian Kent 1cd346
+	unbind_ldap_connection(LOGOPT_ANY, &conn, ctxt);
Ian Kent 1cd346
 	free(query);
Ian Kent 1cd346
 
Ian Kent 1cd346
 	return timestamp;
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
-static int connect_to_server(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
+static int connect_to_server(unsigned logopt, struct ldap_conn *conn,
Ian Kent 1cd346
 			     const char *uri, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	int ret;
Ian Kent 1cd346
 
Ian Kent 1cd346
-	ret = do_connect(logopt, ldap, uri, ctxt);
Ian Kent 1cd346
+	ret = do_connect(logopt, conn, uri, ctxt);
Ian Kent 1cd346
 	if (ret != NSS_STATUS_SUCCESS) {
Ian Kent 1cd346
 		warn(logopt,
Ian Kent 1cd346
 		     MODPREFIX "couldn't connect to server %s",
Ian Kent 1cd346
@@ -842,7 +835,7 @@ static int connect_to_server(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
 	return ret;
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
-static int find_dc_server(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
+static int find_dc_server(unsigned logopt, struct ldap_conn *conn,
Ian Kent 1cd346
 			  const char *uri, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	char *str, *tok, *ptr = NULL;
Ian Kent 1cd346
@@ -858,7 +851,7 @@ static int find_dc_server(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
 		int rv;
Ian Kent 1cd346
 
Ian Kent 1cd346
 		debug(logopt, "trying server uri %s", this);
Ian Kent 1cd346
-		rv = connect_to_server(logopt, ldap, this, ctxt);
Ian Kent 1cd346
+		rv = connect_to_server(logopt, conn, this, ctxt);
Ian Kent 1cd346
 		if (rv == NSS_STATUS_SUCCESS) {
Ian Kent 1cd346
 			info(logopt, "connected to uri %s", this);
Ian Kent 1cd346
 			free(str);
Ian Kent 1cd346
@@ -875,7 +868,7 @@ static int find_dc_server(unsigned logopt, LDAP **ldap,
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
 static int find_server(unsigned logopt,
Ian Kent 1cd346
-		       LDAP **ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
+		       struct ldap_conn *conn, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	struct ldap_uri *this = NULL;
Ian Kent 1cd346
 	struct list_head *p, *first;
Ian Kent 1cd346
@@ -906,7 +899,7 @@ static int find_server(unsigned logopt,
Ian Kent 1cd346
 		if (!strstr(this->uri, ":///")) {
Ian Kent 1cd346
 			uri = strdup(this->uri);
Ian Kent 1cd346
 			debug(logopt, "trying server uri %s", uri);
Ian Kent 1cd346
-			rv = connect_to_server(logopt, ldap, uri, ctxt);
Ian Kent 1cd346
+			rv = connect_to_server(logopt, conn, uri, ctxt);
Ian Kent 1cd346
 			if (rv == NSS_STATUS_SUCCESS) {
Ian Kent 1cd346
 				ret = NSS_STATUS_SUCCESS;
Ian Kent 1cd346
 				info(logopt, "connected to uri %s", uri);
Ian Kent 1cd346
@@ -928,7 +921,7 @@ static int find_server(unsigned logopt,
Ian Kent 1cd346
 				dclist = tmp;
Ian Kent 1cd346
 				uri = strdup(dclist->uri);
Ian Kent 1cd346
 			}
Ian Kent 1cd346
-			rv = find_dc_server(logopt, ldap, uri, ctxt);
Ian Kent 1cd346
+			rv = find_dc_server(logopt, conn, uri, ctxt);
Ian Kent 1cd346
 			if (rv == NSS_STATUS_SUCCESS) {
Ian Kent 1cd346
 				ret = NSS_STATUS_SUCCESS;
Ian Kent 1cd346
 				free(uri);
Ian Kent 1cd346
@@ -947,7 +940,7 @@ static int find_server(unsigned logopt,
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
 	uris_mutex_lock(ctxt);
Ian Kent 1cd346
-	if (ldap)
Ian Kent 1cd346
+	if (conn->ldap)
Ian Kent 1cd346
 		ctxt->uri = this;
Ian Kent 1cd346
 	if (dclist) {
Ian Kent 1cd346
 		if (!ctxt->dclist)
Ian Kent 1cd346
@@ -965,37 +958,39 @@ static int find_server(unsigned logopt,
Ian Kent 1cd346
 }
Ian Kent 1cd346
 
Ian Kent 1cd346
 static int do_reconnect(unsigned logopt,
Ian Kent 1cd346
-			LDAP **ldap, struct lookup_context *ctxt)
Ian Kent 1cd346
+			struct ldap_conn *conn, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	int ret = NSS_STATUS_UNAVAIL;
Ian Kent 1cd346
 	int dcrv = NSS_STATUS_SUCCESS;
Ian Kent 1cd346
 	int rv = NSS_STATUS_SUCCESS;
Ian Kent 1cd346
 
Ian Kent 1cd346
+	ldapinit_mutex_lock();
Ian Kent 1cd346
 	if (ctxt->server || !ctxt->uris) {
Ian Kent 1cd346
-		ret = do_connect(logopt, ldap, ctxt->server, ctxt);
Ian Kent 1cd346
+		ret = do_connect(logopt, conn, ctxt->server, ctxt);
Ian Kent 1cd346
 #ifdef WITH_SASL
Ian Kent 1cd346
 		/* Dispose of the sasl authentication connection and try again. */
Ian Kent 1cd346
 		if (ctxt->auth_required & LDAP_NEED_AUTH &&
Ian Kent 1cd346
 		    ret != NSS_STATUS_SUCCESS && ret != NSS_STATUS_NOTFOUND) {
Ian Kent 1cd346
-			ldapinit_mutex_lock();
Ian Kent 1cd346
-			autofs_sasl_dispose(*ldap, ctxt);
Ian Kent 1cd346
-			ldapinit_mutex_unlock();
Ian Kent 1cd346
-			ret = connect_to_server(logopt, ldap,
Ian Kent 1cd346
+			autofs_sasl_dispose(conn, ctxt);
Ian Kent 1cd346
+			ret = connect_to_server(logopt, conn,
Ian Kent 1cd346
 						ctxt->server, ctxt);
Ian Kent 1cd346
 		}
Ian Kent 1cd346
 #endif
Ian Kent 1cd346
+		ldapinit_mutex_unlock();
Ian Kent 1cd346
 		return ret;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
 	if (ctxt->dclist) {
Ian Kent 1cd346
-		dcrv = find_dc_server(logopt, ldap, ctxt->dclist->uri, ctxt);
Ian Kent 1cd346
-		if (dcrv == NSS_STATUS_SUCCESS)
Ian Kent 1cd346
+		dcrv = find_dc_server(logopt, conn, ctxt->dclist->uri, ctxt);
Ian Kent 1cd346
+		if (dcrv == NSS_STATUS_SUCCESS) {
Ian Kent 1cd346
+			ldapinit_mutex_unlock();
Ian Kent 1cd346
 			return dcrv;
Ian Kent 1cd346
+		}
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
 	uris_mutex_lock(ctxt);
Ian Kent 1cd346
 	if (ctxt->dclist) {
Ian Kent 1cd346
-		if (!ldap || ctxt->dclist->expire < monotonic_time(NULL)) {
Ian Kent 1cd346
+		if (!conn->ldap || ctxt->dclist->expire < monotonic_time(NULL)) {
Ian Kent 1cd346
 			free_dclist(ctxt->dclist);
Ian Kent 1cd346
 			ctxt->dclist = NULL;
Ian Kent 1cd346
 		}
Ian Kent 1cd346
@@ -1009,7 +1004,7 @@ static int do_reconnect(unsigned logopt,
Ian Kent 1cd346
 	if (!ctxt->uri)
Ian Kent 1cd346
 		goto find_server;
Ian Kent 1cd346
 
Ian Kent 1cd346
-	rv = do_connect(logopt, ldap, ctxt->uri->uri, ctxt);
Ian Kent 1cd346
+	rv = do_connect(logopt, conn, ctxt->uri->uri, ctxt);
Ian Kent 1cd346
 #ifdef WITH_SASL
Ian Kent 1cd346
 	/*
Ian Kent 1cd346
 	 * Dispose of the sasl authentication connection and try the
Ian Kent 1cd346
@@ -1017,26 +1012,24 @@ static int do_reconnect(unsigned logopt,
Ian Kent 1cd346
 	 */
Ian Kent 1cd346
 	if (ctxt->auth_required & LDAP_NEED_AUTH &&
Ian Kent 1cd346
 	    rv != NSS_STATUS_SUCCESS && rv != NSS_STATUS_NOTFOUND) {
Ian Kent 1cd346
-		ldapinit_mutex_lock();
Ian Kent 1cd346
-		autofs_sasl_dispose(*ldap, ctxt);
Ian Kent 1cd346
-		ldapinit_mutex_unlock();
Ian Kent 1cd346
-		rv = connect_to_server(logopt, ldap, ctxt->uri->uri, ctxt);
Ian Kent 1cd346
+		autofs_sasl_dispose(conn, ctxt);
Ian Kent 1cd346
+		rv = connect_to_server(logopt, conn, ctxt->uri->uri, ctxt);
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 #endif
Ian Kent 1cd346
-	if (rv == NSS_STATUS_SUCCESS)
Ian Kent 1cd346
+	if (rv == NSS_STATUS_SUCCESS) {
Ian Kent 1cd346
+		ldapinit_mutex_unlock();
Ian Kent 1cd346
 		return rv;
Ian Kent 1cd346
+	}
Ian Kent 1cd346
 
Ian Kent 1cd346
 	/* Failed to connect, try to find a new server */
Ian Kent 1cd346
 
Ian Kent 1cd346
 find_server:
Ian Kent 1cd346
 #ifdef WITH_SASL
Ian Kent 1cd346
-	ldapinit_mutex_lock();
Ian Kent 1cd346
-	autofs_sasl_dispose(*ldap, ctxt);
Ian Kent 1cd346
-	ldapinit_mutex_unlock();
Ian Kent 1cd346
+	autofs_sasl_dispose(conn, ctxt);
Ian Kent 1cd346
 #endif
Ian Kent 1cd346
 
Ian Kent 1cd346
 	/* Current server failed, try the rest or dc connection */
Ian Kent 1cd346
-	ret = find_server(logopt, ldap, ctxt);
Ian Kent 1cd346
+	ret = find_server(logopt, conn, ctxt);
Ian Kent 1cd346
 	if (ret != NSS_STATUS_SUCCESS) {
Ian Kent 1cd346
 		if (ret == NSS_STATUS_NOTFOUND ||
Ian Kent 1cd346
 		    dcrv == NSS_STATUS_NOTFOUND ||
Ian Kent 1cd346
@@ -1044,6 +1037,7 @@ find_server:
Ian Kent 1cd346
 			ret = NSS_STATUS_NOTFOUND;
Ian Kent 1cd346
 		error(logopt, MODPREFIX "failed to find available server");
Ian Kent 1cd346
 	}
Ian Kent 1cd346
+	ldapinit_mutex_unlock();
Ian Kent 1cd346
 
Ian Kent 1cd346
 	return ret;
Ian Kent 1cd346
 }
Ian Kent 1cd346
@@ -1877,11 +1871,6 @@ int lookup_reinit(const char *mapfmt,
Ian Kent 1cd346
 
Ian Kent 1cd346
 	*context = new;
Ian Kent 1cd346
 
Ian Kent 1cd346
-#ifdef WITH_SASL
Ian Kent 1cd346
-	ldapinit_mutex_lock();
Ian Kent 1cd346
-	autofs_sasl_dispose(NULL, ctxt);
Ian Kent 1cd346
-	ldapinit_mutex_unlock();
Ian Kent 1cd346
-#endif
Ian Kent 1cd346
 	free_context(ctxt);
Ian Kent 1cd346
 
Ian Kent 1cd346
 	return 0;
Ian Kent 1cd346
@@ -1893,6 +1882,8 @@ int lookup_read_master(struct master *master, time_t age, void *context)
Ian Kent 1cd346
 	unsigned int timeout = master->default_timeout;
Ian Kent 1cd346
 	unsigned int logging = master->default_logging;
Ian Kent 1cd346
 	unsigned int logopt = master->logopt;
Ian Kent 1cd346
+	struct ldap_conn conn;
Ian Kent 1cd346
+	LDAP *ldap;
Ian Kent 1cd346
 	int rv, l, count;
Ian Kent 1cd346
 	char buf[MAX_ERR_BUF];
Ian Kent 1cd346
 	char parse_buf[PARSE_MAX_BUF];
Ian Kent 1cd346
@@ -1903,12 +1894,13 @@ int lookup_read_master(struct master *master, time_t age, void *context)
Ian Kent 1cd346
 	char **values = NULL;
Ian Kent 1cd346
 	char *attrs[3];
Ian Kent 1cd346
 	int scope = LDAP_SCOPE_SUBTREE;
Ian Kent 1cd346
-	LDAP *ldap = NULL;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	/* Initialize the LDAP context. */
Ian Kent 1cd346
-	rv = do_reconnect(logopt, &ldap, ctxt);
Ian Kent 1cd346
+	memset(&conn, 0, sizeof(struct ldap_conn));
Ian Kent 1cd346
+	rv = do_reconnect(logopt, &conn, ctxt);
Ian Kent 1cd346
 	if (rv)
Ian Kent 1cd346
 		return rv;
Ian Kent 1cd346
+	ldap = conn.ldap;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	class = ctxt->schema->entry_class;
Ian Kent 1cd346
 	entry = ctxt->schema->entry_attr;
Ian Kent 1cd346
@@ -1942,7 +1934,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
Ian Kent 1cd346
 	if ((rv != LDAP_SUCCESS) || !result) {
Ian Kent 1cd346
 		error(logopt, MODPREFIX "query failed for %s: %s",
Ian Kent 1cd346
 		      query, ldap_err2string(rv));
Ian Kent 1cd346
-		unbind_ldap_connection(logging, ldap, ctxt);
Ian Kent 1cd346
+		unbind_ldap_connection(logging, &conn, ctxt);
Ian Kent 1cd346
 		if (result)
Ian Kent 1cd346
 			ldap_msgfree(result);
Ian Kent 1cd346
 		free(query);
Ian Kent 1cd346
@@ -1955,7 +1947,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
Ian Kent 1cd346
 		      MODPREFIX "query succeeded, no matches for %s",
Ian Kent 1cd346
 		      query);
Ian Kent 1cd346
 		ldap_msgfree(result);
Ian Kent 1cd346
-		unbind_ldap_connection(logging, ldap, ctxt);
Ian Kent 1cd346
+		unbind_ldap_connection(logging, &conn, ctxt);
Ian Kent 1cd346
 		free(query);
Ian Kent 1cd346
 		return NSS_STATUS_NOTFOUND;
Ian Kent 1cd346
 	} else
Ian Kent 1cd346
@@ -2076,7 +2068,7 @@ next:
Ian Kent 1cd346
 
Ian Kent 1cd346
 	/* Clean up. */
Ian Kent 1cd346
 	ldap_msgfree(result);
Ian Kent 1cd346
-	unbind_ldap_connection(logopt, ldap, ctxt);
Ian Kent 1cd346
+	unbind_ldap_connection(logopt, &conn, ctxt);
Ian Kent 1cd346
 	free(query);
Ian Kent 1cd346
 
Ian Kent 1cd346
 	return NSS_STATUS_SUCCESS;
Ian Kent 1cd346
@@ -2796,6 +2788,7 @@ static int read_one_map(struct autofs_point *ap,
Ian Kent 1cd346
 			struct lookup_context *ctxt,
Ian Kent 1cd346
 			time_t age, int *result_ldap)
Ian Kent 1cd346
 {
Ian Kent 1cd346
+	struct ldap_conn conn;
Ian Kent 1cd346
 	struct ldap_search_params sp;
Ian Kent 1cd346
 	char buf[MAX_ERR_BUF];
Ian Kent 1cd346
 	char *class, *info, *entry;
Ian Kent 1cd346
@@ -2816,10 +2809,11 @@ static int read_one_map(struct autofs_point *ap,
Ian Kent 1cd346
 	sp.age = age;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	/* Initialize the LDAP context. */
Ian Kent 1cd346
-	sp.ldap = NULL;
Ian Kent 1cd346
-	rv = do_reconnect(ap->logopt, &sp.ldap, ctxt);
Ian Kent 1cd346
+	memset(&conn, 0, sizeof(struct ldap_conn));
Ian Kent 1cd346
+	rv = do_reconnect(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 	if (rv)
Ian Kent 1cd346
 		return rv;
Ian Kent 1cd346
+	sp.ldap = conn.ldap;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	class = ctxt->schema->entry_class;
Ian Kent 1cd346
 	entry = ctxt->schema->entry_attr;
Ian Kent 1cd346
@@ -2878,7 +2872,7 @@ static int read_one_map(struct autofs_point *ap,
Ian Kent 1cd346
 			if (sp.pageSize < 5) {
Ian Kent 1cd346
 				debug(ap->logopt, MODPREFIX
Ian Kent 1cd346
 				      "result size too small");
Ian Kent 1cd346
-				unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
Ian Kent 1cd346
+				unbind_ldap_connection(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 				*result_ldap = rv;
Ian Kent 1cd346
 				free(sp.query);
Ian Kent 1cd346
 				return NSS_STATUS_UNAVAIL;
Ian Kent 1cd346
@@ -2887,7 +2881,7 @@ static int read_one_map(struct autofs_point *ap,
Ian Kent 1cd346
 		}
Ian Kent 1cd346
 
Ian Kent 1cd346
 		if (rv != LDAP_SUCCESS || !sp.result) {
Ian Kent 1cd346
-			unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
Ian Kent 1cd346
+			unbind_ldap_connection(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 			*result_ldap = rv;
Ian Kent 1cd346
 			if (sp.result)
Ian Kent 1cd346
 				ldap_msgfree(sp.result);
Ian Kent 1cd346
@@ -2903,7 +2897,7 @@ static int read_one_map(struct autofs_point *ap,
Ian Kent 1cd346
 			rv = do_get_entries(&sp, source, ctxt);
Ian Kent 1cd346
 		if (rv != LDAP_SUCCESS) {
Ian Kent 1cd346
 			ldap_msgfree(sp.result);
Ian Kent 1cd346
-			unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
Ian Kent 1cd346
+			unbind_ldap_connection(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 			*result_ldap = rv;
Ian Kent 1cd346
 			if (sp.cookie)
Ian Kent 1cd346
 				ber_bvfree(sp.cookie);
Ian Kent 1cd346
@@ -2916,7 +2910,7 @@ static int read_one_map(struct autofs_point *ap,
Ian Kent 1cd346
 
Ian Kent 1cd346
 	debug(ap->logopt, MODPREFIX "done updating map");
Ian Kent 1cd346
 
Ian Kent 1cd346
-	unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
Ian Kent 1cd346
+	unbind_ldap_connection(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 
Ian Kent 1cd346
 	source->age = age;
Ian Kent 1cd346
 	if (sp.cookie)
Ian Kent 1cd346
@@ -2959,6 +2953,8 @@ static int lookup_one(struct autofs_point *ap, struct map_source *source,
Ian Kent 1cd346
 		char *qKey, int qKey_len, struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	struct mapent_cache *mc;
Ian Kent 1cd346
+	struct ldap_conn conn;
Ian Kent 1cd346
+	LDAP *ldap;
Ian Kent 1cd346
 	int rv, i, l, ql, count;
Ian Kent 1cd346
 	char buf[MAX_ERR_BUF];
Ian Kent 1cd346
 	time_t age = monotonic_time(NULL);
Ian Kent 1cd346
@@ -2971,7 +2967,6 @@ static int lookup_one(struct autofs_point *ap, struct map_source *source,
Ian Kent 1cd346
 	struct berval **bvValues;
Ian Kent 1cd346
 	char *attrs[3];
Ian Kent 1cd346
 	int scope = LDAP_SCOPE_SUBTREE;
Ian Kent 1cd346
-	LDAP *ldap = NULL;
Ian Kent 1cd346
 	struct mapent *we;
Ian Kent 1cd346
 	unsigned int wild = 0;
Ian Kent 1cd346
 	int ret = CHE_MISSING;
Ian Kent 1cd346
@@ -2984,11 +2979,13 @@ static int lookup_one(struct autofs_point *ap, struct map_source *source,
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
 	/* Initialize the LDAP context. */
Ian Kent 1cd346
-	rv = do_reconnect(ap->logopt, &ldap, ctxt);
Ian Kent 1cd346
+	memset(&conn, 0, sizeof(struct ldap_conn));
Ian Kent 1cd346
+	rv = do_reconnect(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 	if (rv == NSS_STATUS_UNAVAIL)
Ian Kent 1cd346
 		return CHE_UNAVAIL;
Ian Kent 1cd346
 	if (rv == NSS_STATUS_NOTFOUND)
Ian Kent 1cd346
 		return ret;
Ian Kent 1cd346
+	ldap = conn.ldap;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	class = ctxt->schema->entry_class;
Ian Kent 1cd346
 	entry = ctxt->schema->entry_attr;
Ian Kent 1cd346
@@ -3076,7 +3073,7 @@ static int lookup_one(struct autofs_point *ap, struct map_source *source,
Ian Kent 1cd346
 
Ian Kent 1cd346
 	if ((rv != LDAP_SUCCESS) || !result) {
Ian Kent 1cd346
 		crit(ap->logopt, MODPREFIX "query failed for %s", query);
Ian Kent 1cd346
-		unbind_ldap_connection(ap->logopt, ldap, ctxt);
Ian Kent 1cd346
+		unbind_ldap_connection(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 		if (result)
Ian Kent 1cd346
 			ldap_msgfree(result);
Ian Kent 1cd346
 		free(query);
Ian Kent 1cd346
@@ -3091,7 +3088,7 @@ static int lookup_one(struct autofs_point *ap, struct map_source *source,
Ian Kent 1cd346
 		debug(ap->logopt,
Ian Kent 1cd346
 		     MODPREFIX "got answer, but no entry for %s", query);
Ian Kent 1cd346
 		ldap_msgfree(result);
Ian Kent 1cd346
-		unbind_ldap_connection(ap->logopt, ldap, ctxt);
Ian Kent 1cd346
+		unbind_ldap_connection(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 		free(query);
Ian Kent 1cd346
 		return CHE_MISSING;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
@@ -3277,7 +3274,7 @@ next:
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
 	ldap_msgfree(result);
Ian Kent 1cd346
-	unbind_ldap_connection(ap->logopt, ldap, ctxt);
Ian Kent 1cd346
+	unbind_ldap_connection(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 
Ian Kent 1cd346
 	/* Failed to find wild entry, update cache if needed */
Ian Kent 1cd346
 	cache_writelock(mc);
Ian Kent 1cd346
@@ -3317,7 +3314,8 @@ static int lookup_one_amd(struct autofs_point *ap,
Ian Kent 1cd346
 			  struct lookup_context *ctxt)
Ian Kent 1cd346
 {
Ian Kent 1cd346
 	struct mapent_cache *mc = source->mc;
Ian Kent 1cd346
-	LDAP *ldap = NULL;
Ian Kent 1cd346
+	struct ldap_conn conn;
Ian Kent 1cd346
+	LDAP *ldap;
Ian Kent 1cd346
 	LDAPMessage *result = NULL, *e;
Ian Kent 1cd346
 	char *query;
Ian Kent 1cd346
 	int scope = LDAP_SCOPE_SUBTREE;
Ian Kent 1cd346
@@ -3336,11 +3334,13 @@ static int lookup_one_amd(struct autofs_point *ap,
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
 	/* Initialize the LDAP context. */
Ian Kent 1cd346
-	rv = do_reconnect(ap->logopt, &ldap, ctxt);
Ian Kent 1cd346
+	memset(&conn, 0, sizeof(struct ldap_conn));
Ian Kent 1cd346
+	rv = do_reconnect(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 	if (rv == NSS_STATUS_UNAVAIL)
Ian Kent 1cd346
 		return CHE_UNAVAIL;
Ian Kent 1cd346
 	if (rv == NSS_STATUS_NOTFOUND)
Ian Kent 1cd346
 		return ret;
Ian Kent 1cd346
+	ldap = conn.ldap;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	map = ctxt->schema->map_attr;
Ian Kent 1cd346
 	class = ctxt->schema->entry_class;
Ian Kent 1cd346
@@ -3382,7 +3382,7 @@ static int lookup_one_amd(struct autofs_point *ap,
Ian Kent 1cd346
 	rv = ldap_search_s(ldap, ctxt->base, scope, query, attrs, 0, &result);
Ian Kent 1cd346
 	if ((rv != LDAP_SUCCESS) || !result) {
Ian Kent 1cd346
 		crit(ap->logopt, MODPREFIX "query failed for %s", query);
Ian Kent 1cd346
-		unbind_ldap_connection(ap->logopt, ldap, ctxt);
Ian Kent 1cd346
+		unbind_ldap_connection(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 		if (result)
Ian Kent 1cd346
 			ldap_msgfree(result);
Ian Kent 1cd346
 		free(query);
Ian Kent 1cd346
@@ -3397,7 +3397,7 @@ static int lookup_one_amd(struct autofs_point *ap,
Ian Kent 1cd346
 		debug(ap->logopt,
Ian Kent 1cd346
 		     MODPREFIX "got answer, but no entry for %s", query);
Ian Kent 1cd346
 		ldap_msgfree(result);
Ian Kent 1cd346
-		unbind_ldap_connection(ap->logopt, ldap, ctxt);
Ian Kent 1cd346
+		unbind_ldap_connection(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 		free(query);
Ian Kent 1cd346
 		return CHE_MISSING;
Ian Kent 1cd346
 	}
Ian Kent 1cd346
@@ -3459,7 +3459,7 @@ next:
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
 	ldap_msgfree(result);
Ian Kent 1cd346
-	unbind_ldap_connection(ap->logopt, ldap, ctxt);
Ian Kent 1cd346
+	unbind_ldap_connection(ap->logopt, &conn, ctxt);
Ian Kent 1cd346
 	free(query);
Ian Kent 1cd346
 
Ian Kent 1cd346
 	return ret;