6 define(
'ERR_INTERNAL', 1);
7 define(
'ERR_NO_USER', 2);
8 define(
'ERR_WRONG_PW', 3);
9 define(
'ERR_AS_DATA_INCONSIST', 4);
10 define(
'ERR_AS_INTERNAL', 5);
11 define(
'ERR_AS_ATTRIBUTE', 6);
14 if (!
defined(
'LDAP_OPT_DIAGNOSTIC_MESSAGE')) {
15 define(
'LDAP_OPT_DIAGNOSTIC_MESSAGE', 0x0032);
62 'host=\'' . $hostname .
63 '\', tls=
' . var_export($enable_tls, true) . 64 ', debug=
' . var_export($debug, true) . 65 ', timeout=
' . var_export($timeout, true) . 66 ', referrals=
' . var_export($referrals, true)); 69 * Set debug level before calling connect. Note that this passes 70 * NULL to ldap_set_option, which is an undocumented feature. 72 * OpenLDAP 2.x.x or Netscape Directory SDK x.x needed for this option. 74 if ($debug && !ldap_set_option(null, LDAP_OPT_DEBUG_LEVEL, 7)) { 75 SimpleSAML\Logger::warning('Library - LDAP
__construct(): Unable
to set debug level (LDAP_OPT_DEBUG_LEVEL)
to 7
'); 79 * Prepare a connection for to this LDAP server. Note that this function 80 * doesn't actually connect
to the server.
82 $this->ldap = @ldap_connect($hostname, $port);
83 if ($this->ldap ===
false) {
88 if (!@ldap_set_option($this->ldap, LDAP_OPT_PROTOCOL_VERSION, 3)) {
89 throw $this->
makeException(
'Library - LDAP __construct(): Failed to set LDAP Protocol version (LDAP_OPT_PROTOCOL_VERSION) to 3',
ERR_INTERNAL);
93 if (!@ldap_set_option($this->ldap, LDAP_OPT_REFERRALS, $referrals)) {
94 throw $this->
makeException(
'Library - LDAP __construct(): Failed to set LDAP Referrals (LDAP_OPT_REFERRALS) to '.$referrals,
ERR_INTERNAL);
101 if (!@ldap_set_option($this->ldap, LDAP_OPT_NETWORK_TIMEOUT,
$timeout)) {
104 if (!@ldap_set_option($this->ldap, LDAP_OPT_TIMELIMIT,
$timeout)) {
110 if (stripos($hostname,
"ldaps:") ===
false and $enable_tls) {
111 if (!@ldap_start_tls($this->ldap)) {
131 if (empty($this->ldap)) {
134 $errNo = @ldap_errno($this->ldap);
143 SimpleSAML\Logger::error($description); 147 case ERR_INTERNAL:// 1 - ExInternal 148 return new SimpleSAML_Error_Exception($description, $errNo); 149 case ERR_NO_USER:// 2 - ExUserNotFound 150 return new SimpleSAML_Error_UserNotFound($description, $errNo); 151 case ERR_WRONG_PW:// 3 - ExInvalidCredential 152 return new SimpleSAML_Error_InvalidCredential($description, $errNo); 153 case ERR_AS_DATA_INCONSIST:// 4 - ExAsDataInconsist 154 return new SimpleSAML_Error_AuthSource('ldap
', $description); 155 case ERR_AS_INTERNAL:// 5 - ExAsInternal 156 return new SimpleSAML_Error_AuthSource('ldap
', $description); 160 $description .= '; cause: \
'' . ldap_error($this->ldap) .
'\' (0x
' . dechex($errNo) . ')
'; 161 if (@ldap_get_option($this->ldap, LDAP_OPT_DIAGNOSTIC_MESSAGE, $extendedError) && !empty($extendedError)) { 162 $description .= '; additional: \
'' . $extendedError .
'\'';
206 private function search(
$base, $attribute, $value, $searchFilter = null)
209 $attribute = self::escape_filter_value($attribute,
false);
210 $value = self::escape_filter_value($value);
212 foreach ($attribute as $attr) {
213 $filter .=
'(' . $attr .
'=' . $value.
')';
215 $filter =
'(|' . $filter .
')';
218 if ($searchFilter != null) {
219 $filter =
"(&".$filter.
"".$searchFilter.
")";
225 $result = @ldap_search($this->ldap,
$base, $filter,
array(), 0, 0, $this->timeout);
227 throw $this->
makeException(
'Library - LDAP search(): Failed search on base \'' .
$base .
'\' for \
'' . $filter .
'\'');
231 $count = @ldap_count_entries($this->ldap,
$result);
232 if ($count ===
false) {
233 throw $this->
makeException(
'Library - LDAP search(): Failed to get number of entries returned');
234 } elseif ($count > 1) {
237 } elseif ($count === 0) {
239 throw $this->
makeException(
'Library - LDAP search(): Found no entries searching base \'' .
$base .
'\' for \
'' . $filter .
'\'',
ERR_NO_USER);
244 $entry = @ldap_first_entry($this->ldap,
$result);
245 if ($entry ===
false) {
246 throw $this->
makeException(
'Library - LDAP search(): Unable to retrieve result after searching base \'' .
$base .
'\' for \
'' . $filter .
'\'');
248 $dn = @ldap_get_dn($this->ldap, $entry);
250 throw $this->
makeException(
'Library - LDAP search(): Unable to get DN after searching base \'' .
$base .
'\' for \
'' . $filter .
'\'');
280 public function searchfordn(
$base, $attribute, $value, $allowZeroHits =
false, $searchFilter = null)
288 $result = $this->
search($current, $attribute, $value, $searchFilter);
301 if ($allowZeroHits) {
306 throw $this->
makeException(
'Library - LDAP searchfordn(): LDAP search returned zero entries for filter \'(' .
307 $attribute .
' = ' . $value .
')\' on base(s) \'(' . join(
' & ', $bases) .
')\'', 2);
333 if (is_array($filters)) {
334 foreach ($filters as $attribute => $value) {
335 $filter .=
"($attribute=$value)";
337 if (count($filters) > 1) {
338 $filter = ($and ?
'(&' :
'(|') . $filter .
')';
340 } elseif (is_string($filters)) {
345 if ($filter ==
'' || $filter ==
'(=)') {
350 $bases = (
array) $bases;
357 foreach ($bases as
$base) {
358 $result = @ldap_search($this->ldap, $base, $filter,
$attributes, 0, 0, $this->timeout);
359 if (
$result !==
false && @ldap_count_entries($this->ldap,
$result) > 0) {
367 'ldap:LdapConnection->search_manual : Failed to search LDAP using base(s) [' .
368 implode(
'; ', $bases) .
'] with filter [' . $filter .
']. LDAP error [' .
369 ldap_error($this->ldap) .
']' 371 } elseif (@ldap_count_entries($this->ldap,
$result) < 1) {
373 'ldap:LdapConnection->search_manual : No entries found in LDAP using base(s) [' .
374 implode(
'; ', $bases) .
'] with filter [' . $filter .
']',
383 'ldap:LdapConnection->search_manual : Unable to retrieve entries from search results' 389 $entry = $results[
$i];
392 for ($j = 0; $j < $entry[
'count']; $j++) {
394 $attribute = $entry[
$name];
397 for ($k = 0; $k < $attribute[
'count']; $k++) {
399 if (strtolower(
$name) ===
'jpegphoto' || strtolower(
$name) ===
'objectguid') {
400 $results[
$i][
$name][$k] = base64_encode($attribute[$k]);
407 unset($results[
'count']);
432 if ($sasl_args != null) {
433 if (!function_exists(
'ldap_sasl_bind')) {
434 $ex_msg =
'Library - missing SASL support';
443 $sasl_args[
'authc_id'],
444 $sasl_args[
'authz_id'],
445 $sasl_args[
'props']);
462 switch (ldap_errno($this->ldap)) {
478 throw $this->
makeException(
'Library - LDAP bind(): Bind failed with DN \'' . $dn .
'\'');
493 if (!@ldap_set_option($this->ldap, $option, $value)) {
495 'ldap:LdapConnection->setOption : Failed to set LDAP option [' .
496 $option .
'] with the value [' . $value .
'] error: ' . ldap_error($this->ldap),
503 'ldap:LdapConnection->setOption : Set the LDAP option [' .
504 $option .
'] with the value [' . $value .
']' 540 $result = @ldap_read($this->ldap, $dn,
'objectClass=*',
$attributes, 0, 0, $this->timeout);
542 throw $this->
makeException(
'Library - LDAP getAttributes(): Failed to get attributes from DN \'' . $dn .
'\'');
544 $entry = @ldap_first_entry($this->ldap,
$result);
545 if ($entry ===
false) {
546 throw $this->
makeException(
'Library - LDAP getAttributes(): Could not get first entry from DN \'' . $dn .
'\'');
548 $attributes = @ldap_get_attributes($this->ldap, $entry);
550 throw $this->
makeException(
'Library - LDAP getAttributes(): Could not get attributes of first entry from DN \'' . $dn .
'\'');
559 $attribute = $attributes[
$name];
563 for ($j = 0; $j < $attribute[
'count']; $j++) {
564 $value = $attribute[$j];
566 if (!empty($maxsize) && strlen($value) >= $maxsize) {
569 $name .
'\' exceeded maximum allowed
size by
' + ($maxsize - strlen($value))); 573 // Base64 encode binary attributes 574 if (strtolower($name) === 'jpegphoto
' || strtolower($name) === 'objectguid
') { 575 $values[] = base64_encode($value); 583 $result[$name] = $values; 588 SimpleSAML\Logger::debug(
'Library - LDAP getAttributes(): Found attributes \'(' . join(
',', array_keys(
$result)) .
')\'');
609 $username = addcslashes($username,
',+"\\<>;*');
611 if (isset(
$config[
'priv_user_dn'])) {
614 if (isset(
$config[
'dnpattern'])) {
615 $dn = str_replace(
'%username%', $username,
$config[
'dnpattern']);
624 SimpleSAML\Logger::info(
'Library - LDAP validate(): Failed to authenticate \''. $username .
'\' using DN \
'' . $dn .
'\'');
654 if (!is_array($values)) {
655 $values =
array($values);
658 foreach ($values as
$key => $val) {
660 $val = str_replace(
'\\',
'\5c', $val);
661 $val = str_replace(
'*',
'\2a', $val);
662 $val = str_replace(
'(',
'\28', $val);
663 $val = str_replace(
')',
'\29', $val);
666 $val = self::asc2hex32($val);
672 $values[
$key] = $val;
693 for (
$i = 0;
$i < strlen($string);
$i++) {
694 $char = substr($string,
$i, 1);
695 if (ord($char) < 32) {
696 $hex = dechex(ord($char));
697 if (strlen($hex) == 1) {
700 $string = str_replace($char,
'\\'.$hex, $string);
712 return preg_replace(
"/^dn:/",
"",
$authz_id);
716 return $this->
searchfordn($searchBase, $searchAttributes,
734 public function whoami($searchBase, $searchAttributes)
738 if (function_exists(
'ldap_exop_whoami')) {
739 if (version_compare(phpversion(),
'7',
'<')) {
740 if (ldap_exop_whoami($this->ldap,
$authz_id) !==
true) {
744 if ((
$authz_id = ldap_exop_whoami($this->ldap)) ===
false) {
754 if (!isset($dn) || ($dn ==
'')) {
searchfordn($base, $attribute, $value, $allowZeroHits=false, $searchFilter=null)
Search for a DN.
static asc2hex32($string)
Borrowed function from PEAR:LDAP.
searchformultiple($bases, $filters, $attributes=array(), $and=true, $escape=true)
This method was created specifically for the ldap:AttributeAddUsersGroups->searchActiveDirectory() me...
static arrayize($data, $index=0)
Put a non-array variable into an array.
search($base, $attribute, $value, $searchFilter=null)
Search for DN from a single base.
authzid_to_dn($searchBase, $searchAttributes, $authz_id)
Convert SASL authz_id into a DN.
setOption($option, $value)
Applies an LDAP option to the current connection.
static escape_filter_value($values=array(), $singleValue=true)
Borrowed function from PEAR:LDAP.
const ERR_AS_DATA_INCONSIST
Attribute-related utility methods.
validate($config, $username, $password=null)
Enter description here...
$authz_id
LDAP user: authz_id if SASL is in use, binding dn otherwise.
makeException($description, $type=null)
Convenience method to create an LDAPException as well as log the description.
Create styles array
The data for the language used.
getAttributes($dn, $attributes=null, $maxsize=null)
Search a given DN for attributes, and return the resulting associative array.
__construct($hostname, $enable_tls=true, $debug=false, $timeout=0, $port=389, $referrals=true)
Private constructor restricts instantiation to getInstance().
whoami($searchBase, $searchAttributes)
ldap_exop_whoami accessor, if available.
defined( 'APPLICATION_ENV')||define( 'APPLICATION_ENV'
bind($dn, $password, array $sasl_args=null)
Bind to LDAP with a specific DN and password.
const ERR_INTERNAL
Constants defining possible errors.
Set page orientation and size