359 lines
13 KiB
Diff
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
|
||
|
|