From 4206e5dbe37277a4002010e85438fe376b5b1812 Mon Sep 17 00:00:00 2001 From: Sumit Bose 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