|
|
45d81b |
From a315e923a930e743de51c05183de383245f1c83e Mon Sep 17 00:00:00 2001
|
|
|
45d81b |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
45d81b |
Date: Mon, 31 Oct 2016 21:39:57 +0100
|
|
|
45d81b |
Subject: [PATCH 151/151] SYSDB: Augment sysdb_try_to_find_expected_dn to match
|
|
|
45d81b |
search base as well
|
|
|
45d81b |
|
|
|
45d81b |
In cases where the domain name in sssd.conf does not match the AD
|
|
|
45d81b |
domain, our previous matching process wouldn't match. This patch
|
|
|
45d81b |
augments the matching as follows:
|
|
|
45d81b |
- the search base is known to sysdb_try_to_find_expected_dn and is
|
|
|
45d81b |
expected to be non-NULL
|
|
|
45d81b |
- the existing matching is ran first
|
|
|
45d81b |
- during the search base, matching, all the non-DC components are
|
|
|
45d81b |
stripped from the search base to 'canonicalize' the search base
|
|
|
45d81b |
- if only a single entry that matches with a non-DC DN component
|
|
|
45d81b |
(matching with a DC component would mean the DN comes from a
|
|
|
45d81b |
different domain) then this entry is a match and is returned
|
|
|
45d81b |
|
|
|
45d81b |
Resolves:
|
|
|
45d81b |
https://fedorahosted.org/sssd/ticket/3199
|
|
|
45d81b |
|
|
|
45d81b |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
45d81b |
(cherry picked from commit 24d8c85fae253f988165c112af208198cf48eef6)
|
|
|
45d81b |
---
|
|
|
45d81b |
src/db/sysdb.h | 1 +
|
|
|
45d81b |
src/db/sysdb_subdomains.c | 99 ++++++++++++++++++++++++++++++
|
|
|
45d81b |
src/providers/ldap/sdap_async_initgroups.c | 8 ++-
|
|
|
45d81b |
src/tests/cmocka/test_sysdb_subdomains.c | 43 +++++++++++--
|
|
|
45d81b |
4 files changed, 144 insertions(+), 7 deletions(-)
|
|
|
45d81b |
|
|
|
45d81b |
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
|
|
|
45d81b |
index a0279fb249e1258c9cb73a4fcab55e4b242c61f3..6a1bbf089206970892590e85ae1f5c741a79f969 100644
|
|
|
45d81b |
--- a/src/db/sysdb.h
|
|
|
45d81b |
+++ b/src/db/sysdb.h
|
|
|
45d81b |
@@ -1296,6 +1296,7 @@ errno_t sysdb_handle_original_uuid(const char *orig_name,
|
|
|
45d81b |
|
|
|
45d81b |
errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom,
|
|
|
45d81b |
const char *domain_component_name,
|
|
|
45d81b |
+ const char *ldap_search_base,
|
|
|
45d81b |
struct sysdb_attrs **usr_attrs,
|
|
|
45d81b |
size_t count,
|
|
|
45d81b |
struct sysdb_attrs **exp_usr);
|
|
|
45d81b |
diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
|
|
|
45d81b |
index b011bad6c988db952622e7ddaabf015ec24e54ba..780140484f6f023bc6e8c12266e3b81ff016ec10 100644
|
|
|
45d81b |
--- a/src/db/sysdb_subdomains.c
|
|
|
45d81b |
+++ b/src/db/sysdb_subdomains.c
|
|
|
45d81b |
@@ -1320,8 +1320,97 @@ static errno_t match_basedn(TALLOC_CTX *tmp_ctx,
|
|
|
45d81b |
_result);
|
|
|
45d81b |
}
|
|
|
45d81b |
|
|
|
45d81b |
+static errno_t match_search_base(TALLOC_CTX *tmp_ctx,
|
|
|
45d81b |
+ struct sss_domain_info *dom,
|
|
|
45d81b |
+ const char *domain_component_name,
|
|
|
45d81b |
+ const char *domain_search_base,
|
|
|
45d81b |
+ struct sysdb_attrs **usr_attrs,
|
|
|
45d81b |
+ size_t count,
|
|
|
45d81b |
+ struct sysdb_attrs **_result)
|
|
|
45d81b |
+{
|
|
|
45d81b |
+ errno_t ret;
|
|
|
45d81b |
+ bool ok;
|
|
|
45d81b |
+ const char *search_base;
|
|
|
45d81b |
+ struct ldb_context *ldb_ctx;
|
|
|
45d81b |
+ struct sysdb_attrs *result = NULL;
|
|
|
45d81b |
+ struct ldb_dn *ldb_search_base;
|
|
|
45d81b |
+ int search_base_comp_num;
|
|
|
45d81b |
+ int non_dc_comp_num;
|
|
|
45d81b |
+ const char *component_name;
|
|
|
45d81b |
+
|
|
|
45d81b |
+ ldb_ctx = sysdb_ctx_get_ldb(dom->sysdb);
|
|
|
45d81b |
+ if (ldb_ctx == NULL) {
|
|
|
45d81b |
+ DEBUG(SSSDBG_OP_FAILURE, "Missing ldb context.\n");
|
|
|
45d81b |
+ ret = EINVAL;
|
|
|
45d81b |
+ goto done;
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+
|
|
|
45d81b |
+ ldb_search_base = ldb_dn_new(tmp_ctx, ldb_ctx, domain_search_base);
|
|
|
45d81b |
+ if (ldb_search_base == NULL) {
|
|
|
45d81b |
+ DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
|
|
|
45d81b |
+ ret = ENOMEM;
|
|
|
45d81b |
+ goto done;
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+
|
|
|
45d81b |
+ /* strip non-DC components from the search base */
|
|
|
45d81b |
+ search_base_comp_num = ldb_dn_get_comp_num(ldb_search_base);
|
|
|
45d81b |
+ for (non_dc_comp_num = 0;
|
|
|
45d81b |
+ non_dc_comp_num < search_base_comp_num;
|
|
|
45d81b |
+ non_dc_comp_num++) {
|
|
|
45d81b |
+
|
|
|
45d81b |
+ component_name = ldb_dn_get_component_name(ldb_search_base,
|
|
|
45d81b |
+ non_dc_comp_num);
|
|
|
45d81b |
+ if (strcasecmp(domain_component_name, component_name) == 0) {
|
|
|
45d81b |
+ break;
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+
|
|
|
45d81b |
+ if (non_dc_comp_num == search_base_comp_num) {
|
|
|
45d81b |
+ /* The search base does not have any non-DC components, the search wouldn't
|
|
|
45d81b |
+ * match anyway
|
|
|
45d81b |
+ */
|
|
|
45d81b |
+ ret = EOK;
|
|
|
45d81b |
+ *_result = NULL;
|
|
|
45d81b |
+ goto done;
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+
|
|
|
45d81b |
+ ok = ldb_dn_remove_child_components(ldb_search_base, non_dc_comp_num);
|
|
|
45d81b |
+ if (!ok) {
|
|
|
45d81b |
+ ret = EINVAL;
|
|
|
45d81b |
+ goto done;
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+
|
|
|
45d81b |
+ search_base = ldb_dn_get_linearized(ldb_search_base);
|
|
|
45d81b |
+ if (search_base == NULL) {
|
|
|
45d81b |
+ ret = ENOMEM;
|
|
|
45d81b |
+ goto done;
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+
|
|
|
45d81b |
+ ret = match_cn_users(tmp_ctx, usr_attrs, count, search_base, &result);
|
|
|
45d81b |
+ if (ret != EOK) {
|
|
|
45d81b |
+ goto done;
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+
|
|
|
45d81b |
+ if (result == NULL) {
|
|
|
45d81b |
+ ret = match_non_dc_comp(tmp_ctx, dom,
|
|
|
45d81b |
+ usr_attrs, count,
|
|
|
45d81b |
+ ldb_search_base, search_base,
|
|
|
45d81b |
+ domain_component_name,
|
|
|
45d81b |
+ &result);
|
|
|
45d81b |
+ if (ret != EOK) {
|
|
|
45d81b |
+ goto done;
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+
|
|
|
45d81b |
+ ret = EOK;
|
|
|
45d81b |
+ *_result = result;
|
|
|
45d81b |
+done:
|
|
|
45d81b |
+ return ret;
|
|
|
45d81b |
+}
|
|
|
45d81b |
+
|
|
|
45d81b |
errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom,
|
|
|
45d81b |
const char *domain_component_name,
|
|
|
45d81b |
+ const char *domain_search_base,
|
|
|
45d81b |
struct sysdb_attrs **usr_attrs,
|
|
|
45d81b |
size_t count,
|
|
|
45d81b |
struct sysdb_attrs **exp_usr)
|
|
|
45d81b |
@@ -1332,6 +1421,7 @@ errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom,
|
|
|
45d81b |
struct sysdb_attrs *result = NULL;
|
|
|
45d81b |
|
|
|
45d81b |
if (dom == NULL || domain_component_name == NULL
|
|
|
45d81b |
+ || domain_search_base == NULL
|
|
|
45d81b |
|| usr_attrs == NULL || count == 0) {
|
|
|
45d81b |
return EINVAL;
|
|
|
45d81b |
}
|
|
|
45d81b |
@@ -1364,6 +1454,15 @@ errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom,
|
|
|
45d81b |
}
|
|
|
45d81b |
|
|
|
45d81b |
if (result == NULL) {
|
|
|
45d81b |
+ ret = match_search_base(tmp_ctx, dom, domain_component_name,
|
|
|
45d81b |
+ domain_search_base, usr_attrs, count,
|
|
|
45d81b |
+ &result);
|
|
|
45d81b |
+ if (ret != EOK) {
|
|
|
45d81b |
+ goto done;
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+ }
|
|
|
45d81b |
+
|
|
|
45d81b |
+ if (result == NULL) {
|
|
|
45d81b |
DEBUG(SSSDBG_OP_FAILURE, "No matching DN found.\n");
|
|
|
45d81b |
ret = ENOENT;
|
|
|
45d81b |
goto done;
|
|
|
45d81b |
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
|
|
|
45d81b |
index 8eaba261c49082d086df9f19464ac0f40fae71fb..1173f4a875a1ea79990ff491ee7f2512f8435ac7 100644
|
|
|
45d81b |
--- a/src/providers/ldap/sdap_async_initgroups.c
|
|
|
45d81b |
+++ b/src/providers/ldap/sdap_async_initgroups.c
|
|
|
45d81b |
@@ -2947,7 +2947,13 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
|
|
|
45d81b |
DEBUG(SSSDBG_OP_FAILURE,
|
|
|
45d81b |
"Expected one user entry and got %zu\n", count);
|
|
|
45d81b |
|
|
|
45d81b |
- ret = sysdb_try_to_find_expected_dn(state->dom, "dc", usr_attrs, count,
|
|
|
45d81b |
+ /* When matching against a search base, it's sufficient to pick only
|
|
|
45d81b |
+ * the first search base because all bases in a single domain would
|
|
|
45d81b |
+ * have the same DC= components
|
|
|
45d81b |
+ */
|
|
|
45d81b |
+ ret = sysdb_try_to_find_expected_dn(state->dom, "dc",
|
|
|
45d81b |
+ state->sdom->search_bases[0]->basedn,
|
|
|
45d81b |
+ usr_attrs, count,
|
|
|
45d81b |
&state->orig_user);
|
|
|
45d81b |
if (ret != EOK) {
|
|
|
45d81b |
DEBUG(SSSDBG_OP_FAILURE,
|
|
|
45d81b |
diff --git a/src/tests/cmocka/test_sysdb_subdomains.c b/src/tests/cmocka/test_sysdb_subdomains.c
|
|
|
45d81b |
index c9db56841e841472c81d00a79f475dbbd975ccb0..52056e0435d2793893f1a4e336f38acf7a70b2c0 100644
|
|
|
45d81b |
--- a/src/tests/cmocka/test_sysdb_subdomains.c
|
|
|
45d81b |
+++ b/src/tests/cmocka/test_sysdb_subdomains.c
|
|
|
45d81b |
@@ -520,7 +520,9 @@ static void test_try_to_find_expected_dn(void **state)
|
|
|
45d81b |
int ret;
|
|
|
45d81b |
struct sysdb_attrs *result;
|
|
|
45d81b |
struct sysdb_attrs *usr_attrs[10] = { NULL };
|
|
|
45d81b |
+ struct sysdb_attrs *dom_usr_attrs[10] = { NULL };
|
|
|
45d81b |
struct sss_domain_info *dom;
|
|
|
45d81b |
+ char *dom_basedn;
|
|
|
45d81b |
struct subdom_test_ctx *test_ctx =
|
|
|
45d81b |
talloc_get_type(*state, struct subdom_test_ctx);
|
|
|
45d81b |
|
|
|
45d81b |
@@ -528,6 +530,9 @@ static void test_try_to_find_expected_dn(void **state)
|
|
|
45d81b |
"child2.test_sysdb_subdomains_2", true);
|
|
|
45d81b |
assert_non_null(dom);
|
|
|
45d81b |
|
|
|
45d81b |
+ ret = domain_to_basedn(test_ctx, dom->name, &dom_basedn);
|
|
|
45d81b |
+ assert_int_equal(ret, EOK);
|
|
|
45d81b |
+
|
|
|
45d81b |
usr_attrs[0] = sysdb_new_attrs(test_ctx);
|
|
|
45d81b |
assert_non_null(usr_attrs[0]);
|
|
|
45d81b |
|
|
|
45d81b |
@@ -535,13 +540,13 @@ static void test_try_to_find_expected_dn(void **state)
|
|
|
45d81b |
"uid=user,cn=abc,dc=c2,dc=child2,dc=test_sysdb_subdomains_2");
|
|
|
45d81b |
assert_int_equal(ret, EOK);
|
|
|
45d81b |
|
|
|
45d81b |
- ret = sysdb_try_to_find_expected_dn(NULL, NULL, NULL, 0, NULL);
|
|
|
45d81b |
+ ret = sysdb_try_to_find_expected_dn(NULL, NULL, NULL, NULL, 0, NULL);
|
|
|
45d81b |
assert_int_equal(ret, EINVAL);
|
|
|
45d81b |
|
|
|
45d81b |
- ret = sysdb_try_to_find_expected_dn(dom, "dc", usr_attrs, 1, &result);
|
|
|
45d81b |
+ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, usr_attrs, 1, &result);
|
|
|
45d81b |
assert_int_equal(ret, ENOENT);
|
|
|
45d81b |
|
|
|
45d81b |
- ret = sysdb_try_to_find_expected_dn(dom, "xy", usr_attrs, 1, &result);
|
|
|
45d81b |
+ ret = sysdb_try_to_find_expected_dn(dom, "xy", dom_basedn, usr_attrs, 1, &result);
|
|
|
45d81b |
assert_int_equal(ret, EOK);
|
|
|
45d81b |
assert_ptr_equal(result, usr_attrs[0]);
|
|
|
45d81b |
|
|
|
45d81b |
@@ -559,11 +564,11 @@ static void test_try_to_find_expected_dn(void **state)
|
|
|
45d81b |
"uid=user2,cn=abc,dc=c2,dc=child2,dc=test_sysdb_subdomains_2");
|
|
|
45d81b |
assert_int_equal(ret, EOK);
|
|
|
45d81b |
|
|
|
45d81b |
- ret = sysdb_try_to_find_expected_dn(dom, "dc", usr_attrs, 3, &result);
|
|
|
45d81b |
+ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, usr_attrs, 3, &result);
|
|
|
45d81b |
assert_int_equal(ret, EOK);
|
|
|
45d81b |
assert_ptr_equal(result, usr_attrs[1]);
|
|
|
45d81b |
|
|
|
45d81b |
- ret = sysdb_try_to_find_expected_dn(dom, "xy", usr_attrs, 3, &result);
|
|
|
45d81b |
+ ret = sysdb_try_to_find_expected_dn(dom, "xy", dom_basedn, usr_attrs, 3, &result);
|
|
|
45d81b |
assert_int_equal(ret, EINVAL);
|
|
|
45d81b |
|
|
|
45d81b |
/* Make sure cn=users match is preferred */
|
|
|
45d81b |
@@ -575,10 +580,36 @@ static void test_try_to_find_expected_dn(void **state)
|
|
|
45d81b |
"uid=user2,cn=abc,cn=users,dc=child2,dc=test_sysdb_subdomains_2");
|
|
|
45d81b |
assert_int_equal(ret, EOK);
|
|
|
45d81b |
|
|
|
45d81b |
- ret = sysdb_try_to_find_expected_dn(dom, "dc", usr_attrs, 3, &result);
|
|
|
45d81b |
+ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, usr_attrs, 3, &result);
|
|
|
45d81b |
assert_int_equal(ret, EOK);
|
|
|
45d81b |
assert_ptr_equal(result, usr_attrs[2]);
|
|
|
45d81b |
|
|
|
45d81b |
+ /* test a case where the domain name does not match the basedn */
|
|
|
45d81b |
+ dom->name = discard_const("default");
|
|
|
45d81b |
+ dom_usr_attrs[0] = usr_attrs[0];
|
|
|
45d81b |
+
|
|
|
45d81b |
+ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, dom_usr_attrs, 1, &result);
|
|
|
45d81b |
+ assert_int_equal(ret, ENOENT);
|
|
|
45d81b |
+
|
|
|
45d81b |
+ dom_usr_attrs[1] = usr_attrs[1];
|
|
|
45d81b |
+ dom_usr_attrs[2] = usr_attrs[2];
|
|
|
45d81b |
+
|
|
|
45d81b |
+ /* Make sure cn=users match is preferred */
|
|
|
45d81b |
+ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, dom_usr_attrs, 3, &result);
|
|
|
45d81b |
+ assert_int_equal(ret, EOK);
|
|
|
45d81b |
+ assert_ptr_equal(result, dom_usr_attrs[2]);
|
|
|
45d81b |
+
|
|
|
45d81b |
+ talloc_free(usr_attrs[2]);
|
|
|
45d81b |
+ usr_attrs[2] = sysdb_new_attrs(test_ctx);
|
|
|
45d81b |
+ assert_non_null(usr_attrs[2]);
|
|
|
45d81b |
+ ret = sysdb_attrs_add_string(usr_attrs[2], SYSDB_ORIG_DN,
|
|
|
45d81b |
+ "uid=user2,cn=abc,dc=c2,dc=child2,dc=test_sysdb_subdomains_2");
|
|
|
45d81b |
+ assert_int_equal(ret, EOK);
|
|
|
45d81b |
+
|
|
|
45d81b |
+ dom_usr_attrs[2] = usr_attrs[2];
|
|
|
45d81b |
+ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, dom_usr_attrs, 3, &result);
|
|
|
45d81b |
+ assert_int_equal(ret, EOK);
|
|
|
45d81b |
+ assert_ptr_equal(result, usr_attrs[1]);
|
|
|
45d81b |
|
|
|
45d81b |
talloc_free(usr_attrs[0]);
|
|
|
45d81b |
talloc_free(usr_attrs[1]);
|
|
|
45d81b |
--
|
|
|
45d81b |
2.7.4
|
|
|
45d81b |
|