Move code to find user DNs to Horde_Ldap.
authorJan Schneider <jan@horde.org>
Mon, 20 Sep 2010 13:21:52 +0000 (15:21 +0200)
committerJan Schneider <jan@horde.org>
Mon, 20 Sep 2010 13:21:52 +0000 (15:21 +0200)
framework/Auth/lib/Horde/Auth/Ldap.php
framework/Core/lib/Horde/Core/Factory/Ldap.php
framework/Ldap/lib/Horde/Ldap.php

index d8dce3e..bc54752 100644 (file)
@@ -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;
-    }
-
 }
index b806da4..c73bfe0 100644 (file)
@@ -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();
index 621004b..8580d67 100644 (file)
@@ -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.