diff options
author | Pavel Březina <pbrezina@redhat.com> | 2015-11-06 13:00:47 +0100 |
---|---|---|
committer | Lukas Slebodnik <lslebodn@redhat.com> | 2015-12-15 16:25:57 +0100 |
commit | a13cf3d295a4a6654dfa7e4193c0a2bc8bb78e92 (patch) | |
tree | d3cd4769dd68a4adb976ab9744f4f83b5f7b0e1d /src/providers/ldap/sdap_sudo.c | |
parent | e131fef2d3f40bce5af85613690df8aa15f90fde (diff) | |
download | sssd-a13cf3d295a4a6654dfa7e4193c0a2bc8bb78e92.tar.gz sssd-a13cf3d295a4a6654dfa7e4193c0a2bc8bb78e92.tar.xz sssd-a13cf3d295a4a6654dfa7e4193c0a2bc8bb78e92.zip |
SUDO: convert periodical refreshes to be_ptask
This removes old sudo timer and simplyfies code a lot. It also
allows to manage offline/online state.
- Full and smart refresh are disabled when offline.
- Full refresh is run immediately when sssd is back online.
- Smart refresh is scheduled normally when sssd is back online.
Resolves:
https://fedorahosted.org/sssd/ticket/1943
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
Diffstat (limited to 'src/providers/ldap/sdap_sudo.c')
-rw-r--r-- | src/providers/ldap/sdap_sudo.c | 470 |
1 files changed, 12 insertions, 458 deletions
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c index ccc775fb0..4885564ec 100644 --- a/src/providers/ldap/sdap_sudo.c +++ b/src/providers/ldap/sdap_sudo.c @@ -30,8 +30,6 @@ #include "providers/ldap/sdap_sudo_cache.h" #include "db/sysdb_sudo.h" -#define SUDO_MAX_FIRST_REFRESH_DELAY 16 - struct sdap_sudo_full_refresh_state { struct sdap_sudo_ctx *sudo_ctx; struct sdap_id_ctx *id_ctx; @@ -41,15 +39,8 @@ struct sdap_sudo_full_refresh_state { int error; }; -static struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx, - struct sdap_sudo_ctx *sudo_ctx); - static void sdap_sudo_full_refresh_done(struct tevent_req *subreq); -static int sdap_sudo_full_refresh_recv(struct tevent_req *req, - int *dp_error, - int *error); - struct sdap_sudo_rules_refresh_state { struct sdap_id_ctx *id_ctx; size_t num_rules; @@ -76,35 +67,8 @@ struct sdap_sudo_smart_refresh_state { struct sysdb_ctx *sysdb; }; -static struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx, - struct sdap_sudo_ctx *sudo_ctx); - static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq); -static int sdap_sudo_smart_refresh_recv(struct tevent_req *req, - int *dp_error, - int *error); - -static void sdap_sudo_periodical_first_refresh_done(struct tevent_req *req); - -static void sdap_sudo_periodical_full_refresh_done(struct tevent_req *req); - -static void sdap_sudo_periodical_smart_refresh_done(struct tevent_req *req); - -static int sdap_sudo_schedule_refresh(TALLOC_CTX *mem_ctx, - struct sdap_sudo_ctx *sudo_ctx, - enum sdap_sudo_refresh_type refresh, - tevent_req_fn callback, - time_t delay, - time_t timeout, - struct tevent_req **_req); - -static int sdap_sudo_schedule_full_refresh(struct sdap_sudo_ctx *sudo_ctx, - time_t delay); - -static int sdap_sudo_schedule_smart_refresh(struct sdap_sudo_ctx *sudo_ctx, - time_t delay); - static void sdap_sudo_shutdown(struct be_req *req) { @@ -117,7 +81,6 @@ struct bet_ops sdap_sudo_ops = { }; static void sdap_sudo_get_hostinfo_done(struct tevent_req *req); -static int sdap_sudo_setup_periodical_refresh(struct sdap_sudo_ctx *sudo_ctx); int sdap_sudo_init(struct be_ctx *be_ctx, struct sdap_id_ctx *id_ctx, @@ -162,7 +125,7 @@ int sdap_sudo_init(struct be_ctx *be_ctx, sudo_ctx->use_host_filter = false; - ret = sdap_sudo_setup_periodical_refresh(sudo_ctx); + ret = sdap_sudo_ptask_setup(sudo_ctx->id_ctx->be, sudo_ctx); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Unable to setup periodical refresh" @@ -200,94 +163,13 @@ static void sdap_sudo_get_hostinfo_done(struct tevent_req *req) sudo_ctx->hostnames = talloc_move(sudo_ctx, &hostnames); sudo_ctx->ip_addr = talloc_move(sudo_ctx, &ip_addr); - ret = sdap_sudo_setup_periodical_refresh(sudo_ctx); + ret = sdap_sudo_ptask_setup(sudo_ctx->id_ctx->be, sudo_ctx); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Unable to setup periodical refresh" "of sudo rules [%d]: %s\n", ret, strerror(ret)); } } -static int sdap_sudo_setup_periodical_refresh(struct sdap_sudo_ctx *sudo_ctx) -{ - struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx; - time_t smart_default; - time_t smart_interval; - time_t full_interval; - time_t last_full; - time_t delay; - int ret; - - smart_interval = dp_opt_get_int(id_ctx->opts->basic, - SDAP_SUDO_SMART_REFRESH_INTERVAL); - - full_interval = dp_opt_get_int(id_ctx->opts->basic, - SDAP_SUDO_FULL_REFRESH_INTERVAL); - - if (smart_interval == 0 && full_interval == 0) { - smart_default = id_ctx->opts->basic[SDAP_SUDO_SMART_REFRESH_INTERVAL].def_val.number; - - DEBUG(SSSDBG_MINOR_FAILURE, "At least one periodical update has to be " - "enabled. Setting smart refresh interval to default value (%ld).\n", - smart_default); - - ret = dp_opt_set_int(id_ctx->opts->basic, - SDAP_SUDO_SMART_REFRESH_INTERVAL, - smart_default); - if (ret != EOK) { - return ret; - } - } - - if (full_interval <= smart_interval) { - DEBUG(SSSDBG_MINOR_FAILURE, "Full refresh interval has to be greater" - "than smart refresh interval. Periodical full refresh will be " - "disabled.\n"); - ret = dp_opt_set_int(id_ctx->opts->basic, - SDAP_SUDO_FULL_REFRESH_INTERVAL, - 0); - if (ret != EOK) { - return ret; - } - } - - ret = sysdb_sudo_get_last_full_refresh(id_ctx->be->domain, - &last_full); - if (ret != EOK) { - return ret; - } - - if (last_full == 0) { - /* If this is the first startup, we need to kick off - * an refresh immediately, to close a window where - * clients requesting sudo information won't get an - * immediate reply with no entries - */ - delay = 0; - } else { - /* At least one update has previously run, - * so clients will get cached data. - * We will delay the refresh so we don't slow - * down the startup process if this is happening - * during system boot. - */ - - /* delay at least by 10s */ - delay = 10; - } - - ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx, - SDAP_SUDO_REFRESH_FULL, - sdap_sudo_periodical_first_refresh_done, - delay, full_interval, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo " - "rules! Periodical updates will not work!\n"); - return ret; - } - - return EOK; -} - static void sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, char *usn) { unsigned int usn_number; @@ -532,8 +414,8 @@ fail: } /* issue full refresh of sudo rules */ -static struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx, - struct sdap_sudo_ctx *sudo_ctx) +struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx, + struct sdap_sudo_ctx *sudo_ctx) { struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; @@ -657,9 +539,9 @@ done: tevent_req_done(req); } -static int sdap_sudo_full_refresh_recv(struct tevent_req *req, - int *dp_error, - int *error) +int sdap_sudo_full_refresh_recv(struct tevent_req *req, + int *dp_error, + int *error) { struct sdap_sudo_full_refresh_state *state = NULL; state = tevent_req_data(req, struct sdap_sudo_full_refresh_state); @@ -835,8 +717,8 @@ static int sdap_sudo_rules_refresh_recv(struct tevent_req *req, } /* issue smart refresh of sudo rules */ -static struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx, - struct sdap_sudo_ctx *sudo_ctx) +struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx, + struct sdap_sudo_ctx *sudo_ctx) { struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; @@ -959,9 +841,9 @@ done: tevent_req_done(req); } -static int sdap_sudo_smart_refresh_recv(struct tevent_req *req, - int *dp_error, - int *error) +int sdap_sudo_smart_refresh_recv(struct tevent_req *req, + int *dp_error, + int *error) { struct sdap_sudo_smart_refresh_state *state = NULL; state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state); @@ -971,331 +853,3 @@ static int sdap_sudo_smart_refresh_recv(struct tevent_req *req, return sdap_sudo_refresh_recv(state, state->subreq, dp_error, error, NULL, NULL); } - -static void sdap_sudo_full_refresh_online_cb(void *pvt) -{ - struct sdap_sudo_ctx *sudo_ctx = NULL; - time_t timeout; - int ret; - - sudo_ctx = talloc_get_type(pvt, struct sdap_sudo_ctx); - - /* remove online callback */ - talloc_zfree(sudo_ctx->first_refresh_online_cb); - - /* schedule new first refresh only if this callback wasn't triggered - * by ongoing full refresh */ - if (sudo_ctx->full_refresh_in_progress) { - return; - } - - /* otherwise cancel the concurrent timer for full refresh */ - talloc_zfree(sudo_ctx->first_refresh_timer); - - /* and fire full refresh immediately */ - timeout = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic, - SDAP_SUDO_FULL_REFRESH_INTERVAL); - if (timeout == 0) { - /* runtime configuration change? */ - DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules " - "is disabled\n"); - return; - } - - ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx, - SDAP_SUDO_REFRESH_FULL, - sdap_sudo_periodical_first_refresh_done, - 0, timeout, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo " - "rules! Periodical updates will not work!\n"); - } -} - -static void sdap_sudo_periodical_first_refresh_done(struct tevent_req *req) -{ - struct tevent_req *subreq = NULL; /* req from sdap_sudo_full_refresh_send() */ - struct sdap_sudo_ctx *sudo_ctx = NULL; - time_t delay; - time_t timeout; - int dp_error = DP_ERR_OK; - int error = EOK; - int ret; - - ret = sdap_sudo_timer_recv(req, req, &subreq); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "Sudo timer failed [%d]: %s\n", ret, strerror(ret)); - goto schedule; - } - - ret = sdap_sudo_full_refresh_recv(subreq, &dp_error, &error); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules " - "failed [%d]: %s)\n", ret, strerror(ret)); - goto schedule; - } - - if (dp_error != DP_ERR_OK || error != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules " - "failed [dp_error: %d] ([%d]: %s)\n", - dp_error, error, strerror(error)); - goto schedule; - } - -schedule: - sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx); - if (sudo_ctx->first_refresh_timer == req) { - sudo_ctx->first_refresh_timer = NULL; - } - talloc_zfree(req); - - /* full refresh */ - delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic, - SDAP_SUDO_FULL_REFRESH_INTERVAL); - if (delay == 0) { - /* runtime configuration change? */ - DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules " - "is disabled\n"); - return; - } - - /* if we are offline, we will try to perform another full refresh */ - if (dp_error == DP_ERR_OFFLINE) { - sudo_ctx->full_refresh_attempts++; - timeout = delay; - delay = sudo_ctx->full_refresh_attempts << 1; - if (delay > SUDO_MAX_FIRST_REFRESH_DELAY) { - delay = SUDO_MAX_FIRST_REFRESH_DELAY; - } - - DEBUG(SSSDBG_TRACE_FUNC, "Data provider is offline. " - "Scheduling another full refresh in %ld minutes.\n", delay); - - ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx, - SDAP_SUDO_REFRESH_FULL, - sdap_sudo_periodical_first_refresh_done, - delay * 60, timeout, - &sudo_ctx->first_refresh_timer); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo " - "rules! Periodical updates will not work!\n"); - } - - /* also setup online callback to make sure the refresh is fired as soon - * as possible */ - ret = be_add_online_cb(sudo_ctx->id_ctx->be, sudo_ctx->id_ctx->be, - sdap_sudo_full_refresh_online_cb, - sudo_ctx, &sudo_ctx->first_refresh_online_cb); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Could not set up online callback\n"); - } - - return; - } - - ret = sdap_sudo_schedule_full_refresh(sudo_ctx, delay); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Full periodical refresh will not work.\n"); - } - - /* smart refresh */ - delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic, - SDAP_SUDO_SMART_REFRESH_INTERVAL); - if (delay == 0) { - /* runtime configuration change? */ - DEBUG(SSSDBG_TRACE_FUNC, "Periodical smart refresh of sudo rules " - "is disabled\n"); - return; - } - - ret = sdap_sudo_schedule_smart_refresh(sudo_ctx, delay); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Smart periodical refresh will not work.\n"); - } -} - -static void sdap_sudo_periodical_full_refresh_done(struct tevent_req *req) -{ - struct tevent_req *subreq = NULL; /* req from sdap_sudo_full_refresh_send() */ - struct sdap_sudo_ctx *sudo_ctx = NULL; - time_t delay; - int dp_error = DP_ERR_FATAL; - int error = EFAULT; - int ret; - - ret = sdap_sudo_timer_recv(req, req, &subreq); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "Sudo timer failed [%d]: %s\n", ret, strerror(ret)); - goto schedule; - } - - ret = sdap_sudo_full_refresh_recv(subreq, &dp_error, &error); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules " - "failed [%d]: %s)\n", ret, strerror(ret)); - goto schedule; - } - - if (dp_error != DP_ERR_OK || error != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules " - "failed [dp_error: %d] ([%d]: %s)\n", - dp_error, error, strerror(error)); - goto schedule; - } - -schedule: - sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx); - talloc_zfree(req); - - delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic, - SDAP_SUDO_FULL_REFRESH_INTERVAL); - if (delay == 0) { - /* runtime configuration change? */ - DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules " - "is disabled\n"); - return; - } - - ret = sdap_sudo_schedule_full_refresh(sudo_ctx, delay); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Full periodical refresh will not work.\n"); - } -} - -static void sdap_sudo_periodical_smart_refresh_done(struct tevent_req *req) -{ - struct tevent_req *subreq = NULL; /* req from sdap_sudo_smart_refresh_send() */ - struct sdap_sudo_ctx *sudo_ctx = NULL; - time_t delay; - int dp_error; - int error; - int ret; - - ret = sdap_sudo_timer_recv(req, req, &subreq); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "Sudo timer failed [%d]: %s\n", ret, strerror(ret)); - goto schedule; - } - - ret = sdap_sudo_smart_refresh_recv(subreq, &dp_error, &error); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Periodical smart refresh of sudo rules " - "failed [%d]: %s\n", ret, strerror(ret)); - } - - if (dp_error != DP_ERR_OK || error != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Periodical smart refresh of sudo rules " - "failed [dp_error: %d] ([%d]: %s)\n", - dp_error, error, strerror(error)); - goto schedule; - } - -schedule: - sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx); - talloc_zfree(req); - - delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic, - SDAP_SUDO_SMART_REFRESH_INTERVAL); - if (delay == 0) { - /* runtime configuration change? */ - DEBUG(SSSDBG_TRACE_FUNC, "Periodical smart refresh of sudo rules " - "is disabled\n"); - return; - } - - ret = sdap_sudo_schedule_smart_refresh(sudo_ctx, delay); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Smart periodical refresh will not work.\n"); - } -} - -static int sdap_sudo_schedule_refresh(TALLOC_CTX *mem_ctx, - struct sdap_sudo_ctx *sudo_ctx, - enum sdap_sudo_refresh_type refresh, - tevent_req_fn callback, - time_t delay, - time_t timeout, - struct tevent_req **_req) -{ - struct tevent_req *req = NULL; - sdap_sudo_timer_fn_t send_fn = NULL; - const char *name = NULL; - struct timeval when; - - when = tevent_timeval_current_ofs(delay, 0); - - switch (refresh) { - case SDAP_SUDO_REFRESH_FULL: - send_fn = sdap_sudo_full_refresh_send; - name = "Full refresh"; - break; - case SDAP_SUDO_REFRESH_SMART: - send_fn = sdap_sudo_smart_refresh_send; - name = "Smart refresh"; - break; - case SDAP_SUDO_REFRESH_RULES: - DEBUG(SSSDBG_OP_FAILURE, "Rules refresh can't be scheduled!\n"); - return EINVAL; - default: - DEBUG(SSSDBG_CRIT_FAILURE, "Unknown refresh type [%d].\n", refresh); - return EINVAL; - } - - - - req = sdap_sudo_timer_send(mem_ctx, sudo_ctx->id_ctx->be->ev, sudo_ctx, - when, timeout, send_fn); - if (req == NULL) { - return ENOMEM; - } - - tevent_req_set_callback(req, callback, sudo_ctx); - - DEBUG(SSSDBG_TRACE_FUNC, "%s scheduled at: %lld\n", - name, (long long)when.tv_sec); - - if (_req != NULL) { - *_req = req; - } - - return EOK; -} - -static int sdap_sudo_schedule_full_refresh(struct sdap_sudo_ctx *sudo_ctx, - time_t delay) -{ - int ret; - - ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx, - SDAP_SUDO_REFRESH_FULL, - sdap_sudo_periodical_full_refresh_done, - delay, delay, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo " - "rules!\n"); - return ret; - } - - return EOK; -} - -static int sdap_sudo_schedule_smart_refresh(struct sdap_sudo_ctx *sudo_ctx, - time_t delay) -{ - int ret; - - ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx, - SDAP_SUDO_REFRESH_SMART, - sdap_sudo_periodical_smart_refresh_done, - delay, delay, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule smart refresh of sudo " - "rules!\n"); - return ret; - } - - return EOK; -} |