diff --git a/lib/SimpleSAML/Auth/LDAP.php b/lib/SimpleSAML/Auth/LDAP.php index 2fb262f3b3270dcb54cc050889852c5a002ac98e..6f36104d8efb48635b7812c6eeb702fde3389aed 100644 --- a/lib/SimpleSAML/Auth/LDAP.php +++ b/lib/SimpleSAML/Auth/LDAP.php @@ -56,12 +56,12 @@ class SimpleSAML_Auth_LDAP public function __construct($hostname, $enable_tls = true, $debug = false, $timeout = 0, $port = 389, $referrals = true) { // Debug - SimpleSAML\Logger::debug('Library - LDAP __construct(): Setup LDAP with ' . - 'host=\'' . $hostname . - '\', tls=' . var_export($enable_tls, true) . - ', debug=' . var_export($debug, true) . - ', timeout=' . var_export($timeout, true) . - ', referrals=' . var_export($referrals, true)); + SimpleSAML\Logger::debug('Library - LDAP __construct(): Setup LDAP with '. + 'host=\''.$hostname. + '\', tls='.var_export($enable_tls, true). + ', debug='.var_export($debug, true). + ', timeout='.var_export($timeout, true). + ', referrals='.var_export($referrals, true)); /* * Set debug level before calling connect. Note that this passes @@ -79,7 +79,7 @@ class SimpleSAML_Auth_LDAP */ $this->ldap = @ldap_connect($hostname, $port); if ($this->ldap === false) { - throw $this->makeException('Library - LDAP __construct(): Unable to connect to \'' . $hostname . '\'', ERR_INTERNAL); + throw $this->makeException('Library - LDAP __construct(): Unable to connect to \''.$hostname.'\'', ERR_INTERNAL); } // Enable LDAP protocol version 3 @@ -97,10 +97,10 @@ class SimpleSAML_Auth_LDAP $this->timeout = $timeout; if ($timeout > 0) { if (!@ldap_set_option($this->ldap, LDAP_OPT_NETWORK_TIMEOUT, $timeout)) { - SimpleSAML\Logger::warning('Library - LDAP __construct(): Unable to set timeouts (LDAP_OPT_NETWORK_TIMEOUT) to ' . $timeout); + SimpleSAML\Logger::warning('Library - LDAP __construct(): Unable to set timeouts (LDAP_OPT_NETWORK_TIMEOUT) to '.$timeout); } if (!@ldap_set_option($this->ldap, LDAP_OPT_TIMELIMIT, $timeout)) { - SimpleSAML\Logger::warning('Library - LDAP __construct(): Unable to set timeouts (LDAP_OPT_TIMELIMIT) to ' . $timeout); + SimpleSAML\Logger::warning('Library - LDAP __construct(): Unable to set timeouts (LDAP_OPT_TIMELIMIT) to '.$timeout); } } @@ -136,7 +136,7 @@ class SimpleSAML_Auth_LDAP if ($type) { if ($errNo !== 0) { // Only log real LDAP errors; not success - SimpleSAML\Logger::error($description . '; cause: \'' . ldap_error($this->ldap) . '\' (0x' . dechex($errNo) . ')'); + SimpleSAML\Logger::error($description.'; cause: \''.ldap_error($this->ldap).'\' (0x'.dechex($errNo).')'); } else { SimpleSAML\Logger::error($description); } @@ -155,9 +155,9 @@ class SimpleSAML_Auth_LDAP } } else { if ($errNo !== 0) { - $description .= '; cause: \'' . ldap_error($this->ldap) . '\' (0x' . dechex($errNo) . ')'; + $description .= '; cause: \''.ldap_error($this->ldap).'\' (0x'.dechex($errNo).')'; if (@ldap_get_option($this->ldap, LDAP_OPT_DIAGNOSTIC_MESSAGE, $extendedError) && !empty($extendedError)) { - $description .= '; additional: \'' . $extendedError . '\''; + $description .= '; additional: \''.$extendedError.'\''; } } switch ($errNo) { @@ -187,6 +187,10 @@ class SimpleSAML_Auth_LDAP * The attribute name(s) to search for. * @param string $value * The attribute value to search for. + * Additional search filter + * @param string|null $searchFilter + * The scope of the search + * @param string $scope * @return string * The DN of the resulting found element. * @throws SimpleSAML_Error_Exception if: @@ -201,16 +205,16 @@ class SimpleSAML_Auth_LDAP * @throws SimpleSAML_Error_UserNotFound if: * - Zero entries were found */ - private function search($base, $attribute, $value, $searchFilter = null) + private function search($base, $attribute, $value, $searchFilter = null, $scope = "subtree") { // Create the search filter $attribute = self::escape_filter_value($attribute, false); $value = self::escape_filter_value($value, true); $filter = ''; foreach ($attribute as $attr) { - $filter .= '(' . $attr . '=' . $value. ')'; + $filter .= '('.$attr.'='.$value.')'; } - $filter = '(|' . $filter . ')'; + $filter = '(|'.$filter.')'; // Append LDAP filters if defined if ($searchFilter != null) { @@ -218,10 +222,17 @@ class SimpleSAML_Auth_LDAP } // Search using generated filter - SimpleSAML\Logger::debug('Library - LDAP search(): Searching base \'' . $base . '\' for \'' . $filter . '\''); - $result = @ldap_search($this->ldap, $base, $filter, array(), 0, 0, $this->timeout, LDAP_DEREF_NEVER); + SimpleSAML\Logger::debug('Library - LDAP search(): Searching base ('.$scope.') \''.$base.'\' for \''.$filter.'\''); + if ($scope === 'base') { + $result = @ldap_read($this->ldap, $base, $filter, array(), 0, 0, $this->timeout, LDAP_DEREF_NEVER); + } else if ($scope === 'onelevel') { + $result = @ldap_list($this->ldap, $base, $filter, array(), 0, 0, $this->timeout, LDAP_DEREF_NEVER); + } else { + $result = @ldap_search($this->ldap, $base, $filter, array(), 0, 0, $this->timeout, LDAP_DEREF_NEVER); + } + if ($result === false) { - throw $this->makeException('Library - LDAP search(): Failed search on base \'' . $base . '\' for \'' . $filter . '\''); + throw $this->makeException('Library - LDAP search(): Failed search on base \''.$base.'\' for \''.$filter.'\''); } // Sanity checks on search results @@ -230,21 +241,21 @@ class SimpleSAML_Auth_LDAP throw $this->makeException('Library - LDAP search(): Failed to get number of entries returned'); } elseif ($count > 1) { // More than one entry is found. External error - throw $this->makeException('Library - LDAP search(): Found ' . $count . ' entries searching base \'' . $base . '\' for \'' . $filter . '\'', ERR_AS_DATA_INCONSIST); + throw $this->makeException('Library - LDAP search(): Found '.$count.' entries searching base \''.$base.'\' for \''.$filter.'\'', ERR_AS_DATA_INCONSIST); } elseif ($count === 0) { // No entry is fond => wrong username is given (or not registered in the catalogue). User error - throw $this->makeException('Library - LDAP search(): Found no entries searching base \'' . $base . '\' for \'' . $filter . '\'', ERR_NO_USER); + throw $this->makeException('Library - LDAP search(): Found no entries searching base \''.$base.'\' for \''.$filter.'\'', ERR_NO_USER); } // Resolve the DN from the search result $entry = @ldap_first_entry($this->ldap, $result); if ($entry === false) { - throw $this->makeException('Library - LDAP search(): Unable to retrieve result after searching base \'' . $base . '\' for \'' . $filter . '\''); + throw $this->makeException('Library - LDAP search(): Unable to retrieve result after searching base \''.$base.'\' for \''.$filter.'\''); } $dn = @ldap_get_dn($this->ldap, $entry); if ($dn === false) { - throw $this->makeException('Library - LDAP search(): Unable to get DN after searching base \'' . $base . '\' for \'' . $filter . '\''); + throw $this->makeException('Library - LDAP search(): Unable to get DN after searching base \''.$base.'\' for \''.$filter.'\''); } return $dn; } @@ -264,6 +275,8 @@ class SimpleSAML_Auth_LDAP * Defaults to FALSE. * @param string|null $searchFilter * Additional searchFilter to be added to the (attribute=value) filter + * @param string $scope + * The scope of the search * @return string * The DN of the matching element, if found. If no element was found and * $allowZeroHits is set to FALSE, an exception will be thrown; otherwise @@ -275,14 +288,14 @@ class SimpleSAML_Auth_LDAP * - $allowZeroHits is FALSE and no result is found * */ - public function searchfordn($base, $attribute, $value, $allowZeroHits = false, $searchFilter = null) + public function searchfordn($base, $attribute, $value, $allowZeroHits = false, $searchFilter = null, $scope = 'subtree') { // Traverse all search bases, returning DN if found $bases = SimpleSAML\Utils\Arrays::arrayize($base); foreach ($bases as $current) { try { // Single base search - $result = $this->search($current, $attribute, $value, $searchFilter); + $result = $this->search($current, $attribute, $value, $searchFilter, $scope); // We don't hawe to look any futher if user is found if (!empty($result)) { @@ -300,8 +313,8 @@ class SimpleSAML_Auth_LDAP return null; } else { // Zero hits not allowed - throw $this->makeException('Library - LDAP searchfordn(): LDAP search returned zero entries for filter \'(' . - join(' | ', $attribute) . ' = ' . $value . ')\' on base(s) \'(' . join(' & ', $bases) . ')\'', 2); + throw $this->makeException('Library - LDAP searchfordn(): LDAP search returned zero entries for filter \'('. + join(' | ', $attribute).' = '.$value.')\' on base(s) \'('.join(' & ', $bases).')\'', 2); } } @@ -316,9 +329,10 @@ class SimpleSAML_Auth_LDAP * @param string|array $attributes Array of attributes requested from LDAP * @param bool $and If multiple filters defined, then either bind them with & or | * @param bool $escape Weather to escape the filter values or not + * @param string $scope The scope of the search * @return array */ - public function searchformultiple($bases, $filters, $attributes = array(), $and = true, $escape = true) + public function searchformultiple($bases, $filters, $attributes = array(), $and = true, $escape = true, $scope = 'subtree') { // Escape the filter values, if requested if ($escape) { @@ -332,7 +346,7 @@ class SimpleSAML_Auth_LDAP $filter .= "($attribute=$value)"; } if (count($filters) > 1) { - $filter = ($and ? '(&' : '(|') . $filter . ')'; + $filter = ($and ? '(&' : '(|').$filter.')'; } } elseif (is_string($filters)) { $filter = $filters; @@ -352,7 +366,14 @@ class SimpleSAML_Auth_LDAP // Search each base until result is found $result = false; foreach ($bases as $base) { - $result = @ldap_search($this->ldap, $base, $filter, $attributes, 0, 0, $this->timeout); + if ($scope === 'base') { + $result = @ldap_read($this->ldap, $base, $filter, $attributes, 0, 0, $this->timeout); + } else if ($scope === 'onelevel') { + $result = @ldap_list($this->ldap, $base, $filter, $attributes, 0, 0, $this->timeout); + } else { + $result = @ldap_search($this->ldap, $base, $filter, $attributes, 0, 0, $this->timeout); + } + if ($result !== false && @ldap_count_entries($this->ldap, $result) > 0) { break; } @@ -361,14 +382,14 @@ class SimpleSAML_Auth_LDAP // Verify that a result was found in one of the bases if ($result === false) { throw $this->makeException( - 'ldap:LdapConnection->search_manual : Failed to search LDAP using base(s) [' . - implode('; ', $bases) . '] with filter [' . $filter . ']. LDAP error [' . - ldap_error($this->ldap) . ']' + 'ldap:LdapConnection->search_manual : Failed to search LDAP using base(s) ['. + implode('; ', $bases).'] with filter ['.$filter.']. LDAP error ['. + ldap_error($this->ldap).']' ); } elseif (@ldap_count_entries($this->ldap, $result) < 1) { throw $this->makeException( - 'ldap:LdapConnection->search_manual : No entries found in LDAP using base(s) [' . - implode('; ', $bases) . '] with filter [' . $filter . ']', + 'ldap:LdapConnection->search_manual : No entries found in LDAP using base(s) ['. + implode('; ', $bases).'] with filter ['.$filter.']', ERR_NO_USER ); } @@ -451,7 +472,7 @@ class SimpleSAML_Auth_LDAP if ($error === true) { // Good $this->authz_id = $authz_id; - SimpleSAML\Logger::debug('Library - LDAP bind(): Bind successful with DN \'' . $dn . '\''); + SimpleSAML\Logger::debug('Library - LDAP bind(): Bind successful with DN \''.$dn.'\''); return true; } @@ -474,7 +495,7 @@ class SimpleSAML_Auth_LDAP } // Bad - throw $this->makeException('Library - LDAP bind(): Bind failed with DN \'' . $dn . '\''); + throw $this->makeException('Library - LDAP bind(): Bind failed with DN \''.$dn.'\''); } @@ -491,16 +512,16 @@ class SimpleSAML_Auth_LDAP // Attempt to set the LDAP option if (!@ldap_set_option($this->ldap, $option, $value)) { throw $this->makeException( - 'ldap:LdapConnection->setOption : Failed to set LDAP option [' . - $option . '] with the value [' . $value . '] error: ' . ldap_error($this->ldap), + 'ldap:LdapConnection->setOption : Failed to set LDAP option ['. + $option.'] with the value ['.$value.'] error: '.ldap_error($this->ldap), ERR_INTERNAL ); } // Log debug message SimpleSAML\Logger::debug( - 'ldap:LdapConnection->setOption : Set the LDAP option [' . - $option . '] with the value [' . $value . ']' + 'ldap:LdapConnection->setOption : Set the LDAP option ['. + $option.'] with the value ['.$value.']' ); } @@ -526,31 +547,31 @@ class SimpleSAML_Auth_LDAP // Preparations, including a pretty debug message... $description = 'all attributes'; if (is_array($attributes)) { - $description = '\'' . join(',', $attributes) . '\''; + $description = '\''.join(',', $attributes).'\''; } else { // Get all attributes... // TODO: Verify that this originally was the intended behaviour. Could $attributes be a string? $attributes = array(); } - SimpleSAML\Logger::debug('Library - LDAP getAttributes(): Getting ' . $description . ' from DN \'' . $dn . '\''); + SimpleSAML\Logger::debug('Library - LDAP getAttributes(): Getting '.$description.' from DN \''.$dn.'\''); // Attempt to get attributes // TODO: Should aliases be dereferenced? $result = @ldap_read($this->ldap, $dn, 'objectClass=*', $attributes, 0, 0, $this->timeout); if ($result === false) { - throw $this->makeException('Library - LDAP getAttributes(): Failed to get attributes from DN \'' . $dn . '\''); + throw $this->makeException('Library - LDAP getAttributes(): Failed to get attributes from DN \''.$dn.'\''); } $entry = @ldap_first_entry($this->ldap, $result); if ($entry === false) { - throw $this->makeException('Library - LDAP getAttributes(): Could not get first entry from DN \'' . $dn . '\''); + throw $this->makeException('Library - LDAP getAttributes(): Could not get first entry from DN \''.$dn.'\''); } - $attributes = @ldap_get_attributes($this->ldap, $entry); // Recycling $attributes... Possibly bad practice. + $attributes = @ldap_get_attributes($this->ldap, $entry); // Recycling $attributes... Possibly bad practice. if ($attributes === false) { - throw $this->makeException('Library - LDAP getAttributes(): Could not get attributes of first entry from DN \'' . $dn . '\''); + throw $this->makeException('Library - LDAP getAttributes(): Could not get attributes of first entry from DN \''.$dn.'\''); } // Parsing each found attribute into our result set - $result = array(); // Recycling $result... Possibly bad practice. + $result = array(); // Recycling $result... Possibly bad practice. for ($i = 0; $i < $attributes['count']; $i++) { // Ignore attributes that exceed the maximum allowed size $name = $attributes[$i]; @@ -563,8 +584,8 @@ class SimpleSAML_Auth_LDAP if (!empty($maxsize) && strlen($value) >= $maxsize) { // Ignoring and warning - SimpleSAML\Logger::warning('Library - LDAP getAttributes(): Attribute \'' . - $name . '\' exceeded maximum allowed size by ' + ($maxsize - strlen($value))); + SimpleSAML\Logger::warning('Library - LDAP getAttributes(): Attribute \''. + $name.'\' exceeded maximum allowed size by ' +($maxsize - strlen($value))); continue; } @@ -581,7 +602,7 @@ class SimpleSAML_Auth_LDAP } // We're done - SimpleSAML\Logger::debug('Library - LDAP getAttributes(): Found attributes \'(' . join(',', array_keys($result)) . ')\''); + SimpleSAML\Logger::debug('Library - LDAP getAttributes(): Found attributes \'('.join(',', array_keys($result)).')\''); return $result; } @@ -616,7 +637,7 @@ class SimpleSAML_Auth_LDAP // escape characters with a special meaning, also in the password $password = addcslashes($password, ',+"\\<>;*'); if (!$this->bind($dn, $password)) { - SimpleSAML\Logger::info('Library - LDAP validate(): Failed to authenticate \''. $username . '\' using DN \'' . $dn . '\''); + SimpleSAML\Logger::info('Library - LDAP validate(): Failed to authenticate \''.$username.'\' using DN \''.$dn.'\''); return false; } } @@ -658,7 +679,7 @@ class SimpleSAML_Auth_LDAP $val = self::asc2hex32($val); if (null === $val) { - $val = '\0'; // apply escaped "null" if string is empty + $val = '\0'; // apply escaped "null" if string is empty } $values[$key] = $val; diff --git a/modules/ldap/docs/ldap.md b/modules/ldap/docs/ldap.md index fae1ca1c6ae30d51f946d48a3a8ba4088b38c510..1bad69582b69d30162c4b1b1a7aff9bba7a74919 100644 --- a/modules/ldap/docs/ldap.md +++ b/modules/ldap/docs/ldap.md @@ -63,6 +63,12 @@ authentication source: */ 'search.base' => 'ou=people,dc=example,dc=org', + /* + * The scope of the search. Valid values are 'subtree' and 'onelevel' and 'base', + * first one being the default if no value is set. + */ + 'search.scope' => 'subtree', + /* * The attribute(s) the username should match against. * @@ -94,7 +100,7 @@ You also need to update the `hostname` and `dnpattern` options. The `hostname` should be the hostname of your LDAP server, and the `dnpattern` should be a pattern which can be used to generate the `dn` of a user with a given username. - +- All other options have default values, and are not required. ### Searching for a user ### diff --git a/modules/ldap/lib/Auth/Process/BaseFilter.php b/modules/ldap/lib/Auth/Process/BaseFilter.php index c1da79255aebfd83d0e58a0b047b9013839902e1..d7116a2d835ec3b6c101b2f4d882123631809093 100644 --- a/modules/ldap/lib/Auth/Process/BaseFilter.php +++ b/modules/ldap/lib/Auth/Process/BaseFilter.php @@ -99,11 +99,11 @@ abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_Proce // This way if the class is extended the proper name is used $classname = get_class($this); $classname = explode('_', $classname); - $this->title = 'ldap:' . end($classname) . ' : '; + $this->title = 'ldap:'.end($classname).' : '; // Log the construction SimpleSAML\Logger::debug( - $this->title . 'Creating and configuring the filter.' + $this->title.'Creating and configuring the filter.' ); // If an authsource was defined (an not empty string)... @@ -111,8 +111,8 @@ abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_Proce // Log the authsource request SimpleSAML\Logger::debug( - $this->title . 'Attempting to get configuration values from authsource [' . - $config['authsource'] . ']' + $this->title.'Attempting to get configuration values from authsource ['. + $config['authsource'].']' ); // Get the authsources file, which should contain the config @@ -121,7 +121,7 @@ abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_Proce // Verify that the authsource config exists if (!$authsource->hasValue($config['authsource'])) { throw new SimpleSAML_Error_Exception( - $this->title . 'Authsource [' . $config['authsource'] . + $this->title.'Authsource ['.$config['authsource']. '] defined in filter parameters not found in authsources.php' ); } @@ -134,7 +134,7 @@ abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_Proce // TODO: Support ldap:LDAPMulti, if possible if (@$authsource[0] != 'ldap:LDAP') { throw new SimpleSAML_Error_Exception( - $this->title . 'Authsource [' . $config['authsource'] . + $this->title.'Authsource ['.$config['authsource']. '] specified in filter parameters is not an ldap:LDAP type' ); } @@ -162,7 +162,10 @@ abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_Proce // only set when search.enabled = true if (isset($authsource['search.enable']) && $authsource['search.enable']) { if (isset($authsource['search.base'])) { - $authconfig['ldap.basedn'] = $authsource['search.base']; + $authconfig['ldap.basedn'] = $authsource['search.base']; + } + if (isset($authsource['search.scope'])) { + $authconfig['ldap.scope'] = $authsource['search.scope']; } if (isset($authsource['search.username'])) { $authconfig['ldap.username'] = $authsource['search.username']; @@ -192,8 +195,8 @@ abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_Proce // Authsource complete SimpleSAML\Logger::debug( - $this->title . 'Retrieved authsource [' . $config['authsource'] . - '] configuration values: ' . $this->var_export($authconfig) + $this->title.'Retrieved authsource ['.$config['authsource']. + '] configuration values: '.$this->var_export($authconfig) ); } @@ -213,9 +216,9 @@ abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_Proce // Log the member values retrieved above SimpleSAML\Logger::debug( - $this->title . 'Configuration values retrieved;' . - ' BaseDN: ' . $this->var_export($this->base_dn) . - ' Product: ' . $this->var_export($this->product) + $this->title.'Configuration values retrieved;'. + ' BaseDN: '.$this->var_export($this->base_dn). + ' Product: '.$this->var_export($this->product) ); // Setup the attribute map which will be used to search LDAP @@ -231,7 +234,7 @@ abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_Proce // Log the attribute map SimpleSAML\Logger::debug( - $this->title . 'Attribute map created: ' . $this->var_export($this->attribute_map) + $this->title.'Attribute map created: '.$this->var_export($this->attribute_map) ); // Setup the object type map which is used to determine a DNs' type @@ -242,7 +245,7 @@ abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_Proce // Log the type map SimpleSAML\Logger::debug( - $this->title . 'Type map created: ' . $this->var_export($this->type_map) + $this->title.'Type map created: '.$this->var_export($this->type_map) ); } @@ -272,15 +275,15 @@ abstract class sspmod_ldap_Auth_Process_BaseFilter extends SimpleSAML_Auth_Proce // Log the LDAP connection SimpleSAML\Logger::debug( - $this->title . 'Connecting to LDAP server;' . - ' Hostname: ' . $hostname . - ' Port: ' . $port . - ' Enable TLS: ' . ($enable_tls ? 'Yes' : 'No') . - ' Debug: ' . ($debug ? 'Yes' : 'No') . - ' Referrals: ' . ($referrals ? 'Yes' : 'No') . - ' Timeout: ' . $timeout . - ' Username: ' . $username . - ' Password: ' . (empty($password) ? '' : '********') + $this->title.'Connecting to LDAP server;'. + ' Hostname: '.$hostname. + ' Port: '.$port. + ' Enable TLS: '.($enable_tls ? 'Yes' : 'No'). + ' Debug: '.($debug ? 'Yes' : 'No'). + ' Referrals: '.($referrals ? 'Yes' : 'No'). + ' Timeout: '.$timeout. + ' Username: '.$username. + ' Password: '.(empty($password) ? '' : '********') ); // Connect to the LDAP server to be queried during processing diff --git a/modules/ldap/lib/ConfigHelper.php b/modules/ldap/lib/ConfigHelper.php index d76684bb8026d7721891f8409d527dbbff53595e..c02adf8b02444c15018475f0a26ba1b9e498a380 100644 --- a/modules/ldap/lib/ConfigHelper.php +++ b/modules/ldap/lib/ConfigHelper.php @@ -56,30 +56,31 @@ class sspmod_ldap_ConfigHelper */ private $referrals; - /** * Whether we need to search for the users DN. */ private $searchEnable; - /** * The username we should bind with before we can search for the user. */ private $searchUsername; - /** * The password we should bind with before we can search for the user. */ private $searchPassword; - /** * Array with the base DN(s) for the search. */ private $searchBase; + /** + * The scope of the search. + */ + private $searchScope; + /** * Additional LDAP filter fields for the search */ @@ -90,31 +91,26 @@ class sspmod_ldap_ConfigHelper */ private $searchAttributes; - /** * The DN pattern we should use to create the DN from the username. */ private $dnPattern; - /** * The attributes we should fetch. Can be NULL in which case we will fetch all attributes. */ private $attributes; - /** * The user cannot get all attributes, privileged reader required */ private $privRead; - /** * The DN we should bind with before we can get the attributes. */ private $privUsername; - /** * The password we should bind with before we can get the attributes. */ @@ -153,6 +149,7 @@ class sspmod_ldap_ConfigHelper } $this->searchBase = $config->getArrayizeString('search.base'); + $this->searchScope = $config->getString('search.scope', 'subtree'); $this->searchFilter = $config->getString('search.filter', null); $this->searchAttributes = $config->getArray('search.attributes'); @@ -187,7 +184,7 @@ class sspmod_ldap_ConfigHelper assert(is_string($password)); if (empty($password)) { - SimpleSAML\Logger::info($this->location . ': Login with empty password disallowed.'); + SimpleSAML\Logger::info($this->location.': Login with empty password disallowed.'); throw new SimpleSAML_Error_Error('WRONGUSERPASS'); } @@ -203,16 +200,16 @@ class sspmod_ldap_ConfigHelper } } - $dn = $ldap->searchfordn($this->searchBase, $this->searchAttributes, $username, true, $this->searchFilter); + $dn = $ldap->searchfordn($this->searchBase, $this->searchAttributes, $username, true, $this->searchFilter, $this->searchScope); if ($dn === null) { /* User not found with search. */ - SimpleSAML\Logger::info($this->location . ': Unable to find users DN. username=\'' . $username . '\''); + SimpleSAML\Logger::info($this->location.': Unable to find users DN. username=\''.$username.'\''); throw new SimpleSAML_Error_Error('WRONGUSERPASS'); } } if (!$ldap->bind($dn, $password, $sasl_args)) { - SimpleSAML\Logger::info($this->location . ': '. $username . ' failed to authenticate. DN=' . $dn); + SimpleSAML\Logger::info($this->location.': '.$username.' failed to authenticate. DN='.$dn); throw new SimpleSAML_Error_Error('WRONGUSERPASS'); } @@ -275,7 +272,7 @@ class sspmod_ldap_ConfigHelper } return $ldap->searchfordn($this->searchBase, $attribute, - $value, $allowZeroHits, $this->searchFilter); + $value, $allowZeroHits, $this->searchFilter, $this->searchScope); } public function getAttributes($dn, $attributes = null)