8000 Introducing the LDAP component · symfony/ldap@604c64b · GitHub
[go: up one dir, main page]

Skip to content

Commit 604c64b

Browse files
committed
Introducing the LDAP component
0 parents  commit 604c64b

10 files changed

+474
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor/
2+
composer.lock
3+
phpunit.xml

Exception/ConnectionException.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Ldap\Exception;
13+
14+
/**
15+
* ConnectionException is throw if binding to ldap can not be established.
16+
*
17+
* @author Grégoire Pineau <lyrixx@lyrixx.info>
18+
*/
19+
class ConnectionException extends \RuntimeException
20+
{
21+
}

Exception/LdapException.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Ldap\Exception;
13+
14+
/**
15+
* LdapException is throw if php ldap module is not loaded.
16+
*
17+
* @author Grégoire Pineau <lyrixx@lyrixx.info>
18+
*/
19+
class LdapException extends \RuntimeException
20+
{
21+
}

LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2004-2015 Fabien Potencier
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is furnished
8+
to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

LdapClient.php

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
<?php
2+
3+
namespace Symfony\Component\Ldap;
4+
5+
use Symfony\Component\Ldap\Exception\ConnectionException;
6+
use Symfony\Component\Ldap\Exception\LdapException;
7+
8+
/**
9+
* @author Grégoire Pineau <lyrixx@lyrixx.info>
10+
* @author Francis Besset <francis.besset@gmail.com>
11+
* @author Charles Sarrazin <charles@sarraz.in>
12+
*/
13+
class LdapClient implements LdapClientInterface
14+
{
15+
private $host;
16+
private $port;
17+
private $version;
18+
private $useSsl;
19+
private $useStartTls;
20+
private $optReferrals;
21+
private $connection< F438 /span>;
22+
private $charmaps;
23+
24+
/**
25+
* Constructor.
26+
*
27+
* @param string $host
28+
* @param int $port
29+
* @param int $version
30+
* @param bool $useSsl
31+
* @param bool $useStartTls
32+
* @param bool $optReferrals
33+
*/
34+
public function __construct($host = null, $port = 389, $version = 3, $useSsl = false, $useStartTls = false, $optReferrals = false)
35+
{
36+
if (!extension_loaded('ldap')) {
37+
throw new LdapException('The ldap module is needed.');
38+
}
39+
40+
$this->host = $host;
41+
$this->port = $port;
42+
$this->version = $version;
43+
$this->useSsl = (bool) $useSsl;
44+
$this->useStartTls = (bool) $useStartTls;
45+
$this->optReferrals = (bool) $optReferrals;
46+
}
47+
48+
public function __destruct()
49+
{
50+
$this->disconnect();
51+
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
public function bind($dn = null, $password = null)
57+
{
58+
if (!$this->connection) {
59+
$this->connect();
60+
}
61+
62+
if (false === @ldap_bind($this->connection, $dn, $password)) {
63+
throw new ConnectionException(ldap_error($this->connection));
64+
}
65+
}
66+
67+
/**
68+
* {@inheritdoc}
69+
*/
70+
public function find($dn, $query, $filter = '*')
71+
{
72+
if (!is_array($filter)) {
73+
$filter = array($filter);
74+
}
75+
76+
$search = ldap_search($this->connection, $dn, $query, $filter);
77+
$infos = ldap_get_entries($this->connection, $search);
78+
79+
if (0 === $infos['count']) {
80+
return;
81+
}
82+
83+
return $infos;
84+
}
85+
86+
/**
87+
* {@inheritdoc}
88+
*/
89+
public function escape($subject, $ignore = '', $flags = 0)
90+
{
91+
if (function_exists('ldap_escape')) {
92+
return ldap_escape($subject, $ignore, $flags);
93+
}
94+
95+
return $this->doEscape($subject, $ignore, $flags);
96+
}
97+
98+
private function connect()
99+
{
100+
if (!$this->connection) {
101+
$host = $this->host;
102+
103+
if ($this->useSsl) {
104+
$host = 'ldaps://'.$host;
105+
}
106+
107+
ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $this-> F987 ;version);
108+
ldap_set_option($this->connection, LDAP_OPT_REFERRALS, $this->optReferrals);
109+
110+
$this->connection = ldap_connect($host, $this->port);
111+
112+
if ($this->useStartTls) {
113+
ldap_start_tls($this->connection);
114+
}
115+
}
116+
}
117+
118+
private function disconnect()
119+
{
120+
if ($this->connection && is_resource($this->connection)) {
121+
ldap_unbind($this->connection);
122+
}
123+
124+
$this->connection = null;
125+
}
126+
127+
/**
128+
* Stub implementation of the {@link ldap_escape()} function of the ldap
129+
* extension.
130+
*
131+
* Escape strings for safe use in LDAP filters and DNs.
132+
*
133+
* @author Chris Wright <ldapi@daverandom.com>
134+
*
135+
* @param string $subject
136+
* @param string $ignore
137+
* @param int $flags
138+
*
139+
* @return string
140+
*
141+
* @see http://stackoverflow.com/a/8561604
142+
*/
143+
private function doEscape($subject, $ignore = '', $flags = 0)
144+
{
145+
$charMaps = $this->getCharmaps();
146+
147+
// Create the base char map to escape
148+
$flags = (int) $flags;
149+
$charMap = array();
150+
151+
if ($flags & self::LDAP_ESCAPE_FILTER) {
152+
$charMap += $charMaps[self::LDAP_ESCAPE_FILTER];
153+
}
154+
155+
if ($flags & self::LDAP_ESCAPE_DN) {
156+
$charMap += $charMaps[self::LDAP_ESCAPE_DN];
157+
}
158+
159+
if (!$charMap) {
160+
$charMap = $charMaps[0];
161+
}
162+
163+
// Remove any chars to ignore from the list
164+
$ignore = (string) $ignore;
165+
166+
for ($i = 0, $l = strlen($ignore); $i < $l; ++$i) {
167+
unset($charMap[$ignore[$i]]);
168+
}
169+
170+
// Do the main replacement
171+
$result = strtr($subject, $charMap);
172+
173+
// Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed
174+
if ($flags & self::LDAP_ESCAPE_DN) {
175+
if ($result[0] === ' ') {
176+
$result = '\\20'.substr($result, 1);
177+
}
178+
179+
if ($result[strlen($result) - 1] === ' ') {
180+
$result = substr($result, 0, -1).'\\20';
181+
}
182+
}
183+
184+
return $result;
185+
}
186+
187+
private function getCharmaps()
188+
{
189+
if (null !== $this->charmaps) {
190+
return $this->charmaps;
191+
}
192+
193+
$charMaps = array(
194+
self::LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"),
195+
self::LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'),
196+
);
197+
198+
$charMaps[0] = array();
199+
200+
for ($i = 0; $i < 256; ++$i) {
201+
$charMaps[0][chr($i)] = sprintf('\\%02x', $i);
202+
}
203+
204+
for ($i = 0, $l = count($charMaps[self::LDAP_ESCAPE_FILTER]); $i < $l; ++$i) {
205+
$chr = $charMaps[self::LDAP_ESCAPE_FILTER][$i];
206+
unset($charMaps[self::LDAP_ESCAPE_FILTER][$i]);
207+
$charMaps[self::LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr];
208+
}
209+
210+
for ($i = 0, $l = count($charMaps[self::LDAP_ESCAPE_DN]); $i < $l; ++$i) {
211+
$chr = $charMaps[self::LDAP_ESCAPE_DN][$i];
212+
unset($charMaps[self::LDAP_ESCAPE_DN][$i]);
213+
$charMaps[self::LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr];
214+
}
215+
216+
$this->charmaps = $charMaps;
217+
218+
return $this->charmaps;
219+
}
220+
}

