611 lines
19 KiB
Diff
611 lines
19 KiB
Diff
|
From 5edf5c55bb259ac29454493d06097c5fab8a2199 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
||
|
Date: Fri, 18 Dec 2015 13:05:41 +0100
|
||
|
Subject: [PATCH 31/49] IPA SUDO: Implement smart refresh
|
||
|
|
||
|
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
||
|
(cherry picked from commit cc7f9b639144183eb4f8bd86e5bed077da7d4e35)
|
||
|
---
|
||
|
src/providers/ipa/ipa_sudo.h | 1 +
|
||
|
src/providers/ipa/ipa_sudo_async.c | 312 ++++++++++++++++++++++++++++++++++-
|
||
|
src/providers/ipa/ipa_sudo_refresh.c | 132 ++++++++++++++-
|
||
|
3 files changed, 438 insertions(+), 7 deletions(-)
|
||
|
|
||
|
diff --git a/src/providers/ipa/ipa_sudo.h b/src/providers/ipa/ipa_sudo.h
|
||
|
index 9dd72948732f4b6e19f4a6546128c5319cd97bda..81ada14e46550fab815a7df262abd0b5fa11afd7 100644
|
||
|
--- a/src/providers/ipa/ipa_sudo.h
|
||
|
+++ b/src/providers/ipa/ipa_sudo.h
|
||
|
@@ -59,6 +59,7 @@ struct tevent_req *
|
||
|
ipa_sudo_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
struct tevent_context *ev,
|
||
|
struct ipa_sudo_ctx *sudo_ctx,
|
||
|
+ const char *cmdgroups_filter,
|
||
|
const char *search_filter,
|
||
|
const char *delete_filter);
|
||
|
|
||
|
diff --git a/src/providers/ipa/ipa_sudo_async.c b/src/providers/ipa/ipa_sudo_async.c
|
||
|
index d52b97da17337b224c4be4b4fb65b0a99000e4b6..79e69ce962fd5cc2df0e9aac10a5469ffd73c6be 100644
|
||
|
--- a/src/providers/ipa/ipa_sudo_async.c
|
||
|
+++ b/src/providers/ipa/ipa_sudo_async.c
|
||
|
@@ -160,14 +160,217 @@ ipa_sudo_highest_usn(TALLOC_CTX *mem_ctx,
|
||
|
return EOK;
|
||
|
}
|
||
|
|
||
|
+static errno_t
|
||
|
+ipa_sudo_assoc_rules_filter(TALLOC_CTX *mem_ctx,
|
||
|
+ struct sysdb_attrs **cmdgroups,
|
||
|
+ size_t num_cmdgroups,
|
||
|
+ char **_filter)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ const char *origdn;
|
||
|
+ char *sanitized;
|
||
|
+ char *filter;
|
||
|
+ errno_t ret;
|
||
|
+ size_t i;
|
||
|
+
|
||
|
+ if (num_cmdgroups == 0) {
|
||
|
+ return ENOENT;
|
||
|
+ }
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(NULL);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ filter = talloc_strdup(tmp_ctx, "");
|
||
|
+ if (filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (i = 0; i < num_cmdgroups; i++) {
|
||
|
+ ret = sysdb_attrs_get_string(cmdgroups[i], SYSDB_ORIG_DN, &origdn);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get original dn [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ ret = ERR_INTERNAL;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_filter_sanitize(tmp_ctx, origdn, &sanitized);
|
||
|
+ if (ret != EOK) {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ filter = talloc_asprintf_append(filter, "(%s=%s)",
|
||
|
+ SYSDB_IPA_SUDORULE_ORIGCMD, sanitized);
|
||
|
+ if (filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ filter = talloc_asprintf(tmp_ctx, "(&(objectClass=%s)(|%s)))",
|
||
|
+ SYSDB_SUDO_CACHE_OC, filter);
|
||
|
+ if (filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ *_filter = talloc_steal(mem_ctx, filter);
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_sudo_assoc_rules(TALLOC_CTX *mem_ctx,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ struct sysdb_attrs **cmdgroups,
|
||
|
+ size_t num_cmdgroups,
|
||
|
+ struct sysdb_attrs ***_rules,
|
||
|
+ size_t *_num_rules)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ const char *attrs[] = {SYSDB_NAME, NULL};
|
||
|
+ struct sysdb_attrs **rules;
|
||
|
+ struct ldb_message **msgs;
|
||
|
+ size_t num_rules;
|
||
|
+ char *filter;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(NULL);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_sudo_assoc_rules_filter(tmp_ctx, cmdgroups,
|
||
|
+ num_cmdgroups, &filter);
|
||
|
+ if (ret != EOK) {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_search_custom(tmp_ctx, domain, filter,
|
||
|
+ SUDORULE_SUBDIR, attrs,
|
||
|
+ &num_rules, &msgs);
|
||
|
+ if (ret == ENOENT) {
|
||
|
+ *_rules = NULL;
|
||
|
+ *_num_rules = 0;
|
||
|
+ ret = EOK;
|
||
|
+ goto done;
|
||
|
+ } else if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up sudo rules [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_msg2attrs(tmp_ctx, num_rules, msgs, &rules);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not convert ldb message to "
|
||
|
+ "sysdb_attrs [%d]: %s\n", ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ *_rules = talloc_steal(mem_ctx, rules);
|
||
|
+ *_num_rules = num_rules;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_sudo_filter_rules_bycmdgroups(TALLOC_CTX *mem_ctx,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ struct sysdb_attrs **cmdgroups,
|
||
|
+ size_t num_cmdgroups,
|
||
|
+ struct sdap_attr_map *map_rule,
|
||
|
+ char **_filter)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ struct sysdb_attrs **rules;
|
||
|
+ size_t num_rules;
|
||
|
+ const char *name;
|
||
|
+ char *sanitized;
|
||
|
+ char *filter;
|
||
|
+ errno_t ret;
|
||
|
+ size_t i;
|
||
|
+
|
||
|
+ if (num_cmdgroups == 0) {
|
||
|
+ *_filter = NULL;
|
||
|
+ return EOK;
|
||
|
+ }
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(NULL);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_sudo_assoc_rules(tmp_ctx, domain, cmdgroups, num_cmdgroups,
|
||
|
+ &rules, &num_rules);
|
||
|
+ if (ret != EOK) {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (num_rules == 0) {
|
||
|
+ *_filter = NULL;
|
||
|
+ ret = EOK;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ filter = talloc_strdup(tmp_ctx, "");
|
||
|
+ if (filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (i = 0; i < num_rules; i++) {
|
||
|
+ ret = sysdb_attrs_get_string(rules[i], SYSDB_NAME, &name);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get name [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_filter_sanitize(tmp_ctx, name, &sanitized);
|
||
|
+ if (ret != EOK) {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ filter = talloc_asprintf_append(filter, "(%s=%s)",
|
||
|
+ map_rule[IPA_AT_SUDORULE_NAME].name, sanitized);
|
||
|
+ if (filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ filter = talloc_asprintf(tmp_ctx, "(|%s)", filter);
|
||
|
+ if (filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ *_filter = talloc_steal(mem_ctx, filter);
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
struct ipa_sudo_fetch_state {
|
||
|
struct tevent_context *ev;
|
||
|
struct sysdb_ctx *sysdb;
|
||
|
+ struct sss_domain_info *domain;
|
||
|
struct ipa_sudo_ctx *sudo_ctx;
|
||
|
struct sdap_options *sdap_opts;
|
||
|
struct ipa_hostinfo *host;
|
||
|
struct sdap_handle *sh;
|
||
|
const char *search_filter;
|
||
|
+ const char *cmdgroups_filter;
|
||
|
|
||
|
struct sdap_attr_map *map_cmdgroup;
|
||
|
struct sdap_attr_map *map_rule;
|
||
|
@@ -180,6 +383,8 @@ struct ipa_sudo_fetch_state {
|
||
|
char *usn;
|
||
|
};
|
||
|
|
||
|
+static errno_t ipa_sudo_fetch_addtl_cmdgroups(struct tevent_req *req);
|
||
|
+static void ipa_sudo_fetch_addtl_cmdgroups_done(struct tevent_req *subreq);
|
||
|
static errno_t ipa_sudo_fetch_rules(struct tevent_req *req);
|
||
|
static void ipa_sudo_fetch_rules_done(struct tevent_req *subreq);
|
||
|
static errno_t ipa_sudo_fetch_cmdgroups(struct tevent_req *req);
|
||
|
@@ -191,6 +396,7 @@ static void ipa_sudo_fetch_done(struct tevent_req *req);
|
||
|
static struct tevent_req *
|
||
|
ipa_sudo_fetch_send(TALLOC_CTX *mem_ctx,
|
||
|
struct tevent_context *ev,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
struct sysdb_ctx *sysdb,
|
||
|
struct ipa_sudo_ctx *sudo_ctx,
|
||
|
struct ipa_hostinfo *host,
|
||
|
@@ -199,6 +405,7 @@ ipa_sudo_fetch_send(TALLOC_CTX *mem_ctx,
|
||
|
struct sdap_attr_map *map_host,
|
||
|
struct sdap_attr_map *map_hostgroup,
|
||
|
struct sdap_handle *sh,
|
||
|
+ const char *cmdgroups_filter,
|
||
|
const char *search_filter)
|
||
|
{
|
||
|
struct ipa_sudo_fetch_state *state = NULL;
|
||
|
@@ -214,11 +421,13 @@ ipa_sudo_fetch_send(TALLOC_CTX *mem_ctx,
|
||
|
|
||
|
state->ev = ev;
|
||
|
state->sysdb = sysdb;
|
||
|
+ state->domain = domain;
|
||
|
state->sudo_ctx = sudo_ctx;
|
||
|
state->sdap_opts = sudo_ctx->sdap_opts;
|
||
|
state->host = host;
|
||
|
state->sh = sh;
|
||
|
state->search_filter = search_filter == NULL ? "" : search_filter;
|
||
|
+ state->cmdgroups_filter = cmdgroups_filter;
|
||
|
|
||
|
state->map_cmdgroup = sudo_ctx->sudocmdgroup_map;
|
||
|
state->map_rule = sudo_ctx->sudorule_map;
|
||
|
@@ -234,7 +443,15 @@ ipa_sudo_fetch_send(TALLOC_CTX *mem_ctx,
|
||
|
goto immediately;
|
||
|
}
|
||
|
|
||
|
- ret = ipa_sudo_fetch_rules(req);
|
||
|
+ if (state->cmdgroups_filter != NULL) {
|
||
|
+ /* We need to fetch additional cmdgroups that may not be revealed
|
||
|
+ * during normal search. Such as when using entryUSN filter in smart
|
||
|
+ * refresh, some command groups may have change but none rule was
|
||
|
+ * modified but we need to fetch associated rules anyway. */
|
||
|
+ ret = ipa_sudo_fetch_addtl_cmdgroups(req);
|
||
|
+ } else {
|
||
|
+ ret = ipa_sudo_fetch_rules(req);
|
||
|
+ }
|
||
|
if (ret != EAGAIN) {
|
||
|
goto immediately;
|
||
|
}
|
||
|
@@ -253,6 +470,87 @@ immediately:
|
||
|
}
|
||
|
|
||
|
static errno_t
|
||
|
+ipa_sudo_fetch_addtl_cmdgroups(struct tevent_req *req)
|
||
|
+{
|
||
|
+ struct ipa_sudo_fetch_state *state;
|
||
|
+ struct tevent_req *subreq;
|
||
|
+ struct sdap_attr_map *map;
|
||
|
+ char *filter;
|
||
|
+
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC, "About to fetch additional command groups\n");
|
||
|
+
|
||
|
+ state = tevent_req_data(req, struct ipa_sudo_fetch_state);
|
||
|
+ map = state->map_cmdgroup;
|
||
|
+
|
||
|
+ filter = talloc_asprintf(state, "(&(objectClass=%s)%s)",
|
||
|
+ map[IPA_OC_SUDOCMDGROUP].name,
|
||
|
+ state->cmdgroups_filter);
|
||
|
+ if (filter == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build filter\n");
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ subreq = sdap_search_bases_send(state, state->ev, state->sdap_opts,
|
||
|
+ state->sh, state->sudo_sb, map, true, 0,
|
||
|
+ filter, NULL);
|
||
|
+ if (subreq == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_set_callback(subreq, ipa_sudo_fetch_addtl_cmdgroups_done, req);
|
||
|
+ return EAGAIN;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+ipa_sudo_fetch_addtl_cmdgroups_done(struct tevent_req *subreq)
|
||
|
+{
|
||
|
+ struct ipa_sudo_fetch_state *state = NULL;
|
||
|
+ struct tevent_req *req = NULL;
|
||
|
+ struct sysdb_attrs **attrs;
|
||
|
+ size_t num_attrs;
|
||
|
+ char *filter;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
||
|
+ state = tevent_req_data(req, struct ipa_sudo_fetch_state);
|
||
|
+
|
||
|
+ ret = sdap_search_bases_recv(subreq, state, &num_attrs, &attrs);
|
||
|
+ talloc_zfree(subreq);
|
||
|
+ if (ret != EOK) {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ DEBUG(SSSDBG_IMPORTANT_INFO, "Received %zu additional command groups\n",
|
||
|
+ num_attrs);
|
||
|
+
|
||
|
+ ret = ipa_sudo_filter_rules_bycmdgroups(state, state->domain, attrs,
|
||
|
+ num_attrs, state->map_rule,
|
||
|
+ &filter);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to construct rules filter "
|
||
|
+ "[%d]: %s\n", ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ state->search_filter = sdap_or_filters(state, state->search_filter, filter);
|
||
|
+ if (state->search_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_sudo_fetch_rules(req);
|
||
|
+
|
||
|
+done:
|
||
|
+ if (ret == EOK) {
|
||
|
+ ipa_sudo_fetch_done(req);
|
||
|
+ } else if (ret != EAGAIN) {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ }
|
||
|
+
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
ipa_sudo_fetch_rules(struct tevent_req *req)
|
||
|
{
|
||
|
struct ipa_sudo_fetch_state *state;
|
||
|
@@ -543,6 +841,7 @@ struct ipa_sudo_refresh_state {
|
||
|
struct ipa_sudo_ctx *sudo_ctx;
|
||
|
struct ipa_options *ipa_opts;
|
||
|
struct sdap_options *sdap_opts;
|
||
|
+ const char *cmdgroups_filter;
|
||
|
const char *search_filter;
|
||
|
const char *delete_filter;
|
||
|
|
||
|
@@ -563,6 +862,7 @@ struct tevent_req *
|
||
|
ipa_sudo_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
struct tevent_context *ev,
|
||
|
struct ipa_sudo_ctx *sudo_ctx,
|
||
|
+ const char *cmdgroups_filter,
|
||
|
const char *search_filter,
|
||
|
const char *delete_filter)
|
||
|
{
|
||
|
@@ -592,6 +892,12 @@ ipa_sudo_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
goto immediately;
|
||
|
}
|
||
|
|
||
|
+ state->cmdgroups_filter = talloc_strdup(state, cmdgroups_filter);
|
||
|
+ if (cmdgroups_filter != NULL && state->cmdgroups_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+
|
||
|
state->search_filter = talloc_strdup(state, search_filter);
|
||
|
if (search_filter != NULL && state->search_filter == NULL) {
|
||
|
ret = ENOMEM;
|
||
|
@@ -716,13 +1022,13 @@ ipa_sudo_refresh_host_done(struct tevent_req *subreq)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
- subreq = ipa_sudo_fetch_send(state, state->ev, state->sysdb,
|
||
|
+ subreq = ipa_sudo_fetch_send(state, state->ev, state->domain, state->sysdb,
|
||
|
state->sudo_ctx, host,
|
||
|
state->sdap_opts->user_map,
|
||
|
state->sdap_opts->group_map,
|
||
|
state->ipa_opts->host_map,
|
||
|
state->ipa_opts->hostgroup_map, state->sh,
|
||
|
- state->search_filter);
|
||
|
+ state->cmdgroups_filter, state->search_filter);
|
||
|
if (subreq == NULL) {
|
||
|
state->dp_error = DP_ERR_FATAL;
|
||
|
tevent_req_error(req, ENOMEM);
|
||
|
diff --git a/src/providers/ipa/ipa_sudo_refresh.c b/src/providers/ipa/ipa_sudo_refresh.c
|
||
|
index f1b99c0de96dd2226eb3181ce44e54c019139c6e..bdde4a0026f224898a4987476f49122ea92a6052 100644
|
||
|
--- a/src/providers/ipa/ipa_sudo_refresh.c
|
||
|
+++ b/src/providers/ipa/ipa_sudo_refresh.c
|
||
|
@@ -69,7 +69,8 @@ ipa_sudo_full_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
|
||
|
DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
|
||
|
|
||
|
- subreq = ipa_sudo_refresh_send(state, ev, sudo_ctx, NULL, delete_filter);
|
||
|
+ subreq = ipa_sudo_refresh_send(state, ev, sudo_ctx,
|
||
|
+ NULL, NULL, delete_filter);
|
||
|
if (subreq == NULL) {
|
||
|
ret = ENOMEM;
|
||
|
goto immediately;
|
||
|
@@ -141,6 +142,129 @@ ipa_sudo_full_refresh_recv(struct tevent_req *req,
|
||
|
return EOK;
|
||
|
}
|
||
|
|
||
|
+struct ipa_sudo_smart_refresh_state {
|
||
|
+ int dp_error;
|
||
|
+};
|
||
|
+
|
||
|
+static void ipa_sudo_smart_refresh_done(struct tevent_req *subreq);
|
||
|
+
|
||
|
+static struct tevent_req *
|
||
|
+ipa_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
+ struct tevent_context *ev,
|
||
|
+ struct ipa_sudo_ctx *sudo_ctx)
|
||
|
+{
|
||
|
+ struct sdap_server_opts *srv_opts = sudo_ctx->id_ctx->srv_opts;
|
||
|
+ struct ipa_sudo_smart_refresh_state *state;
|
||
|
+ struct tevent_req *subreq;
|
||
|
+ struct tevent_req *req;
|
||
|
+ char *cmdgroups_filter;
|
||
|
+ char *search_filter;
|
||
|
+ const char *usn;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ req = tevent_req_create(mem_ctx, &state,
|
||
|
+ struct ipa_sudo_smart_refresh_state);
|
||
|
+ if (req == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!sudo_ctx->full_refresh_done
|
||
|
+ || srv_opts == NULL || srv_opts->max_sudo_value == NULL) {
|
||
|
+ /* Perform full refresh first */
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, "
|
||
|
+ "waiting for full refresh!\n");
|
||
|
+ ret = EINVAL;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Download all rules from LDAP that are newer than usn */
|
||
|
+ usn = srv_opts->max_sudo_value;
|
||
|
+
|
||
|
+ cmdgroups_filter = talloc_asprintf(state,
|
||
|
+ "(&(%s>=%s)(!(%s=%s)))",
|
||
|
+ sudo_ctx->sudocmdgroup_map[IPA_AT_SUDOCMDGROUP_ENTRYUSN].name, usn,
|
||
|
+ sudo_ctx->sudocmdgroup_map[IPA_AT_SUDOCMDGROUP_ENTRYUSN].name, usn);
|
||
|
+ if (cmdgroups_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+
|
||
|
+ search_filter = talloc_asprintf(state,
|
||
|
+ "(&(%s>=%s)(!(%s=%s)))",
|
||
|
+ sudo_ctx->sudorule_map[IPA_AT_SUDORULE_ENTRYUSN].name, usn,
|
||
|
+ sudo_ctx->sudorule_map[IPA_AT_SUDORULE_ENTRYUSN].name, usn);
|
||
|
+ if (search_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Do not remove any rules that are already in the sysdb. */
|
||
|
+
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC, "Issuing a smart refresh of sudo rules "
|
||
|
+ "(USN > %s)\n", usn);
|
||
|
+
|
||
|
+ subreq = ipa_sudo_refresh_send(state, ev, sudo_ctx, cmdgroups_filter,
|
||
|
+ search_filter, NULL);
|
||
|
+ if (subreq == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_set_callback(subreq, ipa_sudo_smart_refresh_done, req);
|
||
|
+
|
||
|
+ return req;
|
||
|
+
|
||
|
+immediately:
|
||
|
+ if (ret == EOK) {
|
||
|
+ tevent_req_done(req);
|
||
|
+ } else {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ }
|
||
|
+ tevent_req_post(req, ev);
|
||
|
+
|
||
|
+ return req;
|
||
|
+}
|
||
|
+
|
||
|
+static void ipa_sudo_smart_refresh_done(struct tevent_req *subreq)
|
||
|
+{
|
||
|
+ struct tevent_req *req = NULL;
|
||
|
+ struct ipa_sudo_smart_refresh_state *state = NULL;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
||
|
+ state = tevent_req_data(req, struct ipa_sudo_smart_refresh_state);
|
||
|
+
|
||
|
+ ret = ipa_sudo_refresh_recv(subreq, &state->dp_error, NULL);
|
||
|
+ talloc_zfree(subreq);
|
||
|
+ if (ret != EOK || state->dp_error != DP_ERR_OK) {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC, "Successful smart refresh of sudo rules\n");
|
||
|
+
|
||
|
+done:
|
||
|
+ if (ret != EOK) {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_done(req);
|
||
|
+}
|
||
|
+
|
||
|
+int ipa_sudo_smart_refresh_recv(struct tevent_req *req,
|
||
|
+ int *dp_error)
|
||
|
+{
|
||
|
+ struct ipa_sudo_smart_refresh_state *state = NULL;
|
||
|
+ state = tevent_req_data(req, struct ipa_sudo_smart_refresh_state);
|
||
|
+
|
||
|
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
||
|
+
|
||
|
+ *dp_error = state->dp_error;
|
||
|
+
|
||
|
+ return EOK;
|
||
|
+}
|
||
|
+
|
||
|
struct ipa_sudo_rules_refresh_state {
|
||
|
size_t num_rules;
|
||
|
int dp_error;
|
||
|
@@ -230,7 +354,7 @@ ipa_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
goto immediately;
|
||
|
}
|
||
|
|
||
|
- subreq = ipa_sudo_refresh_send(req, ev, sudo_ctx, search_filter,
|
||
|
+ subreq = ipa_sudo_refresh_send(req, ev, sudo_ctx, NULL, search_filter,
|
||
|
delete_filter);
|
||
|
if (subreq == NULL) {
|
||
|
ret = ENOMEM;
|
||
|
@@ -327,7 +451,7 @@ ipa_sudo_ptask_smart_refresh_send(TALLOC_CTX *mem_ctx,
|
||
|
struct ipa_sudo_ctx *sudo_ctx;
|
||
|
sudo_ctx = talloc_get_type(pvt, struct ipa_sudo_ctx);
|
||
|
|
||
|
- return ipa_sudo_full_refresh_send(mem_ctx, be_ctx->ev, sudo_ctx);
|
||
|
+ return ipa_sudo_smart_refresh_send(mem_ctx, be_ctx->ev, sudo_ctx);
|
||
|
}
|
||
|
|
||
|
static errno_t
|
||
|
@@ -335,7 +459,7 @@ ipa_sudo_ptask_smart_refresh_recv(struct tevent_req *req)
|
||
|
{
|
||
|
int dp_error;
|
||
|
|
||
|
- return ipa_sudo_full_refresh_recv(req, &dp_error);
|
||
|
+ return ipa_sudo_smart_refresh_recv(req, &dp_error);
|
||
|
}
|
||
|
|
||
|
errno_t
|
||
|
--
|
||
|
2.5.0
|
||
|
|