[SSSD] [PATCHES] IPA: add trusted domains with missing idrange

Sumit Bose sbose at redhat.com
Thu Oct 24 12:14:59 UTC 2013


Hi,

this patch set tries to fix https://fedorahosted.org/sssd/ticket/2101 .
Currently we rely on the fact that the external mapping is the default
in the case of an error. But this leads to a loot of useless CPU cycles
and maybe irritating error messages. With this patch set each trusted AD
member domain gets a proper range assigned if the forest root is
configured to manage the POSIX attributes.

bye,
Sumit
-------------- next part --------------
From e1a86771137f67e0e8d24c4bbb014bfc21d85538 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 23 Oct 2013 14:39:55 +0200
Subject: [PATCH 1/4] find_subdomain_by_sid: skip domains with missing
 domain_id

---
 Makefile.am                   |  12 ++-
 src/tests/cmocka/test_utils.c | 221 ++++++++++++++++++++++++++++++++++++++++++
 src/util/domain_info_utils.c  |  30 +++---
 3 files changed, 251 insertions(+), 12 deletions(-)
 create mode 100644 src/tests/cmocka/test_utils.c

diff --git a/Makefile.am b/Makefile.am
index cb24df8..d2a7384 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -153,7 +153,8 @@ if HAVE_CMOCKA
         sss_nss_idmap-tests \
         dyndns-tests \
         fqnames-tests \
-        test_sss_idmap
+        test_sss_idmap \
+        test_utils
 endif
 
 check_PROGRAMS = \
@@ -1397,6 +1398,15 @@ test_sss_idmap_LDADD = \
     $(SSSD_INTERNAL_LTLIBS) \
     libsss_test_common.la
 
