summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/providers/data_provider.h1
-rw-r--r--src/responder/nss/nsssrv.c53
-rw-r--r--src/responder/nss/nsssrv_cmd.c91
-rw-r--r--src/responder/nss/nsssrv_private.h3
4 files changed, 148 insertions, 0 deletions
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index d82b4c94a..415e97717 100644
--- a/src/providers/data_provider.h
+++ b/src/providers/data_provider.h
@@ -59,6 +59,7 @@
* the nss responder to tell it to update the mmap
* cache */
#define DP_REV_METHOD_UPDATE_CACHE "updateCache"
+#define DP_REV_METHOD_INITGR_CHECK "initgrCheck"
/**
* @defgroup pamHandler PAM DBUS request
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index 94aada5ec..71f9a0bce 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -294,8 +294,61 @@ static int nss_update_memcache(DBusMessage *message,
return EOK;
}
+static int nss_memcache_initgr_check(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);
+ DBusError dbus_error;
+ dbus_bool_t dbret;
+ DBusMessage *reply;
+ char *user;
+ char *domain;
+ uint32_t *groups;
+ int gnum;
+
+ dbus_error_init(&dbus_error);
+
+ dbret = dbus_message_get_args(message, &dbus_error,
+ DBUS_TYPE_STRING, &user,
+ DBUS_TYPE_STRING, &domain,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
+ &groups, &gnum,
+ DBUS_TYPE_INVALID);
+
+ if (!dbret) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed, to parse message!\n"));
+ if (dbus_error_is_set(&dbus_error)) {
+ dbus_error_free(&dbus_error);
+ }
+ return EIO;
+ }
+
+ DEBUG(SSSDBG_TRACE_LIBS,
+ ("Got request for [%s@%s]\n", user, domain));
+
+ nss_update_initgr_memcache(nctx, user, domain, gnum, groups);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply) return ENOMEM;
+
+ dbret = dbus_message_append_args(reply, DBUS_TYPE_INVALID);
+ if (!dbret) {
+ dbus_message_unref(reply);
+ return EIO;
+ }
+
+ /* send reply back */
+ sbus_conn_send_reply(conn, reply);
+ dbus_message_unref(reply);
+
+ return EOK;
+}
+
static struct sbus_method nss_dp_methods[] = {
{ DP_REV_METHOD_UPDATE_CACHE, nss_update_memcache },
+ { DP_REV_METHOD_INITGR_CHECK, nss_memcache_initgr_check },
{ NULL, NULL }
};
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index a02edd1e6..6b6f7dff3 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -3341,6 +3341,97 @@ done:
return EOK;
}
+void nss_update_initgr_memcache(struct nss_ctx *nctx,
+ const char *name, const char *domain,
+ int gnum, uint32_t *groups)
+{
+ struct sss_domain_info *dom;
+ struct ldb_result *res;
+ bool changed = false;
+ uint32_t id;
+ uint32_t gids[gnum];
+ int ret;
+ int i, j;
+
+ if (gnum == 0) {
+ /* there are no groups to invalidate in any case, just return */
+ return;
+ }
+
+ for (dom = nctx->rctx->domains; dom != NULL; dom = dom->next) {
+ if (strcasecmp(dom->name, domain) == 0) {
+ break;
+ }
+ }
+
+ if (dom == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Unknown domain (%s) requested by provider\n", domain));
+ return;
+ }
+
+ ret = sysdb_initgroups(NULL, dom->sysdb, name, &res);
+ if (ret != EOK && ret != ENOENT) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Failed to make request to our cache! [%d][%s]\n",
+ ret, strerror(ret)));
+ return;
+ }
+
+ /* copy, we need the original intact in case we need to invalidate
+ * all the original groups */
+ memcpy(gids, groups, gnum * sizeof(uint32_t));
+
+ if (ret == ENOENT || res->count == 0) {
+ changed = true;
+ } else {
+ /* we skip the first entry, it's the user itself */
+ for (i = 1; i < res->count; i++) {
+ id = ldb_msg_find_attr_as_uint(res->msgs[i], SYSDB_GIDNUM, 0);
+ if (id == 0) {
+ /* probably non-posix group, skip */
+ continue;
+ }
+ for (j = 0; j < gnum; j++) {
+ if (gids[j] == id) {
+ gids[j] = 0;
+ break;
+ }
+ }
+ if (j >= gnum) {
+ /* we couldn't find a match, this means the groups have
+ * changed after the refresh */
+ changed = true;
+ break;
+ }
+ }
+
+ if (!changed) {
+ for (j = 0; j < gnum; j++) {
+ if (gids[j] != 0) {
+ /* we found an un-cleared groups, this means the groups
+ * have changed after the refresh (some got deleted) */
+ changed = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ for (i = 0; i < gnum; i++) {
+ id = groups[i];
+
+ ret = sss_mmap_cache_gr_invalidate_gid(nctx->grp_mc_ctx, id);
+ if (ret != EOK && ret != ENOENT) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Internal failure in memory cache code: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ }
+ }
+}
+
/* FIXME: what about mpg, should we return the user's GID ? */
/* FIXME: should we filter out GIDs ? */
static int fill_initgr(struct sss_packet *packet, struct ldb_result *res)
diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h
index c58893110..5e614d201 100644
--- a/src/responder/nss/nsssrv_private.h
+++ b/src/responder/nss/nsssrv_private.h
@@ -125,5 +125,8 @@ errno_t check_cache(struct nss_dom_ctx *dctx,
void nss_update_pw_memcache(struct nss_ctx *nctx);
void nss_update_gr_memcache(struct nss_ctx *nctx);
+void nss_update_initgr_memcache(struct nss_ctx *nctx,
+ const char *name, const char *domain,
+ int gnum, uint32_t *groups);
#endif /* NSSSRV_PRIVATE_H_ */