Blame SOURCES/0018-ad-add-ad_check_domain_-send-recv.patch

1bb595
From 3ae3286d61ed796f0be7a1d72157af3687bc04a5 Mon Sep 17 00:00:00 2001
1bb595
From: Sumit Bose <sbose@redhat.com>
1bb595
Date: Thu, 7 May 2020 21:26:16 +0200
1bb595
Subject: [PATCH 18/19] ad: add ad_check_domain_{send|recv}
1bb595
MIME-Version: 1.0
1bb595
Content-Type: text/plain; charset=UTF-8
1bb595
Content-Transfer-Encoding: 8bit
1bb595
1bb595
This new request tries to get the basic domain information like domain
1bb595
SID and NetBIOS domain name for a domain given by the name. To achieve
1bb595
this the needed data is added to general domain structure and the SDAP
1bb595
domain structure. If the domain data cannot be looked up the data is
1bb595
removed again.
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 | 251 +++++++++++++++++++++++++++++++
1bb595
 1 file changed, 251 insertions(+)
1bb595
1bb595
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
1bb595
index 198f5c916..299aa7391 100644
1bb595
--- a/src/providers/ad/ad_subdomains.c
1bb595
+++ b/src/providers/ad/ad_subdomains.c
1bb595
@@ -2143,3 +2143,254 @@ errno_t ad_subdomains_init(TALLOC_CTX *mem_ctx,
1bb595
 
1bb595
     return EOK;
1bb595
 }
