diff options
author | Stephen Gallagher <sgallagh@redhat.com> | 2012-06-12 20:29:26 -0400 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2012-06-13 10:01:12 -0400 |
commit | 2c62da337e31217d03f5bf0f768b574d166bb2fe (patch) | |
tree | 3742677f8ebcf242543590122494152c919b3f5f /src/providers/ldap | |
parent | d42d371c00c83ae44b9d1c3e88ecbe0e01b112e6 (diff) | |
download | sssd-2c62da337e31217d03f5bf0f768b574d166bb2fe.tar.gz sssd-2c62da337e31217d03f5bf0f768b574d166bb2fe.tar.bz2 sssd-2c62da337e31217d03f5bf0f768b574d166bb2fe.zip |
LDAP: Auto-detect support for the ldap match rule
This patch extends the RootDSE lookup so that we will perform a
second request to test whether the match rule syntax can be used.
If both groups and initgroups are disabled in the configuration,
this lookup request can be skipped.
Diffstat (limited to 'src/providers/ldap')
-rw-r--r-- | src/providers/ldap/ldap_opts.h | 2 | ||||
-rw-r--r-- | src/providers/ldap/sdap.c | 7 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 2 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async.c | 96 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_groups.c | 1 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_initgroups.c | 4 |
6 files changed, 107 insertions, 5 deletions
diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h index 1c21bea9..2d08f7a6 100644 --- a/src/providers/ldap/ldap_opts.h +++ b/src/providers/ldap/ldap_opts.h @@ -103,7 +103,7 @@ struct dp_option default_basic_opts[] = { { "ldap_idmap_default_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_idmap_default_domain_sid", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_groups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, - { "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_TRUE, BOOL_FALSE }, DP_OPTION_TERMINATOR }; diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c index cb02f4a5..325825e2 100644 --- a/src/providers/ldap/sdap.c +++ b/src/providers/ldap/sdap.c @@ -179,8 +179,11 @@ int sdap_parse_entry(TALLOC_CTX *memctx, str = ldap_first_attribute(sh->ldap, sm->msg, &ber); if (!str) { ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); - DEBUG(1, ("Entry has no attributes [%d(%s)]!?\n", - lerrno, sss_ldap_err2string(lerrno))); + DEBUG(lerrno == LDAP_SUCCESS + ? SSSDBG_TRACE_INTERNAL + : SSSDBG_MINOR_FAILURE, + ("Entry has no attributes [%d(%s)]!?\n", + lerrno, sss_ldap_err2string(lerrno))); if (map) { ret = EINVAL; goto done; diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index a92305ff..253b08c5 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -386,6 +386,8 @@ struct sdap_options { struct sdap_search_base **sudo_search_bases; struct sdap_search_base **service_search_bases; struct sdap_search_base **autofs_search_bases; + + bool support_matching_rule; }; struct sdap_server_opts { diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c index 46f0215a..4b286922 100644 --- a/src/providers/ldap/sdap_async.c +++ b/src/providers/ldap/sdap_async.c @@ -836,6 +836,7 @@ struct sdap_get_rootdse_state { }; static void sdap_get_rootdse_done(struct tevent_req *subreq); +static void sdap_get_matching_rule_done(struct tevent_req *subreq); struct tevent_req *sdap_get_rootdse_send(TALLOC_CTX *memctx, struct tevent_context *ev, @@ -883,6 +884,11 @@ struct tevent_req *sdap_get_rootdse_send(TALLOC_CTX *memctx, return req; } +/* This is not a real attribute, it's just there to avoid + * actually pulling real data down, to save bandwidth + */ +#define SDAP_MATCHING_RULE_TEST_ATTR "sssmatchingruletest" + static void sdap_get_rootdse_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, @@ -892,6 +898,8 @@ static void sdap_get_rootdse_done(struct tevent_req *subreq) struct sysdb_attrs **results; size_t num_results; int ret; + const char *filter; + const char *attrs[] = { SDAP_MATCHING_RULE_TEST_ATTR, NULL }; ret = sdap_get_generic_recv(subreq, state, &num_results, &results); talloc_zfree(subreq); @@ -917,7 +925,81 @@ static void sdap_get_rootdse_done(struct tevent_req *subreq) state->rootdse = talloc_steal(state, results[0]); talloc_zfree(results); - DEBUG(9, ("Got rootdse\n")); + DEBUG(SSSDBG_TRACE_INTERNAL, ("Got rootdse\n")); + + /* Auto-detect the ldap matching rule if requested */ + if ((!dp_opt_get_bool(state->opts->basic, + SDAP_AD_MATCHING_RULE_INITGROUPS)) + && !dp_opt_get_bool(state->opts->basic, + SDAP_AD_MATCHING_RULE_GROUPS)) { + /* This feature is disabled for both groups + * and initgroups. Skip the auto-detection + * lookup. + */ + DEBUG(SSSDBG_TRACE_INTERNAL, + ("Skipping auto-detection of match rule\n")); + tevent_req_done(req); + return; + } + + DEBUG(SSSDBG_TRACE_INTERNAL, + ("Auto-detecting support for match rule\n")); + + /* Create a filter using the matching rule. It need not point + * at any valid data. We're only going to be looking for the + * error code. + */ + filter = "("SDAP_MATCHING_RULE_TEST_ATTR":" + SDAP_MATCHING_RULE_IN_CHAIN":=)"; + + /* Perform a trivial query with the matching rule in play. + * If it returns success, we know it is available. If it + * returns EIO, we know it isn't. + */ + subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh, + "", LDAP_SCOPE_BASE, filter, attrs, NULL, + 0, dp_opt_get_int(state->opts->basic, + SDAP_SEARCH_TIMEOUT), + false); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sdap_get_matching_rule_done, req); +} + +static void sdap_get_matching_rule_done(struct tevent_req *subreq) +{ + errno_t ret; + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sdap_get_rootdse_state *state = tevent_req_data(req, + struct sdap_get_rootdse_state); + size_t num_results; + struct sysdb_attrs **results; + + ret = sdap_get_generic_recv(subreq, state, &num_results, &results); + talloc_zfree(subreq); + if (ret == EOK) { + /* The search succeeded */ + state->opts->support_matching_rule = true; + } else if (ret == EIO) { + /* The search failed. Disable support for + * matching rule lookups. + */ + state->opts->support_matching_rule = false; + } else { + DEBUG(SSSDBG_MINOR_FAILURE, + ("Unexpected error while testing for matching rule support\n")); + tevent_req_error(req, ret); + return; + } + + DEBUG(SSSDBG_CONF_SETTINGS, + ("LDAP server %s the matching rule extension\n", + state->opts->support_matching_rule + ? "supports" + : "does not support")); tevent_req_done(req); } @@ -1292,6 +1374,18 @@ static void sdap_get_generic_ext_done(struct sdap_op *op, /* Try to return what we've got */ DEBUG(SSSDBG_MINOR_FAILURE, ("LDAP sizelimit was exceeded, returning incomplete data\n")); + } else if (result == LDAP_INAPPROPRIATE_MATCHING) { + /* This error should only occur when we're testing for + * specialized functionality like the ldap matching rule + * filter for Active Directory. Warn at a higher log + * level and return EIO. + */ + DEBUG(SSSDBG_TRACE_INTERNAL, + ("LDAP_INAPPROPRIATE_MATCHING: %s\n", + errmsg ? errmsg : "no errmsg set")); + ldap_memfree(errmsg); + tevent_req_error(req, EIO); + return; } else if (result != LDAP_SUCCESS && result != LDAP_NO_SUCH_OBJECT) { DEBUG(SSSDBG_OP_FAILURE, ("Unexpected result from ldap: %s(%d), %s\n", diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c index 8be5ff1d..720c3cc2 100644 --- a/src/providers/ldap/sdap_async_groups.c +++ b/src/providers/ldap/sdap_async_groups.c @@ -1513,6 +1513,7 @@ static void sdap_get_groups_process(struct tevent_req *subreq) */ if (!state->enumeration && (state->opts->schema_type != SDAP_SCHEMA_RFC2307) + && state->opts->support_matching_rule && dp_opt_get_bool(state->opts->basic, SDAP_AD_MATCHING_RULE_GROUPS)) { subreq = sdap_get_ad_match_rule_members_send( state, state->ev, state->opts, state->sh, diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index 2f146b01..8a837bcc 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -2665,7 +2665,9 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) return; } - if (dp_opt_get_bool(state->opts->basic, SDAP_AD_MATCHING_RULE_INITGROUPS)) { + if (state->opts->support_matching_rule + && dp_opt_get_bool(state->opts->basic, + SDAP_AD_MATCHING_RULE_INITGROUPS)) { /* Take advantage of AD's extensibleMatch filter to look up * all parent groups in a single request. */ |