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 <roland@bitarbeiter.net>
This commit is contained in:
Roland Tapken 2018-02-07 15:49:40 +01:00 committed by Arthur Schiwon
parent c2d8a36d9a
commit afb182650e
No known key found for this signature in database
GPG Key ID: 7424F1874854DF23
1 changed files with 19 additions and 14 deletions

View File

@ -252,28 +252,33 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD
* @param array|null &$seen * @param array|null &$seen
* @return array * @return array
*/ */
private function _getGroupDNsFromMemberOf($DN, &$seen = null) { private function _getGroupDNsFromMemberOf($DN) {
if ($seen === null) {
$seen = array();
}
if (array_key_exists($DN, $seen)) {
// avoid loops
return array();
}
$seen[$DN] = 1;
$groups = $this->access->readAttribute($DN, 'memberOf'); $groups = $this->access->readAttribute($DN, 'memberOf');
if (!is_array($groups)) { if (!is_array($groups)) {
return array(); return array();
} }
$allGroups = $groups;
$nestedGroups = $this->access->connection->ldapNestedGroups; $nestedGroups = $this->access->connection->ldapNestedGroups;
if ((int)$nestedGroups === 1) { if ((int)$nestedGroups === 1) {
foreach ($groups as $group) { $seen = array();
$subGroups = $this->_getGroupDNsFromMemberOf($group, $seen); while ($group = array_pop($groups)) {
$allGroups = array_merge($allGroups, $subGroups); 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);
} }
} }
return $this->access->groupsMatchFilter($allGroups); }
// Get unique group DN's from those we have visited in the loop
$groups = array_keys($seen);
}
return $this->access->groupsMatchFilter($groups);
} }
/** /**