diff options
-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; } |