special case for controlPagedResultResponse. It would be nice if there was a generic way to pass by reference with call_user_func_array..
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
This commit is contained in:
parent
ecd299e8de
commit
8829d84949
1 changed files with 78 additions and 33 deletions
|
@ -47,6 +47,8 @@ use OCA\User_LDAP\User\Manager;
|
||||||
use OCA\User_LDAP\User\OfflineUser;
|
use OCA\User_LDAP\User\OfflineUser;
|
||||||
use OCA\User_LDAP\Mapping\AbstractMapping;
|
use OCA\User_LDAP\Mapping\AbstractMapping;
|
||||||
|
|
||||||
|
use OC\ServerNotAvailableException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Access
|
* Class Access
|
||||||
* @package OCA\User_LDAP
|
* @package OCA\User_LDAP
|
||||||
|
@ -167,12 +169,6 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
\OCP\Util::WARN);
|
\OCP\Util::WARN);
|
||||||
return false;
|
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
|
//Cancel possibly running Paged Results operation, otherwise we run in
|
||||||
//LDAP protocol errors
|
//LDAP protocol errors
|
||||||
$this->abandonPagedSearch();
|
$this->abandonPagedSearch();
|
||||||
|
@ -190,7 +186,7 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
$values = [];
|
$values = [];
|
||||||
$isRangeRequest = false;
|
$isRangeRequest = false;
|
||||||
do {
|
do {
|
||||||
$result = $this->executeRead($cr, $dn, $attrToRead, $filter, $maxResults);
|
$result = $this->executeRead($dn, $attrToRead, $filter, $maxResults);
|
||||||
if(is_bool($result)) {
|
if(is_bool($result)) {
|
||||||
// when an exists request was run and it was successful, an empty
|
// when an exists request was run and it was successful, an empty
|
||||||
// array must be returned
|
// array must be returned
|
||||||
|
@ -232,7 +228,6 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
/**
|
/**
|
||||||
* Runs an read operation against LDAP
|
* Runs an read operation against LDAP
|
||||||
*
|
*
|
||||||
* @param resource $cr the LDAP connection
|
|
||||||
* @param string $dn
|
* @param string $dn
|
||||||
* @param string $attribute
|
* @param string $attribute
|
||||||
* @param string $filter
|
* @param string $filter
|
||||||
|
@ -241,10 +236,10 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
* was performed and the requested DN found, array with the
|
* was performed and the requested DN found, array with the
|
||||||
* returned data on a successful usual operation
|
* returned data on a successful usual operation
|
||||||
*/
|
*/
|
||||||
public function executeRead($cr, $dn, $attribute, $filter, $maxResults) {
|
public function executeRead($dn, $attribute, $filter, $maxResults) {
|
||||||
$this->initPagedSearch($filter, array($dn), array($attribute), $maxResults, 0);
|
$this->initPagedSearch($filter, array($dn), array($attribute), $maxResults, 0);
|
||||||
$dn = $this->helper->DNasBaseParameter($dn);
|
$dn = $this->helper->DNasBaseParameter($dn);
|
||||||
$rr = @$this->ldap->read($cr, $dn, $filter, array($attribute));
|
$rr = @$this->invokeLDAPMethod('read', $dn, $filter, array($attribute));
|
||||||
if (!$this->ldap->isResource($rr)) {
|
if (!$this->ldap->isResource($rr)) {
|
||||||
if ($attribute !== '') {
|
if ($attribute !== '') {
|
||||||
//do not throw this message on userExists check, irritates
|
//do not throw this message on userExists check, irritates
|
||||||
|
@ -253,18 +248,18 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
//in case an error occurs , e.g. object does not exist
|
//in case an error occurs , e.g. object does not exist
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($attribute === '' && ($filter === 'objectclass=*' || $this->ldap->countEntries($cr, $rr) === 1)) {
|
if ($attribute === '' && ($filter === 'objectclass=*' || $this->invokeLDAPMethod('countEntries', $rr) === 1)) {
|
||||||
\OCP\Util::writeLog('user_ldap', 'readAttribute: ' . $dn . ' found', \OCP\Util::DEBUG);
|
\OCP\Util::writeLog('user_ldap', 'readAttribute: ' . $dn . ' found', \OCP\Util::DEBUG);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
$er = $this->ldap->firstEntry($cr, $rr);
|
$er = $this->invokeLDAPMethod('firstEntry', $rr);
|
||||||
if (!$this->ldap->isResource($er)) {
|
if (!$this->ldap->isResource($er)) {
|
||||||
//did not match the filter, return false
|
//did not match the filter, return false
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//LDAP attributes are not case sensitive
|
//LDAP attributes are not case sensitive
|
||||||
$result = \OCP\Util::mb_array_change_key_case(
|
$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');
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
@ -337,15 +332,8 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
if(intval($this->connection->turnOnPasswordChange) !== 1) {
|
if(intval($this->connection->turnOnPasswordChange) !== 1) {
|
||||||
throw new \Exception('LDAP password changes are disabled.');
|
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 {
|
try {
|
||||||
return $this->ldap->modReplace($cr, $userDN, $password);
|
return $this->invokeLDAPMethod('modReplace', $userDN, $password);
|
||||||
} catch(ConstraintViolationException $e) {
|
} catch(ConstraintViolationException $e) {
|
||||||
throw new HintException('Password change rejected.', \OC::$server->getL10N('user_ldap')->t('Password change rejected. Hint: ').$e->getMessage(), $e->getCode());
|
throw new HintException('Password change rejected.', \OC::$server->getL10N('user_ldap')->t('Password change rejected. Hint: ').$e->getMessage(), $e->getCode());
|
||||||
}
|
}
|
||||||
|
@ -937,6 +925,52 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
return $this->count('objectclass=*', $this->connection->ldapBase, array('dn'), $limit, $offset);
|
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.
|
* retrieved. Results will according to the order in the array.
|
||||||
* @param int $limit optional, maximum results to be counted
|
* @param int $limit optional, maximum results to be counted
|
||||||
|
@ -962,7 +996,23 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
$pagedSearchOK = $this->initPagedSearch($filter, $base, $attr, intval($limit), $offset);
|
$pagedSearchOK = $this->initPagedSearch($filter, $base, $attr, intval($limit), $offset);
|
||||||
|
|
||||||
$linkResources = array_pad(array(), count($base), $cr);
|
$linkResources = array_pad(array(), count($base), $cr);
|
||||||
|
try {
|
||||||
$sr = $this->ldap->search($linkResources, $base, $filter, $attr);
|
$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);
|
$error = $this->ldap->errno($cr);
|
||||||
if(!is_array($sr) || $error !== 0) {
|
if(!is_array($sr) || $error !== 0) {
|
||||||
\OCP\Util::writeLog('user_ldap', 'Attempt for Paging? '.print_r($pagedSearchOK, true), \OCP\Util::ERROR);
|
\OCP\Util::writeLog('user_ldap', 'Attempt for Paging? '.print_r($pagedSearchOK, true), \OCP\Util::ERROR);
|
||||||
|
@ -990,7 +1040,7 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
if($pagedSearchOK) {
|
if($pagedSearchOK) {
|
||||||
$cr = $this->connection->getConnectionResource();
|
$cr = $this->connection->getConnectionResource();
|
||||||
foreach($sr as $key => $res) {
|
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);
|
$this->setPagedResultCookie($base[$key], $filter, $limit, $offset, $cookie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1079,7 +1129,7 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
$counter = 0;
|
$counter = 0;
|
||||||
|
|
||||||
foreach($searchResults as $res) {
|
foreach($searchResults as $res) {
|
||||||
$count = intval($this->ldap->countEntries($cr, $res));
|
$count = intval($this->invokeLDAPMethod('countEntries', $res));
|
||||||
$counter += $count;
|
$counter += $count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1129,7 +1179,7 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($sr as $res) {
|
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'],
|
$continue = $this->processPagedSearchStatus($sr, $filter, $base, $findings['count'],
|
||||||
|
@ -1691,8 +1741,7 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
*/
|
*/
|
||||||
private function abandonPagedSearch() {
|
private function abandonPagedSearch() {
|
||||||
if($this->connection->hasPagedResultSupport) {
|
if($this->connection->hasPagedResultSupport) {
|
||||||
$cr = $this->connection->getConnectionResource();
|
$this->invokeLDAPMethod('controlPagedResult', 0, false, $this->lastCookie);
|
||||||
$this->ldap->controlPagedResult($cr, 0, false, $this->lastCookie);
|
|
||||||
$this->getPagedSearchResultState();
|
$this->getPagedSearchResultState();
|
||||||
$this->lastCookie = '';
|
$this->lastCookie = '';
|
||||||
$this->cookies = array();
|
$this->cookies = array();
|
||||||
|
@ -1818,9 +1867,7 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
if(!is_null($cookie)) {
|
if(!is_null($cookie)) {
|
||||||
//since offset = 0, this is a new search. We abandon other searches that might be ongoing.
|
//since offset = 0, this is a new search. We abandon other searches that might be ongoing.
|
||||||
$this->abandonPagedSearch();
|
$this->abandonPagedSearch();
|
||||||
$pagedSearchOK = $this->ldap->controlPagedResult(
|
$pagedSearchOK = $this->invokeLDAPMethod('controlPagedResult', $limit, false, $cookie);
|
||||||
$this->connection->getConnectionResource(), $limit,
|
|
||||||
false, $cookie);
|
|
||||||
if(!$pagedSearchOK) {
|
if(!$pagedSearchOK) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1846,9 +1893,7 @@ class Access extends LDAPUtility implements IUserTools {
|
||||||
// in case someone set it to 0 … use 500, otherwise no results will
|
// in case someone set it to 0 … use 500, otherwise no results will
|
||||||
// be returned.
|
// be returned.
|
||||||
$pageSize = intval($this->connection->ldapPagingSize) > 0 ? intval($this->connection->ldapPagingSize) : 500;
|
$pageSize = intval($this->connection->ldapPagingSize) > 0 ? intval($this->connection->ldapPagingSize) : 500;
|
||||||
$pagedSearchOK = $this->ldap->controlPagedResult(
|
$pagedSearchOK = $this->invokeLDAPMethod('controlPagedResult', $pageSize, false, '');
|
||||||
$this->connection->getConnectionResource(), $pageSize, false, ''
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $pagedSearchOK;
|
return $pagedSearchOK;
|
||||||
|
|
Loading…
Reference in a new issue