Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
special case for controlPagedResultResponse. It would be nice if ther…
…e was a generic way to pass by reference with call_user_func_array..

Signed-off-by: Arthur Schiwon <[email protected]>
  • Loading branch information
bline authored and blizzz committed May 26, 2017
commit 3f176a7449c782dbf1b666096ba7acf474347de8
106 changes: 76 additions & 30 deletions apps/user_ldap/lib/Access.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
use OCA\User_LDAP\User\OfflineUser;
use OCA\User_LDAP\Mapping\AbstractMapping;

use OC\ServerNotAvailableException;

/**
* Class Access
* @package OCA\User_LDAP
Expand Down Expand Up @@ -167,12 +169,6 @@ public function readAttribute($dn, $attr, $filter = 'objectClass=*') {
\OCP\Util::WARN);
return false;
}
$cr = $this->connection->getConnectionResource();
if(!$this->ldap->isResource($cr)) {
//LDAP not available
\OCP\Util::writeLog('user_ldap', 'LDAP resource not available.', \OCP\Util::DEBUG);
return false;
}
//Cancel possibly running Paged Results operation, otherwise we run in
//LDAP protocol errors
$this->abandonPagedSearch();
Expand All @@ -184,7 +180,7 @@ public function readAttribute($dn, $attr, $filter = 'objectClass=*') {
$maxResults = $pagingSize > 20 ? $pagingSize : 500;
$this->initPagedSearch($filter, array($dn), array($attr), $maxResults, 0);
$dn = $this->helper->DNasBaseParameter($dn);
$rr = @$this->ldap->read($cr, $dn, $filter, array($attr));
$rr = @$this->invokeLDAPMethod('read', $dn, $filter, array($attr));
if(!$this->ldap->isResource($rr)) {
if ($attr !== '') {
//do not throw this message on userExists check, irritates
Expand All @@ -193,18 +189,18 @@ public function readAttribute($dn, $attr, $filter = 'objectClass=*') {
//in case an error occurs , e.g. object does not exist
return false;
}
if ($attr === '' && ($filter === 'objectclass=*' || $this->ldap->countEntries($cr, $rr) === 1)) {
if ($attr === '' && ($filter === 'objectclass=*' || $this->invokeLDAPMethod('countEntries', $rr) === 1)) {
\OCP\Util::writeLog('user_ldap', 'readAttribute: '.$dn.' found', \OCP\Util::DEBUG);
return array();
}
$er = $this->ldap->firstEntry($cr, $rr);
$er = $this->invokeLDAPMethod('firstEntry', $rr);
if(!$this->ldap->isResource($er)) {
//did not match the filter, return false
return false;
}
//LDAP attributes are not case sensitive
$result = \OCP\Util::mb_array_change_key_case(
$this->ldap->getAttributes($cr, $er), MB_CASE_LOWER, 'UTF-8');
$this->invokeLDAPMethod('getAttributes', $er), MB_CASE_LOWER, 'UTF-8');
$attr = mb_strtolower($attr, 'UTF-8');

if(isset($result[$attr]) && $result[$attr]['count'] > 0) {
Expand Down Expand Up @@ -237,15 +233,8 @@ public function setPassword($userDN, $password) {
if(intval($this->connection->turnOnPasswordChange) !== 1) {
throw new \Exception('LDAP password changes are disabled.');
}
$cr = $this->connection->getConnectionResource();
if(!$this->ldap->isResource($cr)) {
//LDAP not available
\OCP\Util::writeLog('user_ldap', 'LDAP resource not available.', \OCP\Util::DEBUG);
return false;
}

try {
return $this->ldap->modReplace($cr, $userDN, $password);
return $this->invokeLDAPMethod('modReplace', $userDN, $password);
} catch(ConstraintViolationException $e) {
throw new HintException('Password change rejected.', \OC::$server->getL10N('user_ldap')->t('Password change rejected. Hint: ').$e->getMessage(), $e->getCode());
}
Expand Down Expand Up @@ -834,6 +823,52 @@ public function countObjects($limit = null, $offset = null) {
return $this->count('objectclass=*', $this->connection->ldapBase, array('dn'), $limit, $offset);
}

/**
* @return mixed
*/
private function invokeLDAPMethod() {
$arguments = func_get_args();
$command = array_shift($arguments);
if (!method_exists($this->ldap, $command)) {
return null;
}
$cr = $this->connection->getConnectionResource();
if(!$this->ldap->isResource($cr)) {
// Seems like we didn't find any resource.
\OCP\Util::writeLog('user_ldap', "Could not $command, because resource is missing.", \OCP\Util::DEBUG);
return false;
}
array_unshift($arguments, $cr);
// php no longer supports call-time pass-by-reference
// make special case for controlPagedResultResponse as the third argument is a reference
$doMethod = function () use ($command, &$arguments) {
if ($command == 'controlPagedResultResponse') {
return $this->ldap->controlPagedResultResponse($arguments[0], $arguments[1], $arguments[2]);
} else {
return call_user_func_array(array($this->ldap, $command), $arguments);
}
};
try {
$ret = $doMethod();
} catch (ServerNotAvailableException $e) {
/* Server connection lost, attempt to reestablish it
* Maybe implement exponential backoff?
* This was enough to get solr indexer working which has large delays between LDAP fetches.
*/
\OCP\Util::writeLog('user_ldap', "Connection lost on $command, attempting to reestablish.", \OCP\Util::DEBUG);
$this->connection = clone $this->connection;
$cr = $this->connection->getConnectionResource();
if(!$this->ldap->isResource($cr)) {
// Seems like we didn't find any resource.
\OCP\Util::writeLog('user_ldap', "Could not $command, because resource is missing.", \OCP\Util::DEBUG);
return false;
}
$arguments[0] = $cr;
$ret = $doMethod();
}
return $ret;
}

