0
0
Fork 0
mirror of https://github.com/nextcloud/server.git synced 2025-03-15 00:43:23 +00:00

Unfold call to ldap_parse_result. Handle cookie outside of adapter.

Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
This commit is contained in:
Côme Chilliet 2022-09-08 11:33:43 +02:00
parent 3c9b1c5296
commit d10dfa84db
No known key found for this signature in database
GPG key ID: A3E2F658B28C760A
4 changed files with 33 additions and 112 deletions
apps/user_ldap/lib

View file

@ -95,8 +95,7 @@ class Access extends LDAPUtility {
private $ncUserManager;
/** @var LoggerInterface */
private $logger;
/** @var string */
private $lastCookie = '';
private string $lastCookie = '';
public function __construct(
Connection $connection,
@ -1910,7 +1909,7 @@ class Access extends LDAPUtility {
* @return bool
*/
public function hasMoreResults() {
if (empty($this->lastCookie) && $this->lastCookie !== '0') {
if ($this->lastCookie === '') {
// as in RFC 2696, when all results are returned, the cookie will
// be empty.
return false;
@ -1962,8 +1961,8 @@ class Access extends LDAPUtility {
'offset' => $offset
]
);
//get the cookie from the search for the previous search, required by LDAP
if (empty($this->lastCookie) && $this->lastCookie !== "0" && ($offset > 0)) {
// Get the cookie from the search for the previous search, required by LDAP
if (($this->lastCookie === '') && ($offset > 0)) {
// no cookie known from a potential previous search. We need
// to start from 0 to come to the desired page. cookie value
// of '0' is valid, because 389ds
@ -1980,15 +1979,15 @@ class Access extends LDAPUtility {
$this->abandonPagedSearch();
}
$pagedSearchOK = true;
$this->invokeLDAPMethod('controlPagedResult', $limit, false);
$this->invokeLDAPMethod('controlPagedResult', $limit, false, $this->lastCookie);
$this->logger->debug('Ready for a paged search', ['app' => 'user_ldap']);
/* ++ Fixing RHDS searches with pages with zero results ++
* We couldn't get paged searches working with our RHDS for login ($limit = 0),
* due to pages with zero results.
* So we added "&& !empty($this->lastCookie)" to this test to ignore pagination
* if we don't have a previous paged search.
*/
} elseif (!empty($this->lastCookie)) {
/* ++ Fixing RHDS searches with pages with zero results ++
* We couldn't get paged searches working with our RHDS for login ($limit = 0),
* due to pages with zero results.
* So we added "&& !empty($this->lastCookie)" to this test to ignore pagination
* if we don't have a previous paged search.
*/
} elseif ($this->lastCookie !== '') {
// a search without limit was requested. However, if we do use
// Paged Search once, we always must do it. This requires us to
// initialize it with the configured page size.
@ -1997,7 +1996,7 @@ class Access extends LDAPUtility {
// be returned.
$pageSize = (int)$this->connection->ldapPagingSize > 0 ? (int)$this->connection->ldapPagingSize : 500;
$pagedSearchOK = true;
$this->invokeLDAPMethod('controlPagedResult', $pageSize, false);
$this->invokeLDAPMethod('controlPagedResult', $pageSize, false, $this->lastCookie);
}
return $pagedSearchOK;

View file

@ -87,19 +87,23 @@ class LDAP implements ILDAPWrapper {
* {@inheritDoc}
*/
public function controlPagedResultResponse($link, $result, &$cookie): bool {
$this->preFunctionCall(
$this->pagedResultsAdapter->getResponseCallFunc(),
$this->pagedResultsAdapter->getResponseCallArgs([$link, $result, &$cookie])
);
$errorCode = 0;
$errorMessage = '';
$controls = [];
$matchedDn = null;
$referrals = [];
$success = $this->invokeLDAPMethod('parse_result', $link, $result,
$errorCode,
$matchedDn,
$errorMessage,
$referrals,
$controls);
$result = $this->pagedResultsAdapter->responseCall($link);
$cookie = $this->pagedResultsAdapter->getCookie($link);
$cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? '';
if ($this->isResultFalse($result)) {
$this->postFunctionCall();
}
// TODO do not ignore error code and message
return $result;
return $success;
}
/**

View file

@ -35,31 +35,7 @@ interface IAdapter {
* The adapter receives paged result parameters from the client. It may
* store the parameters for later use.
*/
public function setRequestParameters($link, int $pageSize, bool $isCritical): void;
/**
* The adapter shall report which PHP function will be called to process
* the paged results call
*
* It will used by the callee for diagnosis and error handling.
*/
public function getResponseCallFunc(): string;
/**
* The adapter shall report with arguments will be provided to the LDAP
* function it will call
*
* It will used by the callee for diagnosis and error handling.
*/
public function getResponseCallArgs(array $originalArgs): array;
/**
* the adapter should do its LDAP function call and return success state
*
* @param resource|\LDAP\Connection $link LDAP resource
* @return bool
*/
public function responseCall($link): bool;
public function setRequestParameters($link, int $pageSize, bool $isCritical, string $cookie = ''): void;
/**
* The adapter receives the parameters that were passed to a search
@ -80,12 +56,4 @@ interface IAdapter {
* ldap_search function.
*/
public function getSearchArgs($link): array;
/**
* Returns the current paged results cookie
*
* @param resource|\LDAP\Connection $link LDAP resource
* @return string
*/
public function getCookie($link): string;
}

View file

@ -39,55 +39,7 @@ class Php73 implements IAdapter {
/** @var array */
protected $linkData = [];
public function getResponseCallFunc(): string {
return 'ldap_parse_result';
}
public function responseCall($link): bool {
$linkId = $this->getLinkId($link);
return ldap_parse_result(...$this->linkData[$linkId]['responseArgs']);
}
public function getResponseCallArgs(array $originalArgs): array {
$link = array_shift($originalArgs);
$linkId = $this->getLinkId($link);
if (!isset($this->linkData[$linkId])) {
$this->linkData[$linkId] = [];
}
$this->linkData[$linkId]['responseErrorCode'] = 0;
$this->linkData[$linkId]['responseErrorMessage'] = '';
$this->linkData[$linkId]['serverControls'] = [];
$matchedDn = null;
$referrals = [];
$this->linkData[$linkId]['responseArgs'] = [
$link,
array_shift($originalArgs),
&$this->linkData[$linkId]['responseErrorCode'],
$matchedDn,
&$this->linkData[$linkId]['responseErrorMessage'],
$referrals,
&$this->linkData[$linkId]['serverControls']
];
return $this->linkData[$linkId]['responseArgs'];
}
public function getCookie($link): string {
$linkId = $this->getLinkId($link);
return $this->linkData[$linkId]['serverControls'][LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? '';
}
private function resetCookie(int $linkId): void {
if (isset($this->linkData[$linkId]['serverControls'][LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'])) {
$this->linkData[$linkId]['serverControls'][LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] = '';
}
}
public function setRequestParameters($link, int $pageSize, bool $isCritical): void {
public function setRequestParameters($link, int $pageSize, bool $isCritical, string $cookie = ''): void {
$linkId = $this->getLinkId($link);
if (!isset($this->linkData[$linkId])) {
$this->linkData[$linkId] = [];
@ -95,10 +47,7 @@ class Php73 implements IAdapter {
$this->linkData[$linkId]['requestArgs'] = [];
$this->linkData[$linkId]['requestArgs']['pageSize'] = $pageSize;
$this->linkData[$linkId]['requestArgs']['isCritical'] = $isCritical;
if ($pageSize === 0) {
$this->resetCookie($linkId);
}
$this->linkData[$linkId]['requestArgs']['cookie'] = $cookie;
}
public function setSearchArgs(
@ -132,8 +81,9 @@ class Php73 implements IAdapter {
'oid' => LDAP_CONTROL_PAGEDRESULTS,
'value' => [
'size' => $this->linkData[$linkId]['requestArgs']['pageSize'],
'cookie' => $this->linkData[$linkId]['serverControls'][LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? '',
]
'cookie' => $this->linkData[$linkId]['requestArgs']['cookie'],
],
'iscritical' => $this->linkData[$linkId]['requestArgs']['isCritical'],
]];
$this->linkData[$linkId][$methodKey][] = -1; // timelimit