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