From 1148c6e936c487c72740ba93ae430b42837e6999 Mon Sep 17 00:00:00 2001 From: alecpl Date: Thu, 30 Sep 2010 07:28:51 +0000 Subject: [PATCH] - Add option do bind for an individual LDAP address book (#1486997) --- CHANGELOG | 1 + config/main.inc.php.dist | 8 +++++++- program/include/rcube_ldap.php | 35 +++++++++++++++++++++++++++------- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f3f2b7963..6bf79cd98 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -9,6 +9,7 @@ CHANGELOG Roundcube Webmail - Fix HTML to plain text conversion doesn't handle citation blocks (#1486921) - Use custom sorting when SORT is disabled by IMAP admin (#1486959) - Allow setting some washtml options from plugin (#1486578) +- Add option do bind for an individual LDAP address book (#1486997) RELEASE 0.4.1 ------------- diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist index c0c2b0321..167fb40fd 100644 --- a/config/main.inc.php.dist +++ b/config/main.inc.php.dist @@ -407,16 +407,22 @@ $rcmail_config['ldap_public']['Verisign'] = array( // For example %n = mail.domain.tld, %d = domain.tld 'hosts' => array('directory.verisign.com'), 'port' => 389, - 'use_tls' => false, + 'use_tls' => false, 'user_specific' => false, // If true the base_dn, bind_dn and bind_pass default to the user's IMAP login. // %fu - The full username provided, assumes the username is an email // address, uses the username_domain value if not an email address. // %u - The username prior to the '@'. // %d - The domain name after the '@'. // %dc - The domain name hierarchal string e.g. "dc=test,dc=domain,dc=com" + // %dn - DN found by ldap search when search_filter/search_base_dn are used 'base_dn' => '', 'bind_dn' => '', 'bind_pass' => '', + // It's possible to bind for an individual address book + // The login name is used to search for the DN to bind with + 'search_base_dn' => '', + 'search_filter' => '', // e.g. '(&(objectClass=posixAccount)(uid=%u))' + 'writable' => false, // Indicates if we can write to the LDAP directory or not. // If writable is true then these fields need to be populated: // LDAP_Object_Classes, required_fields, LDAP_rdn diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php index 9d451df45..d5cc13257 100644 --- a/program/include/rcube_ldap.php +++ b/program/include/rcube_ldap.php @@ -4,7 +4,7 @@ | program/include/rcube_ldap.php | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2006-2009, Roundcube Dev. - Switzerland | + | Copyright (C) 2006-2010, Roundcube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -29,22 +29,22 @@ class rcube_ldap extends rcube_addressbook var $conn; var $prop = array(); var $fieldmap = array(); - + var $filter = ''; var $result = null; var $ldap_result = null; var $sort_col = ''; var $mail_domain = ''; var $debug = false; - + /** public properties */ var $primary_key = 'ID'; var $readonly = true; var $list_page = 1; var $page_size = 10; var $ready = false; - - + + /** * Object constructor * @@ -90,7 +90,7 @@ class rcube_ldap extends rcube_addressbook if (is_resource($this->conn)) return true; - + if (!is_array($this->prop['hosts'])) $this->prop['hosts'] = array($this->prop['hosts']); @@ -134,8 +134,29 @@ class rcube_ldap extends rcube_addressbook list($u, $d) = explode('@', $fu); $dc = 'dc='.strtr($d, array('.' => ',dc=')); // hierarchal domain string - // Replace the bind_dn and base_dn variables. $replaces = array('%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u); + + if ($this->prop['search_base_dn'] && $this->prop['search_filter']) { + // 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); + + $this->_debug("S: searching with base {$this->prop['search_base_dn']} for {$this->prop['search_filter']}"); + + $res = ldap_search($this->conn, $this->prop['search_base_dn'], $this->prop['search_filter'], array('uid')); + if ($res && ($entry = ldap_first_entry($this->conn, $res))) { + $bind_dn = ldap_get_dn($this->conn, $entry); + + $this->_debug("S: search returned dn: $bind_dn"); + + if ($bind_dn) { + $this->prop['bind_dn'] = $bind_dn; + $dn = ldap_explode_dn($bind_dn, 1); + $replaces['%dn'] = $dn[0]; + } + } + } + // Replace the bind_dn and base_dn variables. $this->prop['bind_dn'] = strtr($this->prop['bind_dn'], $replaces); $this->prop['base_dn'] = strtr($this->prop['base_dn'], $replaces); }