|
|
44f86b |
From 2519d5ea3757862bebc17d73d74c7e5c57bdc815 Mon Sep 17 00:00:00 2001
|
|
|
44f86b |
From: Sumit Bose <sbose@redhat.com>
|
|
|
44f86b |
Date: Tue, 16 Feb 2021 14:30:55 +0100
|
|
|
44f86b |
Subject: [PATCH 66/66] AD: read trusted domains from local domain as well
|
|
|
44f86b |
MIME-Version: 1.0
|
|
|
44f86b |
Content-Type: text/plain; charset=UTF-8
|
|
|
44f86b |
Content-Transfer-Encoding: 8bit
|
|
|
44f86b |
|
|
|
44f86b |
Currently SSSD only uses information stored in a domain controller of
|
|
|
44f86b |
the forest root domain to get the names of other trusted domains in the
|
|
|
44f86b |
forest. Depending on how the forest was created the forest root might
|
|
|
44f86b |
not have LDAP objects for all domains in the forest. It looks like a
|
|
|
44f86b |
typical case are child domains of other domains in the forest.
|
|
|
44f86b |
|
|
|
44f86b |
As a start SSSD can now include trusted domains stored in the LDAP tree
|
|
|
44f86b |
of a local domain controller as well. In a long run it would make sense
|
|
|
44f86b |
to allow SSSD to explicitly search for domain by looking up DNS entries
|
|
|
44f86b |
and checking a potential domain controller with a CLDAP ping.
|
|
|
44f86b |
|
|
|
44f86b |
Resolves: https://github.com/SSSD/sssd/issues/5528
|
|
|
44f86b |
|
|
|
44f86b |
:feature: Besides trusted domains known by the forest root, trusted
|
|
|
44f86b |
domains known by the local domain are used as well.
|
|
|
44f86b |
|
|
|
44f86b |
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
|
|
44f86b |
(cherry picked from commit 95adf488f94f5968f6cfba9e3bef74c07c02ccff)
|
|
|
44f86b |
|
|
|
44f86b |
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
|
|
44f86b |
---
|
|
|
44f86b |
src/providers/ad/ad_subdomains.c | 105 +++++++++++++++++++++++++------
|
|
|
44f86b |
1 file changed, 86 insertions(+), 19 deletions(-)
|
|
|
44f86b |
|
|
|
44f86b |
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
|
|
|
44f86b |
index ba4efe975..16aecbc64 100644
|
|
|
44f86b |
--- a/src/providers/ad/ad_subdomains.c
|
|
|
44f86b |
+++ b/src/providers/ad/ad_subdomains.c
|
|
|
44f86b |
@@ -45,6 +45,7 @@
|
|
|
44f86b |
#define AD_AT_TRUST_TYPE "trustType"
|
|
|
44f86b |
#define AD_AT_TRUST_PARTNER "trustPartner"
|
|
|
44f86b |
#define AD_AT_TRUST_ATTRS "trustAttributes"
|
|
|
44f86b |
+#define AD_AT_DOMAIN_NAME "cn"
|
|
|
44f86b |
|
|
|
44f86b |
/* trustType=2 denotes uplevel (NT5 and later) trusted domains. See
|
|
|
44f86b |
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms680342%28v=vs.85%29.aspx
|
|
|
44f86b |
@@ -56,7 +57,6 @@
|
|
|
44f86b |
*/
|
|
|
44f86b |
#define SLAVE_DOMAIN_FILTER_BASE "(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*))"
|
|
|
44f86b |
#define SLAVE_DOMAIN_FILTER "(&"SLAVE_DOMAIN_FILTER_BASE")"
|
|
|
44f86b |
-#define FOREST_ROOT_FILTER_FMT "(&"SLAVE_DOMAIN_FILTER_BASE"(cn=%s))"
|
|
|
44f86b |
|
|
|
44f86b |
/* Attributes of schema objects. See e.g.
|
|
|
44f86b |
* https://docs.microsoft.com/en-us/windows/desktop/AD/characteristics-of-attributes
|
|
|
44f86b |
@@ -646,6 +646,10 @@ done:
|
|
|
44f86b |
return ret;
|
|
|
44f86b |
}
|
|
|
44f86b |
|
|
|
44f86b |
+/* How many times we keep a domain not found during searches before it will be
|
|
|
44f86b |
+ * removed. */
|
|
|
44f86b |
+#define MAX_NOT_FOUND 6
|
|
|
44f86b |
+
|
|
|
44f86b |
static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx,
|
|
|
44f86b |
struct sdap_idmap_ctx *idmap_ctx,
|
|
|
44f86b |
struct sdap_options *opts,
|
|
|
44f86b |
@@ -706,6 +710,25 @@ static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx,
|
|
|
44f86b |
}
|
|
|
44f86b |
|
|
|
44f86b |
if (c >= num_subdomains) {
|
|
|
44f86b |
+ DEBUG(SSSDBG_CONF_SETTINGS, "Domain [%s] not in current list.\n",
|
|
|
44f86b |
+ dom->name);
|
|
|
44f86b |
+ /* Since the forest root might not have trustedDomain objects for
|
|
|
44f86b |
+ * each domain in the forest, especially e.g. for child-domains of
|
|
|
44f86b |
+ * child-domains, we cannot reliable say if a domain is still
|
|
|
44f86b |
+ * present or not.
|
|
|
44f86b |
+ * Maybe it would work to check the crossRef objects in
|
|
|
44f86b |
+ * CN=Partitions,CN=Configuration as well to understand if a
|
|
|
44f86b |
+ * domain is still known in the forest or not.
|
|
|
44f86b |
+ * For the time being we use a counter, if a domain was not found
|
|
|
44f86b |
+ * after multiple attempts it will be deleted. */
|
|
|
44f86b |
+
|
|
|
44f86b |
+ if (dom->not_found_counter++ < MAX_NOT_FOUND) {
|
|
|
44f86b |
+ DEBUG(SSSDBG_TRACE_ALL,
|
|
|
44f86b |
+ "Domain [%s] was not found [%zu] times.\n", dom->name,
|
|
|
44f86b |
+ dom->not_found_counter);
|
|
|
44f86b |
+ continue;
|
|
|
44f86b |
+ }
|
|
|
44f86b |
+
|
|
|
44f86b |
/* ok this subdomain does not exist anymore, let's clean up */
|
|
|
44f86b |
sss_domain_set_state(dom, DOM_DISABLED);
|
|
|
44f86b |
|
|
|
44f86b |
@@ -743,6 +766,7 @@ static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx,
|
|
|
44f86b |
/* terminate all requests for this subdomain so we can free it */
|
|
|
44f86b |
dp_terminate_domain_requests(be_ctx->provider, dom->name);
|
|
|
44f86b |
talloc_zfree(sdom);
|
|
|
44f86b |
+
|
|
|
44f86b |
} else {
|
|
|
44f86b |
/* ok let's try to update it */
|
|
|
44f86b |
ret = ad_subdom_enumerates(domain, subdomains[c], &enumerate);
|
|
|
44f86b |
@@ -750,6 +774,7 @@ static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx,
|
|
|
44f86b |
goto done;
|
|
|
44f86b |
}
|
|
|
44f86b |
|
|
|
44f86b |
+ dom->not_found_counter = 0;
|
|
|
44f86b |
ret = ad_subdom_store(be_ctx->cdb, idmap_ctx, domain,
|
|
|
44f86b |
subdomains[c], enumerate);
|
|
|
44f86b |
if (ret) {
|
|
|
44f86b |
@@ -1310,10 +1335,9 @@ ad_get_root_domain_send(TALLOC_CTX *mem_ctx,
|
|
|
44f86b |
struct tevent_req *req;
|
|
|
44f86b |
struct sdap_options *opts;
|
|
|
44f86b |
errno_t ret;
|
|
|
44f86b |
- const char *filter;
|
|
|
44f86b |
const char *attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
|
|
|
44f86b |
AD_AT_SID, AD_AT_TRUST_TYPE,
|
|
|
44f86b |
- AD_AT_TRUST_ATTRS, NULL };
|
|
|
44f86b |
+ AD_AT_TRUST_ATTRS, AD_AT_DOMAIN_NAME, NULL };
|
|
|
44f86b |
|
|
|
44f86b |
req = tevent_req_create(mem_ctx, &state, struct ad_get_root_domain_state);
|
|
|
44f86b |
if (req == NULL) {
|
|
|
44f86b |
@@ -1338,15 +1362,10 @@ ad_get_root_domain_send(TALLOC_CTX *mem_ctx,
|
|
|
44f86b |
state->domain = domain;
|
|
|
44f86b |
state->forest = forest;
|
|
|
44f86b |
|
|
|
44f86b |
- filter = talloc_asprintf(state, FOREST_ROOT_FILTER_FMT, forest);
|
|
|
44f86b |
- if (filter == NULL) {
|
|
|
44f86b |
- ret = ENOMEM;
|
|
|
44f86b |
- goto immediately;
|
|
|
44f86b |
- }
|
|
|
44f86b |
-
|
|
|
44f86b |
subreq = sdap_search_bases_return_first_send(state, ev, opts, sh,
|
|
|
44f86b |
opts->sdom->search_bases,
|
|
|
44f86b |
- NULL, false, 0, filter, attrs,
|
|
|
44f86b |
+ NULL, false, 0,
|
|
|
44f86b |
+ SLAVE_DOMAIN_FILTER, attrs,
|
|
|
44f86b |
NULL);
|
|
|
44f86b |
if (subreq == NULL) {
|
|
|
44f86b |
ret = ENOMEM;
|
|
|
44f86b |
@@ -1368,11 +1387,33 @@ immediately:
|
|
|
44f86b |
return req;
|
|
|
44f86b |
}
|
|
|
44f86b |
|
|
|
44f86b |
+static struct sysdb_attrs *find_domain(size_t count, struct sysdb_attrs **reply,
|
|
|
44f86b |
+ const char *dom_name)
|
|
|
44f86b |
+{
|
|
|
44f86b |
+ size_t c;
|
|
|
44f86b |
+ const char *name;
|
|
|
44f86b |
+ int ret;
|
|
|
44f86b |
+
|
|
|
44f86b |
+ for (c = 0; c < count; c++) {
|
|
|
44f86b |
+ ret = sysdb_attrs_get_string(reply[c], AD_AT_DOMAIN_NAME, &name);
|
|
|
44f86b |
+ if (ret != EOK) {
|
|
|
44f86b |
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to find domain name, skipping");
|
|
|
44f86b |
+ continue;
|
|
|
44f86b |
+ }
|
|
|
44f86b |
+ if (strcasecmp(name, dom_name) == 0) {
|
|
|
44f86b |
+ return reply[c];
|
|
|
44f86b |
+ }
|
|
|
44f86b |
+ }
|
|
|
44f86b |
+
|
|
|
44f86b |
+ return NULL;
|
|
|
44f86b |
+}
|
|
|
44f86b |
+
|
|
|
44f86b |
static void ad_get_root_domain_done(struct tevent_req *subreq)
|
|
|
44f86b |
{
|
|
|
44f86b |
struct tevent_req *req;
|
|
|
44f86b |
struct ad_get_root_domain_state *state;
|
|
|
44f86b |
errno_t ret;
|
|
|
44f86b |
+ bool has_changes = false;
|
|
|
44f86b |
|
|
|
44f86b |
req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
44f86b |
state = tevent_req_data(req, struct ad_get_root_domain_state);
|
|
|
44f86b |
@@ -1387,7 +1428,37 @@ static void ad_get_root_domain_done(struct tevent_req *subreq)
|
|
|
44f86b |
goto done;
|
|
|
44f86b |
}
|
|
|
44f86b |
|
|
|
44f86b |
- if (state->reply_count == 0) {
|
|
|
44f86b |
+ find_domain(state->reply_count, state->reply, state->forest);
|
|
|
44f86b |
+
|
|
|
44f86b |
+ if (state->reply_count == 0
|
|
|
44f86b |
+ || find_domain(state->reply_count, state->reply,
|
|
|
44f86b |
+ state->forest) == NULL) {
|
|
|
44f86b |
+
|
|
|
44f86b |
+ if (state->reply_count > 0) {
|
|
|
44f86b |
+ /* refresh the other domains we have found before checking forest
|
|
|
44f86b |
+ * root */
|
|
|
44f86b |
+ ret = ad_subdomains_refresh(state->be_ctx, state->idmap_ctx,
|
|
|
44f86b |
+ state->opts,
|
|
|
44f86b |
+ state->reply, state->reply_count, false,
|
|
|
44f86b |
+ &state->sd_ctx->last_refreshed,
|
|
|
44f86b |
+ &has_changes);
|
|
|
44f86b |
+ if (ret != EOK) {
|
|
|
44f86b |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
44f86b |
+ "ad_subdomains_refresh failed [%d]: %s\n",
|
|
|
44f86b |
+ ret, sss_strerror(ret));
|
|
|
44f86b |
+ goto done;
|
|
|
44f86b |
+ }
|
|
|
44f86b |
+
|
|
|
44f86b |
+ if (has_changes) {
|
|
|
44f86b |
+ ret = ad_subdom_reinit(state->sd_ctx);
|
|
|
44f86b |
+ if (ret != EOK) {
|
|
|
44f86b |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
44f86b |
+ "Could not reinitialize subdomains\n");
|
|
|
44f86b |
+ goto done;
|
|
|
44f86b |
+ }
|
|
|
44f86b |
+ }
|
|
|
44f86b |
+ }
|
|
|
44f86b |
+
|
|
|
44f86b |
DEBUG(SSSDBG_OP_FAILURE,
|
|
|
44f86b |
"No information provided for root domain, trying directly.\n");
|
|
|
44f86b |
subreq = ad_check_domain_send(state, state->ev, state->be_ctx,
|
|
|
44f86b |
@@ -1400,11 +1471,6 @@ static void ad_get_root_domain_done(struct tevent_req *subreq)
|
|
|
44f86b |
}
|
|
|
44f86b |
tevent_req_set_callback(subreq, ad_check_root_domain_done, req);
|
|
|
44f86b |
return;
|
|
|
44f86b |
- } else if (state->reply_count > 1) {
|
|
|
44f86b |
- DEBUG(SSSDBG_CRIT_FAILURE, "Multiple results for root domain search, "
|
|
|
44f86b |
- "domain list might be incomplete!\n");
|
|
|
44f86b |
- ret = ERR_MALFORMED_ENTRY;
|
|
|
44f86b |
- goto done;
|
|
|
44f86b |
}
|
|
|
44f86b |
|
|
|
44f86b |
ret = ad_get_root_domain_refresh(state);
|
|
|
44f86b |
@@ -1522,7 +1588,7 @@ ad_get_root_domain_refresh(struct ad_get_root_domain_state *state)
|
|
|
44f86b |
errno_t ret;
|
|
|
44f86b |
|
|
|
44f86b |
ret = ad_subdomains_refresh(state->be_ctx, state->idmap_ctx, state->opts,
|
|
|
44f86b |
- state->reply, state->reply_count, true,
|
|
|
44f86b |
+ state->reply, state->reply_count, false,
|
|
|
44f86b |
&state->sd_ctx->last_refreshed,
|
|
|
44f86b |
&has_changes);
|
|
|
44f86b |
if (ret != EOK) {
|
|
|
44f86b |
@@ -1539,8 +1605,9 @@ ad_get_root_domain_refresh(struct ad_get_root_domain_state *state)
|
|
|
44f86b |
}
|
|
|
44f86b |
}
|
|
|
44f86b |
|
|
|
44f86b |
- state->root_domain_attrs = state->reply[0];
|
|
|
44f86b |
- root_domain = ads_get_root_domain(state->be_ctx, state->reply[0]);
|
|
|
44f86b |
+ state->root_domain_attrs = find_domain(state->reply_count, state->reply,
|
|
|
44f86b |
+ state->forest);
|
|
|
44f86b |
+ root_domain = ads_get_root_domain(state->be_ctx, state->root_domain_attrs);
|
|
|
44f86b |
if (root_domain == NULL) {
|
|
|
44f86b |
DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n");
|
|
|
44f86b |
ret = EFAULT;
|
|
|
44f86b |
--
|
|
|
44f86b |
2.26.3
|
|
|
44f86b |
|