summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2011-10-19 09:56:06 +0000
committeralecpl <alec@alec.pl>2011-10-19 09:56:06 +0000
commitc041d57036d4a30730408c8fbba2d4e12778d2d5 (patch)
treea57e7031a251da9516ffc70357524d2d0631424f
parenta561cd35b8eb4c91e634a590774b8d18ed5b8a4a (diff)
- Added 'search_dn_default' variable in ldap config
- Better handling of situation when search for bind DN doesn't return data
-rw-r--r--config/main.inc.php.dist2
-rw-r--r--program/include/rcube_ldap.php146
2 files changed, 86 insertions, 62 deletions
diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist
index 9ce4440c6..3782374f3 100644
--- a/config/main.inc.php.dist
+++ b/config/main.inc.php.dist
@@ -535,6 +535,8 @@ $rcmail_config['ldap_public']['Verisign'] = array(
// The login name is used to search for the DN to bind with
'search_base_dn' => '',
'search_filter' => '', // e.g. '(&(objectClass=posixAccount)(uid=%u))'
+ // Default for %dn variable if search doesn't return DN value
+ 'search_dn_default' => '',
// Optional authentication identifier to be used as SASL authorization proxy
// bind_dn need to be empty
'auth_cid' => '',
diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php
index f33db0cf4..1f03e1500 100644
--- a/program/include/rcube_ldap.php
+++ b/program/include/rcube_ldap.php
@@ -165,12 +165,14 @@ class rcube_ldap extends rcube_addressbook
foreach ($this->prop['hosts'] as $host)
{
- $host = idn_to_ascii(rcube_parse_host($host));
- $this->_debug("C: Connect [$host".($this->prop['port'] ? ':'.$this->prop['port'] : '')."]");
+ $host = idn_to_ascii(rcube_parse_host($host));
+ $hostname = $host.($this->prop['port'] ? ':'.$this->prop['port'] : '');
+
+ $this->_debug("C: Connect [$hostname]");
if ($lc = @ldap_connect($host, $this->prop['port']))
{
- if ($this->prop['use_tls']===true)
+ if ($this->prop['use_tls'] === true)
if (!ldap_start_tls($lc))
continue;
@@ -184,85 +186,105 @@ class rcube_ldap extends rcube_addressbook
$this->_debug("S: NOT OK");
}
- if (is_resource($this->conn))
- {
- $this->ready = true;
+ // See if the directory is writeable.
+ if ($this->prop['writable']) {
+ $this->readonly = false;
+ }
+
+ if (!is_resource($this->conn)) {
+ raise_error(array('code' => 100, 'type' => 'ldap',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Could not connect to any LDAP server, last tried $hostname"), true);
- $bind_pass = $this->prop['bind_pass'];
- $bind_user = $this->prop['bind_user'];
- $bind_dn = $this->prop['bind_dn'];
+ return false;
+ }
- $this->base_dn = $this->prop['base_dn'];
- $this->groups_base_dn = ($this->prop['groups']['base_dn']) ?
- $this->prop['groups']['base_dn'] : $this->base_dn;
+ $bind_pass = $this->prop['bind_pass'];
+ $bind_user = $this->prop['bind_user'];
+ $bind_dn = $this->prop['bind_dn'];
- // User specific access, generate the proper values to use.
- if ($this->prop['user_specific']) {
- // No password set, use the session password
- if (empty($bind_pass)) {
- $bind_pass = $RCMAIL->decrypt($_SESSION['password']);
- }
+ $this->base_dn = $this->prop['base_dn'];
+ $this->groups_base_dn = ($this->prop['groups']['base_dn']) ?
+ $this->prop['groups']['base_dn'] : $this->base_dn;
- // Get the pieces needed for variable replacement.
- if ($fu = $RCMAIL->user->get_username())
- list($u, $d) = explode('@', $fu);
- else
- $d = $this->mail_domain;
+ // User specific access, generate the proper values to use.
+ if ($this->prop['user_specific']) {
+ // No password set, use the session password
+ if (empty($bind_pass)) {
+ $bind_pass = $RCMAIL->decrypt($_SESSION['password']);
+ }
- $dc = 'dc='.strtr($d, array('.' => ',dc=')); // hierarchal domain string
+ // Get the pieces needed for variable replacement.
+ if ($fu = $RCMAIL->user->get_username())
+ list($u, $d) = explode('@', $fu);
+ else
+ $d = $this->mail_domain;
- $replaces = array('%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u);
+ $dc = 'dc='.strtr($d, array('.' => ',dc=')); // hierarchal domain string
- 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);
+ $replaces = array('%dn' => '', '%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u);
- $this->_debug("S: searching with base {$this->prop['search_base_dn']} for {$this->prop['search_filter']}");
+ 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);
- $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: 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) {
+ if (($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) {
- $dn = ldap_explode_dn($bind_dn, 1);
- $replaces = array('%dn' => $dn[0]) + $replaces;
- }
+ $dn = ldap_explode_dn($bind_dn, 1);
+ $replaces['%dn'] = $dn[0];
}
}
- // Replace the bind_dn and base_dn variables.
- $bind_dn = strtr($bind_dn, $replaces);
- $this->base_dn = strtr($this->base_dn, $replaces);
- $this->groups_base_dn = strtr($this->groups_base_dn, $replaces);
+ else {
+ $this->_debug("S: ".ldap_error($this->conn));
+ }
- if (empty($bind_user)) {
- $bind_user = $u;
+ // DN not found
+ if (empty($replaces['%dn'])) {
+ if (!empty($this->prop['search_dn_default']))
+ $replaces['%dn'] = $this->prop['search_dn_default'];
+ else {
+ raise_error(array(
+ 'code' => 100, 'type' => 'ldap',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "DN not found using LDAP search."), true);
+ return false;
+ }
}
}
- 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);
- }
+ // Replace the bind_dn and base_dn variables.
+ $bind_dn = strtr($bind_dn, $replaces);
+ $this->base_dn = strtr($this->base_dn, $replaces);
+ $this->groups_base_dn = strtr($this->groups_base_dn, $replaces);
+
+ if (empty($bind_user)) {
+ $bind_user = $u;
}
}
- else
- raise_error(array('code' => 100, 'type' => 'ldap',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Could not connect to any LDAP server, last tried $host:{$this->prop[port]}"), true);
- // See if the directory is writeable.
- if ($this->prop['writable']) {
- $this->readonly = false;
- } // end if
+ if (empty($bind_pass)) {
+ $this->ready = true;
+ }
+ else {
+ 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);
+ }
+ }
+
+ return $this->ready;
}