summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolai Kondrashov <Nikolai.Kondrashov@redhat.com>2017-03-17 12:34:58 +0200
committerJakub Hrozek <jhrozek@redhat.com>2017-07-27 10:33:04 +0200
commit24b3a7b91a54b5b55cfddb52b3d5ac565afdcff1 (patch)
treef36363671106b08819178d307d61534517bad908
parent200787df74510f6edc9387cf9c33f133ccfc0ae3 (diff)
downloadsssd-24b3a7b91a54b5b55cfddb52b3d5ac565afdcff1.tar.gz
sssd-24b3a7b91a54b5b55cfddb52b3d5ac565afdcff1.tar.xz
sssd-24b3a7b91a54b5b55cfddb52b3d5ac565afdcff1.zip
DP: Overlay sessionRecording attribute on initgr
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>
-rw-r--r--src/providers/data_provider/dp_target_id.c265
1 files 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 2088f9529..820a6574c 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;