|
|
9f2ebf |
From 427a1f162e0ceb97e4e9491f81048646bd144910 Mon Sep 17 00:00:00 2001
|
|
|
9f2ebf |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
9f2ebf |
Date: Tue, 7 Nov 2017 17:01:34 +0100
|
|
|
9f2ebf |
Subject: [PATCH 74/83] AD: Implement a real getAccountDomain handler for the
|
|
|
9f2ebf |
AD provider
|
|
|
9f2ebf |
MIME-Version: 1.0
|
|
|
9f2ebf |
Content-Type: text/plain; charset=UTF-8
|
|
|
9f2ebf |
Content-Transfer-Encoding: 8bit
|
|
|
9f2ebf |
|
|
|
9f2ebf |
After this patch, the AD provider drops the default getAccountDomain
|
|
|
9f2ebf |
handler in favor of the handler added in this patch.
|
|
|
9f2ebf |
|
|
|
9f2ebf |
The handler first checks if the domain is eligible for locating
|
|
|
9f2ebf |
the domain of an ID with the help of the Global Catalog at all, which
|
|
|
9f2ebf |
only happens if:
|
|
|
9f2ebf |
- the Global Catalog is enabled
|
|
|
9f2ebf |
- POSIX IDs are used, not ID-mapping
|
|
|
9f2ebf |
- the Global catalog contains some POSIX IDs
|
|
|
9f2ebf |
|
|
|
9f2ebf |
If all these hold true, then the Global Catalog is searched with
|
|
|
9f2ebf |
an empty search base, which searches the whole GC. If a single entry
|
|
|
9f2ebf |
is returned, its original DN is converted to a domain name and returned.
|
|
|
9f2ebf |
|
|
|
9f2ebf |
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
|
|
9f2ebf |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
9f2ebf |
(cherry picked from commit 095844d6b48aef483c33e5a369a405ae686e044d)
|
|
|
9f2ebf |
---
|
|
|
9f2ebf |
src/providers/ad/ad_id.c | 469 +++++++++++++++++++++++++++++++++++++++++++++
|
|
|
9f2ebf |
src/providers/ad/ad_id.h | 10 +
|
|
|
9f2ebf |
src/providers/ad/ad_init.c | 4 +-
|
|
|
9f2ebf |
3 files changed, 481 insertions(+), 2 deletions(-)
|
|
|
9f2ebf |
|
|
|
9f2ebf |
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
|
|
|
9f2ebf |
index e14ada386f16851a65097952c85e57b7acda14aa..0b8f49819405c7dbbfa18b5359f7743441dc65e5 100644
|
|
|
9f2ebf |
--- a/src/providers/ad/ad_id.c
|
|
|
9f2ebf |
+++ b/src/providers/ad/ad_id.c
|
|
|
9f2ebf |
@@ -27,6 +27,7 @@
|
|
|
9f2ebf |
#include "providers/ad/ad_pac.h"
|
|
|
9f2ebf |
#include "providers/ldap/sdap_async_enum.h"
|
|
|
9f2ebf |
#include "providers/ldap/sdap_idmap.h"
|
|
|
9f2ebf |
+#include "providers/ldap/sdap_async.h"
|
|
|
9f2ebf |
|
|
|
9f2ebf |
static void
|
|
|
9f2ebf |
disable_gc(struct ad_options *ad_options)
|
|
|
9f2ebf |
@@ -1076,3 +1077,471 @@ ad_enumeration_recv(struct tevent_req *req)
|
|
|
9f2ebf |
return EOK;
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
|
|
|
9f2ebf |
+static errno_t ad_get_account_domain_prepare_search(struct tevent_req *req);
|
|
|
9f2ebf |
+static errno_t ad_get_account_domain_connect_retry(struct tevent_req *req);
|
|
|
9f2ebf |
+static void ad_get_account_domain_connect_done(struct tevent_req *subreq);
|
|
|
9f2ebf |
+static void ad_get_account_domain_posix_check_done(struct tevent_req *subreq);
|
|
|
9f2ebf |
+static void ad_get_account_domain_search(struct tevent_req *req);
|
|
|
9f2ebf |
+static void ad_get_account_domain_search_done(struct tevent_req *subreq);
|
|
|
9f2ebf |
+static void ad_get_account_domain_evaluate(struct tevent_req *req);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+struct ad_get_account_domain_state {
|
|
|
9f2ebf |
+ struct tevent_context *ev;
|
|
|
9f2ebf |
+ struct ad_id_ctx *id_ctx;
|
|
|
9f2ebf |
+ struct sdap_id_ctx *sdap_id_ctx;
|
|
|
9f2ebf |
+ struct sdap_domain *sdom;
|
|
|
9f2ebf |
+ uint32_t entry_type;
|
|
|
9f2ebf |
+ uint32_t filter_type;
|
|
|
9f2ebf |
+ char *clean_filter;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ bool twopass;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ struct sdap_search_base **search_bases;
|
|
|
9f2ebf |
+ size_t base_iter;
|
|
|
9f2ebf |
+ const char *base_filter;
|
|
|
9f2ebf |
+ char *filter;
|
|
|
9f2ebf |
+ const char **attrs;
|
|
|
9f2ebf |
+ int dp_error;
|
|
|
9f2ebf |
+ struct dp_reply_std reply;
|
|
|
9f2ebf |
+ struct sdap_id_op *op;
|
|
|
9f2ebf |
+ struct sysdb_attrs **objects;
|
|
|
9f2ebf |
+ size_t count;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ const char *found_domain_name;
|
|
|
9f2ebf |
+};
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+struct tevent_req *
|
|
|
9f2ebf |
+ad_get_account_domain_send(TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
+ struct ad_id_ctx *id_ctx,
|
|
|
9f2ebf |
+ struct dp_get_acct_domain_data *data,
|
|
|
9f2ebf |
+ struct dp_req_params *params)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state *state;
|
|
|
9f2ebf |
+ struct tevent_req *req;
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+ bool use_id_mapping;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ req = tevent_req_create(mem_ctx, &state,
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state);
|
|
|
9f2ebf |
+ if (req == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
|
|
9f2ebf |
+ return NULL;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ state->ev = params->ev;
|
|
|
9f2ebf |
+ state->id_ctx = id_ctx;
|
|
|
9f2ebf |
+ state->sdap_id_ctx = id_ctx->sdap_id_ctx;
|
|
|
9f2ebf |
+ state->entry_type = data->entry_type & BE_REQ_TYPE_MASK;
|
|
|
9f2ebf |
+ state->filter_type = data->filter_type;
|
|
|
9f2ebf |
+ state->attrs = talloc_array(state, const char *, 2);
|
|
|
9f2ebf |
+ if (state->attrs == NULL) {
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto immediately;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ state->attrs[0] = "objectclass";
|
|
|
9f2ebf |
+ state->attrs[1] = NULL;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (params->be_ctx->domain->mpg == true
|
|
|
9f2ebf |
+ || state->entry_type == BE_REQ_USER_AND_GROUP) {
|
|
|
9f2ebf |
+ state->twopass = true;
|
|
|
9f2ebf |
+ if (state->entry_type == BE_REQ_USER_AND_GROUP) {
|
|
|
9f2ebf |
+ state->entry_type = BE_REQ_GROUP;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /* The get-account-domain request only works with GC */
|
|
|
9f2ebf |
+ if (dp_opt_get_bool(id_ctx->ad_options->basic, AD_ENABLE_GC) == false) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_CONF_SETTINGS,
|
|
|
9f2ebf |
+ "Global catalog support is not enabled, "
|
|
|
9f2ebf |
+ "cannot locate the account domain\n");
|
|
|
9f2ebf |
+ ret = ERR_GET_ACCT_DOM_NOT_SUPPORTED;
|
|
|
9f2ebf |
+ goto immediately;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ state->sdom = sdap_domain_get(id_ctx->sdap_id_ctx->opts,
|
|
|
9f2ebf |
+ params->be_ctx->domain);
|
|
|
9f2ebf |
+ if (state->sdom == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find sdap_domain\n");
|
|
|
9f2ebf |
+ ret = EIO;
|
|
|
9f2ebf |
+ goto immediately;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /* Currently we only support locating the account domain
|
|
|
9f2ebf |
+ * if ID mapping is disabled. With ID mapping enabled, we can
|
|
|
9f2ebf |
+ * already shortcut the 'real' ID request
|
|
|
9f2ebf |
+ */
|
|
|
9f2ebf |
+ use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
|
|
|
9f2ebf |
+ state->sdap_id_ctx->opts->idmap_ctx,
|
|
|
9f2ebf |
+ state->sdom->dom->name,
|
|
|
9f2ebf |
+ state->sdom->dom->domain_id);
|
|
|
9f2ebf |
+ if (use_id_mapping == true) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_CONF_SETTINGS,
|
|
|
9f2ebf |
+ "No point in locating domain with GC if ID-mapping "
|
|
|
9f2ebf |
+ "is enabled\n");
|
|
|
9f2ebf |
+ ret = ERR_GET_ACCT_DOM_NOT_SUPPORTED;
|
|
|
9f2ebf |
+ goto immediately;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = sss_filter_sanitize(state, data->filter_value, &state->clean_filter);
|
|
|
9f2ebf |
+ if (ret != EOK) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Cannot sanitize filter [%d]: %s\n", ret, sss_strerror(ret));
|
|
|
9f2ebf |
+ goto immediately;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = ad_get_account_domain_prepare_search(req);
|
|
|
9f2ebf |
+ if (ret != EOK) {
|
|
|
9f2ebf |
+ goto immediately;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /* FIXME - should gc_ctx always default to ignore_offline on creation
|
|
|
9f2ebf |
+ * time rather than setting the flag on first use?
|
|
|
9f2ebf |
+ */
|
|
|
9f2ebf |
+ id_ctx->gc_ctx->ignore_mark_offline = true;
|
|
|
9f2ebf |
+ state->op = sdap_id_op_create(state, id_ctx->gc_ctx->conn_cache);
|
|
|
9f2ebf |
+ if (state->op == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto immediately;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = ad_get_account_domain_connect_retry(req);
|
|
|
9f2ebf |
+ if (ret != EOK) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "Connection error");
|
|
|
9f2ebf |
+ goto immediately;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ return req;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+immediately:
|
|
|
9f2ebf |
+ dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /* TODO For backward compatibility we always return EOK to DP now. */
|
|
|
9f2ebf |
+ tevent_req_done(req);
|
|
|
9f2ebf |
+ tevent_req_post(req, params->ev);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ return req;
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static errno_t ad_get_account_domain_prepare_search(struct tevent_req *req)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state *state = tevent_req_data(req,
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state);
|
|
|
9f2ebf |
+ const char *attr_name = NULL;
|
|
|
9f2ebf |
+ const char *objectclass = NULL;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ switch (state->entry_type) {
|
|
|
9f2ebf |
+ case BE_REQ_USER:
|
|
|
9f2ebf |
+ state->search_bases = state->sdom->user_search_bases;
|
|
|
9f2ebf |
+ attr_name = state->sdap_id_ctx->opts->user_map[SDAP_AT_USER_UID].name;
|
|
|
9f2ebf |
+ objectclass = state->sdap_id_ctx->opts->user_map[SDAP_OC_USER].name;
|
|
|
9f2ebf |
+ break;
|
|
|
9f2ebf |
+ case BE_REQ_GROUP:
|
|
|
9f2ebf |
+ state->search_bases = state->sdom->group_search_bases;
|
|
|
9f2ebf |
+ attr_name = state->sdap_id_ctx->opts->group_map[SDAP_AT_GROUP_GID].name;
|
|
|
9f2ebf |
+ objectclass = state->sdap_id_ctx->opts->group_map[SDAP_OC_GROUP].name;
|
|
|
9f2ebf |
+ break;
|
|
|
9f2ebf |
+ default:
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Unsupported request type %X\n",
|
|
|
9f2ebf |
+ state->entry_type & BE_REQ_TYPE_MASK);
|
|
|
9f2ebf |
+ return EINVAL;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ switch (state->filter_type) {
|
|
|
9f2ebf |
+ case BE_FILTER_IDNUM:
|
|
|
9f2ebf |
+ break;
|
|
|
9f2ebf |
+ default:
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Unsupported filter type %X\n", state->filter_type);
|
|
|
9f2ebf |
+ return EINVAL;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ talloc_zfree(state->base_filter);
|
|
|
9f2ebf |
+ state->base_filter = talloc_asprintf(state,
|
|
|
9f2ebf |
+ "(&(%s=%s)(objectclass=%s))",
|
|
|
9f2ebf |
+ attr_name,
|
|
|
9f2ebf |
+ state->clean_filter,
|
|
|
9f2ebf |
+ objectclass);
|
|
|
9f2ebf |
+ if (state->base_filter == NULL) {
|
|
|
9f2ebf |
+ return ENOMEM;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ return EOK;
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static errno_t ad_get_account_domain_connect_retry(struct tevent_req *req)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state *state = tevent_req_data(req,
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state);
|
|
|
9f2ebf |
+ struct tevent_req *subreq;
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ subreq = sdap_id_op_connect_send(state->op, state, &ret;;
|
|
|
9f2ebf |
+ if (subreq == NULL) {
|
|
|
9f2ebf |
+ return ENOMEM;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ tevent_req_set_callback(subreq, ad_get_account_domain_connect_done, req);
|
|
|
9f2ebf |
+ return ret;
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static void ad_get_account_domain_connect_done(struct tevent_req *subreq)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct tevent_req *req = tevent_req_callback_data(subreq,
|
|
|
9f2ebf |
+ struct tevent_req);
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state *state = tevent_req_data(req,
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state);
|
|
|
9f2ebf |
+ int dp_error = DP_ERR_FATAL;
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = sdap_id_op_connect_recv(subreq, &dp_error);
|
|
|
9f2ebf |
+ talloc_zfree(subreq);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (ret != EOK) {
|
|
|
9f2ebf |
+ state->dp_error = dp_error;
|
|
|
9f2ebf |
+ tevent_req_error(req, ret);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /* If POSIX attributes have been requested with an AD server and we
|
|
|
9f2ebf |
+ * have no idea about POSIX attributes support, run a one-time check
|
|
|
9f2ebf |
+ */
|
|
|
9f2ebf |
+ if (state->sdap_id_ctx->srv_opts &&
|
|
|
9f2ebf |
+ state->sdap_id_ctx->srv_opts->posix_checked == false) {
|
|
|
9f2ebf |
+ subreq = sdap_gc_posix_check_send(state,
|
|
|
9f2ebf |
+ state->ev,
|
|
|
9f2ebf |
+ state->sdap_id_ctx->opts,
|
|
|
9f2ebf |
+ sdap_id_op_handle(state->op),
|
|
|
9f2ebf |
+ dp_opt_get_int(
|
|
|
9f2ebf |
+ state->sdap_id_ctx->opts->basic,
|
|
|
9f2ebf |
+ SDAP_SEARCH_TIMEOUT));
|
|
|
9f2ebf |
+ if (subreq == NULL) {
|
|
|
9f2ebf |
+ tevent_req_error(req, ENOMEM);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ tevent_req_set_callback(subreq, ad_get_account_domain_posix_check_done, req);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ad_get_account_domain_search(req);
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static void ad_get_account_domain_posix_check_done(struct tevent_req *subreq)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct tevent_req *req = tevent_req_callback_data(subreq,
|
|
|
9f2ebf |
+ struct tevent_req);
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state *state = tevent_req_data(req,
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state);
|
|
|
9f2ebf |
+ int dp_error = DP_ERR_FATAL;
|
|
|
9f2ebf |
+ bool has_posix;
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+ errno_t ret2;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = sdap_gc_posix_check_recv(subreq, &has_posix);
|
|
|
9f2ebf |
+ talloc_zfree(subreq);
|
|
|
9f2ebf |
+ if (ret != EOK) {
|
|
|
9f2ebf |
+ /* We can only finish the id_op on error as the connection
|
|
|
9f2ebf |
+ * is re-used by the real search
|
|
|
9f2ebf |
+ */
|
|
|
9f2ebf |
+ ret2 = sdap_id_op_done(state->op, ret, &dp_error);
|
|
|
9f2ebf |
+ if (dp_error == DP_ERR_OK && ret2 != EOK) {
|
|
|
9f2ebf |
+ /* retry */
|
|
|
9f2ebf |
+ ret = ad_get_account_domain_connect_retry(req);
|
|
|
9f2ebf |
+ if (ret != EOK) {
|
|
|
9f2ebf |
+ tevent_req_error(req, ret);
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ tevent_req_error(req, ret);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ state->sdap_id_ctx->srv_opts->posix_checked = true;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /*
|
|
|
9f2ebf |
+ * If the GC has no POSIX attributes, there is nothing we can do.
|
|
|
9f2ebf |
+ * Return an error and let the responders disable the functionality
|
|
|
9f2ebf |
+ * from now on.
|
|
|
9f2ebf |
+ */
|
|
|
9f2ebf |
+ if (has_posix == false) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_CONF_SETTINGS,
|
|
|
9f2ebf |
+ "The Global Catalog has no POSIX attributes\n");
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ disable_gc(state->id_ctx->ad_options);
|
|
|
9f2ebf |
+ dp_reply_std_set(&state->reply,
|
|
|
9f2ebf |
+ DP_ERR_DECIDE, ERR_GET_ACCT_DOM_NOT_SUPPORTED,
|
|
|
9f2ebf |
+ NULL);
|
|
|
9f2ebf |
+ tevent_req_done(req);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ad_get_account_domain_search(req);
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static void ad_get_account_domain_search(struct tevent_req *req)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state *state = tevent_req_data(req,
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state);
|
|
|
9f2ebf |
+ struct tevent_req *subreq;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ talloc_zfree(state->filter);
|
|
|
9f2ebf |
+ state->filter = sdap_combine_filters(state, state->base_filter,
|
|
|
9f2ebf |
+ state->search_bases[state->base_iter]->filter);
|
|
|
9f2ebf |
+ if (state->filter == NULL) {
|
|
|
9f2ebf |
+ tevent_req_error(req, ENOMEM);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ subreq = sdap_get_generic_send(state, state->ev, state->sdap_id_ctx->opts,
|
|
|
9f2ebf |
+ sdap_id_op_handle(state->op),
|
|
|
9f2ebf |
+ "",
|
|
|
9f2ebf |
+ LDAP_SCOPE_SUBTREE,
|
|
|
9f2ebf |
+ state->filter,
|
|
|
9f2ebf |
+ state->attrs, NULL, 0,
|
|
|
9f2ebf |
+ dp_opt_get_int(state->sdap_id_ctx->opts->basic,
|
|
|
9f2ebf |
+ SDAP_SEARCH_TIMEOUT),
|
|
|
9f2ebf |
+ false);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (subreq == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
|
|
|
9f2ebf |
+ tevent_req_error(req, EIO);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ tevent_req_set_callback(subreq, ad_get_account_domain_search_done, req);
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static void ad_get_account_domain_search_done(struct tevent_req *subreq)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct tevent_req *req = tevent_req_callback_data(subreq,
|
|
|
9f2ebf |
+ struct tevent_req);
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state *state = tevent_req_data(req,
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state);
|
|
|
9f2ebf |
+ size_t count;
|
|
|
9f2ebf |
+ struct sysdb_attrs **objects;
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = sdap_get_generic_recv(subreq, state,
|
|
|
9f2ebf |
+ &count, &objects);
|
|
|
9f2ebf |
+ talloc_zfree(subreq);
|
|
|
9f2ebf |
+ if (ret) {
|
|
|
9f2ebf |
+ tevent_req_error(req, ret);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_TRACE_FUNC,
|
|
|
9f2ebf |
+ "Search returned %zu results.\n", count);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (count > 0) {
|
|
|
9f2ebf |
+ size_t copied;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ state->objects =
|
|
|
9f2ebf |
+ talloc_realloc(state,
|
|
|
9f2ebf |
+ state->objects,
|
|
|
9f2ebf |
+ struct sysdb_attrs *,
|
|
|
9f2ebf |
+ state->count + count + 1);
|
|
|
9f2ebf |
+ if (!state->objects) {
|
|
|
9f2ebf |
+ tevent_req_error(req, ENOMEM);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ copied = sdap_steal_objects_in_dom(state->sdap_id_ctx->opts,
|
|
|
9f2ebf |
+ state->objects,
|
|
|
9f2ebf |
+ state->count,
|
|
|
9f2ebf |
+ NULL,
|
|
|
9f2ebf |
+ objects, count,
|
|
|
9f2ebf |
+ false);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ state->count += copied;
|
|
|
9f2ebf |
+ state->objects[state->count] = NULL;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /* Even though we search with an empty search base (=across all domains)
|
|
|
9f2ebf |
+ * the reason we iterate over search bases is that the search bases can
|
|
|
9f2ebf |
+ * also contain a filter which might restrict the IDs we find
|
|
|
9f2ebf |
+ */
|
|
|
9f2ebf |
+ state->base_iter++;
|
|
|
9f2ebf |
+ if (state->search_bases[state->base_iter]) {
|
|
|
9f2ebf |
+ /* There are more search bases to try */
|
|
|
9f2ebf |
+ ad_get_account_domain_search(req);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /* No more searches, evaluate results */
|
|
|
9f2ebf |
+ ad_get_account_domain_evaluate(req);
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static void ad_get_account_domain_evaluate(struct tevent_req *req)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state *state = tevent_req_data(req,
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state);
|
|
|
9f2ebf |
+ struct sss_domain_info *obj_dom;
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (state->count == 0) {
|
|
|
9f2ebf |
+ if (state->twopass
|
|
|
9f2ebf |
+ && state->entry_type != BE_REQ_USER) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_TRACE_FUNC, "Retrying search\n");
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ state->entry_type = BE_REQ_USER;
|
|
|
9f2ebf |
+ state->base_iter = 0;
|
|
|
9f2ebf |
+ ret = ad_get_account_domain_prepare_search(req);
|
|
|
9f2ebf |
+ if (ret != EOK) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "Cannot retry search\n");
|
|
|
9f2ebf |
+ tevent_req_error(req, ret);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ad_get_account_domain_search(req);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_TRACE_FUNC, "Not found\n");
|
|
|
9f2ebf |
+ dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERR_NOT_FOUND, NULL);
|
|
|
9f2ebf |
+ tevent_req_done(req);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ } else if (state->count > 1) {
|
|
|
9f2ebf |
+ /* FIXME: If more than one entry was found, return error for now
|
|
|
9f2ebf |
+ * as the account requsts have no way of returning multiple
|
|
|
9f2ebf |
+ * messages back until we switch to the rdp_* requests
|
|
|
9f2ebf |
+ * from the responder side
|
|
|
9f2ebf |
+ */
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "Multiple entries found, error!\n");
|
|
|
9f2ebf |
+ dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERANGE, NULL);
|
|
|
9f2ebf |
+ tevent_req_done(req);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /* Exactly one entry was found */
|
|
|
9f2ebf |
+ obj_dom = sdap_get_object_domain(state->sdap_id_ctx->opts,
|
|
|
9f2ebf |
+ state->objects[0],
|
|
|
9f2ebf |
+ state->sdom->dom);
|
|
|
9f2ebf |
+ if (obj_dom == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f2ebf |
+ "Could not match entry with domain!\n");
|
|
|
9f2ebf |
+ dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERR_NOT_FOUND, NULL);
|
|
|
9f2ebf |
+ tevent_req_done(req);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_TRACE_INTERNAL,
|
|
|
9f2ebf |
+ "Found object in domain %s\n", obj_dom->name);
|
|
|
9f2ebf |
+ dp_reply_std_set(&state->reply, DP_ERR_DECIDE, EOK, obj_dom->name);
|
|
|
9f2ebf |
+ tevent_req_done(req);
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+errno_t ad_get_account_domain_recv(TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
+ struct tevent_req *req,
|
|
|
9f2ebf |
+ struct dp_reply_std *data)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct ad_get_account_domain_state *state = NULL;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ state = tevent_req_data(req, struct ad_get_account_domain_state);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ *data = state->reply;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ return EOK;
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
diff --git a/src/providers/ad/ad_id.h b/src/providers/ad/ad_id.h
|
|
|
9f2ebf |
index 145fdc8f2dfdeda5a17b0ce5892a547da934c244..5154393c5f125f472c92155006aac14d04bbca1a 100644
|
|
|
9f2ebf |
--- a/src/providers/ad/ad_id.h
|
|
|
9f2ebf |
+++ b/src/providers/ad/ad_id.h
|
|
|
9f2ebf |
@@ -54,4 +54,14 @@ ad_enumeration_send(TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
errno_t
|
|
|
9f2ebf |
ad_enumeration_recv(struct tevent_req *req);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
+struct tevent_req *
|
|
|
9f2ebf |
+ad_get_account_domain_send(TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
+ struct ad_id_ctx *id_ctx,
|
|
|
9f2ebf |
+ struct dp_get_acct_domain_data *data,
|
|
|
9f2ebf |
+ struct dp_req_params *params);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+errno_t ad_get_account_domain_recv(TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
+ struct tevent_req *req,
|
|
|
9f2ebf |
+ struct dp_reply_std *data);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
#endif /* AD_ID_H_ */
|
|
|
9f2ebf |
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
|
|
|
9f2ebf |
index 7efb6aa71cbd2551422c87e0b0c5c1fe91390375..22a3ecf7e5a020da88b6c9164f5999d13a9aa5e3 100644
|
|
|
9f2ebf |
--- a/src/providers/ad/ad_init.c
|
|
|
9f2ebf |
+++ b/src/providers/ad/ad_init.c
|
|
|
9f2ebf |
@@ -511,8 +511,8 @@ errno_t sssm_ad_id_init(TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
struct sdap_id_ctx, void, struct dp_reply_std);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER,
|
|
|
9f2ebf |
- default_account_domain_send, default_account_domain_recv, NULL,
|
|
|
9f2ebf |
- void, struct dp_get_acct_domain_data, struct dp_reply_std);
|
|
|
9f2ebf |
+ ad_get_account_domain_send, ad_get_account_domain_recv, id_ctx,
|
|
|
9f2ebf |
+ struct ad_id_ctx, struct dp_get_acct_domain_data, struct dp_reply_std);
|
|
|
9f2ebf |
|
|
|
9f2ebf |
return EOK;
|
|
|
9f2ebf |
}
|
|
|
9f2ebf |
--
|
|
|
9f2ebf |
2.14.3
|
|
|
9f2ebf |
|