From ebba1aa6b9783daa0d530e9f5e307f7be17d3cd3 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 5 Dec 2012 17:40:43 +0000 Subject: Hook to perform a mmap cache update from sssd_nss 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(+) (limited to 'src') diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index bb944509d..9c7340021 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 e01bd1a4d..8694edaf6 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 db1efdd21..2397fb38d 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 f1d47c3bc..c58893110 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_ */ -- cgit