From ad0ea2ccb0269a2f1b94722c43b1e82ce81ed0de Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Tue, 19 Oct 2021 22:00:13 +0200 Subject: [PATCH] fix potential unwarranted memberships in nested groups from LDAP - the issue was present only when using PHP based resolving of nested group members. Normally nested members are common in AD (and Samba4) and are resolved per LDAP_MATCHING_RULE_IN_CHAIN by default - resolving nested members is recursive - when the cache entry was created it happend for intermediate groups, too, containing members from the parent group - the check was added to only cache the root group with its members - a runtime cache stores intermediate ldap read results Signed-off-by: Arthur Schiwon --- apps/user_ldap/lib/Group_LDAP.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/user_ldap/lib/Group_LDAP.php b/apps/user_ldap/lib/Group_LDAP.php index 744f921c6dd3e..29ef89582937a 100644 --- a/apps/user_ldap/lib/Group_LDAP.php +++ b/apps/user_ldap/lib/Group_LDAP.php @@ -248,7 +248,12 @@ private function _groupMembers(string $dnGroup, ?array &$seen = null): array { // but not included in the results laters on $excludeFromResult = $dnGroup; } + // cache only base groups, otherwise groups get additional unwarranted members + $shouldCacheResult = count($seen) === 0; + + static $rawMemberReads = []; // runtime cache for intermediate ldap read results $allMembers = []; + if (array_key_exists($dnGroup, $seen)) { return []; } @@ -290,7 +295,11 @@ private function _groupMembers(string $dnGroup, ?array &$seen = null): array { } $seen[$dnGroup] = 1; - $members = $this->access->readAttribute($dnGroup, $this->access->connection->ldapGroupMemberAssocAttr); + $members = $rawMemberReads[$dnGroup] ?? null; + if ($members === null) { + $members = $this->access->readAttribute($dnGroup, $this->access->connection->ldapGroupMemberAssocAttr); + $rawMemberReads[$dnGroup] = $members; + } if (is_array($members)) { $fetcher = function ($memberDN) use (&$seen) { return $this->_groupMembers($memberDN, $seen); @@ -306,7 +315,10 @@ private function _groupMembers(string $dnGroup, ?array &$seen = null): array { } } - $this->access->connection->writeToCache($cacheKey, $allMembers); + if ($shouldCacheResult) { + $this->access->connection->writeToCache($cacheKey, $allMembers); + unset($rawMemberReads[$dnGroup]); + } if (isset($attemptedLdapMatchingRuleInChain) && $this->access->connection->ldapMatchingRuleInChainState === Configuration::LDAP_SERVER_FEATURE_UNKNOWN && !empty($allMembers)