Hi, the first two attached patches should fix https://fedorahosted.org/sssd/ticket/2093 and make https://fedorahosted.org/sssd/ticket/2080 invalid. The third fixes wrong return code in one of the functions I touched with in the other patches.
bye, Sumit
From 67857f5b40662c8b32d2d854ebffa07ef05d7fe3 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> 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
From aeca422eba8fdf4722547ed26ced1d2ba797fd20 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Wed, 25 Sep 2013 17:21:36 +0200 Subject: [PATCH 2/3] ipa_server_mode: write capaths to krb5 include file If there are member domains in a trusted forest which are DNS-wise not proper children of the forest root the IPA KDC needs some help to determine the right authentication path. In general this should be done internally by the IPA KDC but this works requires more effort than letting sssd write the needed data to the include file for krb5.conf. If this functionality is available for the IPA KDC this patch might be removed from the sssd tree. Fixes https://fedorahosted.org/sssd/ticket/2093 --- src/providers/ad/ad_subdomains.c | 2 +- src/providers/ipa/ipa_subdomains.c | 4 ++- src/util/domain_info_utils.c | 51 +++++++++++++++++++++++++++++++++++- src/util/util.h | 3 +- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c index e8345ae..f6d2eb8 100644 --- a/src/providers/ad/ad_subdomains.c +++ b/src/providers/ad/ad_subdomains.c @@ -482,7 +482,7 @@ static void ad_subdomains_get_slave_domain_done(struct tevent_req *req) goto done; } - ret = sss_write_domain_mappings(ctx->sd_ctx->be_ctx->domain); + ret = sss_write_domain_mappings(ctx->sd_ctx->be_ctx->domain, false); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, ("sss_krb5_write_mappings failed.\n")); diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index 5d3227d..16e679c 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -924,7 +924,9 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) goto done; } - ret = sss_write_domain_mappings(domain); + ret = sss_write_domain_mappings(domain, + dp_opt_get_bool(ctx->sd_ctx->id_ctx->ipa_options->basic, + IPA_SERVER_MODE)); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, ("sss_krb5_write_mappings failed.\n")); diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c index aa8bbbc..9f2714b 100644 --- a/src/util/domain_info_utils.c +++ b/src/util/domain_info_utils.c @@ -323,9 +323,10 @@ sss_krb5_touch_config(void) } errno_t -sss_write_domain_mappings(struct sss_domain_info *domain) +sss_write_domain_mappings(struct sss_domain_info *domain, bool add_capaths) { struct sss_domain_info *dom; + struct sss_domain_info *parent_dom; errno_t ret; errno_t err; TALLOC_CTX *tmp_ctx; @@ -336,6 +337,9 @@ sss_write_domain_mappings(struct sss_domain_info *domain) mode_t old_mode; FILE *fstream = NULL; int i; + bool capaths_started; + char *uc_forest; + char *uc_parent; if (domain == NULL || domain->name == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("No domain name provided\n")); @@ -421,6 +425,51 @@ sss_write_domain_mappings(struct sss_domain_info *domain) } } + if (add_capaths) { + capaths_started = false; + parent_dom = domain; + uc_parent = get_uppercase_realm(tmp_ctx, parent_dom->name); + if (uc_parent == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("get_uppercase_realm failed.\n")); + ret = ENOMEM; + goto done; + } + + for (dom = get_next_domain(domain, true); + dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */ + dom = get_next_domain(dom, false)) { + + if (dom->forest == NULL) { + continue; + } + + uc_forest = get_uppercase_realm(tmp_ctx, dom->forest); + if (uc_forest == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("get_uppercase_realm failed.\n")); + ret = ENOMEM; + goto done; + } + + if (!capaths_started) { + ret = fprintf(fstream, "[capaths]\n"); + if (ret < 0) { + DEBUG(SSSDBG_OP_FAILURE, ("fprintf failed\n")); + ret = EIO; + goto done; + } + capaths_started = true; + } + + ret = fprintf(fstream, "%s = {\n %s = %s\n}\n%s = {\n %s = %s\n}\n", + dom->realm, uc_parent, uc_forest, + uc_parent, dom->realm, uc_forest); + if (ret < 0) { + DEBUG(SSSDBG_CRIT_FAILURE, ("fprintf failed\n")); + goto done; + } + } + } + ret = fclose(fstream); fstream = NULL; if (ret != 0) { diff --git a/src/util/util.h b/src/util/util.h index 0175440..bb3b614 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -575,7 +575,8 @@ errno_t sssd_domain_init(TALLOC_CTX *mem_ctx, #define IS_SUBDOMAIN(dom) ((dom)->parent != NULL) -errno_t sss_write_domain_mappings(struct sss_domain_info *domain); +errno_t sss_write_domain_mappings(struct sss_domain_info *domain, + bool add_capaths); /* from util_lock.c */ errno_t sss_br_lock_file(int fd, size_t start, size_t len, -- 1.7.7.6
From dfee332521b1ba63bf13468e66038cf2a9916586 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Thu, 26 Sep 2013 10:10:39 +0200 Subject: [PATCH 3/3] Do not return DP_ERR_FATAL in case of success --- src/providers/ipa/ipa_subdomains.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index 16e679c..307fa38 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -872,6 +872,7 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) struct ipa_subdomains_req_ctx *ctx; struct sss_domain_info *domain; bool refresh_has_changes = false; + int dp_error = DP_ERR_FATAL; ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx); domain = ctx->sd_ctx->be_ctx->domain; @@ -956,7 +957,10 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) } done: - be_req_terminate(ctx->be_req, DP_ERR_FATAL, ret, NULL); + if (ret == EOK) { + dp_error = DP_ERR_OK; + } + be_req_terminate(ctx->be_req, dp_error, ret, NULL); } -- 1.7.7.6
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/sssd-devel