From 231bd1b34023daa3080cf461085e6e4aa7f4d733 Mon Sep 17 00:00:00 2001 From: Michal Židek Date: Mar 15 2017 15:28:53 +0000 Subject: SUBDOMAINS: Configurable search bases Added new trusted domain section in the sssd.conf were the search bases for the trusted domain can be specified. Resolves: https://pagure.io/SSSD/sssd/issue/2599 Reviewed-by: Jakub Hrozek --- diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c index 9a6fece..ec952d3 100644 --- a/src/providers/ad/ad_common.c +++ b/src/providers/ad/ad_common.c @@ -33,6 +33,13 @@ errno_t ad_set_search_bases(struct sdap_options *id_opts); static errno_t ad_set_sdap_options(struct ad_options *ad_opts, struct sdap_options *id_opts); +char *create_subdom_conf_path(TALLOC_CTX *mem_ctx, + const char *conf_path, + const char *subdom_name) +{ + return talloc_asprintf(mem_ctx, "%s/%s", conf_path, subdom_name); +} + static struct sdap_options * ad_create_default_sdap_options(TALLOC_CTX *mem_ctx) { @@ -107,8 +114,119 @@ fail: return NULL; } +static errno_t +ad_create_sdap_options(TALLOC_CTX *mem_ctx, + struct confdb_ctx *cdb, + const char *conf_path, + struct sdap_options **_id_opts) +{ + struct sdap_options *id_opts; + errno_t ret = EOK; + + if (cdb == NULL || conf_path == NULL) { + /* Fallback to defaults if there is no confdb */ + id_opts = ad_create_default_sdap_options(mem_ctx); + if (id_opts == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to initialize default sdap options\n"); + ret = EIO; + } + /* Nothing to do without cdb */ + goto done; + } + + id_opts = talloc_zero(mem_ctx, struct sdap_options); + if (!id_opts) { + ret = ENOMEM; + goto done; + } + + ret = dp_get_options(id_opts, cdb, conf_path, + ad_def_ldap_opts, + SDAP_OPTS_BASIC, + &id_opts->basic); + if (ret != EOK) { + goto done; + } + + /* Get sdap option maps */ + + /* General Attribute Map */ + ret = sdap_get_map(id_opts, + cdb, conf_path, + ad_2008r2_attr_map, + SDAP_AT_GENERAL, + &id_opts->gen_map); + if (ret != EOK) { + goto done; + } + + /* User map */ + ret = sdap_get_map(id_opts, + cdb, conf_path, + ad_2008r2_user_map, + SDAP_OPTS_USER, + &id_opts->user_map); + if (ret != EOK) { + goto done; + } + + ret = sdap_extend_map_with_list(id_opts, id_opts, + SDAP_USER_EXTRA_ATTRS, + id_opts->user_map, + SDAP_OPTS_USER, + &id_opts->user_map, + &id_opts->user_map_cnt); + if (ret != EOK) { + goto done; + } + + /* Group map */ + ret = sdap_get_map(id_opts, + cdb, conf_path, + ad_2008r2_group_map, + SDAP_OPTS_GROUP, + &id_opts->group_map); + if (ret != EOK) { + goto done; + } + + /* Netgroup map */ + ret = sdap_get_map(id_opts, + cdb, conf_path, + ad_netgroup_map, + SDAP_OPTS_NETGROUP, + &id_opts->netgroup_map); + if (ret != EOK) { + goto done; + } + + /* Services map */ + ret = sdap_get_map(id_opts, + cdb, conf_path, + ad_service_map, + SDAP_OPTS_SERVICES, + &id_opts->service_map); + if (ret != EOK) { + goto done; + } + + ret = EOK; +done: + if (ret == EOK) { + *_id_opts = id_opts; + } else { + talloc_free(id_opts); + } + + return ret; +} + struct ad_options * -ad_create_default_options(TALLOC_CTX *mem_ctx) +ad_create_options(TALLOC_CTX *mem_ctx, + struct confdb_ctx *cdb, + const char *conf_path, + struct sss_domain_info *subdom) { struct ad_options *ad_options; errno_t ret; @@ -116,17 +234,32 @@ ad_create_default_options(TALLOC_CTX *mem_ctx) ad_options = talloc_zero(mem_ctx, struct ad_options); if (ad_options == NULL) return NULL; - ret = dp_copy_defaults(ad_options, - ad_basic_opts, - AD_OPTS_BASIC, - &ad_options->basic); + if (cdb != NULL && conf_path != NULL) { + ret = dp_get_options(ad_options, + cdb, + conf_path, + ad_basic_opts, + AD_OPTS_BASIC, + &ad_options->basic); + } else { + /* Fallback to reading the defaults only if no confdb + * is available */ + ret = dp_copy_defaults(ad_options, + ad_basic_opts, + AD_OPTS_BASIC, + &ad_options->basic); + } if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get basic AD options\n"); talloc_free(ad_options); return NULL; } - ad_options->id = ad_create_default_sdap_options(ad_options); - if (ad_options->id == NULL) { + ret = ad_create_sdap_options(ad_options, + cdb, + conf_path, + &ad_options->id); + if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD LDAP options\n"); talloc_free(ad_options); return NULL; @@ -175,26 +308,33 @@ set_common_ad_trust_opts(struct ad_options *ad_options, struct ad_options * ad_create_2way_trust_options(TALLOC_CTX *mem_ctx, + struct confdb_ctx *cdb, + const char *conf_path, const char *realm, - const char *ad_domain, + struct sss_domain_info *subdom, const char *hostname, const char *keytab) { struct ad_options *ad_options; errno_t ret; - ad_options = ad_create_default_options(mem_ctx); - if (ad_options == NULL) return NULL; + ad_options = ad_create_options(mem_ctx, cdb, conf_path, subdom); + if (ad_options == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "ad_create_options failed\n"); + return NULL; + } - ret = set_common_ad_trust_opts(ad_options, realm, ad_domain, hostname, + ret = set_common_ad_trust_opts(ad_options, realm, subdom->name, hostname, keytab); if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "set_common_ad_trust_opts failed\n"); talloc_free(ad_options); return NULL; } ret = ad_set_sdap_options(ad_options, ad_options->id); if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "ad_set_sdap_options failed"); talloc_free(ad_options); return NULL; } @@ -204,7 +344,9 @@ ad_create_2way_trust_options(TALLOC_CTX *mem_ctx, struct ad_options * ad_create_1way_trust_options(TALLOC_CTX *mem_ctx, - const char *ad_domain, + struct confdb_ctx *cdb, + const char *subdom_conf_path, + struct sss_domain_info *subdom, const char *hostname, const char *keytab, const char *sasl_authid) @@ -213,18 +355,25 @@ ad_create_1way_trust_options(TALLOC_CTX *mem_ctx, const char *realm; errno_t ret; - ad_options = ad_create_default_options(mem_ctx); - if (ad_options == NULL) return NULL; + ad_options = ad_create_options(mem_ctx, cdb, subdom_conf_path, subdom); + if (ad_options == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "ad_create_options failed\n"); + return NULL; + } - realm = get_uppercase_realm(ad_options, ad_domain); + realm = get_uppercase_realm(ad_options, subdom->name); if (!realm) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to get uppercase realm\n"); talloc_free(ad_options); return NULL; } ret = set_common_ad_trust_opts(ad_options, realm, - ad_domain, hostname, keytab); + subdom->name, hostname, keytab); if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "set_common_ad_trust_opts failed [%d]: %s\n", + ret, sss_strerror(ret)); talloc_free(ad_options); return NULL; } @@ -240,6 +389,8 @@ ad_create_1way_trust_options(TALLOC_CTX *mem_ctx, ret = ad_set_sdap_options(ad_options, ad_options->id); if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "ad_set_sdap_options failed [%d]: %s\n", + ret, sss_strerror(ret)); talloc_free(ad_options); return NULL; } @@ -247,97 +398,6 @@ ad_create_1way_trust_options(TALLOC_CTX *mem_ctx, return ad_options; } -static errno_t -ad_create_sdap_options(TALLOC_CTX *mem_ctx, - struct confdb_ctx *cdb, - const char *conf_path, - struct sdap_options **_id_opts) -{ - struct sdap_options *id_opts; - errno_t ret; - - id_opts = talloc_zero(mem_ctx, struct sdap_options); - if (!id_opts) { - ret = ENOMEM; - goto done; - } - - ret = dp_get_options(id_opts, cdb, conf_path, - ad_def_ldap_opts, - SDAP_OPTS_BASIC, - &id_opts->basic); - if (ret != EOK) { - goto done; - } - - /* Get sdap option maps */ - - /* General Attribute Map */ - ret = sdap_get_map(id_opts, - cdb, conf_path, - ad_2008r2_attr_map, - SDAP_AT_GENERAL, - &id_opts->gen_map); - if (ret != EOK) { - goto done; - } - - /* User map */ - ret = sdap_get_map(id_opts, - cdb, conf_path, - ad_2008r2_user_map, - SDAP_OPTS_USER, - &id_opts->user_map); - if (ret != EOK) { - goto done; - } - - ret = sdap_extend_map_with_list(id_opts, id_opts, - SDAP_USER_EXTRA_ATTRS, - id_opts->user_map, - SDAP_OPTS_USER, - &id_opts->user_map, - &id_opts->user_map_cnt); - if (ret != EOK) { - goto done; - } - - /* Group map */ - ret = sdap_get_map(id_opts, - cdb, conf_path, - ad_2008r2_group_map, - SDAP_OPTS_GROUP, - &id_opts->group_map); - if (ret != EOK) { - goto done; - } - - /* Netgroup map */ - ret = sdap_get_map(id_opts, - cdb, conf_path, - ad_netgroup_map, - SDAP_OPTS_NETGROUP, - &id_opts->netgroup_map); - if (ret != EOK) { - goto done; - } - - /* Services map */ - ret = sdap_get_map(id_opts, - cdb, conf_path, - ad_service_map, - SDAP_OPTS_SERVICES, - &id_opts->service_map); - if (ret != EOK) { - goto done; - } - - ret = EOK; - *_id_opts = id_opts; -done: - return ret; -} - errno_t ad_get_common_options(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h index 23351e3..e02b932 100644 --- a/src/providers/ad/ad_common.h +++ b/src/providers/ad/ad_common.h @@ -99,6 +99,10 @@ struct ad_options { struct be_nsupdate_ctx *dyndns_ctx; }; +char *create_subdom_conf_path(TALLOC_CTX *mem_ctx, + const char *conf_path, + const char *subdom_name); + errno_t ad_get_common_options(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, @@ -106,20 +110,32 @@ ad_get_common_options(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, struct ad_options **_opts); -struct ad_options *ad_create_default_options(TALLOC_CTX *mem_ctx); +/* FIXME: ad_get_common_options and ad_create_options are + * similar. The later is subdomain specific. It may be + * good to merge the two into one more generic funtion. */ +struct ad_options *ad_create_options(TALLOC_CTX *mem_ctx, + struct confdb_ctx *cdb, + const char *conf_path, + struct sss_domain_info *subdom); struct ad_options *ad_create_2way_trust_options(TALLOC_CTX *mem_ctx, + struct confdb_ctx *cdb, + const char *conf_path, const char *realm, - const char *ad_domain, + struct sss_domain_info *subdom, const char *hostname, const char *keytab); struct ad_options *ad_create_1way_trust_options(TALLOC_CTX *mem_ctx, - const char *ad_domain, + struct confdb_ctx *cdb, + const char *conf_path, + struct sss_domain_info *subdom, const char *hostname, const char *keytab, const char *sasl_authid); +errno_t ad_set_search_bases(struct sdap_options *id_opts); + errno_t ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, const char *primary_servers, diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c index ad075c1..6787abd 100644 --- a/src/providers/ad/ad_subdomains.c +++ b/src/providers/ad/ad_subdomains.c @@ -158,6 +158,7 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, const char *realm; const char *hostname; const char *keytab; + char *subdom_conf_path; realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM); hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME); @@ -168,8 +169,18 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, return EINVAL; } - ad_options = ad_create_2way_trust_options(id_ctx, realm, ad_domain, + subdom_conf_path = create_subdom_conf_path(id_ctx, + be_ctx->conf_path, + subdom->name); + if (subdom_conf_path == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "subdom_conf_path failed\n"); + return ENOMEM; + } + + ad_options = ad_create_2way_trust_options(id_ctx, be_ctx->cdb, + subdom_conf_path, realm, subdom, hostname, keytab); + talloc_free(subdom_conf_path); if (ad_options == NULL) { DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n"); talloc_free(ad_options); diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c index ddd66bf..cb270f5 100644 --- a/src/providers/ipa/ipa_subdomains_server.c +++ b/src/providers/ipa/ipa_subdomains_server.c @@ -129,6 +129,8 @@ const char *ipa_trust_dir2str(uint32_t direction) static struct ad_options * ipa_create_1way_trust_ctx(struct ipa_id_ctx *id_ctx, + struct be_ctx *be_ctx, + const char *subdom_conf_path, const char *forest, const char *forest_realm, struct sss_domain_info *subdom) @@ -136,9 +138,7 @@ ipa_create_1way_trust_ctx(struct ipa_id_ctx *id_ctx, char *keytab; char *principal; struct ad_options *ad_options; - const char *ad_domain; - ad_domain = subdom->name; keytab = forest_keytab(id_ctx, forest); principal = subdomain_trust_princ(id_ctx, forest_realm, subdom); if (keytab == NULL || principal == NULL) { @@ -146,7 +146,9 @@ ipa_create_1way_trust_ctx(struct ipa_id_ctx *id_ctx, } ad_options = ad_create_1way_trust_options(id_ctx, - ad_domain, + be_ctx->cdb, + subdom_conf_path, + subdom, id_ctx->server_mode->hostname, keytab, principal); @@ -159,32 +161,46 @@ ipa_create_1way_trust_ctx(struct ipa_id_ctx *id_ctx, return ad_options; } -static struct ad_options *ipa_ad_options_new(struct ipa_id_ctx *id_ctx, +static struct ad_options *ipa_ad_options_new(struct be_ctx *be_ctx, + struct ipa_id_ctx *id_ctx, struct sss_domain_info *subdom) { struct ad_options *ad_options = NULL; uint32_t direction; const char *forest; const char *forest_realm; + char *subdom_conf_path; /* Trusts are only established with forest roots */ direction = subdom->forest_root->trust_direction; forest_realm = subdom->forest_root->realm; forest = subdom->forest_root->forest; + subdom_conf_path = create_subdom_conf_path(id_ctx, + be_ctx->conf_path, + subdom->name); + if (subdom_conf_path == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "subdom_conf_path failed\n"); + return NULL; + } + if (direction & LSA_TRUST_DIRECTION_OUTBOUND) { ad_options = ad_create_2way_trust_options(id_ctx, + be_ctx->cdb, + subdom_conf_path, id_ctx->server_mode->realm, - subdom->name, + subdom, id_ctx->server_mode->hostname, NULL); } else if (direction & LSA_TRUST_DIRECTION_INBOUND) { - ad_options = ipa_create_1way_trust_ctx(id_ctx, forest, + ad_options = ipa_create_1way_trust_ctx(id_ctx, be_ctx, + subdom_conf_path, forest, forest_realm, subdom); } else { DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported trust direction!\n"); ad_options = NULL; } + talloc_free(subdom_conf_path); if (ad_options == NULL) { DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n"); @@ -214,7 +230,7 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, ad_domain = subdom->name; DEBUG(SSSDBG_TRACE_LIBS, "Setting up AD subdomain %s\n", subdom->name); - ad_options = ipa_ad_options_new(id_ctx, subdom); + ad_options = ipa_ad_options_new(be_ctx, id_ctx, subdom); if (ad_options == NULL) { DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n"); talloc_free(ad_options); @@ -313,6 +329,13 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, return EFAULT; } + ret = ad_set_search_bases(ad_options->id); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD search bases\n"); + talloc_free(ad_options); + return ret; + } + sdap_inherit_options(subdom->parent->sd_inherit, id_ctx->sdap_id_ctx->opts, ad_id_ctx->sdap_id_ctx->opts); diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c index ea99989..3187af1 100644 --- a/src/tests/cmocka/test_ad_common.c +++ b/src/tests/cmocka/test_ad_common.c @@ -389,24 +389,6 @@ struct ad_common_test_ctx { struct sss_domain_info *subdom; }; -static void test_ad_create_default_options(void **state) -{ - struct ad_options *ad_options; - const char *s; - - ad_options = ad_create_default_options(global_talloc_context); - - assert_non_null(ad_options->basic); - - /* Not too much to test here except some defaults */ - s = dp_opt_get_string(ad_options->basic, AD_DOMAIN); - assert_null(s); - - assert_non_null(ad_options->id); - - talloc_free(ad_options); -} - static int test_ad_common_setup(void **state) { struct ad_common_test_ctx *test_ctx; @@ -462,9 +444,12 @@ static void test_ad_create_1way_trust_options(void **state) /* Make sure this is not the keytab that __wrap_krb5_kt_default uses */ mock_keytab_with_contents(test_ctx, ONEWAY_KEYTAB_PATH, ONEWAY_TEST_PRINC); + test_ctx->subdom->name = discard_const(ONEWAY_DOMNAME); test_ctx->ad_ctx->ad_options = ad_create_1way_trust_options( test_ctx->ad_ctx, - ONEWAY_DOMNAME, + NULL, + NULL, + test_ctx->subdom, ONEWAY_HOST_NAME, ONEWAY_KEYTAB_PATH, ONEWAY_AUTHID); @@ -524,13 +509,17 @@ static void test_ad_create_2way_trust_options(void **state) call_real_sasl_options = true; mock_keytab_with_contents(test_ctx, KEYTAB_PATH, KEYTAB_TEST_PRINC); + test_ctx->subdom->name = discard_const(DOMNAME); test_ctx->ad_ctx->ad_options = ad_create_2way_trust_options( - test_ctx->ad_ctx, - REALMNAME, - DOMNAME, - HOST_NAME, - NULL); + test_ctx->ad_ctx, + NULL, + NULL, + REALMNAME, + test_ctx->subdom, + HOST_NAME, + NULL); + assert_non_null(test_ctx->ad_ctx->ad_options); assert_int_equal(test_ctx->ad_ctx->ad_options->id->schema_type, @@ -592,11 +581,15 @@ test_ldap_conn_setup(void **state) ad_ctx = test_ctx->ad_ctx; - ad_ctx->ad_options = ad_create_2way_trust_options(ad_ctx, - REALMNAME, - DOMNAME, - HOST_NAME, - NULL); + test_ctx->ad_ctx->ad_options = ad_create_2way_trust_options( + ad_ctx, + NULL, + NULL, + REALMNAME, + test_ctx->subdom, + HOST_NAME, + NULL); + assert_non_null(ad_ctx->ad_options); ad_ctx->gc_ctx = talloc_zero(ad_ctx, struct sdap_id_conn_ctx); @@ -889,7 +882,6 @@ int main(int argc, const char *argv[]) }; const struct CMUnitTest tests[] = { - cmocka_unit_test(test_ad_create_default_options), cmocka_unit_test_setup_teardown(test_ad_create_1way_trust_options, test_ad_common_setup, test_ad_common_teardown),