Blob Blame History Raw
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