diff options
author | Pavel Březina <pbrezina@redhat.com> | 2012-05-09 15:00:39 +0200 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2012-06-29 11:37:18 -0400 |
commit | b041138015878405fe09ee6695d9ff5e5be07405 (patch) | |
tree | 2fc12b400c1709a7cf2a1f46850e655f4004bb14 | |
parent | 3ea714e82b83e0553212b5dbe8f9148908bc9ddb (diff) | |
download | sssd-b041138015878405fe09ee6695d9ff5e5be07405.tar.gz sssd-b041138015878405fe09ee6695d9ff5e5be07405.tar.bz2 sssd-b041138015878405fe09ee6695d9ff5e5be07405.zip |
sudo ldap provider: support periodical smart refresh
When SSSD is started, then full refresh is scheduled.
The smart refresh is scheduled after this full refresh,
if USN (or modifyTimestamp) values are available.
If full refresh interval <= smart refresh interval then
full refresh will be disabled.
If both refresh types are 0 then smart refresh interval
is set to default value.
-rw-r--r-- | src/providers/ldap/sdap_sudo.c | 250 |
1 files changed, 177 insertions, 73 deletions
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c index 8cc449f4..a0bba0d0 100644 --- a/src/providers/ldap/sdap_sudo.c +++ b/src/providers/ldap/sdap_sudo.c @@ -71,10 +71,18 @@ 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_full_refresh(struct sdap_id_ctx *id_ctx, + time_t delay); + +static int sdap_sudo_schedule_smart_refresh(struct sdap_id_ctx *id_ctx, + time_t delay); + static void sdap_sudo_shutdown(struct be_req *req) { @@ -86,7 +94,7 @@ struct bet_ops sdap_sudo_ops = { .finalize = sdap_sudo_shutdown }; -int sdap_sudo_setup_periodical_full_refresh(struct sdap_id_ctx *id_ctx); +int sdap_sudo_setup_periodical_refresh(struct sdap_id_ctx *id_ctx); int sdap_sudo_init(struct be_ctx *be_ctx, struct sdap_id_ctx *id_ctx, @@ -108,76 +116,97 @@ int sdap_sudo_init(struct be_ctx *be_ctx, return ret; } - ret = sdap_sudo_setup_periodical_full_refresh(id_ctx); + ret = sdap_sudo_setup_periodical_refresh(id_ctx); if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("Unable to setup periodical full refresh" + DEBUG(SSSDBG_OP_FAILURE, ("Unable to setup periodical refresh" "of sudo rules [%d]: %s\n", ret, strerror(ret))); } return EOK; } -int sdap_sudo_setup_periodical_full_refresh(struct sdap_id_ctx *id_ctx) +int sdap_sudo_setup_periodical_refresh(struct sdap_id_ctx *id_ctx) { struct tevent_req *req; + time_t smart_default; + time_t smart_interval; time_t full_interval; time_t last_full; - time_t now; struct timeval tv; int ret; - /* setup periodical full refresh */ + 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 (full_interval != 0) { - ret = sysdb_sudo_get_last_full_refresh(id_ctx->be->sysdb, &last_full); + + 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 (%d).\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 (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 - */ - tv = tevent_timeval_current(); - } 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. - */ - - now = time(NULL); - if (last_full + full_interval < now) { - /* delay at least by 10s */ - tv = tevent_timeval_current_ofs(10, 0); - } else { - tv = tevent_timeval_set(last_full + full_interval, 0); - } - } - - req = sdap_sudo_timer_send(id_ctx, id_ctx->be->ev, id_ctx, - tv, full_interval, - sdap_sudo_full_refresh_send); - if (req == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("Unable to schedule full refresh of sudo " - "rules! Full periodical refresh will not work.\n")); - return ENOMEM; + 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; } + } - tevent_req_set_callback(req, sdap_sudo_periodical_full_refresh_done, - id_ctx); + ret = sysdb_sudo_get_last_full_refresh(id_ctx->be->sysdb, &last_full); + if (ret != EOK) { + return ret; + } - DEBUG(SSSDBG_TRACE_FUNC, ("Full refresh scheduled at: %lld\n", - (long long)tv.tv_sec)); + 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 + */ + tv = tevent_timeval_current(); } else { - DEBUG(SSSDBG_CONF_SETTINGS, ("Periodical full refresh of sudo rules " - "is disabled\n")); + /* 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 */ + tv = tevent_timeval_current_ofs(10, 0); } + req = sdap_sudo_timer_send(id_ctx, id_ctx->be->ev, id_ctx, + tv, full_interval, + sdap_sudo_full_refresh_send); + if (req == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("Unable to schedule full refresh of sudo " + "rules! Periodical updates will not work!\n")); + return ENOMEM; + } + + tevent_req_set_callback(req, sdap_sudo_periodical_first_refresh_done, + id_ctx); + + DEBUG(SSSDBG_TRACE_FUNC, ("Full refresh scheduled at: %lld\n", + (long long)tv.tv_sec)); + return EOK; } @@ -594,12 +623,10 @@ static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq) tevent_req_done(req); } -static void sdap_sudo_periodical_full_refresh_done(struct tevent_req *req) +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 tevent_req *newreq = NULL; struct sdap_id_ctx *id_ctx = NULL; - struct timeval tv; time_t delay; int dp_error; int error; @@ -624,6 +651,7 @@ schedule: id_ctx = tevent_req_callback_data(req, struct sdap_id_ctx); talloc_zfree(req); + /* full refresh */ delay = dp_opt_get_int(id_ctx->opts->basic, SDAP_SUDO_FULL_REFRESH_INTERVAL); if (delay == 0) { /* runtime configuration change? */ @@ -632,29 +660,72 @@ schedule: return; } - /* schedule new refresh */ - tv = tevent_timeval_current_ofs(delay, 0); - newreq = sdap_sudo_timer_send(id_ctx, id_ctx->be->ev, id_ctx, - tv, delay, sdap_sudo_full_refresh_send); - if (newreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("Unable to schedule full refresh of sudo " - "rules! Full periodical refresh will not work.\n")); + ret = sdap_sudo_schedule_full_refresh(id_ctx, delay); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Full periodical refresh will not work.\n")); + } + + /* smart refresh */ + delay = dp_opt_get_int(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; } - tevent_req_set_callback(newreq, sdap_sudo_periodical_full_refresh_done, - id_ctx); + ret = sdap_sudo_schedule_smart_refresh(id_ctx, delay); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Smart periodical refresh will not work.\n")); + } +} - DEBUG(SSSDBG_TRACE_FUNC, ("Full refresh scheduled at: %lld\n", - (long long)tv.tv_sec)); +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_id_ctx *id_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_full_refresh_recv(subreq, &dp_error, &error); + if (dp_error != DP_ERR_OK || error != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Periodical full refresh of sudo rules " + "failed [dp_error: %d] ([%d]: %s)", + dp_error, error, strerror(error))); + goto schedule; + } + +schedule: + id_ctx = tevent_req_callback_data(req, struct sdap_id_ctx); + talloc_zfree(req); + + delay = dp_opt_get_int(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(id_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 tevent_req *newreq = NULL; struct sdap_id_ctx *id_ctx = NULL; - struct timeval tv; time_t delay; int dp_error; int error; @@ -679,12 +750,6 @@ schedule: id_ctx = tevent_req_callback_data(req, struct sdap_id_ctx); talloc_zfree(req); - if (id_ctx->srv_opts == NULL || id_ctx->srv_opts->supports_usn == false) { - DEBUG(SSSDBG_TRACE_FUNC, ("USN values are not supported by the server. " - "Smart refresh of sudo rules will not work!\n")); - return; - } - delay = dp_opt_get_int(id_ctx->opts->basic, SDAP_SUDO_SMART_REFRESH_INTERVAL); if (delay == 0) { /* runtime configuration change? */ @@ -693,19 +758,58 @@ schedule: return; } + ret = sdap_sudo_schedule_smart_refresh(id_ctx, delay); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Smart periodical refresh will not work.\n")); + } +} + +static int sdap_sudo_schedule_full_refresh(struct sdap_id_ctx *id_ctx, + time_t delay) +{ + struct tevent_req *req = NULL; + struct timeval tv; + + /* schedule new refresh */ + tv = tevent_timeval_current_ofs(delay, 0); + req = sdap_sudo_timer_send(id_ctx, id_ctx->be->ev, id_ctx, + tv, delay, sdap_sudo_full_refresh_send); + if (req == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("Unable to schedule full refresh of sudo " + "rules!\n")); + return ENOMEM; + } + + tevent_req_set_callback(req, sdap_sudo_periodical_full_refresh_done, + id_ctx); + + DEBUG(SSSDBG_TRACE_FUNC, ("Full refresh scheduled at: %lld\n", + (long long)tv.tv_sec)); + + return EOK; +} + +static int sdap_sudo_schedule_smart_refresh(struct sdap_id_ctx *id_ctx, + time_t delay) +{ + struct tevent_req *req = NULL; + struct timeval tv; + /* schedule new refresh */ tv = tevent_timeval_current_ofs(delay, 0); - newreq = sdap_sudo_timer_send(id_ctx, id_ctx->be->ev, id_ctx, - tv, delay, sdap_sudo_smart_refresh_send); - if (newreq == NULL) { + req = sdap_sudo_timer_send(id_ctx, id_ctx->be->ev, id_ctx, + tv, delay, sdap_sudo_smart_refresh_send); + if (req == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("Unable to schedule smart refresh of sudo " - "rules! Smart periodical refresh will not work.\n")); - return; + "rules!\n")); + return ENOMEM; } - tevent_req_set_callback(newreq, sdap_sudo_periodical_smart_refresh_done, + tevent_req_set_callback(req, sdap_sudo_periodical_smart_refresh_done, id_ctx); DEBUG(SSSDBG_TRACE_FUNC, ("Smart refresh scheduled at: %lld\n", (long long)tv.tv_sec)); + + return EOK; } |