+test_utils_SOURCES = \
+    $(TEST_MOCK_OBJ) \
+    src/tests/cmocka/test_utils.c
+test_utils_CFLAGS = \
+    $(AM_CFLAGS)
+test_utils_LDADD = \
+    $(CMOCKA_LIBS) \
+    $(SSSD_INTERNAL_LTLIBS) \
+    libsss_test_common.la
 endif
 
 noinst_PROGRAMS = pam_test_client
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
new file mode 100644
index 0000000..9152dcf
--- /dev/null
+++ b/src/tests/cmocka/test_utils.c
@@ -0,0 +1,221 @@
+/*
+    Authors:
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2013 Red Hat
+
+    SSSD tests: Tests for utility functions
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <popt.h>
+
+#include "tests/cmocka/common_mock.h"
+
+#define DOM_COUNT 10
+#define DOMNAME_TMPL "name_%u.dom"
+#define FLATNAME_TMPL "name_%u"
+#define SID_TMPL "S-1-5-21-1-2-%u"
+
+struct dom_list_test_ctx {
+    size_t dom_count;
+    struct sss_domain_info *dom_list;
+};
+
+void setup_dom_list(void **state)
+{
+    struct dom_list_test_ctx *test_ctx;
+    struct sss_domain_info *dom = NULL;
+    size_t c;
+
+    assert_true(leak_check_setup());
+
+    test_ctx = talloc_zero(global_talloc_context, struct dom_list_test_ctx);
+    assert_non_null(test_ctx);
+
+    test_ctx->dom_count = DOM_COUNT;
+
+    for (c = 0; c < test_ctx->dom_count; c++) {
+        dom = talloc_zero(test_ctx, struct sss_domain_info);
+        assert_non_null(dom);
+
+        dom->name = talloc_asprintf(dom, DOMNAME_TMPL, c);
+        assert_non_null(dom->name);
+
+        dom->flat_name = talloc_asprintf(dom, FLATNAME_TMPL, c);
+        assert_non_null(dom->flat_name);
+
+        dom->domain_id = talloc_asprintf(dom, SID_TMPL, c);
+        assert_non_null(dom->domain_id);
+
+        DLIST_ADD(test_ctx->dom_list, dom);
+    }
+
+    check_leaks_push(test_ctx);
+    *state = test_ctx;
+}
+
+void teardown_dom_list(void **state)
+{
+    struct dom_list_test_ctx *test_ctx = talloc_get_type(*state,
+                                                      struct dom_list_test_ctx);
+    if (test_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Type mismatch\n"));
+        return;
+    }
+
+    assert_true(check_leaks_pop(test_ctx) == true);
+    talloc_free(test_ctx);
+    assert_true(leak_check_teardown());
+}
+
+void test_find_subdomain_by_sid_null(void **state)
+{
+    struct dom_list_test_ctx *test_ctx = talloc_get_type(*state,
+                                                      struct dom_list_test_ctx);
+    struct sss_domain_info *dom;
+
+    dom = find_subdomain_by_sid(NULL, NULL);
+    assert_null(dom);
+
+    dom = find_subdomain_by_sid(test_ctx->dom_list, NULL);
+    assert_null(dom);
+
+    dom = find_subdomain_by_sid(NULL, "S-1-5-21-1-2-3");
+    assert_null(dom);
+}
+
+void test_find_subdomain_by_sid(void **state)
+{
+    struct dom_list_test_ctx *test_ctx = talloc_get_type(*state,
+                                                      struct dom_list_test_ctx);
+    struct sss_domain_info *dom;
+    size_t c;
+    char *name;
+    char *flat_name;
+    char *sid;
+
+    for (c = 0; c < test_ctx->dom_count; c++) {
+        name = talloc_asprintf(global_talloc_context, DOMNAME_TMPL, c);
+        assert_non_null(name);
+
+        flat_name = talloc_asprintf(global_talloc_context, FLATNAME_TMPL, c);
+        assert_non_null(flat_name);
+
+        sid = talloc_asprintf(global_talloc_context, SID_TMPL, c);
+        assert_non_null(sid);
+
+        dom = find_subdomain_by_sid(test_ctx->dom_list, sid);
+        assert_non_null(dom);
+        assert_string_equal(name, dom->name);
+        assert_string_equal(flat_name, dom->flat_name);
+        assert_string_equal(sid, dom->domain_id);
+
+        talloc_free(name);
+        talloc_free(flat_name);
+        talloc_free(sid);
+    }
+}
+
+void test_find_subdomain_by_sid_missing_sid(void **state)
+{
+    struct dom_list_test_ctx *test_ctx = talloc_get_type(*state,
+                                                      struct dom_list_test_ctx);
+    struct sss_domain_info *dom;
+    size_t c;
+    char *name;
+    char *flat_name;
+    char *sid;
+    size_t mis;
+
+    mis = test_ctx->dom_count/2;
+    assert_true((mis >= 1 && mis < test_ctx->dom_count));
+
+    dom = test_ctx->dom_list;
+    for (c = 0; c < mis; c++) {
+        assert_non_null(dom);
+        dom = dom->next;
+    }
+    assert_non_null(dom);
+    dom->domain_id = NULL;
+
+    for (c = 0; c < test_ctx->dom_count; c++) {
+        name = talloc_asprintf(global_talloc_context, DOMNAME_TMPL, c);
+        assert_non_null(name);
+
+        flat_name = talloc_asprintf(global_talloc_context, FLATNAME_TMPL, c);
+        assert_non_null(flat_name);
+
+        sid = talloc_asprintf(global_talloc_context, SID_TMPL, c);
+        assert_non_null(sid);
+
+        dom = find_subdomain_by_sid(test_ctx->dom_list, sid);
+        if (c == mis - 1) {
+            assert_null(dom);
+        } else {
+            assert_non_null(dom);
+            assert_string_equal(name, dom->name);
+            assert_string_equal(flat_name, dom->flat_name);
+            assert_string_equal(sid, dom->domain_id);
+        }
+
+        talloc_free(name);
+        talloc_free(flat_name);
+        talloc_free(sid);
+    }
+}
+
+int main(int argc, const char *argv[])
+{
+    poptContext pc;
+    int opt;
+    struct poptOption long_options[] = {
+        POPT_AUTOHELP
+        SSSD_DEBUG_OPTS
+        POPT_TABLEEND
+    };
+
+    const UnitTest tests[] = {
+        unit_test_setup_teardown(test_find_subdomain_by_sid_null,
+                                 setup_dom_list, teardown_dom_list),
+        unit_test_setup_teardown(test_find_subdomain_by_sid,
+                                 setup_dom_list, teardown_dom_list),
+        unit_test_setup_teardown(test_find_subdomain_by_sid_missing_sid,
+                                 setup_dom_list, teardown_dom_list),
+    };
+
+    /* Set debug level to invalid value so we can deside if -d 0 was used. */
+    debug_level = SSSDBG_INVALID;
+
+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+    while((opt = poptGetNextOpt(pc)) != -1) {
+        switch(opt) {
+        default:
+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
+                    poptBadOption(pc, 0), poptStrerror(opt));
+            poptPrintUsage(pc, stderr, 0);
+            return 1;
+        }
+    }
+    poptFreeContext(pc);
+
+    DEBUG_INIT(debug_level);
+
+    /* Even though normally the tests should clean up after themselves
+     * they might not after a failed run. Remove the old db to be sure */
+    tests_set_cwd();
+
+    return run_tests(tests);
+}
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index 9d7bb5f..9f2f154 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -112,26 +112,34 @@ struct sss_domain_info *find_subdomain_by_sid(struct sss_domain_info *domain,
                                               const char *sid)
 {
     struct sss_domain_info *dom = domain;
-    size_t sid_len = strlen(sid);
+    size_t sid_len;
     size_t dom_sid_len;
 
+    if (sid == NULL) {
+        return NULL;
+    }
+
+    sid_len = strlen(sid);
+
     while (dom && dom->disabled) {
         dom = get_next_domain(dom, true);
     }
 
     while (dom) {
-        dom_sid_len = strlen(dom->domain_id);
+        if (dom->domain_id != NULL) {
+            dom_sid_len = strlen(dom->domain_id);
 
-        if (strncasecmp(dom->domain_id, sid, dom_sid_len) == 0) {
-            if (dom_sid_len == sid_len) {
-                /* sid is domain sid */
-                return dom;
-            }
+            if (strncasecmp(dom->domain_id, sid, dom_sid_len) == 0) {
+                if (dom_sid_len == sid_len) {
+                    /* sid is domain sid */
+                    return dom;
+                }
 
-            /* sid is object sid, check if domain sid is align with
-             * sid first subauthority component */
-            if (sid[dom_sid_len] == '-') {
-                return dom;
+                /* sid is object sid, check if domain sid is align with
+                 * sid first subauthority component */
+                if (sid[dom_sid_len] == '-') {
+                    return dom;
+                }
             }
         }
 
-- 
1.8.3.1

-------------- next part --------------
From dc0115802904c954c79d90cd846da9f5bd965019 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 24 Oct 2013 11:44:11 +0200
Subject: [PATCH 2/4] idmap: add
 sss_idmap_domain_by_name_has_algorithmic_mapping()

---
 src/lib/idmap/sss_idmap.c         | 33 +++++++++++++++++++++++++++++
 src/lib/idmap/sss_idmap.h         | 44 +++++++++++++++++++++++++++++++++++----
 src/tests/cmocka/test_sss_idmap.c | 41 ++++++++++++++++++++++++++++++++++++
 3 files changed, 114 insertions(+), 4 deletions(-)

diff --git a/src/lib/idmap/sss_idmap.c b/src/lib/idmap/sss_idmap.c
index 17bd577..9278e10 100644
--- a/src/lib/idmap/sss_idmap.c
+++ b/src/lib/idmap/sss_idmap.c
@@ -953,3 +953,36 @@ sss_idmap_domain_has_algorithmic_mapping(struct sss_idmap_ctx *ctx,
 
     return IDMAP_SID_UNKNOWN;
 }
+
+enum idmap_error_code
+sss_idmap_domain_by_name_has_algorithmic_mapping(struct sss_idmap_ctx *ctx,
+                                                 const char *dom_name,
+                                                 bool *has_algorithmic_mapping)
+{
+    struct idmap_domain_info *idmap_domain_info;
+
+    if (dom_name == NULL) {
+        return IDMAP_ERROR;
+    }
+
+    CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
+
+    if (ctx->idmap_domain_info == NULL) {
+        return IDMAP_NO_DOMAIN;
+    }
+
+    idmap_domain_info = ctx->idmap_domain_info;
+
+    while (idmap_domain_info != NULL) {
+        if (idmap_domain_info->name != NULL
+                && strcmp(dom_name, idmap_domain_info->name) == 0) {
+
+            *has_algorithmic_mapping = !idmap_domain_info->external_mapping;
+            return IDMAP_SUCCESS;
+        }
+
+        idmap_domain_info = idmap_domain_info->next;
+    }
+
+    return IDMAP_NAME_UNKNOWN;
+}
diff --git a/src/lib/idmap/sss_idmap.h b/src/lib/idmap/sss_idmap.h
index 91e5d0b..4101fb9 100644
--- a/src/lib/idmap/sss_idmap.h
+++ b/src/lib/idmap/sss_idmap.h
@@ -81,7 +81,10 @@ enum idmap_error_code {
     IDMAP_COLLISION,
 
     /** External source should be consulted for idmapping */
-    IDMAP_EXTERNAL
+    IDMAP_EXTERNAL,
+
+    /** The provided  name was not found */
+    IDMAP_NAME_UNKNOWN
 };
 
 /**
@@ -524,11 +527,21 @@ bool is_domain_sid(const char *str);
 /**
  * @brief Check if a domain is configured with algorithmic mapping
  *
- * @param[in] ctx      Idmap context
- * @param[in] dom_sid  SID string, can be either a domain SID or an object SID
+ * @param[in] ctx                      Idmap context
+ * @param[in] dom_sid                  SID string, can be either a domain SID
+ *                                     or an object SID
+ * @param[out] has_algorithmic_mapping Boolean value indicating if the given
+ *                                     domain is configured for algorithmic
+ *                                     mapping or not.
  *
  * @return
- * TODO ....
+ *  - #IDMAP_SUCCESS:         Domain for the given SID was found and
+ *                            has_algorithmic_mapping is set accordingly
+ *  - #IDMAP_SID_INVALID:     Provided SID is invalid
+ *  - #IDMAP_CONTEXT_INVALID: Provided idmap context is invalid
+ *  - #IDMAP_NO_DOMAIN:       No domains are available in the idmap context
+ *  - #IDMAP_SID_UNKNOWN:     No domain with the given SID was found in the
+ *                            idmap context
  */
 enum idmap_error_code
 sss_idmap_domain_has_algorithmic_mapping(struct sss_idmap_ctx *ctx,
@@ -536,6 +549,29 @@ sss_idmap_domain_has_algorithmic_mapping(struct sss_idmap_ctx *ctx,
                                          bool *has_algorithmic_mapping);
 
 /**
+ * @brief Check if a domain is configured with algorithmic mapping
+ *
+ * @param[in]  ctx                     Idmap context
+ * @param[in]  dom_name                Name of the domain
+ * @param[out] has_algorithmic_mapping Boolean value indicating if the given
+ *                                     domain is configured for algorithmic
+ *                                     mapping or not.
+ *
+ * @return
+ *  - #IDMAP_SUCCESS:         Domain for the given name was found and
+ *                            has_algorithmic_mapping is set accordingly
+ *  - #IDMAP_ERROR:           Provided name is invalid
+ *  - #IDMAP_CONTEXT_INVALID: Provided idmap context is invalid
+ *  - #IDMAP_NO_DOMAIN:       No domains are available in the idmap context
+ *  - #IDMAP_NAME_UNKNOWN:    No domain with the given name was found in the
+ *                            idmap context
+ */
+enum idmap_error_code
+sss_idmap_domain_by_name_has_algorithmic_mapping(struct sss_idmap_ctx *ctx,
+                                                 const char *dom_name,
+                                                 bool *has_algorithmic_mapping);
+
+/**
  * @brief Convert binary SID to SID structure
  *
  * @param[in] ctx      Idmap context
diff --git a/src/tests/cmocka/test_sss_idmap.c b/src/tests/cmocka/test_sss_idmap.c
index 2f6a67d..53ed35a 100644
--- a/src/tests/cmocka/test_sss_idmap.c
+++ b/src/tests/cmocka/test_sss_idmap.c
@@ -367,6 +367,44 @@ void test_has_algorithmic(void **state)
     assert_false(use_id_mapping);
 }
 
+void test_has_algorithmic_by_name(void **state)
+{
+    struct test_ctx *test_ctx;
+    bool use_id_mapping;
+    enum idmap_error_code err;
+
+    test_ctx = talloc_get_type(*state, struct test_ctx);
+
+    assert_non_null(test_ctx);
+
+    err = sss_idmap_domain_by_name_has_algorithmic_mapping(NULL, NULL, &use_id_mapping);
+    assert_int_equal(err, IDMAP_ERROR);
+
+    err = sss_idmap_domain_by_name_has_algorithmic_mapping(NULL, TEST_DOM_SID,
+                                                   &use_id_mapping);
+    assert_int_equal(err, IDMAP_CONTEXT_INVALID);
+
+    err = sss_idmap_domain_by_name_has_algorithmic_mapping(test_ctx->idmap_ctx, NULL,
+                                                   &use_id_mapping);
+    assert_int_equal(err, IDMAP_ERROR);
+
+    err = sss_idmap_domain_by_name_has_algorithmic_mapping(test_ctx->idmap_ctx,
+                                                   TEST_DOM_NAME"1",
+                                                   &use_id_mapping);
+    assert_int_equal(err, IDMAP_NAME_UNKNOWN);
+
+    err = sss_idmap_domain_by_name_has_algorithmic_mapping(test_ctx->idmap_ctx,
+                                                   TEST_DOM_NAME,
+                                                   &use_id_mapping);
+    assert_int_equal(err, IDMAP_SUCCESS);
+    assert_true(use_id_mapping);
+
+    err = sss_idmap_domain_by_name_has_algorithmic_mapping(test_ctx->idmap_ctx,
+                                                   TEST_2_DOM_NAME,
+                                                   &use_id_mapping);
+    assert_int_equal(err, IDMAP_SUCCESS);
+    assert_false(use_id_mapping);
+}
 
 int main(int argc, const char *argv[])
 {
@@ -396,6 +434,9 @@ int main(int argc, const char *argv[])
         unit_test_setup_teardown(test_has_algorithmic,
                                  test_sss_idmap_setup_with_both,
                                  test_sss_idmap_teardown),
+        unit_test_setup_teardown(test_has_algorithmic_by_name,
+                                 test_sss_idmap_setup_with_both,
+                                 test_sss_idmap_teardown),
     };
 
     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-- 
1.8.3.1

-------------- next part --------------
From dffdd7cc99025cb8790f34f79bdf294762f3468d Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 24 Oct 2013 11:45:57 +0200
Subject: [PATCH 3/4] sdap_idmap_domain_has_algorithmic_mapping: add domain
 name argument

When libss_idmap was only used to algorithmically map a SID to a POSIX
ID a domain SID was strictly necessary and the only information needed
to find a domain.

With the introduction of external mappings there are cases where a
domain SID is not available. Currently we relied on the fact that
external mapping was always used as a default if not specific
information about the domain was found. The lead to extra CPU cycles and
potentially confusing debug messages. Adding the domain name as a search
parameter will avoid this.
---
 src/providers/ad/ad_subdomains.c           |  1 +
 src/providers/ipa/ipa_subdomains.c         |  2 +-
 src/providers/ldap/ldap_id.c               |  2 ++
 src/providers/ldap/sdap_async_enum.c       |  2 ++
 src/providers/ldap/sdap_async_groups.c     |  1 +
 src/providers/ldap/sdap_async_initgroups.c |  4 ++++
 src/providers/ldap/sdap_async_users.c      |  1 +
 src/providers/ldap/sdap_idmap.c            | 12 +++++++++++-
 src/providers/ldap/sdap_idmap.h            |  1 +
 9 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index d8e9b26..30c510c 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -162,6 +162,7 @@ ad_subdom_store(struct ad_subdomains_ctx *ctx,
 
     mpg = sdap_idmap_domain_has_algorithmic_mapping(
                                              ctx->sdap_id_ctx->opts->idmap_ctx,
+                                             domain->name,
                                              domain->domain_id);
 
     /* AD subdomains are currently all mpg and do not enumerate */
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index d6cb0c6..93bbdae 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -577,7 +577,7 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent,
         goto done;
     }
 
-    mpg = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx, id);
+    mpg = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx, name, id);
 
     ret = ipa_subdom_get_forest(tmp_ctx, sysdb_ctx_get_ldb(parent->sysdb),
                                 attrs, &forest);
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index 59dfd0a..9fd95ce 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -105,6 +105,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
 
     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
                                                           ctx->opts->idmap_ctx,
+                                                          sdom->dom->name,
                                                           sdom->dom->domain_id);
     switch (filter_type) {
     case BE_FILTER_NAME:
@@ -471,6 +472,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
 
     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
                                                           ctx->opts->idmap_ctx,
+                                                          sdom->dom->name,
                                                           sdom->dom->domain_id);
 
     switch(filter_type) {
diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c
index b03c19a..a1bc097 100644
--- a/src/providers/ldap/sdap_async_enum.c
+++ b/src/providers/ldap/sdap_async_enum.c
@@ -366,6 +366,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
 
     use_mapping = sdap_idmap_domain_has_algorithmic_mapping(
                                                         ctx->opts->idmap_ctx,
+                                                        sdom->dom->name,
                                                         sdom->dom->domain_id);
 
     /* We always want to filter on objectclass and an available name */
@@ -540,6 +541,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
 
     use_mapping = sdap_idmap_domain_has_algorithmic_mapping(
                                                         ctx->opts->idmap_ctx,
+                                                        sdom->dom->name,
                                                         sdom->dom->domain_id);
 
     /* We always want to filter on objectclass and an available name */
diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
index b111895..00ac3e9 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -478,6 +478,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
     }
 
     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
+                                                               dom->name,
                                                                sid_str);
     if (use_id_mapping) {
         posix_group = true;
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index e8de8d5..c16d484 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -100,6 +100,7 @@ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
     }
 
     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
