From a3d875782a1baf7e84cc86403633831a8f0435ea Mon Sep 17 00:00:00 2001 From: Jan Schneider Date: Mon, 20 Sep 2010 15:21:52 +0200 Subject: [PATCH] Move code to find user DNs to Horde_Ldap. --- framework/Auth/lib/Horde/Auth/Ldap.php | 85 +++++++------------------- framework/Core/lib/Horde/Core/Factory/Ldap.php | 12 ++-- framework/Ldap/lib/Horde/Ldap.php | 38 +++++++++++- 3 files changed, 63 insertions(+), 72 deletions(-) diff --git a/framework/Auth/lib/Horde/Auth/Ldap.php b/framework/Auth/lib/Horde/Auth/Ldap.php index d8dce3ef7..bc54752b3 100644 --- a/framework/Auth/lib/Horde/Auth/Ldap.php +++ b/framework/Auth/lib/Horde/Auth/Ldap.php @@ -71,36 +71,6 @@ class Horde_Auth_Ldap extends Horde_Auth_Base } /** - * Find the user dn. - * - * @param string $userId The userId to find. - * - * @return string The user's full DN - * @throws Horde_Auth_Exception - */ - protected function _findDN($userId) - { - /* Search for the user's full DN. */ - $filter = $this->_getParamFilter(); - $filter = '(&(' . $this->_params['uid'] . '=' . $userId . ')' . - $filter . ')'; - - try { - $search = $this->_ldap->search(null, $filter, array('attributes' => array($this->_params['uid']))); - } catch (Horde_Ldap_Exception $e) { - throw new Horde_Auth_Exception('Could not search the LDAP server.'); - } - - if (!$search->count()) { - throw new Horde_Auth_Exception('Empty result.'); - } - - $entry = $search->shiftEntry(); - - return $entry->currentDN(); - } - - /** * Checks for shadowLastChange and shadowMin/Max support and returns their * values. We will also check for pwdLastSet if Active Directory is * support is requested. For this check to succeed we need to be bound @@ -215,7 +185,13 @@ class Horde_Auth_Ldap extends Horde_Auth_Base { /* Search for the user's full DN. */ $this->_ldap->bind(); - $dn = $this->_findDN($userId); + try { + $dn = $this->_ldap->findUserDN($userId); + } catch (Horde_Exception_NotFound $e) { + throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN); + } catch (Horde_Exception_Ldap $e) { + throw new Horde_Auth_Exception($e->getMessage(), Horde_Auth::REASON_MESSAGE); + } /* Attempt to bind to the LDAP server as the user. */ try { @@ -315,7 +291,11 @@ class Horde_Auth_Ldap extends Horde_Auth_Base if (is_null($dn)) { /* Search for the user's full DN. */ - $dn = $this->_findDN($userId); + try { + $dn = $this->_ldap->findUserDN($userId); + } catch (Horde_Exception_Ldap $e) { + throw new Horde_Auth_Exception($e); + } } try { @@ -347,7 +327,11 @@ class Horde_Auth_Ldap extends Horde_Auth_Base if (is_null($olddn)) { /* Search for the user's full DN. */ - $dn = $this->_findDN($oldID); + try { + $dn = $this->_ldap->findUserDN($oldID); + } catch (Horde_Exception_Ldap $e) { + throw new Horde_Auth_Exception($e); + } $olddn = $dn; $newdn = preg_replace('/uid=.*?,/', 'uid=' . $newID . ',', $dn, 1); @@ -393,8 +377,6 @@ class Horde_Auth_Ldap extends Horde_Auth_Base */ public function listUsers() { - $filter = $this->_getParamFilter(); - $params = array( 'attributes' => array($this->_params['uid']), 'scope' => $this->_params['scope'], @@ -405,7 +387,11 @@ class Horde_Auth_Ldap extends Horde_Auth_Base * Note: You cannot override a server-side limit with this. */ $userlist = array(); try { - $search = $this->_ldap->search($this->_params['basedn'], $filter, $params)->as_struct(); + $search = $this->_ldap->search( + $this->_params['basedn'], + Horde_Ldap_Filter::build($this->_params), + $params) + ->as_struct(); $uid = Horde_String::lower($this->_params['uid']); foreach ($search as $val) { $userlist[] = $val[$uid][0]; @@ -414,31 +400,4 @@ class Horde_Auth_Ldap extends Horde_Auth_Base return $userlist; } - - /** - * Return a formatted LDAP filter as configured within the parameters. - * - * @return string LDAP search filter - */ - protected function _getParamFilter() - { - if (!empty($this->_params['filter'])) { - $filter = $this->_params['filter']; - } elseif (!is_array($this->_params['objectclass'])) { - $filter = 'objectclass=' . $this->_params['objectclass']; - } else { - $filter = ''; - if (count($this->_params['objectclass']) > 1) { - $filter = '(&' . $filter; - foreach ($this->_params['objectclass'] as $objectclass) { - $filter .= '(objectclass=' . $objectclass . ')'; - } - $filter .= ')'; - } elseif (count($this->_params['objectclass']) == 1) { - $filter = '(objectClass=' . $this->_params['objectclass'][0] . ')'; - } - } - return $filter; - } - } diff --git a/framework/Core/lib/Horde/Core/Factory/Ldap.php b/framework/Core/lib/Horde/Core/Factory/Ldap.php index b806da491..c73bfe0ba 100644 --- a/framework/Core/lib/Horde/Core/Factory/Ldap.php +++ b/framework/Core/lib/Horde/Core/Factory/Ldap.php @@ -75,17 +75,15 @@ class Horde_Core_Factory_Ldap $config = $this->getConfig($type); - /* Determine if we are using the base LDAP config. */ - if (isset($config['driverconfig']) && - ($config['driverconfig'] == 'horde')) { - $this->_instances[$sig] = $this->getLdap(); - return $this->_instances[$sig]; + /* BC check for old configuration without 'user' setting, so that + administrators can still log in through LDAP and update the + configuration. */ + if (!isset($config['user'])) { + $config['user'] = $config; } try { $this->_instances[$sig] = new Horde_Ldap($config); - // Establish the connection so it is available when searching later - $this->_instances[$sig]->bind(); } catch (Horde_Exception $e) { if ($pushed) { $GLOBALS['registry']->popApp(); diff --git a/framework/Ldap/lib/Horde/Ldap.php b/framework/Ldap/lib/Horde/Ldap.php index 621004b40..8580d67e8 100644 --- a/framework/Ldap/lib/Horde/Ldap.php +++ b/framework/Ldap/lib/Horde/Ldap.php @@ -30,6 +30,9 @@ class Horde_Ldap * - options: hash of LDAP options to set. * - filter: default search filter. * - scope: default search scope. + * - user: configuration parameters for {@link findUserDN()}, + * must contain 'uid', and 'filter' or 'objectclass' + * entries. * - auto_reconnect: if true, the class will automatically * attempt to reconnect to the LDAP server in certain * failure conditions when attempting a search, or other @@ -47,12 +50,13 @@ class Horde_Ldap 'port' => 389, 'version' => 3, 'starttls' => false, - 'binddn' => '', - 'bindpw' => '', + 'binddn' => '', + 'bindpw' => '', 'basedn' => '', 'options' => array(), 'filter' => '(objectClass=*)', 'scope' => 'sub', + 'user' => array(), 'auto_reconnect' => false, 'min_backoff' => 1, 'current_backoff' => 1, @@ -839,6 +843,36 @@ class Horde_Ldap } /** + * Returns the DN of a user. + * + * The purpose is to quickly find the full DN of a user so it can be used + * to re-bind as this user. This method requires the 'user' configuration + * parameter to be set. + * + * @param string $user The user to find. + * + * @return string The user's full DN. + * @throws Horde_Ldap_Exception + * @throws Horde_Exception_NotFound + */ + public function findUserDN($user) + { + $filter = Horde_Ldap_Filter::combine( + 'and', + array(Horde_Ldap_Filter::build($this->_config['user']), + Horde_Ldap_Filter::create($this->_config['user']['uid'], 'equals', $user))); + $search = $this->search( + null, + $filter, + array('attributes' => array($this->_config['user']['uid']))); + if (!$search->count()) { + throw new Horde_Exception_NotFound(); + } + $entry = $search->shiftEntry(); + return $entry->currentDN(); + } + + /** * Sets an LDAP option. * * @param string $option Option to set. -- 2.11.0