/**
* retrieved. Results will according to the order in the array.
* @param int $limit optional, maximum results to be counted
Expand All @@ -859,7 +894,23 @@ private function executeSearch($filter, $base, &$attr = null, $limit = null, $of
$pagedSearchOK = $this->initPagedSearch($filter, $base, $attr, intval($limit), $offset);

$linkResources = array_pad(array(), count($base), $cr);
$sr = $this->ldap->search($linkResources, $base, $filter, $attr);
try {
$sr = $this->ldap->search($linkResources, $base, $filter, $attr);
} catch (ServerNotAvailableException $e) {
/* Server connection lost, attempt to reestablish it
* According to MS docs, LDAP cookies survive reconnects
*/
\OCP\Util::writeLog('user_ldap', "Connection lost on search, attempting to reestablish.", \OCP\Util::DEBUG);
$this->connection = clone $this->connection;
$cr = $this->connection->getConnectionResource();
if(!$this->ldap->isResource($cr)) {
// Seems like we didn't find any resource.
\OCP\Util::writeLog('user_ldap', "Could not search, because resource is missing.", \OCP\Util::DEBUG);
return false;
}
$linkResources = array_pad(array(), count($base), $cr);
$sr = $this->ldap->search($linkResources, $base, $filter, $attr);
}
$error = $this->ldap->errno($cr);
if(!is_array($sr) || $error !== 0) {
\OCP\Util::writeLog('user_ldap', 'Attempt for Paging? '.print_r($pagedSearchOK, true), \OCP\Util::ERROR);
Expand Down Expand Up @@ -887,7 +938,7 @@ private function processPagedSearchStatus($sr, $filter, $base, $iFoundItems, $li
if($pagedSearchOK) {
$cr = $this->connection->getConnectionResource();
foreach($sr as $key => $res) {
if($this->ldap->controlPagedResultResponse($cr, $res, $cookie)) {
if($this->invokeLDAPMethod('controlPagedResultResponse', $res, $cookie)) {
$this->setPagedResultCookie($base[$key], $filter, $limit, $offset, $cookie);
}
}
Expand Down Expand Up @@ -976,7 +1027,7 @@ private function countEntriesInSearchResults($searchResults) {
$counter = 0;

foreach($searchResults as $res) {
$count = intval($this->ldap->countEntries($cr, $res));
$count = intval($this->invokeLDAPMethod('countEntries', $res));
$counter += $count;
}

Expand Down Expand Up @@ -1026,7 +1077,7 @@ private function search($filter, $base, $attr = null, $limit = null, $offset = n
}

foreach($sr as $res) {
$findings = array_merge($findings, $this->ldap->getEntries($cr , $res ));
$findings = array_merge($findings, $this->invokeLDAPMethod('getEntries', $res));
}

$continue = $this->processPagedSearchStatus($sr, $filter, $base, $findings['count'],
Expand Down Expand Up @@ -1588,8 +1639,7 @@ public function isDNPartOfBase($dn, $bases) {
*/
private function abandonPagedSearch() {
if($this->connection->hasPagedResultSupport) {
$cr = $this->connection->getConnectionResource();
$this->ldap->controlPagedResult($cr, 0, false, $this->lastCookie);
$this->invokeLDAPMethod('controlPagedResult', 0, false, $this->lastCookie);
$this->getPagedSearchResultState();
$this->lastCookie = '';
$this->cookies = array();
Expand Down Expand Up @@ -1715,9 +1765,7 @@ private function initPagedSearch($filter, $bases, $attr, $limit, $offset) {
if(!is_null($cookie)) {
//since offset = 0, this is a new search. We abandon other searches that might be ongoing.
$this->abandonPagedSearch();
$pagedSearchOK = $this->ldap->controlPagedResult(
$this->connection->getConnectionResource(), $limit,
false, $cookie);
$pagedSearchOK = $this->invokeLDAPMethod('controlPagedResult', $limit, false, $cookie);
if(!$pagedSearchOK) {
return false;
}
Expand All @@ -1743,9 +1791,7 @@ private function initPagedSearch($filter, $bases, $attr, $limit, $offset) {
// in case someone set it to 0 … use 500, otherwise no results will
// be returned.
$pageSize = intval($this->connection->ldapPagingSize) > 0 ? intval($this->connection->ldapPagingSize) : 500;
$pagedSearchOK = $this->ldap->controlPagedResult(
$this->connection->getConnectionResource(), $pageSize, false, ''
);
$pagedSearchOK = $this->invokeLDAPMethod('controlPagedResult', $pageSize, false, '');
}

return $pagedSearchOK;
Expand Down