URL: https://github.com/SSSD/sssd/pull/5829 Author: justin-stephenson Title: #5829: DP: Resolve intermediate groups prior to SR overlay Action: synchronized
To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/5829/head:pr5829 git checkout pr5829
From 4f52d6a62a3df8bddabb9b7291bf0afee8ff10b4 Mon Sep 17 00:00:00 2001 From: Justin Stephenson <jstep...@redhat.com> Date: Thu, 7 Oct 2021 00:37:25 +0000 Subject: [PATCH] DP: Resolve intermediate groups prior to SR overlay SSSD SR exclude_groups checking can fail when only intermediate groups are fetched during the login process. Add a step to resolve these groups during Initgroups processing to ensure the exclude groups check matches against the group name correctly. This logic exists already similarly in the simple access provider. --- src/providers/data_provider/dp_target_id.c | 265 ++++++++++++++++++++- 1 file changed, 259 insertions(+), 6 deletions(-) diff --git a/src/providers/data_provider/dp_target_id.c b/src/providers/data_provider/dp_target_id.c index a71cdf65c6..8aa667483e 100644 --- a/src/providers/data_provider/dp_target_id.c +++ b/src/providers/data_provider/dp_target_id.c @@ -448,10 +448,234 @@ static void dp_req_initgr_pp_set_initgr_timestamp(struct dp_initgr_ctx *ctx, } } + +struct dp_sr_resolve_groups_state { + struct data_provider *provider; + struct dp_initgr_ctx *initgroups_ctx; + struct dp_reply_std reply; + + uint32_t *resolve_gids; /* Groups needing resolution */ + int resolve_gnum; + int num_iter; + uint32_t gnum; +}; + +static errno_t dp_sr_resolve_groups_check(struct dp_sr_resolve_groups_state *state); +static errno_t dp_sr_resolve_groups_next(struct tevent_req *req); +static void dp_sr_resolve_groups_done(struct tevent_req *subreq); + +struct tevent_req * +dp_sr_resolve_groups_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct dp_reply_std reply, + struct data_provider *provider, + struct dp_initgr_ctx *initgr_ctx) +{ + + struct dp_sr_resolve_groups_state *state; + struct tevent_req *req; + int ret; + + req = tevent_req_create(mem_ctx, &state, struct dp_sr_resolve_groups_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); + return NULL; + } + + if (initgr_ctx->username == NULL) { + ret = EOK; + goto done; + } + + /* Only proceed if scope is applicable: 'some' or 'all' */ + if (provider->be_ctx->sr_conf.scope == SESSION_RECORDING_SCOPE_NONE) { + ret = EOK; + goto done; + } + + state->provider = provider; + state->initgroups_ctx = initgr_ctx; + state->reply = reply; + state->gnum = initgr_ctx->gnum; + + /* Check if group is intermediate(has gidNumber and isPosix == False) */ + state->resolve_gids = talloc_zero_array(state, uint32_t, initgr_ctx->gnum + 1); + if (state->resolve_gids == NULL) { + ret = ENOMEM; + goto done; + } + + ret = dp_sr_resolve_groups_check(state); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Failed checking groups to resolve\n"); + goto done; + } + + state->num_iter = 0; + ret = dp_sr_resolve_groups_next(req); + if (ret == EAGAIN) { + /* async processing */ + return req; + } + +done: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + + return req; +} + +static errno_t dp_sr_resolve_groups_next(struct tevent_req *req) +{ + struct dp_sr_resolve_groups_state *state; + struct tevent_req *subreq; + struct dp_id_data *ar; + uint32_t gid; + + state = tevent_req_data(req, struct dp_sr_resolve_groups_state); + + if (state->num_iter >= state->resolve_gnum) { + return EOK; + } + + gid = state->resolve_gids[state->num_iter]; + + ar = talloc_zero(state, struct dp_id_data); + if (ar == NULL) { + return ENOMEM; + } + + ar->entry_type = BE_REQ_GROUP; + ar->filter_type = BE_FILTER_IDNUM; + ar->filter_value = talloc_asprintf(ar, "%llu", (unsigned long long) gid); + ar->domain = talloc_strdup(ar, state->initgroups_ctx->domain_info->name); + if (!ar->domain || !ar->filter_value) { + return ENOMEM; + } + + subreq = dp_req_send(state, state->provider, ar->domain, + "DP Resolve Group", 0, NULL, + DPT_ID, DPM_ACCOUNT_HANDLER, 0, ar, NULL); + if (!subreq) { + return ENOMEM; + } + + tevent_req_set_callback(subreq, dp_sr_resolve_groups_done, req); + + state->num_iter++; + return EAGAIN; +} + +static void dp_sr_resolve_groups_done(struct tevent_req *subreq) +{ + struct dp_sr_resolve_groups_state *state; + struct tevent_req *req; + struct dp_reply_std *reply; + int ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct dp_sr_resolve_groups_state); + + ret = dp_req_recv_ptr(state, subreq, struct dp_reply_std, &reply); + talloc_free(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + /* Try next group */ + ret = dp_sr_resolve_groups_next(req); + if (ret == EOK) { + tevent_req_done(req); + } else if (ret != EAGAIN) { + tevent_req_error(req, ret); + } + + return; +} + +errno_t dp_sr_resolve_groups_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req) +{ + + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} + +static errno_t +dp_sr_resolve_groups_check(struct dp_sr_resolve_groups_state *state) +{ + errno_t ret; + struct ldb_message *group; + struct ldb_result *res; + struct sss_domain_info *domain_info; + const char *group_attrs[] = { SYSDB_NAME, SYSDB_POSIX, + SYSDB_GIDNUM, NULL }; + uint32_t gid; + const char *name; + const char *val; + + domain_info = state->initgroups_ctx->domain_info; + + ret = sysdb_initgroups(state, domain_info, state->initgroups_ctx->username, &res); + if (ret == ENOENT || (ret == EOK && res->count == 0)) { + return EOK; + } else if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get initgroups [%d]: %s\n", + ret, sss_strerror(ret)); + return ret; + } + + /* Get GID */ + for (int i = 0; i < res->count; i++) { + gid = sss_view_ldb_msg_find_attr_as_uint64(domain_info, + res->msgs[i], + SYSDB_GIDNUM, 0); + if (gid == 0) { + continue; + } + DEBUG(SSSDBG_TRACE_ALL, "Checking if group needs to be resolved: [%d]\n", + gid); + + /* Check the cache by GID again and fetch the name */ + ret = sysdb_search_group_by_gid(state, state->initgroups_ctx->domain_info, gid, + group_attrs, &group); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not look up group by gid [%"SPRIgid"]: [%d][%s]\n", + gid, ret, sss_strerror(ret)); + continue; + } + + name = ldb_msg_find_attr_as_string(group, SYSDB_NAME, NULL); + if (!name) { + DEBUG(SSSDBG_OP_FAILURE, "No group name\n"); + continue; + } + + val = ldb_msg_find_attr_as_string(group, SYSDB_POSIX, NULL); + + /* Group needs to be resolved */ + if ((strcasecmp(val, "FALSE") == 0) && gid > 0) { + state->resolve_gids[state->resolve_gnum] = gid; + state->resolve_gnum++; + } + } + + return EOK; +} + + struct dp_get_account_info_state { const char *request_name; bool initgroups; + struct tevent_context *ev; struct data_provider *provider; struct dp_id_data *data; struct dp_reply_std reply; @@ -460,6 +684,7 @@ struct dp_get_account_info_state { static void dp_get_account_info_request_done(struct tevent_req *subreq); static errno_t dp_get_account_info_initgroups_step(struct tevent_req *req); +static void dp_get_account_info_initgroups_resolv_done(struct tevent_req *subreq); static void dp_get_account_info_done(struct tevent_req *subreq); struct tevent_req * @@ -491,6 +716,7 @@ dp_get_account_info_send(TALLOC_CTX *mem_ctx, goto done; } + state->ev = ev; state->provider = provider; state->request_name = "Account"; state->initgroups = false; @@ -572,7 +798,6 @@ static errno_t dp_get_account_info_initgroups_step(struct tevent_req *req) { struct dp_get_account_info_state *state; struct tevent_req *subreq; - errno_t ret; state = tevent_req_data(req, struct dp_get_account_info_state); @@ -580,6 +805,35 @@ static errno_t dp_get_account_info_initgroups_step(struct tevent_req *req) return EOK; } + /* Create subrequest to handle SR data */ + subreq = dp_sr_resolve_groups_send(state, state->ev, state->reply, + state->provider, state->initgr_ctx); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n"); + return ENOMEM; + } + + tevent_req_set_callback(subreq, dp_get_account_info_initgroups_resolv_done, req); + + return EAGAIN; +} + + +static void dp_get_account_info_initgroups_resolv_done(struct tevent_req *subreq) +{ + struct dp_get_account_info_state *state; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct dp_get_account_info_state); + + ret = dp_sr_resolve_groups_recv(state, subreq); + talloc_free(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } if (state->initgr_ctx->username != NULL) { /* There is no point in contacting NSS responder if user did * not exist before this request. */ @@ -592,19 +846,18 @@ static errno_t dp_get_account_info_initgroups_step(struct tevent_req *req) state->initgr_ctx->groups); if (subreq == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n"); - return ENOMEM; + ret = ENOMEM; + tevent_req_error(req, ret); + return; } tevent_req_set_callback(subreq, dp_get_account_info_done, req); - ret = EAGAIN; - } else { - ret = EOK; } dp_req_initgr_pp_set_initgr_timestamp(state->initgr_ctx, &state->reply); dp_req_initgr_pp_sr_overlay(state->provider, state->initgr_ctx); - return ret; + tevent_req_done(req); } static void dp_get_account_info_done(struct tevent_req *subreq)
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure