Revision: 1609
          http://mrbs.svn.sourceforge.net/mrbs/?rev=1609&view=rev
Author:   jberanek
Date:     2010-11-17 18:54:36 +0000 (Wed, 17 Nov 2010)

Log Message:
-----------
* Introduced the ability to get a user's email address from LDAP if
 the system is configured to use LDAP for authentication. Adds the
 config variables: $ldap_get_user_email, $ldap_email_attrib. As part of
 this work also added two new LDAP config variables:
 $ldap_unbind_between_attempts and $ldap_debug.

Modified Paths:
--------------
    mrbs/trunk/web/auth_ldap.inc
    mrbs/trunk/web/functions_mail.inc
    mrbs/trunk/web/systemdefaults.inc.php

Modified: mrbs/trunk/web/auth_ldap.inc
===================================================================
--- mrbs/trunk/web/auth_ldap.inc        2010-11-17 17:59:26 UTC (rev 1608)
+++ mrbs/trunk/web/auth_ldap.inc        2010-11-17 18:54:36 UTC (rev 1609)
@@ -8,18 +8,21 @@
   $auth['session']='http';
 }
 
-/* authValidateUser($user, $pass)
+/* authLdapAction($callback, $user, &$object)
  * 
- * Checks if the specified username/password pair are valid
+ * Connects/binds to all configured LDAP servers/base DNs and
+ * then performs a callback, passing the LDAP object, $base_dn,
+ * user DN (in $dn), $user and a generic object $object
+ *
+ * $callback - The callback function
+ * $user     - The user name
+ * &$object  - Reference to the generic object, type defined by caller
  * 
- * $user  - The user name
- * $pass  - The password
- * 
  * Returns:
  *   0        - The pair are invalid or do not exist
  *   non-zero - The pair are valid
  */
