|
|
9f89df |
From 2341059ba000d4fa87691f84bf3c39822b38aecb Mon Sep 17 00:00:00 2001
|
|
|
9f89df |
From: Sumit Bose <sbose@redhat.com>
|
|
|
9f89df |
Date: Tue, 18 Oct 2016 18:18:44 +0200
|
|
|
9f89df |
Subject: [PATCH 146/151] LDAP/AD: resolve domain local groups for remote users
|
|
|
9f89df |
|
|
|
9f89df |
If a user from a trusted domain in the same forest is a direct or
|
|
|
9f89df |
indirect member of domain local groups from the local domain those
|
|
|
9f89df |
memberships must be resolved as well. Since those domain local groups
|
|
|
9f89df |
are not valid in the trusted domain a DC from the trusted domain which
|
|
|
9f89df |
is used to lookup the user data is not aware of them. As a consequence
|
|
|
9f89df |
those memberships must be resolved against a local DC in a second step.
|
|
|
9f89df |
|
|
|
9f89df |
Resolves https://fedorahosted.org/sssd/ticket/3206
|
|
|
9f89df |
|
|
|
9f89df |
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
9f89df |
(cherry picked from commit 25699846bd1c9f8bb513b6271eb4366ab682fbd2)
|
|
|
9f89df |
---
|
|
|
9f89df |
src/db/sysdb.h | 2 +
|
|
|
9f89df |
src/providers/ldap/sdap_async_initgroups.c | 158 +++++++++-
|
|
|
9f89df |
src/providers/ldap/sdap_async_initgroups_ad.c | 407 ++++++++++++++++++++++++++
|
|
|
9f89df |
src/providers/ldap/sdap_async_private.h | 10 +
|
|
|
9f89df |
4 files changed, 570 insertions(+), 7 deletions(-)
|
|
|
9f89df |
|
|
|
9f89df |
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
|
|
|
9f89df |
index 4164657c2b329a240d46fe3ecdfb4b2eefffc5b3..a0279fb249e1258c9cb73a4fcab55e4b242c61f3 100644
|
|
|
9f89df |
--- a/src/db/sysdb.h
|
|
|
9f89df |
+++ b/src/db/sysdb.h
|
|
|
9f89df |
@@ -224,6 +224,8 @@
|
|
|
9f89df |
SYSDB_OVERRIDE_DN, \
|
|
|
9f89df |
SYSDB_OVERRIDE_OBJECT_DN, \
|
|
|
9f89df |
SYSDB_DEFAULT_OVERRIDE_NAME, \
|
|
|
9f89df |
+ SYSDB_UUID, \
|
|
|
9f89df |
+ SYSDB_ORIG_DN, \
|
|
|
9f89df |
NULL}
|
|
|
9f89df |
|
|
|
9f89df |
#define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \
|
|
|
9f89df |
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
|
|
|
9f89df |
index f1ba65a98b07a593b0e3a722d0b2c56c8e4b821e..8eaba261c49082d086df9f19464ac0f40fae71fb 100644
|
|
|
9f89df |
--- a/src/providers/ldap/sdap_async_initgroups.c
|
|
|
9f89df |
+++ b/src/providers/ldap/sdap_async_initgroups.c
|
|
|
9f89df |
@@ -2317,6 +2317,7 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req)
|
|
|
9f89df |
struct sdap_rfc2307bis_nested_ctx *state =
|
|
|
9f89df |
tevent_req_data(req, struct sdap_rfc2307bis_nested_ctx);
|
|
|
9f89df |
char *oc_list;
|
|
|
9f89df |
+ const char *class;
|
|
|
9f89df |
|
|
|
9f89df |
tmp_ctx = talloc_new(state);
|
|
|
9f89df |
if (!tmp_ctx) {
|
|
|
9f89df |
@@ -2324,9 +2325,21 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req)
|
|
|
9f89df |
goto done;
|
|
|
9f89df |
}
|
|
|
9f89df |
|
|
|
9f89df |
- ret = sdap_get_group_primary_name(state, state->opts,
|
|
|
9f89df |
- state->groups[state->group_iter],
|
|
|
9f89df |
- state->dom, &state->primary_name);
|
|
|
9f89df |
+ ret = sysdb_attrs_get_string(state->groups[state->group_iter],
|
|
|
9f89df |
+ SYSDB_OBJECTCLASS, &class);
|
|
|
9f89df |
+ if (ret == EOK) {
|
|
|
9f89df |
+ /* If there is a objectClass attribute the object is coming from the
|
|
|
9f89df |
+ * cache and the name attribute of the object already has the primary
|
|
|
9f89df |
+ * name.
|
|
|
9f89df |
+ * If the objectClass attribute is missing the object is coming from
|
|
|
9f89df |
+ * LDAP and we have to find the primary name first. */
|
|
|
9f89df |
+ ret = sysdb_attrs_get_string(state->groups[state->group_iter],
|
|
|
9f89df |
+ SYSDB_NAME, &state->primary_name);
|
|
|
9f89df |
+ } else {
|
|
|
9f89df |
+ ret = sdap_get_group_primary_name(state, state->opts,
|
|
|
9f89df |
+ state->groups[state->group_iter],
|
|
|
9f89df |
+ state->dom, &state->primary_name);
|
|
|
9f89df |
+ }
|
|
|
9f89df |
if (ret != EOK) {
|
|
|
9f89df |
goto done;
|
|
|
9f89df |
}
|
|
|
9f89df |
@@ -3069,6 +3082,103 @@ fail:
|
|
|
9f89df |
tevent_req_error(req, ret);
|
|
|
9f89df |
}
|
|
|
9f89df |
|
|
|
9f89df |
+static void sdap_ad_check_domain_local_groups_done(struct tevent_req *subreq);
|
|
|
9f89df |
+
|
|
|
9f89df |
+errno_t sdap_ad_check_domain_local_groups(struct tevent_req *req)
|
|
|
9f89df |
+{
|
|
|
9f89df |
+ struct sdap_get_initgr_state *state = tevent_req_data(req,
|
|
|
9f89df |
+ struct sdap_get_initgr_state);
|
|
|
9f89df |
+ int ret;
|
|
|
9f89df |
+ struct sdap_domain *local_sdom;
|
|
|
9f89df |
+ const char *orig_name;
|
|
|
9f89df |
+ const char *sysdb_name;
|
|
|
9f89df |
+ struct ldb_result *res;
|
|
|
9f89df |
+ struct tevent_req *subreq;
|
|
|
9f89df |
+ struct sysdb_attrs **groups;
|
|
|
9f89df |
+
|
|
|
9f89df |
+ /* We only need to check for domain local groups in the AD case and if the
|
|
|
9f89df |
+ * user is not from our domain, i.e. if the user comes from a sub-domain.
|
|
|
9f89df |
+ */
|
|
|
9f89df |
+ if (state->opts->schema_type != SDAP_SCHEMA_AD
|
|
|
9f89df |
+ || !IS_SUBDOMAIN(state->dom)
|
|
|
9f89df |
+ || !dp_target_enabled(state->id_ctx->be->provider, "ad", DPT_ID)) {
|
|
|
9f89df |
+ return EOK;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ local_sdom = sdap_domain_get(state->id_ctx->opts, state->dom->parent);
|
|
|
9f89df |
+ if (local_sdom == NULL || local_sdom->pvt == NULL) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n",
|
|
|
9f89df |
+ state->dom->parent->name);
|
|
|
9f89df |
+ return EINVAL;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = sysdb_attrs_get_string(state->orig_user, SYSDB_NAME, &orig_name);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing name in user object.\n");
|
|
|
9f89df |
+ return ret;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ sysdb_name = sss_create_internal_fqname(state, orig_name, state->dom->name);
|
|
|
9f89df |
+ if (sysdb_name == NULL) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "sss_create_internal_fqname failed.\n");
|
|
|
9f89df |
+ return ENOMEM;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = sysdb_initgroups(state, state->dom, sysdb_name, &res;;
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_initgroups failed for user [%s].\n",
|
|
|
9f89df |
+ sysdb_name);
|
|
|
9f89df |
+ return ret;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ if (res->count == 0) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
9f89df |
+ "sysdb_initgroups returned no results for user [%s].\n",
|
|
|
9f89df |
+ sysdb_name);
|
|
|
9f89df |
+ return EINVAL;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ /* The user object, the first entry in the res->msgs, is included as well
|
|
|
9f89df |
+ * to cover the case where the remote user is directly added to
|
|
|
9f89df |
+ * a domain local group. */
|
|
|
9f89df |
+ ret = sysdb_msg2attrs(state, res->count, res->msgs, &groups);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_msg2attrs failed.\n");
|
|
|
9f89df |
+ return ret;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ subreq = sdap_ad_get_domain_local_groups_send(state, state->ev, local_sdom,
|
|
|
9f89df |
+ state->opts, state->sysdb, state->dom->parent,
|
|
|
9f89df |
+ groups, res->count);
|
|
|
9f89df |
+ if (subreq == NULL) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "sdap_ad_get_domain_local_groups_send failed.\n");
|
|
|
9f89df |
+ return ENOMEM;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ tevent_req_set_callback(subreq, sdap_ad_check_domain_local_groups_done,
|
|
|
9f89df |
+ req);
|
|
|
9f89df |
+
|
|
|
9f89df |
+ return EAGAIN;
|
|
|
9f89df |
+}
|
|
|
9f89df |
+
|
|
|
9f89df |
+static void sdap_ad_check_domain_local_groups_done(struct tevent_req *subreq)
|
|
|
9f89df |
+{
|
|
|
9f89df |
+ struct tevent_req *req = tevent_req_callback_data(subreq,
|
|
|
9f89df |
+ struct tevent_req);
|
|
|
9f89df |
+ int ret;
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = sdap_ad_get_domain_local_groups_recv(subreq);
|
|
|
9f89df |
+ talloc_zfree(subreq);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ tevent_req_error(req, ret);
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ tevent_req_done(req);
|
|
|
9f89df |
+
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
+}
|
|
|
9f89df |
+
|
|
|
9f89df |
static void sdap_get_initgr_pgid(struct tevent_req *req);
|
|
|
9f89df |
static void sdap_get_initgr_done(struct tevent_req *subreq)
|
|
|
9f89df |
{
|
|
|
9f89df |
@@ -3201,8 +3311,6 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
|
|
|
9f89df |
if (ret == EOK) {
|
|
|
9f89df |
DEBUG(SSSDBG_TRACE_FUNC,
|
|
|
9f89df |
"Primary group already cached, nothing to do.\n");
|
|
|
9f89df |
- ret = EOK;
|
|
|
9f89df |
- goto done;
|
|
|
9f89df |
} else {
|
|
|
9f89df |
gid = talloc_asprintf(state, "%lu", (unsigned long)primary_gid);
|
|
|
9f89df |
if (gid == NULL) {
|
|
|
9f89df |
@@ -3219,10 +3327,28 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
|
|
|
9f89df |
goto done;
|
|
|
9f89df |
}
|
|
|
9f89df |
tevent_req_set_callback(subreq, sdap_get_initgr_pgid, req);
|
|
|
9f89df |
+
|
|
|
9f89df |
+ talloc_free(tmp_ctx);
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
}
|
|
|
9f89df |
|
|
|
9f89df |
- talloc_free(tmp_ctx);
|
|
|
9f89df |
- return;
|
|
|
9f89df |
+ ret = sdap_ad_check_domain_local_groups(req);
|
|
|
9f89df |
+ if (ret == EAGAIN) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_TRACE_ALL,
|
|
|
9f89df |
+ "Checking for domain local group memberships.\n");
|
|
|
9f89df |
+ talloc_free(tmp_ctx);
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
+ } else if (ret == EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_TRACE_ALL,
|
|
|
9f89df |
+ "No need to check for domain local group memberships.\n");
|
|
|
9f89df |
+ } else {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f89df |
+ "sdap_ad_check_domain_local_groups failed, "
|
|
|
9f89df |
+ "meberships to domain local groups might be missing.\n");
|
|
|
9f89df |
+ /* do not let the request fail completely because we already have at
|
|
|
9f89df |
+ * least "some" groups */
|
|
|
9f89df |
+ ret = EOK;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
|
|
|
9f89df |
done:
|
|
|
9f89df |
talloc_free(tmp_ctx);
|
|
|
9f89df |
@@ -3247,7 +3373,25 @@ static void sdap_get_initgr_pgid(struct tevent_req *subreq)
|
|
|
9f89df |
return;
|
|
|
9f89df |
}
|
|
|
9f89df |
|
|
|
9f89df |
+ ret = sdap_ad_check_domain_local_groups(req);
|
|
|
9f89df |
+ if (ret == EAGAIN) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_TRACE_ALL,
|
|
|
9f89df |
+ "Checking for domain local group memberships.\n");
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
+ } else if (ret == EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_TRACE_ALL,
|
|
|
9f89df |
+ "No need to check for domain local group memberships.\n");
|
|
|
9f89df |
+ } else {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "sdap_ad_check_domain_local_groups failed.\n");
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f89df |
+ "sdap_ad_check_domain_local_groups failed, "
|
|
|
9f89df |
+ "meberships to domain local groups might be missing.\n");
|
|
|
9f89df |
+ /* do not let the request fail completely because we already have at
|
|
|
9f89df |
+ * least "some" groups */
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
tevent_req_done(req);
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
}
|
|
|
9f89df |
|
|
|
9f89df |
int sdap_get_initgr_recv(struct tevent_req *req)
|
|
|
9f89df |
diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
|
|
|
9f89df |
index ad54c1fb837eb4b8e123a1c230feb697eb37bb41..1fee4ab43a6c13803a088ffa4695dde7f39b3d2b 100644
|
|
|
9f89df |
--- a/src/providers/ldap/sdap_async_initgroups_ad.c
|
|
|
9f89df |
+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
|
|
|
9f89df |
@@ -1412,6 +1412,413 @@ static errno_t sdap_ad_tokengroups_initgr_posix_recv(struct tevent_req *req)
|
|
|
9f89df |
return EOK;
|
|
|
9f89df |
}
|
|
|
9f89df |
|
|
|
9f89df |
+struct sdap_ad_get_domain_local_groups_state {
|
|
|
9f89df |
+ struct tevent_context *ev;
|
|
|
9f89df |
+ struct sdap_id_conn_ctx *conn;
|
|
|
9f89df |
+ struct sdap_options *opts;
|
|
|
9f89df |
+ struct sdap_id_op *op;
|
|
|
9f89df |
+ struct sysdb_ctx *sysdb;
|
|
|
9f89df |
+ struct sss_domain_info *dom;
|
|
|
9f89df |
+ int dp_error;
|
|
|
9f89df |
+
|
|
|
9f89df |
+ struct sdap_search_base **search_bases;
|
|
|
9f89df |
+ struct sysdb_attrs **groups;
|
|
|
9f89df |
+ size_t num_groups;
|
|
|
9f89df |
+ hash_table_t *group_hash;
|
|
|
9f89df |
+};
|
|
|
9f89df |
+
|
|
|
9f89df |
+static void
|
|
|
9f89df |
+sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq);
|
|
|
9f89df |
+static void sdap_ad_get_domain_local_groups_done(struct tevent_req *subreq);
|
|
|
9f89df |
+
|
|
|
9f89df |
+struct tevent_req *
|
|
|
9f89df |
+sdap_ad_get_domain_local_groups_send(TALLOC_CTX *mem_ctx,
|
|
|
9f89df |
+ struct tevent_context *ev,
|
|
|
9f89df |
+ struct sdap_domain *local_sdom,
|
|
|
9f89df |
+ struct sdap_options *opts,
|
|
|
9f89df |
+ struct sysdb_ctx *sysdb,
|
|
|
9f89df |
+ struct sss_domain_info *dom,
|
|
|
9f89df |
+ struct sysdb_attrs **groups,
|
|
|
9f89df |
+ size_t num_groups)
|
|
|
9f89df |
+{
|
|
|
9f89df |
+ struct sdap_ad_get_domain_local_groups_state *state;
|
|
|
9f89df |
+ struct tevent_req *req;
|
|
|
9f89df |
+ struct tevent_req *subreq;
|
|
|
9f89df |
+ struct ad_id_ctx *ad_id_ctx;
|
|
|
9f89df |
+ errno_t ret;
|
|
|
9f89df |
+
|
|
|
9f89df |
+ req = tevent_req_create(mem_ctx, &state,
|
|
|
9f89df |
+ struct sdap_ad_get_domain_local_groups_state);
|
|
|
9f89df |
+ if (req == NULL) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
|
|
9f89df |
+ return NULL;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ state->ev = ev;
|
|
|
9f89df |
+ ad_id_ctx = talloc_get_type(local_sdom->pvt, struct ad_id_ctx);
|
|
|
9f89df |
+ state->conn = ad_id_ctx->ldap_ctx;
|
|
|
9f89df |
+ state->opts = opts;
|
|
|
9f89df |
+ state->sysdb = sysdb;
|
|
|
9f89df |
+ state->dom = dom;
|
|
|
9f89df |
+ state->search_bases = state->conn->id_ctx->opts->sdom->group_search_bases;
|
|
|
9f89df |
+ state->groups = groups;
|
|
|
9f89df |
+ state->num_groups = num_groups;
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = sss_hash_create(state, 32, &state->group_hash);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "sss_hash_create failed.\n");
|
|
|
9f89df |
+ goto fail;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ state->op = sdap_id_op_create(state, state->conn->conn_cache);
|
|
|
9f89df |
+ if (state->op == NULL) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
|
|
|
9f89df |
+ ret = ENOMEM;
|
|
|
9f89df |
+ goto fail;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ subreq = sdap_id_op_connect_send(state->op, state, &ret;;
|
|
|
9f89df |
+ if (subreq == NULL) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n");
|
|
|
9f89df |
+ goto fail;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ tevent_req_set_callback(subreq,
|
|
|
9f89df |
+ sdap_ad_get_domain_local_groups_connect_done, req);
|
|
|
9f89df |
+
|
|
|
9f89df |
+ return req;
|
|
|
9f89df |
+
|
|
|
9f89df |
+fail:
|
|
|
9f89df |
+ tevent_req_error(req, ret);
|
|
|
9f89df |
+ tevent_req_post(req, ev);
|
|
|
9f89df |
+ return req;
|
|
|
9f89df |
+}
|
|
|
9f89df |
+
|
|
|
9f89df |
+static void
|
|
|
9f89df |
+sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq)
|
|
|
9f89df |
+{
|
|
|
9f89df |
+
|
|
|
9f89df |
+ struct tevent_req *req = tevent_req_callback_data(subreq,
|
|
|
9f89df |
+ struct tevent_req);
|
|
|
9f89df |
+ struct sdap_ad_get_domain_local_groups_state *state = tevent_req_data(req,
|
|
|
9f89df |
+ struct sdap_ad_get_domain_local_groups_state);
|
|
|
9f89df |
+ int dp_error = DP_ERR_FATAL;
|
|
|
9f89df |
+ int ret;
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = sdap_id_op_connect_recv(subreq, &dp_error);
|
|
|
9f89df |
+ talloc_zfree(subreq);
|
|
|
9f89df |
+
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ state->dp_error = dp_error;
|
|
|
9f89df |
+ tevent_req_error(req, ret);
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ subreq = rfc2307bis_nested_groups_send(state, state->ev, state->opts,
|
|
|
9f89df |
+ state->sysdb, state->dom,
|
|
|
9f89df |
+ sdap_id_op_handle(state->op),
|
|
|
9f89df |
+ state->search_bases,
|
|
|
9f89df |
+ state->groups, state->num_groups,
|
|
|
9f89df |
+ state->group_hash, 0);
|
|
|
9f89df |
+ if (subreq == NULL) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "rfc2307bis_nested_groups_send failed.\n");
|
|
|
9f89df |
+ state->dp_error = DP_ERR_FATAL;
|
|
|
9f89df |
+ tevent_req_error(req, ENOMEM);
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ tevent_req_set_callback(subreq,
|
|
|
9f89df |
+ sdap_ad_get_domain_local_groups_done, req);
|
|
|
9f89df |
+
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
+}
|
|
|
9f89df |
+
|
|
|
9f89df |
+struct sdap_nested_group {
|
|
|
9f89df |
+ struct sysdb_attrs *group;
|
|
|
9f89df |
+ struct sysdb_attrs **ldap_parents;
|
|
|
9f89df |
+ size_t parents_count;
|
|
|
9f89df |
+};
|
|
|
9f89df |
+
|
|
|
9f89df |
+static errno_t
|
|
|
9f89df |
+sdap_ad_get_domain_local_groups_parse_parents(TALLOC_CTX *mem_ctx,
|
|
|
9f89df |
+ struct sdap_nested_group *gr,
|
|
|
9f89df |
+ struct sss_domain_info *dom,
|
|
|
9f89df |
+ struct sysdb_ctx *sysdb,
|
|
|
9f89df |
+ struct sdap_options *opts,
|
|
|
9f89df |
+ const char **_sysdb_name,
|
|
|
9f89df |
+ enum sysdb_member_type *_type,
|
|
|
9f89df |
+ char ***_add_list,
|
|
|
9f89df |
+ char ***_del_list)
|
|
|
9f89df |
+{
|
|
|
9f89df |
+ int ret;
|
|
|
9f89df |
+ size_t c;
|
|
|
9f89df |
+ char **groupnamelist = NULL;
|
|
|
9f89df |
+ struct sysdb_attrs *groups[1];
|
|
|
9f89df |
+ enum sysdb_member_type type;
|
|
|
9f89df |
+ const char *sysdb_name;
|
|
|
9f89df |
+ const char *group_name;
|
|
|
9f89df |
+ const char *class;
|
|
|
9f89df |
+ struct sss_domain_info *obj_dom;
|
|
|
9f89df |
+ char *local_groups_base_dn;
|
|
|
9f89df |
+ char **cached_local_parents = NULL;
|
|
|
9f89df |
+ char **add_list = NULL;
|
|
|
9f89df |
+ char **del_list = NULL;
|
|
|
9f89df |
+ TALLOC_CTX *tmp_ctx;
|
|
|
9f89df |
+
|
|
|
9f89df |
+ tmp_ctx = talloc_new(NULL);
|
|
|
9f89df |
+ if (tmp_ctx == NULL) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
|
|
|
9f89df |
+ return ENOMEM;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ local_groups_base_dn = talloc_asprintf(tmp_ctx, SYSDB_TMPL_GROUP_BASE,
|
|
|
9f89df |
+ dom->name);
|
|
|
9f89df |
+ if (local_groups_base_dn == NULL) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
|
|
|
9f89df |
+ ret = ENOMEM;
|
|
|
9f89df |
+ goto done;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ if (gr->parents_count != 0) {
|
|
|
9f89df |
+ /* Store the parents if needed */
|
|
|
9f89df |
+ ret = sdap_nested_groups_store(sysdb, dom, opts,
|
|
|
9f89df |
+ gr->ldap_parents, gr->parents_count);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_MINOR_FAILURE, "Could not save groups [%d]: %s\n",
|
|
|
9f89df |
+ ret, strerror(ret));
|
|
|
9f89df |
+ goto done;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = sysdb_attrs_primary_fqdn_list(dom, tmp_ctx,
|
|
|
9f89df |
+ gr->ldap_parents, gr->parents_count,
|
|
|
9f89df |
+ opts->group_map[SDAP_AT_GROUP_NAME].name,
|
|
|
9f89df |
+ &groupnamelist);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_primary_fqdn_list failed.\n");
|
|
|
9f89df |
+ goto done;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = sysdb_attrs_get_string(gr->group, SYSDB_NAME, &sysdb_name);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f89df |
+ "sysdb_attrs_get_string failed to get SYSDB_NAME, "
|
|
|
9f89df |
+ "skipping.\n");
|
|
|
9f89df |
+ goto done;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = sysdb_attrs_get_string(gr->group, SYSDB_OBJECTCLASS, &class);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ /* If objectclass is missing gr->group is a nested parent found during
|
|
|
9f89df |
+ * the nested group lookup. It might not already stored in the cache.
|
|
|
9f89df |
+ */
|
|
|
9f89df |
+ DEBUG(SSSDBG_TRACE_LIBS,
|
|
|
9f89df |
+ "sysdb_attrs_get_string failed to get SYSDB_OBJECTCLASS "
|
|
|
9f89df |
+ "for [%s], assuming group.\n", sysdb_name);
|
|
|
9f89df |
+
|
|
|
9f89df |
+ /* make sure group exists in cache */
|
|
|
9f89df |
+ groups[0]= gr->group;
|
|
|
9f89df |
+ ret = sdap_nested_groups_store(sysdb, dom, opts, groups, 1);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_MINOR_FAILURE, "Could not save groups [%d]: %s\n",
|
|
|
9f89df |
+ ret, strerror(ret));
|
|
|
9f89df |
+ goto done;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ /* Since the object is coming from LDAP it cannot have the internal
|
|
|
9f89df |
+ * fully-qualified name, so we can expand it unconditionally. */
|
|
|
9f89df |
+ group_name = NULL;
|
|
|
9f89df |
+ ret = sysdb_attrs_primary_name(dom->sysdb, gr->group,
|
|
|
9f89df |
+ opts->group_map[SDAP_AT_GROUP_NAME].name,
|
|
|
9f89df |
+ &group_name);
|
|
|
9f89df |
+ if (ret != EOK || group_name == NULL) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "Could not determine primary name\n");
|
|
|
9f89df |
+ group_name = sysdb_name;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ group_name = sss_create_internal_fqname(tmp_ctx, group_name,
|
|
|
9f89df |
+ dom->name);
|
|
|
9f89df |
+ if (group_name != NULL) {
|
|
|
9f89df |
+ sysdb_name = group_name;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ type = SYSDB_MEMBER_GROUP;
|
|
|
9f89df |
+ } else {
|
|
|
9f89df |
+ if (class != NULL && strcmp(class, SYSDB_USER_CLASS) == 0) {
|
|
|
9f89df |
+ type = SYSDB_MEMBER_USER;
|
|
|
9f89df |
+ } else {
|
|
|
9f89df |
+ type = SYSDB_MEMBER_GROUP;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ /* We need to get the cached list of groups form the local domain the
|
|
|
9f89df |
+ * object is a member of to compare them with the current list just
|
|
|
9f89df |
+ * retrieved (groupnamelist). Even if this list is empty we have to
|
|
|
9f89df |
+ * proceed because the membership might have been removed recently on the
|
|
|
9f89df |
+ * server. */
|
|
|
9f89df |
+
|
|
|
9f89df |
+ obj_dom = find_domain_by_object_name(get_domains_head(dom),
|
|
|
9f89df |
+ sysdb_name);
|
|
|
9f89df |
+ if (obj_dom == NULL) {
|
|
|
9f89df |
+ obj_dom = dom;
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "Cannot find domain for [%s], "
|
|
|
9f89df |
+ "trying with local domain [%s].\n",
|
|
|
9f89df |
+ sysdb_name, obj_dom->name);
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = sysdb_get_direct_parents(tmp_ctx, obj_dom, dom, type, sysdb_name,
|
|
|
9f89df |
+ &cached_local_parents);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE,"sysdb_get_direct_parents failed.\n");
|
|
|
9f89df |
+ goto done;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ if (cached_local_parents != NULL && cached_local_parents[0] == NULL) {
|
|
|
9f89df |
+ talloc_zfree(cached_local_parents);
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) {
|
|
|
9f89df |
+ if (cached_local_parents != NULL) {
|
|
|
9f89df |
+ for (c = 0; cached_local_parents[c] != NULL; c++) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_TRACE_ALL, "[%s] cached_local_parents [%s].\n",
|
|
|
9f89df |
+ sysdb_name, cached_local_parents[c]);
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ if (groupnamelist != NULL) {
|
|
|
9f89df |
+ for (c = 0; groupnamelist[c] != NULL; c++) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_TRACE_ALL, "[%s] groupnamelist [%s].\n",
|
|
|
9f89df |
+ sysdb_name, groupnamelist[c]);
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = diff_string_lists(tmp_ctx, cached_local_parents, groupnamelist,
|
|
|
9f89df |
+ &del_list, &add_list, NULL);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "diff_string_lists failed.\n");
|
|
|
9f89df |
+ goto done;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) {
|
|
|
9f89df |
+ if (add_list != NULL) {
|
|
|
9f89df |
+ for (c = 0; add_list[c] != NULL; c++) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_TRACE_ALL, "add: [%s] will be member of [%s].\n",
|
|
|
9f89df |
+ sysdb_name, add_list[c]);
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ if (del_list != NULL) {
|
|
|
9f89df |
+ for (c = 0; del_list[c] != NULL; c++) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_TRACE_ALL, "del: [%s] was member of [%s].\n",
|
|
|
9f89df |
+ sysdb_name, del_list[c]);
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ *_type = type;
|
|
|
9f89df |
+ *_sysdb_name = talloc_steal(mem_ctx, sysdb_name);
|
|
|
9f89df |
+ *_add_list = talloc_steal(mem_ctx, groupnamelist);
|
|
|
9f89df |
+ *_del_list = talloc_steal(mem_ctx, del_list);
|
|
|
9f89df |
+ ret = EOK;
|
|
|
9f89df |
+
|
|
|
9f89df |
+done:
|
|
|
9f89df |
+ talloc_free(tmp_ctx);
|
|
|
9f89df |
+
|
|
|
9f89df |
+ return ret;
|
|
|
9f89df |
+}
|
|
|
9f89df |
+
|
|
|
9f89df |
+static void sdap_ad_get_domain_local_groups_done(struct tevent_req *subreq)
|
|
|
9f89df |
+{
|
|
|
9f89df |
+
|
|
|
9f89df |
+ struct tevent_req *req = tevent_req_callback_data(subreq,
|
|
|
9f89df |
+ struct tevent_req);
|
|
|
9f89df |
+ struct sdap_ad_get_domain_local_groups_state *state = tevent_req_data(req,
|
|
|
9f89df |
+ struct sdap_ad_get_domain_local_groups_state);
|
|
|
9f89df |
+ int ret;
|
|
|
9f89df |
+ int hret;
|
|
|
9f89df |
+ unsigned long count;
|
|
|
9f89df |
+ hash_value_t *values = NULL;
|
|
|
9f89df |
+ struct sdap_nested_group *gr;
|
|
|
9f89df |
+ size_t c;
|
|
|
9f89df |
+ const char *sysdb_name = NULL;
|
|
|
9f89df |
+ enum sysdb_member_type type;
|
|
|
9f89df |
+ char **add_list = NULL;
|
|
|
9f89df |
+ char **del_list = NULL;
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = rfc2307bis_nested_groups_recv(subreq);
|
|
|
9f89df |
+ talloc_zfree(subreq);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ tevent_req_error(req, ret);
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ hret = hash_values(state->group_hash, &count, &values);
|
|
|
9f89df |
+ if (hret != HASH_SUCCESS) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "hash_values failed.\n");
|
|
|
9f89df |
+ ret = EIO;
|
|
|
9f89df |
+ goto done;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ for (c = 0; c < count; c++) {
|
|
|
9f89df |
+ gr = talloc_get_type(values[c].ptr,
|
|
|
9f89df |
+ struct sdap_nested_group);
|
|
|
9f89df |
+
|
|
|
9f89df |
+ /* The values from the hash are either user or group objects returned
|
|
|
9f89df |
+ * by sysdb_initgroups() which where used to start the request or
|
|
|
9f89df |
+ * nested parents found during the request. The nested parents contain
|
|
|
9f89df |
+ * the processed LDAP data and can be identified by a missing
|
|
|
9f89df |
+ * objectclass attribute. */
|
|
|
9f89df |
+ ret = sdap_ad_get_domain_local_groups_parse_parents(state, gr,
|
|
|
9f89df |
+ state->dom,
|
|
|
9f89df |
+ state->sysdb,
|
|
|
9f89df |
+ state->opts,
|
|
|
9f89df |
+ &sysdb_name,
|
|
|
9f89df |
+ &type,
|
|
|
9f89df |
+ &add_list,
|
|
|
9f89df |
+ &del_list);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
9f89df |
+ "sdap_ad_get_domain_local_groups_parse_parents failed.\n");
|
|
|
9f89df |
+ continue;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ if ((add_list == NULL && del_list == NULL)
|
|
|
9f89df |
+ || (add_list == NULL && del_list != NULL && del_list[0] == NULL)
|
|
|
9f89df |
+ || (add_list != NULL && add_list[0] == NULL && del_list == NULL)
|
|
|
9f89df |
+ || (add_list != NULL && add_list[0] == NULL
|
|
|
9f89df |
+ && del_list != NULL && del_list[0] == NULL) ) {
|
|
|
9f89df |
+ continue;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Updating domain local memberships for %s\n",
|
|
|
9f89df |
+ sysdb_name);
|
|
|
9f89df |
+ ret = sysdb_update_members(state->dom, sysdb_name, type,
|
|
|
9f89df |
+ (const char *const *) add_list,
|
|
|
9f89df |
+ (const char *const *) del_list);
|
|
|
9f89df |
+ if (ret != EOK) {
|
|
|
9f89df |
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_members failed.\n");
|
|
|
9f89df |
+ goto done;
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ ret = EOK;
|
|
|
9f89df |
+done:
|
|
|
9f89df |
+ talloc_zfree(values);
|
|
|
9f89df |
+
|
|
|
9f89df |
+ if (ret == EOK) {
|
|
|
9f89df |
+ tevent_req_done(req);
|
|
|
9f89df |
+ } else {
|
|
|
9f89df |
+ tevent_req_error(req, ret);
|
|
|
9f89df |
+ }
|
|
|
9f89df |
+
|
|
|
9f89df |
+ return;
|
|
|
9f89df |
+}
|
|
|
9f89df |
+
|
|
|
9f89df |
+errno_t sdap_ad_get_domain_local_groups_recv(struct tevent_req *req)
|
|
|
9f89df |
+{
|
|
|
9f89df |
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
9f89df |
+ return EOK;
|
|
|
9f89df |
+}
|
|
|
9f89df |
+
|
|
|
9f89df |
struct sdap_ad_tokengroups_initgroups_state {
|
|
|
9f89df |
bool use_id_mapping;
|
|
|
9f89df |
struct sss_domain_info *domain;
|
|
|
9f89df |
diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h
|
|
|
9f89df |
index 4af4f7144d8855e4ed705f6a64e0a7818bc0b9a9..266bc03115e2bdd6a283f5f7da565fd00d3a77be 100644
|
|
|
9f89df |
--- a/src/providers/ldap/sdap_async_private.h
|
|
|
9f89df |
+++ b/src/providers/ldap/sdap_async_private.h
|
|
|
9f89df |
@@ -173,4 +173,14 @@ errno_t sdap_nested_groups_store(struct sysdb_ctx *sysdb,
|
|
|
9f89df |
struct sysdb_attrs **groups,
|
|
|
9f89df |
unsigned long count);
|
|
|
9f89df |
|
|
|
9f89df |
+struct tevent_req *
|
|
|
9f89df |
+sdap_ad_get_domain_local_groups_send(TALLOC_CTX *mem_ctx,
|
|
|
9f89df |
+ struct tevent_context *ev,
|
|
|
9f89df |
+ struct sdap_domain *local_sdom,
|
|
|
9f89df |
+ struct sdap_options *opts,
|
|
|
9f89df |
+ struct sysdb_ctx *sysdb,
|
|
|
9f89df |
+ struct sss_domain_info *dom,
|
|
|
9f89df |
+ struct sysdb_attrs **groups,
|
|
|
9f89df |
+ size_t num_groups);
|
|
|
9f89df |
+errno_t sdap_ad_get_domain_local_groups_recv(struct tevent_req *req);
|
|
|
9f89df |
#endif /* _SDAP_ASYNC_PRIVATE_H_ */
|
|
|
9f89df |
--
|
|
|
9f89df |
2.7.4
|
|
|
9f89df |
|