Browse Source
use serverControls directly with LDAP calls, fixes 19127
use serverControls directly with LDAP calls, fixes 19127
- adapters for PHP API version to Support PHP < 7.3 - switch to pass only one base per search - cookie logic is moved from Access to API adapters Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>pull/20037/head
No known key found for this signature in database
GPG Key ID: 7424F1874854DF23
16 changed files with 749 additions and 227 deletions
-
47.drone.yml
-
4apps/user_ldap/composer/composer/autoload_classmap.php
-
4apps/user_ldap/composer/composer/autoload_static.php
-
326apps/user_ldap/lib/Access.php
-
2apps/user_ldap/lib/Command/CheckUser.php
-
2apps/user_ldap/lib/ILDAPWrapper.php
-
65apps/user_ldap/lib/LDAP.php
-
130apps/user_ldap/lib/PagedResults/IAdapter.php
-
126apps/user_ldap/lib/PagedResults/Php54.php
-
162apps/user_ldap/lib/PagedResults/Php73.php
-
37apps/user_ldap/lib/PagedResults/TLinkId.php
-
4apps/user_ldap/lib/User/User.php
-
34apps/user_ldap/tests/AccessTest.php
-
3apps/user_ldap/tests/LDAPTest.php
-
8apps/user_ldap/tests/User/UserTest.php
-
22build/integration/ldap_features/openldap-uid-username.feature
@ -0,0 +1,130 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\User_LDAP\PagedResults; |
|||
|
|||
interface IAdapter { |
|||
|
|||
/** |
|||
* Methods for initiating Paged Results Control |
|||
*/ |
|||
|
|||
/** |
|||
* 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 is asked for an function that is being explicitly called to |
|||
* send the control parameters to LDAP. If not function has to be called, |
|||
* null shall be returned. |
|||
* |
|||
* It will used by the callee for diagnosis and error handling. |
|||
*/ |
|||
public function getRequestCallFunc(): ?string; |
|||
|
|||
/** |
|||
* The adapter is asked to provide the arguments it would pass to the |
|||
* function returned by getRequestCallFunc(). If none shall be called, an |
|||
* empty array should be returned. |
|||
* |
|||
* It will used by the callee for diagnosis and error handling. |
|||
*/ |
|||
public function getRequestCallArgs($link): array; |
|||
|
|||
/** |
|||
* The adapter is asked to do the necessary calls to LDAP, if |
|||
* getRequestCallFunc returned a function. If none, it will not be called |
|||
* so the return value is best set to false. Otherwise it shall respond |
|||
* whether setting the controls was successful. |
|||
*/ |
|||
public function requestCall($link): bool; |
|||
|
|||
/** |
|||
* 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 it's LDAP function call and return success state |
|||
* |
|||
* @param resource $link LDAP resource |
|||
* @return bool |
|||
*/ |
|||
public function responseCall($link): bool; |
|||
|
|||
/** |
|||
* The adapter receives the parameters that were passed to a search |
|||
* operation. Typically it wants to save the them for the call proper later |
|||
* on. |
|||
*/ |
|||
public function setSearchArgs( |
|||
$link, |
|||
string $baseDN, |
|||
string $filter, |
|||
array $attr, |
|||
int $attrsOnly, |
|||
int $limit |
|||
): void; |
|||
|
|||
/** |
|||
* The adapter shall report which arguments shall be passed to the |
|||
* ldap_search function. |
|||
*/ |
|||
public function getSearchArgs($link): array; |
|||
|
|||
/** |
|||
* The adapter receives the parameters that were passed to a read |
|||
* operation. Typically it wants to save the them for the call proper later |
|||
* on. |
|||
*/ |
|||
public function setReadArgs($link, string $baseDN, string $filter, array $attr): void; |
|||
|
|||
/** |
|||
* The adapter shall report which arguments shall be passed to the |
|||
* ldap_read function. |
|||
*/ |
|||
public function getReadArgs($link): array; |
|||
|
|||
/** |
|||
* Returns the current paged results cookie |
|||
* |
|||
* @param resource $link LDAP resource |
|||
* @return string |
|||
*/ |
|||
public function getCookie($link): string; |
|||
|
|||
} |
@ -0,0 +1,126 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\User_LDAP\PagedResults; |
|||
|
|||
/** |
|||
* Class Php54 |
|||
* |
|||
* implements paged results support with PHP APIs available from PHP 5.4 |
|||
* |
|||
* @package OCA\User_LDAP\PagedResults |
|||
*/ |
|||
class Php54 implements IAdapter { |
|||
use TLinkId; |
|||
|
|||
/** @var array */ |
|||
protected $linkData = []; |
|||
|
|||
public function getResponseCallFunc(): string { |
|||
return 'ldap_control_paged_result_response'; |
|||
} |
|||
|
|||
public function responseCall($link): bool { |
|||
$linkId = $this->getLinkId($link); |
|||
return ldap_control_paged_result_response(...$this->linkData[$linkId]['responseArgs']); |
|||
} |
|||
|
|||
public function getResponseCallArgs(array $originalArgs): array { |
|||
$linkId = $this->getLinkId($originalArgs[0]); |
|||
if(!isset($this->linkData[$linkId])) { |
|||
throw new \LogicException('There should be a request before the response'); |
|||
} |
|||
$this->linkData[$linkId]['responseArgs'] = &$originalArgs; |
|||
$this->linkData[$linkId]['cookie'] = &$originalArgs[2]; |
|||
return $originalArgs; |
|||
} |
|||
|
|||
public function getCookie($link): string { |
|||
$linkId = $this->getLinkId($link); |
|||
return $this->linkData[$linkId]['cookie']; |
|||
} |
|||
|
|||
public function getRequestCallFunc(): ?string { |
|||
return 'ldap_control_paged_result'; |
|||
} |
|||
|
|||
public function setRequestParameters($link, int $pageSize, bool $isCritical): void { |
|||
$linkId = $this->getLinkId($link); |
|||
|
|||
if($pageSize === 0 || !isset($this->linkData[$linkId]['cookie'])) { |
|||
// abandons a previous paged search
|
|||
$this->linkData[$linkId]['cookie'] = ''; |
|||
} |
|||
|
|||
$this->linkData[$linkId]['requestArgs'] = [ |
|||
$link, |
|||
$pageSize, |
|||
$isCritical, |
|||
&$this->linkData[$linkId]['cookie'] |
|||
]; |
|||
} |
|||
|
|||
public function getRequestCallArgs($link): array { |
|||
$linkId = $this->getLinkId($link); |
|||
return $this->linkData[$linkId]['requestArgs']; |
|||
} |
|||
|
|||
public function requestCall($link): bool { |
|||
$linkId = $this->getLinkId($link); |
|||
return ldap_control_paged_result(...$this->linkData[$linkId]['requestArgs']); |
|||
} |
|||
|
|||
public function setSearchArgs( |
|||
$link, |
|||
string $baseDN, |
|||
string $filter, |
|||
array $attr, |
|||
int $attrsOnly, |
|||
int $limit |
|||
): void { |
|||
$linkId = $this->getLinkId($link); |
|||
if(!isset($this->linkData[$linkId])) { |
|||
$this->linkData[$linkId] = []; |
|||
} |
|||
$this->linkData[$linkId]['searchArgs'] = func_get_args(); |
|||
} |
|||
|
|||
public function getSearchArgs($link): array { |
|||
$linkId = $this->getLinkId($link); |
|||
return $this->linkData[$linkId]['searchArgs']; |
|||
} |
|||
|
|||
public function setReadArgs($link, string $baseDN, string $filter, array $attr): void { |
|||
$linkId = $this->getLinkId($link); |
|||
if(!isset($this->linkData[$linkId])) { |
|||
$this->linkData[$linkId] = []; |
|||
} |
|||
$this->linkData[$linkId]['readArgs'] = func_get_args(); |
|||
} |
|||
|
|||
public function getReadArgs($link): array { |
|||
$linkId = $this->getLinkId($link); |
|||
return $this->linkData[$linkId]['readArgs']; |
|||
} |
|||
} |
@ -0,0 +1,162 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\User_LDAP\PagedResults; |
|||
|
|||
/** |
|||
* Class Php73 |
|||
* |
|||
* implements paged results support with PHP APIs available from PHP 7.3 |
|||
* |
|||
* @package OCA\User_LDAP\PagedResults |
|||
*/ |
|||
class Php73 implements IAdapter { |
|||
use TLinkId; |
|||
|
|||
/** @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'] ?? ''; |
|||
} |
|||
|
|||
public function getRequestCallFunc(): ?string { |
|||
return null; |
|||
} |
|||
|
|||
public function setRequestParameters($link, int $pageSize, bool $isCritical): void { |
|||
$linkId = $this->getLinkId($link); |
|||
if(!isset($this->linkData[$linkId])) { |
|||
$this->linkData[$linkId] = []; |
|||
} |
|||
$this->linkData[$linkId]['requestArgs'] = []; |
|||
$this->linkData[$linkId]['requestArgs']['pageSize'] = $pageSize; |
|||
$this->linkData[$linkId]['requestArgs']['isCritical'] = $isCritical; |
|||
} |
|||
|
|||
public function getRequestCallArgs($link): array { |
|||
// no separate call
|
|||
return []; |
|||
} |
|||
|
|||
public function requestCall($link): bool { |
|||
// no separate call
|
|||
return false; |
|||
} |
|||
|
|||
public function setSearchArgs( |
|||
$link, |
|||
string $baseDN, |
|||
string $filter, |
|||
array $attr, |
|||
int $attrsOnly, |
|||
int $limit |
|||
): void { |
|||
$linkId = $this->getLinkId($link); |
|||
if(!isset($this->linkData[$linkId])) { |
|||
$this->linkData[$linkId] = []; |
|||
} |
|||
|
|||
$this->linkData[$linkId]['searchArgs'] = func_get_args(); |
|||
$this->preparePagesResultsArgs($linkId, 'searchArgs'); |
|||
} |
|||
|
|||
public function getSearchArgs($link): array { |
|||
$linkId = $this->getLinkId($link); |
|||
return $this->linkData[$linkId]['searchArgs']; |
|||
} |
|||
|
|||
public function setReadArgs($link, string $baseDN, string $filter, array $attr): void { |
|||
$linkId = $this->getLinkId($link); |
|||
if(!isset($this->linkData[$linkId])) { |
|||
$this->linkData[$linkId] = []; |
|||
} |
|||
|
|||
$this->linkData[$linkId]['readArgs'] = func_get_args(); |
|||
$this->linkData[$linkId]['readArgs'][] = 0; // $attrsonly default
|
|||
$this->linkData[$linkId]['readArgs'][] = -1; // $sizelimit default
|
|||
$this->preparePagesResultsArgs($linkId, 'readArgs'); |
|||
} |
|||
|
|||
public function getReadArgs($link): array { |
|||
$linkId = $this->getLinkId($link); |
|||
return $this->linkData[$linkId]['readArgs']; |
|||
} |
|||
|
|||
protected function preparePagesResultsArgs(int $linkId, string $methodKey): void { |
|||
if(!isset($this->linkData[$linkId]['requestArgs'])) { |
|||
return; |
|||
} |
|||
|
|||
$serverControls = [[ |
|||
'oid' => LDAP_CONTROL_PAGEDRESULTS, |
|||
'value' => [ |
|||
'size' => $this->linkData[$linkId]['requestArgs']['pageSize'], |
|||
'cookie' => $this->linkData[$linkId]['serverControls'][LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? '' |
|||
] |
|||
]]; |
|||
|
|||
$this->linkData[$linkId][$methodKey][] = -1; // timelimit
|
|||
$this->linkData[$linkId][$methodKey][] = LDAP_DEREF_NEVER; |
|||
$this->linkData[$linkId][$methodKey][] = $serverControls; |
|||
} |
|||
} |
@ -0,0 +1,37 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\User_LDAP\PagedResults; |
|||
|
|||
|
|||
trait TLinkId { |
|||
public function getLinkId($link) { |
|||
if(is_resource($link)) { |
|||
return (int)$link; |
|||
} else if(is_array($link) && isset($link[0]) && is_resource($link[0])) { |
|||
return (int)$link[0]; |
|||
} |
|||
throw new \RuntimeException('No resource provided'); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue