URL: https://github.com/SSSD/sssd/pull/5784
Author: ikerexxe
 Title: #5784: proxy: allow removing group members
Action: opened

PR body:
"""
The proxy provider doesn't allow to remove group members once they have
been added. This patch allows to do it by looping the member list from
the cache and comparing it with the actual membership list. If a member
is missing then it's removed from the cache.

Resolves: https://github.com/SSSD/sssd/issues/5783
"""

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5784/head:pr5784
git checkout pr5784
From 97c7d0357c5761f47b9dc7b7d103e193517a49e4 Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedr...@redhat.com>
Date: Tue, 14 Sep 2021 12:35:09 +0200
Subject: [PATCH] proxy: allow removing group members

The proxy provider doesn't allow to remove group members once they have
been added. This patch allows to do it by looping the member list from
the cache and comparing it with the actual membership list. If a member
is missing then it's removed from the cache.

Resolves: https://github.com/SSSD/sssd/issues/5783

Signed-off-by: Iker Pedrosa <ipedr...@redhat.com>
---
 src/providers/proxy/proxy_id.c | 151 +++++++++++++++++++++++++++++++++
 1 file changed, 151 insertions(+)

diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c
index 25daea585d..2c463f3f83 100644
--- a/src/providers/proxy/proxy_id.c
+++ b/src/providers/proxy/proxy_id.c
@@ -1488,6 +1488,152 @@ static int get_initgr(TALLOC_CTX *mem_ctx,
     return ret;
 }
 
+static int compare_group_members(struct proxy_id_ctx *ctx,
+                       TALLOC_CTX *tmp_ctx,
+                       struct sss_domain_info *dom,
+                       long int num_gids,
+                       gid_t *gids,
+                       char *db_groupname,
+                       bool *group_found)
+{
+    int j = 0;
+    int ret = EOK;
+    size_t buflen = 0;
+    char *buffer = NULL;
+    char *network_groupname = NULL;
+    enum nss_status status;
+    struct group *grp = NULL;
+    bool delete_group = false;
+
+    grp = talloc(tmp_ctx, struct group);
+    if (!grp) {
+        ret = ENOMEM;
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc() failed\n");
+        goto done;
+    }
+
+    // group 0 is the primary group so it can be skipped
+    for (j = 1; j < num_gids; j++) {
+        do {
+            /* always zero out the grp structure */
+            memset(grp, 0, sizeof(struct group));
+            buffer = grow_group_buffer(tmp_ctx, &buffer, &buflen);
+            if (!buffer) {
+                ret = ENOMEM;
+                goto done;
+            }
+
+            status = ctx->ops.getgrgid_r(gids[j], grp, buffer, buflen, &ret);
+
+            ret = handle_getgr_result(status, grp, dom, &delete_group);
+        } while (ret == EAGAIN);
+
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                    "getgrgid failed [%d]: %s\n", ret, strerror(ret));
+            goto done;
+        }
+
+        network_groupname = sss_create_internal_fqname(tmp_ctx, grp->gr_name, dom->name);
+        if (network_groupname == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "Failed to create fqdn '%s'\n",
+                  grp->gr_name);
+            ret = ENOMEM;
+            goto done;
+        }
+
+        if (strstr(db_groupname, network_groupname) != NULL) {
+            *group_found = true;
+            ret = EOK;
+            goto done;
+        }
+    }
+
+done:
+    return ret;
+}
+
+static int remove_group_members(struct proxy_id_ctx *ctx,
+                                struct sysdb_ctx *sysdb,
+                                struct sss_domain_info *dom,
+                                struct passwd *pwd,
+                                long int num_gids,
+                                gid_t *gids)
+{
+    TALLOC_CTX *tmp_ctx;
+    int ret = EOK;
+    int i = 0;
+    int num_values = 0;
+    char *groupname = NULL;
+    const char *username = NULL;
+    const char *attr = SYSDB_MEMBEROF;
+    const char *attrs[] = {attr, NULL};
+    struct ldb_result *res = NULL;
+    struct ldb_message_element *el = NULL;
+    bool group_found = false;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) {
+        ret = ENOMEM;
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
+        goto done;
+    }
+
+    username = sss_create_internal_fqname(tmp_ctx, pwd->pw_name, dom->name);
+    if (username == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = sysdb_get_user_attr(tmp_ctx, dom, username, attrs, &res);
+    if (res->count > 0) {
+        el = ldb_msg_find_element(res->msgs[0], attr);
+        if (el) {
+            num_values = el->num_values;
+        }
+    }
+
+    for (i = 0; i < num_values; i++) {
+        group_found = false;
+
+        ret = sysdb_get_rdn(sysdb, tmp_ctx, (const char *) el->values[i].data, NULL, &groupname);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE, "Could not get rdn from [%s]\n",
+                  (const char *) el->values[i].data);
+            goto done;
+        }
+
+        if (!groupname) {
+            ret = ENOMEM;
+            DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strndup() failed\n");
+            goto done;
+        }
+
+        ret = compare_group_members(ctx, tmp_ctx, dom, num_gids, gids,
+                                    groupname, &group_found);
+        if (ret != EOK) {
+            goto done;
+        }
+
+        if (!group_found) {
+            ret = sysdb_remove_group_member(dom, groupname,
+                                            username,
+                                            SYSDB_MEMBER_USER, false);
+
+            if (ret != EOK) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                      "Could not remove member [%s] from group [%s]\n",
+                      username, groupname);
+            }
+        }
+    }
+
+done:
+    talloc_zfree(tmp_ctx);
+
+    return ret;
+}
+
 static int get_initgr_groups_process(TALLOC_CTX *memctx,
                                      struct proxy_id_ctx *ctx,
                                      struct sysdb_ctx *sysdb,
@@ -1542,6 +1688,11 @@ static int get_initgr_groups_process(TALLOC_CTX *memctx,
         }
     } while(status == NSS_STATUS_TRYAGAIN);
 
+    ret = remove_group_members(ctx, sysdb, dom, pwd, num_gids, gids);
+    if (ret) {
+        return ret;
+    }
+
     switch (status) {
     case NSS_STATUS_NOTFOUND:
         DEBUG(SSSDBG_FUNC_DATA, "The initgroups call returned 'NOTFOUND'. "
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org
Do not reply to spam on the list, report it: 
https://pagure.io/fedora-infrastructure

Reply via email to