ipa_subdomains.c revision e438fbf102c3d787902504bdae177e84230cbbc9
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder/*
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder SSSD
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder
97018cf5fa25b494adffd7e9b4e87320dae6bf47Christian Maeder IPA Subdomains Module
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder
b4fbc96e05117839ca409f5f20f97b3ac872d1edTill Mossakowski Authors:
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder Sumit Bose <sbose@redhat.com>
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder Copyright (C) 2011 Red Hat
f3a94a197960e548ecd6520bb768cb0d547457bbChristian Maeder
679d3f541f7a9ede4079e045f7758873bb901872Till Mossakowski This program is free software; you can redistribute it and/or modify
679d3f541f7a9ede4079e045f7758873bb901872Till Mossakowski it under the terms of the GNU General Public License as published by
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder the Free Software Foundation; either version 3 of the License, or
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder (at your option) any later version.
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder This program is distributed in the hope that it will be useful,
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski but WITHOUT ANY WARRANTY; without even the implied warranty of
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder GNU General Public License for more details.
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder You should have received a copy of the GNU General Public License
c83546084a1344bb2ef752b83d0e082823508db2Christian Maeder along with this program. If not, see <http://www.gnu.org/licenses/>.
9248af0871ebcf3796514f8d835cb5d6ca0b0398Christian Maeder*/
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder#include "providers/ldap/sdap_async.h"
f69658e57cba7ecb37c0d84181f4c563215c2534Till Mossakowski#include "providers/ldap/sdap_idmap.h"
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder#include "providers/ipa/ipa_subdomains.h"
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder#include "providers/ipa/ipa_common.h"
7bf4436b6f9987b070033a323757b206c898c1beChristian Maeder#include "providers/ipa/ipa_id.h"
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder
9603ad7198b72e812688ad7970e4eac4b553837aKlaus Luettich#include <ctype.h>
0799b5dc3f06d2640e66e9ab54b8b217348fd719Christian Maeder
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder#define SUBDOMAINS_FILTER "objectclass=ipaNTTrustedDomain"
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder#define MASTER_DOMAIN_FILTER "objectclass=ipaNTDomainAttrs"
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder#define RANGE_FILTER "objectclass=ipaIDRange"
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder
e182d0ec56025d97d74829cac75ee31eec12b093Maciek Makowski#define IPA_CN "cn"
c83546084a1344bb2ef752b83d0e082823508db2Christian Maeder#define IPA_FLATNAME "ipaNTFlatName"
9603ad7198b72e812688ad7970e4eac4b553837aKlaus Luettich#define IPA_SID "ipaNTSecurityIdentifier"
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder#define IPA_TRUSTED_DOMAIN_SID "ipaNTTrustedDomainSID"
58b671de3fe578346fef9642ffa3c5a0a0edb3cbTill Mossakowski#define IPA_RANGE_TYPE "ipaRangeType"
56cd0da55d058b262b1626ddcd78db6bd9a90551Christian Maeder
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder#define IPA_BASE_ID "ipaBaseID"
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder#define IPA_ID_RANGE_SIZE "ipaIDRangeSize"
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder#define IPA_BASE_RID "ipaBaseRID"
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder#define IPA_SECONDARY_BASE_RID "ipaSecondaryBaseRID"
c616e681da8c052b62e14247fea522da099ac0e4Christian Maeder#define OBJECTCLASS "objectClass"
43b4c41fbb07705c9df321221ab9cb9832460407Christian Maeder
43b4c41fbb07705c9df321221ab9cb9832460407Christian Maeder#define IPA_ASSIGNED_ID_VIEW "ipaAssignedIDView"
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder/* do not refresh more often than every 5 seconds for now */
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder#define IPA_SUBDOMAIN_REFRESH_LIMIT 5
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder
b0294d73dcefc502ddaa13e18b46103a5916971fTill Mossakowski#define IPA_SUBDOMAIN_DISABLED_PERIOD 3600
c83546084a1344bb2ef752b83d0e082823508db2Christian Maeder
c83546084a1344bb2ef752b83d0e082823508db2Christian Maederenum ipa_subdomains_req_type {
9248af0871ebcf3796514f8d835cb5d6ca0b0398Christian Maeder IPA_SUBDOMAINS_MASTER,
9248af0871ebcf3796514f8d835cb5d6ca0b0398Christian Maeder IPA_SUBDOMAINS_SLAVE,
9248af0871ebcf3796514f8d835cb5d6ca0b0398Christian Maeder IPA_SUBDOMAINS_RANGES,
9248af0871ebcf3796514f8d835cb5d6ca0b0398Christian Maeder
9248af0871ebcf3796514f8d835cb5d6ca0b0398Christian Maeder IPA_SUBDOMAINS_MAX /* Counter */
c83546084a1344bb2ef752b83d0e082823508db2Christian Maeder};
c83546084a1344bb2ef752b83d0e082823508db2Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maederstruct ipa_subdomains_req_params {
9248af0871ebcf3796514f8d835cb5d6ca0b0398Christian Maeder const char *filter;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder tevent_req_fn cb;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder const char *attrs[9];
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder};
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maederstruct ipa_subdomains_ctx {
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder struct be_ctx *be_ctx;
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder struct ipa_id_ctx *id_ctx;
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder struct sdap_id_ctx *sdap_id_ctx;
85211b47d269cda6a9e5b1446b99f19eae1f3c73Christian Maeder struct sdap_search_base **search_bases;
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder struct sdap_search_base **master_search_bases;
c83546084a1344bb2ef752b83d0e082823508db2Christian Maeder struct sdap_search_base **ranges_search_bases;
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski struct sdap_search_base **host_search_bases;
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski
74885352ea11b26253d453af28dc904dadc4d530Christian Maeder time_t last_refreshed;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder struct tevent_timer *timer_event;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder bool configured_explicit;
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder time_t disabled_until;
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski bool view_read_at_init;
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski};
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maederstatic void ipa_subdomains_done(struct ipa_subdomains_ctx *sd_ctx,
a1c6679d00e15a949730ab640159e0adc5b0e3e7Christian Maeder struct be_req *req, int dp_err,
a1c6679d00e15a949730ab640159e0adc5b0e3e7Christian Maeder int error, const char *errstr)
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder{
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder sd_ctx->view_read_at_init = true;
dc8100ead1e97ea34c9ff3fe4af14d37510bf8aeChristian Maeder return be_req_terminate(req, dp_err, error, errstr);
dc8100ead1e97ea34c9ff3fe4af14d37510bf8aeChristian Maeder}
dc8100ead1e97ea34c9ff3fe4af14d37510bf8aeChristian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maederstruct be_ctx *ipa_get_subdomains_be_ctx(struct be_ctx *be_ctx)
f0e85ee7e4accfc01f46aa0363acc59fcd248e8aTill Mossakowski{
f0e85ee7e4accfc01f46aa0363acc59fcd248e8aTill Mossakowski struct ipa_subdomains_ctx *subdom_ctx;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
f0e85ee7e4accfc01f46aa0363acc59fcd248e8aTill Mossakowski subdom_ctx = talloc_get_type(be_ctx->bet_info[BET_SUBDOMAINS].pvt_bet_data,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder struct ipa_subdomains_ctx);
a3bcb365497d592616a4e527b426ec210dcd385cChristian Maeder if (subdom_ctx == NULL) {
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder DEBUG(SSSDBG_TRACE_ALL, "Subdomains are not configured.\n");
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder return NULL;
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder }
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder return subdom_ctx->be_ctx;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder}
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maederstatic errno_t
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maederipa_ad_ctx_new(struct be_ctx *be_ctx,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder struct ipa_id_ctx *id_ctx,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder struct sss_domain_info *subdom,
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder struct ad_id_ctx **_ad_id_ctx)
a3bcb365497d592616a4e527b426ec210dcd385cChristian Maeder{
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder struct ad_options *ad_options;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder struct ad_id_ctx *ad_id_ctx;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder const char *gc_service_name;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder struct ad_srv_plugin_ctx *srv_ctx;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder char *ad_domain;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder const char *ad_site_override;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder struct sdap_domain *sdom;
a3bcb365497d592616a4e527b426ec210dcd385cChristian Maeder errno_t ret;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder const char *extra_attrs;
15bceb77af626f79747d46d35979640f229a4c71Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder ad_options = ad_create_default_options(id_ctx, id_ctx->server_mode->realm,
15bceb77af626f79747d46d35979640f229a4c71Christian Maeder id_ctx->server_mode->hostname);
15bceb77af626f79747d46d35979640f229a4c71Christian Maeder if (ad_options == NULL) {
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n");
0ea2cddb8715a770e646895e16b7b8085f49167cChristian Maeder talloc_free(ad_options);
b83ff3749d99d03b641adee264b781039a551addChristian Maeder return ENOMEM;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder }
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski ad_domain = subdom->name;
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder ret = dp_opt_set_string(ad_options->basic, AD_DOMAIN, ad_domain);
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder if (ret != EOK) {
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot set AD domain\n");
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder talloc_free(ad_options);
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder return ret;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder }
42972ddff400840d46eb54422b60083228b2996cChristian Maeder
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder ret = dp_opt_set_string(ad_options->basic, AD_KRB5_REALM,
42972ddff400840d46eb54422b60083228b2996cChristian Maeder id_ctx->server_mode->realm);
99aecbb3a3f935dd4663a45760a703faabdd04fbChristian Maeder if (ret != EOK) {
99aecbb3a3f935dd4663a45760a703faabdd04fbChristian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot set AD realm\n");
cd84b488be8f6fbb674c28b8403279f13f6df015Christian Maeder talloc_free(ad_options);
42972ddff400840d46eb54422b60083228b2996cChristian Maeder return ret;
42972ddff400840d46eb54422b60083228b2996cChristian Maeder }
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder extra_attrs = dp_opt_get_string(id_ctx->sdap_id_ctx->opts->basic,
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder SDAP_USER_EXTRA_ATTRS);
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder if (extra_attrs != NULL) {
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder DEBUG(SSSDBG_TRACE_ALL,
dc8100ead1e97ea34c9ff3fe4af14d37510bf8aeChristian Maeder "Setting extra attrs for subdomain [%s] to [%s].\n", ad_domain,
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder extra_attrs);
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder ret = dp_opt_set_string(ad_options->id->basic, SDAP_USER_EXTRA_ATTRS,
a081d56252673c9e4a017e6282f59766f0cbcd42Christian Maeder extra_attrs);
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder if (ret != EOK) {
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder DEBUG(SSSDBG_OP_FAILURE, "dp_opt_get_string failed.\n");
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder talloc_free(ad_options);
74885352ea11b26253d453af28dc904dadc4d530Christian Maeder return ret;
b83ff3749d99d03b641adee264b781039a551addChristian Maeder }
b83ff3749d99d03b641adee264b781039a551addChristian Maeder
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder ret = sdap_extend_map_with_list(ad_options->id, ad_options->id,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder SDAP_USER_EXTRA_ATTRS,
f1d04fe5072b827d9cc490ebdbca78108241a392Christian Maeder ad_options->id->user_map,
f1d04fe5072b827d9cc490ebdbca78108241a392Christian Maeder SDAP_OPTS_USER,
f1d04fe5072b827d9cc490ebdbca78108241a392Christian Maeder &ad_options->id->user_map,
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder &ad_options->id->user_map_cnt);
f1d04fe5072b827d9cc490ebdbca78108241a392Christian Maeder if (ret != EOK) {
f1d04fe5072b827d9cc490ebdbca78108241a392Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sdap_extend_map_with_list failed.\n");
f1d04fe5072b827d9cc490ebdbca78108241a392Christian Maeder talloc_free(ad_options);
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder return ret;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder }
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder } else {
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder DEBUG(SSSDBG_TRACE_ALL, "No extra attrs set.\n");
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder }
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder
26ed2a19326560786ff94dfc462309d6d5d862a8Heng Jiang gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski if (gc_service_name == NULL) {
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski talloc_free(ad_options);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski return ENOMEM;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder }
15bceb77af626f79747d46d35979640f229a4c71Christian Maeder
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski /* Set KRB5 realm to same as the one of IPA when IPA
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski * is able to attach PAC. For testing, use hardcoded. */
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder ret = ad_failover_init(ad_options, be_ctx, NULL, NULL,
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski id_ctx->server_mode->realm,
503e836b34d3abed34520eb4a0a345b5e13f248dTill Mossakowski subdom->name, gc_service_name,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder subdom->name, &ad_options->service);
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder if (ret != EOK) {
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n");
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder talloc_free(ad_options);
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski return ret;
ff49754b0e0b7ca133a66ce6c0b240c55128cde1Heng Jiang }
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder ad_id_ctx = ad_id_ctx_init(ad_options, be_ctx);
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski if (ad_id_ctx == NULL) {
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski talloc_free(ad_options);
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder return ENOMEM;
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski }
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder ad_id_ctx->sdap_id_ctx->opts = ad_options->id;
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski ad_options->id_ctx = ad_id_ctx;
ff49754b0e0b7ca133a66ce6c0b240c55128cde1Heng Jiang
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder ad_site_override = dp_opt_get_string(ad_options->basic, AD_SITE);
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
8db14bfdbfec2f153de435718d748fe5e22fd634Heng Jiang /* use AD plugin */
ff49754b0e0b7ca133a66ce6c0b240c55128cde1Heng Jiang srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx->be_res,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder default_host_dbs,
26ed2a19326560786ff94dfc462309d6d5d862a8Heng Jiang ad_id_ctx->ad_options->id,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder id_ctx->server_mode->hostname,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder ad_domain,
26ed2a19326560786ff94dfc462309d6d5d862a8Heng Jiang ad_site_override);
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder if (srv_ctx == NULL) {
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder return ENOMEM;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder }
26ed2a19326560786ff94dfc462309d6d5d862a8Heng Jiang be_fo_set_srv_lookup_plugin(be_ctx, ad_srv_plugin_send,
26ed2a19326560786ff94dfc462309d6d5d862a8Heng Jiang ad_srv_plugin_recv, srv_ctx, "AD");
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder ret = sdap_domain_subdom_add(ad_id_ctx->sdap_id_ctx,
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder ad_id_ctx->sdap_id_ctx->opts->sdom,
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder subdom->parent);
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder if (ret != EOK) {
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize sdap domain\n");
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder talloc_free(ad_options);
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder return ret;
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder }
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder sdom = sdap_domain_get(ad_id_ctx->sdap_id_ctx->opts, subdom);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski if (sdom == NULL) {
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder return EFAULT;
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder }
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder ret = sdap_id_setup_tasks(be_ctx,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder ad_id_ctx->sdap_id_ctx,
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder sdom,
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder ldap_enumeration_send,
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder ldap_enumeration_recv,
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder ad_id_ctx->sdap_id_ctx);
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder if (ret != EOK) {
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder talloc_free(ad_options);
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder return ret;
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski }
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski sdom->pvt = ad_id_ctx;
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski /* Set up the ID mapping object */
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder ad_id_ctx->sdap_id_ctx->opts->idmap_ctx =
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder id_ctx->sdap_id_ctx->opts->idmap_ctx;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski *_ad_id_ctx = ad_id_ctx;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder return EOK;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder}
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maederstatic errno_t
f1d04fe5072b827d9cc490ebdbca78108241a392Christian Maederipa_server_trust_add(struct be_ctx *be_ctx,
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder struct ipa_id_ctx *id_ctx,
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder struct sss_domain_info *subdom)
db7143998eee23e3d781f1f1e97e953bb831df1fTill Mossakowski{
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski struct ipa_ad_server_ctx *trust_ctx;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder struct ad_id_ctx *ad_id_ctx;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder errno_t ret;
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder ret = ipa_ad_ctx_new(be_ctx, id_ctx, subdom, &ad_id_ctx);
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder if (ret != EOK) {
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski DEBUG(SSSDBG_OP_FAILURE,
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder "Cannot create ad_id_ctx for subdomain %s\n", subdom->name);
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder return ret;
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder }
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski trust_ctx = talloc(id_ctx->server_mode, struct ipa_ad_server_ctx);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski if (trust_ctx == NULL) {
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder return ENOMEM;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder }
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski trust_ctx->dom = subdom;
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski trust_ctx->ad_id_ctx = ad_id_ctx;
e182d0ec56025d97d74829cac75ee31eec12b093Maciek Makowski
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder DLIST_ADD(id_ctx->server_mode->trusts, trust_ctx);
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder return EOK;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder}
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maederstatic errno_t
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maederipa_ad_subdom_refresh(struct be_ctx *be_ctx,
320198216ed3bde106b509c4024b857ce4345880Maciek Makowski struct ipa_id_ctx *id_ctx,
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder struct sss_domain_info *parent)
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder{
e182d0ec56025d97d74829cac75ee31eec12b093Maciek Makowski struct sss_domain_info *dom;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder struct ipa_ad_server_ctx *trust_iter;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder errno_t ret;
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder
e182d0ec56025d97d74829cac75ee31eec12b093Maciek Makowski if (dp_opt_get_bool(id_ctx->ipa_options->basic,
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder IPA_SERVER_MODE) == false) {
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder return EOK;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder }
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
e182d0ec56025d97d74829cac75ee31eec12b093Maciek Makowski for (dom = get_next_domain(parent, true);
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
503e836b34d3abed34520eb4a0a345b5e13f248dTill Mossakowski dom = get_next_domain(dom, false)) {
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder /* Check if we already have an ID context for this subdomain */
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder DLIST_FOR_EACH(trust_iter, id_ctx->server_mode->trusts) {
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder if (trust_iter->dom == dom) {
e182d0ec56025d97d74829cac75ee31eec12b093Maciek Makowski break;
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder }
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder }
e182d0ec56025d97d74829cac75ee31eec12b093Maciek Makowski
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder /* Newly detected trust */
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder if (trust_iter == NULL) {
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder ret = ipa_server_trust_add(be_ctx, id_ctx, dom);
e182d0ec56025d97d74829cac75ee31eec12b093Maciek Makowski if (ret != EOK) {
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder DEBUG(SSSDBG_OP_FAILURE,
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder "Cannot create ad_id_ctx for subdomain %s\n",
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder dom->name);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski continue;
b4b6cffb6746d672e2bb558b72f616f97ac98316Till Mossakowski }
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder }
a3bcb365497d592616a4e527b426ec210dcd385cChristian Maeder }
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder return EOK;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder}
b4b6cffb6746d672e2bb558b72f616f97ac98316Till Mossakowski
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maederstatic errno_t
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maederipa_subdom_reinit(struct ipa_subdomains_ctx *ctx)
b4b6cffb6746d672e2bb558b72f616f97ac98316Till Mossakowski{
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder errno_t ret;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder ret = sss_write_krb5_conf_snippet(
b4b6cffb6746d672e2bb558b72f616f97ac98316Till Mossakowski dp_opt_get_string(ctx->id_ctx->ipa_options->basic,
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder IPA_KRB5_CONFD_PATH));
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder if (ret != EOK) {
b4b6cffb6746d672e2bb558b72f616f97ac98316Till Mossakowski DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
b4b6cffb6746d672e2bb558b72f616f97ac98316Till Mossakowski /* Just continue */
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder }
0e4b70274950d17f45c85d124bc600921e70fd87Christian Maeder
0e4b70274950d17f45c85d124bc600921e70fd87Christian Maeder ret = sysdb_update_subdomains(ctx->be_ctx->domain);
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder if (ret != EOK) {
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski return ret;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder }
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder ret = sss_write_domain_mappings(ctx->be_ctx->domain);
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder if (ret != EOK) {
a3bcb365497d592616a4e527b426ec210dcd385cChristian Maeder DEBUG(SSSDBG_MINOR_FAILURE,
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder "sss_krb5_write_mappings failed.\n");
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder /* Just continue */
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder }
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder return EOK;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder}
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maederstatic void
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maederipa_ad_subdom_remove(struct ipa_subdomains_ctx *ctx,
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder struct sss_domain_info *subdom)
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder{
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder struct ipa_ad_server_ctx *iter;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder struct sdap_domain *sdom;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder if (dp_opt_get_bool(ctx->id_ctx->ipa_options->basic,
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder IPA_SERVER_MODE) == false) {
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski return;
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski }
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder DLIST_FOR_EACH(iter, ctx->id_ctx->server_mode->trusts) {
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski if (iter->dom == subdom) break;
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder }
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski if (iter == NULL) {
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder DEBUG(SSSDBG_CRIT_FAILURE, "No IPA-AD context for subdomain %s\n",
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder subdom->name);
db7143998eee23e3d781f1f1e97e953bb831df1fTill Mossakowski return;
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder }
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder sdom = sdap_domain_get(iter->ad_id_ctx->sdap_id_ctx->opts, subdom);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski if (sdom == NULL) return;
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski be_ptask_destroy(&sdom->enum_task);
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder be_ptask_destroy(&sdom->cleanup_task);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski sdap_domain_remove(iter->ad_id_ctx->sdap_id_ctx->opts, subdom);
587fb54160b66128cf17e4c9bca7494a7f2c3c4aChristian Maeder DLIST_REMOVE(ctx->id_ctx->server_mode->trusts, iter);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski
7bf4436b6f9987b070033a323757b206c898c1beChristian Maeder /* terminate all requests for this subdomain so we can free it */
7bf4436b6f9987b070033a323757b206c898c1beChristian Maeder be_terminate_domain_requests(ctx->be_ctx, subdom->name);
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder talloc_zfree(sdom);
bfa9e03532243ceb487f0384d0f6a447f1ce7670Till Mossakowski}
58b671de3fe578346fef9642ffa3c5a0a0edb3cbTill Mossakowski
58b671de3fe578346fef9642ffa3c5a0a0edb3cbTill Mossakowskiconst char *get_flat_name_from_subdomain_name(struct be_ctx *be_ctx,
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder const char *name)
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder{
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder struct ipa_subdomains_ctx *ctx;
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski struct sss_domain_info *dom;
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski
4ea99e115bbade1632815267d5e0dcb9931aac1eChristian Maeder ctx = talloc_get_type(be_ctx->bet_info[BET_SUBDOMAINS].pvt_bet_data,
4ea99e115bbade1632815267d5e0dcb9931aac1eChristian Maeder struct ipa_subdomains_ctx);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski if (ctx == NULL) {
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder DEBUG(SSSDBG_TRACE_ALL, "Subdomains are not configured.\n");
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder return NULL;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder }
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder dom = find_domain_by_name(ctx->be_ctx->domain, name, true);
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder if (dom) {
e379124f467e5d0ef7d3c0ca238bff0521f70831Till Mossakowski return dom->flat_name;
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder }
c3a264bbb3692f9b44024c6024382e3ed6590688Christian Maeder
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder return NULL;
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder}
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maederstatic errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx,
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder char *domain_name,
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder size_t count,
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder struct sysdb_attrs **reply,
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder struct range_info ***_range_list)
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder{
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder struct range_info **range_list = NULL;
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder struct range_info *r;
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder const char *value;
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder size_t c;
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski size_t d;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder int ret;
c616e681da8c052b62e14247fea522da099ac0e4Christian Maeder enum idmap_error_code err;
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder char *name1;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder char *name2;
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder char *sid1;
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder char *sid2;
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski uint32_t rid1;
c616e681da8c052b62e14247fea522da099ac0e4Christian Maeder uint32_t rid2;
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder struct sss_idmap_range range1;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder struct sss_idmap_range range2;
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski bool mapping1;
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski bool mapping2;
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder range_list = talloc_array(mem_ctx, struct range_info *, count + 1);
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder if (range_list == NULL) {
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder return ENOMEM;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder }
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder
aebf36d7483e5c012eff154d0b76de400d8fe3fcTill Mossakowski for (c = 0; c < count; c++) {
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder r = talloc_zero(range_list, struct range_info);
aebf36d7483e5c012eff154d0b76de400d8fe3fcTill Mossakowski if (r == NULL) {
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
18902cdbb4cbcdaaeff6c0dd23c110ff2067a0bdJorina Freya Gerken ret = ENOMEM;
aebf36d7483e5c012eff154d0b76de400d8fe3fcTill Mossakowski goto done;
e953bea49e7f0e1a43bccf2a66c5e2a2b50848e0Christian Maeder }
e953bea49e7f0e1a43bccf2a66c5e2a2b50848e0Christian Maeder
e953bea49e7f0e1a43bccf2a66c5e2a2b50848e0Christian Maeder ret = sysdb_attrs_get_string(reply[c], IPA_CN, &value);
0799b5dc3f06d2640e66e9ab54b8b217348fd719Christian Maeder if (ret != EOK) {
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder goto done;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder }
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder r->name = talloc_strdup(r, value);
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder if (r->name == NULL) {
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder ret = ENOMEM;
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder goto done;
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder }
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder ret = sysdb_attrs_get_string(reply[c], IPA_TRUSTED_DOMAIN_SID, &value);
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder if (ret == EOK) {
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder r->trusted_dom_sid = talloc_strdup(r, value);
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder if (r->trusted_dom_sid == NULL) {
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder ret = ENOMEM;
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder goto done;
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder }
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder } else if (ret != ENOENT) {
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder goto done;
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski }
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_ID,
f69658e57cba7ecb37c0d84181f4c563215c2534Till Mossakowski &r->base_id);
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
ret = sysdb_attrs_get_uint32_t(reply[c], IPA_ID_RANGE_SIZE,
&r->id_range_size);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_RID,
&r->base_rid);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
ret = sysdb_attrs_get_uint32_t(reply[c], IPA_SECONDARY_BASE_RID,
&r->secondary_base_rid);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
ret = sysdb_attrs_get_string(reply[c], IPA_RANGE_TYPE, &value);
if (ret == EOK) {
r->range_type = talloc_strdup(r, value);
if (r->range_type == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
ret = ENOMEM;
goto done;
}
} else if (ret == ENOENT) {
/* Older IPA servers might not have the range_type attribute, but
* only support local ranges and trusts with algorithmic mapping. */
if (r->trusted_dom_sid == NULL) {
r->range_type = talloc_strdup(r, IPA_RANGE_LOCAL);
} else {
r->range_type = talloc_strdup(r, IPA_RANGE_AD_TRUST);
}
} else {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
if (r->range_type == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
ret = ENOMEM;
goto done;
}
ret = get_idmap_data_from_range(r, domain_name, &name1, &sid1, &rid1,
&range1, &mapping1);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("get_idmap_data_from_range failed.\n"));
goto done;
}
for (d = 0; d < c; d++) {
ret = get_idmap_data_from_range(range_list[d], domain_name, &name2,
&sid2, &rid2, &range2, &mapping2);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
("get_idmap_data_from_range failed.\n"));
goto done;
}
err = sss_idmap_check_collision_ex(name1, sid1, &range1, rid1,
r->name, mapping1,
name2, sid2, &range2, rid2,
range_list[d]->name, mapping2);
if (err != IDMAP_SUCCESS) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Collision of ranges [%s] and [%s] detected.\n",
r->name, range_list[d]->name);
ret = EINVAL;
goto done;
}
}
range_list[c] = r;
}
range_list[c] = NULL;
*_range_list = range_list;
ret = EOK;
done:
if (ret != EOK) {
talloc_free(range_list);
}
return ret;
}
static errno_t ipa_subdom_enumerates(struct sss_domain_info *parent,
struct sysdb_attrs *attrs,
bool *_enumerates)
{
errno_t ret;
const char *name;
ret = sysdb_attrs_get_string(attrs, IPA_CN, &name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
return ret;
}
*_enumerates = subdomain_enumerates(parent, name);
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;
}
DEBUG(SSSDBG_TRACE_ALL, "Checking if we need the forest name for [%s].\n",
orig_dn);
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. In IPA the
* forest root object is stored as e.g.
* cn=AD.DOM,cn=ad,cn=trusts,dc=example,dc=com. Member domains in the
* forest are children of the forest root object e.g.
* cn=SUB.AD.DOM,cn=AD.DOM,cn=ad,cn=trusts,dc=example,dc=com. Since
* the forest name is not stored in the member objects we derive it
* from the RDN of the forest root object. */
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,
bool enumerate)
{
TALLOC_CTX *tmp_ctx;
const char *name;
char *realm;
const char *flat;
const char *id;
char *forest = NULL;
int ret;
bool mpg;
tmp_ctx = talloc_new(parent);
if (tmp_ctx == NULL) {
return ENOMEM;
}
ret = sysdb_attrs_get_string(attrs, IPA_CN, &name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
realm = get_uppercase_realm(tmp_ctx, name);
if (!realm) {
ret = ENOMEM;
goto done;
}
ret = sysdb_attrs_get_string(attrs, IPA_FLATNAME, &flat);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
ret = sysdb_attrs_get_string(attrs, IPA_TRUSTED_DOMAIN_SID, &id);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
mpg = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx, name, 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, forest);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n");
goto done;
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
static errno_t ipa_subdomains_refresh(struct ipa_subdomains_ctx *ctx,
int count, struct sysdb_attrs **reply,
bool *changes)
{
struct sss_domain_info *parent, *dom;
bool handled[count];
const char *value;
int c, h;
int ret;
bool enumerate;
parent = ctx->be_ctx->domain;
memset(handled, 0, sizeof(bool) * count);
h = 0;
/* check existing subdomains */
for (dom = get_next_domain(parent, true);
dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
dom = get_next_domain(dom, false)) {
for (c = 0; c < count; c++) {
if (handled[c]) {
continue;
}
ret = sysdb_attrs_get_string(reply[c], IPA_CN, &value);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
if (strcmp(value, dom->name) == 0) {
break;
}
}
if (c >= count) {
/* ok this subdomain does not exist anymore, let's clean up */
dom->disabled = true;
ret = sysdb_subdomain_delete(dom->sysdb, dom->name);
if (ret != EOK) {
goto done;
}
/* Remove the AD ID ctx from the list of LDAP domains */
ipa_ad_subdom_remove(ctx, dom);
} else {
/* ok let's try to update it */
ret = ipa_subdom_enumerates(parent, reply[c], &enumerate);
if (ret != EOK) {
goto done;
}
ret = ipa_subdom_store(parent, ctx->sdap_id_ctx->opts->idmap_ctx,
reply[c], enumerate);
if (ret) {
/* Nothing we can do about the errorr. Let's at least try
* to reuse the existing domain
*/
DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
"will try to use cached subdomain\n");
}
handled[c] = true;
h++;
}
}
if (count == h) {
/* all domains were already accounted for and have been updated */
ret = EOK;
goto done;
}
/* if we get here it means we have changes to the subdomains list */
*changes = true;
for (c = 0; c < count; c++) {
if (handled[c]) {
continue;
}
/* Nothing we can do about the errorr. Let's at least try
* to reuse the existing domain.
*/
ret = ipa_subdom_enumerates(parent, reply[c], &enumerate);
if (ret != EOK) {
goto done;
}
ret = ipa_subdom_store(parent, ctx->sdap_id_ctx->opts->idmap_ctx,
reply[c], enumerate);
if (ret) {
DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
"will try to use cached subdomain\n");
}
}
ret = EOK;
done:
if (ret != EOK) {
ctx->last_refreshed = 0;
} else {
ctx->last_refreshed = time(NULL);
}
return ret;
}
struct ipa_subdomains_req_ctx {
struct be_req *be_req;
struct ipa_subdomains_ctx *sd_ctx;
struct sdap_id_op *sdap_op;
char *current_filter;
struct sdap_search_base **search_bases;
int search_base_iter;
size_t reply_count;
struct sysdb_attrs **reply;
};
static void ipa_subdomains_get_conn_done(struct tevent_req *req);
static errno_t
ipa_subdomains_handler_get(struct ipa_subdomains_req_ctx *ctx,
enum ipa_subdomains_req_type type);
static void ipa_subdomains_handler_done(struct tevent_req *req);
static void ipa_subdomains_handler_master_done(struct tevent_req *req);
static void ipa_subdomains_handler_ranges_done(struct tevent_req *req);
static struct ipa_subdomains_req_params subdomain_requests[] = {
{ MASTER_DOMAIN_FILTER,
ipa_subdomains_handler_master_done,
{ IPA_CN, IPA_FLATNAME, IPA_SID, NULL }
},
{ SUBDOMAINS_FILTER,
ipa_subdomains_handler_done,
{ IPA_CN, IPA_FLATNAME, IPA_TRUSTED_DOMAIN_SID, NULL }
},
{ RANGE_FILTER,
ipa_subdomains_handler_ranges_done,
{ OBJECTCLASS, IPA_CN,
IPA_BASE_ID, IPA_BASE_RID, IPA_SECONDARY_BASE_RID,
IPA_ID_RANGE_SIZE, IPA_TRUSTED_DOMAIN_SID, IPA_RANGE_TYPE, NULL
}
}
};
static void ipa_subdomains_retrieve(struct ipa_subdomains_ctx *ctx, struct be_req *be_req)
{
struct ipa_subdomains_req_ctx *req_ctx = NULL;
struct tevent_req *req;
int dp_error = DP_ERR_FATAL;
int ret;
req_ctx = talloc(be_req, struct ipa_subdomains_req_ctx);
if (req_ctx == NULL) {
ret = ENOMEM;
goto done;
}
req_ctx->be_req = be_req;
req_ctx->sd_ctx = ctx;
req_ctx->search_base_iter = 0;
req_ctx->search_bases = ctx->ranges_search_bases;
req_ctx->current_filter = NULL;
req_ctx->reply_count = 0;
req_ctx->reply = NULL;
req_ctx->sdap_op = sdap_id_op_create(req_ctx,
ctx->sdap_id_ctx->conn->conn_cache);
if (req_ctx->sdap_op == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n");
ret = ENOMEM;
goto done;
}
req = sdap_id_op_connect_send(req_ctx->sdap_op, req_ctx, &ret);
if (req == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n",
ret, strerror(ret));
goto done;
}
tevent_req_set_callback(req, ipa_subdomains_get_conn_done, req_ctx);
return;
done:
talloc_free(req_ctx);
if (ret == EOK) {
dp_error = DP_ERR_OK;
}
ipa_subdomains_done(ctx, be_req, dp_error, ret, NULL);
}
static void ipa_subdomains_get_conn_done(struct tevent_req *req)
{
int ret;
int dp_error = DP_ERR_FATAL;
struct ipa_subdomains_req_ctx *ctx;
ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx);
ret = sdap_id_op_connect_recv(req, &dp_error);
talloc_zfree(req);
if (ret) {
if (dp_error == DP_ERR_OFFLINE) {
DEBUG(SSSDBG_MINOR_FAILURE,
"No IPA server is available, cannot get the "
"subdomain list while offline\n");
} else {
DEBUG(SSSDBG_OP_FAILURE,
"Failed to connect to IPA server: [%d](%s)\n",
ret, strerror(ret));
}
goto fail;
}
ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_RANGES);
if (ret != EOK && ret != EAGAIN) {
goto fail;
}
return;
fail:
ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
}
static errno_t
ipa_subdomains_handler_get(struct ipa_subdomains_req_ctx *ctx,
enum ipa_subdomains_req_type type)
{
struct tevent_req *req;
struct sdap_search_base *base;
struct ipa_subdomains_req_params *params;
if (type >= IPA_SUBDOMAINS_MAX) {
return EINVAL;
}
params = &subdomain_requests[type];
base = ctx->search_bases[ctx->search_base_iter];
if (base == NULL) {
return EOK;
}
talloc_free(ctx->current_filter);
ctx->current_filter = sdap_get_id_specific_filter(ctx, params->filter,
base->filter);
if (ctx->current_filter == NULL) {
return ENOMEM;
}
req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
ctx->sd_ctx->sdap_id_ctx->opts,
sdap_id_op_handle(ctx->sdap_op),
base->basedn, base->scope,
ctx->current_filter, params->attrs, NULL, 0,
dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic,
SDAP_SEARCH_TIMEOUT), false);
if (req == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
return ENOMEM;
}
tevent_req_set_callback(req, params->cb, ctx);
return EAGAIN;
}
static void ipa_get_view_name_done(struct tevent_req *req);
static errno_t ipa_check_master(struct ipa_subdomains_req_ctx *ctx);
static errno_t ipa_get_view_name(struct ipa_subdomains_req_ctx *ctx)
{
struct tevent_req *req;
struct sdap_search_base *base;
const char *attrs[] = {IPA_CN, OBJECTCLASS, NULL};
struct sdap_attr_map_info *maps;
maps = talloc_zero(ctx, struct sdap_attr_map_info);
if (maps == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
return ENOMEM;
}
maps->map = ctx->sd_ctx->id_ctx->ipa_options->view_map;
maps->num_attrs = IPA_OPTS_VIEW;
base = ctx->search_bases[ctx->search_base_iter];
if (base == NULL) {
return EOK;
}
req = sdap_deref_search_with_filter_send(ctx, ctx->sd_ctx->be_ctx->ev,
ctx->sd_ctx->sdap_id_ctx->opts,
sdap_id_op_handle(ctx->sdap_op),
base->basedn,
ctx->current_filter, IPA_ASSIGNED_ID_VIEW, attrs,
1, maps,
dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic,
SDAP_SEARCH_TIMEOUT));
if (req == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
return ENOMEM;
}
tevent_req_set_callback(req, ipa_get_view_name_done, ctx);
return EAGAIN;
}
static void ipa_get_view_name_done(struct tevent_req *req)
{
int ret;
int sret;
struct ipa_subdomains_req_ctx *ctx;
size_t reply_count;
struct sdap_deref_attrs **reply = NULL;
const char *view_name;
int dp_error = DP_ERR_FATAL;
ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx);
ret = sdap_deref_search_with_filter_recv(req, ctx, &reply_count, &reply);
talloc_zfree(req);
if (ret != EOK) {
if (ret == EOPNOTSUPP) {
DEBUG(SSSDBG_TRACE_FUNC, "get_view_name request failed, looks " \
"like server does not support views.\n");
ret = ipa_check_master(ctx);
if (ret == EAGAIN) {
return;
} else if (ret != EOK) {
goto done;
}
} else {
DEBUG(SSSDBG_OP_FAILURE, "get_view_name request failed.\n");
}
goto done;
}
if (reply_count == 0) {
ctx->search_base_iter++;
ret = ipa_get_view_name(ctx);
if (ret == EAGAIN) {
return;
} else if (ret == EOK) {
DEBUG(SSSDBG_TRACE_FUNC, "No view found, using default.\n");
view_name = SYSDB_DEFAULT_VIEW_NAME;
} else {
goto done;
}
} else if (reply_count > 1) {
DEBUG(SSSDBG_CRIT_FAILURE,
"get_view_name request returned more than one object.\n");
ret = EINVAL;
goto done;
} else {
ret = sysdb_attrs_get_string(reply[0]->attrs, SYSDB_VIEW_NAME,
&view_name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
}
DEBUG(SSSDBG_TRACE_FUNC, "Found view name [%s].\n", view_name);
if (strcmp(view_name, IPA_DEFAULT_VIEW_NAME) == 0) {
DEBUG(SSSDBG_TRACE_ALL,
"Found IPA default view name, replacing with sysdb default.\n");
view_name = SYSDB_DEFAULT_VIEW_NAME;
}
DEBUG(SSSDBG_TRACE_ALL, "read_at_init [%s] current view [%s].\n",
ctx->sd_ctx->view_read_at_init ? "true" : "false",
ctx->sd_ctx->id_ctx->view_name);
if (ctx->sd_ctx->id_ctx->view_name != NULL
&& strcmp(ctx->sd_ctx->id_ctx->view_name, view_name) != 0
&& ctx->sd_ctx->view_read_at_init) {
DEBUG(SSSDBG_CRIT_FAILURE,
"View name changed, this is not supported at runtime. " \
"Please restart SSSD to get the new view applied.\n");
} else {
if (ctx->sd_ctx->id_ctx->view_name == NULL
|| strcmp(ctx->sd_ctx->id_ctx->view_name, view_name) != 0) {
/* View name changed */
if (ctx->sd_ctx->id_ctx->view_name != NULL) {
ret = sysdb_transaction_start(
ctx->sd_ctx->be_ctx->domain->sysdb);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_transaction_start failed.\n");
goto done;
}
if (strcmp(ctx->sd_ctx->id_ctx->view_name,
SYSDB_DEFAULT_VIEW_NAME) != 0) {
/* Old view was not the default view, delete view tree */
ret = sysdb_delete_view_tree(
ctx->sd_ctx->be_ctx->domain->sysdb,
ctx->sd_ctx->id_ctx->view_name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_delete_view_tree failed.\n");
sret = sysdb_transaction_cancel(
ctx->sd_ctx->be_ctx->domain->sysdb);
if (sret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_transaction_cancel failed.\n");
goto done;
}
goto done;
}
}
ret = sysdb_invalidate_overrides(
ctx->sd_ctx->be_ctx->domain->sysdb);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_invalidate_overrides failed.\n");
sret = sysdb_transaction_cancel(
ctx->sd_ctx->be_ctx->domain->sysdb);
if (sret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_transaction_cancel failed.\n");
goto done;
}
goto done;
}
ret = sysdb_transaction_commit(
ctx->sd_ctx->be_ctx->domain->sysdb);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_transaction_commit failed.\n");
goto done;
}
/* TODO: start referesh task */
}
ret = sysdb_update_view_name(ctx->sd_ctx->be_ctx->domain->sysdb,
view_name);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Cannot add/update view name to sysdb.\n");
} else {
talloc_free(ctx->sd_ctx->id_ctx->view_name);
ctx->sd_ctx->id_ctx->view_name = talloc_strdup(
ctx->sd_ctx->id_ctx,
view_name);
if (ctx->sd_ctx->id_ctx->view_name == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot copy view name.\n");
}
}
}
if (!ctx->sd_ctx->view_read_at_init) {
/* refresh view data of all domains at startup */
ret = sysdb_master_domain_update(ctx->sd_ctx->be_ctx->domain);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_master_domain_update failed.\n");
goto done;
}
ret = sysdb_update_subdomains(ctx->sd_ctx->be_ctx->domain);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
goto done;
}
}
ctx->sd_ctx->view_read_at_init = true;
}
ret = ipa_check_master(ctx);
if (ret == EAGAIN) {
return;
} else if (ret != EOK) {
goto done;
}
done:
if (ret == EOK) {
dp_error = DP_ERR_OK;
}
ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
}
static void ipa_subdomains_handler_done(struct tevent_req *req)
{
int ret;
size_t reply_count;
struct sysdb_attrs **reply = NULL;
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;
ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
talloc_zfree(req);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
goto done;
}
if (reply_count) {
ctx->reply = talloc_realloc(ctx, ctx->reply, struct sysdb_attrs *,
ctx->reply_count + reply_count);
if (ctx->reply == NULL) {
ret = ENOMEM;
goto done;
}
memcpy(ctx->reply+ctx->reply_count, reply,
reply_count * sizeof(struct sysdb_attrs *));
ctx->reply_count += reply_count;
}
ctx->search_base_iter++;
ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_SLAVE);
if (ret == EAGAIN) {
return;
} else if (ret != EOK) {
goto done;
}
ret = ipa_subdomains_refresh(ctx->sd_ctx, ctx->reply_count, ctx->reply,
&refresh_has_changes);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Failed to refresh subdomains.\n");
goto done;
}
if (refresh_has_changes) {
ret = ipa_subdom_reinit(ctx->sd_ctx);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
goto done;
}
ret = ipa_ad_subdom_refresh(ctx->sd_ctx->be_ctx, ctx->sd_ctx->id_ctx,
domain);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ipa_ad_subdom_refresh failed.\n");
goto done;
}
}
ctx->search_base_iter = 0;
ctx->search_bases = ctx->sd_ctx->host_search_bases;
talloc_zfree(ctx->current_filter);
ctx->current_filter = talloc_asprintf(ctx, "(&(objectClass=%s)(%s=%s))",
ctx->sd_ctx->id_ctx->ipa_options->host_map[IPA_OC_HOST].name,
ctx->sd_ctx->id_ctx->ipa_options->host_map[IPA_AT_HOST_FQDN].name,
dp_opt_get_string(ctx->sd_ctx->id_ctx->ipa_options->basic,
IPA_HOSTNAME));
if (ctx->current_filter == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
ret = ENOMEM;
goto done;
}
if (ctx->sd_ctx->id_ctx->server_mode == NULL) {
/* Only get view on clients, on servers it is always 'default' */
ret = ipa_get_view_name(ctx);
if (ret == EAGAIN) {
return;
} else if (ret != EOK) {
goto done;
}
}
ret = ipa_check_master(ctx);
if (ret == EAGAIN) {
return;
} else if (ret != EOK) {
goto done;
}
done:
if (ret == EOK) {
dp_error = DP_ERR_OK;
}
ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
}
static errno_t ipa_check_master(struct ipa_subdomains_req_ctx *ctx)
{
int ret;
struct sss_domain_info *domain;
domain = ctx->sd_ctx->be_ctx->domain;
ret = sysdb_master_domain_update(domain);
if (ret != EOK) {
return ret;
}
if (domain->flat_name == NULL ||
domain->domain_id == NULL ||
domain->realm == NULL) {
ctx->search_base_iter = 0;
ctx->search_bases = ctx->sd_ctx->master_search_bases;
ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_MASTER);
if (ret == EAGAIN) {
return EAGAIN;
} else if (ret != EOK) {
return ret;
}
}
return EOK;
}
static void ipa_subdomains_handler_ranges_done(struct tevent_req *req)
{
errno_t ret;
int dp_error = DP_ERR_FATAL;
size_t reply_count;
struct sysdb_attrs **reply = NULL;
struct ipa_subdomains_req_ctx *ctx;
struct range_info **range_list = NULL;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx);
domain = ctx->sd_ctx->be_ctx->domain;
sysdb = domain->sysdb;
ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
talloc_zfree(req);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
goto done;
}
ret = ipa_ranges_parse_results(ctx, domain->name,
reply_count, reply, &range_list);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"ipa_ranges_parse_results request failed.\n");
goto done;
}
ret = sysdb_update_ranges(sysdb, range_list);
talloc_free(range_list);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_ranges failed.\n");
goto done;
}
ctx->search_base_iter = 0;
ctx->search_bases = ctx->sd_ctx->search_bases;
ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_SLAVE);
if (ret == EAGAIN) {
return;
} else if (ret != EOK) {
goto done;
}
DEBUG(SSSDBG_OP_FAILURE, "No search base for ranges available.\n");
ret = EINVAL;
done:
if (ret == EOK) {
dp_error = DP_ERR_OK;
}
ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
}
static void ipa_subdomains_handler_master_done(struct tevent_req *req)
{
errno_t ret;
int dp_error = DP_ERR_FATAL;
size_t reply_count = 0;
struct sysdb_attrs **reply = NULL;
struct ipa_subdomains_req_ctx *ctx;
ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx);
ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
talloc_zfree(req);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
goto done;
}
if (reply_count) {
const char *flat = NULL;
const char *id = NULL;
ret = sysdb_attrs_get_string(reply[0], IPA_FLATNAME, &flat);
if (ret != EOK) {
goto done;
}
ret = sysdb_attrs_get_string(reply[0], IPA_SID, &id);
if (ret != EOK) {
goto done;
}
ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain,
flat, id, NULL);
} else {
ctx->search_base_iter++;
ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_MASTER);
if (ret == EAGAIN) {
return;
} else if (ret != EOK) {
goto done;
}
/* Right now we know there has been an error
* and we don't have the master domain record
*/
DEBUG(SSSDBG_CRIT_FAILURE, "Master domain record not found!\n");
if (!ctx->sd_ctx->configured_explicit) {
ctx->sd_ctx->disabled_until = time(NULL) +
IPA_SUBDOMAIN_DISABLED_PERIOD;
}
ret = EIO;
}
done:
if (ret == EOK) {
dp_error = DP_ERR_OK;
}
ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
}
static void ipa_subdom_online_cb(void *pvt);
static void ipa_subdom_timer_refresh(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval current_time,
void *pvt)
{
ipa_subdom_online_cb(pvt);
}
static void ipa_subdom_be_req_callback(struct be_req *be_req,
int dp_err, int dp_ret,
const char *errstr)
{
talloc_free(be_req);
}
static void ipa_subdom_reset_timeouts_cb(void *pvt)
{
struct ipa_subdomains_ctx *ctx;
ctx = talloc_get_type(pvt, struct ipa_subdomains_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Bad private pointer\n");
return;
}
DEBUG(SSSDBG_TRACE_ALL, "Resetting last_refreshed and disabled_until.\n");
ctx->last_refreshed = 0;
ctx->disabled_until = 0;
}
static void ipa_subdom_online_cb(void *pvt)
{
struct ipa_subdomains_ctx *ctx;
struct be_req *be_req;
struct timeval tv;
uint32_t refresh_interval;
ctx = talloc_get_type(pvt, struct ipa_subdomains_ctx);
if (!ctx) {
DEBUG(SSSDBG_CRIT_FAILURE, "Bad private pointer\n");
return;
}
ctx->disabled_until = 0;
refresh_interval = ctx->be_ctx->domain->subdomain_refresh_interval;
be_req = be_req_create(ctx, NULL, ctx->be_ctx,
ipa_subdom_be_req_callback, NULL);
if (be_req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "be_req_create() failed.\n");
return;
}
ipa_subdomains_retrieve(ctx, be_req);
tv = tevent_timeval_current_ofs(refresh_interval, 0);
ctx->timer_event = tevent_add_timer(ctx->be_ctx->ev, ctx, tv,
ipa_subdom_timer_refresh, ctx);
if (!ctx->timer_event) {
DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom timer event\n");
}
}
static void ipa_subdom_offline_cb(void *pvt)
{
struct ipa_subdomains_ctx *ctx;
ctx = talloc_get_type(pvt, struct ipa_subdomains_ctx);
if (ctx) {
talloc_zfree(ctx->timer_event);
}
}
static errno_t get_config_status(struct be_ctx *be_ctx,
bool *configured_explicit)
{
int ret;
TALLOC_CTX *tmp_ctx = NULL;
char *tmp_str;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
return ENOMEM;
}
ret = confdb_get_string(be_ctx->cdb, tmp_ctx, be_ctx->conf_path,
CONFDB_DOMAIN_SUBDOMAINS_PROVIDER, NULL,
&tmp_str);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed.\n");
goto done;
}
if (tmp_str == NULL) {
*configured_explicit = false;
} else {
*configured_explicit = true;
}
DEBUG(SSSDBG_TRACE_ALL, "IPA subdomain provider is configured %s.\n",
*configured_explicit ? "explicit" : "implicit");
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
void ipa_subdomains_handler(struct be_req *be_req)
{
struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
struct ipa_subdomains_ctx *ctx;
time_t now;
ctx = talloc_get_type(be_ctx->bet_info[BET_SUBDOMAINS].pvt_bet_data,
struct ipa_subdomains_ctx);
if (!ctx) {
be_req_terminate(be_req, DP_ERR_FATAL, EINVAL, NULL);
return;
}
now = time(NULL);
if (ctx->disabled_until > now) {
DEBUG(SSSDBG_TRACE_ALL, "Subdomain provider disabled.\n");
ipa_subdomains_done(ctx, be_req, DP_ERR_OK, EOK, NULL);
return;
}
if (ctx->last_refreshed > now - IPA_SUBDOMAIN_REFRESH_LIMIT) {
ipa_subdomains_done(ctx, be_req, DP_ERR_OK, EOK, NULL);
return;
}
ipa_subdomains_retrieve(ctx, be_req);
}
struct bet_ops ipa_subdomains_ops = {
.handler = ipa_subdomains_handler,
.finalize = NULL
};
int ipa_subdom_init(struct be_ctx *be_ctx,
struct ipa_id_ctx *id_ctx,
struct bet_ops **ops,
void **pvt_data)
{
struct ipa_subdomains_ctx *ctx;
int ret;
bool configured_explicit = false;
ret = get_config_status(be_ctx, &configured_explicit);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "get_config_status failed.\n");
return ret;
}
ctx = talloc_zero(id_ctx, struct ipa_subdomains_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
return ENOMEM;
}
ctx->be_ctx = be_ctx;
ctx->id_ctx = id_ctx;
ctx->sdap_id_ctx = id_ctx->sdap_id_ctx;
ctx->search_bases = id_ctx->ipa_options->subdomains_search_bases;
ctx->master_search_bases = id_ctx->ipa_options->master_domain_search_bases;
ctx->ranges_search_bases = id_ctx->ipa_options->ranges_search_bases;
ctx->host_search_bases = id_ctx->ipa_options->host_search_bases;
ctx->configured_explicit = configured_explicit;
ctx->disabled_until = 0;
*ops = &ipa_subdomains_ops;
*pvt_data = ctx;
ret = be_add_unconditional_online_cb(ctx, be_ctx,
ipa_subdom_reset_timeouts_cb, ctx,
NULL);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Failed to add subdom reset timeouts callback");
}
ret = be_add_online_cb(ctx, be_ctx, ipa_subdom_online_cb, ctx, NULL);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom online callback");
}
ret = be_add_offline_cb(ctx, be_ctx, ipa_subdom_offline_cb, ctx, NULL);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom offline callback");
}
ret = ipa_subdom_reinit(ctx);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "Could not load the list of subdomains. "
"Users from trusted domains might not be resolved correctly\n");
}
return EOK;
}
int ipa_ad_subdom_init(struct be_ctx *be_ctx,
struct ipa_id_ctx *id_ctx)
{
char *realm;
char *hostname;
errno_t ret;
if (dp_opt_get_bool(id_ctx->ipa_options->basic,
IPA_SERVER_MODE) == false) {
return EOK;
}
/* The IPA code relies on the default FQDN format to unparse user
* names. Warn loudly if the full_name_format was customized on the
* IPA server
*/
if ((strcmp(be_ctx->domain->names->fq_fmt,
CONFDB_DEFAULT_FULL_NAME_FORMAT) != 0)
&& (strcmp(be_ctx->domain->names->fq_fmt,
CONFDB_DEFAULT_FULL_NAME_FORMAT_INTERNAL) != 0)) {
DEBUG(SSSDBG_FATAL_FAILURE, "%s is set to a non-default value [%s] " \
"lookups of subdomain users will likely fail!\n",
CONFDB_FULL_NAME_FORMAT, be_ctx->domain->names->fq_fmt);
sss_log(SSS_LOG_ERR, "%s is set to a non-default value [%s] " \
"lookups of subdomain users will likely fail!\n",
CONFDB_FULL_NAME_FORMAT, be_ctx->domain->names->fq_fmt);
/* Attempt to continue */
}
realm = dp_opt_get_string(id_ctx->ipa_options->basic, IPA_KRB5_REALM);
if (realm == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
return EINVAL;
}
hostname = dp_opt_get_string(id_ctx->ipa_options->basic, IPA_HOSTNAME);
if (hostname == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "No host name for IPA?\n");
return EINVAL;
}
id_ctx->server_mode = talloc_zero(id_ctx, struct ipa_server_mode_ctx);
if (id_ctx->server_mode == NULL) {
return ENOMEM;
}
id_ctx->server_mode->realm = realm;
id_ctx->server_mode->hostname = hostname;
id_ctx->server_mode->trusts = NULL;
id_ctx->server_mode->ext_groups = NULL;
ret = ipa_ad_subdom_refresh(be_ctx, id_ctx, be_ctx->domain);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ipa_ad_subdom_refresh failed.\n");
return ret;
}
return EOK;
}