Blob Blame History Raw
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