>From 7c236fa99826519a3a000eb0a84eb748c8c08dc7 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 1 Jun 2015 21:58:15 +0200 Subject: [PATCH 05/29] SYSDB: Add a forest root attribute to sss_domain_info Instead of complex forest root search methods, establish forest root during subdomain list update. The subdomain code can then just use the forest_root pointer. --- src/confdb/confdb.h | 7 +- src/db/sysdb_subdomains.c | 59 +++++++++ src/tests/cmocka/test_sysdb_subdomains.c | 207 ++++++++++++++++++++++++++++++- 3 files changed, 271 insertions(+), 2 deletions(-) diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index 03dc27195d43ed4758c84eede19941869abad7c7..b5e76f7f624bf8c9398a10a7cd61d58f43ceab06 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -265,7 +265,6 @@ struct sss_domain_info { char *realm; char *flat_name; char *domain_id; - char *forest; enum trust_direction trust_direction; struct timeval subdomains_last_checked; @@ -276,6 +275,12 @@ struct sss_domain_info { struct sss_domain_info *next; bool disabled; + + /* Do not use the forest pointer directly in new code, but rather the + * forest_root pointer. sss_domain_info will be more opaque in the future + */ + char *forest; + struct sss_domain_info *forest_root; }; /** diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c index 05ec414d93764277bb19045da9fed354b0b2f2b7..dd272e81c6a40f75f411295f6766adc41a8ee1be 100644 --- a/src/db/sysdb_subdomains.c +++ b/src/db/sysdb_subdomains.c @@ -147,6 +147,63 @@ fail: return NULL; } +static bool is_forest_root(struct sss_domain_info *d) +{ + if (d->forest == NULL) { + /* IPA subdomain provider saves/saved trusted forest root domains + * without the forest attribute. Those are automatically forest + * roots + */ + return true; + } + + if (d->realm && (strcmp(d->forest, d->realm) == 0)) { + return true; + } + + return false; +} + +static bool is_same_forest(struct sss_domain_info *root, + struct sss_domain_info *member) +{ + if (member->forest != NULL + && root->realm != NULL + && strcmp(member->forest, root->realm) == 0) { + return true; + } + + return false; +} + +static void link_forest_roots(struct sss_domain_info *domain) +{ + struct sss_domain_info *d; + struct sss_domain_info *dd; + + for (d = domain; d; d = get_next_domain(d, true)) { + d->forest_root = NULL; + } + + for (d = domain; d; d = get_next_domain(d, true)) { + if (d->forest_root != NULL) { + continue; + } + + if (is_forest_root(d) == true) { + for (dd = domain; dd; dd = get_next_domain(dd, true)) { + if (dd->forest_root != NULL) { + continue; + } + + if (is_same_forest(d, dd) == true) { + dd->forest_root = d; + } + } + } + } +} + errno_t sysdb_update_subdomains(struct sss_domain_info *domain) { int i; @@ -357,6 +414,8 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) } } + link_forest_roots(domain); + ret = EOK; done: diff --git a/src/tests/cmocka/test_sysdb_subdomains.c b/src/tests/cmocka/test_sysdb_subdomains.c index 6744a4226bcd3bb3b8c8c712830d79d7f43b62ae..b0c86490dad7de610d77ed78d320cc564c426f08 100644 --- a/src/tests/cmocka/test_sysdb_subdomains.c +++ b/src/tests/cmocka/test_sysdb_subdomains.c @@ -35,6 +35,10 @@ #define TESTS_PATH "test_sysdb_subdomains" #define TEST_CONF_DB "test_sysdb_subdomains.ldb" #define TEST_DOM_NAME "test_sysdb_subdomains" +#define TEST_FLAT_NAME "TEST" +#define TEST_SID "S-1" +#define TEST_REALM "TEST_SYSDB_SUBDOMAINS" +#define TEST_FOREST TEST_REALM #define TEST_ID_PROVIDER "local" struct subdom_test_ctx { @@ -149,7 +153,6 @@ static void test_sysdb_master_domain_ops(void **state) struct subdom_test_ctx *test_ctx = talloc_get_type(*state, struct subdom_test_ctx); - ret = sysdb_master_domain_add_info(test_ctx->tctx->dom, "realm1", "flat1", "id1", "forest1"); assert_int_equal(ret, EOK); @@ -175,6 +178,199 @@ static void test_sysdb_master_domain_ops(void **state) assert_string_equal(test_ctx->tctx->dom->forest, "forest2"); } +/* Parent domain totally separate from subdomains that imitate + * IPA domain and two forests + */ +static void test_sysdb_link_forest_root_ipa(void **state) +{ + errno_t ret; + struct subdom_test_ctx *test_ctx = + talloc_get_type(*state, struct subdom_test_ctx); + struct sss_domain_info *sub; + struct sss_domain_info *child; + + /* name, realm, flat, SID, forest */ + const char *const dom1[5] = { "dom1.sub", "DOM1.SUB", + "DOM1", "S-1", "DOM1.SUB" }; + const char *const child_dom1[5] = { "child1.dom1.sub", "CHILD1.DOM1.SUB", + "CHILD1.DOM1", "S-1-2", "DOM1.SUB" }; + const char *const dom2[5] = { "dom2.sub", "DOM2.SUB", + "DOM2", "S-2", "DOM2.SUB" }; + const char *const child_dom2[5] = { "child2.dom2.sub", "CHILD2.DOM1.SUB", + "CHILD2.DOM1", "S-2-2", "DOM2.SUB" }; + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + dom1[0], dom1[1], dom1[2], dom1[3], + false, false, dom1[4], + SD_TRUST_DIRECTION_TWOWAY); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + child_dom1[0], child_dom1[1], + child_dom1[2], child_dom1[3], + false, false, child_dom1[4], + SD_TRUST_DIRECTION_TWOWAY); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + dom2[0], dom2[1], dom2[2], dom2[3], + false, false, dom2[4], + SD_TRUST_DIRECTION_TWOWAY); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + child_dom2[0], child_dom2[1], + child_dom2[2], child_dom2[3], + false, false, child_dom2[4], + SD_TRUST_DIRECTION_TWOWAY); + assert_int_equal(ret, EOK); + + ret = sysdb_update_subdomains(test_ctx->tctx->dom); + assert_int_equal(ret, EOK); + + sub = find_domain_by_name(test_ctx->tctx->dom, dom1[0], true); + assert_non_null(sub->forest_root); + assert_true(sub->forest_root = sub); + + child = find_domain_by_name(test_ctx->tctx->dom, child_dom1[0], true); + assert_non_null(child->forest_root); + assert_true(child->forest_root = sub); + + sub = find_domain_by_name(test_ctx->tctx->dom, dom2[0], true); + assert_non_null(sub->forest_root); + assert_true(sub->forest_root = sub); + + child = find_domain_by_name(test_ctx->tctx->dom, child_dom2[0], true); + assert_non_null(child->forest_root); + assert_true(child->forest_root = sub); +} + +/* Parent domain is an AD forest root and there are two subdomains + * child and parallel + */ +static void test_sysdb_link_forest_root_ad(void **state) +{ + errno_t ret; + struct subdom_test_ctx *test_ctx = + talloc_get_type(*state, struct subdom_test_ctx); + struct sss_domain_info *sub; + struct sss_domain_info *child; + + const char *const child_dom[5] = { "child.test_sysdb_subdomains",/* name */ + "CHILD.TEST_SYSDB_SUBDOMAINS",/* realm */ + "CHILD", /* flat */ + "S-1-2", /* sid */ + TEST_FOREST }; /* forest */ + + const char *const sub_dom[5] = { "another.subdomain", /* name */ + "ANOTHER.SUBDOMAIN", /* realm */ + "ANOTHER", /* flat */ + "S-1-3", /* sid */ + TEST_FOREST }; /* forest */ + + ret = sysdb_master_domain_add_info(test_ctx->tctx->dom, + TEST_REALM, + TEST_FLAT_NAME, + TEST_SID, + TEST_FOREST); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + child_dom[0], child_dom[1], + child_dom[2], child_dom[3], + false, false, child_dom[4], + SD_TRUST_DIRECTION_TWOWAY); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + sub_dom[0], sub_dom[1], + sub_dom[2], sub_dom[3], + false, false, sub_dom[4], + SD_TRUST_DIRECTION_TWOWAY); + assert_int_equal(ret, EOK); + + ret = sysdb_update_subdomains(test_ctx->tctx->dom); + assert_int_equal(ret, EOK); + + assert_non_null(test_ctx->tctx->dom->forest_root); + assert_true(test_ctx->tctx->dom->forest_root == test_ctx->tctx->dom); + + child = find_domain_by_name(test_ctx->tctx->dom, child_dom[0], true); + assert_non_null(child->forest_root); + assert_true(child->forest_root = test_ctx->tctx->dom); + + sub = find_domain_by_name(test_ctx->tctx->dom, sub_dom[0], true); + assert_non_null(sub->forest_root); + assert_true(sub->forest_root = test_ctx->tctx->dom); +} + +/* Parent domain is an AD member domain connected to a root domain + */ +static void test_sysdb_link_forest_member_ad(void **state) +{ + errno_t ret; + struct subdom_test_ctx *test_ctx = + talloc_get_type(*state, struct subdom_test_ctx); + struct sss_domain_info *sub; + struct sss_domain_info *root; + + const char *const forest_root[5] = { test_ctx->tctx->dom->name, /* name */ + TEST_FOREST, /* realm */ + TEST_FLAT_NAME, /* flat */ + TEST_SID, /* sid */ + TEST_FOREST }; /* forest */ + + const char *const child_dom[5] = { "child.test_sysdb_subdomains",/* name */ + "CHILD.TEST_SYSDB_SUBDOMAINS",/* realm */ + "CHILD", /* flat */ + "S-1-2", /* sid */ + TEST_FOREST }; /* forest */ + + const char *const sub_dom[5] = { "another.subdomain", /* name */ + "ANOTHER.SUBDOMAIN", /* realm */ + "ANOTHER", /* flat */ + "S-1-3", /* sid */ + TEST_FOREST }; /* forest */ + + ret = sysdb_master_domain_add_info(test_ctx->tctx->dom, + child_dom[1], + child_dom[2], + child_dom[3], + TEST_FOREST); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + sub_dom[0], sub_dom[1], + sub_dom[2], sub_dom[3], + false, false, sub_dom[4], + SD_TRUST_DIRECTION_TWOWAY); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + forest_root[0], forest_root[1], + forest_root[2], forest_root[3], + false, false, forest_root[4], + SD_TRUST_DIRECTION_TWOWAY); + assert_int_equal(ret, EOK); + + ret = sysdb_master_domain_update(test_ctx->tctx->dom); + assert_int_equal(ret, EOK); + + ret = sysdb_update_subdomains(test_ctx->tctx->dom); + assert_int_equal(ret, EOK); + + root = find_domain_by_name(test_ctx->tctx->dom, forest_root[0], true); + assert_non_null(root->forest_root); + assert_true(root->forest_root = root); + + assert_non_null(test_ctx->tctx->dom->forest_root); + assert_true(test_ctx->tctx->dom->forest_root == root); + + sub = find_domain_by_name(test_ctx->tctx->dom, sub_dom[0], true); + assert_non_null(sub->forest_root); + assert_true(sub->forest_root = root); +} + int main(int argc, const char *argv[]) { int rv; @@ -196,6 +392,15 @@ int main(int argc, const char *argv[]) cmocka_unit_test_setup_teardown(test_sysdb_subdomain_create, test_sysdb_subdom_setup, test_sysdb_subdom_teardown), + cmocka_unit_test_setup_teardown(test_sysdb_link_forest_root_ipa, + test_sysdb_subdom_setup, + test_sysdb_subdom_teardown), + cmocka_unit_test_setup_teardown(test_sysdb_link_forest_root_ad, + test_sysdb_subdom_setup, + test_sysdb_subdom_teardown), + cmocka_unit_test_setup_teardown(test_sysdb_link_forest_member_ad, + test_sysdb_subdom_setup, + test_sysdb_subdom_teardown), }; /* Set debug level to invalid value so we can deside if -d 0 was used. */ -- 2.1.0