sssd/0013-DP-Overlay-sessionReco...

359 lines
13 KiB
Diff

From 24b3a7b91a54b5b55cfddb52b3d5ac565afdcff1 Mon Sep 17 00:00:00 2001
From: Nikolai Kondrashov <Nikolai.Kondrashov@redhat.com>
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 <pbrezina@redhat.com>
---
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