diff options
Diffstat (limited to 'apps/user_ldap')
-rw-r--r-- | apps/user_ldap/group_ldap.php | 235 | ||||
-rw-r--r-- | apps/user_ldap/lib/access.php | 94 | ||||
-rw-r--r-- | apps/user_ldap/lib/connection.php | 7 | ||||
-rw-r--r-- | apps/user_ldap/lib/ildapwrapper.php | 9 | ||||
-rw-r--r-- | apps/user_ldap/lib/ldap.php | 11 | ||||
-rw-r--r-- | apps/user_ldap/tests/access.php | 52 | ||||
-rw-r--r-- | apps/user_ldap/tests/data/sid.dat | bin | 0 -> 24 bytes | |||
-rw-r--r-- | apps/user_ldap/tests/group_ldap.php | 152 |
8 files changed, 516 insertions, 44 deletions
diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index 1a35691be85..0d3a70575ba 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -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) { @@ -126,6 +136,125 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { } /** + * 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 * @return array with group names @@ -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); diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index ca5d1386995..e3b6566bcf0 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -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 @@ -181,6 +184,33 @@ class Access extends LDAPUtility implements user\IUserTools { } /** + * 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 * @return string @@ -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 @@ -1233,6 +1268,55 @@ class Access extends LDAPUtility implements user\IUserTools { } /** + * 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 * @return string diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index bafb0e0b895..336ea7b3bbc 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -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; diff --git a/apps/user_ldap/lib/ildapwrapper.php b/apps/user_ldap/lib/ildapwrapper.php index 97ae0810116..590f6d7ac7a 100644 --- a/apps/user_ldap/lib/ildapwrapper.php +++ b/apps/user_ldap/lib/ildapwrapper.php @@ -90,6 +90,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 * @param resource $result LDAP result resource diff --git a/apps/user_ldap/lib/ldap.php b/apps/user_ldap/lib/ldap.php index 2b20b2ab738..967754db7d3 100644 --- a/apps/user_ldap/lib/ldap.php +++ b/apps/user_ldap/lib/ldap.php @@ -99,6 +99,17 @@ class LDAP implements ILDAPWrapper { } /** + * 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 * @return mixed diff --git a/apps/user_ldap/tests/access.php b/apps/user_ldap/tests/access.php index 8ead5d68482..2ff7540b8ef 100644 --- a/apps/user_ldap/tests/access.php +++ b/apps/user_ldap/tests/access.php @@ -77,4 +77,54 @@ class Test_Access extends \PHPUnit_Framework_TestCase { $expected = 'foo\\\\*bar'; $this->assertTrue($expected === $access->escapeFilterPart($input)); } -}
\ No newline at end of file + + 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)); + } +} diff --git a/apps/user_ldap/tests/data/sid.dat b/apps/user_ldap/tests/data/sid.dat Binary files differnew file mode 100644 index 00000000000..3d500c6a872 --- /dev/null +++ b/apps/user_ldap/tests/data/sid.dat diff --git a/apps/user_ldap/tests/group_ldap.php b/apps/user_ldap/tests/group_ldap.php index 1184fe1e82e..c4aed25a1cc 100644 --- a/apps/user_ldap/tests/group_ldap.php +++ b/apps/user_ldap/tests/group_ldap.php @@ -96,6 +96,10 @@ class Test_Group_Ldap extends \PHPUnit_Framework_TestCase { ->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) { //the search operation will call readAttribute, thus we need @@ -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); + } + } |