Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : LDAP Functions : ldap_bind

ldap_bind

Bind to LDAP directory (PHP 4, PHP 5)
bool ldap_bind ( resource link_identifier [, string bind_rdn [, string bind_password]] )

Example 1111. Using LDAP Bind

<?php

// using ldap bind
$ldaprdn  = 'uname';     // ldap rdn or dn
$ldappass = 'password';  // associated password

// connect to ldap server
$ldapconn = ldap_connect("ldap.example.com")
   or die(
"Could not connect to LDAP server.");

if (
$ldapconn) {

   
// binding to ldap server
   
$ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);

   
// verify binding
   
if ($ldapbind) {
       echo
"LDAP bind successful...";
   } else {
       echo
"LDAP bind failed...";
   }

}

?>

Example 1112. Using LDAP Bind Anonymously

<?php

//using ldap bind anonymously

// connect to ldap server
$ldapconn = ldap_connect("ldap.example.com")
   or die(
"Could not connect to LDAP server.");

if (
$ldapconn) {

   
// binding anonymously
   
$ldapbind = ldap_bind($ldapconn);

   if (
$ldapbind) {
       echo
"LDAP bind anonymous successful...";
   } else {
       echo
"LDAP bind anonymous failed...";
   }

}

?>

Code Examples / Notes » ldap_bind

pete dot rowley

You should NOT attempt to bind with a made up password.  However small the chance, the chance remains that your code produces a valid password.  The correct behaviour is to test for an empty password, and if your application will only service authenticated users, not perform any more LDAP operations on behalf of the user - this also happens to be more efficient.

18-oct-2005 07:47

When using Active Directory 2003 (possibly also 2000) you can't search anonymously so you have to bind with a (known) user and password. Or else you will get an Search operations error. I also can confirm that an empty password bind succeeds! So test for an empty password first!
Some excellent information is found here:
http://www.scit.wlv.ac.uk/~jphb/sst/php/extra/ldap.html
http://www.scit.wlv.ac.uk/~jphb/sst/basics/ldap.html


darkstar_ae

This may be a security issue but after tinkering for hours with the below ldap auth function (edi01 at gmx dot at), I discovered that the ldap_bind function will return true if you enter a valid username AND a NULL value!
so if that function were to receive something like $username = 'someuser' and $password = '', it would return true. As long as it isn't a null value the function will work as expected. Might as well check if it is null or empty then.


baroque

