From 58b06b8fee18c4242e301ecf71f92a77f6ba6e7b Mon Sep 17 00:00:00 2001
From: Pavel Reichl <preichl@redhat.com>
Date: Fri, 22 Jan 2016 08:34:14 -0500
Subject: [PATCH] IDMAP: Add test to validate off by one bug

Resolves:
https://fedorahosted.org/sssd/ticket/2922
---
 src/tests/cmocka/test_sss_idmap.c | 125 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 125 insertions(+)

diff --git a/src/tests/cmocka/test_sss_idmap.c b/src/tests/cmocka/test_sss_idmap.c
index 00e03ffd9ab1532fb55795b9935b254c8a89ec16..2c99a09e6d11e8d731860eaad94eda0900fafabe 100644
--- a/src/tests/cmocka/test_sss_idmap.c
+++ b/src/tests/cmocka/test_sss_idmap.c
@@ -43,6 +43,17 @@
 #define TEST_OFFSET 1000000
 #define TEST_OFFSET_STR "1000000"
 
+#define TEST_2922_MIN_ID 1842600000
+#define TEST_2922_MAX_ID 1842799999
+#define TEST_2922_MAX_ID_PLUS_ONE (TEST_2922_MAX_ID + 1)
+
+#define TEST_2922_DFL_SLIDE 9212
+#define TEST_2922_FIRST_SID TEST_DOM_SID"-0"
+/* Last SID = first SID + (default) rangesize -1 */
+#define TEST_2922_LAST_SID TEST_DOM_SID"-199999"
+/* Last SID = first SID + rangesize */
+#define TEST_2922_LAST_SID_PLUS_ONE  TEST_DOM_SID"-200000"
+
 struct test_ctx {
     TALLOC_CTX *mem_idmap;
     struct sss_idmap_ctx *idmap_ctx;
@@ -128,6 +139,53 @@ static int setup_ranges(struct test_ctx *test_ctx, bool external_mapping,
     return 0;
 }
 
+static int setup_ranges_2922(struct test_ctx *test_ctx)
+{
+    struct sss_idmap_range range;
+    enum idmap_error_code err;
+    const char *name;
+    const char *sid;
+    /* Pick a new slice. */
+    id_t slice_num = -1;
+
+    if (test_ctx == NULL) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              "test context is NULL\n");
+        return 1;
+    }
+
+    name = TEST_DOM_NAME;
+    sid = TEST_DOM_SID;
+
+    err = sss_idmap_calculate_range(test_ctx->idmap_ctx, sid, &slice_num,
+                                    &range);
+    if (err != IDMAP_SUCCESS) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              "sss_idmap_calculate_range failed: exp: [%d] but got [%d]\n",
+              IDMAP_SUCCESS, err);
+        return 1;
+    }
+
+    /* Range computation should be deterministic. Lets validate that.  */
+    if (range.min != TEST_2922_MIN_ID
+            || range.max != TEST_2922_MAX_ID
+            || slice_num != TEST_2922_DFL_SLIDE) {
+        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to compute range correctly.\n");
+        return 1;
+    }
+
+    err = sss_idmap_add_domain_ex(test_ctx->idmap_ctx, name, sid, &range,
+                                  NULL, 0, false /* No external mapping */);
+    if (err != IDMAP_SUCCESS) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              "sss_idmap_add_domain_ex failed: exp: [%d] but got [%d]\n",
+              IDMAP_SUCCESS, err);
+        return 1;
+    }
+
+    return 0;
+}
+
 static int test_sss_idmap_setup_with_domains(void **state) {
     struct test_ctx *test_ctx;
 
@@ -140,6 +198,23 @@ static int test_sss_idmap_setup_with_domains(void **state) {
     return 0;
 }
 
+static int test_sss_idmap_setup_with_domains_2922(void **state) {
+    struct test_ctx *test_ctx;
+    int ret;
+
+    test_sss_idmap_setup(state);
+
+    test_ctx = talloc_get_type(*state, struct test_ctx);
+    if (test_ctx == NULL) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              "test context is NULL\n");
+        return 1;
+    }
+
+    ret = setup_ranges_2922(test_ctx);
+    return ret;
+}
+
 static int test_sss_idmap_setup_with_domains_sec_slices(void **state) {
     struct test_ctx *test_ctx;
 
@@ -298,6 +373,53 @@ void test_map_id(void **state)
     sss_idmap_free_sid(test_ctx->idmap_ctx, sid);
 }
 
+/* https://fedorahosted.org/sssd/ticket/2922 */
+/* ID mapping - bug in computing max id for slice range */
+void test_map_id_2922(void **state)
+{
+    struct test_ctx *test_ctx;
+    enum idmap_error_code err;
+    uint32_t id;
+    char *sid = NULL;
+
+    test_ctx = talloc_get_type(*state, struct test_ctx);
+
+    assert_non_null(test_ctx);
+
+    /* Min UNIX ID to SID */
+    err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, TEST_2922_MIN_ID, &sid);
+    assert_int_equal(err, IDMAP_SUCCESS);
+    assert_string_equal(sid, TEST_2922_FIRST_SID);
+    sss_idmap_free_sid(test_ctx->idmap_ctx, sid);
+
+    /* First SID to UNIX ID */
+    err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx, TEST_2922_FIRST_SID, &id);
+    assert_int_equal(err, IDMAP_SUCCESS);
+    assert_int_equal(id, TEST_2922_MIN_ID);
+
+    /* Max UNIX ID to SID */
+    err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, TEST_2922_MAX_ID, &sid);
+    assert_int_equal(err, IDMAP_SUCCESS);
+    assert_string_equal(sid, TEST_2922_LAST_SID);
+    sss_idmap_free_sid(test_ctx->idmap_ctx, sid);
+
+    /* Last SID to UNIX ID */
+    err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx, TEST_2922_LAST_SID, &id);
+    assert_int_equal(err, IDMAP_SUCCESS);
+    assert_int_equal(id, TEST_2922_MAX_ID);
+
+    /* Max UNIX ID + 1 to SID */
+    err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, TEST_2922_MAX_ID_PLUS_ONE,
+                                &sid);
+    assert_int_equal(err, IDMAP_NO_DOMAIN);
+
+    /* Last SID + 1 to UNIX ID */
+    err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx,
+                                TEST_2922_LAST_SID_PLUS_ONE, &id);
+    /* Auto adding new ranges is disable in this test.  */
+    assert_int_equal(err, IDMAP_NO_RANGE);
+}
+
 void test_map_id_sec_slices(void **state)
 {
     struct test_ctx *test_ctx;
@@ -589,6 +711,9 @@ int main(int argc, const char *argv[])
         cmocka_unit_test_setup_teardown(test_map_id,
                                         test_sss_idmap_setup_with_domains,
                                         test_sss_idmap_teardown),
+        cmocka_unit_test_setup_teardown(test_map_id_2922,
+                                        test_sss_idmap_setup_with_domains_2922,
+                                        test_sss_idmap_teardown),
         cmocka_unit_test_setup_teardown(test_map_id_sec_slices,
                                         test_sss_idmap_setup_with_domains_sec_slices,
                                         test_sss_idmap_teardown),
-- 
2.4.3

