This set of functions enumerate each user/group from all domains and invalidate any mmap cache record that matches. --- src/providers/data_provider.h | 6 ++ src/responder/nss/nsssrv.c | 15 +++++ src/responder/nss/nsssrv_cmd.c | 100 ++++++++++++++++++++++++++++++++++++ src/responder/nss/nsssrv_private.h | 3 + 4 files changed, 124 insertions(+), 0 deletions(-)
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index bb944509da9f1dc89216266cf62c57fb4127fd57..9c7340021268925860b48b3e62f0d0b4d4731ebb 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -54,6 +54,12 @@ #define DP_METHOD_AUTOFSHANDLER "autofsHandler" #define DP_METHOD_HOSTHANDLER "hostHandler" #define DP_METHOD_GETDOMAINS "getDomains" + +/* this is a reverse method sent from providers to + * the nss responder to tell it to update the mmap + * cache */ +#define DP_REV_METHOD_UPDATE_CACHE "updateCache" + /** * @defgroup pamHandler PAM DBUS request * @ingroup sss_pam diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c index e01bd1a4d49d80e0c43fa1bbe4521636c87015e6..8694edaf614f6a218621518416965ffb2e558873 100644 --- a/src/responder/nss/nsssrv.c +++ b/src/responder/nss/nsssrv.c @@ -33,6 +33,7 @@ #include "popt.h" #include "util/util.h" #include "responder/nss/nsssrv.h" +#include "responder/nss/nsssrv_private.h" #include "responder/nss/nsssrv_mmap_cache.h" #include "responder/common/negcache.h" #include "db/sysdb.h" @@ -280,7 +281,21 @@ done: return ret; }
+static int nss_update_memcache(DBusMessage *message, + struct sbus_connection *conn) +{ + struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(conn), + struct resp_ctx); + struct nss_ctx *nctx = talloc_get_type(rctx->pvt_ctx, struct nss_ctx); + + nss_update_pw_memcache(nctx); + nss_update_gr_memcache(nctx); + + return EOK; +} + static struct sbus_method nss_dp_methods[] = { + { DP_REV_METHOD_UPDATE_CACHE, nss_update_memcache }, { NULL, NULL } };
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c index db1efdd21f8b0f277c2465bfecdf51bba6395408..2397fb38d37e0fc4c00b2f2967e3d12afbffde2e 100644 --- a/src/responder/nss/nsssrv_cmd.c +++ b/src/responder/nss/nsssrv_cmd.c @@ -107,6 +107,56 @@ struct setent_ctx { * PASSWD db related functions ***************************************************************************/
+void nss_update_pw_memcache(struct nss_ctx *nctx) +{ + struct sss_domain_info *dom; + struct ldb_result *res; + uint64_t exp; + struct sized_string key; + const char *id; + time_t now; + int ret; + int i; + + now = time(NULL); + + for (dom = nctx->rctx->domains; dom != NULL; dom = dom->next) { + ret = sysdb_enumpwent(nctx, dom->sysdb, &res); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Failed to enumerate users for domain [%s]\n", dom->name)); + continue; + } + + for (i = 0; i < res->count; i++) { + exp = ldb_msg_find_attr_as_uint64(res->msgs[i], + SYSDB_CACHE_EXPIRE, 0); + if (exp >= now) { + continue; + } + + /* names require more manipulation (build up fqname conditionally), + * but uidNumber is unique and always resolvable too, so we use + * that to update the cache, as it points to the same entry */ + id = ldb_msg_find_attr_as_string(res->msgs[i], SYSDB_UIDNUM, NULL); + if (!id) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Failed to find uidNumber in %s.\n", + ldb_dn_get_linearized(res->msgs[i]->dn))); + continue; + } + to_sized_string(&key, id); + + ret = sss_mmap_cache_pw_invalidate(nctx->pwd_mc_ctx, &key); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Internal failure in memory cache code: %d [%s]\n", + ret, strerror(ret))); + } + } + } +} + static gid_t get_gid_override(struct ldb_message *msg, struct sss_domain_info *dom) { @@ -1746,6 +1796,56 @@ done: * GROUP db related functions ***************************************************************************/
+void nss_update_gr_memcache(struct nss_ctx *nctx) +{ + struct sss_domain_info *dom; + struct ldb_result *res; + uint64_t exp; + struct sized_string key; + const char *id; + time_t now; + int ret; + int i; + + now = time(NULL); + + for (dom = nctx->rctx->domains; dom != NULL; dom = dom->next) { + ret = sysdb_enumgrent(nctx, dom->sysdb, &res); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Failed to enumerate users for domain [%s]\n", dom->name)); + continue; + } + + for (i = 0; i < res->count; i++) { + exp = ldb_msg_find_attr_as_uint64(res->msgs[i], + SYSDB_CACHE_EXPIRE, 0); + if (exp >= now) { + continue; + } + + /* names require more manipulation (build up fqname conditionally), + * but uidNumber is unique and always resolvable too, so we use + * that to update the cache, as it points to the same entry */ + id = ldb_msg_find_attr_as_string(res->msgs[i], SYSDB_GIDNUM, NULL); + if (!id) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Failed to find gidNumber in %s.\n", + ldb_dn_get_linearized(res->msgs[i]->dn))); + continue; + } + to_sized_string(&key, id); + + ret = sss_mmap_cache_gr_invalidate(nctx->grp_mc_ctx, &key); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Internal failure in memory cache code: %d [%s]\n", + ret, strerror(ret))); + } + } + } +} + #define GID_ROFFSET 0 #define MNUM_ROFFSET sizeof(uint32_t) #define STRS_ROFFSET 2*sizeof(uint32_t) diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h index f1d47c3bc4a62fb816b7b262083e36c05383673d..c58893110ec3617e7950d3bfb7ac1607dde69bb5 100644 --- a/src/responder/nss/nsssrv_private.h +++ b/src/responder/nss/nsssrv_private.h @@ -123,4 +123,7 @@ errno_t check_cache(struct nss_dom_ctx *dctx, sss_dp_callback_t callback, void *pvt);
+void nss_update_pw_memcache(struct nss_ctx *nctx); +void nss_update_gr_memcache(struct nss_ctx *nctx); + #endif /* NSSSRV_PRIVATE_H_ */