diff --git a/src/Iterators/LDAPIterator.php b/src/Iterators/LDAPIterator.php index f9a8ea8..5de4163 100644 --- a/src/Iterators/LDAPIterator.php +++ b/src/Iterators/LDAPIterator.php @@ -114,14 +114,29 @@ private function fetchPagedResult(): bool $baseDn = $ldap->getBaseDn(); } - ldap_control_paged_result($resource, $this->getPageSize(), true, $this->cookie); - if ($this->getReturnAttributes() !== null) { - $resultResource = ldap_search($resource, $baseDn ?? '', $this->getFilter() ?? '', $this->getReturnAttributes() ?? []); + if (version_compare(PHP_VERSION, '8.0.0') < 0) { + ldap_control_paged_result($resource, $this->getPageSize(), true, $this->cookie); + if ($this->getReturnAttributes() !== null) { + $resultResource = ldap_search($resource, $baseDn ?? '', $this->getFilter() ?? '', $this->getReturnAttributes() ?? []); + } else { + $resultResource = ldap_search($resource, $baseDn ?? '', $this->getFilter() ?? ''); + } + if (! is_resource($resultResource)) { + throw new \Exception('ldap_search returned a non-resource type value' . ldap_error($resource)); + } } else { - $resultResource = ldap_search($resource, $baseDn ?? '', $this->getFilter() ?? ''); - } - if (! is_resource($resultResource)) { - throw new \Exception('ldap_search returned a non-resource type value' . ldap_error($resource)); + if ($this->getReturnAttributes() !== null) { + $resultResource = ldap_search($resource, $baseDn ?? '', $this->getFilter() ?? '', $this->getReturnAttributes() ?? [], + 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => $this->getPageSize(), 'cookie' => $this->cookie]]] + ); + } else { + $resultResource = ldap_search($resource, $baseDn ?? '', $this->getFilter() ?? '', [], + 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => $this->getPageSize(), 'cookie' => $this->cookie]]] + ); + } + $response = ldap_parse_result($resource, $resultResource, $errcode , $matcheddn , $errmsg , $referrals, $controls); } $entries = ldap_get_entries($resource, $resultResource); @@ -130,9 +145,18 @@ private function fetchPagedResult(): bool } $entries = $this->getConvertedEntries($entries); - ErrorHandler::start(); - $response = ldap_control_paged_result_response($resource, $resultResource, $this->cookie); - ErrorHandler::stop(); + if (version_compare(PHP_VERSION, '8.0.0') < 0) { + ErrorHandler::start(); + $response = ldap_control_paged_result_response($resource, $resultResource, $this->cookie); + ErrorHandler::stop(); + } else { + if (isset($controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'])) { + // You need to pass the cookie from the last call to the next one + $this->cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']; + } else { + $this->cookie = ''; + } + } if ($response !== true) { throw new LdapException($ldap, 'Paged result was empty'); diff --git a/src/Model/LDAPGateway.php b/src/Model/LDAPGateway.php index 6fd7b39..620c3cf 100644 --- a/src/Model/LDAPGateway.php +++ b/src/Model/LDAPGateway.php @@ -34,6 +34,14 @@ class LDAPGateway */ private static $options = []; + /** + * If configured, only user objects matching this LDAP filter will be considered to this service instead of the default. + * @var string + * + * @config + */ + private static $user_filter = []; + /** * @var Laminas\Ldap\Ldap */ @@ -62,8 +70,10 @@ protected function searchWithIterator($filter, $baseDn = null, $attributes = []) $records = new LDAPIterator($this->getLdap(), $filter, $baseDn, $attributes, $pageSize); $results = $this->processSearchResults($records); - // Reset the LDAP pagination control back to the original, otherwise all further LDAP read queries fail - ldap_control_paged_result($this->getLdap()->getResource(), 1000); + if (version_compare(PHP_VERSION, '8.0.0') < 0) { + // Reset the LDAP pagination control back to the original, otherwise all further LDAP read queries fail + ldap_control_paged_result($this->getLdap()->getResource(), 1000); + } return $results; } @@ -254,7 +264,7 @@ public function getGroupByDN($dn, $baseDn = null, $scope = Ldap::SEARCH_SCOPE_SU */ public function getUsers($baseDn = null, $scope = Ldap::SEARCH_SCOPE_SUB, $attributes = [], $sort = '') { - $filter = '(&(objectClass=user)(!(objectClass=computer))(!(samaccountname=Guest))(!(samaccountname=Administrator))(!(samaccountname=krbtgt)))'; + $filter = $this->config()->user_filter ?: '(&(objectClass=user)(!(objectClass=computer))(!(samaccountname=Guest))(!(samaccountname=Administrator))(!(samaccountname=krbtgt)))'; $this->extend('updateUsersFilter', $filter); @@ -277,7 +287,7 @@ public function getUsers($baseDn = null, $scope = Ldap::SEARCH_SCOPE_SUB, $attri */ public function getUsersWithIterator($baseDn = null, $attributes = []) { - $filter = '(&(objectClass=user)(!(objectClass=computer))(!(samaccountname=Guest))(!(samaccountname=Administrator))(!(samaccountname=krbtgt)))'; + $filter = $this->config()->user_filter ?: '(&(objectClass=user)(!(objectClass=computer))(!(samaccountname=Guest))(!(samaccountname=Administrator))(!(samaccountname=krbtgt)))'; $this->extend('updateUsersWithIteratorFilter', $filter); diff --git a/src/Services/LDAPService.php b/src/Services/LDAPService.php index a3bc970..654d74f 100644 --- a/src/Services/LDAPService.php +++ b/src/Services/LDAPService.php @@ -68,6 +68,14 @@ class LDAPService implements Flushable */ private static $groups_search_locations = []; + /** + * If configured, only group objects within these locations will be searched for nexted groups to this service. + * @var array + * + * @config + */ + private static $nested_groups_search_locations = []; + /** * Location to create new users in (distinguished name). * @var string @@ -301,7 +309,7 @@ public function getNestedGroups($dn, $attributes = []) return LDAPService::$_cache_nested_groups[$dn]; } - $searchLocations = $this->config()->groups_search_locations ?: [null]; + $searchLocations = $this->config()->nested_groups_search_locations ?: $this->config()->groups_search_locations ?: [null]; $results = []; foreach ($searchLocations as $searchLocation) { $records = $this->getGateway()->getNestedGroups($dn, $searchLocation, Ldap::SEARCH_SCOPE_SUB, $attributes);