]> source.dussan.org Git - nextcloud-server.git/commitdiff
LDAP: shortcut in reading nested group members when IN_CHAIN is available
authorArthur Schiwon <blizzz@arthur-schiwon.de>
Wed, 24 Jun 2020 11:09:15 +0000 (13:09 +0200)
committerArthur Schiwon <blizzz@arthur-schiwon.de>
Tue, 11 Aug 2020 23:19:05 +0000 (01:19 +0200)
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
apps/user_ldap/lib/Configuration.php
apps/user_ldap/lib/Group_LDAP.php
apps/user_ldap/tests/Group_LDAPTest.php

index 724f240847a93352b7236f14eddd86a59e6697e3..13cb18be63fe134d4b9c1db033c9f241223bb1e9 100644 (file)
@@ -44,6 +44,10 @@ class Configuration {
        const AVATAR_PREFIX_NONE = 'none';
        const AVATAR_PREFIX_DATA_ATTRIBUTE = 'data:';
 
+       public const LDAP_SERVER_FEATURE_UNKNOWN = 'unknown';
+       public const LDAP_SERVER_FEATURE_AVAILABLE = 'available';
+       public const LDAP_SERVER_FEATURE_UNAVAILABLE = 'unavailable';
+
        protected $configPrefix = null;
        protected $configRead = false;
        /**
@@ -109,6 +113,7 @@ class Configuration {
                'ldapDynamicGroupMemberURL' => null,
                'ldapDefaultPPolicyDN' => null,
                'ldapExtStorageHomeAttribute' => null,
+               'ldapMatchingRuleInChainState' => self::LDAP_SERVER_FEATURE_UNKNOWN,
        );
 
        /**
@@ -481,6 +486,7 @@ class Configuration {
                        'ldap_default_ppolicy_dn'           => '',
                        'ldap_user_avatar_rule'             => 'default',
                        'ldap_ext_storage_home_attribute'   => '',
+                       'ldap_matching_rule_in_chain_state' => self::LDAP_SERVER_FEATURE_UNKNOWN,
                );
        }
 
@@ -542,6 +548,7 @@ class Configuration {
                        'ldap_dynamic_group_member_url'     => 'ldapDynamicGroupMemberURL',
                        'ldap_default_ppolicy_dn'           => 'ldapDefaultPPolicyDN',
                        'ldap_ext_storage_home_attribute'   => 'ldapExtStorageHomeAttribute',
+                       'ldap_matching_rule_in_chain_state' => 'ldapMatchingRuleInChainState',
                        'ldapIgnoreNamingRules'             => 'ldapIgnoreNamingRules', // sysconfig
                );
                return $array;
index b369842d8478048f4e12a94c5883727bb03be8d8..46a0467d15dc0ad89be097779ac93189349f3b8b 100644 (file)
@@ -232,6 +232,31 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
                if($groupMembers !== null) {
                        return $groupMembers;
                }
+
+               if ($this->access->connection->ldapNestedGroups
+                       && $this->access->connection->useMemberOfToDetectMembership
+                       && $this->access->connection->hasMemberOfFilterSupport
+                       && $this->access->connection->ldapMatchingRuleInChainState !== Configuration::LDAP_SERVER_FEATURE_UNAVAILABLE
+               ) {
+                       $attemptedLdapMatchingRuleInChain = true;
+                       // compatibility hack with servers supporting :1.2.840.113556.1.4.1941:, and others)
+                       $filter = $this->access->combineFilterWithAnd([$this->access->connection->ldapUserFilter, 'memberof:1.2.840.113556.1.4.1941:=' . $dnGroup]);
+                       $memberRecords = $this->access->fetchListOfUsers(
+                               $filter,
+                               $this->access->userManager->getAttributes(true)
+                       );
+                       if (!empty($memberRecords)) {
+                               if ($this->access->connection->ldapMatchingRuleInChainState === Configuration::LDAP_SERVER_FEATURE_UNKNOWN) {
+                                       $this->access->connection->ldapMatchingRuleInChainState = Configuration::LDAP_SERVER_FEATURE_AVAILABLE;
+                                       $this->access->connection->saveConfiguration();
+                               }
+                               return array_reduce($memberRecords, function ($carry, $record) {
+                                       $carry[] = $record['dn'][0];
+                                       return $carry;
+                               }, []);
+                       }
+               }
+
                $seen[$dnGroup] = 1;
                $members = $this->access->readAttribute($dnGroup, $this->access->connection->ldapGroupMemberAssocAttr);
                if (is_array($members)) {
@@ -244,6 +269,10 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
                $allMembers += $this->getDynamicGroupMembers($dnGroup);
 
                $this->access->connection->writeToCache($cacheKey, $allMembers);
+               if (isset($attemptedLdapMatchingRuleInChain) && !empty($allMembers)) {
+                       $this->access->connection->ldapMatchingRuleInChainState = Configuration::LDAP_SERVER_FEATURE_UNAVAILABLE;
+                       $this->access->connection->saveConfiguration();
+               }
                return $allMembers;
        }
 
index 7ea4cb463d96f4f0fec40bb93f6fa15bf01f9c59..3e681233186506aeaba7aea690e7a1dd7e2c295d 100644 (file)
@@ -72,6 +72,8 @@ class Group_LDAPTest extends TestCase {
                        ->method('getConnection')
                        ->will($this->returnValue($connector));
 
+               $access->userManager = $this->createMock(Manager::class);
+
                return $access;
        }