From 4709ff46db0dbe073aef061b796d2fd7adeaf18f Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: Mar 21 2013 16:58:05 +0000 Subject: LDAP: If deref search fails, try again without deref https://fedorahosted.org/sssd/ticket/1660 --- diff --git a/src/providers/ipa/ipa_hosts.c b/src/providers/ipa/ipa_hosts.c index 286e5e9..1323cac 100644 --- a/src/providers/ipa/ipa_hosts.c +++ b/src/providers/ipa/ipa_hosts.c @@ -254,6 +254,12 @@ ipa_host_info_done(struct tevent_req *subreq) return; } + if (!sdap_has_deref_support(state->sh, state->opts)) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Server does not support deref\n")); + tevent_req_error(req, EIO); + return; + } + subreq = sdap_deref_search_send(state, state->ev, state->opts, state->sh, host_dn, state->hostgroup_map[IPA_AT_HOSTGROUP_MEMBER_OF].name, diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 1235d1d..8dbf384 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -78,6 +78,7 @@ struct sdap_handle { /* Authentication ticket expiration time (if any) */ time_t expire_time; ber_int_t page_size; + bool disable_deref; struct sdap_fd_events *sdap_fd_events; diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c index 7ac32b9..afa2904 100644 --- a/src/providers/ldap/sdap_async.c +++ b/src/providers/ldap/sdap_async.c @@ -1384,6 +1384,10 @@ static void sdap_get_generic_ext_done(struct sdap_op *op, ldap_memfree(errmsg); tevent_req_error(req, EIO); return; + } else if (result == LDAP_UNAVAILABLE_CRITICAL_EXTENSION) { + ldap_memfree(errmsg); + tevent_req_error(req, ENOTSUP); + return; } else if (result != LDAP_SUCCESS && result != LDAP_NO_SUCH_OBJECT) { DEBUG(SSSDBG_OP_FAILURE, ("Unexpected result from ldap: %s(%d), %s\n", @@ -2054,6 +2058,7 @@ enum sdap_deref_type { }; struct sdap_deref_search_state { + struct sdap_handle *sh; size_t reply_count; struct sdap_deref_attrs **reply; enum sdap_deref_type deref_type; @@ -2080,6 +2085,7 @@ sdap_deref_search_send(TALLOC_CTX *memctx, req = tevent_req_create(memctx, &state, struct sdap_deref_search_state); if (!req) return NULL; + state->sh = sh; state->reply_count = 0; state->reply = NULL; @@ -2144,7 +2150,16 @@ static void sdap_deref_search_done(struct tevent_req *subreq) talloc_zfree(subreq); if (ret != EOK) { DEBUG(2, ("dereference processing failed [%d]: %s\n", ret, strerror(ret))); - sss_log(SSS_LOG_WARNING, "dereference processing failed : %s", strerror(ret)); + if (ret == ENOTSUP) { + sss_log(SSS_LOG_WARNING, + "LDAP server claims to support deref, but deref search failed. " + "Disabling deref for further requests. You can permanently " + "disable deref by setting ldap_deref_threshold to 0 in domain " + "configuration."); + state->sh->disable_deref = true; + } else { + sss_log(SSS_LOG_WARNING, "dereference processing failed : %s", strerror(ret)); + } tevent_req_error(req, ret); return; } @@ -2176,6 +2191,10 @@ bool sdap_has_deref_support(struct sdap_handle *sh, struct sdap_options *opts) int i; int deref_threshold; + if (sh->disable_deref) { + return false; + } + deref_threshold = dp_opt_get_int(opts->basic, SDAP_DEREF_THRESHOLD); if (deref_threshold == 0) { return false; diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c index 5bfa354..4d1ece8 100644 --- a/src/providers/ldap/sdap_async_groups.c +++ b/src/providers/ldap/sdap_async_groups.c @@ -2268,7 +2268,7 @@ sdap_nested_get_user_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, goto immediate; } else { DEBUG(SSSDBG_MINOR_FAILURE, ("Couldn't parse out user information " - "based on DN %s, falling back to an LDAP lookup\n")); + "based on DN %s, falling back to an LDAP lookup\n", user_dn)); } } @@ -3646,7 +3646,17 @@ static void sdap_nested_group_process_deref(struct tevent_req *subreq) &state->derefctx->num_results, &state->derefctx->deref_result); talloc_zfree(subreq); - if (ret != EOK && ret != ENOENT) { + if (ret == ENOTSUP) { + ret = sdap_nested_group_process_noderef(req); + if (ret != EAGAIN) { + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + } + return; + } else if (ret != EOK && ret != ENOENT) { tevent_req_error(req, ret); return; } else if (ret == ENOENT || state->derefctx->deref_result == NULL) { diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index 23be22f..5a6ba02 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -880,7 +880,17 @@ static void sdap_initgr_nested_deref_done(struct tevent_req *subreq) &num_results, &deref_result); talloc_zfree(subreq); - if (ret != EOK && ret != ENOENT) { + if (ret == ENOTSUP) { + ret = sdap_initgr_nested_noderef_search(req); + if (ret != EAGAIN) { + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + } + return; + } else if (ret != EOK && ret != ENOENT) { tevent_req_error(req, ret); return; } else if (ret == ENOENT || deref_result == NULL) {