Blame SOURCES/0101-AD-Use-the-right-sdap_domain-for-the-forest-root.patch

9f2ebf
From d56d41e76741f418e88e479b91193db3ee3f1688 Mon Sep 17 00:00:00 2001
9f2ebf
From: Jakub Hrozek <jhrozek@redhat.com>
9f2ebf
Date: Wed, 17 Jan 2018 21:59:24 +0100
9f2ebf
Subject: [PATCH 101/101] AD: Use the right sdap_domain for the forest root
9f2ebf
MIME-Version: 1.0
9f2ebf
Content-Type: text/plain; charset=UTF-8
9f2ebf
Content-Transfer-Encoding: 8bit
9f2ebf
9f2ebf
Each ad_id_ctx structure which represents a trusted AD domain contains a
9f2ebf
list of sdap_domain structures representing all the other domains. This
9f2ebf
is used to e.g. be able to reach another domain's ad_id_ctx and use its
9f2ebf
LDAP connection.
9f2ebf
9f2ebf
However, the sdap search call that was searching for trusted domains in
9f2ebf
the forest that the root domain knows about, was unconditionally using
9f2ebf
the first sdap_domain structure in the list linked from the root_domain's
9f2ebf
ad_id_ctx structure.
9f2ebf
9f2ebf
It should be noted that this search only happens in case the machine is
9f2ebf
joined to one of the non-root domains in the forest and searches the root
9f2ebf
domain explicitly.
9f2ebf
9f2ebf
In case sdap_domain structures linked from the ad_id_ctx representing
9f2ebf
the root domain were ordered so that the first sdap_domain in the list
9f2ebf
was representing a different domain than the one linked from the
9f2ebf
ad_id_ctx, the sdap search would have used a wrong search base derived
9f2ebf
from the unexpected sdap_domain which would result in a referral being
9f2ebf
returned.
9f2ebf
9f2ebf
This patch explicitly looks up the sdap_domain structure that
9f2ebf
corresponds to the root domain.
9f2ebf
9f2ebf
Resolves:
9f2ebf
https://pagure.io/SSSD/sssd/issue/3594
9f2ebf
9f2ebf
Reviewed-by: Sumit Bose <sbose@redhat.com>
9f2ebf
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
9f2ebf
(cherry picked from commit 9ac071272ce0152eb293d3181a5c12b395655521)
9f2ebf
---
9f2ebf
 src/providers/ad/ad_subdomains.c | 110 +++++++++++++++++++++++++++------------
9f2ebf
 1 file changed, 77 insertions(+), 33 deletions(-)
9f2ebf
9f2ebf
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
9f2ebf
index 1b9483a5dce937d6acdd813486a1e8c18210d35f..bd94ba8ea93679df8d01508b3d4d85217d9c1c87 100644
9f2ebf
--- a/src/providers/ad/ad_subdomains.c
9f2ebf
+++ b/src/providers/ad/ad_subdomains.c
9f2ebf
@@ -57,6 +57,71 @@
9f2ebf
 /* do not refresh more often than every 5 seconds for now */
9f2ebf
 #define AD_SUBDOMAIN_REFRESH_LIMIT 5
9f2ebf
 