-function authValidateUser($user, $pass)
+function authLdapAction($callback, $user, &$object)
 {
   global $auth;
   global $ldap_host;
@@ -28,7 +31,6 @@
   global $ldap_tls;
   global $ldap_base_dn;
   global $ldap_user_attrib;
-  global $ldap_filter;
   global $ldap_dn_search_attrib;
   global $ldap_dn_search_dn;
   global $ldap_dn_search_password;
@@ -42,14 +44,6 @@
   $all_ldap_base_dn     = array();
   $all_ldap_user_attrib = array();
 
-  // Check if we do not have a username/password
-  // User can always bind to LDAP anonymously with empty password,
-  // therefore we need to block empty password here...
-  if (!isset($user) || !isset($pass) || strlen($pass)==0)
-  {
-    return 0;
-  }
-
   // Check that if there is an array of hosts and an array of ports
   // then the number of each must be the same or the authenication
   // is forced to fail.
@@ -100,6 +94,8 @@
   // Check that connection was established
   if ($ldap)
   {
+    authLdapDebug("authLdapAction: Got LDAP connection");
+
     if ($ldap_v3)
     {
       ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
@@ -113,6 +109,7 @@
     // or fail
     foreach ( $all_ldap_base_dn as $idx => $base_dn)
     {
+      authLdapDebug("authLdapAction: start of foreach $base_dn");
       if (isset($ldap_dn_search_attrib))
       {
         if (isset($ldap_dn_search_dn) &&
@@ -127,6 +124,7 @@
           // Anonymous bind
           $res = @ldap_bind($ldap);
         }
+        authLdapDebug("authLdapAction: Result of initial bind is $res");
 
         if ($res)
         {
@@ -136,10 +134,19 @@
 
           if (@ldap_count_entries($ldap, $res) == 1)
           {
+            authLdapDebug("authLdapAction: Found one entry using ".
+                          "\$ldap_dn_search_attrib");
             $entries = ldap_get_entries($ldap, $res);
             $dn = $entries[0]["dn"];
             $user_search = "distinguishedName=" . $dn;
           }
+          else
+          {
+            authLdapDebug("authLdapAction: Didn't find entry using ".
+                          "\$ldap_dn_search_attrib");
+          }
+          authLdapDebug("authLdapAction: base_dn $base_dn user $user ".
+                        "dn $dn");
         }
       }
       else
@@ -147,36 +154,189 @@
         // construct dn for user
         $user_search = $all_ldap_user_attrib[$idx] . "=" . $user;
         $dn = $user_search . "," . $base_dn;
+
+        authLdapDebug("authLdapAction: Constructed dn $dn and ".
+                      "user_search $user_search using ".
+                      "\$ldap_user_attrib");
       }
 
-      // try an authenticated bind
-      // use this to confirm that the user/password pair
-      if ($dn && @ldap_bind($ldap, $dn, $pass))
+      $res = $callback($ldap, $base_dn, $dn, $user_search, $user, $object);
+      if ($res)
       {
-        // however if there is a filter check that the
-        // user is part of the group defined by the filter
-        if (! $ldap_filter)
-        {
-          @ldap_unbind($ldap);
-          return 1;
-        }
-        else
-        {
-          $res = @ldap_search($ldap,
-                              $base_dn,
-                              "(&($user_search)($ldap_filter))",
-                              array()
-                             );
-          if (@ldap_count_entries($ldap, $res) > 0)
-          {
-            @ldap_unbind($ldap);
-            return 1;
-          }
-        }
+        return $res;
       }
+
+    } // foreach
+
+    @ldap_unbind($ldap);
+  } // if ($ldap)
+}
+
+
+/* authLdapGetEmail($user)
+ * 
+ * Gets the email address of the user from LDAP
+ * 
+ * $user  - The user name
+ * 
+ * Returns:
+ *   The user's email address or ''
+ */
+function authLdapGetEmail($user)
+{
+  $email = '';
+  $object = array();
+
+  $res = authLdapAction("authLdapGetEmailCallback", $user, $object);
+
+  if ($res)
+  {
+    $email = $object['email'];
+  }
+  return $email;
+}
+
+
+/* authValidateUserCallback(&$ldap, $base_dn, $dn, $user_search,
+                            $user, &$object)
+ * 
+ * Checks if the specified username/password pair are valid
+ *
+ * &$ldap       - Reference to the LDAP object
+ * $base_dn     - The base DN
+ * $dn          - The user's DN
+ * $user_search - The LDAP filter to find the user
+ * $user        - The user name
+ * &$object     - Reference to the generic object
+ * 
+ * Returns:
+ *   0        - Didn't find a user
+ *   non-zero - Found a user
+ */
+function authLdapGetEmailCallback(&$ldap, $base_dn, $dn, $user_search,
+                                  $user, &$object)
+{
+  global $ldap_email_attrib;
+
+  authLdapDebug("authLdapGetEmailCallback: base_dn $base_dn dn $dn ".
+                "user_search $user_search user $user");
+
+  if ($ldap && $base_dn && $dn && $user_search)
+  {
+    $res = @ldap_search($ldap,
+                        $base_dn,
+                        "($user_search)",
+                        array($ldap_email_attrib)
+                       );
+    if (@ldap_count_entries($ldap, $res) > 0)
+    {
+      authLdapDebug("authLdapGetEmailCallback: search successful");
+      $entries = ldap_get_entries($ldap, $res);
+      $object['email'] = $entries[0][$ldap_email_attrib][0];
+
+      authLdapDebug("authLdapGetEmailCallback: email is '".
+                    $object['email']."'");
+      
+      return 1;
     }
+  }
+  return 0;
+}
+
+/* authValidateUser($user, $pass)
+ * 
+ * Checks if the specified username/password pair are valid
+ * 
+ * $user  - The user name
+ * $pass  - The password
+ * 
+ * Returns:
+ *   0        - The pair are invalid or do not exist
+ *   non-zero - The pair are valid
+ */
+function authValidateUser($user, $pass)
+{
+  // Check if we do not have a username/password
+  // User can always bind to LDAP anonymously with empty password,
+  // therefore we need to block empty password here...
+  if (!isset($user) || !isset($pass) || strlen($pass)==0)
+  {
+    authLdapDebug("Empty username or password passed");
+    return 0;
+  }
+
+  $object = array();
+  $object['pass'] = $pass;
+
+  return authLdapAction("authValidateUserCallback", $user, $object);
+}
+
+
+/* authValidateUserCallback(&$ldap, $base_dn, $dn, $user_search,
+                            $user, &$object)
+ * 
+ * Checks if the specified username/password pair are valid
+ *
+ * &$ldap       - Reference to the LDAP object
+ * $base_dn     - The base DN
+ * $dn          - The user's DN
+ * $user_search - The LDAP filter to find the user
+ * $user        - The user name
+ * &$object     - Reference to the generic object
+ * 
+ * Returns:
+ *   0        - Didn't find a user
+ *   non-zero - Found a user
+ */
+function authValidateUserCallback(&$ldap, $base_dn, $dn, $user_search,
+                                  $user, &$object)
+{
+  global $ldap_filter;
+
+  authLdapDebug("authValidateUserCallback: base_dn $base_dn dn $dn user 
$user");
+
+  $pass = $object['pass'];
+
+  // try an authenticated bind
+  // use this to confirm that the user/password pair
+  if ($dn && @ldap_bind($ldap, $dn, $pass))
+  {
+    // however if there is a filter check that the
+    // user is part of the group defined by the filter
+    if (! $ldap_filter)
+    {
+      authLdapDebug("authValidateUserCallback: Successful authenticated ".
+                    "bind with no $ldap_filter");
+      return 1;
+    }
+    else
+    {
+      authLdapDebug("authValidateUserCallback: Successful authenticated ".
+                    "bind checking $ldap_filter");
+
+      $res = @ldap_search($ldap,
+                          $base_dn,
+                          "(&($user_search)($ldap_filter))",
+                          array()
+                         );
+      if (@ldap_count_entries($ldap, $res) > 0)
+      {
+        authLdapDebug("authValidateUserCallback: Found entry with filter");
+        return 1;
+      }
+      authLdapDebug("authValidateUserCallback: No entry found with filter");
+    }
+  }
+  else
+  {
+    authLdapDebug("authValidateUserCallback: Bind to $dn failed");
+  }
+
+  if ($ldap_unbind_between_attempts)
+  {
     @ldap_unbind($ldap);
   }
+
   // return failure if no connection is established
   return 0;
 }
@@ -213,4 +373,20 @@
   return 1;
 }
 