+                                                             domain->name,
                                                              domain->domain_id);
 
     ret = sysdb_transaction_start(sysdb);
@@ -1542,6 +1543,7 @@ static struct tevent_req *sdap_initgr_rfc2307bis_send(
 
     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
                                                         opts->idmap_ctx,
+                                                        sdom->dom->name,
                                                         sdom->dom->domain_id);
 
     state->base_filter =
@@ -2637,6 +2639,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
 
     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
                                                           id_ctx->opts->idmap_ctx,
+                                                          sdom->dom->name,
                                                           sdom->dom->domain_id);
 
     ret = sss_filter_sanitize(state, name, &clean_name);
@@ -2684,6 +2687,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
 
     state->use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
                                                          state->opts->idmap_ctx,
+                                                         state->dom->name,
                                                          state->dom->domain_id);
 
     ret = sdap_get_initgr_next_base(req);
diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
index 860e8fe..2807b07 100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -215,6 +215,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
 
 
     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
+                                                               dom->name,
                                                                sid_str);
 
     /* Retrieve or map the UID as appropriate */
diff --git a/src/providers/ldap/sdap_idmap.c b/src/providers/ldap/sdap_idmap.c
index af69ee1..249201d 100644
--- a/src/providers/ldap/sdap_idmap.c
+++ b/src/providers/ldap/sdap_idmap.c
@@ -513,6 +513,7 @@ done:
 }
 
 bool sdap_idmap_domain_has_algorithmic_mapping(struct sdap_idmap_ctx *ctx,
+                                               const char *dom_name,
                                                const char *dom_sid)
 {
     enum idmap_error_code err;
@@ -529,6 +530,15 @@ bool sdap_idmap_domain_has_algorithmic_mapping(struct sdap_idmap_ctx *ctx,
         return false;
     }
 
+    err = sss_idmap_domain_by_name_has_algorithmic_mapping(ctx->map,
+                                                  dom_name,
+                                                  &has_algorithmic_mapping);
+    if (err == IDMAP_SUCCESS) {
+        return has_algorithmic_mapping;
+    } else if (err != IDMAP_NAME_UNKNOWN && err != IDMAP_NO_DOMAIN) {
+        return false;
+    }
+
     /* This is the first time we've seen this domain
      * Create a new domain for it. We'll use the dom-sid
      * as the domain name for now, since we don't have
@@ -554,7 +564,7 @@ bool sdap_idmap_domain_has_algorithmic_mapping(struct sdap_idmap_ctx *ctx,
         }
     }
 
-    ret = ctx->find_new_domain(ctx, new_dom_sid, new_dom_sid);
+    ret = ctx->find_new_domain(ctx, dom_name, new_dom_sid);
     talloc_free(tmp_ctx);
     if (ret != EOK) {
         DEBUG(SSSDBG_MINOR_FAILURE,
diff --git a/src/providers/ldap/sdap_idmap.h b/src/providers/ldap/sdap_idmap.h
index c8bc4e2..07499dc 100644
--- a/src/providers/ldap/sdap_idmap.h
+++ b/src/providers/ldap/sdap_idmap.h
@@ -57,6 +57,7 @@ sdap_idmap_sid_to_unix(struct sdap_idmap_ctx *idmap_ctx,
                        id_t *id);
 
 bool sdap_idmap_domain_has_algorithmic_mapping(struct sdap_idmap_ctx *ctx,
+                                               const char *name,
                                                const char *dom_sid);
 
 #endif /* SDAP_IDMAP_H_ */
-- 
1.8.3.1

-------------- next part --------------
From 3e7283a39994ac24a9ff9dfede0d735cc89b4bb0 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 23 Oct 2013 13:30:57 +0200
Subject: [PATCH 4/4] IPA: add trusted domains with missing idrange

If the forest root of a trusted forest is managing POSIX IDs for its
users and groups the same is assumed for all member domains in the
forest which do not have explicitly have an idrange set.

To reflect this SSSD will create the matching ranges automatically.

Fixes https://fedorahosted.org/sssd/ticket/2101
---
 src/providers/ipa/ipa_idmap.c | 136 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/src/providers/ipa/ipa_idmap.c b/src/providers/ipa/ipa_idmap.c
index 2f141f8..cca0157 100644
--- a/src/providers/ipa/ipa_idmap.c
+++ b/src/providers/ipa/ipa_idmap.c
@@ -26,6 +26,135 @@
 #include "providers/ipa/ipa_common.h"
 #include "util/util_sss_idmap.h"
 
+static errno_t ipa_idmap_check_posix_child(struct sdap_idmap_ctx *idmap_ctx,
+                                           const char *dom_name,
+                                           const char *dom_sid_str,
+                                           size_t range_count,
+                                           struct range_info **range_list)
+{
+    bool has_algorithmic_mapping;
+    enum idmap_error_code err;
+    struct sss_domain_info *dom;
+    struct sss_domain_info *forest_root;
+    size_t c;
+    struct sss_idmap_range range;
+    struct range_info *r;
+    char *range_id;
+    TALLOC_CTX *tmp_ctx;
+    bool found = false;
+    int ret;
+
+    err = sss_idmap_domain_has_algorithmic_mapping(idmap_ctx->map, dom_sid_str,
+                                                   &has_algorithmic_mapping);
+    if (err == IDMAP_SUCCESS) {
+        DEBUG(SSSDBG_TRACE_ALL,
+              ("Idmap of domain [%s] already known, nothing to do.\n",
+                dom_sid_str));
+        return EOK;
+    } else {
+        err = sss_idmap_domain_by_name_has_algorithmic_mapping(idmap_ctx->map,
+                                                      dom_name,
+                                                      &has_algorithmic_mapping);
+        if (err == IDMAP_SUCCESS) {
+            DEBUG(SSSDBG_TRACE_ALL,
+                  ("Idmap of domain [%s] already known, nothing to do.\n",
+                    dom_sid_str));
+            return EOK;
+        }
+    }
+    DEBUG(SSSDBG_TRACE_ALL, ("Trying to add idmap for domain [%s].\n",
+                             dom_sid_str));
+
+    if (err != IDMAP_SID_UNKNOWN && err != IDMAP_NAME_UNKNOWN) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("sss_idmap_domain_has_algorithmic_mapping failed.\n"));
+        return EINVAL;
+    }
+
+    dom = find_subdomain_by_sid(idmap_ctx->id_ctx->be->domain, dom_sid_str);
+    if (dom == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("find_subdomain_by_sid failed with SID [%s].\n", dom_sid_str));
+        return EINVAL;
+    }
+
+    if (dom->forest == NULL) {
+        DEBUG(SSSDBG_MINOR_FAILURE, ("No forest available for domain [%s].\n",
+                                     dom_sid_str));
+        return EINVAL;
+    }
+
+    forest_root = find_subdomain_by_name(idmap_ctx->id_ctx->be->domain,
+                                         dom->forest, true);
+    if (forest_root == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("find_subdomain_by_name failed to find forest root [%s].\n",
+               dom->forest));
+        return ENOENT;
+    }
+
+    if (forest_root->domain_id == NULL) {
+        DEBUG(SSSDBG_MINOR_FAILURE, ("Forest root [%s] does not have a SID.\n",
+                                     dom->forest));
+        return EINVAL;
+    }
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
+        return ENOMEM;
+    }
+
+    for (c = 0; c < range_count; c++) {
+        r = range_list[c];
+        if (r->trusted_dom_sid != NULL
+                && strcmp(r->trusted_dom_sid, forest_root->domain_id) == 0) {
+
+            if (r->range_type == NULL
+                    || strcmp(r->range_type, IPA_RANGE_AD_TRUST_POSIX) != 0) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      ("Forest root does not have range type [%s].\n",
+                       IPA_RANGE_AD_TRUST_POSIX));
+                return EINVAL;
+            }
+
+            range.min = r->base_id;
+            range.max = r->base_id + r->id_range_size -1;
+            range_id = talloc_asprintf(tmp_ctx, "%s-%s", dom_sid_str, r->name);
+            if (range_id == NULL) {
+                DEBUG(SSSDBG_OP_FAILURE, ("talloc_asprintf failed.\n"));
+                ret = ENOMEM;
+                goto done;
+            }
+
+            err = sss_idmap_add_domain_ex(idmap_ctx->map, dom_name, dom_sid_str,
+                                          &range, range_id, 0, true);
+            if (err != IDMAP_SUCCESS && err != IDMAP_COLLISION) {
+                DEBUG(SSSDBG_CRIT_FAILURE, ("Could not add range [%s] to ID map\n",
+                                            range_id));
+                ret = EIO;
+                goto done;
+            }
+
+            found = true;
+        }
+    }
+
+    if (!found) {
+        DEBUG(SSSDBG_MINOR_FAILURE, ("No idrange found for forest root [%s].\n",
+                                     forest_root->domain_id));
+        ret = ENOENT;
+        goto done;
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+
+    return ret;
+}
+
 errno_t ipa_idmap_find_new_domain(struct sdap_idmap_ctx *idmap_ctx,
                                   const char *dom_name,
                                   const char *dom_sid_str)
@@ -118,6 +247,13 @@ errno_t ipa_idmap_find_new_domain(struct sdap_idmap_ctx *idmap_ctx,
         }
     }
 
+    ret = ipa_idmap_check_posix_child(idmap_ctx, dom_name, dom_sid_str,
+                                      range_count, range_list);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("ipa_idmap_check_posix_child failed.\n"));
+        goto done;
+    }
+
     ret = EOK;
 
 done:
-- 
1.8.3.1



More information about the sssd-devel mailing list