summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2012-05-09 15:00:39 +0200
committerStephen Gallagher <sgallagh@redhat.com>2012-06-29 11:37:18 -0400
commitb041138015878405fe09ee6695d9ff5e5be07405 (patch)
tree2fc12b400c1709a7cf2a1f46850e655f4004bb14
parent3ea714e82b83e0553212b5dbe8f9148908bc9ddb (diff)
downloadsssd-b041138015878405fe09ee6695d9ff5e5be07405.tar.gz
sssd-b041138015878405fe09ee6695d9ff5e5be07405.tar.xz
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.c250
1 files changed, 177 insertions, 73 deletions
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c
index 8cc449f45..a0bba0d01 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;
}