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