Skip to content

Commit

Permalink
Detect ldap default naming context
Browse files Browse the repository at this point in the history
Read the entries in the RootDTS of the given ldap server, to discover
its default naming context and capabilities

refs #6097
refs #6096
  • Loading branch information
majentsch committed Jun 6, 2014
1 parent 3d1a3e8 commit 305a025
Showing 1 changed file with 136 additions and 43 deletions.
179 changes: 136 additions & 43 deletions library/Icinga/Protocol/Ldap/Connection.php
Expand Up @@ -63,6 +63,7 @@ class Connection
protected $bind_pw;
protected $root_dn;
protected $count;

protected $ldap_extension = array(
'1.3.6.1.4.1.1466.20037' => 'STARTTLS',
// '1.3.6.1.4.1.4203.1.11.1' => '11.1', // PASSWORD_MODIFY
Expand Down Expand Up @@ -109,6 +110,8 @@ class Connection
protected $supports_v3 = false;
protected $supports_tls = false;

protected $capabilities;

/**
* Constructor
*
Expand Down Expand Up @@ -365,6 +368,7 @@ protected function prepareNewConnection()

$ds = ldap_connect($this->hostname, $this->port);
$cap = $this->discoverCapabilities($ds);
$this->capabilities = $cap;

if ($use_tls) {
if ($cap->starttls) {
Expand Down Expand Up @@ -399,7 +403,6 @@ protected function prepareNewConnection()

// TODO: remove this -> FORCING v3 for now
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);

Logger::warning('No LDAPv3 support detected');
}

Expand Down Expand Up @@ -429,6 +432,116 @@ protected function prepareTlsEnvironment()
}
}

protected function hasCapabilityStarTSL($cap)
{
$cap = $this->getExtensionCapabilities($cap);
return isset($cap['1.3.6.1.4.1.1466.20037']);
}

protected function hasCapabilityLdapV3($cap)
{
if ((is_string($cap->supportedLDAPVersion)
&& (int) $cap->supportedLDAPVersion === 3)
|| (is_array($cap->supportedLDAPVersion)
&& in_array(3, $cap->supportedLDAPVersion)
)) {
return true;
}
return false;
}

protected function getExtensionCapabilities($cap)
{
$extensions = array();
if (isset($cap->supportedExtension)) {
foreach ($cap->supportedExtension as $oid) {
if (array_key_exists($oid, $this->ldap_extension)) {
if ($this->ldap_extension[$oid] === 'STARTTLS') {
$extensions['1.3.6.1.4.1.1466.20037'] = $this->ldap_extension['1.3.6.1.4.1.1466.20037'];
}
}
}
}
return $extensions;
}

protected function getMsCapabilities($cap)
{
$ms = array();
foreach ($this->ms_capability as $name) {
$ms[$this->convName($name)] = false;
}

if (isset($cap->supportedCapabilities)) {
foreach ($cap->supportedCapabilities as $oid) {
if (array_key_exists($oid, $this->ms_capability)) {
$ms[$this->convName($this->ms_capability[$oid])] = true;
}
}
}
return (object)$ms;
}

private function convName($name)
{
$parts = explode('_', $name);
foreach ($parts as $i => $part) {
$parts[$i] = ucfirst(strtolower($part));
}
return implode('', $parts);
}

/**
* Get the capabilities of this ldap server
*
* @return stdClass An object, providing the flags 'ldapv3' and 'starttls' to indicate LdapV3 and StartTLS
* support and an additional property 'msCapabilities', containing all supported active directory capabilities.
*/
public function getCapabilities()
{
return $this->capabilities;
}

/**
* Get the default naming context of this ldap connection
*
* @return String|null the default naming context, or null when no contexts are available
*/
public function getDefaultNamingContext()
{
$cap = $this->capabilities;
if (isset($cap->defaultNamingContext)) {
return $cap->defaultNamingContext;
}
$namingContexts = $this->namingContexts($cap);
return empty($namingContexts) ? null : $namingContexts[0];
}

/**
* Fetch the namingContexts for this Ldap-Connection
*
* @return array the available naming contexts
*/
public function namingContexts()
{
$cap = $this->capabilities;
if (!isset($cap->namingContexts)) {
return array();
}
if (!is_array($cap->namingContexts)) {
return array($cap->namingContexts);
}
return $cap->namingContexts;
}

/**
* Discover the capabilities of the given ldap-server
*
* @param $ds The link identifier of the current ldap connection
*
* @return bool|object The capabilities or false if the server has none
* @throws Exception When the capability query fails
*/
protected function discoverCapabilities($ds)
{
$query = $this->select()->from(
Expand Down Expand Up @@ -471,69 +584,49 @@ protected function discoverCapabilities($ds)
$cap = (object) array(
'ldapv3' => false,
'starttls' => false,
'msCapabilities' => array()
);

if ($entry === false) {
// TODO: Is it OK to have no capabilities?
return $cap;
return false;
}
$ldapAttributes = ldap_get_attributes($ds, $entry);
$result = $this->cleanupAttributes(
$ldapAttributes
);
$result = $this->cleanupAttributes($ldapAttributes);
$cap->ldapv3 = $this->hasCapabilityLdapV3($result);
$cap->starttls = $this->hasCapabilityStarTSL($result);
$cap->msCapabilities = $this->getMsCapabilities($result);
$cap->namingContexts = $result->namingContexts;
/*
if (isset($result->dnsHostName)) {
ldap_set_option($ds, LDAP_OPT_HOST_NAME, $result->dnsHostName);
}
*/

if ((is_string($result->supportedLDAPVersion)
&& (int) $result->supportedLDAPVersion === 3)
|| (is_array($result->supportedLDAPVersion)
&& in_array(3, $result->supportedLDAPVersion)
)) {
$cap->ldapv3 = true;
}

if (isset($result->supportedCapabilities)) {
foreach ($result->supportedCapabilities as $oid) {
if (array_key_exists($oid, $this->ms_capability)) {
// echo $this->ms_capability[$oid] . "\n";
}
}
}
if (isset($result->supportedExtension)) {
foreach ($result->supportedExtension as $oid) {
if (array_key_exists($oid, $this->ldap_extension)) {
if ($this->ldap_extension[$oid] === 'STARTTLS') {
$cap->starttls = true;
}
}
}
}
return $cap;
}

public function connect()
public function connect($anonymous = false)
{
if ($this->ds !== null) {
return;
}
$this->ds = $this->prepareNewConnection();

$r = @ldap_bind($this->ds, $this->bind_dn, $this->bind_pw);

if (! $r) {
throw new \Exception(
sprintf(
'LDAP connection to %s:%s (%s / %s) failed: %s',
$this->hostname,
$this->port,
$this->bind_dn,
'***' /* $this->bind_pw */,
ldap_error($this->ds)
)
);
if (!$anonymous) {
$r = @ldap_bind($this->ds, $this->bind_dn, $this->bind_pw);
if (! $r) {
throw new \Exception(
sprintf(
'LDAP connection to %s:%s (%s / %s) failed: %s',
$this->hostname,
$this->port,
$this->bind_dn,
'***' /* $this->bind_pw */,
ldap_error($this->ds)
)
);
}
}
}

Expand Down

0 comments on commit 305a025

Please sign in to comment.