URL: https://github.com/SSSD/sssd/pull/5272
Author: ikerexxe
 Title: #5272: WIP! responder_utils: GetUserGroups() returns 
SYSDB_PRIMARY_GROUP_GIDNUM
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5272/head:pr5272
git checkout pr5272
From ea3072514bd53c5800903f5a001a4d38481d755b Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedr...@redhat.com>
Date: Thu, 13 Aug 2020 09:13:33 +0200
Subject: [PATCH 1/2] IFP: GetUserGroups() returns origPrimaryGroupGidNumber

There was a mismatch between the information provided by NSS and IFP
interfaces. nss_protocol_fill_initgr() returned
origPrimaryGroupGidNumber as one of the group members of a user, but
GetUserGroups() didn't. This commit makes GetUserGroups() also return
origPrimaryGroupGidNumber value.

Resolves:
https://github.com/SSSD/sssd/issues/4569
---
 src/responder/common/responder_utils.c | 48 ++++++++++++--
 src/responder/ifp/ifpsrv_cmd.c         | 87 +++++++++++++++++++-------
 2 files changed, 106 insertions(+), 29 deletions(-)

diff --git a/src/responder/common/responder_utils.c b/src/responder/common/responder_utils.c
index 9141026e77..c72403c267 100644
--- a/src/responder/common/responder_utils.c
+++ b/src/responder/common/responder_utils.c
@@ -27,6 +27,8 @@
 #include "responder/common/cache_req/cache_req.h"
 #include "util/util.h"
 
