diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index 32e2cec596..cef9ca3c4c 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -61,8 +61,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { return false; } //usually, LDAP attributes are said to be case insensitive. But there are exceptions of course. - $members = $this->access->readAttribute($dn_group, - $this->access->connection->ldapGroupMemberAssocAttr); + $members = array_keys($this->_groupMembers($dn_group)); if(!$members) { $this->access->connection->writeToCache('inGroup'.$uid.':'.$gid, false); return false; @@ -89,6 +88,39 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { return $isInGroup; } + private function _groupMembers($dnGroup, &$seen = null) { + if ($seen === null) { + $seen = array(); + } + $allMembers = array(); + if (array_key_exists($dnGroup, $seen)) { + // avoid loops + return array(); + } + // used extensively in cron job, caching makes sense for nested groups + $cacheKey = '_groupMembers'.$dnGroup; + if($this->access->connection->isCached($cacheKey)) { + return $this->access->connection->getFromCache($cacheKey); + } + $seen[$dnGroup] = 1; + $members = $this->access->readAttribute($dnGroup, $this->access->connection->ldapGroupMemberAssocAttr, + $this->access->connection->ldapGroupFilter); + if (is_array($members)) { + foreach ($members as $memberDN) { + $allMembers[$memberDN] = 1; + $nestedGroups = $this->access->connection->ldapNestedGroups; + if (!empty($nestedGroups)) { + $subMembers = $this->_groupMembers($memberDN, $seen); + if ($subMembers) { + $allMembers = array_merge($allMembers, $subMembers); + } + } + } + } + $this->access->connection->writeToCache($cacheKey, $allMembers); + return $allMembers; + } + /** * @brief Get all groups a user belongs to * @param $uid Name of the user @@ -124,18 +156,45 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { $uid = $userDN; } - $filter = $this->access->combineFilterWithAnd(array( - $this->access->connection->ldapGroupFilter, - $this->access->connection->ldapGroupMemberAssocAttr.'='.$uid - )); - $groups = $this->access->fetchListOfGroups($filter, - array($this->access->connection->ldapGroupDisplayName, 'dn')); + $groups = array_values($this->getGroupsByMember($uid)); $groups = array_unique($this->access->ownCloudGroupNames($groups), SORT_LOCALE_STRING); $this->access->connection->writeToCache($cacheKey, $groups); return $groups; } + private function getGroupsByMember($dn, &$seen = null) { + if ($seen === null) { + $seen = array(); + } + $allGroups = array(); + if (array_key_exists($dn, $seen)) { + // avoid loops + return array(); + } + $seen[$dn] = true; + $filter = $this->access->combineFilterWithAnd(array( + $this->access->connection->ldapGroupFilter, + $this->access->connection->ldapGroupMemberAssocAttr.'='.$dn + )); + $groups = $this->access->fetchListOfGroups($filter, + array($this->access->connection->ldapGroupDisplayName, 'dn')); + if (is_array($groups)) { + foreach ($groups as $groupobj) { + $groupDN = $groupobj['dn']; + $allGroups[$groupDN] = $groupobj; + $nestedGroups = $this->access->connection->ldapNestedGroups; + if (!empty($nestedGroups)) { + $supergroups = $this->getGroupsByMember($groupDN, $seen); + if (is_array($supergroups) && (count($supergroups)>0)) { + $allGroups = array_merge($allGroups, $supergroups); + } + } + } + } + return $allGroups; + } + /** * @brief get a list of all users in a group * @returns array with user ids @@ -172,8 +231,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { return array(); } - $members = $this->access->readAttribute($groupDN, - $this->access->connection->ldapGroupMemberAssocAttr); + $members = array_keys($this->_groupMembers($groupDN)); if(!$members) { //in case users could not be retrieved, return empty resultset $this->access->connection->writeToCache($cachekey, array()); diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index 954d0501fa..612a623e91 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -76,6 +76,7 @@ class Configuration { 'ldapExpertUUIDUserAttr' => null, 'ldapExpertUUIDGroupAttr' => null, 'lastJpegPhotoLookup' => null, + 'ldapNestedGroups' => false, ); /** @@ -342,6 +343,7 @@ class Configuration { 'ldap_expert_uuid_group_attr' => '', 'has_memberof_filter_support' => 0, 'last_jpegPhoto_lookup' => 0, + 'ldap_nested_groups' => 0, ); } @@ -393,6 +395,7 @@ class Configuration { 'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr', 'has_memberof_filter_support' => 'hasMemberOfFilterSupport', 'last_jpegPhoto_lookup' => 'lastJpegPhotoLookup', + 'ldap_nested_groups' => 'ldapNestedGroups', ); return $array; } diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 3ccc7a860f..79c4ae224c 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -36,6 +36,7 @@

+

t('Special Attributes'));?>