Skip to content

LDAP: fix inGroup for memberUid type of group memberships - #24402

Merged
blizzz merged 6 commits into
masterfrom
fix/24252/ldap-ingroup-memberid
Dec 15, 2020
Merged

LDAP: fix inGroup for memberUid type of group memberships#24402
blizzz merged 6 commits into
masterfrom
fix/24252/ldap-ingroup-memberid

Conversation

@blizzz

Copy link
Copy Markdown
Member

fixes#24252

basically, the code that resolves the rdns to full DNs returned the whole records, as @Hexasoft observed, but the following code requires a flat list of DNs.

@Hexasoft@steffen-moser can you confirm it fixes the issue for you?

@tofuSCHNITZEL you are informed because it is relevant for zimbramailforwardingaddress types, I would be surprised if it breaks anything though.

It set the label to "developing", because i want to check one, two things tomorrow.

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
@blizzzblizzz added this to the Nextcloud 21 milestone Nov 26, 2020
@blizzzblizzz mentioned this pull request Nov 26, 2020
@steffen-moser

Copy link
Copy Markdown

@blizzz - I think you also need to consider

returnin_array($userDN, $this->cachedGroupMembers[$gid]);
as the list there is also not flat according to my debug log.

I've not checked whether

$isInGroup = in_array($userDN, $members, true);
needs fixing because I did not run into this if clause on any of our Nextcloud servers.

@tofuSCHNITZEL

Copy link
Copy Markdown
Contributor

I just ran a few tests and you change makes total sense... now $members really contains dns so the in_array check works.
But there are problems if this is tripped

if ($bytes >= 9000000) {

because then $dns is already filled but ins this form:

Array
(
[0] => Array
(
[entryuuid] => Array
(
[0] => c2a1b704-4463-1038-9b2b-b7afed259854
)
[dn] => Array
(
[0] => uid=testaccount,ou=people,dc=email,dc=at
)
[uid] => Array
(
[0] => testaccount
)
[displayname] => Array
(
[0] => testaccount
)
)
[1] => Array
(
[entryuuid] => Array
(
[0] => 77dd1308-5857-1030-8796-392f61712f0b
)
[dn] => Array
(
[0] => uid=user.name,ou=people,dc=email,dc=at
)
[uid] => Array
(
[0] => user.name
)
[zimbramailalias] => Array
(
[0] => user@email.at
)
[displayname] => Array
(
[0] => user
)
)
)

and now the array_reduce part might or might not be run (depending if there are filterParts left)
if its run then using $dns as initial with the array_reduce does not produces the desired output.
if its not run then we have nonsense in $members like before this fix

TLDR:
after over an hour of playing around with different scenarios I think I found the solution that works with all cases.

I committed my changes to this branch... I hope this is okay? (and the proper way?)

I'm also thinking, that a foreach for cleaning up the array would be better to understand than the array_reduce.

we could replace:

 // now we cleanup the users array to get only dns
$dns = array_reduce($users, function (array $carry, array $record) {
if (!in_array($carry, $record['dn'][0])) {
$carry[$record['dn'][0]] = 1;
}
return $carry;
}, []);
$members = array_keys($dns);

with a simple:

 // now create a list of dns
$members = [];
foreach ($users as $user){
$dn = $user['dn'][0];
if (!in_array($dn, $members))
$members[] = $dn;
}

also should we could (should?) move:

if (!is_array($members) || count($members) === 0) {
$this->access->connection->writeToCache($cacheKey, false);
returnfalse;

after the switch statement

also added some additional comments and renamed some vars to make it intuitive whats in them
Signed-off-by: Tobias Perschon <tobias@perschon.at>
@tofuSCHNITZEL
tofuSCHNITZELforce-pushed the fix/24252/ldap-ingroup-memberid branch from 578f5f9 to 594370eCompareNovember 27, 2020 10:25
@blizzz

Copy link
Copy Markdown
MemberAuthor

as the list there is also not flat according to my debug log.

is it possible that this was old information, perhaps pulled it from caching? Since it really only is assigned the value of $members. Also not that cachedGroupMembers is not a plain array, but an instance of CappedMemoryCache that behaves like one.

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
@blizzz

Copy link
Copy Markdown
MemberAuthor

@tofuSCHNITZEL good catch with the loop! Also thanks for the commit, that's appreciated. I'd build upon it and turn the last array_reduce to an unsexy, but less hungry and more performant foreach (like you suggest). I'd still work with having the DN as index, as it saves in_arrays and prevents potential duplicates.

Moving the count check down makes sense as well. And dropping the is_array check with it since it is guaranteed by the return type.

- the type check is not necessary anymore for the return type of
_groupMembers()
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
@tofuSCHNITZEL

Copy link
Copy Markdown
Contributor

great ;) should / will this fix be backported to 19 or even earlier? I guess sind its not a huge change we should/could do it. the structure of the file is a bit different pre v20 because of my changes to it for the zimbra support so I could port the changes to the v19 GroupLDAP file.

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
@blizzz

Copy link
Copy Markdown
MemberAuthor

…and added unit tests.

great ;) should / will this fix be backported to 19 or even earlier? I guess sind its not a huge change we should/could do it. the structure of the file is a bit different pre v20 because of my changes to it for the zimbra support so I could port the changes to the v19 GroupLDAP file.

Yes, it is a bug fix, and should be brought back down to 18. If we need to touch a bit there, so be it :)

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
@blizzzblizzz added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Nov 27, 2020
@steffen-moser

steffen-moser commented Nov 27, 2020

Copy link
Copy Markdown

