]> 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 16:22:11 +0000 (18:22 +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 81e33e6244f33c064d88b3e9659608137a188952..5a7c732ab7b54e53f6a989ff0279a64c8ad572f3 100644 (file)
@@ -45,6 +45,10 @@ class Configuration {
        public const AVATAR_PREFIX_NONE = 'none';
        public 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;
        /**
@@ -110,6 +114,7 @@ class Configuration {
                'ldapDynamicGroupMemberURL' => null,
                'ldapDefaultPPolicyDN' => null,
                'ldapExtStorageHomeAttribute' => null,
+               'ldapMatchingRuleInChainState' => self::LDAP_SERVER_FEATURE_UNKNOWN,
        ];
 
        /**
@@ -482,6 +487,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,
                ];
        }
 
@@ -543,6 +549,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 6bf1bd31ba04df84c23d7f28f247f6410643ef98..617b9f498efc436d834efeacbe3a91c7a79cac8f 100644 (file)
@@ -246,6 +246,31 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
                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)) {
@@ -258,6 +283,10 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
                $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 f8dd5af167f3a6dfac9384a15128a4bd5d6dcf8e..3143054940d8b6cb08e90967089b57c87e67b39e 100644 (file)
@@ -73,6 +73,8 @@ class Group_LDAPTest extends TestCase {
                        ->method('getConnection')
                        ->willReturn($connector);
 
+               $access->userManager = $this->createMock(Manager::class);
+
                return $access;
        }