9f2ebf
+static struct sss_domain_info *
9f2ebf
+ads_get_root_domain(struct be_ctx *be_ctx, struct sysdb_attrs *attrs)
9f2ebf
+{
9f2ebf
+    struct sss_domain_info *dom;
9f2ebf
+    const char *name;
9f2ebf
+    errno_t ret;
9f2ebf
+
9f2ebf
+    if (attrs == NULL) {
9f2ebf
+        /* Clients joined to the forest root directly don't even discover
9f2ebf
+         * the root domain, so the attrs are expected to be NULL in this
9f2ebf
+         * case
9f2ebf
+         */
9f2ebf
+        return be_ctx->domain;
9f2ebf
+    }
9f2ebf
+
9f2ebf
+    ret = sysdb_attrs_get_string(attrs, AD_AT_TRUST_PARTNER, &name);
9f2ebf
+    if (ret != EOK) {
9f2ebf
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
9f2ebf
+        return NULL;
9f2ebf
+    }
9f2ebf
+
9f2ebf
+    /* With a subsequent run, the root should already be known */
9f2ebf
+    for (dom = be_ctx->domain; dom != NULL;
9f2ebf
+         dom = get_next_domain(dom, SSS_GND_ALL_DOMAINS)) {
9f2ebf
+
9f2ebf
+        if (strcasecmp(dom->name, name) == 0) {
9f2ebf
+            /* The forest root is special, although it might be disabled for
9f2ebf
+             * general lookups we still want to try to get the domains in the
9f2ebf
+             * forest from a DC of the forest root */
9f2ebf
+            if (sss_domain_get_state(dom) == DOM_DISABLED
9f2ebf
+                    && !sss_domain_is_forest_root(dom)) {
9f2ebf
+                return NULL;
9f2ebf
+            }
9f2ebf
+            return dom;
9f2ebf
+        }
9f2ebf
+    }
9f2ebf
+
9f2ebf
+    return NULL;
9f2ebf
+}
9f2ebf
+
9f2ebf
+static struct sdap_domain *
9f2ebf
+ads_get_root_sdap_domain(struct be_ctx *be_ctx,
9f2ebf
+                         struct sdap_options *opts,
9f2ebf
+                         struct sysdb_attrs *attrs)
9f2ebf
+{
9f2ebf
+    struct sdap_domain *root_sdom;
9f2ebf
+    struct sss_domain_info *root_dom;
9f2ebf
+
9f2ebf
+    root_dom = ads_get_root_domain(be_ctx, attrs);
9f2ebf
+    if (root_dom == NULL) {
9f2ebf
+        DEBUG(SSSDBG_OP_FAILURE,
9f2ebf
+              "ads_get_root_domain did not find the domain\n");
9f2ebf
+        return NULL;
9f2ebf
+    }
9f2ebf
+
9f2ebf
+    root_sdom = sdap_domain_get(opts, root_dom);
9f2ebf
+    if (root_sdom == NULL) {
9f2ebf
+        DEBUG(SSSDBG_OP_FAILURE,
9f2ebf
+              "Failed to find sdap_domain for the root domain\n");
9f2ebf
+        return NULL;
9f2ebf
+    }
9f2ebf
+
9f2ebf
+    return root_sdom;
9f2ebf
+}
9f2ebf
+
9f2ebf
 static errno_t ad_get_enabled_domains(TALLOC_CTX *mem_ctx,
9f2ebf
                                       struct ad_id_ctx *ad_id_ctx,
9f2ebf
                                       const char *ad_domain,
9f2ebf
@@ -755,6 +820,7 @@ struct ad_get_slave_domain_state {
9f2ebf
     struct sdap_options *opts;
9f2ebf
     struct sdap_idmap_ctx *idmap_ctx;
9f2ebf
     struct sysdb_attrs *root_attrs;
9f2ebf
+    struct sdap_domain *root_sdom;
9f2ebf
     struct sdap_id_op *sdap_op;
9f2ebf
 };
9f2ebf
 
9f2ebf
@@ -786,6 +852,13 @@ ad_get_slave_domain_send(TALLOC_CTX *mem_ctx,
9f2ebf
     state->opts = root_id_ctx->sdap_id_ctx->opts;
9f2ebf
     state->idmap_ctx = root_id_ctx->sdap_id_ctx->opts->idmap_ctx;
9f2ebf
     state->root_attrs = root_attrs;
9f2ebf
+    state->root_sdom = ads_get_root_sdap_domain(state->be_ctx,
9f2ebf
+                                                state->opts,
9f2ebf
+                                                state->root_attrs);
9f2ebf
+    if (state->root_sdom == NULL) {
9f2ebf
+        ret = ERR_DOMAIN_NOT_FOUND;
9f2ebf
+        goto immediately;
9f2ebf
+    }
9f2ebf
 
9f2ebf
     state->sdap_op = sdap_id_op_create(state, root_id_ctx->ldap_ctx->conn_cache);
9f2ebf
     if (state->sdap_op == NULL) {
9f2ebf
@@ -861,7 +934,7 @@ static void ad_get_slave_domain_connect_done(struct tevent_req *subreq)
9f2ebf
 
9f2ebf
     subreq = sdap_search_bases_send(state, state->ev, state->opts,
9f2ebf
                                     sdap_id_op_handle(state->sdap_op),
9f2ebf
-                                    state->opts->sdom->search_bases,
9f2ebf
+                                    state->root_sdom->search_bases,
9f2ebf
                                     NULL, false, 0,
9f2ebf
                                     SLAVE_DOMAIN_FILTER, attrs);
9f2ebf
     if (subreq == NULL) {
9f2ebf
@@ -965,38 +1038,6 @@ static errno_t ad_get_slave_domain_recv(struct tevent_req *req)
9f2ebf
     return EOK;
9f2ebf
 }
9f2ebf
 
9f2ebf
-static struct sss_domain_info *
9f2ebf
-ads_get_root_domain(struct be_ctx *be_ctx, struct sysdb_attrs *attrs)
9f2ebf
-{
9f2ebf
-    struct sss_domain_info *dom;
9f2ebf
-    const char *name;
9f2ebf
-    errno_t ret;
9f2ebf
-
9f2ebf
-    ret = sysdb_attrs_get_string(attrs, AD_AT_TRUST_PARTNER, &name);
9f2ebf
-    if (ret != EOK) {
9f2ebf
-        DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
9f2ebf
-        return NULL;
9f2ebf
-    }
9f2ebf
-
9f2ebf
-    /* With a subsequent run, the root should already be known */
9f2ebf
-    for (dom = be_ctx->domain; dom != NULL;
9f2ebf
-         dom = get_next_domain(dom, SSS_GND_ALL_DOMAINS)) {
9f2ebf
-
9f2ebf
-        if (strcasecmp(dom->name, name) == 0) {
9f2ebf
-            /* The forest root is special, although it might be disabled for
9f2ebf
-             * general lookups we still want to try to get the domains in the
9f2ebf
-             * forest from a DC of the forest root */
9f2ebf
-            if (sss_domain_get_state(dom) == DOM_DISABLED
9f2ebf
-                    && !sss_domain_is_forest_root(dom)) {
9f2ebf
-                return NULL;
9f2ebf
-            }
9f2ebf
-            return dom;
9f2ebf
-        }
9f2ebf
-    }
9f2ebf
-
9f2ebf
-    return NULL;
9f2ebf
-}
9f2ebf
-
9f2ebf
 static struct ad_id_ctx *
9f2ebf
 ads_get_root_id_ctx(struct be_ctx *be_ctx,
9f2ebf
                     struct ad_id_ctx *ad_id_ctx,
9f2ebf
@@ -1416,6 +1457,9 @@ static void ad_subdomains_refresh_root_done(struct tevent_req *subreq)
9f2ebf
     req = tevent_req_callback_data(subreq, struct tevent_req);
9f2ebf
     state = tevent_req_data(req, struct ad_subdomains_refresh_state);
9f2ebf
 
9f2ebf
+    /* Note: For clients joined to the root domain, root_attrs is NULL,
9f2ebf
+     * see ad_get_root_domain_send()
9f2ebf
+     */
9f2ebf
     ret = ad_get_root_domain_recv(state, subreq, &root_attrs, &root_id_ctx);
9f2ebf
     talloc_zfree(subreq);
9f2ebf
     if (ret != EOK) {
9f2ebf
-- 
9f2ebf
2.14.3
9f2ebf