This set of functions enumerate the user's groups and invalidate them all
if the list does not matches what we get from the caller.
---
 src/providers/data_provider.h      |    1 +
 src/responder/nss/nsssrv.c         |   53 +++++++++++++++++++++
 src/responder/nss/nsssrv_cmd.c     |   91 ++++++++++++++++++++++++++++++++++++
 src/responder/nss/nsssrv_private.h |    3 +
 4 files changed, 148 insertions(+), 0 deletions(-)

diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index 
9c7340021268925860b48b3e62f0d0b4d4731ebb..f131e2c68c9ab322ccc65025ed4068b5a5ca92be
 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 
8694edaf614f6a218621518416965ffb2e558873..f5cfc85b4861489cd44a1367dc9b26111ff9841c
 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 
2397fb38d37e0fc4c00b2f2967e3d12afbffde2e..14bb3afe1f0a0411db6f693d3c456ce2cf76c372
 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -3346,6 +3346,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 
c58893110ec3617e7950d3bfb7ac1607dde69bb5..5e614d201b8e45e9eb4bb8e8ba3c4d868a845dfa
 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_ */
-- 
1.7.1

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to