summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap/sdap_sudo_timer.c
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2011-12-19 15:46:17 +0100
committerStephen Gallagher <sgallagh@redhat.com>2012-01-17 11:38:16 -0500
commiteb54e05c9658a7274e3238813c54dd0c6577d3ec (patch)
tree2f3d81c0f3e53c067bbeb9ab32cd2b8c18a96d89 /src/providers/ldap/sdap_sudo_timer.c
parent1a542b3698d8c42cf075b722f8838f106eb09fcc (diff)
downloadsssd-eb54e05c9658a7274e3238813c54dd0c6577d3ec.tar.gz
sssd-eb54e05c9658a7274e3238813c54dd0c6577d3ec.tar.xz
sssd-eb54e05c9658a7274e3238813c54dd0c6577d3ec.zip
SUDO Integration - periodical update of rules in data provider
https://fedorahosted.org/sssd/ticket/1110 Adds new configuration options: - ldap_sudo_refresh_enabled - enable/disable periodical updates - ldap_sudo_refresh_timeout - rules timeout (refresh period)
Diffstat (limited to 'src/providers/ldap/sdap_sudo_timer.c')
-rw-r--r--src/providers/ldap/sdap_sudo_timer.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/src/providers/ldap/sdap_sudo_timer.c b/src/providers/ldap/sdap_sudo_timer.c
new file mode 100644
index 000000000..cc664abf0
--- /dev/null
+++ b/src/providers/ldap/sdap_sudo_timer.c
@@ -0,0 +1,236 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2011 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <errno.h>
+#include <tevent.h>
+
+#include "util/util.h"
+#include "providers/ldap/ldap_common.h"
+#include "providers/ldap/sdap_sudo_timer.h"
+#include "providers/ldap/sdap_sudo.h"
+#include "db/sysdb_sudo.h"
+
+struct sdap_sudo_refresh_ctx {
+ struct be_ctx *be_ctx;
+ struct sdap_id_ctx *id_ctx;
+ struct sdap_options *opts;
+
+ struct timeval last_refresh;
+};
+
+static void sdap_sudo_refresh_timer(struct tevent_context *ev,
+ struct tevent_timer *tt,
+ struct timeval tv, void *pvt);
+
+static void sdap_sudo_refresh_reschedule(struct tevent_req *req);
+
+static void sdap_sudo_refresh_timeout(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval tv, void *pvt);
+
+struct sdap_sudo_refresh_ctx *
+sdap_sudo_refresh_ctx_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct sdap_options *opts,
+ struct timeval last_refresh)
+{
+ struct sdap_sudo_refresh_ctx *refresh_ctx = NULL;
+
+ refresh_ctx = talloc_zero(mem_ctx, struct sdap_sudo_refresh_ctx);
+ if (refresh_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero() failed!\n"));
+ return NULL;
+ }
+
+ refresh_ctx->be_ctx = be_ctx;
+ refresh_ctx->id_ctx = id_ctx;
+ refresh_ctx->opts = opts;
+ refresh_ctx->last_refresh = last_refresh;
+
+ return refresh_ctx;
+}
+
+int sdap_sudo_refresh_set_timer(struct sdap_sudo_refresh_ctx *ctx,
+ struct timeval tv)
+{
+ struct tevent_timer *enum_task;
+
+ DEBUG(SSSDBG_TRACE_FUNC, ("Scheduling next refresh of SUDO rules at "
+ "%ld.%ld\n", (long)tv.tv_sec, (long)tv.tv_usec));
+
+ enum_task = tevent_add_timer(ctx->be_ctx->ev, ctx,
+ tv, sdap_sudo_refresh_timer, ctx);
+ if (!enum_task) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("FATAL: failed to setup SUDO rules refresh task!\n"));
+ return EFAULT;
+ }
+
+ return EOK;
+}
+
+static void sdap_sudo_refresh_timer(struct tevent_context *ev,
+ struct tevent_timer *tt,
+ struct timeval tv, void *pvt)
+{
+ struct sdap_sudo_refresh_ctx *refresh_ctx = NULL;
+ struct sdap_sudo_ctx *sudo_ctx = NULL;
+ struct tevent_timer *timeout = NULL;
+ struct tevent_req *req = NULL;
+ int delay = 0;
+ int ret;
+
+ refresh_ctx = talloc_get_type(pvt, struct sdap_sudo_refresh_ctx);
+
+ delay = dp_opt_get_int(refresh_ctx->opts->basic, SDAP_SUDO_REFRESH_TIMEOUT);
+
+ if (be_is_offline(refresh_ctx->be_ctx)) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Backend is marked offline, retry later!\n"));
+ tv = tevent_timeval_current_ofs(delay, 0);
+ ret = sdap_sudo_refresh_set_timer(refresh_ctx, tv);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Error setting up SUDO refresh timer\n"));
+ }
+ return;
+ }
+
+ /* create sudo context */
+ sudo_ctx = talloc_zero(refresh_ctx, struct sdap_sudo_ctx);
+ if (sudo_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero() failed!\n"));
+ tv = tevent_timeval_current_ofs(delay, 0);
+ ret = sdap_sudo_refresh_set_timer(refresh_ctx, tv);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Error setting up SUDO refresh timer\n"));
+ }
+
+ return;
+ }
+
+ sudo_ctx->be_ctx = refresh_ctx->be_ctx;
+ sudo_ctx->be_req = NULL;
+ sudo_ctx->sdap_ctx = refresh_ctx->id_ctx;
+ sudo_ctx->sdap_op = NULL;
+ sudo_ctx->sdap_conn_cache = refresh_ctx->id_ctx->conn_cache;
+ sudo_ctx->username = NULL; /* download all rules */
+ sudo_ctx->uid = 0;
+ sudo_ctx->groups = NULL;
+
+ /* send request */
+ req = sdap_sudo_refresh_send(sudo_ctx, sudo_ctx);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to schedule refresh of SUDO rules, "
+ "retrying later!\n"));
+ tv = tevent_timeval_current_ofs(delay, 0);
+ ret = sdap_sudo_refresh_set_timer(refresh_ctx, tv);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Error setting up SUDO refresh timer\n"));
+ }
+
+ return;
+ }
+ refresh_ctx->last_refresh = tevent_timeval_current();
+
+ tevent_req_set_callback(req, sdap_sudo_refresh_reschedule, refresh_ctx);
+
+ /* schedule timeout */
+ tv = tevent_timeval_current_ofs(delay, 0);
+ timeout = tevent_add_timer(refresh_ctx->be_ctx->ev, req, tv,
+ sdap_sudo_refresh_timeout, req);
+ if (timeout == NULL) {
+ /* If we can't guarantee a timeout, we
+ * need to cancel the request, to avoid
+ * the possibility of starting another
+ * concurrently
+ */
+ talloc_zfree(req);
+
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to schedule refresh of SUDO rules, "
+ "retrying later!\n"));
+ tv = tevent_timeval_current_ofs(delay, 0);
+ ret = sdap_sudo_refresh_set_timer(refresh_ctx, tv);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Error setting up SUDO refresh timer\n"));
+ }
+ }
+
+ return;
+}
+
+static void sdap_sudo_refresh_reschedule(struct tevent_req *req)
+{
+ struct sdap_sudo_refresh_ctx *refresh_ctx = NULL;
+ struct sdap_sudo_ctx *sudo_ctx = NULL;
+ struct timeval tv;
+ int delay;
+ int dp_error;
+ int error;
+ int ret;
+
+ refresh_ctx = tevent_req_callback_data(req, struct sdap_sudo_refresh_ctx);
+ ret = sdap_sudo_refresh_recv(req, &sudo_ctx, &dp_error, &error);
+ talloc_zfree(req);
+ talloc_zfree(sudo_ctx);
+ if (ret != EOK) {
+ tv = tevent_timeval_current();
+ } else {
+ tv = refresh_ctx->last_refresh;
+
+ /* Ok, we've completed a refresh. Save this to the
+ * sysdb so we can postpone starting up the refresh
+ * process on the next SSSD service restart (to avoid
+ * slowing down system boot-up
+ */
+ ret = sysdb_sudo_set_refreshed(refresh_ctx->be_ctx->sysdb, true);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Could not mark domain as having refreshed.\n"));
+ /* This error is non-fatal, so continue */
+ }
+ }
+
+ delay = dp_opt_get_int(refresh_ctx->opts->basic, SDAP_SUDO_REFRESH_TIMEOUT);
+ tv = tevent_timeval_add(&tv, delay, 0);
+ ret = sdap_sudo_refresh_set_timer(refresh_ctx, tv);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Error setting up SUDO refresh timer\n"));
+ }
+}
+
+static void sdap_sudo_refresh_timeout(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval tv, void *pvt)
+{
+ struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
+ struct sdap_sudo_refresh_ctx *refresh_ctx = NULL;
+ int delay;
+
+ refresh_ctx = tevent_req_callback_data(req, struct sdap_sudo_refresh_ctx);
+
+ delay = dp_opt_get_int(refresh_ctx->opts->basic, SDAP_SUDO_REFRESH_TIMEOUT);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Refreshing SUDO rules timed out!"
+ " Timeout too small? (%ds)!\n", delay));
+
+ tv = tevent_timeval_current_ofs(delay, 0);
+ sdap_sudo_refresh_set_timer(refresh_ctx, tv);
+
+ talloc_zfree(req);
+}