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 | |
parent | d42d371c00c83ae44b9d1c3e88ecbe0e01b112e6 (diff) | |
download | sssd-2c62da337e31217d03f5bf0f768b574d166bb2fe.tar.gz sssd-2c62da337e31217d03f5bf0f768b574d166bb2fe.tar.xz 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')
-rw-r--r-- | src/man/sssd-ldap.5.xml | 14 | ||||
-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 |
7 files changed, 120 insertions, 6 deletions
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml index e04befdba..d20d84bca 100644 --- a/src/man/sssd-ldap.5.xml +++ b/src/man/sssd-ldap.5.xml @@ -845,6 +845,12 @@ performance increase on very complex nestings. </para> <para> + If this option is enabled, SSSD will use it if it + detects that the server supports it during initial + connection. So "True" here essentially means + "auto-detect". + </para> + <para> Note: This feature is currently known to work only with Active Directory 2008 R1 and later. See <ulink url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa746475%28v=vs.85%29.aspx"> @@ -866,13 +872,19 @@ dealing with complex or deep nested groups). </para> <para> + If this option is enabled, SSSD will use it if it + detects that the server supports it during initial + connection. So "True" here essentially means + "auto-detect". + </para> + <para> Note: This feature is currently known to work only with Active Directory 2008 R1 and later. See <ulink url="http://msdn.microsoft.com/en-us/library/windows/desktop/aa746475%28v=vs.85%29.aspx"> MSDN(TM) documentation</ulink> for more details. </para> <para> - Default: False + Default: True </para> </listitem> </varlistentry> diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h index 1c21bea9c..2d08f7a60 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 cb02f4a5b..325825e2d 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 a92305ff2..253b08c57 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 46f0215a8..4b2869220 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 8be5ff1d9..720c3cc29 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 2f146b016..8a837bcc5 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. */ |