From 739a1d93a9bf7ca612ed0464cca146765781c9b7 Mon Sep 17 00:00:00 2001
From: Thomas <thomas@roundcube.net>
Date: Thu, 17 Oct 2013 03:20:09 -0400
Subject: [PATCH] Integrate patch with more configuarion possibilities to LDAP (#1488753)

---
 program/lib/Roundcube/rcube_ldap.php |   95 ++++++++++++++++++++++++++++++++---------------
 1 files changed, 64 insertions(+), 31 deletions(-)

diff --git a/program/lib/Roundcube/rcube_ldap.php b/program/lib/Roundcube/rcube_ldap.php
index 24b14f8..bd7f0ac 100644
--- a/program/lib/Roundcube/rcube_ldap.php
+++ b/program/lib/Roundcube/rcube_ldap.php
@@ -81,6 +81,16 @@
                 $this->prop['groups']['name_attr'] = 'cn';
             if (empty($this->prop['groups']['scope']))
                 $this->prop['groups']['scope'] = 'sub';
+            // set default group objectclass => member attribute mapping
+            if (empty($this->prop['groups']['class_member_attr'])) {
+                $this->prop['groups']['class_member_attr'] = array(
+                    'group'                   => 'member',
+                    'groupofnames'            => 'member',
+                    'kolabgroupofnames'       => 'member',
+                    'groupofuniquenames'      => 'uniquemember',
+                    'kolabgroupofuniquenames' => 'uniquemember',
+                );
+            }
 
             // add group name attrib to the list of attributes to be fetched
             $fetch_attributes[] = $this->prop['groups']['name_attr'];
@@ -279,6 +289,14 @@
                             continue;  // bind failed, try neyt host
                     }
 
+                    $search_attribs = array('uid');
+                    if ($search_bind_attrib = (array)$this->prop['search_bind_attrib']) {
+                        foreach ($search_bind_attrib as $r => $attr) {
+                            $search_attribs[] = $attr;
+                            $replaces[$r] = '';
+                        }
+                    }
+
                     // Search for the dn to use to authenticate
                     $this->prop['search_base_dn'] = strtr($this->prop['search_base_dn'], $replaces);
                     $this->prop['search_filter'] = strtr($this->prop['search_filter'], $replaces);
@@ -286,7 +304,7 @@
                     $this->_debug("S: searching with base {$this->prop['search_base_dn']} for {$this->prop['search_filter']}");
 
                     // TODO: use $this->ldap->search() here
