sysdb_subdomains.c revision b5825c74b6bf7a99ae2172392dbecb51179013a6
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce/*
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce SSSD
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce System Database - Sub-domain related calls
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce Copyright (C) 2012 Jan Zeleny <jzeleny@redhat.com>
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce Copyright (C) 2012 Sumit Bose <sbose@redhat.com>
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce This program is free software; you can redistribute it and/or modify
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce it under the terms of the GNU General Public License as published by
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce the Free Software Foundation; either version 3 of the License, or
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce (at your option) any later version.
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce This program is distributed in the hope that it will be useful,
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce but WITHOUT ANY WARRANTY; without even the implied warranty of
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce GNU General Public License for more details.
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce You should have received a copy of the GNU General Public License
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce along with this program. If not, see <http://www.gnu.org/licenses/>.
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce*/
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce#include "util/util.h"
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce#include "db/sysdb_private.h"
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorcestruct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce struct sss_domain_info *parent,
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce const char *name,
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce const char *realm,
edaadf8de0c86a2cfff2d29215775d42919476f3Pavel Březina const char *flat_name,
edaadf8de0c86a2cfff2d29215775d42919476f3Pavel Březina const char *id,
4ebab24f65b54720a6672898b76185462015ababPavel Březina bool mpg,
75d66aea7accc842e68c88f085f9053112b20eccPavel Březina bool enumerate,
c1058e96679c7ed1372825bf5226ce7d28a8e6ffPavel Březina const char *forest,
dee7a89098b698e756f63e4041734d7322ad8b1ePavel Březina uint32_t trust_direction)
ab967283b710dfa05d11ee5b30c7ac916486ceecSimo Sorce{
c6872e79e8496fd075e20aec0343ade99cca725cSimo Sorce struct sss_domain_info *dom;
c6872e79e8496fd075e20aec0343ade99cca725cSimo Sorce bool inherit_option;
c6872e79e8496fd075e20aec0343ade99cca725cSimo Sorce
2745b0156f12df7a7eb93d57716233243658e4d9Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC,
22a21e910fd216ec1468fe769dcc29f1621a52a4Ondrej Kos "Creating [%s] as subdomain of [%s]!\n", name, parent->name);
ab967283b710dfa05d11ee5b30c7ac916486ceecSimo Sorce
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek dom = talloc_zero(mem_ctx, struct sss_domain_info);
ab967283b710dfa05d11ee5b30c7ac916486ceecSimo Sorce if (dom == NULL) {
ab967283b710dfa05d11ee5b30c7ac916486ceecSimo Sorce DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
c6872e79e8496fd075e20aec0343ade99cca725cSimo Sorce return NULL;
233a3c6c48972b177e60d6ef4cecfacd3cf31659Simo Sorce }
c6872e79e8496fd075e20aec0343ade99cca725cSimo Sorce
c6872e79e8496fd075e20aec0343ade99cca725cSimo Sorce dom->parent = parent;
233a3c6c48972b177e60d6ef4cecfacd3cf31659Simo Sorce
233a3c6c48972b177e60d6ef4cecfacd3cf31659Simo Sorce /* Sub-domains always have the same view as the parent */
7c69221077c780e62f6c536e78675f2dc1c131bcMichal Zidek dom->has_views = parent->has_views;
7c69221077c780e62f6c536e78675f2dc1c131bcMichal Zidek if (parent->view_name != NULL) {
7c69221077c780e62f6c536e78675f2dc1c131bcMichal Zidek dom->view_name = talloc_strdup(dom, parent->view_name);
aa7202c8ae677becd6c91d6a27a607fe0f3995eePavel Březina if (dom->view_name == NULL) {
f9961e5f82e0ef474d6492371bfdf9e74e208a99Pavel Březina DEBUG(SSSDBG_OP_FAILURE, "Failed to copy parent's view name.\n");
f9961e5f82e0ef474d6492371bfdf9e74e208a99Pavel Březina goto fail;
7a4e3e29196e3abc1746714fcf93624edae89f93Lukas Slebodnik }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek dom->name = talloc_strdup(dom, name);
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek if (dom->name == NULL) {
dcc6877aa2e2dd63a9dc9c411a9c58feaeb36b9aStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "Failed to copy domain name.\n");
bc30ce9b7d588a17e58012e699986f0d6898b791Pavel Březina goto fail;
2a96981a0ac781d01e5bba473409ed2bdf4cd4e0Jakub Hrozek }
e81deec535d11912b87954c81a1edd768c1386c9Jakub Hrozek
4dd38025efda88f123eac672f87d3cda12f050c8Jakub Hrozek dom->provider = talloc_strdup(dom, parent->provider);
4dd38025efda88f123eac672f87d3cda12f050c8Jakub Hrozek if (dom->provider == NULL) {
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "Failed to copy provider name.\n");
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek goto fail;
7a4e3e29196e3abc1746714fcf93624edae89f93Lukas Slebodnik }
60cab26b12df9a2153823972cde0c38ca86e01b9Yassir Elley
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter dom->conn_name = talloc_strdup(dom, parent->conn_name);
0c1d65998907930678da2d091789446f2c344d5dJakub Hrozek if (dom->conn_name == NULL) {
a2ea3f5d9ef9f17efbb61e942c2bc6cff7d1ebf2Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "Failed to copy connection name.\n");
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozek goto fail;
78a08d30b5fbf6e1e3b589e0cf67022e0c1faa33Michal Židek }
8394eddba54b5d3e3fda868145e3751247bdbdb2Michal Zidek
5a5c5cdeb92f4012fc75fd717bfea06598f68f12Pavel Reichl if (realm != NULL) {
7a4e3e29196e3abc1746714fcf93624edae89f93Lukas Slebodnik dom->realm = talloc_strdup(dom, realm);
1243e093fd31c5660adf1bb3dd477d6935a755beJakub Hrozek if (dom->realm == NULL) {
1243e093fd31c5660adf1bb3dd477d6935a755beJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "Failed to copy realm name.\n");
7a4e3e29196e3abc1746714fcf93624edae89f93Lukas Slebodnik goto fail;
979e8d8d6ed444007eeff6be5269e8dc5d2bdf68Pavel Reichl }
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek }
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (flat_name != NULL) {
a8d887323f83984679a7d9b827a70146656bb7b2Sumit Bose dom->flat_name = talloc_strdup(dom, flat_name);
b42bf6c0c01db08208fb81d8295a2909d307284aPavel Reichl if (dom->flat_name == NULL) {
9118a539a5d59f669f551114f880fe91d6bb8741Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "Failed to copy flat name.\n");
b5825c74b6bf7a99ae2172392dbecb51179013a6Jakub Hrozek goto fail;
19e44537c28f6d5f011cd7ac885c74c1e892605fSimo Sorce }
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose }
c30b7a1931211fdcae0564551a7625cc4f6dee9fJakub Hrozek
e732d23f3ec986a463d757781a334040e03d1f59Jakub Hrozek if (id != NULL) {
e732d23f3ec986a463d757781a334040e03d1f59Jakub Hrozek dom->domain_id = talloc_strdup(dom, id);
dd285415d7a8d8376207960cfa3e977524c3b98cJakub Hrozek if (dom->domain_id == NULL) {
dd285415d7a8d8376207960cfa3e977524c3b98cJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "Failed to copy id.\n");
beec1ee5799570f34a51ea57674c7291c15f7022Jakub Hrozek goto fail;
fcbcfa69f9291936f01f24b5fcb5a7672dca46f3Jakub Hrozek }
4714118890e51b365fbce543d0a042b4b59b2b25Michal Zidek }
efc65e78fa4e01e6cecc8690a9899af61213be62Fabiano Fidêncio
41cd6072648bb7a9e14e56ed38004a2947f67657Jakub Hrozek if (forest != NULL) {
65a38b8c9cabde6c46cc0e9868f54cb9bb10afbfFabiano Fidêncio dom->forest = talloc_strdup(dom, forest);
7171a7584dda534dde5409f3e7f4657e845ece15Fabiano Fidêncio if (dom->forest == NULL) {
d4757440418c7b73bbecec7e40baf6dfe8cc9460Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "Failed to copy forest.\n");
d4757440418c7b73bbecec7e40baf6dfe8cc9460Sumit Bose goto fail;
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek }
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek }
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek dom->enumerate = enumerate;
cac0db2f8004ae88b9263dc3888a11a2d3d3d114Jakub Hrozek dom->fqnames = true;
cac0db2f8004ae88b9263dc3888a11a2d3d3d114Jakub Hrozek dom->mpg = mpg;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina dom->state = DOM_ACTIVE;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* If the parent domain filters out group members, the subdomain should
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina * as well if configured */
c0f9f5a0f6d71a1596ee3cef549b4b02295313c3Jakub Hrozek inherit_option = string_in_list(CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS,
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek parent->sd_inherit, false);
2af80640f18966d65cf82106059ce3c060df93bfamitkuma if (inherit_option) {
ccd349f0274217e1f0cc118e3a6045e2235ce420Fabiano Fidêncio dom->ignore_group_members = parent->ignore_group_members;
7650ded4ffa87fcf7ce5adf00920fecf89cffcf5Michal Zidek }
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce dom->trust_direction = trust_direction;
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce /* If the parent domain explicitly limits ID ranges, the subdomain
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce * should honour the limits as well.
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce */
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce dom->id_min = parent->id_min ? parent->id_min : 0;
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce dom->id_max = parent->id_max ? parent->id_max : 0xffffffff;
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce dom->pwd_expiration_warning = parent->pwd_expiration_warning;
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce dom->cache_credentials = parent->cache_credentials;
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce dom->cache_credentials_min_ff_length =
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce parent->cache_credentials_min_ff_length;
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce dom->case_sensitive = false;
dom->user_timeout = parent->user_timeout;
dom->group_timeout = parent->group_timeout;
dom->netgroup_timeout = parent->netgroup_timeout;
dom->service_timeout = parent->service_timeout;
dom->names = parent->names;
dom->override_homedir = parent->override_homedir;
dom->fallback_homedir = parent->fallback_homedir;
dom->subdomain_homedir = parent->subdomain_homedir;
dom->override_shell = parent->override_shell;
dom->default_shell = parent->default_shell;
dom->homedir_substr = parent->homedir_substr;
if (parent->sysdb == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "Missing sysdb context in parent domain.\n");
goto fail;
}
dom->sysdb = parent->sysdb;
return dom;
fail:
talloc_free(dom);
return NULL;
}
static bool is_forest_root(struct sss_domain_info *d)
{
if (d->forest == NULL) {
/* IPA subdomain provider saves/saved trusted forest root domains
* without the forest attribute. Those are automatically forest
* roots
*/
return true;
}
if (d->realm && (strcasecmp(d->forest, d->realm) == 0)) {
return true;
}
return false;
}
static bool is_same_forest(struct sss_domain_info *root,
struct sss_domain_info *member)
{
if (member->forest != NULL
&& root->realm != NULL
&& strcasecmp(member->forest, root->realm) == 0) {
return true;
}
return false;
}
static void link_forest_roots(struct sss_domain_info *domain)
{
struct sss_domain_info *d;
struct sss_domain_info *dd;
for (d = domain; d; d = get_next_domain(d, true)) {
d->forest_root = NULL;
}
for (d = domain; d; d = get_next_domain(d, true)) {
if (d->forest_root != NULL) {
continue;
}
if (is_forest_root(d) == true) {
d->forest_root = d;
DEBUG(SSSDBG_TRACE_INTERNAL, "[%s] is a forest root\n", d->name);
for (dd = domain; dd; dd = get_next_domain(dd, true)) {
if (dd->forest_root != NULL) {
continue;
}
if (is_same_forest(d, dd) == true) {
dd->forest_root = d;
DEBUG(SSSDBG_TRACE_INTERNAL,
"[%s] is a forest root of [%s]\n",
d->forest_root->name,
dd->name);
}
}
}
}
}
errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
{
int i;
errno_t ret;
TALLOC_CTX *tmp_ctx;
struct ldb_result *res;
const char *attrs[] = {"cn",
SYSDB_SUBDOMAIN_REALM,
SYSDB_SUBDOMAIN_FLAT,
SYSDB_SUBDOMAIN_ID,
SYSDB_SUBDOMAIN_MPG,
SYSDB_SUBDOMAIN_ENUM,
SYSDB_SUBDOMAIN_FOREST,
SYSDB_SUBDOMAIN_TRUST_DIRECTION,
NULL};
struct sss_domain_info *dom;
struct ldb_dn *basedn;
const char *name;
const char *realm;
const char *flat;
const char *id;
const char *forest;
bool mpg;
bool enumerate;
uint32_t trust_direction;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
ret = ENOMEM;
goto done;
}
basedn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, SYSDB_BASE);
if (basedn == NULL) {
ret = EIO;
goto done;
}
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res,
basedn, LDB_SCOPE_ONELEVEL,
attrs, "objectclass=%s", SYSDB_SUBDOMAIN_CLASS);
if (ret != LDB_SUCCESS) {
ret = EIO;
goto done;
}
/* disable all domains,
* let the search result refresh any that are still valid */
for (dom = domain->subdomains; dom; dom = get_next_domain(dom, false)) {
sss_domain_set_state(dom, DOM_DISABLED);
}
if (res->count == 0) {
ret = EOK;
goto done;
}
for (i = 0; i < res->count; i++) {
name = ldb_msg_find_attr_as_string(res->msgs[i], "cn", NULL);
if (name == NULL) {
DEBUG(SSSDBG_MINOR_FAILURE,
"The object [%s] doesn't have a name\n",
ldb_dn_get_linearized(res->msgs[i]->dn));
ret = EINVAL;
goto done;
}
realm = ldb_msg_find_attr_as_string(res->msgs[i],
SYSDB_SUBDOMAIN_REALM, NULL);
flat = ldb_msg_find_attr_as_string(res->msgs[i],
SYSDB_SUBDOMAIN_FLAT, NULL);
id = ldb_msg_find_attr_as_string(res->msgs[i],
SYSDB_SUBDOMAIN_ID, NULL);
mpg = ldb_msg_find_attr_as_bool(res->msgs[i],
SYSDB_SUBDOMAIN_MPG, false);
enumerate = ldb_msg_find_attr_as_bool(res->msgs[i],
SYSDB_SUBDOMAIN_ENUM, false);
forest = ldb_msg_find_attr_as_string(res->msgs[i],
SYSDB_SUBDOMAIN_FOREST, NULL);
trust_direction = ldb_msg_find_attr_as_int(res->msgs[i],
SYSDB_SUBDOMAIN_TRUST_DIRECTION,
0);
/* explicitly use dom->next as we need to check 'disabled' domains */
for (dom = domain->subdomains; dom; dom = dom->next) {
if (strcasecmp(dom->name, name) == 0) {
sss_domain_set_state(dom, DOM_ACTIVE);
/* in theory these may change, but it should never happen */
if (strcasecmp(dom->realm, realm) != 0) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"Realm name changed from [%s] to [%s]!\n",
dom->realm, realm);
talloc_zfree(dom->realm);
dom->realm = talloc_strdup(dom, realm);
if (dom->realm == NULL) {
ret = ENOMEM;
goto done;
}
}
if (strcasecmp(dom->flat_name, flat) != 0) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"Flat name changed from [%s] to [%s]!\n",
dom->flat_name, flat);
talloc_zfree(dom->flat_name);
dom->flat_name = talloc_strdup(dom, flat);
if (dom->flat_name == NULL) {
ret = ENOMEM;
goto done;
}
}
if (strcasecmp(dom->domain_id, id) != 0) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"Domain changed from [%s] to [%s]!\n",
dom->domain_id, id);
talloc_zfree(dom->domain_id);
dom->domain_id = talloc_strdup(dom, id);
if (dom->domain_id == NULL) {
ret = ENOMEM;
goto done;
}
}
if (dom->mpg != mpg) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"MPG state change from [%s] to [%s]!\n",
dom->mpg ? "true" : "false",
mpg ? "true" : "false");
dom->mpg = mpg;
}
if (dom->enumerate != enumerate) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"enumerate state change from [%s] to [%s]!\n",
dom->enumerate ? "true" : "false",
enumerate ? "true" : "false");
dom->enumerate = enumerate;
}
if ((dom->forest == NULL && forest != NULL)
|| (dom->forest != NULL && forest != NULL
&& strcasecmp(dom->forest, forest) != 0)) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"Forest changed from [%s] to [%s]!\n",
dom->forest, forest);
talloc_zfree(dom->forest);
dom->forest = talloc_strdup(dom, forest);
if (dom->forest == NULL) {
ret = ENOMEM;
goto done;
}
}
if (!dom->has_views && dom->view_name == NULL) {
/* maybe views are not initialized, copy from parent */
dom->has_views = dom->parent->has_views;
if (dom->parent->view_name != NULL) {
dom->view_name = talloc_strdup(dom,
dom->parent->view_name);
if (dom->view_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE,
"Failed to copy parent's view name.\n");
ret = ENOMEM;
goto done;
}
}
} else {
if (dom->has_views != dom->parent->has_views
|| strcmp(dom->view_name,
dom->parent->view_name) != 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Sub-domain [%s][%s] and parent [%s][%s] " \
"views are different.\n",
dom->has_views ? "has view" : "has no view",
dom->view_name,
dom->parent->has_views ? "has view" : "has no view",
dom->parent->view_name);
ret = EINVAL;
goto done;
}
}
if (dom->trust_direction != trust_direction) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"Trust direction change from [%d] to [%d]!\n",
dom->trust_direction, trust_direction);
dom->trust_direction = trust_direction;
}
break;
}
}
/* If not found in loop it is a new subdomain */
if (dom == NULL) {
dom = new_subdomain(domain, domain, name, realm,
flat, id, mpg, enumerate, forest,
trust_direction);
if (dom == NULL) {
ret = ENOMEM;
goto done;
}
DLIST_ADD_END(domain->subdomains, dom, struct sss_domain_info *);
}
}
link_forest_roots(domain);
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t sysdb_master_domain_update(struct sss_domain_info *domain)
{
errno_t ret;
TALLOC_CTX *tmp_ctx;
const char *tmp_str;
struct ldb_dn *basedn;
struct ldb_result *res;
const char *attrs[] = {"cn",
SYSDB_SUBDOMAIN_REALM,
SYSDB_SUBDOMAIN_FLAT,
SYSDB_SUBDOMAIN_ID,
SYSDB_SUBDOMAIN_FOREST,
NULL};
char *view_name = NULL;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
basedn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
SYSDB_DOM_BASE, domain->name);
if (basedn == NULL) {
ret = EIO;
goto done;
}
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res,
basedn, LDB_SCOPE_BASE, attrs, NULL);
if (ret != LDB_SUCCESS) {
ret = EIO;
goto done;
}
if (res->count == 0) {
ret = ENOENT;
goto done;
}
if (res->count > 1) {
DEBUG(SSSDBG_OP_FAILURE, "Base search returned [%d] results, "
"expected 1.\n", res->count);
ret = EINVAL;
goto done;
}
tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_REALM,
NULL);
if (tmp_str != NULL &&
(domain->realm == NULL || strcasecmp(tmp_str, domain->realm) != 0)) {
talloc_free(domain->realm);
domain->realm = talloc_strdup(domain, tmp_str);
if (domain->realm == NULL) {
ret = ENOMEM;
goto done;
}
}
tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_FLAT,
NULL);
if (tmp_str != NULL &&
(domain->flat_name == NULL ||
strcasecmp(tmp_str, domain->flat_name) != 0)) {
talloc_free(domain->flat_name);
domain->flat_name = talloc_strdup(domain, tmp_str);
if (domain->flat_name == NULL) {
ret = ENOMEM;
goto done;
}
}
tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_ID,
NULL);
if (tmp_str != NULL &&
(domain->domain_id == NULL ||
strcasecmp(tmp_str, domain->domain_id) != 0)) {
talloc_free(domain->domain_id);
domain->domain_id = talloc_strdup(domain, tmp_str);
if (domain->domain_id == NULL) {
ret = ENOMEM;
goto done;
}
}
tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_FOREST,
NULL);
if (tmp_str != NULL &&
(domain->forest == NULL ||
strcasecmp(tmp_str, domain->forest) != 0)) {
talloc_free(domain->forest);
domain->forest = talloc_strdup(domain, tmp_str);
if (domain->forest == NULL) {
ret = ENOMEM;
goto done;
}
}
ret = sysdb_get_view_name(tmp_ctx, domain->sysdb, &view_name);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name failed.\n");
goto done;
}
/* If no view is defined the default view will be used. In this case
* domain->has_views is FALSE and
* domain->view_name is set to SYSDB_DEFAULT_VIEW_NAME
*
* If there is a view defined
* domain->has_views is TRUE and
* domain->view_name is set to the given view name
*
* Currently changing the view is not supported hence we have to check for
* changes and error out accordingly.
*/
if (ret == ENOENT || is_default_view(view_name)) {
/* handle default view */
if (domain->has_views) {
DEBUG(SSSDBG_CRIT_FAILURE,
"View name change is currently not supported. " \
"New view is the default view while current view is [%s]. " \
"View name is not changed!\n", domain->view_name);
} else {
if (domain->view_name == NULL) {
domain->view_name = talloc_strdup(domain,
SYSDB_DEFAULT_VIEW_NAME);
if (domain->view_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
ret = ENOMEM;
goto done;
}
} else {
if (strcmp(domain->view_name, SYSDB_DEFAULT_VIEW_NAME) != 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Domain [%s] has no view but view name [%s] " \
"is not the default view name [%s].\n",
domain->name, domain->view_name,
SYSDB_DEFAULT_VIEW_NAME);
ret = EINVAL;
goto done;
}
}
}
} else {
/* handle view other than default */
if (domain->has_views) {
if (strcmp(domain->view_name, view_name) != 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
"View name change is currently not supported. " \
"New view is [%s] while current view is [%s]. " \
"View name is not changed!\n",
view_name, domain->view_name);
}
} else {
if (domain->view_name == NULL) {
domain->has_views = true;
domain->view_name = talloc_steal(domain, view_name);
if (domain->view_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_steal failed.\n");
ret = ENOMEM;
goto done;
}
} else {
if (strcmp(domain->view_name, SYSDB_DEFAULT_VIEW_NAME) == 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
"View name change is currently not supported. " \
"New view is [%s] while current is the default view. " \
"View name is not changed!\n", view_name);
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
"Domain currently has no views, " \
"but current view name is set to [%s] " \
"and new view name is [%s].\n",
domain->view_name, view_name);
ret = EINVAL;
goto done;
}
}
}
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain,
const char *realm,
const char *flat,
const char *id,
const char* forest)
{
TALLOC_CTX *tmp_ctx;
struct ldb_message *msg;
int ret;
bool do_update = false;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
msg = ldb_msg_new(tmp_ctx);
if (msg == NULL) {
ret = ENOMEM;
goto done;
}
msg->dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
SYSDB_DOM_BASE, domain->name);
if (msg->dn == NULL) {
ret = EIO;
goto done;
}
if (flat != NULL && (domain->flat_name == NULL ||
strcmp(domain->flat_name, flat) != 0)) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FLAT,
LDB_FLAG_MOD_REPLACE, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FLAT, flat);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
do_update = true;
}
if (id != NULL && (domain->domain_id == NULL ||
strcmp(domain->domain_id, id) != 0)) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_ID,
LDB_FLAG_MOD_REPLACE, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_ID, id);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
do_update = true;
}
if (forest != NULL && (domain->forest == NULL ||
strcmp(domain->forest, forest) != 0)) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FOREST,
LDB_FLAG_MOD_REPLACE, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FOREST, forest);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
do_update = true;
}
if (realm != NULL && (domain->realm == NULL ||
strcmp(domain->realm, realm) != 0)) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_REALM,
LDB_FLAG_MOD_REPLACE, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_REALM, realm);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
do_update = true;
}
if (do_update == false) {
ret = EOK;
goto done;
}
ret = ldb_modify(domain->sysdb->ldb, msg);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add subdomain attributes to "
"[%s]: [%d][%s]!\n", domain->name, ret,
ldb_errstring(domain->sysdb->ldb));
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = sysdb_master_domain_update(domain);
if (ret != EOK) {
goto done;
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
const char *name, const char *realm,
const char *flat_name, const char *domain_id,
bool mpg, bool enumerate, const char *forest,
uint32_t trust_direction)
{
TALLOC_CTX *tmp_ctx;
struct ldb_message *msg;
struct ldb_dn *dn;
struct ldb_result *res;
const char *attrs[] = {"cn",
SYSDB_SUBDOMAIN_REALM,
SYSDB_SUBDOMAIN_FLAT,
SYSDB_SUBDOMAIN_ID,
SYSDB_SUBDOMAIN_MPG,
SYSDB_SUBDOMAIN_ENUM,
SYSDB_SUBDOMAIN_FOREST,
SYSDB_SUBDOMAIN_TRUST_DIRECTION,
NULL};
const char *tmp_str;
bool tmp_bool;
bool store = false;
int realm_flags = 0;
int flat_flags = 0;
int id_flags = 0;
int mpg_flags = 0;
int enum_flags = 0;
int forest_flags = 0;
int td_flags = 0;
uint32_t tmp_td;
int ret;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, name);
if (dn == NULL) {
ret = EIO;
goto done;
}
ret = ldb_search(sysdb->ldb, tmp_ctx, &res,
dn, LDB_SCOPE_BASE, attrs, NULL);
if (ret != LDB_SUCCESS) {
ret = EIO;
goto done;
}
if (res->count == 0) {
ret = sysdb_domain_create(sysdb, name);
if (ret) {
goto done;
}
store = true;
if (realm) realm_flags = LDB_FLAG_MOD_ADD;
if (flat_name) flat_flags = LDB_FLAG_MOD_ADD;
if (domain_id) id_flags = LDB_FLAG_MOD_ADD;
mpg_flags = LDB_FLAG_MOD_ADD;
enum_flags = LDB_FLAG_MOD_ADD;
if (forest) forest_flags = LDB_FLAG_MOD_ADD;
if (trust_direction) td_flags = LDB_FLAG_MOD_ADD;
} else if (res->count != 1) {
ret = EINVAL;
goto done;
} else { /* 1 found */
if (realm) {
tmp_str = ldb_msg_find_attr_as_string(res->msgs[0],
SYSDB_SUBDOMAIN_REALM, NULL);
if (!tmp_str || strcasecmp(tmp_str, realm) != 0) {
realm_flags = LDB_FLAG_MOD_REPLACE;
}
}
if (flat_name) {
tmp_str = ldb_msg_find_attr_as_string(res->msgs[0],
SYSDB_SUBDOMAIN_FLAT, NULL);
if (!tmp_str || strcasecmp(tmp_str, flat_name) != 0) {
flat_flags = LDB_FLAG_MOD_REPLACE;
}
}
if (domain_id) {
tmp_str = ldb_msg_find_attr_as_string(res->msgs[0],
SYSDB_SUBDOMAIN_ID, NULL);
if (!tmp_str || strcasecmp(tmp_str, domain_id) != 0) {
id_flags = LDB_FLAG_MOD_REPLACE;
}
}
tmp_bool = ldb_msg_find_attr_as_bool(res->msgs[0], SYSDB_SUBDOMAIN_MPG,
!mpg);
if (tmp_bool != mpg) {
mpg_flags = LDB_FLAG_MOD_REPLACE;
}
tmp_bool = ldb_msg_find_attr_as_bool(res->msgs[0], SYSDB_SUBDOMAIN_ENUM,
!enumerate);
if (tmp_bool != enumerate) {
enum_flags = LDB_FLAG_MOD_REPLACE;
}
if (forest) {
tmp_str = ldb_msg_find_attr_as_string(res->msgs[0],
SYSDB_SUBDOMAIN_FOREST, NULL);
if (!tmp_str || strcasecmp(tmp_str, forest) != 0) {
forest_flags = LDB_FLAG_MOD_REPLACE;
}
}
tmp_td = ldb_msg_find_attr_as_uint(res->msgs[0],
SYSDB_SUBDOMAIN_TRUST_DIRECTION,
0);
if (tmp_td != trust_direction) {
td_flags = LDB_FLAG_MOD_REPLACE;
}
}
if (!store && realm_flags == 0 && flat_flags == 0 && id_flags == 0
&& mpg_flags == 0 && enum_flags == 0 && forest_flags == 0
&& td_flags == 0) {
ret = EOK;
goto done;
}
msg = ldb_msg_new(tmp_ctx);
if (msg == NULL) {
ret = ENOMEM;
goto done;
}
msg->dn = dn;
if (store) {
ret = ldb_msg_add_empty(msg, SYSDB_OBJECTCLASS, LDB_FLAG_MOD_ADD, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_OBJECTCLASS, SYSDB_SUBDOMAIN_CLASS);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
}
if (realm_flags) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_REALM, realm_flags, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_REALM, realm);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
}
if (flat_flags) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FLAT, flat_flags, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FLAT, flat_name);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
}
if (id_flags) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_ID, id_flags, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_ID, domain_id);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
}
if (mpg_flags) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_MPG, mpg_flags, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_MPG,
mpg ? "TRUE" : "FALSE");
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
}
if (enum_flags) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_ENUM, enum_flags, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_ENUM,
enumerate ? "TRUE" : "FALSE");
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
}
if (forest_flags) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FOREST, forest_flags,
NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FOREST, forest);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
}
if (td_flags) {
ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_TRUST_DIRECTION,
td_flags, NULL);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = ldb_msg_add_fmt(msg, SYSDB_SUBDOMAIN_TRUST_DIRECTION,
"%u", trust_direction);
if (ret != LDB_SUCCESS) {
ret = sysdb_error_to_errno(ret);
goto done;
}
}
ret = ldb_modify(sysdb->ldb, msg);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add subdomain attributes to "
"[%s]: [%d][%s]!\n", name, ret,
ldb_errstring(sysdb->ldb));
ret = sysdb_error_to_errno(ret);
goto done;
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t sysdb_subdomain_delete(struct sysdb_ctx *sysdb, const char *name)
{
TALLOC_CTX *tmp_ctx = NULL;
struct ldb_dn *dn;
int ret;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
ret = ENOMEM;
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "Removing sub-domain [%s] from db.\n", name);
dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, name);
if (dn == NULL) {
ret = ENOMEM;
goto done;
}
ret = sysdb_delete_recursive(sysdb, dn, true);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n");
goto done;
}
done:
talloc_free(tmp_ctx);
return ret;
}