summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/examples/sssd.conf9
-rw-r--r--server/man/sssd.conf.5.xml13
-rw-r--r--server/responder/nss/nsssrv.c16
-rw-r--r--server/responder/nss/nsssrv.h4
-rw-r--r--server/responder/nss/nsssrv_cmd.c35
5 files changed, 75 insertions, 2 deletions
diff --git a/server/examples/sssd.conf b/server/examples/sssd.conf
index 90e0c8d11..b47ab9ddd 100644
--- a/server/examples/sssd.conf
+++ b/server/examples/sssd.conf
@@ -13,6 +13,15 @@ description = NSS Responder Configuration
filterGroups = root
filterUsers = root
+# The EntryCacheTimeout indicates the number of seconds to retain before
+# an entry in cache is considered stale and must block to refresh.
+# The EntryCacheNoWaitRefreshTimeout indicates the number of seconds to
+# wait before updating the cache out-of-band. (NSS requests will still
+# be returned from cache until the full EntryCacheTimeout). Setting this
+# value to 0 turns this feature off (default)
+; EntryCacheTimeout = 600
+; EntryCacheNoWaitRefreshTimeout = 300
+
[services/dp]
description = Data Provider Configuration
diff --git a/server/man/sssd.conf.5.xml b/server/man/sssd.conf.5.xml
index b64899a0e..827dd96ba 100644
--- a/server/man/sssd.conf.5.xml
+++ b/server/man/sssd.conf.5.xml
@@ -336,6 +336,19 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term>EntryCacheNoWaitRefreshTimeout (integer)</term>
+ <listitem>
+ <para>
+ How long should nss_sss return cached entries before
+ initiating an out-of-band cache refresh (0 disables
+ this feature)
+ </para>
+ <para>
+ Default: 0
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term>EntryNegativeTimeout (integer)</term>
<listitem>
<para>
diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c
index ad8043890..3920189af 100644
--- a/server/responder/nss/nsssrv.c
+++ b/server/responder/nss/nsssrv.c
@@ -107,6 +107,22 @@ static int nss_get_config(struct nss_ctx *nctx,
&nctx->filter_users_in_groups);
if (ret != EOK) goto done;
+
+ ret = confdb_get_int(cdb, nctx, NSS_SRV_CONFIG,
+ "EntryCacheNoWaitRefreshTimeout", 0,
+ &nctx->cache_refresh_timeout);
+ if (ret != EOK) goto done;
+ if (nctx->cache_refresh_timeout >= nctx->cache_timeout) {
+ DEBUG(0,("Configuration error: EntryCacheNoWaitRefreshTimeout exceeds"
+ "EntryCacheTimeout. Disabling feature.\n"));
+ nctx->cache_refresh_timeout = 0;
+ }
+ if (nctx->cache_refresh_timeout < 0) {
+ DEBUG(0,("Configuration error: EntryCacheNoWaitRefreshTimeout is"
+ "invalid. Disabling feature.\n"));
+ nctx->cache_refresh_timeout = 0;
+ }
+
ret = confdb_get_string_as_list(cdb, tmpctx, NSS_SRV_CONFIG,
"filterUsers", &filter_list);
if (ret == ENOENT) filter_list = NULL;
diff --git a/server/responder/nss/nsssrv.h b/server/responder/nss/nsssrv.h
index c5a7bb301..a5adbaf83 100644
--- a/server/responder/nss/nsssrv.h
+++ b/server/responder/nss/nsssrv.h
@@ -46,10 +46,12 @@ struct getent_ctx;
struct nss_ctx {
struct resp_ctx *rctx;
- int cache_timeout;
int neg_timeout;
struct nss_nc_ctx *ncache;
+ int cache_timeout;
+ int cache_refresh_timeout;
+
int enum_cache_timeout;
time_t last_user_enum;
time_t last_group_enum;
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
index 3b0f867e2..926009335 100644
--- a/server/responder/nss/nsssrv_cmd.c
+++ b/server/responder/nss/nsssrv_cmd.c
@@ -278,26 +278,50 @@ static errno_t check_cache(struct nss_dom_ctx *dctx,
{
errno_t ret;
int timeout;
+ int refresh_timeout;
time_t now;
uint64_t lastUpdate;
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
struct cli_ctx *cctx = cmdctx->cctx;
bool call_provider = false;
+ sss_dp_callback_t cb = NULL;
if (dctx->check_provider) {
switch (res->count) {
case 0:
+ /* This is a cache miss. We need to get the updated user
+ * information before returning it.
+ */
call_provider = true;
+ cb = callback;
break;
case 1:
timeout = nctx->cache_timeout;
+ refresh_timeout = nctx->cache_refresh_timeout;
now = time(NULL);
lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0],
SYSDB_LAST_UPDATE, 0);
if (lastUpdate + timeout < now) {
+ /* This is a cache miss. We need to get the updated user
+ * information before returning it.
+ */
call_provider = true;
+ cb = callback;
+ }
+ else if (refresh_timeout && (lastUpdate + refresh_timeout < now)) {
+ /* We're past the the cache refresh timeout
+ * We'll return the value from the cache, but we'll also
+ * queue the cache entry for update out-of-band.
+ */
+ call_provider = true;
+ cb = NULL;
+ }
+ else {
+ /* Cache is still valid. Just return it. */
+ call_provider = false;
+ cb = NULL;
}
break;
@@ -340,7 +364,16 @@ static errno_t check_cache(struct nss_dom_ctx *dctx,
/* Tell the calling function to return so the dp callback
* can resolve
*/
- return EAGAIN;
+ if (cb) {
+ return EAGAIN;
+ }
+
+ /* No callback required
+ * This was an out-of-band update. We'll return EOK
+ * so the calling function can return the cached entry
+ * immediately.
+ */
+ DEBUG(3, ("Updating cache out-of-band\n"));
}
return EOK;