-                    $res = @ldap_search($this->ldap->conn, $this->prop['search_base_dn'], $this->prop['search_filter'], array('uid'));
+                    $res = @ldap_search($this->ldap->conn, $this->prop['search_base_dn'], $this->prop['search_filter'], $search_attribs);
                     if ($res) {
                         if (($entry = ldap_first_entry($this->ldap->conn, $res))
                             && ($bind_dn = ldap_get_dn($this->ldap->conn, $entry))
@@ -294,6 +312,15 @@
                             $this->_debug("S: search returned dn: $bind_dn");
                             $dn = ldap_explode_dn($bind_dn, 1);
                             $replaces['%dn'] = $dn[0];
+
+                            // add more replacements from 'search_bind_attrib' config
+                            if ($search_bind_attrib) {
+                                $res = ldap_get_attributes($this->ldap->conn, $entry);
+                                foreach ($search_bind_attrib as $r => $attr) {
+                                    $sa_value = $res[$attr][0];
+                                    $replaces[$r] = $sa_value;
+                                }
+                            }
                         }
                     }
                     else {
@@ -318,6 +345,23 @@
                 $bind_dn              = strtr($bind_dn, $replaces);
                 $this->base_dn        = strtr($this->base_dn, $replaces);
                 $this->groups_base_dn = strtr($this->groups_base_dn, $replaces);
+
+                // replace placeholders in filter settings
+                if (!empty($this->prop['filter']))
+                    $this->prop['filter'] = strtr($this->prop['filter'], $replaces);
+                if (!empty($this->prop['groups']['filter']))
+                    $this->prop['groups']['filter'] = strtr($this->prop['groups']['filter'], $replaces);
+                if (!empty($this->prop['groups']['member_filter']))
+                    $this->prop['groups']['member_filter'] = strtr($this->prop['groups']['member_filter'], $replaces);
+
+                if (!empty($this->prop['group_filters'])) {
+                    foreach ($this->prop['group_filters'] as $i => $gf) {
+                        if (!empty($gf['base_dn']))
+                            $this->prop['group_filters'][$i]['base_dn'] = strtr($gf['base_dn'], $replaces);
+                        if (!empty($gf['filter']))
+                            $this->prop['group_filters'][$i]['filter'] = strtr($gf['filter'], $replaces);
+                    }
+                }
 
                 if (empty($bind_user)) {
                     $bind_user = $u;
@@ -522,9 +566,10 @@
     /**
      * Get all members of the given group
      *
-     * @param string Group DN
-     * @param array  Group entries (if called recursively)
-     * @return array Accumulated group members
+     * @param string  Group DN
+     * @param boolean Count only
+     * @param array   Group entries (if called recursively)
+     * @return array  Accumulated group members
      */
     function list_group_members($dn, $count = false, $entries = null)
     {
@@ -533,11 +578,13 @@
         // fetch group object
         if (empty($entries)) {
             $this->_debug("C: Read Group [dn: $dn]");
-            $entries = $this->ldap->read_entries($dn, '(objectClass=*)', array('dn','objectClass','member','uniqueMember','memberURL'));
+            $entries = $this->ldap->read_entries($dn, '(objectClass=*)', array_merge(array('dn','objectClass','memberURL'), array_values($this->prop['groups']['class_member_attr'])));
             if ($entries === false) {
                 return $group_members;
             }
         }
+
+        $class_member_map = $this->prop['groups']['class_member_attr'];
 
         for ($i=0; $i < $entries['count']; $i++) {
             $entry = $entries[$i];
@@ -546,19 +593,11 @@
                 continue;
 
             foreach ((array)$entry['objectclass'] as $objectclass) {
-                switch (strtolower($objectclass)) {
-                    case "group":
-                    case "groupofnames":
-                    case "kolabgroupofnames":
-                        $group_members = array_merge($group_members, $this->_list_group_members($dn, $entry, 'member', $count));
-                        break;
-                    case "groupofuniquenames":
-                    case "kolabgroupofuniquenames":
-                        $group_members = array_merge($group_members, $this->_list_group_members($dn, $entry, 'uniquemember', $count));
-                        break;
-                    case "groupofurls":
-                        $group_members = array_merge($group_members, $this->_list_group_memberurl($dn, $entry, $count));
-                        break;
+                if ($member_attr = $class_member_map[strtolower($objectclass)]) {
+                    $group_members = array_merge($group_members, $this->_list_group_members($dn, $entry, $member_attr, $count));
+                }
+                else if (!empty($entry['memberurl'])) {
+                    $group_members = array_merge($group_members, $this->_list_group_memberurl($dn, $entry, $count));
                 }
             }
 
@@ -575,6 +614,7 @@
      * @param string Group DN
      * @param array  Group entry
      * @param string Member attribute to use
+     * @param boolean Count only
      * @return array Accumulated group members
      */
     private function _list_group_members($dn, $entry, $attr, $count)
@@ -587,8 +627,7 @@
 
         // read these attributes for all members
         $attrib = $count ? array('dn','objectClass') : $this->prop['list_attributes'];
-        $attrib[] = 'member';
-        $attrib[] = 'uniqueMember';
+        $attrib = array_merge($attrib, array_values($this->prop['groups']['class_member_attr']));
         $attrib[] = 'memberURL';
 
         $filter = $this->prop['groups']['member_filter'] ? $this->prop['groups']['member_filter'] : '(objectclass=*)';
@@ -1869,18 +1908,12 @@
             $object_classes = $this->prop['groups']['object_classes'];
         }
         if (!empty($object_classes)) {
+            $class_member_map = $this->prop['groups']['class_member_attr'];
             foreach ((array)$object_classes as $oc) {
-                switch (strtolower($oc)) {
-                    case 'group':
-                    case 'groupofnames':
-                    case 'kolabgroupofnames':
-                        $member_attr = 'member';
-                        break;
-
-                    case 'groupofuniquenames':
-                    case 'kolabgroupofuniquenames':
-                        $member_attr = 'uniqueMember';
-                        break;
+                $oc = strtolower($oc);
+                if (!empty($class_member_map[$oc])) {
+                    $member_attr = $class_member_map[$oc];
+                    break;
                 }
             }
         }

--
Gitblit v1.9.1