Blob Blame History Raw
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