From 67857f5b40662c8b32d2d854ebffa07ef05d7fe3 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Wed, 25 Sep 2013 13:42:24 +0200 Subject: [PATCH 1/3] IPA: store forest name for forest member domains In order to fix https://fedorahosted.org/sssd/ticket/2093 the name of the forest must be known for a member domain of the forest. --- src/confdb/confdb.h | 1 + src/db/sysdb.h | 3 +- src/db/sysdb_subdomains.c | 49 +++++++++++++++++++++- src/providers/ad/ad_subdomains.c | 2 +- src/providers/ipa/ipa_subdomains.c | 79 +++++++++++++++++++++++++++++++++++- src/tests/sysdb-tests.c | 16 ++++---- src/util/domain_info_utils.c | 11 +++++- src/util/util.h | 3 +- 8 files changed, 148 insertions(+), 16 deletions(-) diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index cb2a624..d1587cd 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -238,6 +238,7 @@ struct sss_domain_info { char *realm; char *flat_name; char *domain_id; + char *forest; struct timeval subdomains_last_checked; struct sss_domain_info *prev; diff --git a/src/db/sysdb.h b/src/db/sysdb.h index f923217..18575bd 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -128,6 +128,7 @@ #define SYSDB_SUBDOMAIN_ID "domainID" #define SYSDB_SUBDOMAIN_MPG "mpg" #define SYSDB_SUBDOMAIN_ENUM "enumerate" +#define SYSDB_SUBDOMAIN_FOREST "memberOfForest" #define SYSDB_BASE_ID "baseID" #define SYSDB_ID_RANGE_SIZE "idRangeSize" @@ -375,7 +376,7 @@ errno_t sysdb_domain_create(struct sysdb_ctx *sysdb, const char *domain_name); errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, const char *name, const char *realm, const char *flat_name, const char *domain_id, - bool mpg, bool enumerate); + bool mpg, bool enumerate, const char *forest); errno_t sysdb_update_subdomains(struct sss_domain_info *domain); diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c index 5ef9aef..34b79db 100644 --- a/src/db/sysdb_subdomains.c +++ b/src/db/sysdb_subdomains.c @@ -35,6 +35,7 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) SYSDB_SUBDOMAIN_ID, SYSDB_SUBDOMAIN_MPG, SYSDB_SUBDOMAIN_ENUM, + SYSDB_SUBDOMAIN_FOREST, NULL}; struct sss_domain_info *dom; struct ldb_dn *basedn; @@ -42,6 +43,7 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) const char *realm; const char *flat; const char *id; + const char *forest; bool mpg; bool enumerate; @@ -101,6 +103,9 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) enumerate = ldb_msg_find_attr_as_bool(res->msgs[i], SYSDB_SUBDOMAIN_ENUM, false); + forest = ldb_msg_find_attr_as_string(res->msgs[i], + SYSDB_SUBDOMAIN_FOREST, NULL); + /* explicitly use dom->next as we need to check 'disabled' domains */ for (dom = domain->subdomains; dom; dom = dom->next) { if (strcasecmp(dom->name, name) == 0) { @@ -156,13 +161,25 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) dom->enumerate = enumerate; } + if (strcasecmp(dom->forest, forest) != 0) { + DEBUG(SSSDBG_TRACE_INTERNAL, + ("Forest changed from [%s] to [%s]!\n", + dom->forest, forest)); + talloc_zfree(dom->forest); + dom->forest = talloc_strdup(dom, forest); + if (dom->forest == NULL) { + ret = ENOMEM; + goto done; + } + } + break; } } /* If not found in loop it is a new subdomain */ if (dom == NULL) { dom = new_subdomain(domain, domain, name, realm, - flat, id, mpg, enumerate); + flat, id, mpg, enumerate, forest); if (dom == NULL) { ret = ENOMEM; goto done; @@ -356,7 +373,7 @@ done: errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, const char *name, const char *realm, const char *flat_name, const char *domain_id, - bool mpg, bool enumerate) + bool mpg, bool enumerate, const char *forest) { TALLOC_CTX *tmp_ctx; struct ldb_message *msg; @@ -368,6 +385,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, SYSDB_SUBDOMAIN_ID, SYSDB_SUBDOMAIN_MPG, SYSDB_SUBDOMAIN_ENUM, + SYSDB_SUBDOMAIN_FOREST, NULL}; const char *tmp_str; bool tmp_bool; @@ -377,6 +395,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, int id_flags = 0; int mpg_flags = 0; int enum_flags = 0; + int forest_flags = 0; int ret; tmp_ctx = talloc_new(NULL); @@ -407,6 +426,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, if (domain_id) id_flags = LDB_FLAG_MOD_ADD; mpg_flags = LDB_FLAG_MOD_ADD; enum_flags = LDB_FLAG_MOD_ADD; + if (forest) forest_flags = LDB_FLAG_MOD_ADD; } else if (res->count != 1) { ret = EINVAL; goto done; @@ -443,10 +463,18 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, if (tmp_bool != enumerate) { enum_flags = LDB_FLAG_MOD_REPLACE; } + + if (forest) { + tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], + SYSDB_SUBDOMAIN_FOREST, NULL); + if (!tmp_str || strcasecmp(tmp_str, forest) != 0) { + forest_flags = LDB_FLAG_MOD_REPLACE; + } + } } if (!store && realm_flags == 0 && flat_flags == 0 && id_flags == 0 - && mpg_flags == 0 && enum_flags == 0) { + && mpg_flags == 0 && enum_flags == 0 && forest_flags == 0) { ret = EOK; goto done; } @@ -544,6 +572,21 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, } } + if (forest_flags) { + ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FOREST, forest_flags, + NULL); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FOREST, forest); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + } + ret = ldb_modify(sysdb->ldb, msg); if (ret != LDB_SUCCESS) { DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add subdomain attributes to " diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c index b95f4e4..e8345ae 100644 --- a/src/providers/ad/ad_subdomains.c +++ b/src/providers/ad/ad_subdomains.c @@ -160,7 +160,7 @@ ad_subdom_store(struct ad_subdomains_ctx *ctx, /* AD subdomains are currently all mpg and do not enumerate */ ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str, - true, false); + true, false, NULL); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("sysdb_subdomain_store failed.\n")); goto done; diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index 496af42..5d3227d 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -456,6 +456,76 @@ static errno_t ipa_subdom_enumerates(struct sss_domain_info *parent, return EOK; } +static errno_t ipa_subdom_get_forest(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb_ctx, + struct sysdb_attrs *attrs, + char **_forest) +{ + int ret; + const char *orig_dn; + struct ldb_dn *dn = NULL; + const struct ldb_val *val; + char *forest = NULL; + + ret = sysdb_attrs_get_string(attrs, SYSDB_ORIG_DN, &orig_dn); + if (ret) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); + goto done; + } + + dn = ldb_dn_new(mem_ctx, ldb_ctx, orig_dn); + if (dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("ldb_dn_new failed.\n")); + goto done; + } + + if (!ldb_dn_validate(dn)) { + DEBUG(SSSDBG_OP_FAILURE, ("Original DN [%s] is not a valid DN.\n", + orig_dn)); + ret = EINVAL; + goto done; + } + + if (ldb_dn_get_comp_num(dn) < 5) { + /* we are only interested in the member domain objects */ + ret = EOK; + goto done; + } + + val = ldb_dn_get_component_val(dn, 3); + if (strncasecmp("trusts", (const char *) val->data, val->length) != 0) { + DEBUG(SSSDBG_TRACE_FUNC, + ("4th component is not 'trust', nothing to do.\n")); + ret = EOK; + goto done; + } + + val = ldb_dn_get_component_val(dn, 2); + if (strncasecmp("ad", (const char *) val->data, val->length) != 0) { + DEBUG(SSSDBG_TRACE_FUNC, + ("3rd component is not 'ad', nothing to do.\n")); + ret = EOK; + goto done; + } + + val = ldb_dn_get_component_val(dn, 1); + forest = talloc_strndup(mem_ctx, (const char *) val->data, val->length); + if (forest == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_strndup failed.\n")); + ret = ENOMEM; + goto done; + } + +done: + talloc_free(dn); + + if (ret == EOK) { + *_forest = forest; + } + + return ret; +} + static errno_t ipa_subdom_store(struct sss_domain_info *parent, struct sdap_idmap_ctx *sdap_idmap_ctx, struct sysdb_attrs *attrs, @@ -466,6 +536,7 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent, char *realm; const char *flat; const char *id; + char *forest = NULL; int ret; bool mpg; @@ -500,8 +571,14 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent, mpg = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx, id); + ret = ipa_subdom_get_forest(tmp_ctx, sysdb_ctx_get_ldb(parent->sysdb), + attrs, &forest); + if (ret != EOK) { + goto done; + } + ret = sysdb_subdomain_store(parent->sysdb, name, realm, flat, - id, mpg, enumerate); + id, mpg, enumerate, forest); if (ret) { DEBUG(SSSDBG_OP_FAILURE, ("sysdb_subdomain_store failed.\n")); goto done; diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c index d0aff2d..cbece72 100644 --- a/src/tests/sysdb-tests.c +++ b/src/tests/sysdb-tests.c @@ -4538,7 +4538,7 @@ START_TEST(test_sysdb_subdomain_create) ret = sysdb_subdomain_store(test_ctx->sysdb, dom1[0], dom1[1], dom1[2], dom1[3], - false, false); + false, false, NULL); fail_if(ret != EOK, "Could not set up the test (dom1)"); ret = sysdb_update_subdomains(test_ctx->domain); @@ -4552,7 +4552,7 @@ START_TEST(test_sysdb_subdomain_create) ret = sysdb_subdomain_store(test_ctx->sysdb, dom2[0], dom2[1], dom2[2], dom2[3], - false, false); + false, false, NULL); fail_if(ret != EOK, "Could not set up the test (dom2)"); ret = sysdb_update_subdomains(test_ctx->domain); @@ -4597,11 +4597,11 @@ START_TEST(test_sysdb_subdomain_store_user) subdomain = new_subdomain(test_ctx, test_ctx->domain, testdom[0], testdom[1], testdom[2], testdom[3], - false, false); + false, false, NULL); fail_unless(subdomain != NULL, "Failed to create new subdomin."); ret = sysdb_subdomain_store(test_ctx->sysdb, testdom[0], testdom[1], testdom[2], testdom[3], - false, false); + false, false, NULL); fail_if(ret != EOK, "Could not set up the test (test subdom)"); ret = sysdb_update_subdomains(test_ctx->domain); @@ -4668,11 +4668,11 @@ START_TEST(test_sysdb_subdomain_user_ops) subdomain = new_subdomain(test_ctx, test_ctx->domain, testdom[0], testdom[1], testdom[2], testdom[3], - false, false); + false, false, NULL); fail_unless(subdomain != NULL, "Failed to create new subdomin."); ret = sysdb_subdomain_store(test_ctx->sysdb, testdom[0], testdom[1], testdom[2], testdom[3], - false, false); + false, false, NULL); fail_if(ret != EOK, "Could not set up the test (test subdom)"); ret = sysdb_update_subdomains(test_ctx->domain); @@ -4723,11 +4723,11 @@ START_TEST(test_sysdb_subdomain_group_ops) subdomain = new_subdomain(test_ctx, test_ctx->domain, testdom[0], testdom[1], testdom[2], testdom[3], - false, false); + false, false, NULL); fail_unless(subdomain != NULL, "Failed to create new subdomin."); ret = sysdb_subdomain_store(test_ctx->sysdb, testdom[0], testdom[1], testdom[2], testdom[3], - false, false); + false, false, NULL); fail_if(ret != EOK, "Could not set up the test (test subdom)"); ret = sysdb_update_subdomains(test_ctx->domain); diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c index 7b1eb1a..aa8bbbc 100644 --- a/src/util/domain_info_utils.c +++ b/src/util/domain_info_utils.c @@ -170,7 +170,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, const char *flat_name, const char *id, bool mpg, - bool enumerate) + bool enumerate, + const char *forest) { struct sss_domain_info *dom; @@ -226,6 +227,14 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, } } + if (forest != NULL) { + dom->forest = talloc_strdup(dom, forest); + if (dom->forest == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("Failed to copy forest.\n")); + goto fail; + } + } + dom->enumerate = enumerate; dom->fqnames = true; dom->mpg = mpg; diff --git a/src/util/util.h b/src/util/util.h index 20d230c..0175440 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -564,7 +564,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, const char *flat_name, const char *id, bool mpg, - bool enumerate); + bool enumerate, + const char *forest); errno_t sssd_domain_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, -- 1.7.7.6