ad_subdomains.c revision a82baf596bac1fdac6addca6419d8992111a8aa2
2665d7759e63acff0bcd4135678f2cc6f2041d46Christian Maeder/*
9658657e918981d91c8647ed8c220464f10a6235Christian Maeder SSSD
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
e6d40133bc9f858308654afb1262b8b483ec5922Till Mossakowski AD Subdomains Module
d5fe06af711a6912ae028ebf873eada4ee8733f8Christian Maeder
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu Authors:
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder Sumit Bose <sbose@redhat.com>
3f69b6948966979163bdfe8331c38833d5d90ecdChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder Copyright (C) 2013 Red Hat
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder This program is free software; you can redistribute it and/or modify
e6d40133bc9f858308654afb1262b8b483ec5922Till Mossakowski it under the terms of the GNU General Public License as published by
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder the Free Software Foundation; either version 3 of the License, or
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder (at your option) any later version.
a7a43d265fef55ddfd7c4412cd96c621ef9738ffChristian Maeder
a7a43d265fef55ddfd7c4412cd96c621ef9738ffChristian Maeder This program is distributed in the hope that it will be useful,
a7a43d265fef55ddfd7c4412cd96c621ef9738ffChristian Maeder but WITHOUT ANY WARRANTY; without even the implied warranty of
a7a43d265fef55ddfd7c4412cd96c621ef9738ffChristian Maeder MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a7a43d265fef55ddfd7c4412cd96c621ef9738ffChristian Maeder GNU General Public License for more details.
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
ae35311385999d91f812155fe99439724d54063bChristian Maeder You should have received a copy of the GNU General Public License
46b207daf66b64930a59f3615c8b127aac0b8e43Christian Maeder along with this program. If not, see <http://www.gnu.org/licenses/>.
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder*/
50a3afe91cef447a03d579976c179dc266290c93Christian Maeder
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist#include "providers/ldap/sdap_async.h"
50a3afe91cef447a03d579976c179dc266290c93Christian Maeder#include "providers/ad/ad_subdomains.h"
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder#include "providers/ad/ad_domain_info.h"
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder#include "providers/ad/ad_srv.h"
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder#include "providers/ad/ad_common.h"
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder
ab9b86500ed66416e1a7c01be54491ed72c7d633Christian Maeder#include "providers/ldap/sdap_idmap.h"
ab9b86500ed66416e1a7c01be54491ed72c7d633Christian Maeder#include "providers/ldap/sdap_ops.h"
78e7910c3360f74f1db172d63d20bb07c64e56e3Christian Maeder#include "util/util_sss_idmap.h"
8ddb1f6f0aa4eb1836867ba3dde21ac1ec79a58dcmaeder#include <ctype.h>
024703c9d1326c23e307c0b0d453ed3358e87fe4cmaeder#include <ndr.h>
47d6bc7bc9a708427f96be8d805f712697ad3d9eChristian Maeder#include <ndr/ndr_nbt.h>
f9e0b18852b238ddb649d341194e05d7200d1bbeChristian Maeder
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maeder/* Attributes of AD trusted domains */
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder#define AD_AT_FLATNAME "flatName"
8e537a087207fb2ea9073ea66776c36b821a58c6Christian Maeder#define AD_AT_SID "securityIdentifier"
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist#define AD_AT_TRUST_TYPE "trustType"
8ddb1f6f0aa4eb1836867ba3dde21ac1ec79a58dcmaeder#define AD_AT_TRUST_PARTNER "trustPartner"
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder#define AD_AT_TRUST_ATTRS "trustAttributes"
ad270004874ce1d0697fb30d7309f180553bb315Christian Maeder
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder/* trustType=2 denotes uplevel (NT5 and later) trusted domains. See
520c5bce318eff52d9315f7c4491c3381a0c4336Christian Maeder * http://msdn.microsoft.com/en-us/library/windows/desktop/ms680342%28v=vs.85%29.aspx
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder * for example.
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder *
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder * The absence of msDS-TrustForestTrustInfo attribute denotes a domain from
46b1095ba983ce859e17c2a12f48b50583b7150cChristian Maeder * the same forest. See http://msdn.microsoft.com/en-us/library/cc223786.aspx
411392046c2ba1752cde81eaa92a95a2c28b672dChristian Maeder * for more information.
78e7910c3360f74f1db172d63d20bb07c64e56e3Christian Maeder */
f527d5da7cd679c1a9b50a4906a0c12d395a6087Christian Maeder#define SLAVE_DOMAIN_FILTER_BASE "(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*))"
9175e29c044318498a40f323f189f9dfd50378efChristian Maeder#define SLAVE_DOMAIN_FILTER "(&"SLAVE_DOMAIN_FILTER_BASE")"
9175e29c044318498a40f323f189f9dfd50378efChristian Maeder#define FOREST_ROOT_FILTER_FMT "(&"SLAVE_DOMAIN_FILTER_BASE"(cn=%s))"
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder/* do not refresh more often than every 5 seconds for now */
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder#define AD_SUBDOMAIN_REFRESH_LIMIT 5
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maederstatic errno_t ad_get_enabled_domains(TALLOC_CTX *mem_ctx,
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder struct ad_id_ctx *ad_id_ctx,
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder const char *ad_domain,
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder const char ***_ad_enabled_domains)
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder{
46b207daf66b64930a59f3615c8b127aac0b8e43Christian Maeder int ret;
024703c9d1326c23e307c0b0d453ed3358e87fe4cmaeder const char *str;
46b1095ba983ce859e17c2a12f48b50583b7150cChristian Maeder const char *option_name;
46b1095ba983ce859e17c2a12f48b50583b7150cChristian Maeder const char **domains = NULL;
4cc271fa22221d0d20cf303553f86c4e3b1a56e4Christian Maeder int count;
c8a9d35be2207e0d4fbd26a2411e1ba17e3e4c96Christian Maeder bool is_ad_in_domains;
c2257f94016aeb9e5c3ff3d4d675a81f8f873f0dChristian Maeder TALLOC_CTX *tmp_ctx = NULL;
3986813db69106b9bb1b62faa77532af42512a0cChristian Maeder
4cc271fa22221d0d20cf303553f86c4e3b1a56e4Christian Maeder tmp_ctx = talloc_new(NULL);
3986813db69106b9bb1b62faa77532af42512a0cChristian Maeder if (tmp_ctx == NULL) {
596a8e9039bd2f42c09cc0da4a57c8073f96fbddChristian Maeder return ENOMEM;
596a8e9039bd2f42c09cc0da4a57c8073f96fbddChristian Maeder }
596a8e9039bd2f42c09cc0da4a57c8073f96fbddChristian Maeder
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder str = dp_opt_get_cstring(ad_id_ctx->ad_options->basic, AD_ENABLED_DOMAINS);
46b1095ba983ce859e17c2a12f48b50583b7150cChristian Maeder if (str == NULL) {
e982190515f83fe6615436530ebe89bb320770d6Christian Maeder *_ad_enabled_domains = NULL;
ab9b86500ed66416e1a7c01be54491ed72c7d633Christian Maeder ret = EOK;
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder goto done;
f04e8f3ff56405901be968fd4c6e9769239f1a9bKlaus Luettich }
08d506ebb78da1e8656a73a349492e042f4c9f72Christian Maeder
d27d203b3f42f0e0ecea00e3f19f55f66045bd96Christian Maeder count = 0;
46b1095ba983ce859e17c2a12f48b50583b7150cChristian Maeder ret = split_on_separator(tmp_ctx, str, ',', true, true,
53a3042e1da2253fd3f103bfef4deb47fc0bf6a6Ewaryst Schulz discard_const_p(char **, &domains), &count);
53a3042e1da2253fd3f103bfef4deb47fc0bf6a6Ewaryst Schulz if (ret != EOK) {
53a3042e1da2253fd3f103bfef4deb47fc0bf6a6Ewaryst Schulz option_name = ad_id_ctx->ad_options->basic[AD_ENABLED_DOMAINS].opt_name;
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse option [%s], [%i] [%s]!\n",
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder option_name, ret, sss_strerror(ret));
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder ret = EINVAL;
ec351e60425e2f99448cb44e933d3828f8025dddChristian Maeder goto done;
32607d06fe7826eb0711c19d348ee4e395f2577aChristian Maeder }
411588cc915b27cef4e7e66fb23e67514b3a0c92Christian Maeder
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist is_ad_in_domains = false;
411588cc915b27cef4e7e66fb23e67514b3a0c92Christian Maeder for (int i = 0; i < count; i++) {
21dbca247d5964daf2c5abd2de2ac1101e3e1ef4Christian Maeder is_ad_in_domains += strcmp(ad_domain, domains[i]) == 0 ? true : false;
ec351e60425e2f99448cb44e933d3828f8025dddChristian Maeder }
56440c7ae61e7277a3494452d0165ee52e677b29Christian Maeder
e4f0eaffd002e9e553ee113be33f9aa6e4181c43Christian Maeder if (is_ad_in_domains == false) {
961978c71545e0177683279f8b63358b3e3804b8Christian Maeder domains = talloc_realloc(tmp_ctx, domains, const char*, count + 2);
961978c71545e0177683279f8b63358b3e3804b8Christian Maeder if (domains == NULL) {
e4f0eaffd002e9e553ee113be33f9aa6e4181c43Christian Maeder ret = ENOMEM;
c4076ff1721f8901a30e4b7aa004479ecb2631e0Felix Gabriel Mance goto done;
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa }
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa domains[count] = talloc_strdup(domains, ad_domain);
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze if (domains[count] == NULL) {
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa ret = ENOMEM;
64c2422e1ba0691556a6639e959820add102315cChristian Maeder goto done;
938677803842b384a91fef21f58f86b8e3188b43Ewaryst Schulz }
4c8d3c5a9e938633f6147b5a595b9b93bfca99e6Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder domains[count + 1] = NULL;
63da71bfb4226f504944b293fb77177ebcaea7d4Ewaryst Schulz } else {
63da71bfb4226f504944b293fb77177ebcaea7d4Ewaryst Schulz domains = talloc_realloc(tmp_ctx, domains, const char*, count + 1);
f8cc2399c16fcda7e3bf9d901a0de0cc8a455f86Ewaryst Schulz if (domains == NULL) {
b83ff3749d99d03b641adee264b781039a551addChristian Maeder ret = ENOMEM;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder goto done;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder }
520c5bce318eff52d9315f7c4491c3381a0c4336Christian Maeder
c2257f94016aeb9e5c3ff3d4d675a81f8f873f0dChristian Maeder domains[count] = NULL;
0850c3e5fb6285405ebaeb5aa433985203ac892dEwaryst Schulz }
bdf2e01977470bedcb4425e2dadabc9e9f6ba149Ewaryst Schulz
bdf2e01977470bedcb4425e2dadabc9e9f6ba149Ewaryst Schulz *_ad_enabled_domains = talloc_steal(mem_ctx, domains);
bdf2e01977470bedcb4425e2dadabc9e9f6ba149Ewaryst Schulz ret = EOK;
0850c3e5fb6285405ebaeb5aa433985203ac892dEwaryst Schulz
961978c71545e0177683279f8b63358b3e3804b8Christian Maederdone:
938677803842b384a91fef21f58f86b8e3188b43Ewaryst Schulz talloc_free(tmp_ctx);
0850c3e5fb6285405ebaeb5aa433985203ac892dEwaryst Schulz return ret;
e49fd57c63845c7806860a9736ad09f6d44dbaedChristian Maeder}
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder
63719301448519453f66383f4e583d9fd5b89ecbChristian Maederstatic errno_t
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maederad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder struct ad_id_ctx *id_ctx,
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder struct sss_domain_info *subdom,
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder struct ad_id_ctx **_subdom_id_ctx)
a43c1a7fa08c12524415386aa13a566cc9e53a4fChristian Maeder{
034d9e2e9ada5aaa5665180720744d51166dacd4Christian Maeder struct ad_options *ad_options;
024703c9d1326c23e307c0b0d453ed3358e87fe4cmaeder struct ad_id_ctx *ad_id_ctx;
024703c9d1326c23e307c0b0d453ed3358e87fe4cmaeder const char *gc_service_name;
427ff3172ae2dfebe3c8fc972735158999997e8aChristian Maeder const char *service_name;
427ff3172ae2dfebe3c8fc972735158999997e8aChristian Maeder struct ad_srv_plugin_ctx *srv_ctx;
72079df98b3cb7cc1fd82a0a24984893dcd05ecaEwaryst Schulz char *ad_domain;
5ca1fe655d7d4e35e59a082b5955b306643329d0Ewaryst Schulz char *ad_site_override;
5f2c34b8971f9ca7e63364b69e167851d001168eEwaryst Schulz struct sdap_domain *sdom;
5f2c34b8971f9ca7e63364b69e167851d001168eEwaryst Schulz errno_t ret;
bdf2e01977470bedcb4425e2dadabc9e9f6ba149Ewaryst Schulz const char *realm;
0850c3e5fb6285405ebaeb5aa433985203ac892dEwaryst Schulz const char *hostname;
5f2c34b8971f9ca7e63364b69e167851d001168eEwaryst Schulz const char *keytab;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder
4d54e7814b18ce142359c92a5868e6dcff9219b5Christian Maeder realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM);
ce900a84ed9d9882c64fccbd6300f6b0d67efa82Christian Maeder hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME);
48a98aa04f4c2c1f5f8f79c007e1ff95e699b31aFlorian Mossakowski keytab = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KEYTAB);
aad8b6ac810a08fca14ce0fbbf324fcce5305ad6Christian Maeder ad_domain = subdom->name;
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder if (realm == NULL || hostname == NULL || ad_domain == NULL) {
aad8b6ac810a08fca14ce0fbbf324fcce5305ad6Christian Maeder DEBUG(SSSDBG_CONF_SETTINGS, "Missing realm or hostname.\n");
53e165a53dfa59f717588d1f8236c9a763826525Christian Maeder return EINVAL;
53e165a53dfa59f717588d1f8236c9a763826525Christian Maeder }
1937dccb04b363364f7a7de17fdaae1d70583af9Christian Maeder
aad8b6ac810a08fca14ce0fbbf324fcce5305ad6Christian Maeder ad_options = ad_create_2way_trust_options(id_ctx, realm, ad_domain,
53e165a53dfa59f717588d1f8236c9a763826525Christian Maeder hostname, keytab);
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder if (ad_options == NULL) {
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n");
08d506ebb78da1e8656a73a349492e042f4c9f72Christian Maeder talloc_free(ad_options);
08d506ebb78da1e8656a73a349492e042f4c9f72Christian Maeder return ENOMEM;
d27d203b3f42f0e0ecea00e3f19f55f66045bd96Christian Maeder }
d27d203b3f42f0e0ecea00e3f19f55f66045bd96Christian Maeder
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder ad_site_override = dp_opt_get_string(ad_options->basic, AD_SITE);
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder gc_service_name = talloc_asprintf(ad_options, "sd_gc_%s", subdom->name);
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder if (gc_service_name == NULL) {
074f8feaf71e0b71a95145e7439746f8eb8e2a7cChristian Maeder talloc_free(ad_options);
c1d06b3018b34ede2b3fb6c7fe2ad28cd5ce5b68Christian Maeder return ENOMEM;
53a3042e1da2253fd3f103bfef4deb47fc0bf6a6Ewaryst Schulz }
53a3042e1da2253fd3f103bfef4deb47fc0bf6a6Ewaryst Schulz
53a3042e1da2253fd3f103bfef4deb47fc0bf6a6Ewaryst Schulz service_name = talloc_asprintf(ad_options, "sd_%s", subdom->name);
53a3042e1da2253fd3f103bfef4deb47fc0bf6a6Ewaryst Schulz if (service_name == NULL) {
ea8e98e298f33f9362293f392c8fb192722b8904Eugen Kuksa talloc_free(ad_options);
ab9b86500ed66416e1a7c01be54491ed72c7d633Christian Maeder return ENOMEM;
e6ac593966607b1da5b619e0f9492d37820eed74Christian Maeder }
f6b2c6c33c635279973b8f378470da7dbb8ecee8Christian Maeder
074f8feaf71e0b71a95145e7439746f8eb8e2a7cChristian Maeder ret = ad_failover_init(ad_options, be_ctx, NULL, NULL, realm,
e6ac593966607b1da5b619e0f9492d37820eed74Christian Maeder service_name, gc_service_name,
f6b2c6c33c635279973b8f378470da7dbb8ecee8Christian Maeder subdom->name, &ad_options->service);
f6b2c6c33c635279973b8f378470da7dbb8ecee8Christian Maeder if (ret != EOK) {
f6b2c6c33c635279973b8f378470da7dbb8ecee8Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n");
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder talloc_free(ad_options);
f6b2c6c33c635279973b8f378470da7dbb8ecee8Christian Maeder return ret;
e6ac593966607b1da5b619e0f9492d37820eed74Christian Maeder }
11c3a215d5cf043181e83929f1ce214df65cb587Christian Maeder
e6ac593966607b1da5b619e0f9492d37820eed74Christian Maeder ad_id_ctx = ad_id_ctx_init(ad_options, be_ctx);
e6ac593966607b1da5b619e0f9492d37820eed74Christian Maeder if (ad_id_ctx == NULL) {
ab9b86500ed66416e1a7c01be54491ed72c7d633Christian Maeder talloc_free(ad_options);
ab9b86500ed66416e1a7c01be54491ed72c7d633Christian Maeder return ENOMEM;
ab9b86500ed66416e1a7c01be54491ed72c7d633Christian Maeder }
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder ad_id_ctx->sdap_id_ctx->opts = ad_options->id;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder ad_options->id_ctx = ad_id_ctx;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder /* use AD plugin */
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx->be_res,
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder default_host_dbs,
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder ad_id_ctx->ad_options->id,
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder hostname,
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder ad_domain,
ab9b86500ed66416e1a7c01be54491ed72c7d633Christian Maeder ad_site_override);
ab9b86500ed66416e1a7c01be54491ed72c7d633Christian Maeder if (srv_ctx == NULL) {
a7b34c1a61dabe150288424d90389d5988bf9d7aChristian Maeder DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
ea8e98e298f33f9362293f392c8fb192722b8904Eugen Kuksa return ENOMEM;
a7b34c1a61dabe150288424d90389d5988bf9d7aChristian Maeder }
c1d06b3018b34ede2b3fb6c7fe2ad28cd5ce5b68Christian Maeder be_fo_set_srv_lookup_plugin(be_ctx, ad_srv_plugin_send,
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist ad_srv_plugin_recv, srv_ctx, "AD");
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist
5382091fd2a705e6f026026e8a6adcd3607bdb9fChristian Maeder ret = sdap_domain_subdom_add(ad_id_ctx->sdap_id_ctx,
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder ad_id_ctx->sdap_id_ctx->opts->sdom,
21dbca247d5964daf2c5abd2de2ac1101e3e1ef4Christian Maeder subdom->parent);
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder if (ret != EOK) {
074f8feaf71e0b71a95145e7439746f8eb8e2a7cChristian Maeder DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize sdap domain\n");
e6ac593966607b1da5b619e0f9492d37820eed74Christian Maeder talloc_free(ad_options);
aad8b6ac810a08fca14ce0fbbf324fcce5305ad6Christian Maeder return ret;
aad8b6ac810a08fca14ce0fbbf324fcce5305ad6Christian Maeder }
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder sdom = sdap_domain_get(ad_id_ctx->sdap_id_ctx->opts, subdom);
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder if (sdom == NULL) {
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder return EFAULT;
21dbca247d5964daf2c5abd2de2ac1101e3e1ef4Christian Maeder }
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder
154be5bfac61cf5b61fd1571e7bfc2572c4b546aMihai Codescu sdap_inherit_options(subdom->parent->sd_inherit,
154be5bfac61cf5b61fd1571e7bfc2572c4b546aMihai Codescu id_ctx->sdap_id_ctx->opts,
25662bf82f592e3268fddcc2c86e83c203b82e53Ewaryst Schulz ad_id_ctx->sdap_id_ctx->opts);
21489db35f79507a68ee6e6926e01b8e8ea60c6bChristian Maeder
7fe976d9f9c4af1aa7636c568d9919859523de0aChristian Maeder /* Set up the ID mapping object */
7fe976d9f9c4af1aa7636c568d9919859523de0aChristian Maeder ad_id_ctx->sdap_id_ctx->opts->idmap_ctx =
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder id_ctx->sdap_id_ctx->opts->idmap_ctx;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder
21dbca247d5964daf2c5abd2de2ac1101e3e1ef4Christian Maeder *_subdom_id_ctx = ad_id_ctx;
154be5bfac61cf5b61fd1571e7bfc2572c4b546aMihai Codescu return EOK;
154be5bfac61cf5b61fd1571e7bfc2572c4b546aMihai Codescu}
7fe976d9f9c4af1aa7636c568d9919859523de0aChristian Maeder
154be5bfac61cf5b61fd1571e7bfc2572c4b546aMihai Codescustruct ad_subdomains_ctx {
486db0a875bcdd0b80cf0d447d14c9c00a92ae94Simon Ulbricht struct be_ctx *be_ctx;
486db0a875bcdd0b80cf0d447d14c9c00a92ae94Simon Ulbricht struct ad_id_ctx *ad_id_ctx;
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder struct sdap_id_ctx *sdap_id_ctx;
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder struct sdap_domain *sdom;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder char *domain_name;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder const char **ad_enabled_domains;
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder
21dbca247d5964daf2c5abd2de2ac1101e3e1ef4Christian Maeder time_t last_refreshed;
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder};
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maederstatic errno_t ad_subdom_enumerates(struct sss_domain_info *parent,
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder struct sysdb_attrs *attrs,
706201451843aa76b8d862de800570c9838c9910Christian Maeder bool *_enumerates)
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder{
38824a7dba4f7d82532afec67e0b594a5af5d76bChristian Maeder errno_t ret;
bbba10ee00dcf6bcbc9f22473b1acd0983b10512notanartist const char *name;
8762d0e3d492aba4d1621fb0de685f0be1372864notanartist
bbba10ee00dcf6bcbc9f22473b1acd0983b10512notanartist ret = sysdb_attrs_get_string(attrs, AD_AT_TRUST_PARTNER, &name);
bbba10ee00dcf6bcbc9f22473b1acd0983b10512notanartist if (ret != EOK) {
bbba10ee00dcf6bcbc9f22473b1acd0983b10512notanartist DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
bbba10ee00dcf6bcbc9f22473b1acd0983b10512notanartist return ret;
8762d0e3d492aba4d1621fb0de685f0be1372864notanartist }
bbba10ee00dcf6bcbc9f22473b1acd0983b10512notanartist
ec351e60425e2f99448cb44e933d3828f8025dddChristian Maeder *_enumerates = subdomain_enumerates(parent, name);
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist return EOK;
32607d06fe7826eb0711c19d348ee4e395f2577aChristian Maeder}
32607d06fe7826eb0711c19d348ee4e395f2577aChristian Maeder
32607d06fe7826eb0711c19d348ee4e395f2577aChristian Maederstatic errno_t
411588cc915b27cef4e7e66fb23e67514b3a0c92Christian Maederad_subdom_store(struct sdap_idmap_ctx *idmap_ctx,
411588cc915b27cef4e7e66fb23e67514b3a0c92Christian Maeder struct sss_domain_info *domain,
411588cc915b27cef4e7e66fb23e67514b3a0c92Christian Maeder struct sysdb_attrs *subdom_attrs,
411588cc915b27cef4e7e66fb23e67514b3a0c92Christian Maeder bool enumerate)
411588cc915b27cef4e7e66fb23e67514b3a0c92Christian Maeder{
32607d06fe7826eb0711c19d348ee4e395f2577aChristian Maeder TALLOC_CTX *tmp_ctx;
411588cc915b27cef4e7e66fb23e67514b3a0c92Christian Maeder const char *name;
feeab95fdf7ec92bcce607c104d9dc98e0e6ea90Soeren D. Schulze char *realm;
ec351e60425e2f99448cb44e933d3828f8025dddChristian Maeder const char *flat;
ec351e60425e2f99448cb44e933d3828f8025dddChristian Maeder errno_t ret;
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist enum idmap_error_code err;
29bda77eb81294ac19df7f1fd0e322dff03cdad0notanartist struct ldb_message_element *el;
29bda77eb81294ac19df7f1fd0e322dff03cdad0notanartist char *sid_str = NULL;
29bda77eb81294ac19df7f1fd0e322dff03cdad0notanartist uint32_t trust_type;
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist bool mpg;
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist tmp_ctx = talloc_new(NULL);
9e6789e67e329416d7f3acf0e7b8367b8dea991bnotanartist if (tmp_ctx == NULL) {
e4f0eaffd002e9e553ee113be33f9aa6e4181c43Christian Maeder ret = ENOMEM;
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa goto done;
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa }
961978c71545e0177683279f8b63358b3e3804b8Christian Maeder
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa ret = sysdb_attrs_get_uint32_t(subdom_attrs, AD_AT_TRUST_TYPE,
feeab95fdf7ec92bcce607c104d9dc98e0e6ea90Soeren D. Schulze &trust_type);
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa if (ret != EOK) {
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_uint32_t failed.\n");
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa goto done;
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa }
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze ret = sysdb_attrs_get_string(subdom_attrs, AD_AT_TRUST_PARTNER, &name);
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze if (ret != EOK) {
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze DEBUG(SSSDBG_OP_FAILURE, "failed to get subdomain name\n");
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze goto done;
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze }
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze realm = get_uppercase_realm(tmp_ctx, name);
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder if (!realm) {
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder ret = ENOMEM;
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder goto done;
c1d06b3018b34ede2b3fb6c7fe2ad28cd5ce5b68Christian Maeder }
b085709d4b69dc84724000b7b917f348edfa932eChristian Maeder
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder ret = sysdb_attrs_get_string(subdom_attrs, AD_AT_FLATNAME, &flat);
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder if (ret) {
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "failed to get flat name of subdomain %s\n",
c1168d10047d2c1394b82953158747775a9b4556Christian Maeder name);
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder goto done;
c1168d10047d2c1394b82953158747775a9b4556Christian Maeder }
57075b3ac70f37e55f72aa86aa1b70c6ccca8207Christian Maeder
57075b3ac70f37e55f72aa86aa1b70c6ccca8207Christian Maeder ret = sysdb_attrs_get_el(subdom_attrs, AD_AT_SID, &el);
57075b3ac70f37e55f72aa86aa1b70c6ccca8207Christian Maeder if (ret != EOK || el->num_values != 1) {
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sdap_attrs_get_el failed.\n");
35cb254f1f46a6f33b5c24111a37fbab49d79cfeChristian Maeder goto done;
35cb254f1f46a6f33b5c24111a37fbab49d79cfeChristian Maeder }
35cb254f1f46a6f33b5c24111a37fbab49d79cfeChristian Maeder
d34c6711bc746459074986c06f7c28b083b4be2fChristian Maeder err = sss_idmap_bin_sid_to_sid(idmap_ctx->map, el->values[0].data,
b085709d4b69dc84724000b7b917f348edfa932eChristian Maeder el->values[0].length, &sid_str);
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder if (err != IDMAP_SUCCESS) {
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maeder DEBUG(SSSDBG_MINOR_FAILURE,
48a98aa04f4c2c1f5f8f79c007e1ff95e699b31aFlorian Mossakowski "Could not convert SID: [%s].\n", idmap_error_string(err));
8865728716566f42fa73e7e0bc080ba3225df764Christian Maeder ret = EFAULT;
ea8e98e298f33f9362293f392c8fb192722b8904Eugen Kuksa goto done;
1937dccb04b363364f7a7de17fdaae1d70583af9Christian Maeder }
bb9642ff292545658dc11251b83a7b7af3c1fccbChristian Maeder
a7b34c1a61dabe150288424d90389d5988bf9d7aChristian Maeder mpg = sdap_idmap_domain_has_algorithmic_mapping(idmap_ctx, name, sid_str);
bb9642ff292545658dc11251b83a7b7af3c1fccbChristian Maeder
bb9642ff292545658dc11251b83a7b7af3c1fccbChristian Maeder ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str,
f6b2c6c33c635279973b8f378470da7dbb8ecee8Christian Maeder mpg, enumerate, domain->forest, 0, NULL);
f6b2c6c33c635279973b8f378470da7dbb8ecee8Christian Maeder if (ret != EOK) {
6c08e47c4275556c18f4f89521bf21fe94c28dd5Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n");
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder goto done;
f6b2c6c33c635279973b8f378470da7dbb8ecee8Christian Maeder }
78e7910c3360f74f1db172d63d20bb07c64e56e3Christian Maeder
78e7910c3360f74f1db172d63d20bb07c64e56e3Christian Maeder ret = EOK;
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maederdone:
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder sss_idmap_free_sid(idmap_ctx->map, sid_str);
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder talloc_free(tmp_ctx);
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder return ret;
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder}
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder
4067eba4f5605d9569d78085deb1a27f08ac34e2Christian Maederstatic errno_t ad_subdomains_refresh(struct be_ctx *be_ctx,
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder struct sdap_idmap_ctx *idmap_ctx,
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder struct sdap_options *opts,
eaa88a5cefdc814e61039c5dcc1bffc324a2f93eChristian Maeder struct sysdb_attrs **subdomains,
bb9642ff292545658dc11251b83a7b7af3c1fccbChristian Maeder size_t num_subdomains,
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder bool root_domain,
e49fd57c63845c7806860a9736ad09f6d44dbaedChristian Maeder time_t *_last_refreshed,
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder bool *_changes)
938677803842b384a91fef21f58f86b8e3188b43Ewaryst Schulz{
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder struct sdap_domain *sdom;
35cb254f1f46a6f33b5c24111a37fbab49d79cfeChristian Maeder struct sss_domain_info *domain;
35cb254f1f46a6f33b5c24111a37fbab49d79cfeChristian Maeder struct sss_domain_info *dom;
35cb254f1f46a6f33b5c24111a37fbab49d79cfeChristian Maeder bool handled[num_subdomains];
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder const char *value;
35cb254f1f46a6f33b5c24111a37fbab49d79cfeChristian Maeder const char *root_name = NULL;
35cb254f1f46a6f33b5c24111a37fbab49d79cfeChristian Maeder size_t c, h;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder int ret;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder bool enumerate;
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder domain = be_ctx->domain;
1937dccb04b363364f7a7de17fdaae1d70583af9Christian Maeder memset(handled, 0, sizeof(bool) * num_subdomains);
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder h = 0;
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder
024703c9d1326c23e307c0b0d453ed3358e87fe4cmaeder if (root_domain) {
938677803842b384a91fef21f58f86b8e3188b43Ewaryst Schulz ret = sysdb_attrs_get_string(subdomains[0], AD_AT_TRUST_PARTNER,
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder &root_name);
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder if (ret != EOK) {
bbba10ee00dcf6bcbc9f22473b1acd0983b10512notanartist DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa goto done;
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze }
53a3042e1da2253fd3f103bfef4deb47fc0bf6a6Ewaryst Schulz }
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder /* check existing subdomains */
c30231257d9116b514dce02703a515fe21cd427dTill Mossakowski for (dom = get_next_domain(domain, SSS_GND_DESCEND);
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder dom = get_next_domain(dom, 0)) {
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder /* If we are handling root domain, skip all the other domains. We don't
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder * want to accidentally remove non-root domains
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder */
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder if (root_name && strcmp(root_name, dom->name) != 0) {
ef2affdc0cdf3acd5c051597c04ab9b08a346a7dChristian Maeder continue;
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder }
1937dccb04b363364f7a7de17fdaae1d70583af9Christian Maeder
1937dccb04b363364f7a7de17fdaae1d70583af9Christian Maeder for (c = 0; c < num_subdomains; c++) {
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder if (handled[c]) {
35cb254f1f46a6f33b5c24111a37fbab49d79cfeChristian Maeder continue;
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder }
35cb254f1f46a6f33b5c24111a37fbab49d79cfeChristian Maeder ret = sysdb_attrs_get_string(subdomains[c], AD_AT_TRUST_PARTNER,
88e08f20c80fea4b7892bbb5e70c5002f7c1da18Christian Maeder &value);
ef4c609cebc5260771dae6e4f3a54a8959e81ed9Christian Maeder if (ret != EOK) {
180ab8c3df8cb0c88f0e881bca93354df6b5d560Christian Maeder DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder goto done;
52e573502bb19ca616ea63283d58ba73f39675d2Christian Maeder }
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder if (strcmp(value, dom->name) == 0) {
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder break;
ea8e98e298f33f9362293f392c8fb192722b8904Eugen Kuksa }
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder }
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder if (c >= num_subdomains) {
ef2affdc0cdf3acd5c051597c04ab9b08a346a7dChristian Maeder /* ok this subdomain does not exist anymore, let's clean up */
3143271856dbf456bd7acc1c07193173f886d986Christian Maeder sss_domain_set_state(dom, DOM_DISABLED);
63719301448519453f66383f4e583d9fd5b89ecbChristian Maeder ret = sysdb_subdomain_delete(dom->sysdb, dom->name);
ce900a84ed9d9882c64fccbd6300f6b0d67efa82Christian Maeder if (ret != EOK) {
ce900a84ed9d9882c64fccbd6300f6b0d67efa82Christian Maeder goto done;
fb37a248ebad4696bbc9d9b94ce1cfc6497a9160Christian Maeder }
fb37a248ebad4696bbc9d9b94ce1cfc6497a9160Christian Maeder
f527d5da7cd679c1a9b50a4906a0c12d395a6087Christian Maeder sdom = sdap_domain_get(opts, dom);
f527d5da7cd679c1a9b50a4906a0c12d395a6087Christian Maeder if (sdom == NULL) {
9175e29c044318498a40f323f189f9dfd50378efChristian Maeder DEBUG(SSSDBG_CRIT_FAILURE, "BUG: Domain does not exist?\n");
9175e29c044318498a40f323f189f9dfd50378efChristian Maeder continue;
9175e29c044318498a40f323f189f9dfd50378efChristian Maeder }
9175e29c044318498a40f323f189f9dfd50378efChristian Maeder
50a3afe91cef447a03d579976c179dc266290c93Christian Maeder /* Remove the subdomain from the list of LDAP domains */
50a3afe91cef447a03d579976c179dc266290c93Christian Maeder sdap_domain_remove(opts, dom);
be_ptask_destroy(&sdom->enum_task);
be_ptask_destroy(&sdom->cleanup_task);
/* terminate all requests for this subdomain so we can free it */
dp_terminate_domain_requests(be_ctx->provider, dom->name);
talloc_zfree(sdom);
} else {
/* ok let's try to update it */
ret = ad_subdom_enumerates(domain, subdomains[c], &enumerate);
if (ret != EOK) {
goto done;
}
ret = ad_subdom_store(idmap_ctx, domain, subdomains[c], enumerate);
if (ret) {
/* Nothing we can do about the error. Let's at least try
* to reuse the existing domains
*/
DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
"will try to use cached subdomain\n");
}
handled[c] = true;
h++;
}
}
if (num_subdomains == h) {
/* all domains were already accounted for and have been updated */
ret = EOK;
*_changes = false;
goto done;
}
/* if we get here it means we have changes to the subdomains list */
*_changes = true;
for (c = 0; c < num_subdomains; c++) {
if (handled[c]) {
continue;
}
/* Nothing we can do about the error. Let's at least try
* to reuse the existing domains.
*/
ret = ad_subdom_enumerates(domain, subdomains[c], &enumerate);
if (ret != EOK) {
goto done;
}
ret = ad_subdom_store(idmap_ctx, domain, subdomains[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) {
*_last_refreshed = 0;
} else {
*_last_refreshed = time(NULL);
}
return ret;
}
static errno_t ad_subdomains_process(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
size_t nsd, struct sysdb_attrs **sd,
struct sysdb_attrs *root,
size_t *_nsd_out,
struct sysdb_attrs ***_sd_out)
{
size_t i, sdi;
struct sysdb_attrs **sd_out;
const char *sd_name;
errno_t ret;
if (root == NULL) {
/* We are connected directly to the root domain. The 'sd'
* list is complete and we can just use it
*/
*_nsd_out = nsd;
*_sd_out = sd;
return EOK;
}
/* If we searched for root separately, we must:
* a) treat the root domain as a subdomain
* b) filter the subdomain we are connected to from the subdomain
* list, from our point of view, it's the master domain
*/
sd_out = talloc_zero_array(mem_ctx, struct sysdb_attrs *, nsd+1);
if (sd_out == NULL) {
return ENOMEM;
}
sdi = 0;
for (i = 0; i < nsd; i++) {
ret = sysdb_attrs_get_string(sd[i], AD_AT_TRUST_PARTNER, &sd_name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto fail;
}
if (strcasecmp(sd_name, domain->name) == 0) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"Not including primary domain %s in the subdomain list\n",
domain->name);
continue;
}
sd_out[sdi] = talloc_steal(sd_out, sd[i]);
sdi++;
}
/* Now include the root */
sd_out[sdi] = talloc_steal(sd_out, root);
*_nsd_out = sdi+1;
*_sd_out = sd_out;
return EOK;
fail:
talloc_free(sd_out);
return ret;
}
static errno_t
ads_store_sdap_subdom(struct ad_subdomains_ctx *ctx,
struct sss_domain_info *parent)
{
int ret;
struct sdap_domain *sditer;
struct ad_id_ctx *subdom_id_ctx;
ret = sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_domain_subdom_add failed.\n");
return ret;
}
DLIST_FOR_EACH(sditer, ctx->sdom) {
if (IS_SUBDOMAIN(sditer->dom) && sditer->pvt == NULL) {
ret = ad_subdom_ad_ctx_new(ctx->be_ctx, ctx->ad_id_ctx,
sditer->dom, &subdom_id_ctx);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ad_subdom_ad_ctx_new failed.\n");
} else {
sditer->pvt = subdom_id_ctx;
}
}
}
return EOK;
}
static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *subdoms_ctx)
{
const char *path;
errno_t ret;
bool canonicalize;
path = dp_opt_get_string(subdoms_ctx->ad_id_ctx->ad_options->basic,
AD_KRB5_CONFD_PATH);
canonicalize = dp_opt_get_bool(
subdoms_ctx->ad_id_ctx->ad_options->auth_ctx->opts,
KRB5_CANONICALIZE);
ret = sss_write_krb5_conf_snippet(path, canonicalize);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
/* Just continue */
}
ret = sysdb_update_subdomains(subdoms_ctx->be_ctx->domain);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
return ret;
}
ret = sss_write_domain_mappings(subdoms_ctx->be_ctx->domain);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "sss_krb5_write_mappings failed.\n");
/* Just continue */
}
ret = ads_store_sdap_subdom(subdoms_ctx, subdoms_ctx->be_ctx->domain);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ads_store_sdap_subdom failed.\n");
return ret;
}
return EOK;
}
struct ad_get_slave_domain_state {
struct tevent_context *ev;
struct ad_subdomains_ctx *sd_ctx;
struct be_ctx *be_ctx;
struct sdap_options *opts;
struct sdap_idmap_ctx *idmap_ctx;
struct sysdb_attrs *root_attrs;
struct sdap_id_op *sdap_op;
};
static errno_t ad_get_slave_domain_retry(struct tevent_req *req);
static void ad_get_slave_domain_connect_done(struct tevent_req *subreq);
static void ad_get_slave_domain_done(struct tevent_req *subreq);
static struct tevent_req *
ad_get_slave_domain_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct ad_subdomains_ctx *sd_ctx,
struct sysdb_attrs *root_attrs,
struct ad_id_ctx *root_id_ctx)
{
struct ad_get_slave_domain_state *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_create(mem_ctx, &state,
struct ad_get_slave_domain_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
return NULL;
}
state->ev = ev;
state->sd_ctx = sd_ctx;
state->be_ctx = sd_ctx->be_ctx;
state->opts = root_id_ctx->sdap_id_ctx->opts;
state->idmap_ctx = root_id_ctx->sdap_id_ctx->opts->idmap_ctx;
state->root_attrs = root_attrs;
state->sdap_op = sdap_id_op_create(state, root_id_ctx->ldap_ctx->conn_cache);
if (state->sdap_op == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
ret = ENOMEM;
goto immediately;
}
ret = ad_get_slave_domain_retry(req);
if (ret == EAGAIN) {
/* asynchronous processing */
return req;
}
immediately:
if (ret == EOK) {
tevent_req_done(req);
} else {
tevent_req_error(req, ret);
}
tevent_req_post(req, ev);
return req;
}
static errno_t ad_get_slave_domain_retry(struct tevent_req *req)
{
struct ad_get_slave_domain_state *state;
struct tevent_req *subreq;
int ret;
state = tevent_req_data(req, struct ad_get_slave_domain_state);
subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed "
"[%d]: %s\n", ret, sss_strerror(ret));
return ret;
}
tevent_req_set_callback(subreq, ad_get_slave_domain_connect_done, req);
return EAGAIN;
}
static void ad_get_slave_domain_connect_done(struct tevent_req *subreq)
{
struct ad_get_slave_domain_state *state;
struct tevent_req *req = NULL;
int dp_error;
errno_t ret;
const char *attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
AD_AT_SID, AD_AT_TRUST_TYPE,
AD_AT_TRUST_ATTRS, NULL };
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_get_slave_domain_state);
ret = sdap_id_op_connect_recv(subreq, &dp_error);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP "
"[%d]: %s\n", ret, sss_strerror(ret));
if (dp_error == DP_ERR_OFFLINE) {
DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, "
"cannot get the subdomain list while offline\n");
ret = ERR_OFFLINE;
}
tevent_req_error(req, ret);
return;
}
subreq = sdap_search_bases_send(state, state->ev, state->opts,
sdap_id_op_handle(state->sdap_op),
state->opts->sdom->search_bases,
NULL, false, 0,
SLAVE_DOMAIN_FILTER, attrs);
if (subreq == NULL) {
tevent_req_error(req, ret);
return;
}
tevent_req_set_callback(subreq, ad_get_slave_domain_done, req);
return;
}
static void ad_get_slave_domain_done(struct tevent_req *subreq)
{
struct ad_get_slave_domain_state *state;
struct tevent_req *req;
struct sysdb_attrs **reply;
size_t reply_count;
struct sysdb_attrs **subdoms;
size_t nsubdoms;
bool has_changes;
int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_get_slave_domain_state);
ret = sdap_search_bases_recv(subreq, state, &reply_count, &reply);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup slave domain data "
"[%d]: %s\n", ret, sss_strerror(ret));
/* We continue to finish sdap_id_op. */
}
ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
if (dp_error == DP_ERR_OK && ret != EOK) {
/* retry */
ret = ad_get_slave_domain_retry(req);
if (ret != EOK) {
goto done;
}
return;
} else if (dp_error == DP_ERR_OFFLINE) {
ret = ERR_OFFLINE;
goto done;
} else if (ret != EOK) {
goto done;
}
/* Based on whether we are connected to the forest root or not, we might
* need to exclude the subdomain we are connected to from the list of
* subdomains.
*/
ret = ad_subdomains_process(state, state->be_ctx->domain,
reply_count, reply, state->root_attrs,
&nsubdoms, &subdoms);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Cannot process subdomain list\n");
tevent_req_error(req, ret);
return;
}
/* Got all the subdomains, let's process them. */
ret = ad_subdomains_refresh(state->be_ctx, state->idmap_ctx, state->opts,
subdoms, nsubdoms, false,
&state->sd_ctx->last_refreshed,
&has_changes);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Failed to refresh subdomains.\n");
goto done;
}
DEBUG(SSSDBG_TRACE_LIBS, "There are %schanges\n",
has_changes ? "" : "no ");
if (has_changes) {
ret = ad_subdom_reinit(state->sd_ctx);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
goto done;
}
}
state->sd_ctx->last_refreshed = time(NULL);
ret = EOK;
done:
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
tevent_req_done(req);
}
static errno_t ad_get_slave_domain_recv(struct tevent_req *req)
{
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
}
static struct sss_domain_info *
ads_get_root_domain(struct be_ctx *be_ctx, struct sysdb_attrs *attrs)
{
struct sss_domain_info *root;
const char *name;
errno_t ret;
ret = sysdb_attrs_get_string(attrs, AD_AT_TRUST_PARTNER, &name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
return NULL;
}
/* With a subsequent run, the root should already be known */
root = find_domain_by_name(be_ctx->domain, name, false);
return root;
}
static struct ad_id_ctx *
ads_get_root_id_ctx(struct be_ctx *be_ctx,
struct ad_id_ctx *ad_id_ctx,
struct sss_domain_info *root_domain,
struct sdap_options *opts)
{
errno_t ret;
struct sdap_domain *sdom;
struct ad_id_ctx *root_id_ctx;
sdom = sdap_domain_get(opts, root_domain);
if (sdom == NULL) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannot get the sdom for %s!\n", root_domain->name);
return NULL;
}
if (sdom->pvt == NULL) {
ret = ad_subdom_ad_ctx_new(be_ctx, ad_id_ctx, root_domain,
&root_id_ctx);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ad_subdom_ad_ctx_new failed.\n");
return NULL;
}
sdom->pvt = root_id_ctx;
} else {
root_id_ctx = sdom->pvt;
}
root_id_ctx->ldap_ctx->ignore_mark_offline = true;
return root_id_ctx;
}
struct ad_get_root_domain_state {
struct ad_subdomains_ctx *sd_ctx;
struct be_ctx *be_ctx;
struct sdap_idmap_ctx *idmap_ctx;
struct sdap_options *opts;
struct ad_id_ctx *root_id_ctx;
struct sysdb_attrs *root_domain_attrs;
};
static void ad_get_root_domain_done(struct tevent_req *subreq);
static struct tevent_req *
ad_get_root_domain_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
const char *forest,
struct sdap_handle *sh,
struct ad_subdomains_ctx *sd_ctx)
{
struct ad_get_root_domain_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
struct sdap_options *opts;
errno_t ret;
const char *filter;
const char *attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
AD_AT_SID, AD_AT_TRUST_TYPE,
AD_AT_TRUST_ATTRS, NULL };
req = tevent_req_create(mem_ctx, &state, struct ad_get_root_domain_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
return NULL;
}
if (forest != NULL && strcasecmp(sd_ctx->be_ctx->domain->name, forest) == 0) {
state->root_id_ctx = sd_ctx->ad_id_ctx;
state->root_domain_attrs = NULL;
ret = EOK;
goto immediately;
}
DEBUG(SSSDBG_TRACE_FUNC, "Looking up the forest root domain.\n");
state->sd_ctx = sd_ctx;
state->opts = opts = sd_ctx->sdap_id_ctx->opts;
state->be_ctx = sd_ctx->be_ctx;
state->idmap_ctx = opts->idmap_ctx;
filter = talloc_asprintf(state, FOREST_ROOT_FILTER_FMT, forest);
if (filter == NULL) {
ret = ENOMEM;
goto immediately;
}
subreq = sdap_search_bases_return_first_send(state, ev, opts, sh,
opts->sdom->search_bases,
NULL, false, 0, filter, attrs);
if (subreq == NULL) {
ret = ENOMEM;
goto immediately;
}
tevent_req_set_callback(subreq, ad_get_root_domain_done, req);
return req;
immediately:
if (ret == EOK) {
tevent_req_done(req);
} else {
tevent_req_error(req, ret);
}
tevent_req_post(req, ev);
return req;
}
static void ad_get_root_domain_done(struct tevent_req *subreq)
{
struct tevent_req *req;
struct ad_get_root_domain_state *state;
struct sysdb_attrs **reply;
struct sss_domain_info *root_domain;
size_t reply_count;
bool has_changes;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_get_root_domain_state);
ret = sdap_search_bases_return_first_recv(subreq, state, &reply_count,
&reply);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unable to lookup forest root information "
"[%d]: %s\n", ret, sss_strerror(ret));
goto done;
}
if (reply_count == 0) {
DEBUG(SSSDBG_OP_FAILURE, "No information provided for root domain\n");
ret = ENOENT;
goto done;
} else if (reply_count > 1) {
DEBUG(SSSDBG_CRIT_FAILURE, "Multiple results for root domain search, "
"domain list might be incomplete!\n");
ret = ERR_MALFORMED_ENTRY;
goto done;
}
ret = ad_subdomains_refresh(state->be_ctx, state->idmap_ctx, state->opts,
reply, reply_count, true,
&state->sd_ctx->last_refreshed,
&has_changes);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ad_subdomains_refresh failed [%d]: %s\n",
ret, sss_strerror(ret));
goto done;
}
if (has_changes) {
ret = ad_subdom_reinit(state->sd_ctx);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
goto done;
}
}
state->root_domain_attrs = reply[0];
root_domain = ads_get_root_domain(state->be_ctx, reply[0]);
if (root_domain == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n");
ret = EFAULT;
goto done;
}
state->root_id_ctx = ads_get_root_id_ctx(state->be_ctx,
state->sd_ctx->ad_id_ctx,
root_domain, state->opts);
if (state->root_id_ctx == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "Cannot create id ctx for the root domain\n");
ret = EFAULT;
goto done;
}
ret = EOK;
done:
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
tevent_req_done(req);
}
static errno_t ad_get_root_domain_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
struct sysdb_attrs **_attrs,
struct ad_id_ctx **_id_ctx)
{
struct ad_get_root_domain_state *state = NULL;
state = tevent_req_data(req, struct ad_get_root_domain_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
*_attrs = talloc_steal(mem_ctx, state->root_domain_attrs);
*_id_ctx = state->root_id_ctx;
return EOK;
}
struct ad_subdomains_refresh_state {
struct tevent_context *ev;
struct be_ctx *be_ctx;
struct ad_subdomains_ctx *sd_ctx;
struct sdap_id_op *sdap_op;
struct sdap_id_ctx *id_ctx;
struct ad_options *ad_options;
};
static errno_t ad_subdomains_refresh_retry(struct tevent_req *req);
static void ad_subdomains_refresh_connect_done(struct tevent_req *subreq);
static void ad_subdomains_refresh_master_done(struct tevent_req *subreq);
static void ad_subdomains_refresh_root_done(struct tevent_req *subreq);
static void ad_subdomains_refresh_done(struct tevent_req *subreq);
static struct tevent_req *
ad_subdomains_refresh_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct ad_subdomains_ctx *sd_ctx)
{
struct ad_subdomains_refresh_state *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_create(mem_ctx, &state,
struct ad_subdomains_refresh_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
return NULL;
}
state->ev = ev;
state->be_ctx = sd_ctx->be_ctx;
state->sd_ctx = sd_ctx;
state->id_ctx = sd_ctx->sdap_id_ctx;
state->ad_options = sd_ctx->ad_id_ctx->ad_options;
state->sdap_op = sdap_id_op_create(state,
sd_ctx->sdap_id_ctx->conn->conn_cache);
if (state->sdap_op == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
ret = ENOMEM;
goto immediately;
}
ret = ad_subdomains_refresh_retry(req);
if (ret == EAGAIN) {
/* asynchronous processing */
return req;
}
immediately:
if (ret == EOK) {
tevent_req_done(req);
} else {
tevent_req_error(req, ret);
}
tevent_req_post(req, ev);
return req;
}
static errno_t ad_subdomains_refresh_retry(struct tevent_req *req)
{
struct ad_subdomains_refresh_state *state;
struct tevent_req *subreq;
int ret;
state = tevent_req_data(req, struct ad_subdomains_refresh_state);
subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed "
"[%d]: %s\n", ret, sss_strerror(ret));
return ret;
}
tevent_req_set_callback(subreq, ad_subdomains_refresh_connect_done, req);
return EAGAIN;
}
static void ad_subdomains_refresh_connect_done(struct tevent_req *subreq)
{
struct ad_subdomains_refresh_state *state;
struct tevent_req *req;
int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_subdomains_refresh_state);
ret = sdap_id_op_connect_recv(subreq, &dp_error);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP "
"[%d]: %s\n", ret, sss_strerror(ret));
if (dp_error == DP_ERR_OFFLINE) {
DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, "
"cannot get the subdomain list while offline\n");
ret = ERR_OFFLINE;
}
tevent_req_error(req, ret);
return;
}
subreq = ad_master_domain_send(state, state->ev, state->id_ctx->conn,
state->sdap_op, state->sd_ctx->domain_name);
if (subreq == NULL) {
tevent_req_error(req, ENOMEM);
return;
}
tevent_req_set_callback(subreq, ad_subdomains_refresh_master_done, req);
return;
}
static void ad_subdomains_refresh_master_done(struct tevent_req *subreq)
{
struct ad_subdomains_refresh_state *state;
struct tevent_req *req;
const char *realm;
char *master_sid;
char *flat_name;
char *forest;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_subdomains_refresh_state);
ret = ad_master_domain_recv(subreq, state, &flat_name, &master_sid,
NULL, &forest);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get master domain information "
"[%d]: %s\n", ret, sss_strerror(ret));
goto done;
}
realm = dp_opt_get_cstring(state->ad_options->basic, AD_KRB5_REALM);
if (realm == NULL) {
DEBUG(SSSDBG_CONF_SETTINGS, "Missing realm.\n");
ret = EINVAL;
goto done;
}
ret = sysdb_master_domain_add_info(state->be_ctx->domain, realm,
flat_name, master_sid, forest, NULL);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Cannot save master domain info [%d]: %s\n",
ret, sss_strerror(ret));
goto done;
}
subreq = ad_get_root_domain_send(state, state->ev, forest,
sdap_id_op_handle(state->sdap_op),
state->sd_ctx);
if (subreq == NULL) {
ret = ENOMEM;
goto done;
}
tevent_req_set_callback(subreq, ad_subdomains_refresh_root_done, req);
return;
done:
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
tevent_req_done(req);
}
static void ad_subdomains_refresh_root_done(struct tevent_req *subreq)
{
struct ad_subdomains_refresh_state *state;
struct tevent_req *req;
struct ad_id_ctx *root_id_ctx;
struct sysdb_attrs *root_attrs;
int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_subdomains_refresh_state);
ret = ad_get_root_domain_recv(state, subreq, &root_attrs, &root_id_ctx);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get forest root [%d]: %s\n",
ret, sss_strerror(ret));
root_attrs = NULL;
root_id_ctx = NULL;
/* We continue to finish sdap_id_op. */
}
/* We finish sdap_id_op here since we connect
* to forest root for slave domains. */
ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
if (dp_error == DP_ERR_OK && ret != EOK) {
/* retry */
ret = ad_subdomains_refresh_retry(req);
if (ret != EOK) {
tevent_req_error(req, ret);
}
return;
} else if (dp_error == DP_ERR_OFFLINE) {
tevent_req_error(req, ERR_OFFLINE);
return;
} else if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
subreq = ad_get_slave_domain_send(state, state->ev, state->sd_ctx,
root_attrs, root_id_ctx);
if (subreq == NULL) {
tevent_req_error(req, ENOMEM);
return;
}
tevent_req_set_callback(subreq, ad_subdomains_refresh_done, req);
return;
}
static void ad_subdomains_refresh_done(struct tevent_req *subreq)
{
struct tevent_req *req;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
ret = ad_get_slave_domain_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unable to get subdomains [%d]: %s\n",
ret, sss_strerror(ret));
}
if (ret != EOK) {
DEBUG(SSSDBG_TRACE_FUNC, "Unable to refresh subdomains [%d]: %s\n",
ret, sss_strerror(ret));
tevent_req_error(req, ret);
return;
}
DEBUG(SSSDBG_TRACE_FUNC, "Subdomains refreshed.\n");
tevent_req_done(req);
}
static errno_t ad_subdomains_refresh_recv(struct tevent_req *req)
{
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
}
struct ad_subdomains_handler_state {
struct dp_reply_std reply;
};
static void ad_subdomains_handler_done(struct tevent_req *subreq);
static struct tevent_req *
ad_subdomains_handler_send(TALLOC_CTX *mem_ctx,
struct ad_subdomains_ctx *sd_ctx,
struct dp_subdomains_data *data,
struct dp_req_params *params)
{
struct ad_subdomains_handler_state *state;
struct tevent_req *req;
struct tevent_req *subreq;
errno_t ret;
req = tevent_req_create(mem_ctx, &state,
struct ad_subdomains_handler_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
return NULL;
}
if (sd_ctx->last_refreshed > time(NULL) - AD_SUBDOMAIN_REFRESH_LIMIT) {
DEBUG(SSSDBG_TRACE_FUNC, "Subdomains were recently refreshed, "
"nothing to do\n");
ret = EOK;
goto immediately;
}
subreq = ad_subdomains_refresh_send(state, params->ev, sd_ctx);
if (subreq == NULL) {
ret = ENOMEM;
goto immediately;
}
tevent_req_set_callback(subreq, ad_subdomains_handler_done, req);
return req;
immediately:
dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
tevent_req_post(req, params->ev);
return req;
}
static void ad_subdomains_handler_done(struct tevent_req *subreq)
{
struct ad_subdomains_handler_state *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_subdomains_handler_state);
ret = ad_subdomains_refresh_recv(subreq);
talloc_zfree(subreq);
/* TODO For backward compatibility we always return EOK to DP now. */
dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
tevent_req_done(req);
}
static errno_t ad_subdomains_handler_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
struct dp_reply_std *data)
{
struct ad_subdomains_handler_state *state;
state = tevent_req_data(req, struct ad_subdomains_handler_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
*data = state->reply;
return EOK;
}
static struct tevent_req *
ad_subdomains_ptask_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct be_ctx *be_ctx,
struct be_ptask *be_ptask,
void *pvt)
{
struct ad_subdomains_ctx *sd_ctx;
sd_ctx = talloc_get_type(pvt, struct ad_subdomains_ctx);
return ad_subdomains_refresh_send(mem_ctx, ev, sd_ctx);
}
static errno_t
ad_subdomains_ptask_recv(struct tevent_req *req)
{
return ad_subdomains_refresh_recv(req);
}
errno_t ad_subdomains_init(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
struct ad_id_ctx *ad_id_ctx,
struct dp_method *dp_methods)
{
struct ad_subdomains_ctx *sd_ctx;
const char *ad_domain;
const char **ad_enabled_domains = NULL;
time_t period;
errno_t ret;
ad_domain = dp_opt_get_string(ad_id_ctx->ad_options->basic, AD_DOMAIN);
sd_ctx = talloc_zero(mem_ctx, struct ad_subdomains_ctx);
if (sd_ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
return ENOMEM;
}
ret = ad_get_enabled_domains(sd_ctx, ad_id_ctx, ad_domain,
&ad_enabled_domains);
if (ret != EOK) {
return EINVAL;
}
sd_ctx->be_ctx = be_ctx;
sd_ctx->sdom = ad_id_ctx->sdap_id_ctx->opts->sdom;
sd_ctx->sdap_id_ctx = ad_id_ctx->sdap_id_ctx;
sd_ctx->domain_name = talloc_strdup(sd_ctx, ad_domain);
if (sd_ctx->domain_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
return ENOMEM;
}
sd_ctx->ad_enabled_domains = ad_enabled_domains;
sd_ctx->ad_id_ctx = ad_id_ctx;
dp_set_method(dp_methods, DPM_DOMAINS_HANDLER,
ad_subdomains_handler_send, ad_subdomains_handler_recv, sd_ctx,
struct ad_subdomains_ctx, struct dp_subdomains_data, struct dp_reply_std);
period = be_ctx->domain->subdomain_refresh_interval;
ret = be_ptask_create(sd_ctx, be_ctx, period, 0, 0, 0, period,
BE_PTASK_OFFLINE_DISABLE, 0,
ad_subdomains_ptask_send, ad_subdomains_ptask_recv, sd_ctx,
"Subdomains Refresh", NULL);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup ptask "
"[%d]: %s\n", ret, sss_strerror(ret));
/* Ignore, responders will trigger refresh from time to time. */
}
ret = ad_subdom_reinit(sd_ctx);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "Could not reinitialize subdomains. "
"Users from trusted domains might not be resolved correctly\n");
/* Ignore this error and try to discover the subdomains later */
}
return EOK;
}