summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2012-06-12 20:29:26 -0400
committerStephen Gallagher <sgallagh@redhat.com>2012-06-13 10:01:12 -0400
commit2c62da337e31217d03f5bf0f768b574d166bb2fe (patch)
tree3742677f8ebcf242543590122494152c919b3f5f
parentd42d371c00c83ae44b9d1c3e88ecbe0e01b112e6 (diff)
downloadsssd-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.
-rw-r--r--src/man/sssd-ldap.5.xml14
-rw-r--r--src/providers/ldap/ldap_opts.h2
-rw-r--r--src/providers/ldap/sdap.c7
-rw-r--r--src/providers/ldap/sdap.h2
-rw-r--r--src/providers/ldap/sdap_async.c96
-rw-r--r--src/providers/ldap/sdap_async_groups.c1
-rw-r--r--src/providers/ldap/sdap_async_initgroups.c4
7 files changed, 120 insertions, 6 deletions
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index e04befdb..d20d84bc 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 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.
*/