From 24b3a7b91a54b5b55cfddb52b3d5ac565afdcff1 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Fri, 17 Mar 2017 12:34:58 +0200 Subject: [PATCH 13/93] DP: Overlay sessionRecording attribute on initgr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add sessionRecording attribute to user entries on initgr request in data provider, specifying if the user name or groups match the ones with session recording enabled. Reviewed-by: Pavel Březina --- src/providers/data_provider/dp_target_id.c | 265 +++++++++++++++++++++++++---- 1 file changed, 231 insertions(+), 34 deletions(-) diff --git a/src/providers/data_provider/dp_target_id.c b/src/providers/data_provider/dp_target_id.c index 2088f9529cab83794ac793c7fd5a320f479dbf11..820a6574cb3a224cce4b7d8286af306f234454a3 100644 --- a/src/providers/data_provider/dp_target_id.c +++ b/src/providers/data_provider/dp_target_id.c @@ -73,15 +73,20 @@ static bool check_and_parse_filter(struct dp_id_data *data, } struct dp_initgr_ctx { - const char *username; const char *domain; + struct sss_domain_info *domain_info; + const char *filter_value; + const char *username; uint32_t gnum; uint32_t *groups; }; -static struct dp_initgr_ctx *create_initgr_ctx(TALLOC_CTX *mem_ctx, - const char *domain, - struct ldb_result *res) +static struct dp_initgr_ctx *create_initgr_ctx( + TALLOC_CTX *mem_ctx, + const char *domain, + struct sss_domain_info *domain_info, + const char *filter_value, + struct ldb_result *res) { struct dp_initgr_ctx *ctx; const char *username; @@ -93,38 +98,53 @@ static struct dp_initgr_ctx *create_initgr_ctx(TALLOC_CTX *mem_ctx, return NULL; } - username = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL); - if (username == NULL) { - ret = EINVAL; - goto done; - } - - ctx->username = talloc_strdup(ctx, username); - if (ctx->username == NULL) { - ret = ENOMEM; - goto done; - } - + /* Copy domain name */ ctx->domain = talloc_strdup(ctx, domain); if (ctx->domain == NULL) { ret = ENOMEM; goto done; } - ctx->groups = talloc_array(mem_ctx, uint32_t, res->count); - if (ctx->groups == NULL) { + /* Copy filter value */ + ctx->filter_value = talloc_strdup(ctx, filter_value); + if (ctx->filter_value == NULL) { ret = ENOMEM; goto done; } - /* The first GID is the primary so it might be duplicated - * later in the list. */ - for (ctx->gnum = 0, i = 0; i < res->count; i++) { - ctx->groups[ctx->gnum] = ldb_msg_find_attr_as_uint(res->msgs[i], - SYSDB_GIDNUM, 0); - /* If 0 it may be a non-posix group, so we skip it. */ - if (ctx->groups[ctx->gnum] != 0) { - ctx->gnum++; + /* Reference domain info */ + ctx->domain_info = domain_info; + + /* If we had the data in sysdb */ + if (res != NULL) { + /* Copy original username */ + username = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL); + if (username == NULL) { + ret = EINVAL; + goto done; + } + ctx->username = talloc_strdup(ctx, username); + if (ctx->username == NULL) { + ret = ENOMEM; + goto done; + } + + /* Copy group IDs */ + ctx->groups = talloc_array(mem_ctx, uint32_t, res->count); + if (ctx->groups == NULL) { + ret = ENOMEM; + goto done; + } + + /* The first GID is the primary so it might be duplicated + * later in the list. */ + for (ctx->gnum = 0, i = 0; i < res->count; i++) { + ctx->groups[ctx->gnum] = ldb_msg_find_attr_as_uint(res->msgs[i], + SYSDB_GIDNUM, 0); + /* If 0 it may be a non-posix group, so we skip it. */ + if (ctx->groups[ctx->gnum] != 0) { + ctx->gnum++; + } } } @@ -139,16 +159,21 @@ done: return ctx; } -static void dp_req_initgr_pp(const char *req_name, - struct data_provider *provider, - struct dp_initgr_ctx *ctx, - struct dp_reply_std *reply) +static void dp_req_initgr_pp_nss_notify(const char *req_name, + struct data_provider *provider, + struct dp_initgr_ctx *ctx) { struct dp_client *dp_cli; DBusMessage *msg; dbus_bool_t dbret; int num; + /* If user didn't exist in the cache previously */ + if (ctx->username == NULL) { + /* There is no point in contacting NSS responder */ + return; + } + dp_cli = provider->clients[DPC_NSS]; if (dp_cli == NULL) { return; @@ -185,6 +210,178 @@ static void dp_req_initgr_pp(const char *req_name, return; } +static void dp_req_initgr_pp_sr_overlay(struct data_provider *provider, + struct dp_initgr_ctx *ctx) +{ + bool enabled = false; + struct be_ctx *be = provider->be_ctx; + struct ldb_result *res; + struct ldb_message *msg; + const char *name; + char *output_name; + char **conf_user; + char **conf_group; + size_t i; + TALLOC_CTX *tmp_ctx = NULL; + errno_t ret; + struct ldb_message_element el = { 0, SYSDB_SESSION_RECORDING, 0, NULL }; + struct sysdb_attrs del_attrs = { 1, &el }; + struct sysdb_attrs *add_attrs; + + /* If selective session recording is not enabled */ + if (be->sr_conf.scope != SESSION_RECORDING_SCOPE_SOME) { + goto done; + } + + /* Allocate temporary talloc context */ + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed creating temporary talloc context\n"); + ret = ENOMEM; + goto done; + } + + /* Get updated initgroups data with overrides */ + ret = sysdb_initgroups_with_views(tmp_ctx, ctx->domain_info, + ctx->filter_value, &res); + if (ret == ENOENT || (ret == EOK && res->count == 0)) { + goto done; + } else if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get initgroups: %s\n", + sss_strerror(ret)); + goto done; + } + + /* Delete sessionRecording attribute so we know when we failed */ + ret = sysdb_set_entry_attr(ctx->domain_info->sysdb, res->msgs[0]->dn, + &del_attrs, SYSDB_MOD_DEL); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed removing %s attribute: %s\n", + SYSDB_SESSION_RECORDING, sss_strerror(ret)); + goto done; + } + + /* Format output username */ + name = sss_get_name_from_msg(ctx->domain_info, res->msgs[0]); + ret = sss_output_fqname(tmp_ctx, ctx->domain_info, name, + be->override_space, &output_name); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed formatting output username from \"%s\": %s\n", + name, sss_strerror(ret)); + goto done; + } + + /* For each user name in session recording config */ + conf_user = be->sr_conf.users; + if (conf_user != NULL) { + for (; *conf_user != NULL && !enabled; conf_user++) { + /* If it matches the requested user name */ + if (strcmp(*conf_user, output_name) == 0) { + enabled = true; + } + } + } + + /* If we have groups in config and are not yet enabled */ + if (be->sr_conf.groups != NULL && + be->sr_conf.groups[0] != NULL && + !enabled) { + /* For each group in response */ + for (i = 0; i < res->count && !enabled; i++) { + /* Get the group msg */ + if (i == 0) { + gid_t gid; + struct ldb_result *group_res; + + /* Get the primary group */ + gid = sss_view_ldb_msg_find_attr_as_uint64(ctx->domain_info, + res->msgs[i], + SYSDB_GIDNUM, 0); + if (gid == 0) { + continue; + } + ret = sysdb_getgrgid_with_views(tmp_ctx, ctx->domain_info, + gid, &group_res); + if (ret == ENOENT) { + continue; + } else if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed retrieving group #%llu: %s\n", + (unsigned long long)gid, sss_strerror(ret)); + goto done; + } else if (group_res->count == 0) { + continue; + } + msg = group_res->msgs[0]; + } else { + msg = res->msgs[i]; + } + /* Get the group's output name */ + name = sss_get_name_from_msg(ctx->domain_info, msg); + if (name == NULL) { + continue; + } + ret = sss_output_fqname(tmp_ctx, ctx->domain_info, + name, be->override_space, + &output_name); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed formatting output group name from \"%s\": %s\n", + name, sss_strerror(ret)); + goto done; + } + /* For each group in configuration */ + for (conf_group = be->sr_conf.groups; + *conf_group != NULL && !enabled; + conf_group++) { + if (strcmp(*conf_group, output_name) == 0) { + enabled = true; + } + } + } + } + + /* Set sessionRecording attribute to enabled value */ + add_attrs = sysdb_new_attrs(tmp_ctx); + if (add_attrs == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed creating attributes\n"); + ret = ENOMEM; + goto done; + } + ret = sysdb_attrs_add_bool(add_attrs, SYSDB_SESSION_RECORDING, enabled); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed setting %s attribute: %s\n", + SYSDB_SESSION_RECORDING, sss_strerror(ret)); + goto done; + } + ret = sysdb_set_entry_attr(ctx->domain_info->sysdb, res->msgs[0]->dn, + add_attrs, SYSDB_MOD_ADD); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed storing %s attribute: %s\n", + SYSDB_SESSION_RECORDING, sss_strerror(ret)); + goto done; + } + +done: + talloc_free(tmp_ctx); +} + +static void dp_req_initgr_pp(const char *req_name, + struct data_provider *provider, + struct dp_initgr_ctx *ctx, + struct dp_reply_std *reply) +{ + (void)reply; + dp_req_initgr_pp_nss_notify(req_name, provider, ctx); + dp_req_initgr_pp_sr_overlay(provider, ctx); +} + static errno_t dp_initgroups(struct sbus_request *sbus_req, struct dp_client *dp_cli, const char *key, @@ -194,7 +391,7 @@ static errno_t dp_initgroups(struct sbus_request *sbus_req, struct be_ctx *be_ctx; struct sss_domain_info *domain; struct dp_initgr_ctx *ctx; - struct ldb_result *res; + struct ldb_result *res = NULL; errno_t ret; be_ctx = dp_client_be(dp_cli); @@ -210,15 +407,15 @@ static errno_t dp_initgroups(struct sbus_request *sbus_req, ret = sysdb_initgroups(sbus_req, domain, data->filter_value, &res); if (ret == ENOENT || (ret == EOK && res->count == 0)) { - /* There is no point in contacting NSS responder. Proceed as usual. */ - return EAGAIN; + talloc_zfree(res); } else if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get initgroups [%d]: %s\n", ret, sss_strerror(ret)); goto done; } - ctx = create_initgr_ctx(sbus_req, data->domain, res); + ctx = create_initgr_ctx(sbus_req, data->domain, domain, + data->filter_value, res); if (ctx == NULL) { ret = ENOMEM; goto done; -- 2.14.1