From 835977127137d5911b4bdcd6267e454ce07ce39c Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 31 May 2017 18:11:38 +0200 Subject: [PATCH] LdapCapabilities: discover NetBIOS name of an AD refs #2153 --- .../Config/UserBackend/LdapBackendForm.php | 31 +------- .../Icinga/Protocol/Ldap/LdapCapabilities.php | 77 ++++++++++++++++++- 2 files changed, 77 insertions(+), 31 deletions(-) diff --git a/application/forms/Config/UserBackend/LdapBackendForm.php b/application/forms/Config/UserBackend/LdapBackendForm.php index fec5f9691..dfebbea35 100644 --- a/application/forms/Config/UserBackend/LdapBackendForm.php +++ b/application/forms/Config/UserBackend/LdapBackendForm.php @@ -303,7 +303,7 @@ class LdapBackendForm extends Form $cap = LdapCapabilities::discoverCapabilities($connection); if ($cap->isActiveDirectory()) { - $netBiosName = $this->discoverADConfigOption($connection, 'nETBIOSName', $cap); + $netBiosName = $cap->getNetBiosName(); if ($netBiosName !== null) { $domains[] = $netBiosName; } @@ -336,33 +336,4 @@ class LdapBackendForm extends Form } } } - - /** - * Discover an AD-specific configuration option (e.g. nETBIOSName) - * - * @param LdapConnection $connection A connection to the AD - * @param string $option The option to discover - * @param LdapCapabilities|null $cap The AD's capabilities if already discovered - * - * @return string|null The value of the option - */ - protected function discoverADConfigOption(LdapConnection $connection, $option, LdapCapabilities $cap = null) - { - if ($cap === null) { - $cap = LdapCapabilities::discoverCapabilities($connection); - } - - $configurationNamingContext = $cap->getConfigurationNamingContext(); - $defaultNamingContext = $cap->getDefaultNamingContext(); - if (!($configurationNamingContext === null || $defaultNamingContext === null)) { - $value = $connection->select() - ->setBase('CN=Partitions,' . $configurationNamingContext) - ->from('*', array($option)) - ->where('nCName', $defaultNamingContext) - ->fetchOne(); - if ($value !== false) { - return $value; - } - } - } } diff --git a/library/Icinga/Protocol/Ldap/LdapCapabilities.php b/library/Icinga/Protocol/Ldap/LdapCapabilities.php index 52199be1b..998f7c5ce 100644 --- a/library/Icinga/Protocol/Ldap/LdapCapabilities.php +++ b/library/Icinga/Protocol/Ldap/LdapCapabilities.php @@ -90,7 +90,7 @@ class LdapCapabilities * * @var array */ - private $oids = array(); + private $oids; /** * Construct a new capability @@ -98,8 +98,19 @@ class LdapCapabilities * @param $attributes StdClass The attributes returned, may be null for guessing default capabilities */ public function __construct($attributes = null) + { + $this->setAttributes($attributes); + } + + /** + * Set the attributes and (re)build the OIDs + * + * @param $attributes StdClass The attributes returned, may be null for guessing default capabilities + */ + protected function setAttributes($attributes) { $this->attributes = $attributes; + $this->oids = array(); $keys = array('supportedControl', 'supportedExtension', 'supportedFeatures', 'supportedCapabilities'); foreach ($keys as $key) { @@ -215,6 +226,18 @@ class LdapCapabilities } } + /** + * Get the NetBIOS name + * + * @return string|null + */ + public function getNetBiosName() + { + if (isset($this->attributes->nETBIOSName)) { + return $this->attributes->nETBIOSName; + } + } + /** * Fetch the namingContexts * @@ -323,9 +346,61 @@ class LdapCapabilities } $cap = new LdapCapabilities($connection->cleanupAttributes(ldap_get_attributes($ds, $entry), $fields)); + $cap->discoverAdConfigOptions($connection); return $cap; } + /** + * Discover the AD-specific configuration options of the given LDAP server + * + * @param LdapConnection $connection The ldap connection to use + * + * @throws LdapException In case the configuration options query has failed + */ + protected function discoverAdConfigOptions(LdapConnection $connection) + { + if ($this->isActiveDirectory()) { + $configurationNamingContext = $this->getConfigurationNamingContext(); + $defaultNamingContext = $this->getDefaultNamingContext(); + if (!($configurationNamingContext === null || $defaultNamingContext === null)) { + $ds = $connection->bind()->getConnection(); + $adFields = array('nETBIOSName'); + $partitions = 'CN=Partitions,' . $configurationNamingContext; + + $result = @ldap_list( + $ds, + $partitions, + (string) $connection->select()->from('*', $adFields)->where('nCName', $defaultNamingContext), + $adFields + ); + if (! $result) { + throw new LdapException( + 'Configuration options query failed (%s:%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) + ); + } + + $entry = ldap_first_entry($ds, $result); + if ($entry === false) { + throw new LdapException( + 'Configuration options not available (%s:%d). Discovery of "' + . $partitions . '" probably not permitted.', + $connection->getHostname(), + $connection->getPort() + ); + } + + $this->setAttributes((object) array_merge( + (array) $this->attributes, + (array) $connection->cleanupAttributes(ldap_get_attributes($ds, $entry), $adFields) + )); + } + } + } + /** * Determine the active directory version using the available capabillities *