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.
829 lines
25 KiB
829 lines
25 KiB
7 years ago
|
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;
|