Skip to content
Merged
Changes from all commits
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
84 changes: 68 additions & 16 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 @@ -184,7 +186,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', $cr, $dn, $filter, array($attr));
if(!$this->ldap->isResource($rr)) {
if ($attr !== '') {
//do not throw this message on userExists check, irritates
Expand All @@ -193,18 +195,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', $cr, $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', $cr, $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', $cr, $er), MB_CASE_LOWER, 'UTF-8');
$attr = mb_strtolower($attr, 'UTF-8');

if(isset($result[$attr]) && $result[$attr]['count'] > 0) {
Expand Down Expand Up @@ -243,9 +245,8 @@ public function setPassword($userDN, $password) {
\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', $cr, $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,12 +835,63 @@ public function countObjects($limit = null, $offset = null) {
return $this->count('objectclass=*', $this->connection->ldapBase, array('dn'), $limit, $offset);
}

/**
* Returns the LDAP handler
* @throws \OC\ServerNotAvailableException
*/

/**
* @return mixed
* @throws \OC\ServerNotAvailableException
*/
private function invokeLDAPMethod() {
$arguments = func_get_args();
$command = array_shift($arguments);
$cr = array_shift($arguments);
if (!method_exists($this->ldap, $command)) {
return null;
}
array_unshift($arguments, $cr);
// php no longer supports call-time pass-by-reference
// thus cannot support controlPagedResultResponse as the third argument
// is a reference
$doMethod = function () use ($command, &$arguments) {
if ($command == 'controlPagedResultResponse') {
throw new \InvalidArgumentException('Invoker does not support controlPagedResultResponse, call LDAP Wrapper directly instead.');
} 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->resetConnectionResource();
$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);
throw $e;
}

$arguments[0] = array_pad([], count($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
* @param int $offset optional, a starting point
* @return array|false array with the search result as first value and pagedSearchOK as
* second | false if not successful
* @throws \OC\ServerNotAvailableException
*/
private function executeSearch($filter, $base, &$attr = null, $limit = null, $offset = null) {
if(!is_null($attr) && !is_array($attr)) {
Expand All @@ -859,8 +911,9 @@ 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);
$error = $this->ldap->errno($cr);
$sr = $this->invokeLDAPMethod('search', $linkResources, $base, $filter, $attr);
// cannot use $cr anymore, might have changed in the previous call!
$error = $this->ldap->errno($this->connection->getConnectionResource());
if(!is_array($sr) || $error !== 0) {
\OCP\Util::writeLog('user_ldap', 'Attempt for Paging? '.print_r($pagedSearchOK, true), \OCP\Util::ERROR);
return false;
Expand Down Expand Up @@ -972,11 +1025,10 @@ private function count($filter, $base, $attr = null, $limit = null, $offset = nu
* @return int
*/
private function countEntriesInSearchResults($searchResults) {
$cr = $this->connection->getConnectionResource();
$counter = 0;

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

Expand Down Expand Up @@ -1026,7 +1078,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', $cr, $res));
}

$continue = $this->processPagedSearchStatus($sr, $filter, $base, $findings['count'],
Expand Down Expand Up @@ -1589,7 +1641,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', $cr, 0, false, $this->lastCookie);
$this->getPagedSearchResultState();
$this->lastCookie = '';
$this->cookies = array();
Expand Down Expand Up @@ -1715,7 +1767,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(
$pagedSearchOK = $this->invokeLDAPMethod('controlPagedResult',
$this->connection->getConnectionResource(), $limit,
false, $cookie);
if(!$pagedSearchOK) {
Expand Down Expand Up @@ -1743,9 +1795,9 @@ 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',
$this->connection->getConnectionResource(),
$pageSize, false, '');
}

return $pagedSearchOK;
Expand Down