Skip to content

Commit 257fbf9

Browse files
authored
Merge pull request #8538 from nextcloud/8522-stable11
[stable11] Fix retrieval of group members with numerical uids from LDAP
2 parents fffe39e + 5ddcb17 commit 257fbf9

File tree

2 files changed

+91
-7
lines changed

2 files changed

+91
-7
lines changed

apps/user_ldap/lib/Group_LDAP.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ public function getDynamicGroupMembers($dnGroup) {
198198
* @param string $dnGroup
199199
* @param array|null &$seen
200200
* @return array|mixed|null
201+
* @throws \OC\ServerNotAvailableException
201202
*/
202203
private function _groupMembers($dnGroup, &$seen = null) {
203204
if ($seen === null) {
@@ -211,26 +212,26 @@ private function _groupMembers($dnGroup, &$seen = null) {
211212
// used extensively in cron job, caching makes sense for nested groups
212213
$cacheKey = '_groupMembers'.$dnGroup;
213214
$groupMembers = $this->access->connection->getFromCache($cacheKey);
214-
if(!is_null($groupMembers)) {
215+
if($groupMembers !== null) {
215216
return $groupMembers;
216217
}
217218
$seen[$dnGroup] = 1;
218219
$members = $this->access->readAttribute($dnGroup, $this->access->connection->ldapGroupMemberAssocAttr,
219220
$this->access->connection->ldapGroupFilter);
220221
if (is_array($members)) {
221-
foreach ($members as $memberDN) {
222-
$allMembers[$memberDN] = 1;
222+
foreach ($members as $member) {
223+
$allMembers[$member] = 1;
223224
$nestedGroups = $this->access->connection->ldapNestedGroups;
224225
if (!empty($nestedGroups)) {
225-
$subMembers = $this->_groupMembers($memberDN, $seen);
226+
$subMembers = $this->_groupMembers($member, $seen);
226227
if ($subMembers) {
227-
$allMembers = array_merge($allMembers, $subMembers);
228+
$allMembers += $subMembers;
228229
}
229230
}
230231
}
231232
}
232233

233-
$allMembers = array_merge($allMembers, $this->getDynamicGroupMembers($dnGroup));
234+
$allMembers += $this->getDynamicGroupMembers($dnGroup);
234235

235236
$this->access->connection->writeToCache($cacheKey, $allMembers);
236237
return $allMembers;

apps/user_ldap/tests/Group_LDAPTest.php

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
use OCA\User_LDAP\Group_LDAP as GroupLDAP;
3232
use OCA\User_LDAP\ILDAPWrapper;
33+
use Test\TestCase;
3334

3435
/**
3536
* Class GroupLDAPTest
@@ -38,7 +39,7 @@
3839
*
3940
* @package OCA\User_LDAP\Tests
4041
*/
41-
class Group_LDAPTest extends \Test\TestCase {
42+
class Group_LDAPTest extends TestCase {
4243
private function getAccessMock() {
4344
static $conMethods;
4445
static $accMethods;
@@ -511,4 +512,86 @@ public function testGetGroupsByMember() {
511512
$groupsAgain = $groupBackend->getUserGroups('userX');
512513
$this->assertEquals(['group1', 'group2'], $groupsAgain);
513514
}
515+
516+
public function groupMemberProvider() {
517+
$base = 'dc=species,dc=earth';
518+
519+
$groups0 = [
520+
'uid=3723,' . $base,
521+
'uid=8372,' . $base,
522+
'uid=8427,' . $base,
523+
'uid=2333,' . $base,
524+
'uid=4754,' . $base,
525+
];
526+
$groups1 = [
527+
'3723',
528+
'8372',
529+
'8427',
530+
'2333',
531+
'4754',
532+
];
533+
$groups2Nested = ['6642', '1424'];
534+
$expGroups2 = array_merge($groups1, $groups2Nested);
535+
536+
return [
537+
[ #0 – test DNs
538+
'cn=Birds,' . $base,
539+
$groups0,
540+
['cn=Birds,' . $base => $groups0]
541+
],
542+
[ #1 – test uids
543+
'cn=Birds,' . $base,
544+
$groups1,
545+
['cn=Birds,' . $base => $groups1]
546+
],
547+
[ #2 – test uids with nested groups
548+
'cn=Birds,' . $base,
549+
$expGroups2,
550+
[
551+
'cn=Birds,' . $base => $groups1,
552+
'8427' => $groups2Nested, // simplified - nested groups would work with DNs
553+
],
554+
],
555+
];
556+
}
557+
558+
/**
559+
* @param string $groupDN
560+
* @param string[] $expectedMembers
561+
* @param array $groupsInfo
562+
* @dataProvider groupMemberProvider
563+
*/
564+
public function testGroupMembers($groupDN, $expectedMembers, $groupsInfo = null) {
565+
$access = $this->getAccessMock();
566+
$access->expects($this->any())
567+
->method('readAttribute')
568+
->willReturnCallback(function($group) use ($groupDN, $expectedMembers, $groupsInfo) {
569+
if(isset($groupsInfo[$group])) {
570+
return $groupsInfo[$group];
571+
}
572+
return [];
573+
});
574+
575+
$access->connection = $this->createMock(Connection::class);
576+
if(count($groupsInfo) > 1) {
577+
$access->connection->expects($this->any())
578+
->method('__get')
579+
->willReturnCallback(function($name) {
580+
if($name === 'ldapNestedGroups') {
581+
return 1;
582+
}
583+
return null;
584+
});
585+
}
586+
587+
/** @var GroupPluginManager $pluginManager */
588+
$pluginManager = $this->createMock(GroupPluginManager::class);
589+
590+
$ldap = new GroupLDAP($access, $pluginManager);
591+
$resultingMembers = $this->invokePrivate($ldap, '_groupMembers', [$groupDN]);
592+
593+
$expected = array_keys(array_flip($expectedMembers));
594+
595+
$this->assertEquals($expected, array_keys($resultingMembers), '', 0.0, 10, true);
596+
}
514597
}

0 commit comments

Comments
 (0)