From c9160931bd57b66bb1bf8312c05b9cb6da2497bc Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Fri, 7 Feb 2014 18:17:09 +0100 Subject: IPA: check ranges for collisions before saving them Fixes https://fedorahosted.org/sssd/ticket/2253 --- src/providers/ipa/ipa_subdomains.c | 83 +++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index 88b6ba525..07ae03b6a 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -351,14 +351,28 @@ const char *get_flat_name_from_subdomain_name(struct be_ctx *be_ctx, } static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, + char *domain_name, size_t count, struct sysdb_attrs **reply, struct range_info ***_range_list) { struct range_info **range_list = NULL; + struct range_info *r; const char *value; size_t c; + size_t d; int ret; + enum idmap_error_code err; + char *name1; + char *name2; + char *sid1; + char *sid2; + uint32_t rid1; + uint32_t rid2; + struct sss_idmap_range range1; + struct sss_idmap_range range2; + bool mapping1; + bool mapping2; range_list = talloc_array(mem_ctx, struct range_info *, count + 1); if (range_list == NULL) { @@ -367,8 +381,8 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, } for (c = 0; c < count; c++) { - range_list[c] = talloc_zero(range_list, struct range_info); - if (range_list[c] == NULL) { + r = talloc_zero(range_list, struct range_info); + if (r == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero failed.\n")); ret = ENOMEM; goto done; @@ -379,8 +393,8 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); goto done; } - range_list[c]->name = talloc_strdup(range_list[c], value); - if (range_list[c]->name == NULL) { + r->name = talloc_strdup(r, value); + if (r->name == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); ret = ENOMEM; goto done; @@ -388,9 +402,8 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, ret = sysdb_attrs_get_string(reply[c], IPA_TRUSTED_DOMAIN_SID, &value); if (ret == EOK) { - range_list[c]->trusted_dom_sid = talloc_strdup(range_list[c], - value); - if (range_list[c]->trusted_dom_sid == NULL) { + r->trusted_dom_sid = talloc_strdup(r, value); + if (r->trusted_dom_sid == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); ret = ENOMEM; goto done; @@ -401,28 +414,28 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, } ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_ID, - &range_list[c]->base_id); + &r->base_id); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); goto done; } ret = sysdb_attrs_get_uint32_t(reply[c], IPA_ID_RANGE_SIZE, - &range_list[c]->id_range_size); + &r->id_range_size); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); goto done; } ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_RID, - &range_list[c]->base_rid); + &r->base_rid); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); goto done; } ret = sysdb_attrs_get_uint32_t(reply[c], IPA_SECONDARY_BASE_RID, - &range_list[c]->secondary_base_rid); + &r->secondary_base_rid); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); goto done; @@ -430,8 +443,8 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, ret = sysdb_attrs_get_string(reply[c], IPA_RANGE_TYPE, &value); if (ret == EOK) { - range_list[c]->range_type = talloc_strdup(range_list[c], value); - if (range_list[c]->range_type == NULL) { + r->range_type = talloc_strdup(r, value); + if (r->range_type == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); ret = ENOMEM; goto done; @@ -439,23 +452,52 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, } else if (ret == ENOENT) { /* Older IPA servers might not have the range_type attribute, but * only support local ranges and trusts with algorithmic mapping. */ - if (range_list[c]->trusted_dom_sid == NULL) { - range_list[c]->range_type = talloc_strdup(range_list[c], - IPA_RANGE_LOCAL); + if (r->trusted_dom_sid == NULL) { + r->range_type = talloc_strdup(r, IPA_RANGE_LOCAL); } else { - range_list[c]->range_type = talloc_strdup(range_list[c], - IPA_RANGE_AD_TRUST); + r->range_type = talloc_strdup(r, IPA_RANGE_AD_TRUST); } } else { DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); goto done; } - if (range_list[c]->range_type == NULL) { + if (r->range_type == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); ret = ENOMEM; goto done; } + + ret = get_idmap_data_from_range(r, domain_name, &name1, &sid1, &rid1, + &range1, &mapping1); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("get_idmap_data_from_range failed.\n")); + goto done; + } + for (d = 0; d < c; d++) { + ret = get_idmap_data_from_range(range_list[d], domain_name, &name2, + &sid2, &rid2, &range2, &mapping2); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("get_idmap_data_from_range failed.\n")); + goto done; + } + + err = sss_idmap_check_collision_ex(name1, sid1, &range1, rid1, + r->name, mapping1, + name2, sid2, &range2, rid2, + range_list[d]->name, mapping2); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Collision of ranges [%s] and [%s] detected.\n", + r->name, range_list[d]->name)); + ret = EINVAL; + goto done; + } + } + + range_list[c] = r; } + range_list[c] = NULL; *_range_list = range_list; @@ -1013,7 +1055,8 @@ static void ipa_subdomains_handler_ranges_done(struct tevent_req *req) goto done; } - ret = ipa_ranges_parse_results(ctx, reply_count, reply, &range_list); + ret = ipa_ranges_parse_results(ctx, domain->name, + reply_count, reply, &range_list); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("ipa_ranges_parse_results request failed.\n")); -- cgit