plugins/kolab_auth

Aleksander Machniak machniak at kolabsys.com
Tue Jun 25 17:45:20 CEST 2013


 plugins/kolab_auth/config.inc.php.dist |   11 +++
 plugins/kolab_auth/kolab_auth_ldap.php |  104 ++++++++++++++++++++++++++++++---
 2 files changed, 106 insertions(+), 9 deletions(-)

New commits:
commit 1778b5ec70156f064fdda61c817c678001406996
Author: Aleksander Machniak <machniak at kolabsys.com>
Date:   Tue Jun 25 17:43:58 2013 +0200

    Implemented auth domain resolving (#1926)

diff --git a/plugins/kolab_auth/config.inc.php.dist b/plugins/kolab_auth/config.inc.php.dist
index 05c610b..3f77ea2 100644
--- a/plugins/kolab_auth/config.inc.php.dist
+++ b/plugins/kolab_auth/config.inc.php.dist
@@ -2,6 +2,17 @@
 
 // The id of the LDAP address book (which refers to the $rcmail_config['ldap_public'])
 // or complete addressbook definition array.
+// --------------------------------------------------------------------
+// Note: Multi-domain (hosted) installations can resolve domain aliases
+//   by adding following settings in kolab_auth_addressbook spec.:
+//
+//   'domain_base_dn'   => 'cn=kolab,cn=config',
+//   'domain_filter'    => '(&(objectclass=domainrelatedobject)(associateddomain=%s))',
+//   'domain_name_attr' => 'associateddomain',
+//
+//   With this %dc variable in base_dn and groups/base_dn will be
+//   replaced with DN string of resolved domain
+//---------------------------------------------------------------------
 $rcmail_config['kolab_auth_addressbook'] = '';
 
 // This will overwrite defined filter
diff --git a/plugins/kolab_auth/kolab_auth_ldap.php b/plugins/kolab_auth/kolab_auth_ldap.php
index b9e557e..c8ebcd1 100644
--- a/plugins/kolab_auth/kolab_auth_ldap.php
+++ b/plugins/kolab_auth/kolab_auth_ldap.php
@@ -27,13 +27,14 @@
  */
 class kolab_auth_ldap extends rcube_ldap_generic
 {
+    private $icache = array();
+
 
     function __construct($p)
     {
         $rcmail = rcube::get_instance();
 
         $this->debug    = (bool) $rcmail->config->get('ldap_debug');
-        $this->domain   = $rcmail->config->get('username_domain');
         $this->fieldmap = $p['fieldmap'];
         $this->fieldmap['uid'] = 'uid';
 
@@ -110,6 +111,8 @@ class kolab_auth_ldap extends rcube_ldap_generic
         $base_dn = $this->parse_vars($this->config['base_dn'], $user, $host);
         $scope   = $this->config['scope'];
 
+        // @TODO: print error if filter is empty
+
         // get record
         if ($result = parent::search($base_dn, $filter, $scope, $this->attributes)) {
             if ($result->count() == 1) {
@@ -273,7 +276,7 @@ class kolab_auth_ldap extends rcube_ldap_generic
             $filter = '(&(' . preg_replace('/^\(|\)$/', '', $this->config['filter']) . ')' . $filter . ')';
         }
 
-        $base_dn = $this->parse_vars($this->config['base_dn'], $_SESSION['username']);
+        $base_dn = $this->parse_vars($this->config['base_dn']);
         $scope   = $this->config['scope'];
         $attrs   = array_values($this->fieldmap);
         $list    = array();
@@ -357,26 +360,109 @@ class kolab_auth_ldap extends rcube_ldap_generic
     /**
      * Prepares filter query for LDAP search
      */
-    function parse_vars($str, $user, $host = null)
+    function parse_vars($str, $user = null, $host = null)
     {
-        if (!empty($this->domain) && strpos($user, '@') === false) {
-            if ($host && is_array($this->domain) && isset($this->domain[$host])) {
-                $user .= '@'.rcube_utils::parse_host($this->domain[$host], $host);
+        // When authenticating user $user is always set
+        // if not set it means we use this LDAP object for other
+        // purposes, e.g. kolab_delegation, then username with
+        // correct domain is in a session
+        if (!$user) {
+            $user = $_SESSION['username'];
+        }
+        else if (isset($this->icache[$user])) {
+            list($user, $dc) = $this->icache[$user];
+        }
+        else {
+            $orig_user = $user;
+            $rcmail = rcube::get_instance();
+
+            // get default domain
+            if ($username_domain = $rcmail->config->get('username_domain')) {
+                if ($host && is_array($username_domain) && isset($username_domain[$host])) {
+                    $domain = rcube_utils::parse_host($username_domain[$host], $host);
+                }
+                else if (is_string($username_domain)) {
+                    $domain = rcube_utils::parse_host($username_domain, $host);
+                }
+            }
+
+            // realmed username (with domain)
+            if (strpos($user, '@')) {
+                list($usr, $dom) = explode('@', $user);
+
+                // unrealm domain, user login can contain a domain alias
+                if ($dom != $domain && ($r_domain = $this->find_domain($dom))) {
+                    // $dom is a domain DN string?
+                    if (strpos($r_domain, '=')) {
+                        $dc = $r_domain;
+                    }
+                    else {
+                        $user = $usr . '@' . $r_domain;
+                    }
+                }
             }
-            else if (is_string($this->domain)) {
-                $user .= '@'.rcube_utils::parse_host($this->domain, $host);
+            else if ($domain && !strpos($user, '@')) {
+                $user .= '@' . $domain;
             }
+
+            $this->icache[$orig_user] = array($user, $dc);
         }
 
         // replace variables in filter
         list($u, $d) = explode('@', $user);
-        $dc = 'dc='.strtr($d, array('.' => ',dc=')); // hierarchal domain string
+
+        // hierarchal domain string
+        if (empty($dc)) {
+            $dc = 'dc=' . strtr($d, array('.' => ',dc='));
+        }
+
         $replaces = array('%dc' => $dc, '%d' => $d, '%fu' => $user, '%u' => $u);
 
         return strtr($str, $replaces);
     }
 
     /**
+     * Find root domain for specified domain
+     *
+     * @param string $domain Domain name
+     *
+     * @return string Domain name or domain DN string
+     */
+    function find_domain($domain)
+    {
+        if (empty($domain) || empty($this->config['domain_base_dn']) || empty($this->config['domain_filter'])) {
+            return null;
+        }
+
+        $base_dn   = $this->config['domain_base_dn'];
+        $filter    = $this->config['domain_filter'];
+        $name_attr = $this->config['domain_name_attribute'];
+
+        if (empty($name_attr)) {
+            $name_attr = 'associateddomain';
+        }
+
+        $filter = str_replace('%s', rcube_ldap_generic::quote_string($domain), $filter);
+        $result = parent::search($base_dn, $filter, 'sub', array($name_attr, 'inetdomainbasedn'));
+
+        if (!$result) {
+            return null;
+        }
+
+        $entries  = $result->entries(true);
+        $entry_dn = key($entries);
+        $entry    = $entries[$entry_dn];
+
+        if (is_array($entry)) {
+            if (!empty($entry['inetdomainbasedn'])) {
+                return $entry['inetdomainbasedn'];
+            }
+
+            return is_array($entry[$name_attr]) ? $entry[$name_attr][0] : $entry[$name_attr];
+        }
+    }
+
+    /**
      * HTML-safe DN string encoding
      *
      * @param string $str DN string





More information about the commits mailing list