From 177901d07983f3aa0464ac55bd5d5975b66bc7dc Mon Sep 17 00:00:00 2001 From: Roland Tapken Date: Wed, 7 Feb 2018 15:49:40 +0100 Subject: [PATCH] user_ldap: really resolve nested groups The previous patch fixed the problem only for one level of indirection because groupsMatchFilter() had been applied on each recursive call (and thus there would be no second level if the first level fails the check). This new implementation replaces the recursive call with a stack that iterates all nested groups before filtering with groupsMatchFilter(). Signed-off-by: Roland Tapken --- apps/user_ldap/lib/Group_LDAP.php | 33 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/apps/user_ldap/lib/Group_LDAP.php b/apps/user_ldap/lib/Group_LDAP.php index bb2a75c3dfe..7032d481b03 100644 --- a/apps/user_ldap/lib/Group_LDAP.php +++ b/apps/user_ldap/lib/Group_LDAP.php @@ -252,28 +252,33 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD * @param array|null &$seen * @return array */ - private function _getGroupDNsFromMemberOf($DN, &$seen = null) { - if ($seen === null) { - $seen = array(); - } - if (array_key_exists($DN, $seen)) { - // avoid loops - return array(); - } - $seen[$DN] = 1; + private function _getGroupDNsFromMemberOf($DN) { $groups = $this->access->readAttribute($DN, 'memberOf'); if (!is_array($groups)) { return array(); } - $allGroups = $groups; $nestedGroups = $this->access->connection->ldapNestedGroups; if ((int)$nestedGroups === 1) { - foreach ($groups as $group) { - $subGroups = $this->_getGroupDNsFromMemberOf($group, $seen); - $allGroups = array_merge($allGroups, $subGroups); + $seen = array(); + while ($group = array_pop($groups)) { + if ($group === $DN || array_key_exists($group, $seen)) { + // Prevent loops + continue; + } + $seen[$group] = 1; + + // Resolve nested groups + $nestedGroups = $this->access->readAttribute($group, 'memberOf'); + if (is_array($nestedGroups)) { + foreach ($nestedGroups as $nestedGroup) { + array_push($groups, $nestedGroup); + } + } } + // Get unique group DN's from those we have visited in the loop + $groups = array_keys($seen); } - return $this->access->groupsMatchFilter($allGroups); + return $this->access->groupsMatchFilter($groups); } /**