From 56651c15c8fb076b61c41c8e649dda6b9bf4f56f Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Wed, 04 May 2011 15:31:42 -0400
Subject: [PATCH] - Stop execution when LDAP addressbook is configured but PHP's ldap functions doesn't exists
---
program/include/rcube_ldap.php | 146 +++++++++++++++++++++++++++++++++++++++---------
1 files changed, 118 insertions(+), 28 deletions(-)
diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php
index 3cb4748..d9f5a10 100644
--- a/program/include/rcube_ldap.php
+++ b/program/include/rcube_ldap.php
@@ -49,6 +49,8 @@
protected $mail_domain = '';
protected $debug = false;
+ private $base_dn = '';
+ private $groups_base_dn = '';
private $group_cache = array();
private $group_members = array();
@@ -66,7 +68,7 @@
$this->prop = $p;
// check if groups are configured
- if (is_array($p['groups']))
+ if (is_array($p['groups']) and count($p['groups']))
$this->groups = true;
// fieldmap property is given
@@ -125,8 +127,9 @@
if (!function_exists('ldap_connect'))
raise_error(array('code' => 100, 'type' => 'ldap',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "No ldap support in this installation of PHP"), true);
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "No ldap support in this installation of PHP"),
+ true, true);
if (is_resource($this->conn))
return true;
@@ -162,11 +165,16 @@
{
$this->ready = true;
+ $bind_pass = $this->prop['bind_pass'];
+ $bind_user = $this->prop['bind_user'];
+ $bind_dn = $this->prop['bind_dn'];
+ $this->base_dn = $this->prop['base_dn'];
+
// User specific access, generate the proper values to use.
if ($this->prop['user_specific']) {
// No password set, use the session password
- if (empty($this->prop['bind_pass'])) {
- $this->prop['bind_pass'] = $RCMAIL->decrypt($_SESSION['password']);
+ if (empty($bind_pass)) {
+ $bind_pass = $RCMAIL->decrypt($_SESSION['password']);
}
// Get the pieces needed for variable replacement.
@@ -190,19 +198,31 @@
$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);
+ $bind_dn = strtr($bind_dn, $replaces);
+ $this->base_dn = strtr($this->base_dn, $replaces);
+
+ if (empty($bind_user)) {
+ $bind_user = $u;
+ }
}
- if (!empty($this->prop['bind_dn']) && !empty($this->prop['bind_pass']))
- $this->ready = $this->_bind($this->prop['bind_dn'], $this->prop['bind_pass']);
+ if (!empty($bind_pass)) {
+ if (!empty($bind_dn)) {
+ $this->ready = $this->_bind($bind_dn, $bind_pass);
+ }
+ else if (!empty($this->prop['auth_cid'])) {
+ $this->ready = $this->_sasl_bind($this->prop['auth_cid'], $bind_pass, $bind_user);
+ }
+ else {
+ $this->ready = $this->_sasl_bind($bind_user, $bind_pass);
+ }
+ }
}
else
raise_error(array('code' => 100, 'type' => 'ldap',
@@ -213,6 +233,58 @@
if ($this->prop['writable']) {
$this->readonly = false;
} // end if
+ }
+
+
+ /**
+ * Bind connection with (SASL-) user and password
+ *
+ * @param string $authc Authentication user
+ * @param string $pass Bind password
+ * @param string $authz Autorization user
+ *
+ * @return boolean True on success, False on error
+ */
+ private function _sasl_bind($authc, $pass, $authz=null)
+ {
+ if (!$this->conn) {
+ return false;
+ }
+
+ if (!function_exists('ldap_sasl_bind')) {
+ raise_error(array('code' => 100, 'type' => 'ldap',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Unable to bind: ldap_sasl_bind() not exists"),
+ true, true);
+ }
+
+ if (!empty($authz)) {
+ $authz = 'u:' . $authz;
+ }
+
+ if (!empty($this->prop['auth_method'])) {
+ $method = $this->prop['auth_method'];
+ }
+ else {
+ $method = 'DIGEST-MD5';
+ }
+
+ $this->_debug("C: Bind [mech: $method, authc: $authc, authz: $authz] [pass: $pass]");
+
+ if (ldap_sasl_bind($this->conn, NULL, $pass, $method, NULL, $authc, $authz)) {
+ $this->_debug("S: OK");
+ return true;
+ }
+
+ $this->_debug("S: ".ldap_error($this->conn));
+
+ raise_error(array(
+ 'code' => ldap_errno($this->conn), 'type' => 'ldap',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Bind failed for authcid=$authc ".ldap_error($this->conn)),
+ true);
+
+ return false;
}
@@ -238,11 +310,11 @@
$this->_debug("S: ".ldap_error($this->conn));
- $error = array(
- 'code' => ldap_errno($this->conn), 'type' => 'ldap',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Bind failed for dn=$dn: ".ldap_error($this->conn));
- raise_error($error,true);
+ raise_error(array(
+ 'code' => ldap_errno($this->conn), 'type' => 'ldap',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Bind failed for dn=$dn: ".ldap_error($this->conn)),
+ true);
return false;
}
@@ -574,7 +646,7 @@
}
// Build the new entries DN.
- $dn = $this->prop['LDAP_rdn'].'='.$this->_quote_string($newentry[$this->prop['LDAP_rdn']], true).','.$this->prop['base_dn'];
+ $dn = $this->prop['LDAP_rdn'].'='.$this->_quote_string($newentry[$this->prop['LDAP_rdn']], true).','.$this->base_dn;
$this->_debug("C: Add [dn: $dn]: ".print_r($newentry, true));
@@ -658,7 +730,7 @@
if ($replacedata[$this->prop['LDAP_rdn']]) {
$newdn = $this->prop['LDAP_rdn'].'='
.$this->_quote_string($replacedata[$this->prop['LDAP_rdn']], true)
- .','.$this->prop['base_dn'];
+ .','.$this->base_dn;
if ($dn != $newdn) {
$newrdn = $this->prop['LDAP_rdn'].'='
.$this->_quote_string($replacedata[$this->prop['LDAP_rdn']], true);
@@ -767,7 +839,7 @@
$this->_debug("C: Search [".$filter."]");
- if ($this->ldap_result = @$function($this->conn, $this->prop['base_dn'], $filter,
+ if ($this->ldap_result = @$function($this->conn, $this->base_dn, $filter,
array_values($this->fieldmap), 0, (int) $this->prop['sizelimit'], (int) $this->prop['timelimit']))
{
$this->_debug("S: ".ldap_count_entries($this->conn, $this->ldap_result)." record(s)");
@@ -902,11 +974,27 @@
*/
function list_groups($search = null)
{
+ global $RCMAIL;
+
if (!$this->groups)
return array();
- $base_dn = $this->prop['groups']['base_dn'];
- $filter = '(objectClass=groupOfNames)';
+ $this->groups_base_dn = ($this->prop['groups']['base_dn']) ?
+ $this->prop['groups']['base_dn'] : $this->base_dn;
+
+ // replace user specific dn
+ if ($this->prop['user_specific'])
+ {
+ $fu = $RCMAIL->user->get_username();
+ list($u, $d) = explode('@', $fu);
+ $dc = 'dc='.strtr($d, array('.' => ',dc='));
+ $replaces = array('%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u);
+
+ $this->groups_base_dn = strtr($this->groups_base_dn, $replaces);;
+ }
+
+ $base_dn = $this->groups_base_dn;
+ $filter = $this->prop['groups']['filter'];
$res = ldap_search($this->conn, $base_dn, $filter, array('cn','member'));
if ($res === false)
@@ -945,12 +1033,12 @@
if (!$this->group_cache)
$this->list_groups();
- $base_dn = $this->prop['groups']['base_dn'];
+ $base_dn = $this->groups_base_dn;
$new_dn = "cn=$group_name,$base_dn";
$new_gid = base64_encode($group_name);
$new_entry = array(
- 'objectClass' => array('top', 'groupOfNames'),
+ 'objectClass' => $this->prop['groups']['object_classes'],
'cn' => $group_name,
'member' => '',
);
@@ -976,7 +1064,7 @@
if (!$this->group_cache)
$this->list_groups();
- $base_dn = $this->prop['groups']['base_dn'];
+ $base_dn = $this->groups_base_dn;
$group_name = $this->group_cache[$group_id]['name'];
$del_dn = "cn=$group_name,$base_dn";
@@ -995,17 +1083,19 @@
*
* @param string Group identifier
* @param string New name to set for this group
+ * @param string New group identifier (if changed, otherwise don't set)
* @return boolean New name on success, false if no data was changed
*/
- function rename_group($group_id, $new_name)
+ function rename_group($group_id, $new_name, &$new_gid)
{
if (!$this->group_cache)
$this->list_groups();
- $base_dn = $this->prop['groups']['base_dn'];
+ $base_dn = $this->groups_base_dn;
$group_name = $this->group_cache[$group_id]['name'];
$old_dn = "cn=$group_name,$base_dn";
$new_rdn = "cn=$new_name";
+ $new_gid = base64_encode($new_name);
$res = ldap_rename($this->conn, $old_dn, $new_rdn, NULL, TRUE);
if ($res === false)
@@ -1029,7 +1119,7 @@
if (!$this->group_cache)
$this->list_groups();
- $base_dn = $this->prop['groups']['base_dn'];
+ $base_dn = $this->groups_base_dn;
$group_name = $this->group_cache[$group_id]['name'];
$group_dn = "cn=$group_name,$base_dn";
@@ -1059,7 +1149,7 @@
if (!$this->group_cache)
$this->list_groups();
- $base_dn = $this->prop['groups']['base_dn'];
+ $base_dn = $this->groups_base_dn;
$group_name = $this->group_cache[$group_id]['name'];
$group_dn = "cn=$group_name,$base_dn";
@@ -1090,7 +1180,7 @@
if (!$this->groups)
return array();
- $base_dn = $this->prop['groups']['base_dn'];
+ $base_dn = $this->groups_base_dn;
$contact_dn = base64_decode($contact_id);
$filter = "(member=$contact_dn)";
--
Gitblit v1.9.1