From 841fef45aef0a1424d4afbf3ea2bb40566155af9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 7 Feb 2014 18:17:09 +0100
Subject: [PATCH 95/97] 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(-)
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 88b6ba52538be83417e98c9a5dd033bea87ebe4b..07ae03b6ab0325b011a26f36f4fdc9a5766b8445 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"));
--
1.8.5.3