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