Browse Source

support for AD primary groups

support for primary groups

actually the problem is only known on AD, it is only needed to take care of their attributes

adjust to ADs special behaviour

this change was not intended

cache the SID value so it is not requested over and over again

theres only one, use singular

we are access

add tests for new Access methods

add tests for new Group methods

address scrutinizer findings, mostly doc

call ldap_explode_dn from ldap wrapper, enables tests without php5-ldap

PHP Doc

yo dawg, i heard you like backslashes … php doc fix

PHPDoc updated and typos fixed while reviewing
tags/v8.0.0alpha1
Arthur Schiwon 10 years ago
parent
commit
da490bdbbe

+ 198
- 37
apps/user_ldap/group_ldap.php View File

@@ -50,20 +50,29 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
if(!$this->enabled) {
return false;
}
if($this->access->connection->isCached('inGroup'.$uid.':'.$gid)) {
return $this->access->connection->getFromCache('inGroup'.$uid.':'.$gid);
$cacheKey = 'inGroup'.$uid.':'.$gid;
if($this->access->connection->isCached($cacheKey)) {
return $this->access->connection->getFromCache($cacheKey);
}
$dn_user = $this->access->username2dn($uid);
$dn_group = $this->access->groupname2dn($gid);

$userDN = $this->access->username2dn($uid);
$groupDN = $this->access->groupname2dn($gid);
// just in case
if(!$dn_group || !$dn_user) {
$this->access->connection->writeToCache('inGroup'.$uid.':'.$gid, false);
if(!$groupDN || !$userDN) {
$this->access->connection->writeToCache($cacheKey, false);
return false;
}

//check primary group first
if($gid === $this->getUserPrimaryGroup($userDN)) {
$this->access->connection->writeToCache($cacheKey, true);
return true;
}

//usually, LDAP attributes are said to be case insensitive. But there are exceptions of course.
$members = array_keys($this->_groupMembers($dn_group));
$members = array_keys($this->_groupMembers($groupDN));
if(!$members) {
$this->access->connection->writeToCache('inGroup'.$uid.':'.$gid, false);
$this->access->connection->writeToCache($cacheKey, false);
return false;
}

@@ -82,8 +91,8 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
$members = $dns;
}

$isInGroup = in_array($dn_user, $members);
$this->access->connection->writeToCache('inGroup'.$uid.':'.$gid, $isInGroup);
$isInGroup = in_array($userDN, $members);
$this->access->connection->writeToCache($cacheKey, $isInGroup);

return $isInGroup;
}
@@ -91,6 +100,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
/**
* @param string $dnGroup
* @param array|null &$seen
* @return array|mixed|null
*/
private function _groupMembers($dnGroup, &$seen = null) {
if ($seen === null) {
@@ -125,6 +135,125 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
return $allMembers;
}

/**
* translates a primary group ID into an ownCloud internal name
* @param string $gid as given by primaryGroupID on AD
* @param string $dn a DN that belongs to the same domain as the group
* @return string|bool
*/
public function primaryGroupID2Name($gid, $dn) {
$cacheKey = 'primaryGroupIDtoName';
if($this->access->connection->isCached($cacheKey)) {
$groupNames = $this->access->connection->getFromCache($cacheKey);
if(isset($groupNames[$gid])) {
return $groupNames[$gid];
}
}

$domainObjectSid = $this->access->getSID($dn);
if($domainObjectSid === false) {
return false;
}

//we need to get the DN from LDAP
$filter = $this->access->combineFilterWithAnd(array(
$this->access->connection->ldapGroupFilter,
'objectsid=' . $domainObjectSid . '-' . $gid
));
$result = $this->access->searchGroups($filter, array('dn'), 1);
if(empty($result)) {
return false;
}
$dn = $result[0];

//and now the group name
//NOTE once we have separate ownCloud group IDs and group names we can
//directly read the display name attribute instead of the DN
$name = $this->access->dn2groupname($dn);

$this->access->connection->writeToCache($cacheKey, $name);

return $name;
}

/**
* returns the entry's primary group ID
* @param string $dn
* @param string $attribute
* @return string|bool
*/
private function getEntryGroupID($dn, $attribute) {
$value = $this->access->readAttribute($dn, $attribute);
if(is_array($value) && !empty($value)) {
return $value[0];
}
return false;
}

/**
* returns the group's primary ID
* @param string $dn
* @return string|bool
*/
public function getGroupPrimaryGroupID($dn) {
return $this->getEntryGroupID($dn, 'primaryGroupToken');
}

/**
* returns the user's primary group ID
* @param string $dn
* @return string|bool
*/
public function getUserPrimaryGroupIDs($dn) {
return $this->getEntryGroupID($dn, 'primaryGroupID');
}

/**
* returns a list of users that have the given group as primary group
*
* @param string $groupDN
* @param $limit
* @param int $offset
* @return string[]
*/
public function getUsersInPrimaryGroup($groupDN, $limit = -1, $offset = 0) {
$groupID = $this->getGroupPrimaryGroupID($groupDN);
if($groupID === false) {
return array();
}

$filter = $this->access->combineFilterWithAnd(array(
$this->access->connection->ldapUserFilter,
'primaryGroupID=' . $groupID
));

$users = $this->access->fetchListOfUsers(
$filter,
array($this->access->connection->ldapUserDisplayName, 'dn'),
$limit,
$offset
);

return $users;
}

/**
* gets the primary group of a user
* @param string $dn
* @return string
*/
public function getUserPrimaryGroup($dn) {
$groupID = $this->getUserPrimaryGroupIDs($dn);
if($groupID !== false) {
$groupName = $this->primaryGroupID2Name($groupID, $dn);
if($groupName !== false) {
return $groupName;
}
}

return false;
}

/**
* Get all groups a user belongs to
* @param string $uid Name of the user
@@ -161,7 +290,14 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
}

$groups = array_values($this->getGroupsByMember($uid));
$groups = array_unique($this->access->ownCloudGroupNames($groups), SORT_LOCALE_STRING);
$groups = $this->access->ownCloudGroupNames($groups);

$primaryGroup = $this->getUserPrimaryGroup($userDN);
if($primaryGroup !== false) {
$groups[] = $primaryGroup;
}

$groups = array_unique($groups, SORT_LOCALE_STRING);
$this->access->connection->writeToCache($cacheKey, $groups);

return $groups;
@@ -170,6 +306,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
/**
* @param string $dn
* @param array|null &$seen
* @return array
*/
private function getGroupsByMember($dn, &$seen = null) {
if ($seen === null) {
@@ -205,6 +342,11 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {

/**
* get a list of all users in a group
*
* @param string $gid
* @param string $search
* @param int $limit
* @param int $offset
* @return array with user ids
*/
public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
@@ -214,9 +356,9 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
if(!$this->groupExists($gid)) {
return array();
}
$cachekey = 'usersInGroup-'.$gid.'-'.$search.'-'.$limit.'-'.$offset;
$cacheKey = 'usersInGroup-'.$gid.'-'.$search.'-'.$limit.'-'.$offset;
// check for cache of the exact query
$groupUsers = $this->access->connection->getFromCache($cachekey);
$groupUsers = $this->access->connection->getFromCache($cacheKey);
if(!is_null($groupUsers)) {
return $groupUsers;
}
@@ -225,7 +367,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
$groupUsers = $this->access->connection->getFromCache('usersInGroup-'.$gid.'-'.$search);
if(!is_null($groupUsers)) {
$groupUsers = array_slice($groupUsers, $offset, $limit);
$this->access->connection->writeToCache($cachekey, $groupUsers);
$this->access->connection->writeToCache($cacheKey, $groupUsers);
return $groupUsers;
}

@@ -235,14 +377,14 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
$groupDN = $this->access->groupname2dn($gid);
if(!$groupDN) {
// group couldn't be found, return empty resultset
$this->access->connection->writeToCache($cachekey, array());
$this->access->connection->writeToCache($cacheKey, array());
return array();
}

$members = array_keys($this->_groupMembers($groupDN));
if(!$members) {
//in case users could not be retrieved, return empty resultset
$this->access->connection->writeToCache($cachekey, array());
//in case users could not be retrieved, return empty result set
$this->access->connection->writeToCache($cacheKey, array());
return array();
}

@@ -250,7 +392,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
$isMemberUid = (strtolower($this->access->connection->ldapGroupMemberAssocAttr) === 'memberuid');
foreach($members as $member) {
if($isMemberUid) {
//we got uids, need to get their DNs to 'tranlsate' them to usernames
//we got uids, need to get their DNs to 'translate' them to user names
$filter = $this->access->combineFilterWithAnd(array(
\OCP\Util::mb_str_replace('%uid', $member,
$this->access->connection->ldapLoginFilter, 'UTF-8'),
@@ -276,10 +418,16 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
}
}
}

natsort($groupUsers);
$this->access->connection->writeToCache('usersInGroup-'.$gid.'-'.$search, $groupUsers);
$groupUsers = array_slice($groupUsers, $offset, $limit);
$this->access->connection->writeToCache($cachekey, $groupUsers);

//and get users that have the group as primary
$primaryUsers = $this->getUsersInPrimaryGroup($groupDN, $limit, $offset);
$groupUsers = array_unique(array_merge($groupUsers, $primaryUsers));

$this->access->connection->writeToCache($cacheKey, $groupUsers);

return $groupUsers;
}
@@ -291,32 +439,32 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
* @return int|bool
*/
public function countUsersInGroup($gid, $search = '') {
$cachekey = 'countUsersInGroup-'.$gid.'-'.$search;
$cacheKey = 'countUsersInGroup-'.$gid.'-'.$search;
if(!$this->enabled || !$this->groupExists($gid)) {
return false;
}
$groupUsers = $this->access->connection->getFromCache($cachekey);
$groupUsers = $this->access->connection->getFromCache($cacheKey);
if(!is_null($groupUsers)) {
return $groupUsers;
}

$groupDN = $this->access->groupname2dn($gid);
if(!$groupDN) {
// group couldn't be found, return empty resultset
$this->access->connection->writeToCache($cachekey, false);
// group couldn't be found, return empty result set
$this->access->connection->writeToCache($cacheKey, false);
return false;
}

$members = array_keys($this->_groupMembers($groupDN));
if(!$members) {
//in case users could not be retrieved, return empty resultset
$this->access->connection->writeToCache($cachekey, false);
//in case users could not be retrieved, return empty result set
$this->access->connection->writeToCache($cacheKey, false);
return false;
}

if(empty($search)) {
$groupUsers = count($members);
$this->access->connection->writeToCache($cachekey, $groupUsers);
$this->access->connection->writeToCache($cacheKey, $groupUsers);
return $groupUsers;
}
$isMemberUid =
@@ -334,7 +482,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
$groupUsers = array();
foreach($members as $member) {
if($isMemberUid) {
//we got uids, need to get their DNs to 'tranlsate' them to usernames
//we got uids, need to get their DNs to 'translate' them to user names
$filter = $this->access->combineFilterWithAnd(array(
\OCP\Util::mb_str_replace('%uid', $member,
$this->access->connection->ldapLoginFilter, 'UTF-8'),
@@ -359,11 +507,19 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
}
}

//and get users that have the group as primary
$primaryUsers = $this->getUsersInPrimaryGroup($groupDN);
$groupUsers = array_unique(array_merge($groupUsers, $primaryUsers));

return count($groupUsers);
}

/**
* get a list of all groups
*
* @param string $search
* @param $limit
* @param int $offset
* @return array with group names
*
* Returns a list with all groups (used by getGroups)
@@ -372,11 +528,11 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
if(!$this->enabled) {
return array();
}
$cachekey = 'getGroups-'.$search.'-'.$limit.'-'.$offset;
$cacheKey = 'getGroups-'.$search.'-'.$limit.'-'.$offset;

//Check cache before driving unnecessary searches
\OCP\Util::writeLog('user_ldap', 'getGroups '.$cachekey, \OCP\Util::DEBUG);
$ldap_groups = $this->access->connection->getFromCache($cachekey);
\OCP\Util::writeLog('user_ldap', 'getGroups '.$cacheKey, \OCP\Util::DEBUG);
$ldap_groups = $this->access->connection->getFromCache($cacheKey);
if(!is_null($ldap_groups)) {
return $ldap_groups;
}
@@ -397,26 +553,30 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
$offset);
$ldap_groups = $this->access->ownCloudGroupNames($ldap_groups);

$this->access->connection->writeToCache($cachekey, $ldap_groups);
$this->access->connection->writeToCache($cacheKey, $ldap_groups);
return $ldap_groups;
}

/**
* get a list of all groups using a paged search
*
* @param string $search
* @param int $limit
* @param int $offset
* @return array with group names
*
* Returns a list with all groups
* Uses a paged search if available to override a
* server side search limit.
* (active directory has a limit of 1000 by default)
* Uses a paged search if available to override a
* server side search limit.
* (active directory has a limit of 1000 by default)
*/
public function getGroups($search = '', $limit = -1, $offset = 0) {
if(!$this->enabled) {
return array();
}
$pagingsize = $this->access->connection->ldapPagingSize;
$pagingSize = $this->access->connection->ldapPagingSize;
if ((! $this->access->connection->hasPagedResultSupport)
|| empty($pagingsize)) {
|| empty($pagingSize)) {
return $this->getGroupsChunk($search, $limit, $offset);
}
$maxGroups = 100000; // limit max results (just for safety reasons)
@@ -428,7 +588,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
$chunkOffset = $offset;
$allGroups = array();
while ($chunkOffset < $overallLimit) {
$chunkLimit = min($pagingsize, $overallLimit - $chunkOffset);
$chunkLimit = min($pagingSize, $overallLimit - $chunkOffset);
$ldapGroups = $this->getGroupsChunk($search, $chunkLimit, $chunkOffset);
$nread = count($ldapGroups);
\OCP\Util::writeLog('user_ldap', 'getGroups('.$search.'): read '.$nread.' at offset '.$chunkOffset.' (limit: '.$chunkLimit.')', \OCP\Util::DEBUG);
@@ -445,6 +605,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {

/**
* @param string $group
* @return bool
*/
public function groupMatchesFilter($group) {
return (strripos($group, $this->groupSearch) !== false);

+ 89
- 5
apps/user_ldap/lib/access.php View File

@@ -28,6 +28,9 @@ namespace OCA\user_ldap\lib;
* @package OCA\user_ldap\lib
*/
class Access extends LDAPUtility implements user\IUserTools {
/**
* @var \OCA\user_ldap\lib\Connection
*/
public $connection;
public $userManager;
//never ever check this var directly, always use getPagedSearchResultState
@@ -61,8 +64,8 @@ class Access extends LDAPUtility implements user\IUserTools {

/**
* reads a given attribute for an LDAP record identified by a DN
* @param $dn the record in question
* @param $attr the attribute that shall be retrieved
* @param string $dn the record in question
* @param string $attr the attribute that shall be retrieved
* if empty, just check the record's existence
* @param string $filter
* @return array|false an array of values on success or an empty
@@ -180,6 +183,33 @@ class Access extends LDAPUtility implements user\IUserTools {
return $dn;
}

/**
* returns a DN-string that is cleaned from not domain parts, e.g.
* cn=foo,cn=bar,dc=foobar,dc=server,dc=org
* becomes dc=foobar,dc=server,dc=org
* @param string $dn
* @return string
*/
public function getDomainDNFromDN($dn) {
$allParts = $this->ldap->explodeDN($dn, 0);
if($allParts === false) {
//not a valid DN
return '';
}
$domainParts = array();
$dcFound = false;
foreach($allParts as $part) {
if(!$dcFound && strpos($part, 'dc=') === 0) {
$dcFound = true;
}
if($dcFound) {
$domainParts[] = $part;
}
}
$domainDN = implode(',', $domainParts);
return $domainDN;
}

/**
* gives back the database table for the query
* @param bool $isUser
@@ -534,7 +564,7 @@ class Access extends LDAPUtility implements user\IUserTools {
if(!\OC_Group::groupExists($altName)) {
return $altName;
}
$altName = $name . '_' . $lastNo + $attempts;
$altName = $name . '_' . ($lastNo + $attempts);
$attempts++;
}
return false;
@@ -581,6 +611,7 @@ class Access extends LDAPUtility implements user\IUserTools {

/**
* @param boolean $isUsers
* @return array
*/
private function mappedComponents($isUsers) {
$table = $this->getMapTable($isUsers);
@@ -834,7 +865,7 @@ class Access extends LDAPUtility implements user\IUserTools {
private function count($filter, $base, $attr = null, $limit = null, $offset = null, $skipHandling = false) {
\OCP\Util::writeLog('user_ldap', 'Count filter: '.print_r($filter, true), \OCP\Util::DEBUG);

if(is_null($limit)) {
if(is_null($limit) || $limit <= 0) {
$limit = intval($this->connection->ldapPagingSize);
}

@@ -894,6 +925,10 @@ class Access extends LDAPUtility implements user\IUserTools {
* @return array with the search result
*/
private function search($filter, $base, $attr = null, $limit = null, $offset = null, $skipHandling = false) {
if($limit <= 0) {
//otherwise search will fail
$limit = null;
}
$search = $this->executeSearch($filter, $base, $attr, $limit, $offset);
if($search === false) {
return array();
@@ -908,7 +943,7 @@ class Access extends LDAPUtility implements user\IUserTools {
$this->processPagedSearchStatus($sr, $filter, $base, 1, $limit,
$offset, $pagedSearchOK,
$skipHandling);
return;
return array();
}

// Do the server-side sorting
@@ -1232,6 +1267,55 @@ class Access extends LDAPUtility implements user\IUserTools {
return strtoupper($hex_guid_to_guid_str);
}

/**
* gets a SID of the domain of the given dn
* @param string $dn
* @return string|bool
*/
public function getSID($dn) {
$domainDN = $this->getDomainDNFromDN($dn);
$cacheKey = 'getSID-'.$domainDN;
if($this->connection->isCached($cacheKey)) {
return $this->connection->getFromCache($cacheKey);
}

$objectSid = $this->readAttribute($domainDN, 'objectsid');
if(!is_array($objectSid) || empty($objectSid)) {
$this->connection->writeToCache($cacheKey, false);
return false;
}
$domainObjectSid = $this->convertSID2Str($objectSid[0]);
$this->connection->writeToCache($cacheKey, $domainObjectSid);

return $domainObjectSid;
}

/**
* converts a binary SID into a string representation
* @param string $sid
* @return string
* @link http://blogs.freebsdish.org/tmclaugh/2010/07/21/finding-a-users-primary-group-in-ad/#comment-2855
*/
public function convertSID2Str($sid) {
try {
$srl = ord($sid[0]);
$numberSubID = ord($sid[1]);
$x = substr($sid, 2, 6);
$h = unpack('N', "\x0\x0" . substr($x,0,2));
$l = unpack('N', substr($x,2,6));
$iav = bcadd(bcmul($h[1], bcpow(2,32)), $l[1]);
$subIDs = array();
for ($i=0; $i<$numberSubID; $i++) {
$subID = unpack('V', substr($sid, 8+4*$i, 4));
$subIDs[] = $subID[1];
}
} catch (\Exception $e) {
return '';
}

return sprintf('S-%d-%d-%s', $srl, $iav, implode('-', $subIDs));
}

/**
* converts a stored DN so it can be used as base parameter for LDAP queries, internally we store them for usage in LDAP filters
* @param string $dn the DN

+ 7
- 0
apps/user_ldap/lib/connection.php View File

@@ -23,6 +23,13 @@

namespace OCA\user_ldap\lib;

//magic properties (incomplete)
/**
* responsible for LDAP connections in context with the provided configuration
* @property string ldapUserFilter
* @property string ldapUserDisplayName
* @property boolean hasPagedResultSupport
*/
class Connection extends LDAPUtility {
private $ldapConnectionRes = null;
private $configPrefix;

+ 9
- 0
apps/user_ldap/lib/ildapwrapper.php View File

@@ -89,6 +89,15 @@ interface ILDAPWrapper {
*/
public function error($link);

/**
* Splits DN into its component parts
* @param string $dn
* @param int @withAttrib
* @return array|false
* @link http://www.php.net/manual/en/function.ldap-explode-dn.php
*/
public function explodeDN($dn, $withAttrib);

/**
* Return first result id
* @param resource $link LDAP link resource

+ 11
- 0
apps/user_ldap/lib/ldap.php View File

@@ -98,6 +98,17 @@ class LDAP implements ILDAPWrapper {
return $this->invokeLDAPMethod('error', $link);
}

/**
* Splits DN into its component parts
* @param string $dn
* @param int @withAttrib
* @return array|false
* @link http://www.php.net/manual/en/function.ldap-explode-dn.php
*/
public function explodeDN($dn, $withAttrib) {
return $this->invokeLDAPMethod('ldap_explode_dn', $dn, $withAttrib);
}

/**
* @param LDAP $link
* @param LDAP $result

+ 51
- 1
apps/user_ldap/tests/access.php View File

@@ -77,4 +77,54 @@ class Test_Access extends \PHPUnit_Framework_TestCase {
$expected = 'foo\\\\*bar';
$this->assertTrue($expected === $access->escapeFilterPart($input));
}
}

public function testConvertSID2StrSuccess() {
list($lw, $con, $um) = $this->getConnecterAndLdapMock();
$access = new Access($con, $lw, $um);

$sidBinary = file_get_contents(__DIR__ . '/data/sid.dat');
$sidExpected = 'S-1-5-21-249921958-728525901-1594176202';

$this->assertSame($sidExpected, $access->convertSID2Str($sidBinary));
}

public function testConvertSID2StrInputError() {
list($lw, $con, $um) = $this->getConnecterAndLdapMock();
$access = new Access($con, $lw, $um);

$sidIllegal = 'foobar';
$sidExpected = '';

$this->assertSame($sidExpected, $access->convertSID2Str($sidIllegal));
}

public function testGetDomainDNFromDNSuccess() {
list($lw, $con, $um) = $this->getConnecterAndLdapMock();
$access = new Access($con, $lw, $um);

$inputDN = 'uid=zaphod,cn=foobar,dc=my,dc=server,dc=com';
$domainDN = 'dc=my,dc=server,dc=com';

$lw->expects($this->once())
->method('explodeDN')
->with($inputDN, 0)
->will($this->returnValue(explode(',', $inputDN)));

$this->assertSame($domainDN, $access->getDomainDNFromDN($inputDN));
}

public function testGetDomainDNFromDNError() {
list($lw, $con, $um) = $this->getConnecterAndLdapMock();
$access = new Access($con, $lw, $um);

$inputDN = 'foobar';
$expected = '';

$lw->expects($this->once())
->method('explodeDN')
->with($inputDN, 0)
->will($this->returnValue(false));

$this->assertSame($expected, $access->getDomainDNFromDN($inputDN));
}
}

BIN
apps/user_ldap/tests/data/sid.dat View File


+ 151
- 1
apps/user_ldap/tests/group_ldap.php View File

@@ -95,6 +95,10 @@ class Test_Group_Ldap extends \PHPUnit_Framework_TestCase {
->method('groupname2dn')
->will($this->returnValue('cn=group,dc=foo,dc=bar'));

$access->expects($this->any())
->method('fetchListOfUsers')
->will($this->returnValue(array()));

$access->expects($this->any())
->method('readAttribute')
->will($this->returnCallback(function($name) {
@@ -111,7 +115,9 @@ class Test_Group_Ldap extends \PHPUnit_Framework_TestCase {

$access->expects($this->any())
->method('dn2username')
->will($this->returnValue('foobar'));
->will($this->returnCallback(function() {
return 'foobar' . \OCP\Util::generateRandomBytes(7);
}));

$groupBackend = new GroupLDAP($access);
$users = $groupBackend->countUsersInGroup('group', '3');
@@ -119,4 +125,148 @@ class Test_Group_Ldap extends \PHPUnit_Framework_TestCase {
$this->assertSame(2, $users);
}

public function testPrimaryGroupID2NameSuccess() {
$access = $this->getAccessMock();
$this->enableGroups($access);

$userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';

$access->expects($this->once())
->method('getSID')
->with($userDN)
->will($this->returnValue('S-1-5-21-249921958-728525901-1594176202'));

$access->expects($this->once())
->method('searchGroups')
->will($this->returnValue(array('cn=foo,dc=barfoo,dc=bar')));

$access->expects($this->once())
->method('dn2groupname')
->with('cn=foo,dc=barfoo,dc=bar')
->will($this->returnValue('MyGroup'));

$groupBackend = new GroupLDAP($access);

$group = $groupBackend->primaryGroupID2Name('3117', $userDN);

$this->assertSame('MyGroup', $group);
}

public function testPrimaryGroupID2NameNoSID() {
$access = $this->getAccessMock();
$this->enableGroups($access);

$userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';

$access->expects($this->once())
->method('getSID')
->with($userDN)
->will($this->returnValue(false));

$access->expects($this->never())
->method('searchGroups');

$access->expects($this->never())
->method('dn2groupname');

$groupBackend = new GroupLDAP($access);

$group = $groupBackend->primaryGroupID2Name('3117', $userDN);

$this->assertSame(false, $group);
}

public function testPrimaryGroupID2NameNoGroup() {
$access = $this->getAccessMock();
$this->enableGroups($access);

$userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';

$access->expects($this->once())
->method('getSID')
->with($userDN)
->will($this->returnValue('S-1-5-21-249921958-728525901-1594176202'));

$access->expects($this->once())
->method('searchGroups')
->will($this->returnValue(array()));

$access->expects($this->never())
->method('dn2groupname');

$groupBackend = new GroupLDAP($access);

$group = $groupBackend->primaryGroupID2Name('3117', $userDN);

$this->assertSame(false, $group);
}

public function testPrimaryGroupID2NameNoName() {
$access = $this->getAccessMock();
$this->enableGroups($access);

$userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';

$access->expects($this->once())
->method('getSID')
->with($userDN)
->will($this->returnValue('S-1-5-21-249921958-728525901-1594176202'));

$access->expects($this->once())
->method('searchGroups')
->will($this->returnValue(array('cn=foo,dc=barfoo,dc=bar')));

$access->expects($this->once())
->method('dn2groupname')
->will($this->returnValue(false));

$groupBackend = new GroupLDAP($access);

$group = $groupBackend->primaryGroupID2Name('3117', $userDN);

$this->assertSame(false, $group);
}

public function testGetEntryGroupIDValue() {
//tests getEntryGroupID via getGroupPrimaryGroupID
//which is basically identical to getUserPrimaryGroupIDs
$access = $this->getAccessMock();
$this->enableGroups($access);

$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
$attr = 'primaryGroupToken';

$access->expects($this->once())
->method('readAttribute')
->with($dn, $attr)
->will($this->returnValue(array('3117')));

$groupBackend = new GroupLDAP($access);

$gid = $groupBackend->getGroupPrimaryGroupID($dn);

$this->assertSame('3117', $gid);
}

public function testGetEntryGroupIDNoValue() {
//tests getEntryGroupID via getGroupPrimaryGroupID
//which is basically identical to getUserPrimaryGroupIDs
$access = $this->getAccessMock();
$this->enableGroups($access);

$dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
$attr = 'primaryGroupToken';

$access->expects($this->once())
->method('readAttribute')
->with($dn, $attr)
->will($this->returnValue(false));

$groupBackend = new GroupLDAP($access);

$gid = $groupBackend->getGroupPrimaryGroupID($dn);

$this->assertSame(false, $gid);
}

}

Loading…
Cancel
Save