From 96f52f106feed27fd98163780b5b55daee266e2e Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Wed, 29 Sep 2010 22:15:20 +0200
Subject: [PATCH 1/2] sysdb interface for adding fake groups

---
 src/db/sysdb.h                 |    7 ++++++
 src/db/sysdb_ops.c             |   47 ++++++++++++++++++++++++++++++++++++++++
 src/responder/nss/nsssrv_cmd.c |   12 ++++++----
 src/tests/sysdb-tests.c        |   41 ++++++++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+), 5 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index d8a78ba..8e104ad 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -416,6 +416,13 @@ int sysdb_add_group(TALLOC_CTX *mem_ctx,
                     struct sysdb_attrs *attrs,
                     int cache_timeout);
 
+int sysdb_add_fake_group(TALLOC_CTX *mem_ctx,
+                         struct sysdb_ctx *ctx,
+                         struct sss_domain_info *domain,
+                         const char *name,
+                         gid_t gid,
+                         struct sysdb_attrs *attrs);
+
 /* mod_op must be either LDB_FLAG_MOD_ADD or LDB_FLAG_MOD_DELETE */
 int sysdb_mod_group_member(TALLOC_CTX *mem_ctx,
                            struct sysdb_ctx *ctx,
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 14af948..10b04c4 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -1003,6 +1003,53 @@ done:
     return ret;
 }
 
+int sysdb_add_fake_group(TALLOC_CTX *mem_ctx,
+                         struct sysdb_ctx *ctx,
+                         struct sss_domain_info *domain,
+                         const char *name,
+                         gid_t gid,
+                         struct sysdb_attrs *attrs)
+{
+    TALLOC_CTX *tmpctx;
+    time_t now;
+    int ret;
+
+    tmpctx = talloc_new(mem_ctx);
+    if (!tmpctx) {
+        return ENOMEM;
+    }
+
+    /* try to add the group */
+    ret = sysdb_add_basic_group(tmpctx, ctx, domain, name, gid);
+    if (ret) goto done;
+
+    if (!attrs) {
+        attrs = sysdb_new_attrs(tmpctx);
+        if (!attrs) {
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
+    now = time(NULL);
+
+    ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
+    if (ret) goto done;
+
+    ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
+                                 now-1);
+    if (ret) goto done;
+
+    ret = sysdb_set_group_attr(tmpctx, ctx,
+                               domain, name, attrs, SYSDB_MOD_REP);
+
+done:
+    if (ret != EOK) {
+        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+    }
+    talloc_zfree(tmpctx);
+    return ret;
+}
 
 /* =Add-Or-Remove-Group-Memeber=========================================== */
 
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index c3f35e1..fbf4d0b 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -1597,7 +1597,7 @@ static int fill_grent(struct sss_packet *packet,
         name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
         gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
         if (!name || !gid) {
-            DEBUG(1, ("Incomplete group object for %s[%llu]! Skipping\n",
+            DEBUG(2, ("Incomplete or fake group object for %s[%llu]! Skipping\n",
                       name?name:"<NULL>", (unsigned long long int)gid));
             continue;
         }
@@ -2784,7 +2784,7 @@ static int fill_initgr(struct sss_packet *packet, struct ldb_result *res)
     uint8_t *body;
     size_t blen;
     gid_t gid;
-    int ret, i, num;
+    int ret, i, num, total;
 
     if (res->count == 0) {
         return ENOENT;
@@ -2800,16 +2800,18 @@ static int fill_initgr(struct sss_packet *packet, struct ldb_result *res)
     sss_packet_get_body(packet, &body, &blen);
 
     /* skip first entry, it's the user entry */
+    total = 0;
     for (i = 0; i < num; i++) {
         gid = ldb_msg_find_attr_as_uint64(res->msgs[i + 1], SYSDB_GIDNUM, 0);
         if (!gid) {
-            DEBUG(1, ("Incomplete group object for initgroups! Aborting\n"));
-            return EFAULT;
+            DEBUG(2, ("Incomplete or fake group object for initgroups! Aborting\n"));
+            continue;
         }
         ((uint32_t *)body)[2 + i] = gid;
+        total++;
     }
 
-    ((uint32_t *)body)[0] = num; /* num results */
+    ((uint32_t *)body)[0] = total; /* num results */
     ((uint32_t *)body)[1] = 0; /* reserved */
 
     return EOK;
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 98d9a20..5eab19a 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -262,6 +262,16 @@ static int test_add_group(struct test_data *data)
     return ret;
 }
 
+static int test_add_fake_group(struct test_data *data)
+{
+    int ret;
+
+    ret = sysdb_add_fake_group(data, data->ctx->sysdb,
+                               data->ctx->domain, data->groupname,
+                               data->gid, NULL);
+    return ret;
+}
+
 static int test_store_group(struct test_data *data)
 {
     int ret;
@@ -660,6 +670,33 @@ START_TEST (test_sysdb_add_group)
 }
 END_TEST
 
+START_TEST (test_sysdb_add_fake_group)
+{
+    struct sysdb_test_ctx *test_ctx;
+    struct test_data *data;
+    int ret;
+
+    /* Setup */
+    ret = setup_sysdb_tests(&test_ctx);
+    if (ret != EOK) {
+        fail("Could not set up the test");
+        return;
+    }
+
+    data = talloc_zero(test_ctx, struct test_data);
+    data->ctx = test_ctx;
+    data->ev = test_ctx->ev;
+    data->uid = _i;
+    data->gid = _i;
+    data->groupname = talloc_asprintf(data, "testgroup%d", _i);
+
+    ret = test_add_fake_group(data);
+
+    fail_if(ret != EOK, "Could not add fake group %s", data->groupname);
+    talloc_free(test_ctx);
+}
+END_TEST
+
 START_TEST (test_sysdb_getpwnam)
 {
     struct sysdb_test_ctx *test_ctx;
@@ -2292,6 +2329,10 @@ Suite *create_sysdb_suite(void)
     /* test the ignore_not_found parameter for groups */
     tcase_add_test(tc_sysdb, test_sysdb_remove_nonexistent_group);
 
+    /* Create fake groups - remove will fail if the LDB objects don't exist */
+    tcase_add_loop_test(tc_sysdb, test_sysdb_add_fake_group, 28000, 28010);
+    tcase_add_loop_test(tc_sysdb, test_sysdb_remove_local_group_by_gid, 28000, 28010);
+
     /* test custom operations */
     tcase_add_loop_test(tc_sysdb, test_sysdb_store_custom, 29010, 29020);
     tcase_add_test(tc_sysdb, test_sysdb_search_custom_by_name);
-- 
1.7.2.3

