Blame SOURCES/0036-ad-check-forest-root-directly-if-not-present-on-loca.patch

836b22
From de90274339a8ea1efdfbb96a66da74547cd2ae7e Mon Sep 17 00:00:00 2001
836b22
From: Sumit Bose <sbose@redhat.com>
836b22
Date: Tue, 12 May 2020 16:55:32 +0200
836b22
Subject: [PATCH 36/36] ad: check forest root directly if not present on local
836b22
 DC
836b22
MIME-Version: 1.0
836b22
Content-Type: text/plain; charset=UTF-8
836b22
Content-Transfer-Encoding: 8bit
836b22
836b22
If the information about the forest root domain cannot be read from the
836b22
local domain-controller it is tried to read it from a DC of the forest
836b22
root directly.
836b22
836b22
Resolves: https://github.com/SSSD/sssd/issues/5151
836b22
836b22
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
836b22
(cherry picked from commit e25e1e9228a6108d8e94f2e99f3004e6cbfc3349)
836b22
836b22
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
836b22
---
836b22
 src/providers/ad/ad_subdomains.c | 184 +++++++++++++++++++++++++++----
836b22
 1 file changed, 164 insertions(+), 20 deletions(-)
836b22
836b22
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
836b22
index 003b06c16..ba4efe975 100644
836b22
--- a/src/providers/ad/ad_subdomains.c
836b22
+++ b/src/providers/ad/ad_subdomains.c
836b22
@@ -35,6 +35,10 @@
836b22
 #include <ndr.h>
836b22
 #include <ndr/ndr_nbt.h>
836b22
 
836b22
+/* Avoid that ldb_val is overwritten by data_blob.h */
836b22
+#undef ldb_val
836b22
+#include <ldb.h>
836b22
+
836b22
 /* Attributes of AD trusted domains */
836b22
 #define AD_AT_FLATNAME      "flatName"
836b22
 #define AD_AT_SID           "securityIdentifier"
