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