summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2013-09-25 13:42:24 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-09-27 10:33:25 +0200
commitc5711b0279ea85d69fe3c77dfb194360c346e1d7 (patch)
treeffc3b851532fdd0635f5b7b882f593aaa81681f4
parent82d248c7e7d61dba7065a1a744823bc06c1b5b96 (diff)
downloadsssd-c5711b0279ea85d69fe3c77dfb194360c346e1d7.tar.gz
sssd-c5711b0279ea85d69fe3c77dfb194360c346e1d7.tar.bz2
sssd-c5711b0279ea85d69fe3c77dfb194360c346e1d7.zip
IPA: store forest name for forest member domains
In order to fix https://fedorahosted.org/sssd/ticket/2093 the name of the forest must be known for a member domain of the forest.
-rw-r--r--src/confdb/confdb.h1
-rw-r--r--src/db/sysdb.h3
-rw-r--r--src/db/sysdb_subdomains.c51
-rw-r--r--src/providers/ad/ad_subdomains.c2
-rw-r--r--src/providers/ipa/ipa_subdomains.c87
-rw-r--r--src/tests/sysdb-tests.c16
-rw-r--r--src/util/domain_info_utils.c11
-rw-r--r--src/util/util.h3
8 files changed, 158 insertions, 16 deletions
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index cb2a6242..d1587cd4 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -238,6 +238,7 @@ struct sss_domain_info {
char *realm;
char *flat_name;
char *domain_id;
+ char *forest;
struct timeval subdomains_last_checked;
struct sss_domain_info *prev;
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index c2a42d5c..2f73873f 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -128,6 +128,7 @@
#define SYSDB_SUBDOMAIN_ID "domainID"
#define SYSDB_SUBDOMAIN_MPG "mpg"
#define SYSDB_SUBDOMAIN_ENUM "enumerate"
+#define SYSDB_SUBDOMAIN_FOREST "memberOfForest"
#define SYSDB_BASE_ID "baseID"
#define SYSDB_ID_RANGE_SIZE "idRangeSize"
@@ -375,7 +376,7 @@ errno_t sysdb_domain_create(struct sysdb_ctx *sysdb, const char *domain_name);
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);
+ bool mpg, bool enumerate, const char *forest);
errno_t sysdb_update_subdomains(struct sss_domain_info *domain);
diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
index 5ef9aef7..43c75799 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -35,6 +35,7 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
SYSDB_SUBDOMAIN_ID,
SYSDB_SUBDOMAIN_MPG,
SYSDB_SUBDOMAIN_ENUM,
+ SYSDB_SUBDOMAIN_FOREST,
NULL};
struct sss_domain_info *dom;
struct ldb_dn *basedn;
@@ -42,6 +43,7 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
const char *realm;
const char *flat;
const char *id;
+ const char *forest;
bool mpg;
bool enumerate;
@@ -101,6 +103,9 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
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);
+
/* 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) {
@@ -156,13 +161,27 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
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;
+ }
+ }
+
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);
+ flat, id, mpg, enumerate, forest);
if (dom == NULL) {
ret = ENOMEM;
goto done;
@@ -356,7 +375,7 @@ done:
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)
+ bool mpg, bool enumerate, const char *forest)
{
TALLOC_CTX *tmp_ctx;
struct ldb_message *msg;
@@ -368,6 +387,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
SYSDB_SUBDOMAIN_ID,
SYSDB_SUBDOMAIN_MPG,
SYSDB_SUBDOMAIN_ENUM,
+ SYSDB_SUBDOMAIN_FOREST,
NULL};
const char *tmp_str;
bool tmp_bool;
@@ -377,6 +397,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
int id_flags = 0;
int mpg_flags = 0;
int enum_flags = 0;
+ int forest_flags = 0;
int ret;
tmp_ctx = talloc_new(NULL);
@@ -407,6 +428,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
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;
} else if (res->count != 1) {
ret = EINVAL;
goto done;
@@ -443,10 +465,18 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
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;
+ }
+ }
}
if (!store && realm_flags == 0 && flat_flags == 0 && id_flags == 0
- && mpg_flags == 0 && enum_flags == 0) {
+ && mpg_flags == 0 && enum_flags == 0 && forest_flags == 0) {
ret = EOK;
goto done;
}
@@ -544,6 +574,21 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
}
}
+ 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;
+ }
+ }
+
ret = ldb_modify(sysdb->ldb, msg);
if (ret != LDB_SUCCESS) {
DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add subdomain attributes to "
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index b95f4e46..e8345ae5 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -160,7 +160,7 @@ ad_subdom_store(struct ad_subdomains_ctx *ctx,
/* AD subdomains are currently all mpg and do not enumerate */
ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str,
- true, false);
+ true, false, NULL);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("sysdb_subdomain_store failed.\n"));
goto done;
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 496af42b..03b780d6 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -456,6 +456,84 @@ static errno_t ipa_subdom_enumerates(struct sss_domain_info *parent,
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,
@@ -466,6 +544,7 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent,
char *realm;
const char *flat;
const char *id;
+ char *forest = NULL;
int ret;
bool mpg;
@@ -500,8 +579,14 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent,
mpg = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx, 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);
+ id, mpg, enumerate, forest);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE, ("sysdb_subdomain_store failed.\n"));
goto done;
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 781d3951..74b78917 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -4538,7 +4538,7 @@ START_TEST(test_sysdb_subdomain_create)
ret = sysdb_subdomain_store(test_ctx->sysdb,
dom1[0], dom1[1], dom1[2], dom1[3],
- false, false);
+ false, false, NULL);
fail_if(ret != EOK, "Could not set up the test (dom1)");
ret = sysdb_update_subdomains(test_ctx->domain);
@@ -4552,7 +4552,7 @@ START_TEST(test_sysdb_subdomain_create)
ret = sysdb_subdomain_store(test_ctx->sysdb,
dom2[0], dom2[1], dom2[2], dom2[3],
- false, false);
+ false, false, NULL);
fail_if(ret != EOK, "Could not set up the test (dom2)");
ret = sysdb_update_subdomains(test_ctx->domain);
@@ -4597,11 +4597,11 @@ START_TEST(test_sysdb_subdomain_store_user)
subdomain = new_subdomain(test_ctx, test_ctx->domain,
testdom[0], testdom[1], testdom[2], testdom[3],
- false, false);
+ false, false, NULL);
fail_unless(subdomain != NULL, "Failed to create new subdomin.");
ret = sysdb_subdomain_store(test_ctx->sysdb,
testdom[0], testdom[1], testdom[2], testdom[3],
- false, false);
+ false, false, NULL);
fail_if(ret != EOK, "Could not set up the test (test subdom)");
ret = sysdb_update_subdomains(test_ctx->domain);
@@ -4668,11 +4668,11 @@ START_TEST(test_sysdb_subdomain_user_ops)
subdomain = new_subdomain(test_ctx, test_ctx->domain,
testdom[0], testdom[1], testdom[2], testdom[3],
- false, false);
+ false, false, NULL);
fail_unless(subdomain != NULL, "Failed to create new subdomin.");
ret = sysdb_subdomain_store(test_ctx->sysdb,
testdom[0], testdom[1], testdom[2], testdom[3],
- false, false);
+ false, false, NULL);
fail_if(ret != EOK, "Could not set up the test (test subdom)");
ret = sysdb_update_subdomains(test_ctx->domain);
@@ -4723,11 +4723,11 @@ START_TEST(test_sysdb_subdomain_group_ops)
subdomain = new_subdomain(test_ctx, test_ctx->domain,
testdom[0], testdom[1], testdom[2], testdom[3],
- false, false);
+ false, false, NULL);
fail_unless(subdomain != NULL, "Failed to create new subdomin.");
ret = sysdb_subdomain_store(test_ctx->sysdb,
testdom[0], testdom[1], testdom[2], testdom[3],
- false, false);
+ false, false, NULL);
fail_if(ret != EOK, "Could not set up the test (test subdom)");
ret = sysdb_update_subdomains(test_ctx->domain);
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index 7ac4d9d0..4af967cf 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -183,7 +183,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
const char *flat_name,
const char *id,
bool mpg,
- bool enumerate)
+ bool enumerate,
+ const char *forest)
{
struct sss_domain_info *dom;
@@ -239,6 +240,14 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
}
}
+ if (forest != NULL) {
+ dom->forest = talloc_strdup(dom, forest);
+ if (dom->forest == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to copy forest.\n"));
+ goto fail;
+ }
+ }
+
dom->enumerate = enumerate;
dom->fqnames = true;
dom->mpg = mpg;
diff --git a/src/util/util.h b/src/util/util.h
index 6cd59d96..bd450ec7 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -566,7 +566,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
const char *flat_name,
const char *id,
bool mpg,
- bool enumerate);
+ bool enumerate,
+ const char *forest);
errno_t sssd_domain_init(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,