This code sample shows how to connect and bind to eDirectory in PHP using LDAP for Netware.
<?php
$server='137.65.138.159';
$admin='cn=admin,o=novell';
$passwd='novell';
$ds=ldap_connect($server);  // assuming the LDAP server is on this host
if ($ds) {
   // bind with appropriate dn to give update access
   $r=ldap_bind($ds, $admin, $passwd);
if(!$r) die("ldap_bind failed
");
echo "ldap_bind success";
   ldap_close($ds);
} else {
   echo "Unable to connect to LDAP server";
}
?>


josh a.

The OpenLDAP libraries will return error 53 (Server unwilling to perform) when trying to re-bind to a non-anonymous account if you accidentally leave the password field blank. If you want to authenticate against a different field than the dn, you have to bind to the server twice. Your code may look like the following:
<?
function ldapLogin($uname, $pass, $base_dn, $fname, $server, $port){
   $ldc=@ldap_connect($server, $port);
   if (!$ldc) return ERROR_CODE;
   
   $bn='cn=anonymous-user,'.$base_dn;
   $pw='anonymous-pass';
   $lbind=@ldap_bind($ldc, $bn, $pw);
   if (!$lbind) return ERROR_CODE;
   
   
   $ureturn=@ldap_search($ldc, $base_dn, "($fname=$uname)", array('dn', 'givenName', 'sn', 'mail'));
   
   
   $uent=@ldap_first_entry($ldc, $ureturn);
   if (!$uent) return ERROR_CODE;
   
   $bn=@ldap_get_dn($ldc, $uent);
   
   //This line should use $pass rather than $password
   $lbind=@ldap_bind($ldc, $bn, $password);
   // Now you can find the error
   echo ldap_error($ltc);
   if ($lbind) return true; else return false;
?>
Hope this helps someone else running in to the same error.


kokheng

OpenLdap 2.1.x libraries support both LDAPv2 and LDAPv3. The problem lies with the slapd, the ldap server bundled with OpenLDAP.  It's default supported version is LDAPv3. One can set the "allow bind_v2" in the slapd.conf file, with this configured, the PHP ldap_set_option() is not required.

naujocke

One useful item when trying to bind to Novell's NDS LDAP servers.
If you are using NDS 8 and attempt to bind it will work with a partail context.
As an example if you full context is cn=user.ou=sales.ou=division.o=company
and you use as your authentication context cn=user.o=company it will work.
But you will be required to supply the full context to authenticate to an eDirectory based LDAP setup. Such as Netware 6 or eDirectory 8.5 or greater.
Also when using the wildcard * symbol in your object class. If you are not careful it is possible to dump the entire contents of your NDS tree into an array.


john dot hargrove

Note that you have to specify the protocol version prior to making a call to ldap_bind, when the server is expecting LDAP protocol version 3.  If you do not, you will receive a warning and fail to bind, such as:
ldap_bind(): Unable to bind to server: Protocol error
In order to avoid this, make this call:
<?php
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
?>
Where $ds is the result returned by ldap_connect(...);


nicolas van lancker

It seems that Active Directory stores information in UTF8 format.
I needed to utf8_encode() the username and password otherwise the bind failed when a user has accented characters in his password...


dedlfix

It doesn't make much sense to let die() the script in case of an error, otherwise to ask if there were no errors before proceeding the script, as the official examples do.
better:
<?php
ldap_bind(...) or die(...);
do_something();
?>
or even better (die() is quick but dirty)
<?php
if (!ldap_bind(...)) {
 error();
} else {
 do_something();
}
?>


wkaiser

If you do not want to bind as unixadmin or *manager (i. e., for authentication on web applications), the following code could be useful:
<?php
$ldaphost = "ldap.yourdomain.com";
/*for a SSL secured ldap_connect()
$ldaphost = "ldap.yourdomain.com"; */
$ldapport = 389;
$ds = ldap_connect($ldaphost, $ldapport)
or die("Could not connect to $ldaphost");
if ($ds) {
$username = "some_user";
$upasswd = "secret";
$binddn = "uid=$username,ou=people,dc=yourdomain,dc=com";
$ldapbind = ldap_bind($ds, $binddn, $upasswd);

if ($ldapbind) {
print "Congratulations! $some_user is authenticated.";}
else {
print "Nice try, kid. Better luck next time!";}}
?>


kenn

I want to point out that the line that reads
"$ldaprdn  = 'uname';"  
is a bit confusing. You need to ensure that you use the entire rootdn. for instance. your code should look more like this...
<?php
// using ldap bind *** NOTE the uname *****
$ldaprdn  = 'cn=root,dc=testserver,dc=com';    // ldap rdn or dn
$ldappass = 'secret';  // associated password
// connect to ldap server
$ldapconn = ldap_connect("ldap.testserver.com")
  or die("Could not connect to LDAP server.");
if (ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
  echo "Using LDAPv3";
} else {
  echo "Failed to set protocol version to 3";
}
if ($ldapconn) {
  // binding to ldap server
  $ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);
  // verify binding
  if ($ldapbind) {
      echo "LDAP bind successful...";
  } else {
      echo "LDAP bind failed...";
  }
}
?>


romerom

I ran into an issue trying to bind as "cn=manager,dc=example,dc=com".  I took the example kenn posted where he set LDAP_OPT_PROTOCOL_VERSION to "3" for the connection.  Once I set this, I was able to bind with my manager id.

elvisciousatrmci.net

I ran into a problem where I was getting a protocol error when I tried to bind.  I was able to connect fine and ldap commands worked fine from the command line.  
The problem turned out to be that openldap (v 2.1.5) was starting up in version 3 ldap mode, and php (4.2.3) expected it to be in version 2 mode.
To fix this use the ldap_set_option command to change the version that php expects.


owen

I am assuming that ldap_bind does a simple bind and that for other
types of bind, ldap_sasl_bind should be used.
Also, while the allow bind v2 solution will work with slapd, you really should
use ldap v3 if at all possible because of the security improvements and
better protocol definition.  LDAP v2 is largely deprecated at this point.
Hopefully the PHP default LDAP version will move to v3 soon.


get_your_gun

Hey
I was trying this all day and final noticed that when you use bind and authenticate. The user name needs to be as follows for it to work. I am using PHP V 4.03 so this might be different now but here is what I used and the auth worked.
<?php
$ldaphost = "ldap.what.at.greatnet.com";
$ldapport = 389;
$ds = ldap_connect($ldaphost, $ldapport)
or die("Could not connect to $ldaphost");
if ($ds)
{
$username = "johndoe@what.at.greatnet.com";
$upasswd = "pass";
$ldapbind = ldap_bind($ds, $username, $upasswd);
 
if ($ldapbind)
{print "Congratulations! $username is authenticated.";}
else
{print "Nice try, kid. Better luck next time!";}
}
?>


david dot marsh

had to do a bunch of research on this, but it does work, once config'd correctly.
using Apache/2.2.3 (Win32) mod_ssl/2.2.3 OpenSSL/0.9.8b
PHP PHP Version 5.1.5-dev
ldap_bind was getting "81 Can't contact LDAP server" which was really annoying, since the connection worked fine without "ldaps"
using:
$ldapconnect = @ldap_connect( $connection_string );
well, actually the bind was really the one failing...
$bind = ldap_bind($ldapconnect, $client, $this->objSecurityLogin->Password);
many attempts to determine until i smartened up and turned on the trace level:
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);
which must go before the connect!
found that on windows, you can't specifiy a quote in the ldap.conf:
i had:
TLS_REQCERT never
TLS_CACERT "C:\\Documents\\Tools\\Apache2\\conf\\ssl\\ad.pem"
which throws the error..
TLS: could not load verify locations (file:`"C:\Documents\Tools\Apache2\conf\ssl\ad.pem"',dir:`').
TLS: error:0200107B:system library:fopen:Unknown error .\crypto\bio\bss_file.c:122
TLS: error:2006D002:BIO routines:BIO_new_file:system lib .\crypto\bio\bss_file.c:127
TLS: error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib .\crypto\x509\by_file.c:274
ldap_err2string
changed to:
TLS_REQCERT never
TLS_CACERT C:\\Documents\\Tools\\Apache2\\conf\\ssl\\ad.pem
which cleans it up as:
TLS trace: SSL_connect:before/connect initialization
TLS trace: SSL_connect:SSLv2/v3 write client hello A
TLS trace: SSL_connect:SSLv3 read server hello A
TLS certificate verification: depth: 1, err: 0, subject: /DC=xxx/DC=yyy/CN=zzzz, issuer: /DC=abab/DC=yyy/CN=zzzz
TLS certificate verification: depth: 0, err: 0, subject: ......
so the moral to the story is even though PHP wants quotes in some windows config parms, it won't work if its in ldap.conf!


teemu

Example of connecting and searching AD
$con = ldap_connect('ad.domain.com');
ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($con, LDAP_OPT_REFERRALS, 0);
ldap_bind($con, 'user@DOMAIN.COM', 'clear password');
ldap_search($con, 'DC=domain,DC=com', '(uniqueMember=user)');


edi01

complete ldap authentication script:
function checkldapuser($username,$password,$ldap_server){
 if($connect=@ldap_connect($ldap_server)){ // if connected to ldap server
   if (ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3)) {
     echo "version 3
\n";
   } else {
     echo "version 2
\n";
   }
   echo "verification on '$ldap_server': ";
   // bind to ldap connection
   if(($bind=@ldap_bind($connect)) == false){
     print "bind:__FAILED__
\n";
     return false;
   }
   // search for user
   if (($res_id = ldap_search( $connect,
                               "dc=auto,dc=tuwien,dc=ac,dc=at",
                               "uid=$username")) == false) {
     print "failure: search in LDAP-tree failed
";
     return false;
   }
   if (ldap_count_entries($connect, $res_id) != 1) {
     print "failure: username $username found more than once
\n";
     return false;
   }
   if (( $entry_id = ldap_first_entry($connect, $res_id))== false) {
     print "failur: entry of searchresult couln't be fetched
\n";
     return false;
   }
   if (( $user_dn = ldap_get_dn($connect, $entry_id)) == false) {
     print "failure: user-dn coulnd't be fetched
\n";
     return false;
   }
   /* Authentifizierung des User */
   if (($link_id = ldap_bind($connect, $user_dn, $password)) == false) {
     print "failure: username, password didn't match: $user_dn
\n";
     return false;
   }
   return true;
   @ldap_close($connect);
 } else {                                  // no conection to ldap server
   echo "no connection to '$ldap_server'
\n";
 }
 echo "failed: ".ldap_error($connect)."
\n";
 @ldap_close($connect);
 return(false);
}//end function checkldapuser
Here a sample for using this function:
if (checkldapuser('myuser', 'secretpassword', 'ldap://link.to.ldap')) {
 echo "ACCESS GRANTED\n";
} else {
 echo "ACCESS DENIED\n";
}