+/* authLdapDebug($message)
+ *
+ * Output LDAP debugging, if the configuration variable
+ * $ldap_debug is true.
+ *
+ */
+function authLdapDebug($message)
+{
+  global $ldap_debug;
+
+  if ($ldap_debug)
+  {
+    error_log($message);
+  }
+}
+
 ?>

Modified: mrbs/trunk/web/functions_mail.inc
===================================================================
--- mrbs/trunk/web/functions_mail.inc   2010-11-17 17:59:26 UTC (rev 1608)
+++ mrbs/trunk/web/functions_mail.inc   2010-11-17 18:54:36 UTC (rev 1609)
@@ -196,7 +196,7 @@
 // returns an empty string in the event of an error
 function get_email_address($user)
 {
-  global $mail_settings, $auth, $tbl_users;
+  global $mail_settings, $auth, $tbl_users, $ldap_get_user_email;
   
   if ('db' == $auth['type'])
   {
@@ -209,6 +209,10 @@
       $email = "";
     }
   }
+  else if (('ldap' == $auth['type']) && $ldap_get_user_email)
+  {
+    $email = authLdapGetEmail($user);
+  }
   else
   {
     $email = str_replace($mail_settings['username_suffix'], '', $user);

Modified: mrbs/trunk/web/systemdefaults.inc.php
===================================================================
--- mrbs/trunk/web/systemdefaults.inc.php       2010-11-17 17:59:26 UTC (rev 
1608)
+++ mrbs/trunk/web/systemdefaults.inc.php       2010-11-17 18:54:36 UTC (rev 
1609)
@@ -657,6 +657,20 @@
 // they are a valid user of mrbs.
 //$ldap_filter = "mrbsuser=y";
 
+// Set to TRUE to tell MRBS to look up a user's email address in LDAP.
+// Utilises $ldap_email_attrib below
+$ldap_get_user_email = FALSE;
+// The LDAP attribute which holds a user's email address
+$ldap_email_attrib = 'mail';
+
+// Set to TRUE if you want MRBS to call ldap_unbind() between successive
+// attempts to bind. Unbinding while still connected upsets some
+// LDAP servers
+$ldap_unbind_between_attempts = FALSE;
+
+// Output debugging information for LDAP actions
+$ldap_debug = FALSE;
+
 // 'auth_imap' configuration settings
 // See AUTHENTICATION for details of how check against multiple servers
 // Where is the IMAP server


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today
http://p.sf.net/sfu/msIE9-sfdev2dev
_______________________________________________
Mrbs-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mrbs-commits

Reply via email to