From 4d6be3c36169c954c4d61399607fde229902cb07 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 26 Aug 2020 15:40:53 +0200
Subject: [PATCH] ldap: use member DN to create ghost user hash table
---
src/db/sysdb.h | 1 +
src/providers/ldap/sdap.c | 10 ++++++++++
src/providers/ldap/sdap_async_groups.c | 17 +++++++++++++++-
src/providers/ldap/sdap_async_nested_groups.c | 20 +++++++++++++++++--
4 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index a2bc8ed3b..679763bad 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -129,6 +129,7 @@
#define SYSDB_UPN "userPrincipalName"
#define SYSDB_CANONICAL_UPN "canonicalUserPrincipalName"
#define SYSDB_CCACHE_FILE "ccacheFile"
+#define SYSDB_DN_FOR_MEMBER_HASH_TABLE "dnForMemberHashTable"
#define SYSDB_ORIG_DN "originalDN"
#define SYSDB_ORIG_MODSTAMP "originalModifyTimestamp"
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index a9c8b92b8..a1a00df56 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -771,6 +771,16 @@ errno_t sdap_parse_deref(TALLOC_CTX *mem_ctx,
goto done;
}
+ /* The dereference control seems to return the DN from the dereference
+ * attribute (e.g. member) so we can use it as key for the hash table
+ * later. */
+ ret = sysdb_attrs_add_string(res[mi]->attrs,
+ SYSDB_DN_FOR_MEMBER_HASH_TABLE, orig_dn);
+ if (ret) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
+ goto done;
+ }
+
for (dval = dref->attrVals; dval != NULL; dval = dval->next) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"Dereferenced attribute: %s\n", dval->type);
diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
index abe2ed275..4e3c524a4 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -2509,6 +2509,7 @@ static errno_t sdap_nested_group_populate_users(TALLOC_CTX *mem_ctx,
struct ldb_message_element *el;
const char *username;
const char *original_dn;
+ const char *hash_key_dn;
struct sss_domain_info *user_dom;
struct sdap_domain *sdap_dom;
@@ -2607,8 +2608,22 @@ static errno_t sdap_nested_group_populate_users(TALLOC_CTX *mem_ctx,
SYSDB_MOD_REP);
if (ret != EOK) goto done;
} else {
+ /* The DN of the user object and the DN in the member attribute
+ * might differ, e.g. in case. Since we later search the hash with
+ * DNs from the member attribute we should try to use DN from the
+ * member attribute here as well. This should be added earlier in
+ * the SYSDB_DN_FOR_MEMBER_HASH_TABLE attribute. If this does not
+ * exists we fall-back to original_dn which should work in the
+ * most cases as well. */
+ ret = sysdb_attrs_get_string(users[i],
+ SYSDB_DN_FOR_MEMBER_HASH_TABLE,
+ &hash_key_dn);
+ if (ret != EOK) {
+ hash_key_dn = original_dn;
+ }
+
key.type = HASH_KEY_STRING;
- key.str = talloc_steal(ghosts, discard_const(original_dn));
+ key.str = talloc_steal(ghosts, discard_const(hash_key_dn));
value.type = HASH_VALUE_PTR;
/* Already qualified from sdap_get_user_primary_name() */
value.ptr = talloc_steal(ghosts, discard_const(username));
diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c
index 055de29ca..635b46403 100644
--- a/src/providers/ldap/sdap_async_nested_groups.c
+++ b/src/providers/ldap/sdap_async_nested_groups.c
@@ -241,9 +241,12 @@ static errno_t sdap_nested_group_hash_entry(hash_table_t *table,
const char *name = NULL;
errno_t ret;
- ret = sysdb_attrs_get_string(entry, SYSDB_ORIG_DN, &name);
+ ret = sysdb_attrs_get_string(entry, SYSDB_DN_FOR_MEMBER_HASH_TABLE, &name);
if (ret != EOK) {
- return ret;
+ ret = sysdb_attrs_get_string(entry, SYSDB_ORIG_DN, &name);
+ if (ret != EOK) {
+ return ret;
+ }
}
return sdap_nested_group_hash_insert(table, name, entry, false, table_name);
@@ -1495,6 +1498,19 @@ sdap_nested_group_single_step_process(struct tevent_req *subreq)
}
}
+ /* The original DN of the user object itself might differ from the one
+ * used inthe member attribute, e.g. different case. To make sure if
+ * can be found in a hash table when iterating over group members the
+ * DN from the member attribute used for the search as saved as well.
+ */
+ ret = sysdb_attrs_add_string(entry,
+ SYSDB_DN_FOR_MEMBER_HASH_TABLE,
+ state->current_member->dn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
+ goto done;
+ }
+
/* save user in hash table */
ret = sdap_nested_group_hash_user(state->group_ctx, entry);
if (ret == EEXIST) {
--
2.21.3