phredbroughton

As noted before with the password, I have found that if either  of the valuse for user or password are blank, or as in my case a typo resulted in a blank user as it was an undefined variable, the ldap_bind() will just perform an anonymous bind and return true!
Shouldn't this detect the presence of the additional values and return an error? At least if the user or password is passed. If they are both blank I'm not sure what it should do.


jakob

As "john dot lewis at waldenweb dot com" correctly writes (and this is important to note and SHOULD be incorporated into the documentation as a warning - trying to bind with specific username and empty password will return TRUE.

tpiper

An example to help you authenticate against M$ Exchange, rather than use anonymous mode...
you will need to create an NT domain member (I've called it ldapquery) and give it search permission in the LDAP protocol settings in Exchange.
then:
$ds=ldap_connect ("<exchange server>");  
$r=@ldap_bind($ds,"cn=ldapquery, o=<your organisation>, c=<your country>, ","<the password for ldapquery account>");
we've tested this on Exchange 5.5SP3.


alex dot everett

A number of examples and implementations of authentication schemes which use LDAP simple binds to authenticate users fail to properly sanitize user-submitted data. This can allow for an anonymous user to authenticate to a web-based application as an existing user. Provided below is a brief description and example of how this vulnerability can arise. For more detailed information please visit the links at the bottom of this posting.
The bind operation of LDAP, as described in RFC 4513, provides a method which allows for authentication of users. For the Simple Authentication Method a user may use the anonymous authentication mechanism, the unauthenticated authentication mechanism, or the name/password authentication mechanism. The unauthenticated authentication mechanism is used when a client who desires to establish an anonymous authorization state passes a non-zero length distinguished name and a zero length password. Most LDAP servers either can be configured to allow this mechanism or allow it by default. Web-based applications which perform the simple bind operation with the client's credentials are at risk when an anonymous authorization state is established. This can occur when the web-based application passes a distinguished name and a zero length password to the LDAP server.
This is commonly encountered when no password is provided from the client to the web-based application. This situation is described in some of the postings found below. For this situation, the recommendations found in other postings is sufficient to prevent authentication bypass.
However, no prior postings at php.net describe a situation in which a client may pass a distinguished username and a password of non-zero length to the web-based application which results in an anonymous authorization state. Below is an example of this situation.
$dn="testuser";
$pass="\x00\x41";
if (empty($dn) or empty($pass)) { exit(); } //check for empty strings
//if (preg_match('/[^a-zA-Z]/',$dn) or preg_match('/[^a-zA-Z0-9\x20!@#$%^&*()]/',$pass)) { exit(); } //check for expected values (whitelisting)
//if (preg_match('/\x00/',$dn) or preg_match('/\x00/',$pass)) { exit(); } //check for null byte (blacklisting)
$ldapconn=ldap_connect("192.0.2.2") or die("Could not connect to LDAP server.");
if ($ldapconn) {
       ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
       $ldapbind=ldap_bind($ldapconn, $dn, $pass);
       if ($ldapbind) {
               echo("success");
       } else {
               echo("fail");
               }
       }
References:
http://security.okstate.edu


Change Language


Follow Navioo On Twitter
ldap_8859_to_t61
ldap_add
ldap_bind
ldap_close
ldap_compare
ldap_connect
ldap_count_entries
ldap_delete
ldap_dn2ufn
ldap_err2str
ldap_errno
ldap_error
ldap_explode_dn
ldap_first_attribute
ldap_first_entry
ldap_first_reference
ldap_free_result
ldap_get_attributes
ldap_get_dn
ldap_get_entries
ldap_get_option
ldap_get_values_len
ldap_get_values
ldap_list
ldap_mod_add
ldap_mod_del
ldap_mod_replace
ldap_modify
ldap_next_attribute
ldap_next_entry
ldap_next_reference
ldap_parse_reference
ldap_parse_result
ldap_read
ldap_rename
ldap_sasl_bind
ldap_search
ldap_set_option
ldap_set_rebind_proc
ldap_sort
ldap_start_tls
ldap_t61_to_8859
ldap_unbind
eXTReMe Tracker