+static bool is_primary_group_request;
+
 static inline bool
 attr_in_list(const char **list, size_t nlist, const char *str)
 {
@@ -210,6 +212,7 @@ struct resp_resolve_group_names_state {
 
 static void resp_resolve_group_done(struct tevent_req *subreq);
 static errno_t resp_resolve_group_next(struct tevent_req *req);
+static errno_t resp_resolve_group_trigger_request(struct tevent_req *req, const char *attr_name);
 static errno_t resp_resolve_group_reread_names(struct resp_resolve_group_names_state *state);
 
 struct tevent_req *resp_resolve_group_names_send(TALLOC_CTX *mem_ctx,
@@ -222,6 +225,8 @@ struct tevent_req *resp_resolve_group_names_send(TALLOC_CTX *mem_ctx,
     struct tevent_req *req;
     errno_t ret;
 
+    is_primary_group_request = true;
+
     req = tevent_req_create(mem_ctx, &state, struct resp_resolve_group_names_state);
     if (req == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
@@ -275,10 +280,8 @@ resp_resolve_group_needs_refresh(struct resp_resolve_group_names_state *state)
 
 static errno_t resp_resolve_group_next(struct tevent_req *req)
 {
-    struct cache_req_data *data;
-    uint64_t gid;
-    struct tevent_req *subreq;
     struct resp_resolve_group_names_state *state;
+    errno_t ret;
 
     state = tevent_req_data(req, struct resp_resolve_group_names_state);
 
@@ -292,9 +295,38 @@ static errno_t resp_resolve_group_next(struct tevent_req *req)
         return EOK;
     }
 
-    /* Fire a request */
+    if(state->group_iter == 0 && is_primary_group_request == true) {
+        ret = resp_resolve_group_trigger_request(req,
+                                                 SYSDB_PRIMARY_GROUP_GIDNUM);
+
+        /* If auto_private_groups is disabled then
+         * resp_resolve_group_trigger_request will return EINVAL, but this
+         * doesn't mean a failure. Thus, the search should continue with the
+         * next element.
+         */
+        if(ret == EINVAL) {
+            is_primary_group_request = false;
+            return resp_resolve_group_trigger_request(req, SYSDB_GIDNUM);
+        } else {
+            return ret;
+        }
+    } else {
+        return resp_resolve_group_trigger_request(req, SYSDB_GIDNUM);
+    }
+}
+
+static errno_t resp_resolve_group_trigger_request(struct tevent_req *req,
+                                                  const char *attr_name)
+{
+    struct cache_req_data *data;
+    uint64_t gid;
+    struct tevent_req *subreq;
+    struct resp_resolve_group_names_state *state;
+
+    state = tevent_req_data(req, struct resp_resolve_group_names_state);
+
     gid = ldb_msg_find_attr_as_uint64(state->initgr_res->msgs[state->group_iter],
-                                      SYSDB_GIDNUM, 0);
+                                      attr_name, 0);
     if (gid == 0) {
         return EINVAL;
     }
@@ -338,7 +370,11 @@ static void resp_resolve_group_done(struct tevent_req *subreq)
         /* Try to refresh the others on error */
     }
 
-    state->group_iter++;
+    if(state->group_iter == 0 && is_primary_group_request == true) {
+        is_primary_group_request = false;
+    } else {
+        state->group_iter++;
+    }
     state->needs_refresh = true;
 
     ret = resp_resolve_group_next(req);
diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c
index 977d2ce403..9f20bf2db6 100644
--- a/src/responder/ifp/ifpsrv_cmd.c
+++ b/src/responder/ifp/ifpsrv_cmd.c
@@ -370,6 +370,40 @@ ifp_get_user_attr_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req)
     return EOK;
 }
 
+static errno_t
+ifp_user_get_groups_build_group_list(struct resp_ctx *rctx,
+                                     const char *name,
+                                     const char **groupnames,
+                                     int *gri)
+{
+    struct sized_string *group_name;
+    errno_t ret;
+
+    ret = sized_domain_name(NULL, rctx, name, &group_name);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE,
+              "Unable to get sized name for %s [%d]: %s\n",
+              name, ret, sss_strerror(ret));
+        goto done;
+    }
+
+    groupnames[*gri] = talloc_strndup(groupnames,
+                                      group_name->str,
+                                      group_name->len);
+    talloc_free(group_name);
+    if (groupnames[*gri] == NULL) {
+        DEBUG(SSSDBG_MINOR_FAILURE, "talloc_strndup failed\n");
+        ret = ENOMEM;
+        goto done;
+    }
+    (*gri)++;
+
+    DEBUG(SSSDBG_TRACE_FUNC, "Adding group %s\n", groupnames[*gri]);
+
+done:
+    return ret;
+}
+
 static errno_t
 ifp_user_get_groups_build_reply(TALLOC_CTX *mem_ctx,
                                 struct resp_ctx *rctx,
@@ -377,51 +411,58 @@ ifp_user_get_groups_build_reply(TALLOC_CTX *mem_ctx,
                                 struct ldb_result *res,
                                 const char ***_groupnames)
 {
+    TALLOC_CTX *tmp_ctx = NULL;
     int i, gri, num;
     const char *name;
     const char **groupnames;
-    struct sized_string *group_name;
+    gid_t orig_gid;
+    struct ldb_message *msg = NULL;
+    const char *attrs[] = {SYSDB_NAME, NULL};
     errno_t ret;
 
-    /* one less, the first one is the user entry */
-    num = res->count - 1;
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    num = res->count;
     groupnames = talloc_zero_array(mem_ctx, const char *, num + 1);
     if (groupnames == NULL) {
         return ENOMEM;
     }
 
     gri = 0;
-    for (i = 0; i < num; i++) {
+    orig_gid = sss_view_ldb_msg_find_attr_as_uint64(domain,
+                                                res->msgs[0],
+                                                SYSDB_PRIMARY_GROUP_GIDNUM, 0);
+    ret = sysdb_search_group_by_gid(tmp_ctx, domain, orig_gid, attrs, &msg);
+
+    /* If origPrimaryGroupGidNumber exists add it to group list */
+    if(ret == EOK) {
+        name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+
+        if (name != NULL) {
+            ifp_user_get_groups_build_group_list(rctx, name, groupnames, &gri);
+        }
+    }
+
+    /* Start counting from 1 to exclude the user entry */
+    for (i = 1; i < num; i++) {
         name = sss_view_ldb_msg_find_attr_as_string(domain,
-                                                    res->msgs[i + 1],
+                                                    res->msgs[i],
                                                     SYSDB_NAME, NULL);
         if (name == NULL) {
             DEBUG(SSSDBG_MINOR_FAILURE, "Skipping a group with no name\n");
             continue;
         }
 
-        ret = sized_domain_name(NULL, rctx, name, &group_name);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_MINOR_FAILURE,
-                  "Unable to get sized name for %s [%d]: %s\n",
-                  name, ret, sss_strerror(ret));
-            continue;
-        }
-
-        groupnames[gri] = talloc_strndup(groupnames,
-                                         group_name->str, group_name->len);
-        talloc_free(group_name);
-        if (groupnames[gri] == NULL) {
-            DEBUG(SSSDBG_MINOR_FAILURE, "talloc_strndup failed\n");
-            continue;
-        }
-        gri++;
-
-        DEBUG(SSSDBG_TRACE_FUNC, "Adding group %s\n", groupnames[i]);
+        ifp_user_get_groups_build_group_list(rctx, name, groupnames, &gri);
     }
 
     *_groupnames = groupnames;
 
+    talloc_free(tmp_ctx);
     return EOK;
 }
 

