|
|
2fc102 |
From d97ff9abd276e9216e5868be37c3762d208b36c0 Mon Sep 17 00:00:00 2001
|
|
|
2fc102 |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
2fc102 |
Date: Tue, 1 Apr 2014 13:51:49 -0400
|
|
|
2fc102 |
Subject: [PATCH 120/120] AD: connect to forest root when downloading the list
|
|
|
2fc102 |
of subdomains
|
|
|
2fc102 |
|
|
|
2fc102 |
https://fedorahosted.org/sssd/ticket/2285
|
|
|
2fc102 |
|
|
|
2fc102 |
Only the forest root has the knowledge about all the domains in the forest,
|
|
|
2fc102 |
the forest leaves only see themselves and the forest root.
|
|
|
2fc102 |
|
|
|
2fc102 |
This patch switches to connecting to the forest root for downloading the
|
|
|
2fc102 |
trusted domains instead of the server we are connected to.
|
|
|
2fc102 |
---
|
|
|
2fc102 |
src/providers/ad/ad_subdomains.c | 372 ++++++++++++++++++++++++++++++++++++++-
|
|
|
2fc102 |
1 file changed, 363 insertions(+), 9 deletions(-)
|
|
|
2fc102 |
|
|
|
2fc102 |
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
|
|
|
2fc102 |
index 0d9652b5c615add47958cfdc61eba862a332ae4d..3c841788d5d88069d79a9438b72f57c8c2e0ffda 100644
|
|
|
2fc102 |
--- a/src/providers/ad/ad_subdomains.c
|
|
|
2fc102 |
+++ b/src/providers/ad/ad_subdomains.c
|
|
|
2fc102 |
@@ -54,7 +54,9 @@
|
|
|
2fc102 |
* the same forest. See http://msdn.microsoft.com/en-us/library/cc223786.aspx
|
|
|
2fc102 |
* for more information.
|
|
|
2fc102 |
*/
|
|
|
2fc102 |
-#define SLAVE_DOMAIN_FILTER "(&(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*)))"
|
|
|
2fc102 |
+#define SLAVE_DOMAIN_FILTER_BASE "(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*))"
|
|
|
2fc102 |
+#define SLAVE_DOMAIN_FILTER "(&"SLAVE_DOMAIN_FILTER_BASE")"
|
|
|
2fc102 |
+#define FOREST_ROOT_FILTER_FMT "(&"SLAVE_DOMAIN_FILTER_BASE"(cn=%s))"
|
|
|
2fc102 |
|
|
|
2fc102 |
/* do not refresh more often than every 5 seconds for now */
|
|
|
2fc102 |
#define AD_SUBDOMAIN_REFRESH_LIMIT 5
|
|
|
2fc102 |
@@ -80,6 +82,11 @@ struct ad_subdomains_req_ctx {
|
|
|
2fc102 |
char *current_filter;
|
|
|
2fc102 |
size_t base_iter;
|
|
|
2fc102 |
|
|
|
2fc102 |
+ struct ad_id_ctx *root_id_ctx;
|
|
|
2fc102 |
+ struct sdap_id_op *root_op;
|
|
|
2fc102 |
+ size_t root_base_iter;
|
|
|
2fc102 |
+ struct sysdb_attrs *root_domain;
|
|
|
2fc102 |
+
|
|
|
2fc102 |
size_t reply_count;
|
|
|
2fc102 |
struct sysdb_attrs **reply;
|
|
|
2fc102 |
|
|
|
2fc102 |
@@ -461,6 +468,7 @@ static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *ctx)
|
|
|
2fc102 |
|
|
|
2fc102 |
static void ad_subdomains_get_conn_done(struct tevent_req *req);
|
|
|
2fc102 |
static void ad_subdomains_master_dom_done(struct tevent_req *req);
|
|
|
2fc102 |
+static errno_t ad_subdomains_get_root(struct ad_subdomains_req_ctx *ctx);
|
|
|
2fc102 |
static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx);
|
|
|
2fc102 |
|
|
|
2fc102 |
static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx,
|
|
|
2fc102 |
@@ -481,6 +489,10 @@ static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx,
|
|
|
2fc102 |
req_ctx->sd_ctx = ctx;
|
|
|
2fc102 |
req_ctx->current_filter = NULL;
|
|
|
2fc102 |
req_ctx->base_iter = 0;
|
|
|
2fc102 |
+ req_ctx->root_base_iter = 0;
|
|
|
2fc102 |
+ req_ctx->root_id_ctx = NULL;
|
|
|
2fc102 |
+ req_ctx->root_op = NULL;
|
|
|
2fc102 |
+ req_ctx->root_domain = NULL;
|
|
|
2fc102 |
req_ctx->reply_count = 0;
|
|
|
2fc102 |
req_ctx->reply = NULL;
|
|
|
2fc102 |
|
|
|
2fc102 |
@@ -575,7 +587,20 @@ static void ad_subdomains_master_dom_done(struct tevent_req *req)
|
|
|
2fc102 |
goto done;
|
|
|
2fc102 |
}
|
|
|
2fc102 |
|
|
|
2fc102 |
- ret = ad_subdomains_get_slave(ctx);
|
|
|
2fc102 |
+ if (strcasecmp(ctx->sd_ctx->be_ctx->domain->name, ctx->forest) != 0) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_TRACE_FUNC,
|
|
|
2fc102 |
+ ("SSSD needs to look up the forest root domain\n"));
|
|
|
2fc102 |
+ ret = ad_subdomains_get_root(ctx);
|
|
|
2fc102 |
+ } else {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_TRACE_FUNC,
|
|
|
2fc102 |
+ ("Connected to forest root, looking up child domains..\n"));
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ctx->root_op = ctx->sdap_op;
|
|
|
2fc102 |
+ ctx->root_id_ctx = ctx->sd_ctx->ad_id_ctx;
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ret = ad_subdomains_get_slave(ctx);
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
if (ret == EAGAIN) {
|
|
|
2fc102 |
return;
|
|
|
2fc102 |
} else if (ret != EOK) {
|
|
|
2fc102 |
@@ -586,6 +611,244 @@ done:
|
|
|
2fc102 |
be_req_terminate(ctx->be_req, DP_ERR_FATAL, ret, NULL);
|
|
|
2fc102 |
}
|
|
|
2fc102 |
|
|
|
2fc102 |
+static void ad_subdomains_get_root_domain_done(struct tevent_req *req);
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+static errno_t ad_subdomains_get_root(struct ad_subdomains_req_ctx *ctx)
|
|
|
2fc102 |
+{
|
|
|
2fc102 |
+ struct tevent_req *req;
|
|
|
2fc102 |
+ struct sdap_search_base *base;
|
|
|
2fc102 |
+ struct sdap_id_ctx *sdap_id_ctx;
|
|
|
2fc102 |
+ char *filter;
|
|
|
2fc102 |
+ const char *forest_root_attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
|
|
|
2fc102 |
+ AD_AT_SID, AD_AT_TRUST_TYPE,
|
|
|
2fc102 |
+ AD_AT_TRUST_ATTRS, NULL };
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ sdap_id_ctx = ctx->sd_ctx->sdap_id_ctx;
|
|
|
2fc102 |
+ base = sdap_id_ctx->opts->sdom->search_bases[ctx->root_base_iter];
|
|
|
2fc102 |
+ if (base == NULL) {
|
|
|
2fc102 |
+ return EOK;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ filter = talloc_asprintf(ctx, FOREST_ROOT_FILTER_FMT, ctx->forest);
|
|
|
2fc102 |
+ if (filter == NULL) {
|
|
|
2fc102 |
+ return ENOMEM;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
|
|
|
2fc102 |
+ sdap_id_ctx->opts,
|
|
|
2fc102 |
+ sdap_id_op_handle(ctx->sdap_op),
|
|
|
2fc102 |
+ base->basedn, LDAP_SCOPE_SUBTREE,
|
|
|
2fc102 |
+ filter, forest_root_attrs,
|
|
|
2fc102 |
+ NULL, 0,
|
|
|
2fc102 |
+ dp_opt_get_int(sdap_id_ctx->opts->basic,
|
|
|
2fc102 |
+ SDAP_SEARCH_TIMEOUT),
|
|
|
2fc102 |
+ false);
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ if (req == NULL) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send failed.\n"));
|
|
|
2fc102 |
+ return ENOMEM;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ tevent_req_set_callback(req, ad_subdomains_get_root_domain_done, ctx);
|
|
|
2fc102 |
+ return EAGAIN;
|
|
|
2fc102 |
+}
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx);
|
|
|
2fc102 |
+static void ad_subdomains_root_conn_done(struct tevent_req *req);
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+static void ad_subdomains_get_root_domain_done(struct tevent_req *req)
|
|
|
2fc102 |
+{
|
|
|
2fc102 |
+ int ret;
|
|
|
2fc102 |
+ size_t reply_count;
|
|
|
2fc102 |
+ struct sysdb_attrs **reply = NULL;
|
|
|
2fc102 |
+ struct ad_subdomains_req_ctx *ctx;
|
|
|
2fc102 |
+ int dp_error = DP_ERR_FATAL;
|
|
|
2fc102 |
+ bool has_changes;
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
|
|
|
2fc102 |
+ talloc_zfree(req);
|
|
|
2fc102 |
+ if (ret != EOK) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send request failed.\n"));
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ if (reply_count == 0) {
|
|
|
2fc102 |
+ /* If no root domain was found in the default search base, try the
|
|
|
2fc102 |
+ * next one, if available
|
|
|
2fc102 |
+ */
|
|
|
2fc102 |
+ ctx->root_base_iter++;
|
|
|
2fc102 |
+ ret = ad_subdomains_get_root(ctx);
|
|
|
2fc102 |
+ if (ret == EAGAIN) {
|
|
|
2fc102 |
+ return;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ } else if (reply_count > 1) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
2fc102 |
+ ("Multiple results for root domain search, "
|
|
|
2fc102 |
+ "domain list might be incomplete!\n"));
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ctx->root_op = ctx->sdap_op;
|
|
|
2fc102 |
+ ctx->root_id_ctx = ctx->sd_ctx->ad_id_ctx;
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ret = ad_subdomains_get_slave(ctx);
|
|
|
2fc102 |
+ if (ret == EAGAIN) {
|
|
|
2fc102 |
+ return;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+ /* Exactly one result, good. */
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ /* We won't use the operation to the local LDAP anymore, but
|
|
|
2fc102 |
+ * read from the forest root
|
|
|
2fc102 |
+ */
|
|
|
2fc102 |
+ ret = sdap_id_op_done(ctx->sdap_op, ret, &dp_error);
|
|
|
2fc102 |
+ if (ret != EOK) {
|
|
|
2fc102 |
+ if (dp_error == DP_ERR_OFFLINE) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
|
|
2fc102 |
+ ("No AD server is available, cannot get the "
|
|
|
2fc102 |
+ "subdomain list while offline\n"));
|
|
|
2fc102 |
+ } else {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
2fc102 |
+ ("Failed to search the AD server: [%d](%s)\n",
|
|
|
2fc102 |
+ ret, strerror(ret)));
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ret = ad_subdomains_refresh(ctx->sd_ctx, 1, reply, &has_changes);
|
|
|
2fc102 |
+ if (ret != EOK) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("ad_subdomains_refresh failed.\n"));
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ if (has_changes) {
|
|
|
2fc102 |
+ ret = ad_subdom_reinit(ctx->sd_ctx);
|
|
|
2fc102 |
+ if (ret != EOK) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not reinitialize subdomains\n"));
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ctx->root_domain = reply[0];
|
|
|
2fc102 |
+ ctx->root_id_ctx = ads_get_root_id_ctx(ctx);
|
|
|
2fc102 |
+ if (ctx->root_id_ctx == NULL) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
2fc102 |
+ ("Cannot create id ctx for the root domain\n"));
|
|
|
2fc102 |
+ ret = EFAULT;
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ctx->root_op = sdap_id_op_create(ctx,
|
|
|
2fc102 |
+ ctx->root_id_ctx->ldap_ctx->conn_cache);
|
|
|
2fc102 |
+ if (ctx->root_op == NULL) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_create failed.\n"));
|
|
|
2fc102 |
+ ret = ENOMEM;
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ req = sdap_id_op_connect_send(ctx->root_op, ctx, &ret;;
|
|
|
2fc102 |
+ if (req == NULL) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_connect_send failed: %d(%s).\n",
|
|
|
2fc102 |
+ ret, strerror(ret)));
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ tevent_req_set_callback(req, ad_subdomains_root_conn_done, ctx);
|
|
|
2fc102 |
+ return;
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+fail:
|
|
|
2fc102 |
+ if (ret == EOK) {
|
|
|
2fc102 |
+ ctx->sd_ctx->last_refreshed = time(NULL);
|
|
|
2fc102 |
+ dp_error = DP_ERR_OK;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+ be_req_terminate(ctx->be_req, dp_error, ret, NULL);
|
|
|
2fc102 |
+}
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx)
|
|
|
2fc102 |
+{
|
|
|
2fc102 |
+ errno_t ret;
|
|
|
2fc102 |
+ const char *name;
|
|
|
2fc102 |
+ struct sss_domain_info *root;
|
|
|
2fc102 |
+ struct sdap_domain *sdom;
|
|
|
2fc102 |
+ struct ad_id_ctx *root_id_ctx;
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ret = sysdb_attrs_get_string(ctx->root_domain, AD_AT_TRUST_PARTNER, &name);
|
|
|
2fc102 |
+ if (ret != EOK) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n"));
|
|
|
2fc102 |
+ return NULL;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ /* With a subsequent run, the root should already be known */
|
|
|
2fc102 |
+ root = find_subdomain_by_name(ctx->sd_ctx->be_ctx->domain,
|
|
|
2fc102 |
+ name, false);
|
|
|
2fc102 |
+ if (root == NULL) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not find the root domain\n"));
|
|
|
2fc102 |
+ return NULL;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ sdom = sdap_domain_get(ctx->sd_ctx->ad_id_ctx->sdap_id_ctx->opts, root);
|
|
|
2fc102 |
+ if (sdom == NULL) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
2fc102 |
+ ("Cannot get the sdom for %s!\n", root->name));
|
|
|
2fc102 |
+ return NULL;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ if (sdom->pvt == NULL) {
|
|
|
2fc102 |
+ ret = ad_subdom_ad_ctx_new(ctx->sd_ctx->be_ctx,
|
|
|
2fc102 |
+ ctx->sd_ctx->ad_id_ctx,
|
|
|
2fc102 |
+ root,
|
|
|
2fc102 |
+ &root_id_ctx);
|
|
|
2fc102 |
+ if (ret != EOK) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("ad_subdom_ad_ctx_new failed.\n"));
|
|
|
2fc102 |
+ return NULL;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+ sdom->pvt = root_id_ctx;
|
|
|
2fc102 |
+ } else {
|
|
|
2fc102 |
+ root_id_ctx = sdom->pvt;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ return root_id_ctx;
|
|
|
2fc102 |
+}
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+static void ad_subdomains_root_conn_done(struct tevent_req *req)
|
|
|
2fc102 |
+{
|
|
|
2fc102 |
+ int ret;
|
|
|
2fc102 |
+ int dp_error = DP_ERR_FATAL;
|
|
|
2fc102 |
+ struct ad_subdomains_req_ctx *ctx;
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ret = sdap_id_op_connect_recv(req, &dp_error);
|
|
|
2fc102 |
+ talloc_zfree(req);
|
|
|
2fc102 |
+ if (ret) {
|
|
|
2fc102 |
+ if (dp_error == DP_ERR_OFFLINE) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
|
|
2fc102 |
+ ("No AD server is available, cannot get the "
|
|
|
2fc102 |
+ "subdomain list while offline\n"));
|
|
|
2fc102 |
+ } else {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
2fc102 |
+ ("Failed to connect to AD server: [%d](%s)\n",
|
|
|
2fc102 |
+ ret, strerror(ret)));
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ret = ad_subdomains_get_slave(ctx);
|
|
|
2fc102 |
+ if (ret == EAGAIN) {
|
|
|
2fc102 |
+ return;
|
|
|
2fc102 |
+ } else if (ret != EOK) {
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+fail:
|
|
|
2fc102 |
+ be_req_terminate(ctx->be_req, dp_error, ret, NULL);
|
|
|
2fc102 |
+}
|
|
|
2fc102 |
+
|
|
|
2fc102 |
static void ad_subdomains_get_slave_domain_done(struct tevent_req *req);
|
|
|
2fc102 |
|
|
|
2fc102 |
static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx)
|
|
|
2fc102 |
@@ -596,18 +859,18 @@ static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx)
|
|
|
2fc102 |
AD_AT_SID, AD_AT_TRUST_TYPE,
|
|
|
2fc102 |
AD_AT_TRUST_ATTRS, NULL };
|
|
|
2fc102 |
|
|
|
2fc102 |
- base = ctx->sd_ctx->sdap_id_ctx->opts->sdom->search_bases[ctx->base_iter];
|
|
|
2fc102 |
+ base = ctx->root_id_ctx->sdap_id_ctx->opts->sdom->search_bases[ctx->base_iter];
|
|
|
2fc102 |
if (base == NULL) {
|
|
|
2fc102 |
return EOK;
|
|
|
2fc102 |
}
|
|
|
2fc102 |
|
|
|
2fc102 |
req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
|
|
|
2fc102 |
- ctx->sd_ctx->sdap_id_ctx->opts,
|
|
|
2fc102 |
- sdap_id_op_handle(ctx->sdap_op),
|
|
|
2fc102 |
+ ctx->root_id_ctx->sdap_id_ctx->opts,
|
|
|
2fc102 |
+ sdap_id_op_handle(ctx->root_op),
|
|
|
2fc102 |
base->basedn, LDAP_SCOPE_SUBTREE,
|
|
|
2fc102 |
SLAVE_DOMAIN_FILTER, slave_dom_attrs,
|
|
|
2fc102 |
NULL, 0,
|
|
|
2fc102 |
- dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic,
|
|
|
2fc102 |
+ dp_opt_get_int(ctx->root_id_ctx->sdap_id_ctx->opts->basic,
|
|
|
2fc102 |
SDAP_SEARCH_TIMEOUT),
|
|
|
2fc102 |
false);
|
|
|
2fc102 |
|
|
|
2fc102 |
@@ -620,6 +883,68 @@ static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx)
|
|
|
2fc102 |
return EAGAIN;
|
|
|
2fc102 |
}
|
|
|
2fc102 |
|
|
|
2fc102 |
+static errno_t ad_subdomains_process(TALLOC_CTX *mem_ctx,
|
|
|
2fc102 |
+ struct sss_domain_info *domain,
|
|
|
2fc102 |
+ size_t nsd, struct sysdb_attrs **sd,
|
|
|
2fc102 |
+ struct sysdb_attrs *root,
|
|
|
2fc102 |
+ size_t *_nsd_out,
|
|
|
2fc102 |
+ struct sysdb_attrs ***_sd_out)
|
|
|
2fc102 |
+{
|
|
|
2fc102 |
+ size_t i, sdi;
|
|
|
2fc102 |
+ struct sysdb_attrs **sd_out;
|
|
|
2fc102 |
+ const char *sd_name;
|
|
|
2fc102 |
+ errno_t ret;
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ if (root == NULL) {
|
|
|
2fc102 |
+ /* We are connected directly to the root domain. The 'sd'
|
|
|
2fc102 |
+ * list is complete and we can just use it
|
|
|
2fc102 |
+ */
|
|
|
2fc102 |
+ *_nsd_out = nsd;
|
|
|
2fc102 |
+ *_sd_out = sd;
|
|
|
2fc102 |
+ return EOK;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ /* If we searched for root separately, we must:
|
|
|
2fc102 |
+ * a) treat the root domain as a subdomain
|
|
|
2fc102 |
+ * b) filter the subdomain we are connected to from the subdomain
|
|
|
2fc102 |
+ * list, from our point of view, it's the master domain
|
|
|
2fc102 |
+ */
|
|
|
2fc102 |
+ sd_out = talloc_zero_array(mem_ctx, struct sysdb_attrs *, nsd+1);
|
|
|
2fc102 |
+ if (sd_out == NULL) {
|
|
|
2fc102 |
+ return ENOMEM;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ sdi = 0;
|
|
|
2fc102 |
+ for (i = 0; i < nsd; i++) {
|
|
|
2fc102 |
+ ret = sysdb_attrs_get_string(sd[i], AD_AT_TRUST_PARTNER, &sd_name);
|
|
|
2fc102 |
+ if (ret != EOK) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n"));
|
|
|
2fc102 |
+ goto fail;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ if (strcasecmp(sd_name, domain->name) == 0) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_TRACE_INTERNAL,
|
|
|
2fc102 |
+ ("Not including primary domain %s in the subdomain list\n",
|
|
|
2fc102 |
+ domain->name));
|
|
|
2fc102 |
+ continue;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ sd_out[sdi] = talloc_steal(sd_out, sd[i]);
|
|
|
2fc102 |
+ sdi++;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ /* Now include the root */
|
|
|
2fc102 |
+ sd_out[sdi] = talloc_steal(sd_out, root);
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ *_nsd_out = sdi+1;
|
|
|
2fc102 |
+ *_sd_out = sd_out;
|
|
|
2fc102 |
+ return EOK;
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+fail:
|
|
|
2fc102 |
+ talloc_free(sd_out);
|
|
|
2fc102 |
+ return ret;
|
|
|
2fc102 |
+}
|
|
|
2fc102 |
+
|
|
|
2fc102 |
static void ad_subdomains_get_slave_domain_done(struct tevent_req *req)
|
|
|
2fc102 |
{
|
|
|
2fc102 |
int ret;
|
|
|
2fc102 |
@@ -628,6 +953,8 @@ static void ad_subdomains_get_slave_domain_done(struct tevent_req *req)
|
|
|
2fc102 |
struct ad_subdomains_req_ctx *ctx;
|
|
|
2fc102 |
int dp_error = DP_ERR_FATAL;
|
|
|
2fc102 |
bool refresh_has_changes = false;
|
|
|
2fc102 |
+ size_t nsubdoms;
|
|
|
2fc102 |
+ struct sysdb_attrs **subdoms;
|
|
|
2fc102 |
|
|
|
2fc102 |
ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
|
|
|
2fc102 |
|
|
|
2fc102 |
@@ -653,13 +980,40 @@ static void ad_subdomains_get_slave_domain_done(struct tevent_req *req)
|
|
|
2fc102 |
ctx->base_iter++;
|
|
|
2fc102 |
ret = ad_subdomains_get_slave(ctx);
|
|
|
2fc102 |
if (ret == EAGAIN) {
|
|
|
2fc102 |
+ /* Search in progress */
|
|
|
2fc102 |
+ return;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ ret = sdap_id_op_done(ctx->root_op, ret, &dp_error);
|
|
|
2fc102 |
+ if (ret != EOK) {
|
|
|
2fc102 |
+ if (dp_error == DP_ERR_OFFLINE) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
|
|
2fc102 |
+ ("No AD server is available, cannot get the "
|
|
|
2fc102 |
+ "subdomain list while offline\n"));
|
|
|
2fc102 |
+ } else {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
2fc102 |
+ ("Failed to search the AD server: [%d](%s)\n",
|
|
|
2fc102 |
+ ret, strerror(ret)));
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+ tevent_req_error(req, ret);
|
|
|
2fc102 |
+ return;
|
|
|
2fc102 |
+ }
|
|
|
2fc102 |
+
|
|
|
2fc102 |
+ /* Based on whether we are connected to the forest root or not, we might
|
|
|
2fc102 |
+ * need to exclude the subdomain we are connected to from the list of
|
|
|
2fc102 |
+ * subdomains
|
|
|
2fc102 |
+ */
|
|
|
2fc102 |
+ ret = ad_subdomains_process(ctx, ctx->sd_ctx->be_ctx->domain,
|
|
|
2fc102 |
+ ctx->reply_count, ctx->reply,
|
|
|
2fc102 |
+ ctx->root_domain, &nsubdoms, &subdoms);
|
|
|
2fc102 |
+ if (ret != EOK) {
|
|
|
2fc102 |
+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot process subdomain list\n"));
|
|
|
2fc102 |
+ tevent_req_error(req, ret);
|
|
|
2fc102 |
return;
|
|
|
2fc102 |
- } else if (ret != EOK) {
|
|
|
2fc102 |
- goto done;
|
|
|
2fc102 |
}
|
|
|
2fc102 |
|
|
|
2fc102 |
/* Got all the subdomains, let's process them */
|
|
|
2fc102 |
- ret = ad_subdomains_refresh(ctx->sd_ctx, ctx->reply_count, ctx->reply,
|
|
|
2fc102 |
+ ret = ad_subdomains_refresh(ctx->sd_ctx, nsubdoms, subdoms,
|
|
|
2fc102 |
&refresh_has_changes);
|
|
|
2fc102 |
if (ret != EOK) {
|
|
|
2fc102 |
DEBUG(SSSDBG_OP_FAILURE, ("Failed to refresh subdomains.\n"));
|
|
|
2fc102 |
--
|
|
|
2fc102 |
1.9.0
|
|
|
2fc102 |
|