Blob Blame History Raw
From 4206e5dbe37277a4002010e85438fe376b5b1812 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 3 Feb 2014 13:30:35 +0100
Subject: [PATCH 93/97] IDMAP: add sss_idmap_check_collision(_ex)

---
 src/lib/idmap/sss_idmap.c         | 129 ++++++++++++++++++++++++++------------
 src/lib/idmap/sss_idmap.h         |  65 +++++++++++++++++++
 src/tests/cmocka/test_sss_idmap.c |  93 +++++++++++++++++++++++++++
 3 files changed, 247 insertions(+), 40 deletions(-)

diff --git a/src/lib/idmap/sss_idmap.c b/src/lib/idmap/sss_idmap.c
index 3f1e7a58f390a3c10999251e2155ef513ba69bd7..4c453120539a549807e9b6bb4db2dc396c1b3152 100644
--- a/src/lib/idmap/sss_idmap.c
+++ b/src/lib/idmap/sss_idmap.c
@@ -380,55 +380,104 @@ enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx,
     return IDMAP_SUCCESS;
 }
 
+enum idmap_error_code sss_idmap_check_collision_ex(const char *o_name,
+                                                const char *o_sid,
+                                                struct sss_idmap_range *o_range,
+                                                uint32_t o_first_rid,
+                                                const char *o_range_id,
+                                                bool o_external_mapping,
+                                                const char *n_name,
+                                                const char *n_sid,
+                                                struct sss_idmap_range *n_range,
+                                                uint32_t n_first_rid,
+                                                const char *n_range_id,
+                                                bool n_external_mapping)
+{
+    bool names_equal;
+    bool sids_equal;
+
+    /* TODO: if both ranges have the same ID check if an update is
+     * needed. */
+
+    /* Check if ID ranges overlap.
+     * ID ranges with external mapping may overlap. */
+    if ((!n_external_mapping && !o_external_mapping)
+        && ((n_range->min >= o_range->min
+                && n_range->min <= o_range->max)
+            || (n_range->max >= o_range->min
+                && n_range->max <= o_range->max))) {
+        return IDMAP_COLLISION;
+    }
+
+    names_equal = (strcasecmp(n_name, o_name) == 0);
+    sids_equal = ((n_sid == NULL && o_sid == NULL)
+                    || (n_sid != NULL && o_sid != NULL
+                        && strcasecmp(n_sid, o_sid) == 0));
+
+    /* check if domain name and SID are consistent */
+    if ((names_equal && !sids_equal) || (!names_equal && sids_equal)) {
+        return IDMAP_COLLISION;
+    }
+
+    /* check if external_mapping is consistent */
+    if (names_equal && sids_equal
+            && n_external_mapping != o_external_mapping) {
+        return IDMAP_COLLISION;
+    }
+
+    /* check if RID ranges overlap */
+    if (names_equal && sids_equal
+            && n_external_mapping == false
+            && n_first_rid >= o_first_rid
+            && n_first_rid <= o_first_rid + (o_range->max - o_range->min)) {
+        return IDMAP_COLLISION;
+    }
+
+    return IDMAP_SUCCESS;
+}
+
+enum idmap_error_code sss_idmap_check_collision(struct sss_idmap_ctx *ctx,
+                                                char *n_name, char *n_sid,
+                                                struct sss_idmap_range *n_range,
+                                                uint32_t n_first_rid,
+                                                char *n_range_id,
+                                                bool n_external_mapping)
+{
+    struct idmap_domain_info *dom;
+    enum idmap_error_code err;
+
+    for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) {
+        err = sss_idmap_check_collision_ex(dom->name, dom->sid, dom->range,
+                                           dom->first_rid, dom->range_id,
+                                           dom->external_mapping,
+                                           n_name, n_sid, n_range, n_first_rid,
+                                           n_range_id, n_external_mapping);
+        if (err != IDMAP_SUCCESS) {
+            return err;
+        }
+    }
+    return IDMAP_SUCCESS;
+}
+
 static enum idmap_error_code dom_check_collision(
                                              struct idmap_domain_info *dom_list,
                                              struct idmap_domain_info *new_dom)
 {
     struct idmap_domain_info *dom;
-    bool names_equal;
-    bool sids_equal;
+    enum idmap_error_code err;
 
     for (dom = dom_list; dom != NULL; dom = dom->next) {
-
-        /* TODO: if both ranges have the same ID check if an update is
-         * needed. */
-
-        /* Check if ID ranges overlap.
-         * ID ranges with external mapping may overlap. */
-        if ((!new_dom->external_mapping && !dom->external_mapping)
-            && ((new_dom->range->min >= dom->range->min
-                    && new_dom->range->min <= dom->range->max)
-                || (new_dom->range->max >= dom->range->min
-                    && new_dom->range->max <= dom->range->max))) {
-            return IDMAP_COLLISION;
-        }
-
-        names_equal = (strcasecmp(new_dom->name, dom->name) == 0);
-        sids_equal = ((new_dom->sid == NULL && dom->sid == NULL)
-                        || (new_dom->sid != NULL && dom->sid != NULL
-                            && strcasecmp(new_dom->sid, dom->sid) == 0));
-
-        /* check if domain name and SID are consistent */
-        if ((names_equal && !sids_equal) || (!names_equal && sids_equal)) {
-            return IDMAP_COLLISION;
-        }
-
-        /* check if external_mapping is consistent */
-        if (names_equal && sids_equal
-                && new_dom->external_mapping != dom->external_mapping) {
-            return IDMAP_COLLISION;
-        }
-
-        /* check if RID ranges overlap */
-        if (names_equal && sids_equal
-                && new_dom->external_mapping == false
-                && new_dom->first_rid >= dom->first_rid
-                && new_dom->first_rid <=
-                    dom->first_rid + (dom->range->max - dom->range->min)) {
-            return IDMAP_COLLISION;
+        err = sss_idmap_check_collision_ex(dom->name, dom->sid, dom->range,
+                                           dom->first_rid, dom->range_id,
+                                           dom->external_mapping,
+                                           new_dom->name, new_dom->sid,
+                                           new_dom->range, new_dom->first_rid,
+                                           new_dom->range_id,
+                                           new_dom->external_mapping);
+        if (err != IDMAP_SUCCESS) {
+            return err;
         }
     }
-
     return IDMAP_SUCCESS;
 }
 
diff --git a/src/lib/idmap/sss_idmap.h b/src/lib/idmap/sss_idmap.h
index 1e1c9a5cfe490301d0e633db808589f1bc0ef857..ccc63f7f760b877cdb17696325731f8e540b2736 100644
--- a/src/lib/idmap/sss_idmap.h
+++ b/src/lib/idmap/sss_idmap.h
@@ -289,6 +289,71 @@ enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx,
                                               const char *range_id,
                                               uint32_t rid,
                                               bool external_mapping);
