Revision: 1870
Author: olavmrk
Date: Mon Oct 19 04:13:01 2009
Log: LDAP: Add support for proxy authentication.

Patch by Emmanuel Dreyfus.
http://code.google.com/p/simplesamlphp/source/detail?r=1870

Modified:
  /trunk/lib/SimpleSAML/Auth/LDAP.php
  /trunk/modules/ldap/lib/Auth/Source/LDAP.php
  /trunk/modules/ldap/lib/ConfigHelper.php

=======================================
--- /trunk/lib/SimpleSAML/Auth/LDAP.php Mon Aug 17 02:06:32 2009
+++ /trunk/lib/SimpleSAML/Auth/LDAP.php Mon Oct 19 04:13:01 2009
@@ -29,6 +29,11 @@
         */
        private $ldap = null;

+       /**
+        * LDAP user: authz_id if SASL is in use, binding dn otherwise
+        */
+       private $authz_id = null;
+
        /**
         * Timeout value, in seconds.
         *
@@ -294,25 +299,57 @@
         * The DN used.
         * @param string $password
         * The password used.
+        * @param array $sasl_args
+        * Array of SASL options for SASL bind
         * @return bool
-        * Returns TRUE if successful, FALSE if LDAP_INVALID_CREDENTIALS.
+        * Returns TRUE if successful, FALSE if
+        * LDAP_INVALID_CREDENTIALS, LDAP_X_PROXY_AUTHZ_FAILURE,
+        * LDAP_INAPPROPRIATE_AUTH, LDAP_INSUFFICIENT_ACCESS
         * @throws SimpleSAML_Error_Exception on other errors
         */
-       public function bind($dn, $password) {
-
-               // Bind, with error handling.
-               if (@ldap_bind($this->ldap, $dn, $password)) {
-
+       public function bind($dn, $password, array $sasl_args = NULL) {
+               $authz_id = null;
+
+               if ($sasl_args != NULL) {
+                       if (!function_exists(ldap_sasl_bind)) {
+                               $ex_msg = 'Library - missing SASL support';
+                               throw $this->makeException($ex_msg);
+                       }
+
+                       // SASL Bind, with error handling.
+                       $authz_id = $sasl_args['authz_id'];
+                       $error = @ldap_sasl_bind($this->ldap, $dn, $password,
+                                                $sasl_args['mech'],
+                                                $sasl_args['realm'],
+                                                $sasl_args['authc_id'],
+                                                $sasl_args['authz_id'],
+                                                $sasl_args['props']);
+               } else {
+                       // Simple Bind, with error handling.
+                       $authz_id = $dn;
+                       $error = @ldap_bind($this->ldap, $dn, $password);
+               }
+
+               if ($error === TRUE) {
                        // Good.
+                       $this->authz_id = $authz_id;
                        SimpleSAML_Logger::debug('Library - LDAP bind(): Bind 
successful with  
DN \'' . $dn . '\'');
                        return TRUE;

                }

-               /* Handle invalid DN/password.
-                * LDAP_INVALID_CREDENTIALS */
-               if (ldap_errno($this->ldap) === 49) {
+               /* Handle errors
+                * LDAP_INVALID_CREDENTIALS
+                * LDAP_INSUFFICIENT_ACCESS */
+               switch(ldap_errno($this->ldap)) {
+               case 47:        /* LDAP_X_PROXY_AUTHZ_FAILURE */
+               case 48:        /* LDAP_INAPPROPRIATE_AUTH */
+               case 49:        /* LDAP_INVALID_CREDENTIALS */
+               case 50:        /* LDAP_INSUFFICIENT_ACCESS */
                        return FALSE;
+                       break;
+               default;
+                       break;
                }

                // Bad.
@@ -502,6 +539,47 @@
                }
                return $string;
        }
+
+       /**
+        * Convert SASL authz_id into a DN
+        */
+       private  function authzid_to_dn($searchBase, $searchAttributes,  
$authz_id) {
+               if (preg_match("/^dn:/", $authz_id))
+                       return preg_replace("/^dn:/", "", $authz_id);
+
+               if (preg_match("/^u:/", $authz_id))
+                       return $this->searchfordn($searchBase, 
$searchAttributes,
+                                                 preg_replace("/^u:/", "", 
$authz_id));
+
+               return $authz_id;
+       }
+
+       /**
+        * ldap_exop_whoami accessor, if available. Use requested authz_id
+        * otherwise.
+        *
+        * ldap_exop_whoami is not yet included in PHP. For reference, the
+        * feature request: http://bugs.php.net/bug.php?id=42060
+        * And the patch against lastest PHP release:
+        *  
http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/databases/php-ldap/files/ldap-ctrl-exop.patch
+        */
+       public  function whoami($searchBase, $searchAttributes) {
+               $authz_id = '';
+
+               if (function_exists('ldap_exop_whoami')) {
+                       if (ldap_exop_whoami($this->ldap, $authz_id) !== true)
+                           throw $this->getLDAPException('LDAP whoami exop 
failure');
+               } else {
+                       $authz_id = $this->authz_id;
+               }
+
+               $dn = $this->authzid_to_dn($searchBase, $searchAttributes, 
$authz_id);
+
+               if (!isset($dn) || ($dn == ''))
+                       throw $this->getLDAPException('Cannot figure userID');
+
+               return $dn;
+       }

  }

=======================================
--- /trunk/modules/ldap/lib/Auth/Source/LDAP.php        Thu Mar  5 01:14:20 2009
+++ /trunk/modules/ldap/lib/Auth/Source/LDAP.php        Mon Oct 19 04:13:01 2009
@@ -42,13 +42,14 @@
         *
         * @param string $username  The username the user wrote.
         * @param string $password  The password the user wrote.
+        * param array $sasl_arg  Associative array of SASL options
         * @return array  Associative array with the users attributes.
         */
-       protected function login($username, $password) {
+       protected function login($username, $password, array $sasl_args = NULL) 
{
                assert('is_string($username)');
                assert('is_string($password)');

-               return $this->ldapConfig->login($username, $password);
+               return $this->ldapConfig->login($username, $password, 
$sasl_args);
        }

  }
=======================================
--- /trunk/modules/ldap/lib/ConfigHelper.php    Mon Aug 17 02:06:18 2009
+++ /trunk/modules/ldap/lib/ConfigHelper.php    Mon Oct 19 04:13:01 2009
@@ -160,9 +160,10 @@
         *
         * @param string $username  The username the user wrote.
         * @param string $password  The password the user wrote.
+        * @param arrray $sasl_args  Array of SASL options for LDAP bind.
         * @return array  Associative array with the users attributes.
         */
-       public function login($username, $password) {
+       public function login($username, $password, array $sasl_args = NULL) {
                assert('is_string($username)');
                assert('is_string($password)');

@@ -186,10 +187,14 @@
                        }
                }

-               if (!$ldap->bind($dn, $password)) {
+               if (!$ldap->bind($dn, $password, $sasl_args)) {
                        SimpleSAML_Logger::info($this->location . ': '. 
$username . ' failed to  
authenticate. DN=' . $dn);
                        throw new SimpleSAML_Error_Error('WRONGUSERPASS');
                }
+
+               /* In case of SASL bind, authenticated and authorized DN may 
differ */
+               if (isset($sasl_args))
+                       $dn = $ldap->whoami($this->searchBase, 
$this->searchAttributes);

                /* Are privs needed to get the attributes? */
                if ($this->privRead) {

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"simpleSAMLphp commits" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/simplesamlphp-commits?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to