LdapClientInterface.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Symfony\Component\Ldap;
4+
5+
use Symfony\Component\Ldap\Exception\ConnectionException;
6+
7+
/**
8+
* Ldap interface.
9+
*
10+
* @author Grégoire Pineau <lyrixx@lyrixx.info>
11+
* @author Charles Sarrazin <charles@sarraz.in>
12+
*/
13+
interface LdapClientInterface
14+
{
15+
const LDAP_ESCAPE_FILTER = 0x01;
16+
const LDAP_ESCAPE_DN = 0x02;
17+
18+
/**
19+
* Return a connection bound to the ldap.
20+
*
21+
* @param string $dn A LDAP dn
22+
* @param string $password A password
23+
*
24+
* @throws ConnectionException If dn / password could not be bound.
25+
*/
26+
public function bind($dn = null, $password = null);
27+
28+
/*
29+
* Find a username into ldap connection.
30+
*
31+
* @param string $dn
32+
* @param string $query
33+
* @param mixed $filter
34+
*
35+
* @return array|null
36+
*/
37+
public function find($dn, $query, $filter = '*');
38+
39+
/**
40+
* Escape a string for use in an LDAP filter or DN.
41+
*
42+
* @param string $subject
43+
* @param string $ignore
44+
* @param int $flags
45+
*
46+
* @return string
47+
*/
48+
public function escape($subject, $ignore = '', $flags = 0);
49+
}

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Ldap Component
2+
=============
3+
4+
A Ldap client for PHP on top of PHP's ldap extension.
5+
6+
This component also provides a stub for the missing
7+
`ldap_escape` function in PHP versions lower than 5.6.
8+
9+
Documentation
10+
-------------
11+
12+
The documentation for the component can be found [online] [0].
13+
14+
Resources
15+
---------
16+
17+
You can run the unit tests with the following command:
18+
19+
$ cd path/to/Symfony/Component/Ldap/
20+
$ composer install
21+
$ phpunit
22+
23+
[0]: https://symfony.com/doc/2.8/components/ldap.html

0 commit comments

Comments
 (0)
0