as the list there is also not flat according to my debug log.

is it possible that this was old information, perhaps pulled it from caching? Since it really only is assigned the value of $members. Also not that cachedGroupMembers is not a plain array, but an instance of CappedMemoryCache that behaves like one.

Of course, It is very well possible that this old information came from caching.

We encountered the problem on two servers, but only one of them is actually running using a cache. And only on this server, the if clause, where line 112 resides, was entered, and only there I needed the fix. I haven't done further testing, but maybe emptying the cache would have also helped (after fixing it at the right place where the cache gets filled).

@Hexasoft

Hexasoft commented Nov 27, 2020

Copy link
Copy Markdown

Sorry, I was too busy at work to test the last proposal.
Thank you for your job. For the last change, not sure if it can occurs, but is it certain that $dn = $user['dn'][0]; is always defined? I mean, does adding if (isset($user['dn'][0])) {} is of any interest?
@steffen-moser: before testing, I invalidated all caches (by changing TTL in configuration). Before doing this I also get strange behaviors.

@tofuSCHNITZEL

Copy link
Copy Markdown
Contributor

Thank you for your job. For the last change, not sure if it can occurs, but is it certain that $dn = $user['dn'][0]; is always defined? I mean, does adding if (isset($user['dn'][0])) {} is of any interest?

I think, since dn is such an integral attribute to ldap, it will always be a part of a ldap query response.

@blizzz

blizzz commented Nov 30, 2020

Copy link
Copy Markdown
MemberAuthor

Thank you for your job. For the last change, not sure if it can occurs, but is it certain that $dn = $user['dn'][0]; is always defined? I mean, does adding if (isset($user['dn'][0])) {} is of any interest?

I think, since dn is such an integral attribute to ldap, it will always be a part of a ldap query response.

Yes, it always returns the dn as it is the de-facto (current!) identifier, even if you ask for a single different attribute:

dapsearch -LLL -a find -H ldap://localhost:7770 -D cn=root,dc=nc,dc=zara -W -b "ou=small,dc=nc,dc=zara" "uid=*" uid Enter LDAP Password: dn: uid=folk_0,ou=users,ou=small,dc=nc,dc=zara
uid: folk_0
dn: uid=folk_1,ou=users,ou=small,dc=nc,dc=zara
uid: folk_1
dn: uid=folk_2,ou=users,ou=small,dc=nc,dc=zara
uid: folk_2
…

@faily-bot

faily-botBot commented Nov 30, 2020

Copy link
Copy Markdown

🤖 beep boop beep 🤖

Here are the logs for the failed build:

Status of 36131: failure

mariadb10.1-php7.3

Show full log
There were 2 warnings:
1) Test\Files\ViewTest::testRenameFailDeleteTargetKeepSource
Trying to configure method "writeStream" which cannot be configured because it does not exist, has not been specified, is final, or is static
2) Test\Files\ViewTest::testCopyFailDeleteTargetKeepSource
Trying to configure method "writeStream" which cannot be configured because it does not exist, has not been specified, is final, or is static
--
There was 1 failure:
1) Test\Files\ObjectStore\ObjectStoreStorageTest::testRenameOverWriteDirectory
Failed asserting that false matches expected 'foo'.
/drone/src/tests/lib/Files/ObjectStore/ObjectStoreStorageTest.php:148

@blizzz
blizzz requested a review from rullzerDecember 1, 2020 12:20

@ChristophWurstChristophWurst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 🐘

@rullzerrullzer mentioned this pull request Dec 14, 2020
59 tasks

@tofuSCHNITZELtofuSCHNITZEL left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@blizzz
blizzz merged commit f68cab4 into masterDec 15, 2020
@blizzz
blizzz deleted the fix/24252/ldap-ingroup-memberid branch December 15, 2020 21:33
@blizzz

Copy link
Copy Markdown
MemberAuthor

/backport to stable20

@blizzz

Copy link
Copy Markdown
MemberAuthor

/backport to stable19

@backportbot-nextcloud

Copy link
Copy Markdown

The backport to stable19 failed. Please do this backport manually.

@tofuSCHNITZEL

Copy link
Copy Markdown
Contributor

@blizzz how will we do the stable19 backport? will we create a new branch and do the changes there manually? on what commit will this branch be based?

@blizzz

Copy link
Copy Markdown
MemberAuthor

@blizzz how will we do the stable19 backport? will we create a new branch and do the changes there manually? on what commit will this branch be based?

Yes, we should do it. It's somewhere deep in my list, but if you want to beat me, that would be really appreciated :) A branch called backport/24402/stable19 shall be based against stable19. 'git cherry-pick' the commits in chronological order, and git mergetool to resolve conflicts.

@tofuSCHNITZEL

Copy link
Copy Markdown
Contributor

@blizzz how will we do the stable19 backport? will we create a new branch and do the changes there manually? on what commit will this branch be based?

Yes, we should do it. It's somewhere deep in my list, but if you want to beat me, that would be really appreciated :) A branch called backport/24402/stable19 shall be based against stable19. 'git cherry-pick' the commits in chronological order, and git mergetool to resolve conflicts.

okay tried my best ;) hopefully I did everything how its supposed to be done ;)
it was interesting that the auto merging at the first cherry-pick replaced the wrong $dns = array_merge($dns, $users); (the one inside the over 9000 if) I guess it just matched the first "similar" line occurrence since the line numbers were different

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to reviewWaiting for reviewsbugfeature: ldap

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LDAP inGroup() failing

5 participants

@blizzz@steffen-moser@tofuSCHNITZEL@Hexasoft@ChristophWurst