LdapConnection: Properly handle multiple hosts if encryption is involved
refs #2645
This commit is contained in:
parent
7864450dde
commit
8d3e8b829f
|
@ -291,8 +291,8 @@ class LdapCapabilities
|
||||||
$result = @ldap_read($ds, '', (string) $connection->select()->from('*', $fields), $fields);
|
$result = @ldap_read($ds, '', (string) $connection->select()->from('*', $fields), $fields);
|
||||||
if (! $result) {
|
if (! $result) {
|
||||||
throw new LdapException(
|
throw new LdapException(
|
||||||
'Capability query failed (%s:%d): %s. Check if hostname and port of the'
|
'Capability query failed (%s; Default port: %d): %s. Check if hostname and port'
|
||||||
. ' ldap resource are correct and if anonymous access is permitted.',
|
. ' of the ldap resource are correct and if anonymous access is permitted.',
|
||||||
$connection->getHostname(),
|
$connection->getHostname(),
|
||||||
$connection->getPort(),
|
$connection->getPort(),
|
||||||
ldap_error($ds)
|
ldap_error($ds)
|
||||||
|
@ -302,7 +302,7 @@ class LdapCapabilities
|
||||||
$entry = ldap_first_entry($ds, $result);
|
$entry = ldap_first_entry($ds, $result);
|
||||||
if ($entry === false) {
|
if ($entry === false) {
|
||||||
throw new LdapException(
|
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->getHostname(),
|
||||||
$connection->getPort(),
|
$connection->getPort(),
|
||||||
ldap_error($ds)
|
ldap_error($ds)
|
||||||
|
|
|
@ -18,6 +18,7 @@ use Icinga\Data\Inspection;
|
||||||
use Icinga\Data\Selectable;
|
use Icinga\Data\Selectable;
|
||||||
use Icinga\Data\Sortable;
|
use Icinga\Data\Sortable;
|
||||||
use Icinga\Exception\ProgrammingError;
|
use Icinga\Exception\ProgrammingError;
|
||||||
|
use Icinga\Web\Url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulate LDAP connections and query creation
|
* Encapsulate LDAP connections and query creation
|
||||||
|
@ -316,11 +317,11 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
$success = @ldap_bind($ds, $this->bindDn, $this->bindPw);
|
$success = @ldap_bind($ds, $this->bindDn, $this->bindPw);
|
||||||
if (! $success) {
|
if (! $success) {
|
||||||
throw new LdapException(
|
throw new LdapException(
|
||||||
'LDAP connection to %s:%s (%s / %s) failed: %s',
|
'LDAP bind (%s / %s) to %s with default port %s failed: %s',
|
||||||
$this->hostname,
|
|
||||||
$this->port,
|
|
||||||
$this->bindDn,
|
$this->bindDn,
|
||||||
'***' /* $this->bindPw */,
|
'***' /* $this->bindPw */,
|
||||||
|
$this->hostname,
|
||||||
|
$this->port,
|
||||||
ldap_error($ds)
|
ldap_error($ds)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1155,8 +1156,19 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
$hostname = $this->hostname;
|
$hostname = $this->hostname;
|
||||||
if ($this->encryption === static::LDAPS) {
|
if ($this->encryption === static::LDAPS) {
|
||||||
$info->write('Connect using LDAPS');
|
$info->write('Connect using LDAPS');
|
||||||
|
$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;
|
$hostname = 'ldaps://' . $hostname;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$ds = ldap_connect($hostname, $this->port);
|
$ds = ldap_connect($hostname, $this->port);
|
||||||
|
|
||||||
|
@ -1209,12 +1221,27 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
$scope = $query->getScope();
|
$scope = $query->getScope();
|
||||||
|
|
||||||
if (Logger::getInstance()->getLevel() === Logger::DEBUG) {
|
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' : '';
|
$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) {
|
if ($this->bound) {
|
||||||
$bindParams = ' -D "' . $this->bindDn . '"' . ($this->bindPw ? ' -W' : '');
|
$bindParams = ' -D "' . $this->bindDn . '"' . ($this->bindPw ? ' -W' : '');
|
||||||
}
|
}
|
||||||
|
@ -1232,7 +1259,7 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
Logger::debug("Issueing LDAP search. Use '%s' to reproduce.", sprintf(
|
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',
|
'ldapsearch -P 3%s -H "%s"%s -b "%s" -s "%s" -z %u -l %u -a "%s"%s%s%s',
|
||||||
$starttlsParam,
|
$starttlsParam,
|
||||||
$ldapUrl,
|
implode(' ', $ldapUrls),
|
||||||
$bindParams,
|
$bindParams,
|
||||||
$baseDn,
|
$baseDn,
|
||||||
$scope,
|
$scope,
|
||||||
|
@ -1452,11 +1479,11 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
// Try a bind-command with the given user credentials, this must not fail
|
// Try a bind-command with the given user credentials, this must not fail
|
||||||
$success = @ldap_bind($ds, $this->bindDn, $this->bindPw);
|
$success = @ldap_bind($ds, $this->bindDn, $this->bindPw);
|
||||||
$msg = sprintf(
|
$msg = sprintf(
|
||||||
'LDAP bind to %s:%s (%s / %s)',
|
'LDAP bind (%s / %s) to %s with default port %s',
|
||||||
$this->hostname,
|
|
||||||
$this->port,
|
|
||||||
$this->bindDn,
|
$this->bindDn,
|
||||||
'***' /* $this->bindPw */
|
'***' /* $this->bindPw */,
|
||||||
|
$this->hostname,
|
||||||
|
$this->port
|
||||||
);
|
);
|
||||||
if (! $success) {
|
if (! $success) {
|
||||||
// ldap_error does not return any proper error messages in case of certificate errors. Connecting
|
// ldap_error does not return any proper error messages in case of certificate errors. Connecting
|
||||||
|
|
Loading…
Reference in New Issue