1bb595
+
1bb595
+struct ad_check_domain_state {
1bb595
+    struct tevent_context *ev;
1bb595
+    struct be_ctx *be_ctx;
1bb595
+    struct sdap_id_op *sdap_op;
1bb595
+    struct ad_id_ctx *dom_id_ctx;
1bb595
+    struct sdap_options *opts;
1bb595
+
1bb595
+    const char *dom_name;
1bb595
+    struct sss_domain_info *dom;
1bb595
+    struct sss_domain_info *parent;
1bb595
+    struct sdap_domain *sdom;
1bb595
+
1bb595
+    char *flat;
1bb595
+    char *site;
1bb595
+    char *forest;
1bb595
+    char *sid;
1bb595
+};
1bb595
+
1bb595
+static void ad_check_domain_connect_done(struct tevent_req *subreq);
1bb595
+static void ad_check_domain_done(struct tevent_req *subreq);
1bb595
+
1bb595
+static int ad_check_domain_destructor(void *mem)
1bb595
+{
1bb595
+    struct ad_check_domain_state *state = talloc_get_type(mem,
1bb595
+                                                  struct ad_check_domain_state);
1bb595
+
1bb595
+    if (state->sdom != NULL) {
1bb595
+        DEBUG(SSSDBG_TRACE_ALL, "Removing sdap domain [%s].\n",
1bb595
+                                state->dom->name);
1bb595
+        sdap_domain_remove(state->opts, state->dom);
1bb595
+        /* terminate all requests for this subdomain so we can free it */
1bb595
+        dp_terminate_domain_requests(state->be_ctx->provider, state->dom->name);
1bb595
+        talloc_zfree(state->sdom);
1bb595
+    }
1bb595
+
1bb595
+    if (state->dom != NULL) {
1bb595
+        DEBUG(SSSDBG_TRACE_ALL, "Removing domain [%s].\n", state->dom->name);
1bb595
+        sss_domain_set_state(state->dom, DOM_DISABLED);
1bb595
+        DLIST_REMOVE(state->be_ctx->domain->subdomains, state->dom);
1bb595
+        talloc_zfree(state->dom);
1bb595
+    }
1bb595
+
1bb595
+    return 0;
1bb595
+}
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
+{
1bb595
+    errno_t ret;
1bb595
+    struct tevent_req *req;
1bb595
+    struct tevent_req *subreq;
1bb595
+    struct ad_check_domain_state *state;
1bb595
+
1bb595
+    req = tevent_req_create(mem_ctx, &state, struct ad_check_domain_state);
1bb595
+    if (req == NULL) {
1bb595
+        DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
1bb595
+        return NULL;
1bb595
+    }
1bb595
+
1bb595
+    state->ev = ev;
1bb595
+    state->be_ctx = be_ctx;
1bb595
+    state->opts = ad_id_ctx->sdap_id_ctx->opts;
1bb595
+    state->dom_name = dom_name;
1bb595
+    state->parent = NULL;
1bb595
+    state->sdom = NULL;
1bb595
+
1bb595
+    state->dom = find_domain_by_name(be_ctx->domain, dom_name, true);
1bb595
+    if (state->dom == NULL) {
1bb595
+        state->parent = find_domain_by_name(be_ctx->domain, parent_dom_name,
1bb595
+                                            true);
1bb595
+        if (state->parent == NULL) {
1bb595
+            DEBUG(SSSDBG_OP_FAILURE,
1bb595
+                  "Failed to find domain object for domain [%s].\n",
1bb595
+                  parent_dom_name);
1bb595
+            ret = ENOENT;
1bb595
+            goto immediately;
1bb595
+        }
1bb595
+
1bb595
+        state->dom = new_subdomain(state->parent, state->parent, dom_name,
1bb595
+                                   dom_name, NULL, NULL, MPG_DISABLED, false,
1bb595
+                                   state->parent->forest,
1bb595
+                                   NULL, 0, be_ctx->cdb, true);
1bb595
+        if (state->dom == NULL) {
1bb595
+            DEBUG(SSSDBG_OP_FAILURE, "new_subdomain() failed.\n");
1bb595
+            ret = EINVAL;
1bb595
+            goto immediately;
1bb595
+        }
1bb595
+
1bb595
+        talloc_set_destructor((TALLOC_CTX *) state, ad_check_domain_destructor);
1bb595
+
1bb595
+        DLIST_ADD_END(state->parent->subdomains, state->dom,
1bb595
+                      struct sss_domain_info *);
1bb595
+
1bb595
+        ret = sdap_domain_add(state->opts, state->dom, &state->sdom);
1bb595
+        if (ret != EOK) {
1bb595
+            DEBUG(SSSDBG_OP_FAILURE, "sdap_domain_subdom_add failed.\n");
1bb595
+            goto immediately;
1bb595
+        }
1bb595
+
1bb595
+        ret = ad_set_search_bases(ad_id_ctx->ad_options->id, state->sdom);
1bb595
+        if (ret != EOK) {
1bb595
+            DEBUG(SSSDBG_MINOR_FAILURE, "failed to set ldap search bases for "
1bb595
+                  "domain '%s'. Will try to use automatically detected search "
1bb595
+                  "bases.", state->sdom->dom->name);
1bb595
+        }
1bb595
+
1bb595
+    }
1bb595
+
1bb595
+    state->dom_id_ctx = ads_get_dom_id_ctx(be_ctx, ad_id_ctx, state->dom,
1bb595
+                                           state->opts);
1bb595
+    if (state->dom_id_ctx == NULL) {
1bb595
+        DEBUG(SSSDBG_OP_FAILURE, "ads_get_dom_id_ctx() failed.\n");
1bb595
+        ret = EINVAL;
1bb595
+        goto immediately;
1bb595
+    }
1bb595
+
1bb595
+    state->sdap_op = sdap_id_op_create(state,
1bb595
+                             state->dom_id_ctx->sdap_id_ctx->conn->conn_cache);
1bb595
+    if (state->sdap_op == NULL) {
1bb595
+        DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
1bb595
+         ret = ENOMEM;
1bb595
+         goto immediately;
1bb595
+    }
1bb595
+
1bb595
+    subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret;;
1bb595
+    if (subreq == NULL) {
1bb595
+        DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed "
1bb595
+              "[%d]: %s\n", ret, sss_strerror(ret));
1bb595
+         goto immediately;
1bb595
+    }
1bb595
+
1bb595
+    tevent_req_set_callback(subreq, ad_check_domain_connect_done, req);
1bb595
+
1bb595
+    return req;
1bb595
+
1bb595
+immediately:
1bb595
+    if (ret == EOK) {
1bb595
+        tevent_req_done(req);
1bb595
+    } else {
1bb595
+        tevent_req_error(req, ret);
1bb595
+    }
1bb595
+    tevent_req_post(req, ev);
1bb595
+
1bb595
+    return req;
1bb595
+}
1bb595
+
1bb595
+static void ad_check_domain_connect_done(struct tevent_req *subreq)
1bb595
+{
1bb595
+    struct tevent_req *req;
1bb595
+    struct ad_check_domain_state *state;
1bb595
+    int ret;
1bb595
+    int dp_error;
1bb595
+
1bb595
+    req = tevent_req_callback_data(subreq, struct tevent_req);
1bb595
+    state = tevent_req_data(req, struct ad_check_domain_state);
1bb595
+
1bb595
+    ret = sdap_id_op_connect_recv(subreq, &dp_error);
1bb595
+    talloc_zfree(subreq);
1bb595
+
1bb595
+    if (ret != EOK) {
1bb595
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP "
1bb595
+              "[%d]: %s\n", ret, sss_strerror(ret));
1bb595
+        if (dp_error == DP_ERR_OFFLINE) {
1bb595
+            DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, "
1bb595
+                  "cannot get the subdomain list while offline\n");
1bb595
+            ret = ERR_OFFLINE;
1bb595
+        }
1bb595
+        tevent_req_error(req, ret);
1bb595
+        return;
1bb595
+    }
1bb595
+
1bb595
+    subreq = ad_domain_info_send(state, state->ev,
1bb595
+                                 state->dom_id_ctx->sdap_id_ctx->conn,
1bb595
+                                 state->sdap_op, state->dom_name);
1bb595
+
1bb595
+    tevent_req_set_callback(subreq, ad_check_domain_done, req);
1bb595
+
1bb595
+    return;
1bb595
+}
1bb595
+
1bb595
+static void ad_check_domain_done(struct tevent_req *subreq)
1bb595
+{
1bb595
+    struct tevent_req *req;
1bb595
+    struct ad_check_domain_state *state;
1bb595
+    errno_t ret;
1bb595
+
1bb595
+
1bb595
+    req = tevent_req_callback_data(subreq, struct tevent_req);
1bb595
+    state = tevent_req_data(req, struct ad_check_domain_state);
1bb595
+
1bb595
+    ret = ad_domain_info_recv(subreq, state, &state->flat, &state->sid,
1bb595
+                              &state->site, &state->forest);
1bb595
+    talloc_zfree(subreq);
1bb595
+    if (ret != EOK) {
1bb595
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to lookup domain information "
1bb595
+              "[%d]: %s\n", ret, sss_strerror(ret));
1bb595
+        goto done;
1bb595
+    }
1bb595
+    DEBUG(SSSDBG_TRACE_ALL, "%s %s %s %s.\n", state->flat, state->sid,
1bb595
+                                              state->site, state->forest);
1bb595
+
1bb595
+    /* New domain was successfully checked, remove destructor. */
1bb595
+    talloc_set_destructor(state, NULL);
1bb595
+
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
+}
1bb595
+
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
+    struct ad_check_domain_state *state = tevent_req_data(req,
1bb595
+                                                  struct ad_check_domain_state);
1bb595
+
1bb595
+    TEVENT_REQ_RETURN_ON_ERROR(req);
1bb595
+
1bb595
+    if (_flat) {
1bb595
+        *_flat = talloc_steal(mem_ctx, state->flat);
1bb595
+    }
1bb595
+
1bb595
+    if (_site) {
1bb595
+        *_site = talloc_steal(mem_ctx, state->site);
1bb595
+    }
1bb595
+
1bb595
+    if (_forest) {
1bb595
+        *_forest = talloc_steal(mem_ctx, state->forest);
1bb595
+    }
1bb595
+
1bb595
+    if (_id) {
1bb595
+        *_id = talloc_steal(mem_ctx, state->sid);
1bb595
+    }
1bb595
+
1bb595
+    return EOK;
1bb595
+}
1bb595
-- 
1bb595
2.21.3
1bb595