+
+/**
+ * @brief Check if a new range would collide with any existing one
+ *
+ * @param[in] ctx         Idmap context
+ * @param[in] n_name      Zero-terminated string with the domain name the new
+ *                        range should belong to
+ * @param[in] n_sid       Zero-terminated string representation of the domain
+ *                        SID (S-1-15-.....) the new range sould belong to
+ * @param[in] n_range     The new id range
+ * @param[in] n_range_id  unique identifier of the new range, it is needed
+ *                        to allow updates at runtime, may be NULL
+ * @param[in] n_first_rid The RID that should be mapped to the first ID of the
+ *                        new range.
+ * @param[in] n_external_mapping Mapping type of the new range
+ *
+ * @return
+ *  - #IDMAP_COLLISION:     New range collides with existing one
+ */
+enum idmap_error_code sss_idmap_check_collision(struct sss_idmap_ctx *ctx,
+                                                char *n_name, char *n_sid,
+                                                struct sss_idmap_range *n_range,
+                                                uint32_t n_first_rid,
+                                                char *n_range_id,
+                                                bool n_external_mapping);
+
+/**
+ * @brief Check if two ranges would collide
+ *
+ * @param[in] o_name      Zero-terminated string with the domain name the
+ *                        first range should belong to
+ * @param[in] o_sid       Zero-terminated string representation of the domain
+ *                        SID (S-1-15-.....) the first range sould belong to
+ * @param[in] o_range     The first id range
+ * @param[in] o_range_id  unique identifier of the first range, it is needed
+ *                        to allow updates at runtime, may be NULL
+ * @param[in] o_first_rid The RID that should be mapped to the first ID of the
+ *                        first range.
+ * @param[in] o_external_mapping Mapping type of the first range
+ * @param[in] n_name      Zero-terminated string with the domain name the
+ *                        second range should belong to
+ * @param[in] n_sid       Zero-terminated string representation of the domain
+ *                        SID (S-1-15-.....) the second range sould belong to
+ * @param[in] n_range     The second id range
+ * @param[in] n_range_id  unique identifier of the second range, it is needed
+ *                        to allow updates at runtime, may be NULL
+ * @param[in] n_first_rid The RID that should be mapped to the first ID of the
+ *                        second range.
+ * @param[in] n_external_mapping Mapping type of the second range
+ *
+ * @return
+ *  - #IDMAP_COLLISION:     New range collides with existing one
+ */
+enum idmap_error_code sss_idmap_check_collision_ex(const char *o_name,
+                                                const char *o_sid,
+                                                struct sss_idmap_range *o_range,
+                                                uint32_t o_first_rid,
+                                                const char *o_range_id,
+                                                bool o_external_mapping,
+                                                const char *n_name,
+                                                const char *n_sid,
+                                                struct sss_idmap_range *n_range,
+                                                uint32_t n_first_rid,
+                                                const char *n_range_id,
+                                                bool n_external_mapping);
 /**
  * @brief Translate SID to a unix UID or GID
  *
diff --git a/src/tests/cmocka/test_sss_idmap.c b/src/tests/cmocka/test_sss_idmap.c
index 019b4618ef0e14e87cb86d64989e8f5ca9dfdfd8..ff933216416b61618bf764d8c2554b273706c787 100644
--- a/src/tests/cmocka/test_sss_idmap.c
+++ b/src/tests/cmocka/test_sss_idmap.c
@@ -30,11 +30,15 @@
 #define TEST_RANGE_MAX 399999
 #define TEST_DOM_NAME "test.dom"
 #define TEST_DOM_SID "S-1-5-21-123-456-789"
+#define TEST_FIRST_RID 0
+#define TEST_EXT_MAPPING true
 
 #define TEST_2_RANGE_MIN 600000
 #define TEST_2_RANGE_MAX 799999
 #define TEST_2_DOM_NAME "test2.dom"
 #define TEST_2_DOM_SID "S-1-5-21-987-654-321"
+#define TEST_2_FIRST_RID 1000000
+#define TEST_2_EXT_MAPPING true
 
 #define TEST_OFFSET 1000000
 #define TEST_OFFSET_STR "1000000"
@@ -408,6 +412,94 @@ void test_has_algorithmic_by_name(void **state)
     assert_false(use_id_mapping);
 }
 
+void test_sss_idmap_check_collision_ex(void **state)
+{
+    enum idmap_error_code err;
+    struct sss_idmap_range r1 = {TEST_RANGE_MIN, TEST_RANGE_MAX};
+    struct sss_idmap_range r2 = {TEST_2_RANGE_MIN, TEST_2_RANGE_MAX};
+
+    err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1,
+                                       TEST_FIRST_RID, NULL,
+                                       TEST_EXT_MAPPING,
+                                       TEST_2_DOM_NAME, TEST_2_DOM_SID, &r2,
+                                       TEST_2_FIRST_RID, NULL,
+                                       TEST_2_EXT_MAPPING);
+    assert_int_equal(err, IDMAP_SUCCESS);
+
+    /* Same name, different SID */
+    err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1,
+                                       TEST_FIRST_RID, NULL,
+                                       TEST_EXT_MAPPING,
+                                       TEST_DOM_NAME, TEST_2_DOM_SID, &r2,
+                                       TEST_2_FIRST_RID, NULL,
+                                       TEST_2_EXT_MAPPING);
+    assert_int_equal(err, IDMAP_COLLISION);
+
+    /* Same SID, different name */
+    err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1,
+                                       TEST_FIRST_RID, NULL,
+                                       TEST_EXT_MAPPING,
+                                       TEST_2_DOM_NAME, TEST_DOM_SID, &r2,
+                                       TEST_2_FIRST_RID, NULL,
+                                       TEST_2_EXT_MAPPING);
+    assert_int_equal(err, IDMAP_COLLISION);
+
+    /* Same SID and name, no overlaps */
+    err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1,
+                                       TEST_FIRST_RID, NULL,
+                                       TEST_EXT_MAPPING,
+                                       TEST_DOM_NAME, TEST_DOM_SID, &r2,
+                                       TEST_2_FIRST_RID, NULL,
+                                       TEST_2_EXT_MAPPING);
+    assert_int_equal(err, IDMAP_SUCCESS);
+
+    /* Same SID and name, different mappings */
+    err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1,
+                                       TEST_FIRST_RID, NULL,
+                                       TEST_EXT_MAPPING,
+                                       TEST_DOM_NAME, TEST_DOM_SID, &r2,
+                                       TEST_2_FIRST_RID, NULL,
+                                       !TEST_EXT_MAPPING);
+    assert_int_equal(err, IDMAP_COLLISION);
+
+    /* Same SID and name, Overlapping RID range */
+    err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1,
+                                       TEST_FIRST_RID, NULL,
+                                       false,
+                                       TEST_DOM_NAME, TEST_DOM_SID, &r2,
+                                       TEST_FIRST_RID, NULL,
+                                       false);
+    assert_int_equal(err, IDMAP_COLLISION);
+
+    /* Different SID and name, Overlapping RID range */
+    err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1,
+                                       TEST_FIRST_RID, NULL,
+                                       false,
+                                       TEST_2_DOM_NAME, TEST_2_DOM_SID, &r2,
+                                       TEST_FIRST_RID, NULL,
+                                       false);
+    assert_int_equal(err, IDMAP_SUCCESS);
+
+
+    /* Overlapping ranges with no external mapping */
+    err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1,
+                                       TEST_FIRST_RID, NULL,
+                                       false,
+                                       TEST_2_DOM_NAME, TEST_2_DOM_SID, &r1,
+                                       TEST_2_FIRST_RID, NULL,
+                                       false);
+    assert_int_equal(err, IDMAP_COLLISION);
+
+    /* Overlapping ranges with external mapping */
+    err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1,
+                                       TEST_FIRST_RID, NULL,
+                                       true,
+                                       TEST_2_DOM_NAME, TEST_2_DOM_SID, &r1,
+                                       TEST_2_FIRST_RID, NULL,
+                                       true);
+    assert_int_equal(err, IDMAP_SUCCESS);
+}
+
 int main(int argc, const char *argv[])
 {
     poptContext pc;
@@ -439,6 +531,7 @@ int main(int argc, const char *argv[])
         unit_test_setup_teardown(test_has_algorithmic_by_name,
                                  test_sss_idmap_setup_with_both,
                                  test_sss_idmap_teardown),
+        unit_test(test_sss_idmap_check_collision_ex),
     };
 
     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-- 
1.8.5.3