Merge branch 'feature/ldap-get-naming-contexts-6097'

This commit is contained in:
Matthias Jentsch 2014-06-06 18:20:02 +02:00
commit 506cfe214b
1 changed files with 136 additions and 43 deletions

View File

@ -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
@ -109,6 +110,8 @@ class Connection
protected $supports_v3 = false;
protected $supports_tls = false;
protected $capabilities;
/**
* Constructor
*
@ -365,6 +368,7 @@ class Connection
$ds = ldap_connect($this->hostname, $this->port);
$cap = $this->discoverCapabilities($ds);
$this->capabilities = $cap;
if ($use_tls) {
if ($cap->starttls) {
@ -399,7 +403,6 @@ class Connection
// TODO: remove this -> FORCING v3 for now
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
Logger::warning('No LDAPv3 support detected');
}
@ -429,6 +432,116 @@ class Connection
}
}
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(
@ -471,69 +584,49 @@ class Connection
$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)
)
);
}
}
}