Skip to content

Commit

Permalink
LdapConnection: Properly handle multiple hosts if encryption is involved
Browse files Browse the repository at this point in the history
refs #2645
  • Loading branch information
nilmerg committed Feb 2, 2017
1 parent 7864450 commit 8d3e8b8
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 16 deletions.
6 changes: 3 additions & 3 deletions library/Icinga/Protocol/Ldap/LdapCapabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,8 @@ public static function discoverCapabilities(LdapConnection $connection)
$result = @ldap_read($ds, '', (string) $connection->select()->from('*', $fields), $fields);
if (! $result) {
throw new LdapException(
'Capability query failed (%s:%d): %s. Check if hostname and port of the'
. ' ldap resource are correct and if anonymous access is permitted.',
'Capability query failed (%s; Default port: %d): %s. Check if hostname and port'
. ' of the ldap resource are correct and if anonymous access is permitted.',
$connection->getHostname(),
$connection->getPort(),
ldap_error($ds)
Expand All @@ -302,7 +302,7 @@ public static function discoverCapabilities(LdapConnection $connection)
$entry = ldap_first_entry($ds, $result);
if ($entry === false) {
throw new LdapException(
'Capabilities not available (%s:%d): %s. Discovery of root DSE probably not permitted.',
'Capabilities not available (%s; Default port: %d): %s. Discovery of root DSE probably not permitted.',
$connection->getHostname(),
$connection->getPort(),
ldap_error($ds)
Expand Down
53 changes: 40 additions & 13 deletions library/Icinga/Protocol/Ldap/LdapConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Icinga\Data\Selectable;
use Icinga\Data\Sortable;
use Icinga\Exception\ProgrammingError;
use Icinga\Web\Url;

/**
* Encapsulate LDAP connections and query creation
Expand Down Expand Up @@ -316,11 +317,11 @@ public function bind()
$success = @ldap_bind($ds, $this->bindDn, $this->bindPw);
if (! $success) {
throw new LdapException(
'LDAP connection to %s:%s (%s / %s) failed: %s',
$this->hostname,
$this->port,
'LDAP bind (%s / %s) to %s with default port %s failed: %s',
$this->bindDn,
'***' /* $this->bindPw */,
$this->hostname,
$this->port,
ldap_error($ds)
);
}
Expand Down Expand Up @@ -1155,7 +1156,18 @@ protected function prepareNewConnection(Inspection $info = null)
$hostname = $this->hostname;
if ($this->encryption === static::LDAPS) {
$info->write('Connect using LDAPS');
$hostname = 'ldaps://' . $hostname;
$ldapUrls = explode(' ', $hostname);
if (count($ldapUrls) > 1) {
foreach ($ldapUrls as & $uri) {
if (strpos($uri, '://') === false) {
$uri = 'ldaps://' . $uri;
}
}

$hostname = implode(' ', $ldapUrls);
} else {
$hostname = 'ldaps://' . $hostname;
}
}

$ds = ldap_connect($hostname, $this->port);
Expand Down Expand Up @@ -1209,12 +1221,27 @@ public function ldapSearch(
$scope = $query->getScope();

if (Logger::getInstance()->getLevel() === Logger::DEBUG) {
// We're checking the level by ourself to avoid rendering the ldapsearch commandline for nothing
// We're checking the level by ourselves to avoid rendering the ldapsearch commandline for nothing
$starttlsParam = $this->encryption === static::STARTTLS ? ' -ZZ' : '';
$ldapUrl = ($this->encryption === static::LDAPS ? 'ldaps://' : 'ldap://')
. $this->hostname
. ($this->port ? ':' . $this->port : '');

$ldapUrls = array();
$defaultScheme = $this->encryption === static::LDAPS ? 'ldaps://' : 'ldap://';
foreach (explode(' ', $this->hostname) as $uri) {
$url = Url::fromPath($uri);
if (! $url->getScheme()) {
$uri = $defaultScheme . $uri . ($this->port ? ':' . $this->port : '');
} else {
if ($url->getPort() === null) {
$url->setPort($this->port);
}

$uri = $url->getAbsoluteUrl();
}

$ldapUrls[] = $uri;
}

$bindParams = '';
if ($this->bound) {
$bindParams = ' -D "' . $this->bindDn . '"' . ($this->bindPw ? ' -W' : '');
}
Expand All @@ -1232,7 +1259,7 @@ public function ldapSearch(
Logger::debug("Issueing LDAP search. Use '%s' to reproduce.", sprintf(
'ldapsearch -P 3%s -H "%s"%s -b "%s" -s "%s" -z %u -l %u -a "%s"%s%s%s',
$starttlsParam,
$ldapUrl,
implode(' ', $ldapUrls),
$bindParams,
$baseDn,
$scope,
Expand Down Expand Up @@ -1452,11 +1479,11 @@ public function inspect()
// Try a bind-command with the given user credentials, this must not fail
$success = @ldap_bind($ds, $this->bindDn, $this->bindPw);
$msg = sprintf(
'LDAP bind to %s:%s (%s / %s)',
$this->hostname,
$this->port,
'LDAP bind (%s / %s) to %s with default port %s',
$this->bindDn,
'***' /* $this->bindPw */
'***' /* $this->bindPw */,
$this->hostname,
$this->port
);
if (! $success) {
// ldap_error does not return any proper error messages in case of certificate errors. Connecting
Expand Down

0 comments on commit 8d3e8b8

Please sign in to comment.