summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap/sdap_async.c
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 /src/providers/ldap/sdap_async.c
parentd42d371c00c83ae44b9d1c3e88ecbe0e01b112e6 (diff)
downloadsssd-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/providers/ldap/sdap_async.c')
-rw-r--r--src/providers/ldap/sdap_async.c96
1 files changed, 95 insertions, 1 deletions
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",