diff --git a/CHANGELOG b/CHANGELOG index a9e509d..85af0ad 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -49,6 +49,7 @@ - fix incorrect read/write size of startup status token (Matthias Koenig). - fix off-by-one error for lookup of map keys exactly 255 characters long. - improve handling of server not available. +- fix LDAP_URI server selection. 18/06/2007 autofs-5.0.2 ----------------------- diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c index 18733f3..303b7f2 100644 --- a/modules/cyrus-sasl.c +++ b/modules/cyrus-sasl.c @@ -75,6 +75,7 @@ static const char *krb5ccval = "MEMORY:_autofstkt"; static pthread_mutex_t krb5cc_mutex = PTHREAD_MUTEX_INITIALIZER; static unsigned int krb5cc_in_use = 0; +static unsigned int init_callbacks = 1; static int sasl_log_func(void *, int, const char *); static int getpass_func(sasl_conn_t *, void *, int, sasl_secret_t **); static int getuser_func(void *, int, const char **, unsigned *); @@ -386,7 +387,7 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) debug(logopt, "initializing kerberos ticket: client principal %s ", - ctxt->client_princ ? "" : "autofsclient"); + ctxt->client_princ ? ctxt->client_princ : "autofsclient"); ret = krb5_init_context(&ctxt->krb5ctxt); if (ret) { @@ -599,8 +600,8 @@ sasl_bind_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const c /* OK and CONTINUE are the only non-fatal return codes here. */ if ((result != SASL_OK) && (result != SASL_CONTINUE)) { - error(logopt, "sasl_client start failed with error: %s", - sasl_errdetail(conn)); + warn(logopt, "sasl_client_start failed for %s", host); + debug(logopt, "sasl_client_start: %s", sasl_errdetail(conn)); ldap_memfree(host); sasl_dispose(&conn); return NULL; @@ -721,23 +722,30 @@ autofs_sasl_init(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) sasl_conn_t *conn; /* Start up Cyrus SASL--only needs to be done once. */ - if (sasl_client_init(callbacks) != SASL_OK) { + if (init_callbacks && sasl_client_init(callbacks) != SASL_OK) { error(logopt, "sasl_client_init failed"); return -1; } + init_callbacks = 0; sasl_auth_id = ctxt->user; sasl_auth_secret = ctxt->secret; /* - * If sasl_mech was not filled in, it means that there was no - * mechanism specified in the configuration file. Try to auto- - * select one. + * If LDAP_AUTH_AUTODETECT is set, it means that there was no + * mechanism specified in the configuration file or auto + * selection has been requested, so try to auto-select an + * auth mechanism. */ - if (ctxt->sasl_mech) + if (!(ctxt->auth_required & LDAP_AUTH_AUTODETECT)) conn = sasl_bind_mech(logopt, ldap, ctxt, ctxt->sasl_mech); - else + else { + if (ctxt->sasl_mech) { + free(ctxt->sasl_mech); + ctxt->sasl_mech = NULL; + } conn = sasl_choose_mech(logopt, ldap, ctxt); + } if (conn) { sasl_dispose(&conn); diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c index 7effbf1..93f0477 100644 --- a/modules/lookup_ldap.c +++ b/modules/lookup_ldap.c @@ -402,8 +402,7 @@ static int do_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) debug(logopt, MODPREFIX "auth_required: %d, sasl_mech %s", ctxt->auth_required, ctxt->sasl_mech); - if (ctxt->sasl_mech || - (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT))) { + if (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT)) { rv = autofs_sasl_bind(logopt, ldap, ctxt); debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv); } else { @@ -497,7 +496,7 @@ static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_c * Determine which authentication mechanism to use if we require * authentication. */ - if (ctxt->auth_required & LDAP_AUTH_REQUIRED) { + if (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT)) { ldap = auth_init(logopt, uri, ctxt); if (!ldap && ctxt->auth_required & LDAP_AUTH_AUTODETECT) info(logopt, @@ -510,6 +509,7 @@ static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_c if (!do_bind(logopt, ldap, ctxt)) { unbind_ldap_connection(logopt, ldap, ctxt); + autofs_sasl_done(ctxt); error(logopt, MODPREFIX "cannot bind to server"); return NULL; } @@ -541,6 +541,7 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt) while(p != ctxt->uri) { this = list_entry(p, struct ldap_uri, list); p = p->next; + debug(logopt, "trying server %s", this->uri); ldap = connect_to_server(logopt, this->uri, ctxt); if (ldap) { info(logopt, "connected to uri %s", this->uri); @@ -563,22 +564,23 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt) static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt) { + struct ldap_uri *this; LDAP *ldap; if (ctxt->server || !ctxt->uri) { ldap = do_connect(logopt, ctxt->server, ctxt); return ldap; - } else { - struct ldap_uri *this; - this = list_entry(ctxt->uri->next, struct ldap_uri, list); - ldap = do_connect(logopt, this->uri, ctxt); - if (ldap) - return ldap; - /* Failed to connect, put at end of list */ - list_del_init(&this->list); - list_add_tail(&this->list, ctxt->uri); } + this = list_entry(ctxt->uri->next, struct ldap_uri, list); + ldap = do_connect(logopt, this->uri, ctxt); + if (ldap) + return ldap; + + /* Failed to connect, put at end of list */ + list_del_init(&this->list); + list_add_tail(&this->list, ctxt->uri); + #ifdef WITH_SASL autofs_sasl_done(ctxt); #endif @@ -844,6 +846,8 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt) ctxt->tls_required = tls_required; ctxt->auth_required = auth_required; ctxt->sasl_mech = authtype; + if (!authtype && (auth_required & LDAP_AUTH_REQUIRED)) + ctxt->auth_required |= LDAP_AUTH_AUTODETECT; ctxt->user = user; ctxt->secret = secret; ctxt->client_princ = client_princ; @@ -886,16 +890,6 @@ static LDAP *auth_init(unsigned logopt, const char *uri, struct lookup_context * int ret; LDAP *ldap; - /* - * First, check to see if a preferred authentication method was - * specified by the user. parse_ldap_config will return error - * if the permissions on the file were incorrect, or if the - * specified authentication type is not valid. - */ - ret = parse_ldap_config(logopt, ctxt); - if (ret) - return NULL; - ldap = init_ldap_connection(logopt, uri, ctxt); if (!ldap) return NULL; @@ -909,10 +903,8 @@ static LDAP *auth_init(unsigned logopt, const char *uri, struct lookup_context * * the credential cache and the client and service principals. */ ret = autofs_sasl_init(logopt, ldap, ctxt); - if (ret) { - ctxt->sasl_mech = NULL; + if (ret) return NULL; - } return ldap; } @@ -1134,6 +1126,8 @@ static void free_context(struct lookup_context *ctxt) free(ctxt->user); if (ctxt->secret) free(ctxt->secret); + if (ctxt->client_princ) + free(ctxt->client_princ); if (ctxt->mapname) free(ctxt->mapname); if (ctxt->qdn) @@ -1184,6 +1178,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co struct lookup_context *ctxt; char buf[MAX_ERR_BUF]; LDAP *ldap = NULL; + int ret; *context = NULL; @@ -1224,6 +1219,20 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co } } +#ifdef WITH_SASL + /* + * First, check to see if a preferred authentication method was + * specified by the user. parse_ldap_config will return error + * if the permissions on the file were incorrect, or if the + * specified authentication type is not valid. + */ + ret = parse_ldap_config(LOGOPT_NONE, ctxt); + if (ret) { + free_context(ctxt); + return 1; + } +#endif + if (ctxt->server || !ctxt->uri) { ldap = connect_to_server(LOGOPT_NONE, ctxt->server, ctxt); if (!ldap) {