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);
61 '\', tls=
'.var_export($enable_tls, true). 62 ', debug=
'.var_export($debug, true). 63 ', timeout=
'.var_export($timeout, true). 64 ', referrals=
'.var_export($referrals, true)); 67 * Set debug level before calling connect. Note that this passes 68 * NULL to ldap_set_option, which is an undocumented feature. 70 * OpenLDAP 2.x.x or Netscape Directory SDK x.x needed for this option. 72 if ($debug && !ldap_set_option(null, LDAP_OPT_DEBUG_LEVEL, 7)) { 73 SimpleSAML\Logger::warning('Library - LDAP
__construct(): Unable to
set debug level (LDAP_OPT_DEBUG_LEVEL) to 7
'); 77 * Prepare a connection for to this LDAP server. Note that this function 78 * doesn't actually connect to
the server.
80 $this->ldap = @ldap_connect($hostname, $port);
81 if ($this->ldap ===
false) {
86 if (!@ldap_set_option($this->ldap, LDAP_OPT_PROTOCOL_VERSION, 3)) {
87 throw $this->
makeException(
'Library - LDAP __construct(): Failed to set LDAP Protocol version (LDAP_OPT_PROTOCOL_VERSION) to 3',
ERR_INTERNAL);
91 if (!@ldap_set_option($this->ldap, LDAP_OPT_REFERRALS, $referrals)) {
92 throw $this->
makeException(
'Library - LDAP __construct(): Failed to set LDAP Referrals (LDAP_OPT_REFERRALS) to '.$referrals,
ERR_INTERNAL);
99 if (!@ldap_set_option($this->ldap, LDAP_OPT_NETWORK_TIMEOUT,
$timeout)) {
102 if (!@ldap_set_option($this->ldap, LDAP_OPT_TIMELIMIT,
$timeout)) {
108 if (stripos($hostname,
"ldaps:") ===
false && $enable_tls) {
109 if (!@ldap_start_tls($this->ldap)) {
129 if (empty($this->ldap)) {
132 $errNo = @ldap_errno($this->ldap);
141 SimpleSAML\Logger::error($description); 145 case ERR_INTERNAL:// 1 - ExInternal 146 return new SimpleSAML_Error_Exception($description, $errNo); 147 case ERR_NO_USER:// 2 - ExUserNotFound 148 return new SimpleSAML_Error_UserNotFound($description, $errNo); 149 case ERR_WRONG_PW:// 3 - ExInvalidCredential 150 return new SimpleSAML_Error_InvalidCredential($description, $errNo); 151 case ERR_AS_DATA_INCONSIST:// 4 - ExAsDataInconsist 152 return new SimpleSAML_Error_AuthSource('ldap
', $description); 153 case ERR_AS_INTERNAL:// 5 - ExAsInternal 154 return new SimpleSAML_Error_AuthSource('ldap
', $description); 158 $description .= '; cause: \
''.ldap_error($this->ldap).
'\' (0x
'.dechex($errNo).')
'; 159 if (@ldap_get_option($this->ldap, LDAP_OPT_DIAGNOSTIC_MESSAGE, $extendedError) && !empty($extendedError)) { 160 $description .= '; additional: \
''.$extendedError.
'\'';
208 private function search(
$base, $attribute, $value, $searchFilter = null, $scope =
"subtree")
211 $attribute = self::escape_filter_value($attribute,
false);
212 $value = self::escape_filter_value($value,
true);
214 foreach ($attribute as $attr) {
215 $filter .=
'('.$attr.
'='.$value.
')';
217 $filter =
'(|'.$filter.
')';
220 if ($searchFilter != null) {
221 $filter =
"(&".$filter.
"".$searchFilter.
")";
226 if ($scope ===
'base') {
227 $result = @ldap_read($this->ldap,
$base, $filter, array(), 0, 0, $this->timeout, LDAP_DEREF_NEVER);
228 }
else if ($scope ===
'onelevel') {
229 $result = @ldap_list($this->ldap,
$base, $filter, array(), 0, 0, $this->timeout, LDAP_DEREF_NEVER);
231 $result = @ldap_search($this->ldap,
$base, $filter, array(), 0, 0, $this->timeout, LDAP_DEREF_NEVER);
235 throw $this->
makeException(
'Library - LDAP search(): Failed search on base \''.
$base.
'\' for \
''.$filter.
'\'');
239 $count = @ldap_count_entries($this->ldap,
$result);
240 if ($count ===
false) {
241 throw $this->
makeException(
'Library - LDAP search(): Failed to get number of entries returned');
242 } elseif ($count > 1) {
245 } elseif ($count === 0) {
252 $entry = @ldap_first_entry($this->ldap,
$result);
253 if ($entry ===
false) {
254 throw $this->
makeException(
'Library - LDAP search(): Unable to retrieve result after searching base \''.
$base.
'\' for \
''.$filter.
'\'');
256 $dn = @ldap_get_dn($this->ldap, $entry);
258 throw $this->
makeException(
'Library - LDAP search(): Unable to get DN after searching base \''.
$base.
'\' for \
''.$filter.
'\'');
291 public function searchfordn(
$base, $attribute, $value, $allowZeroHits =
false, $searchFilter = null, $scope =
'subtree')
298 $result = $this->
search($current, $attribute, $value, $searchFilter, $scope);
311 if ($allowZeroHits) {
316 throw $this->
makeException(
'Library - LDAP searchfordn(): LDAP search returned zero entries for filter \'('.
317 join(
' | ', $attribute).
' = '.$value.
')\' on base(s) \'('.join(
' & ', $bases).
')\'', 2);
344 if (is_array($filters)) {
345 foreach ($filters as $attribute => $value) {
346 $filter .=
"($attribute=$value)";
348 if (count($filters) > 1) {
349 $filter = ($and ?
'(&' :
'(|').$filter.
')';
351 } elseif (is_string($filters)) {
356 if ($filter ==
'' || $filter ==
'(=)') {
361 $bases = (array) $bases;
368 foreach ($bases as
$base) {
369 if ($scope ===
'base') {
371 }
else if ($scope ===
'onelevel') {
374 $result = @ldap_search($this->ldap, $base, $filter,
$attributes, 0, 0, $this->timeout);
377 if (
$result !==
false && @ldap_count_entries($this->ldap,
$result) > 0) {
385 'ldap:LdapConnection->search_manual : Failed to search LDAP using base(s) ['.
386 implode(
'; ', $bases).
'] with filter ['.$filter.
']. LDAP error ['.
387 ldap_error($this->ldap).
']' 389 } elseif (@ldap_count_entries($this->ldap,
$result) < 1) {
391 'ldap:LdapConnection->search_manual : No entries found in LDAP using base(s) ['.
392 implode(
'; ', $bases).
'] with filter ['.$filter.
']',
401 'ldap:LdapConnection->search_manual : Unable to retrieve entries from search results' 407 $entry = $results[
$i];
410 for ($j = 0; $j < $entry[
'count']; $j++) {
412 $attribute = $entry[
$name];
415 for ($k = 0; $k < $attribute[
'count']; $k++) {
417 if (strtolower(
$name) ===
'jpegphoto' || strtolower(
$name) ===
'objectguid') {
418 $results[
$i][
$name][$k] = base64_encode($attribute[$k]);
425 unset($results[
'count']);
448 if ($sasl_args != null) {
449 if (!function_exists(
'ldap_sasl_bind')) {
450 $ex_msg =
'Library - missing SASL support';
456 $error = @ldap_sasl_bind(
462 $sasl_args[
'authc_id'],
463 $sasl_args[
'authz_id'],
469 $error = @ldap_bind($this->ldap, $dn,
$password);
472 if ($error ===
true) {
482 switch (ldap_errno($this->ldap)) {
498 throw $this->
makeException(
'Library - LDAP bind(): Bind failed with DN \''.$dn.
'\'');
513 if (!@ldap_set_option($this->ldap, $option, $value)) {
515 'ldap:LdapConnection->setOption : Failed to set LDAP option ['.
516 $option.
'] with the value ['.$value.
'] error: '.ldap_error($this->ldap),
523 'ldap:LdapConnection->setOption : Set the LDAP option ['.
524 $option.
'] with the value ['.$value.
']' 560 $result = @ldap_read($this->ldap, $dn,
'objectClass=*',
$attributes, 0, 0, $this->timeout);
562 throw $this->
makeException(
'Library - LDAP getAttributes(): Failed to get attributes from DN \''.$dn.
'\'');
564 $entry = @ldap_first_entry($this->ldap,
$result);
565 if ($entry ===
false) {
566 throw $this->
makeException(
'Library - LDAP getAttributes(): Could not get first entry from DN \''.$dn.
'\'');
568 $attributes = @ldap_get_attributes($this->ldap, $entry);
570 throw $this->
makeException(
'Library - LDAP getAttributes(): Could not get attributes of first entry from DN \''.$dn.
'\'');
578 $attribute = $attributes[
$name];
582 for ($j = 0; $j < $attribute[
'count']; $j++) {
583 $value = $attribute[$j];
585 if (!empty($maxsize) && strlen($value) > $maxsize) {
588 $name.
'\' exceeded maximum allowed
size by
'.(strlen($value) - $maxsize)); 592 // Base64 encode binary attributes 593 if (strtolower($name) === 'jpegphoto
' || strtolower($name) === 'objectguid
' || strtolower($name) === 'ms-ds-consistencyguid
') { 594 $values[] = base64_encode($value); 601 $result[$name] = $values; 605 SimpleSAML\Logger::debug(
'Library - LDAP getAttributes(): Found attributes \'('.join(
',', array_keys(
$result)).
')\'');
625 $username = addcslashes($username,
',+"\\<>;*');
627 if (isset(
$config[
'priv_user_dn'])) {
630 if (isset(
$config[
'dnpattern'])) {
631 $dn = str_replace(
'%username%', $username,
$config[
'dnpattern']);
640 SimpleSAML\Logger::info(
'Library - LDAP validate(): Failed to authenticate \''.$username.
'\' using DN \
''.$dn.
'\'');
673 $val = str_replace(
'\\',
'\5c', $val);
674 $val = str_replace(
'*',
'\2a', $val);
675 $val = str_replace(
'(',
'\28', $val);
676 $val = str_replace(
')',
'\29', $val);
679 $val = self::asc2hex32($val);
706 for (
$i = 0;
$i < strlen($string);
$i++) {
707 $char = substr($string,
$i, 1);
708 if (ord($char) < 32) {
709 $hex = dechex(ord($char));
710 if (strlen($hex) == 1) {
713 $string = str_replace($char,
'\\'.$hex, $string);
725 return preg_replace(
"/^dn:/",
"",
$authz_id);
750 public function whoami($searchBase, $searchAttributes)
753 if (function_exists(
'ldap_exop_whoami')) {
754 if (version_compare(phpversion(),
'7',
'<')) {
755 if (ldap_exop_whoami($this->ldap,
$authz_id) !==
true) {
759 if ((
$authz_id = ldap_exop_whoami($this->ldap)) ===
false) {
769 if (!isset($dn) || ($dn ==
'')) {
static asc2hex32($string)
Borrowed function from PEAR:LDAP.
static arrayize($data, $index=0)
Put a non-array variable into an array.
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.
searchfordn($base, $attribute, $value, $allowZeroHits=false, $searchFilter=null, $scope='subtree')
Search for a DN.
searchformultiple($bases, $filters, $attributes=array(), $and=true, $escape=true, $scope='subtree')
This method was created specifically for the ldap:AttributeAddUsersGroups->searchActiveDirectory() me...
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.
if(array_key_exists('yes', $_REQUEST)) $attributes
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.
bind($dn, $password, array $sasl_args=null)
Bind to LDAP with a specific DN and password.
const ERR_INTERNAL
Constants defining possible errors.
search($base, $attribute, $value, $searchFilter=null, $scope="subtree")
Search for DN from a single base.