From cffe6e09c6b4cd8afa049365bbd432ace5d2a9d9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 26 Oct 2023 14:09:48 +0200
Subject: [PATCH] nssidmap: fix sss_nss_getgrouplist_timeout() with empty
 secondary group list
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

sss_nss_getgrouplist_timeout() is intended as a replacement for
getgrouplist() which only gets secondary groups from SSSD. Currently it
returns an ENOENT error if there are no secondary groups returned by
SSSD. However, as with getgrouplist(), there is the second parameter
which expects a single GID which will be added to the result. This means
that sss_nss_getgrouplist_timeout() will always return at least this GID
as a result and an ENOENT error does not make sense.

With this patch sss_nss_getgrouplist_timeout() will not return an error
anymore if there are no secondary groups but just a result with the
single GID from the second parameter.

Reviewed-by: Alejandro López <allopez@redhat.com>
Reviewed-by: Tomáš Halman <thalman@redhat.com>
---
 src/sss_client/idmap/sss_nss_ex.c      |  5 ++--
 src/tests/cmocka/sss_nss_idmap-tests.c | 32 ++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/src/sss_client/idmap/sss_nss_ex.c b/src/sss_client/idmap/sss_nss_ex.c
index b5230d6b7..24e2a6be9 100644
--- a/src/sss_client/idmap/sss_nss_ex.c
+++ b/src/sss_client/idmap/sss_nss_ex.c
@@ -241,8 +241,9 @@ static int sss_get_ex(struct nss_input *inp, uint32_t flags,
     /* Get number of results from repbuf. */
     SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);
 
-    /* no results if not found */
-    if (num_results == 0) {
+    /* no results if not found, INITGR requests are handled separately */
+    if (num_results == 0 && inp->cmd != SSS_NSS_INITGR
+                         && inp->cmd != SSS_NSS_INITGR_EX) {
         ret = ENOENT;
         goto out;
     }
diff --git a/src/tests/cmocka/sss_nss_idmap-tests.c b/src/tests/cmocka/sss_nss_idmap-tests.c
index 880bab0e5..30b24a57e 100644
--- a/src/tests/cmocka/sss_nss_idmap-tests.c
+++ b/src/tests/cmocka/sss_nss_idmap-tests.c
@@ -30,6 +30,7 @@
 #include "util/util.h"
 #include "util/sss_endian.h"
 
+#define IPA_389DS_PLUGIN_HELPER_CALLS 1
 #include "sss_client/idmap/sss_nss_idmap.h"
 #include "tests/cmocka/common_mock.h"
 
@@ -50,6 +51,8 @@ uint8_t buf3[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x
 uint8_t buf4[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 't', 'e', 's', 't', 'x'};
 
 uint8_t buf_orig1[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 'k', 'e', 'y', 0x00, 'v', 'a', 'l', 'u', 'e', 0x00};
+
+uint8_t buf_initgr[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00};
 #elif (__BYTE_ORDER == __BIG_ENDIAN)
 uint8_t buf1[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 't', 'e', 's', 't', 0x00};
 uint8_t buf2[] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 't', 'e', 's', 't', 0x00};
@@ -57,10 +60,14 @@ uint8_t buf3[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x
 uint8_t buf4[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 't', 'e', 's', 't', 'x'};
 
 uint8_t buf_orig1[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'k', 'e', 'y', 0x00, 'v', 'a', 'l', 'u', 'e', 0x00};
+
+uint8_t buf_initgr[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde};
 #else
  #error "unknow endianess"
 #endif
 
+uint8_t buf_initgr_no_gr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
 enum nss_status __wrap_sss_nss_make_request_timeout(enum sss_cli_command cmd,
                                                     struct sss_cli_req_data *rd,
                                                     int timeout,
@@ -148,12 +155,37 @@ void test_getorigbyname(void **state)
     sss_nss_free_kv(kv_list);
 }
 
+void test_sss_nss_getgrouplist_timeout(void **state)
+{
+    int ret;
+    gid_t groups[10];
+    int ngroups = sizeof(groups);
+    struct sss_nss_make_request_test_data d = {buf_initgr, sizeof(buf_initgr), 0, NSS_STATUS_SUCCESS};
+
+    will_return(__wrap_sss_nss_make_request_timeout, &d);
+    ret = sss_nss_getgrouplist_timeout("test", 111, groups, &ngroups, 0, 0);
+    assert_int_equal(ret, EOK);
+    assert_int_equal(ngroups, 2);
+    assert_int_equal(groups[0], 111);
+    assert_int_equal(groups[1], 222);
+
+    d.repbuf = buf_initgr_no_gr;
+    d.replen = sizeof(buf_initgr_no_gr);
+
+    will_return(__wrap_sss_nss_make_request_timeout, &d);
+    ret = sss_nss_getgrouplist_timeout("test", 111, groups, &ngroups, 0, 0);
+    assert_int_equal(ret, EOK);
+    assert_int_equal(ngroups, 1);
+    assert_int_equal(groups[0], 111);
+}
+
 int main(int argc, const char *argv[])
 {
 
     const struct CMUnitTest tests[] = {
         cmocka_unit_test(test_getsidbyname),
         cmocka_unit_test(test_getorigbyname),
+        cmocka_unit_test(test_sss_nss_getgrouplist_timeout),
     };
 
     return cmocka_run_group_tests(tests, NULL, NULL);
-- 
2.33.0

