|
|
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 |
|