From 33ab29202bc995f7689e461f3aa1104cb938ca63 Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedr...@redhat.com>
Date: Mon, 24 Aug 2020 13:12:13 +0200
Subject: [PATCH 2/2] IFP-TESTS: GetUserGroups() returns
 origPrimaryGroupGidNumber

New infopipe test case to check:
Given auto_private_groups is enabled
When GetUserGroups is called
Then the origPrimaryGroupGidNumber is returned as part of the group
memberships

Resolves:
https://github.com/SSSD/sssd/issues/4569
---
 src/tests/intg/test_infopipe.py | 38 +++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/src/tests/intg/test_infopipe.py b/src/tests/intg/test_infopipe.py
index d75b377637..142319bfa5 100644
--- a/src/tests/intg/test_infopipe.py
+++ b/src/tests/intg/test_infopipe.py
@@ -203,6 +203,7 @@ def format_basic_conf(ldap_conn, schema):
         memcache_timeout    = 0
 
         [ifp]
+        debug_level         = 0xffff
         # it need to be executed with valgrind because there is a problem
         # problem with "ifp" + client registration in monitor
         # There is not such problem in 1st test. Just in following tests.
@@ -335,6 +336,28 @@ def simple_rfc2307(request, ldap_conn):
     return None
 
 
+@pytest.fixture
+def auto_private_groups_rfc2307(request, ldap_conn):
+    ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
+    ent_list.add_user("user1", 1001, 2001)
+
+    ent_list.add_group("group1", 2001)
+    ent_list.add_group("single_user_group", 2011, ["user1"])
+    ent_list.add_group("two_user_group", 2012, ["user1"])
+
+    create_ldap_fixture(request, ldap_conn, ent_list)
+
+    conf = \
+        format_basic_conf(ldap_conn, SCHEMA_RFC2307) + \
+        unindent("""
+            [domain/LDAP]
+            auto_private_groups = True
+        """).format(**locals())
+    create_conf_fixture(request, conf)
+    create_sssd_fixture(request)
+    return None
+
+
 def test_ping_raw(dbus_system_bus, ldap_conn, simple_rfc2307):
     # test with disabled introspection
     sssd_obj = dbus_system_bus.get_object('org.freedesktop.sssd.infopipe',
@@ -536,6 +559,21 @@ def test_get_user_groups(dbus_system_bus, ldap_conn, sanity_rfc2307):
     assert sorted(res) == ['single_user_group', 'two_user_group']
 
 
+'''
+Given auto_private_groups is enabled
+When GetUserGroups is called
+Then the origPrimaryGroupGidNumber is returned as part of the group memberships
+'''
+def test_get_user_groups_given_auto_private_groups_enabled(dbus_system_bus, ldap_conn, auto_private_groups_rfc2307):
+    sssd_obj = dbus_system_bus.get_object('org.freedesktop.sssd.infopipe',
+                                          '/org/freedesktop/sssd/infopipe')
+    sssd_interface = dbus.Interface(sssd_obj, 'org.freedesktop.sssd.infopipe')
+
+    res = sssd_interface.GetUserGroups('user1')
+
+    assert sorted(res) == ['group1', 'single_user_group', 'two_user_group']
+
+
 def get_user_property(dbus_system_bus, username, prop_name):
     users_obj = dbus_system_bus.get_object(
                                         'org.freedesktop.sssd.infopipe',
_______________________________________________
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

Reply via email to