836b22
@@ -1261,15 +1265,37 @@ ads_get_dom_id_ctx(struct be_ctx *be_ctx,
836b22
 
836b22
 struct ad_get_root_domain_state {
836b22
     struct ad_subdomains_ctx *sd_ctx;
836b22
+    struct tevent_context *ev;
836b22
     struct be_ctx *be_ctx;
836b22
     struct sdap_idmap_ctx *idmap_ctx;
836b22
     struct sdap_options *opts;
836b22
+    const char *domain;
836b22
+    const char *forest;
836b22
 
836b22
+    struct sysdb_attrs **reply;
836b22
+    size_t reply_count;
836b22
     struct ad_id_ctx *root_id_ctx;
836b22
     struct sysdb_attrs *root_domain_attrs;
836b22
 };
836b22
 
836b22
 static void ad_get_root_domain_done(struct tevent_req *subreq);
836b22
+static void ad_check_root_domain_done(struct tevent_req *subreq);
836b22
+static errno_t
836b22
+ad_get_root_domain_refresh(struct ad_get_root_domain_state *state);
836b22
+
836b22
+struct tevent_req *
836b22
+ad_check_domain_send(TALLOC_CTX *mem_ctx,
836b22
+                     struct tevent_context *ev,
836b22
+                     struct be_ctx *be_ctx,
836b22
+                     struct ad_id_ctx *ad_id_ctx,
836b22
+                     const char *dom_name,
836b22
+                     const char *parent_dom_name);
836b22
+errno_t ad_check_domain_recv(TALLOC_CTX *mem_ctx,
836b22
+                             struct tevent_req *req,
836b22
+                             char **_flat,
836b22
+                             char **_id,
836b22
+                             char **_site,
836b22
+                             char **_forest);
836b22
 
836b22
 static struct tevent_req *
836b22
 ad_get_root_domain_send(TALLOC_CTX *mem_ctx,
836b22
@@ -1308,6 +1334,9 @@ ad_get_root_domain_send(TALLOC_CTX *mem_ctx,
836b22
     state->opts = opts = sd_ctx->sdap_id_ctx->opts;
836b22
     state->be_ctx = sd_ctx->be_ctx;
836b22
     state->idmap_ctx = opts->idmap_ctx;
836b22
+    state->ev = ev;
836b22
+    state->domain = domain;
836b22
+    state->forest = forest;
836b22
 
836b22
     filter = talloc_asprintf(state, FOREST_ROOT_FILTER_FMT, forest);
836b22
     if (filter == NULL) {
836b22
@@ -1343,17 +1372,14 @@ static void ad_get_root_domain_done(struct tevent_req *subreq)
836b22
 {
836b22
     struct tevent_req *req;
836b22
     struct ad_get_root_domain_state *state;
836b22
-    struct sysdb_attrs **reply;
836b22
-    struct sss_domain_info *root_domain;
836b22
-    size_t reply_count;
836b22
-    bool has_changes;
836b22
     errno_t ret;
836b22
 
836b22
     req = tevent_req_callback_data(subreq, struct tevent_req);
836b22
     state = tevent_req_data(req, struct ad_get_root_domain_state);
836b22
 
836b22
-    ret = sdap_search_bases_return_first_recv(subreq, state, &reply_count,
836b22
-                                              &reply);
836b22
+    ret = sdap_search_bases_return_first_recv(subreq, state,
836b22
+                                              &state->reply_count,
836b22
+                                              &state->reply);
836b22
     talloc_zfree(subreq);
836b22
     if (ret != EOK) {
836b22
         DEBUG(SSSDBG_OP_FAILURE, "Unable to lookup forest root information "
836b22
@@ -1361,19 +1387,142 @@ static void ad_get_root_domain_done(struct tevent_req *subreq)
836b22
         goto done;
836b22
     }
836b22
 
836b22
-    if (reply_count == 0) {
836b22
-        DEBUG(SSSDBG_OP_FAILURE, "No information provided for root domain\n");
836b22
-        ret = ENOENT;
836b22
-        goto done;
836b22
-    } else if (reply_count > 1) {
836b22
+    if (state->reply_count == 0) {
836b22
+        DEBUG(SSSDBG_OP_FAILURE,
836b22
+              "No information provided for root domain, trying directly.\n");
836b22
+        subreq = ad_check_domain_send(state, state->ev, state->be_ctx,
836b22
+                                      state->sd_ctx->ad_id_ctx, state->forest,
836b22
+                                      state->domain);
836b22
+        if (subreq == NULL) {
836b22
+            DEBUG(SSSDBG_OP_FAILURE, "ad_check_domain_send() failed.\n");
836b22
+            ret = ENOMEM;
836b22
+            goto done;
836b22
+        }
836b22
+        tevent_req_set_callback(subreq, ad_check_root_domain_done, req);
836b22
+        return;
836b22
+    } else if (state->reply_count > 1) {
836b22
         DEBUG(SSSDBG_CRIT_FAILURE, "Multiple results for root domain search, "
836b22
               "domain list might be incomplete!\n");
836b22
         ret = ERR_MALFORMED_ENTRY;
836b22
         goto done;
836b22
     }
836b22
 
836b22
+    ret = ad_get_root_domain_refresh(state);
836b22
+    if (ret != EOK) {
836b22
+        DEBUG(SSSDBG_OP_FAILURE, "ad_get_root_domain_refresh() failed.\n");
836b22
+    }
836b22
+
836b22
+done:
836b22
+    if (ret != EOK) {
836b22
+        tevent_req_error(req, ret);
836b22
+        return;
836b22
+    }
836b22
+
836b22
+    tevent_req_done(req);
836b22
+}
836b22
+
836b22
+static void ad_check_root_domain_done(struct tevent_req *subreq)
836b22
+{
836b22
+    struct tevent_req *req;
836b22
+    struct ad_get_root_domain_state *state;
836b22
+    errno_t ret;
836b22
+    char *flat = NULL;
836b22
+    char *id = NULL;
836b22
+    enum idmap_error_code err;
836b22
+    struct ldb_val id_val;
836b22
+
836b22
+    req = tevent_req_callback_data(subreq, struct tevent_req);
836b22
+    state = tevent_req_data(req, struct ad_get_root_domain_state);
836b22
+
836b22
+    ret = ad_check_domain_recv(state, subreq, &flat, &id, NULL, NULL);
836b22
+    talloc_zfree(subreq);
836b22
+    if (ret != EOK) {
836b22
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to check forest root information "
836b22
+              "[%d]: %s\n", ret, sss_strerror(ret));
836b22
+        goto done;
836b22
+    }
836b22
+
836b22
+    if (flat == NULL) {
836b22
+        DEBUG(SSSDBG_CRIT_FAILURE,
836b22
+              "NetBIOS name of forest root not available.\n");
836b22
+        ret = EINVAL;
836b22
+        goto done;
836b22
+    }
836b22
+
836b22
+    if (id == NULL) {
836b22
+        DEBUG(SSSDBG_CRIT_FAILURE,
836b22
+              "Domain SID of forest root not available.\n");
836b22
+        ret = EINVAL;
836b22
+        goto done;
836b22
+    }
836b22
+
836b22
+    state->reply = talloc_array(state, struct sysdb_attrs *, 1);
836b22
+    if (state->reply == NULL) {
836b22
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_array() failed.\n");
836b22
+        ret = ENOMEM;
836b22
+        goto done;
836b22
+    }
836b22
+
836b22
+    state->reply[0] = sysdb_new_attrs(state->reply);
836b22
+    if (state->reply[0] == NULL) {
836b22
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs() failed.\n");
836b22
+        ret = ENOMEM;
836b22
+        goto done;
836b22
+    }
836b22
+
836b22
+    ret = sysdb_attrs_add_string(state->reply[0], AD_AT_FLATNAME, flat);
836b22
+    if (ret != EOK) {
836b22
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string() failed.\n");
836b22
+        goto done;
836b22
+    }
836b22
+
836b22
+    ret = sysdb_attrs_add_string(state->reply[0], AD_AT_TRUST_PARTNER,
836b22
+                                 state->forest);
836b22
+    if (ret != EOK) {
836b22
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string() failed.\n");
836b22
+        goto done;
836b22
+    }
836b22
+
836b22
+    err = sss_idmap_sid_to_bin_sid(state->idmap_ctx->map, id,
836b22
+                                   &id_val.data, &id_val.length);
836b22
+    if (err != IDMAP_SUCCESS) {
836b22
+        DEBUG(SSSDBG_OP_FAILURE,
836b22
+              "Could not convert SID: [%s].\n", idmap_error_string(err));
836b22
+        ret = EFAULT;
836b22
+        goto done;
836b22
+    }
836b22
+
836b22
+    ret = sysdb_attrs_add_val(state->reply[0], AD_AT_SID, &id_val);
836b22
+    if (ret != EOK) {
836b22
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string() failed.\n");
836b22
+        goto done;
836b22
+    }
836b22
+
836b22
+    state->reply_count = 1;
836b22
+
836b22
+    ret = ad_get_root_domain_refresh(state);
836b22
+    if (ret != EOK) {
836b22
+        DEBUG(SSSDBG_OP_FAILURE, "ad_get_root_domain_refresh() failed.\n");
836b22
+    }
836b22
+
836b22
+done:
836b22
+    if (ret != EOK) {
836b22
+        tevent_req_error(req, ret);
836b22
+        return;
836b22
+    }
836b22
+
836b22
+    tevent_req_done(req);
836b22
+}
836b22
+
836b22
+static errno_t
836b22
+ad_get_root_domain_refresh(struct ad_get_root_domain_state *state)
836b22
+{
836b22
+    struct sss_domain_info *root_domain;
836b22
+    bool has_changes;
836b22
+    errno_t ret;
836b22
+
836b22
     ret = ad_subdomains_refresh(state->be_ctx, state->idmap_ctx, state->opts,
836b22
-                                reply, reply_count, true,
836b22
+                                state->reply, state->reply_count, true,
836b22
                                 &state->sd_ctx->last_refreshed,
836b22
                                 &has_changes);
836b22
     if (ret != EOK) {
836b22
@@ -1390,8 +1539,8 @@ static void ad_get_root_domain_done(struct tevent_req *subreq)
836b22
         }
836b22
     }
836b22
 
836b22
-    state->root_domain_attrs = reply[0];
836b22
-    root_domain = ads_get_root_domain(state->be_ctx, reply[0]);
836b22
+    state->root_domain_attrs = state->reply[0];
836b22
+    root_domain = ads_get_root_domain(state->be_ctx, state->reply[0]);
836b22
     if (root_domain == NULL) {
836b22
         DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n");
836b22
         ret = EFAULT;
836b22
@@ -1410,12 +1559,7 @@ static void ad_get_root_domain_done(struct tevent_req *subreq)
836b22
     ret = EOK;
836b22
 
836b22
 done:
836b22
-    if (ret != EOK) {
836b22
-        tevent_req_error(req, ret);
836b22
-        return;
836b22
-    }
836b22
-
836b22
-    tevent_req_done(req);
836b22
+    return ret;
836b22
 }
836b22
 
836b22
 static errno_t ad_get_root_domain_recv(TALLOC_CTX *mem_ctx,
836b22
-- 
836b22
2.21.1
836b22