Added the possibility to configure all Ldap options for connection

This commit is contained in:
Charles Sarrazin 2016-05-08 21:21:13 +02:00
parent cab3f45a77
commit a8bae3175f
5 changed files with 175 additions and 29 deletions

View File

@ -24,22 +24,40 @@ abstract class AbstractConnection implements ConnectionInterface
public function __construct(array $config = array())
{
$resolver = new OptionsResolver();
$resolver->setDefaults(array(
'host' => null,
'port' => 389,
'version' => 3,
'useSsl' => false,
'useStartTls' => false,
'optReferrals' => false,
));
$resolver->setNormalizer('host', function (Options $options, $value) {
if ($value && $options['useSsl']) {
return 'ldaps://'.$value;
}
return $value;
});
$this->configureOptions($resolver);
$this->config = $resolver->resolve($config);
}
/**
* Configures the adapter's options.
*
* @param OptionsResolver $resolver An OptionsResolver instance
*/
protected function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'host' => 'localhost',
'version' => 3,
'connection_string' => null,
'encryption' => 'none',
'options' => array(),
));
$resolver->setDefault('port', function (Options $options) {
return 'ssl' === $options['encryption'] ? 636 : 389;
});
$resolver->setDefault('connection_string', function (Options $options) {
return sprintf('ldap%s://%s:%s', 'ssl' === $options['encryption'] ? 's' : '', $options['host'], $options['port']);
});
$resolver->setAllowedTypes('host', 'string');
$resolver->setAllowedTypes('port', 'numeric');
$resolver->setAllowedTypes('connection_string', 'string');
$resolver->setAllowedTypes('version', 'numeric');
$resolver->setAllowedValues('encryption', array('none', 'ssl', 'tls'));
$resolver->setAllowedTypes('options', 'array');
}
}

View File

@ -14,6 +14,8 @@ namespace Symfony\Component\Ldap\Adapter\ExtLdap;
use Symfony\Component\Ldap\Adapter\AbstractConnection;
use Symfony\Component\Ldap\Exception\ConnectionException;
use Symfony\Component\Ldap\Exception\LdapException;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @author Charles Sarrazin <charles@sarraz.in>
@ -67,24 +69,75 @@ class Connection extends AbstractConnection
return $this->connection;
}
public function setOption($name, $value)
{
if (!@ldap_set_option($this->connection, ConnectionOptions::getOption($name), $value)) {
throw new LdapException(sprintf('Could not set value "%s" for option "%s".', $value, $name));
}
}
public function getOption($name)
{
if (!@ldap_get_option($this->connection, ConnectionOptions::getOption($name), $ret)) {
throw new LdapException(sprintf('Could not retrieve value for option "%s".', $name));
}
return $ret;
}
protected function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefault('debug', false);
$resolver->setAllowedTypes('debug', 'bool');
$resolver->setDefault('referrals', false);
$resolver->setAllowedTypes('referrals', 'bool');
$resolver->setNormalizer('options', function (Options $options, $value) {
if (true === $options['debug']) {
$value['debug_level'] = 7;
}
if (!isset($value['protocol_version'])) {
$value['protocol_version'] = $options['version'];
}
if (!isset($value['referrals'])) {
$value['referrals'] = $options['referrals'];
}
return $value;
});
$resolver->setAllowedValues('options', function (array $values) {
foreach ($values as $name => $value) {
if (!ConnectionOptions::isOption($name)) {
return false;
}
}
return true;
});
}
private function connect()
{
if ($this->connection) {
return;
}
$host = $this->config['host'];
$this->connection = ldap_connect($this->config['connection_string']);
ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $this->config['version']);
ldap_set_option($this->connection, LDAP_OPT_REFERRALS, $this->config['optReferrals']);
$this->connection = ldap_connect($host, $this->config['port']);
foreach ($this->config['options'] as $name => $value) {
$this->setOption($name, $value);
}
if (false === $this->connection) {
throw new LdapException(sprintf('Could not connect to Ldap server: %s', ldap_error($this->connection)));
}
if ($this->config['useStartTls'] && false === ldap_start_tls($this->connection)) {
if ('tls' === $this->config['encryption'] && false === ldap_start_tls($this->connection)) {
throw new LdapException(sprintf('Could not initiate TLS connection: %s', ldap_error($this->connection)));
}
}

View File

@ -0,0 +1,78 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Ldap\Adapter\ExtLdap;
use Symfony\Component\Ldap\Exception\LdapException;
/**
* A class representing the Ldap extension's options, which can be used with
* ldap_set_option or ldap_get_option.
*
* @author Charles Sarrazin <charles@sarraz.in>
*
* @internal
*/
final class ConnectionOptions
{
const API_INFO = 0x00;
const DEREF = 0x02;
const SIZELIMIT = 0x03;
const TIMELIMIT = 0x04;
const REFERRALS = 0x08;
const RESTART = 0x09;
const PROTOCOL_VERSION = 0x11;
const SERVER_CONTROLS = 0x12;
const CLIENT_CONTROLS = 0x13;
const API_FEATURE_INFO = 0x15;
const HOST_NAME = 0x30;
const ERROR_NUMBER = 0x31;
const ERROR_STRING = 0x32;
const MATCHED_DN = 0x33;
const DEBUG_LEVEL = 0x5001;
const NETWORK_TIMEOUT = 0x5005;
const X_SASL_MECH = 0x6100;
const X_SASL_REALM = 0x6101;
const X_SASL_AUTHCID = 0x6102;
const X_SASL_AUTHZID = 0x6103;
public static function getOptionName($name)
{
return sprintf('%s::%s', self::class, strtoupper($name));
}
/**
* Fetches an option's corresponding constant value from an option name.
* The option name can either be in snake or camel case.
*
* @param string $name
*
* @return int
*
* @throws LdapException
*/
public static function getOption($name)
{
// Convert
$constantName = self::getOptionName($name);
if (!defined($constantName)) {
throw new LdapException(sprintf('Unknown option "%s"', $name));
}
return constant($constantName);
}
public static function isOption($name)
{
return defined(self::getOptionName($name));
}
}

View File

@ -35,7 +35,7 @@ class Query extends AbstractQuery
$con = $this->connection->getResource();
$this->connection = null;
if (null === $this->search) {
if (null === $this->search || false === $this->search) {
return;
}
@ -60,7 +60,7 @@ class Query extends AbstractQuery
$con = $this->connection->getResource();
$this->search = ldap_search(
$this->search = @ldap_search(
$con,
$this->dn,
$this->query,

View File

@ -9,9 +9,6 @@
* file that was distributed with this source code.
*/
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
namespace Symfony\Component\Ldap\Adapter;
use Symfony\Component\Ldap\Entry;
@ -21,10 +18,10 @@ use Symfony\Component\Ldap\Entry;
*/
interface QueryInterface
{
const DEREF_NEVER = 0;
const DEREF_SEARCHING = 1;
const DEREF_FINDING = 2;
const DEREF_ALWAYS = 3;
const DEREF_NEVER = 0x00;
const DEREF_SEARCHING = 0x01;
const DEREF_FINDING = 0x02;
const DEREF_ALWAYS = 0x03;
/**
* Executes a query and returns the list of Ldap entries.