ad_subdomains.c revision cc4caf88344210ea9777d618f0f71935ca5e7f8b
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder AD Subdomains Module
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder Sumit Bose <sbose@redhat.com>
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers Copyright (C) 2013 Red Hat
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers This program is free software; you can redistribute it and/or modify
698573ebc6be4bd63c295a3704fd9459a0c6699cChristian Maeder it under the terms of the GNU General Public License as published by
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers the Free Software Foundation; either version 3 of the License, or
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers (at your option) any later version.
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers This program is distributed in the hope that it will be useful,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers but WITHOUT ANY WARRANTY; without even the implied warranty of
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers GNU General Public License for more details.
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers You should have received a copy of the GNU General Public License
4e521879e36515b983525ff9a4ea82ba44e5bbffChristian Maeder along with this program. If not, see <http://www.gnu.org/licenses/>.
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers/* Attributes of AD trusted domains */
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers/* trustType=2 denotes uplevel (NT5 and later) trusted domains. See
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers * http://msdn.microsoft.com/en-us/library/windows/desktop/ms680342%28v=vs.85%29.aspx
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers * for example.
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers * The absence of msDS-TrustForestTrustInfo attribute denotes a domain from
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers * the same forest. See http://msdn.microsoft.com/en-us/library/cc223786.aspx
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers * for more information.
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers#define SLAVE_DOMAIN_FILTER_BASE "(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*))"
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers#define SLAVE_DOMAIN_FILTER "(&"SLAVE_DOMAIN_FILTER_BASE")"
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers#define FOREST_ROOT_FILTER_FMT "(&"SLAVE_DOMAIN_FILTER_BASE"(cn=%s))"
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers/* do not refresh more often than every 5 seconds for now */
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers keytab = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KEYTAB);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder if (realm == NULL || hostname == NULL || ad_domain == NULL) {
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_CONF_SETTINGS, "Missing realm or hostname.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ad_options = ad_create_2way_trust_options(id_ctx, realm,
c64d33a7fbeae730cbe65193fe3cc24e7aa1ddd6Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ad_site_override = dp_opt_get_string(ad_options->basic, AD_SITE);
c64d33a7fbeae730cbe65193fe3cc24e7aa1ddd6Christian Maeder gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = ad_failover_init(ad_options, be_ctx, NULL, NULL, realm,
c64d33a7fbeae730cbe65193fe3cc24e7aa1ddd6Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ad_id_ctx = ad_id_ctx_init(ad_options, be_ctx);
fea14169cb07365fe4d12fea734d7b761ea8b287Christian Maeder ad_id_ctx->sdap_id_ctx->opts = ad_options->id;
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers /* use AD plugin */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx->be_res,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers be_fo_set_srv_lookup_plugin(be_ctx, ad_srv_plugin_send,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = sdap_domain_subdom_add(ad_id_ctx->sdap_id_ctx,
fea14169cb07365fe4d12fea734d7b761ea8b287Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize sdap domain\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers sdom = sdap_domain_get(ad_id_ctx->sdap_id_ctx->opts, subdom);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers sdap_inherit_options(subdom->parent->sd_inherit,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Set up the ID mapping object */
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckersads_store_sdap_subdom(struct ad_subdomains_ctx *ctx,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_OP_FAILURE, "sdap_domain_subdom_add failed.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers if (IS_SUBDOMAIN(sditer->dom) && sditer->pvt == NULL) {
dd38bafd384f5a5bc9634aad395505a0fd74395aChristian Maeder ret = ad_subdom_ad_ctx_new(ctx->be_ctx, ctx->ad_id_ctx,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_OP_FAILURE, "ad_subdom_ad_ctx_new failed.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckersstatic errno_t ad_subdom_enumerates(struct sss_domain_info *parent,
dd38bafd384f5a5bc9634aad395505a0fd74395aChristian Maeder ret = sysdb_attrs_get_string(attrs, AD_AT_TRUST_PARTNER, &name);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers *_enumerates = subdomain_enumerates(parent, name);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = sysdb_attrs_get_uint32_t(subdom_attrs, AD_AT_TRUST_TYPE,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_uint32_t failed.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = sysdb_attrs_get_string(subdom_attrs, AD_AT_TRUST_PARTNER, &name);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_OP_FAILURE, "failed to get subdomain name\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = sysdb_attrs_get_string(subdom_attrs, AD_AT_FLATNAME, &flat);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_OP_FAILURE, "failed to get flat name of subdomain %s\n",
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = sysdb_attrs_get_el(subdom_attrs, AD_AT_SID, &el);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_OP_FAILURE, "sdap_attrs_get_el failed.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers err = sss_idmap_bin_sid_to_sid(ctx->idmap_ctx,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers "Could not convert SID: [%s].\n", idmap_error_string(err));
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder mpg = sdap_idmap_domain_has_algorithmic_mapping(
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder sss_idmap_free_sid(ctx->sdap_id_ctx->opts->idmap_ctx->map, sid_str);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic errno_t ad_subdomains_refresh(struct ad_subdomains_ctx *ctx,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = sysdb_attrs_get_string(reply[0], AD_AT_TRUST_PARTNER,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* check existing subdomains */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder for (dom = get_next_domain(domain, SSS_GND_DESCEND);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers /* If we are handling root domain, skip all the other domains. We don't
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers * want to accidentally remove non-root domains
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers if (root_name && strcmp(root_name, dom->name) != 0) {
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder for (c = 0; c < count; c++) {
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = sysdb_attrs_get_string(reply[c], AD_AT_TRUST_PARTNER, &value);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* ok this subdomain does not exist anymore, let's clean up */
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = sysdb_subdomain_delete(dom->sysdb, dom->name);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers sdom = sdap_domain_get(ctx->sdap_id_ctx->opts, dom);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE, "BUG: Domain does not exist?\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Remove the subdomain from the list of LDAP domains */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder sdap_domain_remove(ctx->sdap_id_ctx->opts, dom);
e07538a3c4dbc690e57f61aded6db89d876b2374Christian Maeder /* terminate all requests for this subdomain so we can free it */
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers be_terminate_domain_requests(ctx->be_ctx, dom->name);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* ok let's try to update it */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = ad_subdom_enumerates(domain, reply[c], &enumerate);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = ad_subdom_store(ctx, domain, reply[c], enumerate);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Nothing we can do about the error. Let's at least try
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * to reuse the existing domains
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
e07538a3c4dbc690e57f61aded6db89d876b2374Christian Maeder "will try to use cached subdomain\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* all domains were already accounted for and have been updated */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* if we get here it means we have changes to the subdomains list */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder for (c = 0; c < count; c++) {
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Nothing we can do about the error. Let's at least try
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * to reuse the existing domains.
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = ad_subdom_enumerates(domain, reply[c], &enumerate);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = ad_subdom_store(ctx, domain, reply[c], enumerate);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "will try to use cached subdomain\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic errno_t ad_subdom_reinit(struct ad_subdomains_ctx *ctx)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder dp_opt_get_string(ctx->ad_id_ctx->ad_options->basic,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Just continue */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = sysdb_update_subdomains(ctx->be_ctx->domain);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = sss_write_domain_mappings(ctx->be_ctx->domain);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_MINOR_FAILURE, "sss_krb5_write_mappings failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Just continue */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = ads_store_sdap_subdom(ctx, ctx->be_ctx->domain);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "ads_store_sdap_subdom failed.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckersstatic void ad_subdomains_get_conn_done(struct tevent_req *req);
e07538a3c4dbc690e57f61aded6db89d876b2374Christian Maederstatic void ad_subdomains_master_dom_done(struct tevent_req *req);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckersstatic errno_t ad_subdomains_get_root(struct ad_subdomains_req_ctx *ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder struct ad_subdomains_req_ctx *req_ctx = NULL;
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder req_ctx = talloc_zero(be_req, struct ad_subdomains_req_ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder req_ctx->sdap_op = sdap_id_op_create(req_ctx,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n");
e07538a3c4dbc690e57f61aded6db89d876b2374Christian Maeder req = sdap_id_op_connect_send(req_ctx->sdap_op, req_ctx, &ret);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n",
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder tevent_req_set_callback(req, ad_subdomains_get_conn_done, req_ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder be_req_terminate(be_req, dp_error, ret, NULL);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic void ad_subdomains_get_conn_done(struct tevent_req *req)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = sdap_id_op_connect_recv(req, &dp_error);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "No AD server is available, cannot get the "
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "subdomain list while offline\n");
f7d2e793728bbb7fd185e027eb9dfd7b9dd11c21Christian Maeder "Failed to connect to AD server: [%d](%s)\n",
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder req = ad_master_domain_send(ctx, ctx->sd_ctx->be_ctx->ev,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "ad_master_domain_send failed.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers tevent_req_set_callback(req, ad_subdomains_master_dom_done, ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder be_req_terminate(ctx->be_req, dp_error, ret, NULL);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic void ad_subdomains_master_dom_done(struct tevent_req *req)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot retrieve master domain info\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder realm = dp_opt_get_cstring(ctx->sd_ctx->ad_id_ctx->ad_options->basic,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_CONF_SETTINGS, "Missing realm.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot save master domain info\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers strcasecmp(ctx->sd_ctx->be_ctx->domain->name, ctx->forest) != 0) {
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers "SSSD needs to look up the forest root domain\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "Connected to forest root, looking up child domains..\n");
e07538a3c4dbc690e57f61aded6db89d876b2374Christian Maeder be_req_terminate(ctx->be_req, DP_ERR_FATAL, ret, NULL);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic void ad_subdomains_get_root_domain_done(struct tevent_req *req);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic errno_t ad_subdomains_get_root(struct ad_subdomains_req_ctx *ctx)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder const char *forest_root_attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder base = sdap_id_ctx->opts->sdom->search_bases[ctx->root_base_iter];
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder filter = talloc_asprintf(ctx, FOREST_ROOT_FILTER_FMT, ctx->forest);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder tevent_req_set_callback(req, ad_subdomains_get_root_domain_done, ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic struct sss_domain_info *ads_get_root_domain(struct ad_subdomains_req_ctx *ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic void ad_subdomains_root_conn_done(struct tevent_req *req);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckersstatic void ad_subdomains_get_root_domain_done(struct tevent_req *req)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers /* If no root domain was found in the default search base, try the
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * next one, if available
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "Multiple results for root domain search, "
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "domain list might be incomplete!\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Exactly one result, good. */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* We won't use the operation to the local LDAP anymore, but
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * read from the forest root
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = sdap_id_op_done(ctx->sdap_op, ret, &dp_error);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "No AD server is available, cannot get the "
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers "subdomain list while offline\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "Failed to search the AD server: [%d](%s)\n",
f7d2e793728bbb7fd185e027eb9dfd7b9dd11c21Christian Maeder ret = ad_subdomains_refresh(ctx->sd_ctx, 1, true, reply, &has_changes);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "ad_subdomains_refresh failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx->root_domain = ads_get_root_domain(ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot create id ctx for the root domain\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder req = sdap_id_op_connect_send(ctx->root_op, ctx, &ret);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n",
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder tevent_req_set_callback(req, ad_subdomains_root_conn_done, ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder be_req_terminate(ctx->be_req, dp_error, ret, NULL);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic struct sss_domain_info *ads_get_root_domain(struct ad_subdomains_req_ctx *ctx)
e07538a3c4dbc690e57f61aded6db89d876b2374Christian Maeder ret = sysdb_attrs_get_string(ctx->root_domain_attrs, AD_AT_TRUST_PARTNER, &name);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* With a subsequent run, the root should already be known */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder root = find_domain_by_name(ctx->sd_ctx->be_ctx->domain,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder sdom = sdap_domain_get(ctx->sd_ctx->ad_id_ctx->sdap_id_ctx->opts,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "Cannot get the sdom for %s!\n", ctx->root_domain->name);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = ad_subdom_ad_ctx_new(ctx->sd_ctx->be_ctx,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "ad_subdom_ad_ctx_new failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder root_id_ctx->ldap_ctx->ignore_mark_offline = true;
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic void ad_subdomains_root_conn_done(struct tevent_req *req)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = sdap_id_op_connect_recv(req, &dp_error);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder be_mark_dom_offline(ctx->root_domain, be_req_get_be_ctx(ctx->be_req));
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "Failed to connect to AD server: [%d](%s)\n",
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder be_req_terminate(ctx->be_req, dp_error, ret, NULL);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic void ad_subdomains_get_slave_domain_done(struct tevent_req *req);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckersstatic errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder const char *slave_dom_attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers base = ctx->root_id_ctx->sdap_id_ctx->opts->sdom->search_bases[ctx->base_iter];
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers dp_opt_get_int(ctx->root_id_ctx->sdap_id_ctx->opts->basic,
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
fea14169cb07365fe4d12fea734d7b761ea8b287Christian Maeder tevent_req_set_callback(req, ad_subdomains_get_slave_domain_done, ctx);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckersstatic errno_t ad_subdomains_process(TALLOC_CTX *mem_ctx,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* We are connected directly to the root domain. The 'sd'
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * list is complete and we can just use it
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* If we searched for root separately, we must:
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * a) treat the root domain as a subdomain
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * b) filter the subdomain we are connected to from the subdomain
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * list, from our point of view, it's the master domain
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder sd_out = talloc_zero_array(mem_ctx, struct sysdb_attrs *, nsd+1);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers for (i = 0; i < nsd; i++) {
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = sysdb_attrs_get_string(sd[i], AD_AT_TRUST_PARTNER, &sd_name);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder if (strcasecmp(sd_name, domain->name) == 0) {
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "Not including primary domain %s in the subdomain list\n",
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Now include the root */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic void ad_subdomains_get_slave_domain_done(struct tevent_req *req)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx->reply = talloc_realloc(ctx, ctx->reply, struct sysdb_attrs *,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder reply_count * sizeof(struct sysdb_attrs *));
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers /* Search in progress */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = sdap_id_op_done(ctx->root_op, ret, &dp_error);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "No AD server is available, cannot get the "
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "subdomain list while offline\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "Failed to search the AD server: [%d](%s)\n",
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Based on whether we are connected to the forest root or not, we might
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * need to exclude the subdomain we are connected to from the list of
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ret = ad_subdomains_process(ctx, ctx->sd_ctx->be_ctx->domain,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx->root_domain_attrs, &nsubdoms, &subdoms);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, ("Cannot process subdomain list\n"));
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Got all the subdomains, let's process them */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = ad_subdomains_refresh(ctx->sd_ctx, nsubdoms, false, subdoms,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Failed to refresh subdomains.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers DEBUG(SSSDBG_TRACE_LIBS, "There are %schanges\n",
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder be_req_terminate(ctx->be_req, dp_error, ret, NULL);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic void ad_subdom_timer_refresh(struct tevent_context *ev,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maederstatic void ad_subdom_be_req_callback(struct be_req *be_req,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx = talloc_get_type(pvt, struct ad_subdomains_ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE, "Bad private pointer\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder refresh_interval = ctx->be_ctx->domain->subdomain_refresh_interval;
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder be_req = be_req_create(ctx, NULL, ctx->be_ctx, "AD subdomains",
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE, "be_req_create() failed.\n");
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers tv = tevent_timeval_current_ofs(refresh_interval, 0);
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers ctx->timer_event = tevent_add_timer(ctx->be_ctx->ev, ctx, tv,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom timer event\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx = talloc_get_type(pvt, struct ad_subdomains_ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maedervoid ad_subdomains_handler(struct be_req *be_req)
c1c5a93b6f5bf18be1f4a0a9da6c0e32ff00266cFelix Reckers struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx = talloc_get_type(be_ctx->bet_info[BET_SUBDOMAINS].pvt_bet_data,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder be_req_terminate(be_req, DP_ERR_FATAL, EINVAL, NULL);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder if (ctx->last_refreshed > now - AD_SUBDOMAIN_REFRESH_LIMIT) {
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder be_req_terminate(be_req, DP_ERR_OK, EOK, NULL);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx = talloc_zero(id_ctx, struct ad_subdomains_ctx);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ctx->domain_name = talloc_strdup(ctx, ad_domain);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = be_add_online_cb(ctx, be_ctx, ad_subdom_online_cb, ctx, NULL);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom online callback\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ret = be_add_offline_cb(ctx, be_ctx, ad_subdom_offline_cb, ctx, NULL);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom offline callback\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder err = sss_idmap_init(sss_idmap_talloc, ctx, sss_idmap_talloc_free,
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE, "Failed to initialize idmap context.\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder DEBUG(SSSDBG_MINOR_FAILURE, "Could not reinitialize subdomains. "
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder "Users from trusted domains might not be resolved correctly\n");
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* Ignore this error and try to discover the subdomains later */