Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
LDAP PHP Change Password Page
<?php
/**
* LDAP PHP Change Password Webpage
* @author: Matt Rude <http://mattrude.com>
* @website: http://technology.mattrude.com/2010/11/ldap-php-change-password-webpage/
*
*
* GNU GENERAL PUBLIC LICENSE
* Version 2, June 1991
*
* Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
$message = array();
$message_css = "";
function changePassword($user,$oldPassword,$newPassword,$newPasswordCnf){
global $message;
global $message_css;
$server = "localhost";
$dn = "ou=People,dc=example";
error_reporting(0);
ldap_connect($server);
$con = ldap_connect($server);
ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);
// bind anon and find user by uid
$user_search = ldap_search($con,$dn,"(|(uid=$user)(mail=$user))");
$user_get = ldap_get_entries($con, $user_search);
$user_entry = ldap_first_entry($con, $user_search);
$user_dn = ldap_get_dn($con, $user_entry);
$user_id = $user_get[0]["uid"][0];
$user_givenName = $user_get[0]["givenName"][0];
$user_search_arry = array( "*", "ou", "uid", "mail", "passwordRetryCount", "passwordhistory" );
$user_search_filter = "(|(uid=$user_id)(mail=$user))";
$user_search_opt = ldap_search($con,$user_dn,$user_search_filter,$user_search_arry);
$user_get_opt = ldap_get_entries($con, $user_search_opt);
$passwordRetryCount = $user_get_opt[0]["passwordRetryCount"][0];
$passwordhistory = $user_get_opt[0]["passwordhistory"][0];
//$message[] = "Username: " . $user_id;
//$message[] = "DN: " . $user_dn;
//$message[] = "Current Pass: " . $oldPassword;
//$message[] = "New Pass: " . $newPassword;
/* Start the testing */
if ( $passwordRetryCount == 3 ) {
$message[] = "Error E101 - Your Account is Locked Out!!!";
return false;
}
if (ldap_bind($con, $user_dn, $oldPassword) === false) {
$message[] = "Error E101 - Current Username or Password is wrong.";
return false;
}
if ($newPassword != $newPasswordCnf ) {
$message[] = "Error E102 - Your New passwords do not match!";
return false;
}
$encoded_newPassword = "{SHA}" . base64_encode( pack( "H*", sha1( $newPassword ) ) );
$history_arr = ldap_get_values($con,$user_dn,"passwordhistory");
if ( $history_arr ) {
$message[] = "Error E102 - Your new password matches one of the last 10 passwords that you used, you MUST come up with a new password.";
return false;
}
if (strlen($newPassword) < 8 ) {
$message[] = "Error E103 - Your new password is too short.<br/>Your password must be at least 8 characters long.";
return false;
}
if (!preg_match("/[0-9]/",$newPassword)) {
$message[] = "Error E104 - Your new password must contain at least one number.";
return false;
}
if (!preg_match("/[a-zA-Z]/",$newPassword)) {
$message[] = "Error E105 - Your new password must contain at least one letter.";
return false;
}
if (!preg_match("/[A-Z]/",$newPassword)) {
$message[] = "Error E106 - Your new password must contain at least one uppercase letter.";
return false;
}
if (!preg_match("/[a-z]/",$newPassword)) {
$message[] = "Error E107 - Your new password must contain at least one lowercase letter.";
return false;
}
if (!$user_get) {
$message[] = "Error E200 - Unable to connect to server, you may not change your password at this time, sorry.";
return false;
}
$auth_entry = ldap_first_entry($con, $user_search);
$mail_addresses = ldap_get_values($con, $auth_entry, "mail");
$given_names = ldap_get_values($con, $auth_entry, "givenName");
$password_history = ldap_get_values($con, $auth_entry, "passwordhistory");
$mail_address = $mail_addresses[0];
$first_name = $given_names[0];
/* And Finally, Change the password */
$entry = array();
$entry["userPassword"] = "$encoded_newPassword";
if (ldap_modify($con,$user_dn,$entry) === false){
$error = ldap_error($con);
$errno = ldap_errno($con);
$message[] = "E201 - Your password cannot be change, please contact the administrator.";
$message[] = "$errno - $error";
} else {
$message_css = "yes";
mail($mail_address,"Password change notice","Dear $first_name,
Your password on http://support.example.com for account $user_id was just changed. If you did not make this change, please contact support@example.com.
If you were the one who changed your password, you may disregard this message.
Thanks
-Matt");
$message[] = "The password for $user_id has been changed.<br/>An informational email as been sent to $mail_address.<br/>Your new password is now fully Active.";
}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Password Change Page</title>
<style type="text/css">
body { font-family: Verdana,Arial,Courier New; font-size: 0.7em; }
th { text-align: right; padding: 0.8em; }
#container { text-align: center; width: 500px; margin: 5% auto; }
.msg_yes { margin: 0 auto; text-align: center; color: green; background: #D4EAD4; border: 1px solid green; border-radius: 10px; margin: 2px; }
.msg_no { margin: 0 auto; text-align: center; color: red; background: #FFF0F0; border: 1px solid red; border-radius: 10px; margin: 2px; }
</style>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<div id="container">
<h2>Password Change Page</h2>
<p>Your new password must be 8 characters long or longer and have at least:<br/>
one capital letter, one lowercase letter, &amp; one number.<br/>
You must use a new password, your current password<br/>can not be the same as your new password.</p>
<?php
if (isset($_POST["submitted"])) {
changePassword($_POST['username'],$_POST['oldPassword'],$_POST['newPassword1'],$_POST['newPassword2']);
global $message_css;
if ($message_css == "yes") {
?><div class="msg_yes"><?php
} else {
?><div class="msg_no"><?php
$message[] = "Your password was not changed.";
}
foreach ( $message as $one ) { echo "<p>$one</p>"; }
?></div><?php
} ?>
<form action="<?php print $_SERVER['PHP_SELF']; ?>" name="passwordChange" method="post">
<table style="width: 400px; margin: 0 auto;">
<tr><th>Username or Email Address:</th><td><input name="username" type="text" size="20px" autocomplete="off" /></td></tr>
<tr><th>Current password:</th><td><input name="oldPassword" size="20px" type="password" /></td></tr>
<tr><th>New password:</th><td><input name="newPassword1" size="20px" type="password" /></td></tr>
<tr><th>New password (again):</th><td><input name="newPassword2" size="20px" type="password" /></td></tr>
<tr><td colspan="2" style="text-align: center;" >
<input name="submitted" type="submit" value="Change Password"/>
<button onclick="$('frm').action='changepassword.php';$('frm').submit();">Cancel</button>
</td></tr>
</table>
</form>
</div>
</body>
</html>
@kymair

This comment has been minimized.

Copy link

commented Jun 15, 2011

Thanks very much. It works well.

@sporty

This comment has been minimized.

Copy link

commented Feb 20, 2013

I wanted this!
Thank you very much! (from Japan)

@jevo

This comment has been minimized.

Copy link

commented Jun 3, 2013

works really good. Thx

@ukirfan

This comment has been minimized.

Copy link

commented Jul 3, 2013

I do not have anonymous binding feature , how to avoid Error E200 . Thanks

@vincentkersten

This comment has been minimized.

Copy link

commented Jan 3, 2014

Saved me :) Does the works as it should, thank you very much!

@souzavirginio

This comment has been minimized.

Copy link

commented Apr 14, 2014

E201 - Your password cannot be change, please contact the administrator. Can you help me ?

@hellracer

This comment has been minimized.

Copy link

commented Jul 30, 2014

E201 it means that your server might require a rootdn to change some ldap attributes. to do this specify your root dn by inserting this two variables in changePassword function

$rootdn = "cn=Manager,dc=mycompany,dc=com";
$rootpwd = "mysecretkeys";

approximately at line 93 insert the following code

/* And Finally, Change the password */
$entry = array();
$entry["userPassword"] = "$encoded_newPassword";
$r = ldap_bind($con,$rootdn,$rootpwd);

at line 95 modify the conditional statement into this

if ($r = ldap_modify($con,$user_dn,$entry) === false){
$error = ldap_error($con);
$errno = ldap_errno($con);
$message[] = "E201 - Your password cannot be change, please contact the administrator.";
$message[] = "$errno - $error";
}

I hope this helps

@shtrom

This comment has been minimized.

Copy link

commented Jul 19, 2015

Neat. Thanks!

@mmorejon

This comment has been minimized.

Copy link

commented Aug 24, 2015

Very useful!!!!! Thanks.

@narayan8291

This comment has been minimized.

Copy link

commented Sep 10, 2015

I keep getting the error "Error E101 - Current Username or Password is wrong." even when my username and password are correct.
When I commented the line error_reporting(0), I get a warning in line 34 and it says "Warning: ldap_search(): Search: Bad search filter". For my ldap instance, I have modified line 34 to "$user_search = ldap_search($con,$dn,"(|(User Name=$user)(Email=$email_user))");" and I supply the value for $email_user to the function.

Am I missing something? Any suggestions would be greatly appreciated. Thanks

@mmeinert

This comment has been minimized.

Copy link

commented Oct 5, 2015

Worked directly, this is timesaving thanks

@CosmeFC

This comment has been minimized.

Copy link

commented Nov 12, 2015

Same problem with narayan8291.
I am using CentOS 7.

@Delvius

This comment has been minimized.

Copy link

commented Nov 17, 2015

Are you sure "userPassword" is the correct attribute to change password ? I found many samples with the "unicodePwd" attribute ?
What's the difference between these two fields ?

@jult

This comment has been minimized.

Copy link

commented Feb 10, 2016

Could you add/insert Samba password linkage to this fine php? Something nicked from this would be OK by me:

function ntpasswd($Input) {
  // Convert the password from UTF8 to UTF16 (little endian)
  $Input=iconv('UTF-8','UTF-16LE',$Input);

  $MD4Hash=hash('md4',$Input);

  // Make it uppercase, not necessary, but it's common to do so with NTLM hashes
  $NTLMHash=strtoupper($MD4Hash);

  // Return the result
  return($NTLMHash);
}

function checknt($passwd, $hash){
        return (ntpasswd($passwd) === strtoupper($hash));
}

function sshapasswd($input){
        mt_srand((double)(microtime(true) ^ posix_getpid()));
        $salt = pack("CCCC", mt_rand(0,255), mt_rand(0,255), mt_rand(0,255), mt_rand(0,255));

        $passwd_sha1 = sha1($input . $salt, TRUE);

        $result = '{SSHA}' . base64_encode($passwd_sha1 . $salt);

        if (!checkssha($result, $input))
                return null;
        else
                return $result;

}

function checkssha ($input, $passwd){
        $orig = base64_decode(substr($input, 6));
        $hash = substr($orig, 0, 20);
        $salt = substr($orig, 20, 4);

        if (sha1($passwd . $salt, TRUE) == $hash){
                return TRUE;
        } else {
                return FALSE;
        }
}

function check_ldap_passwd($username, $passwd){
        global $ldap, $ldap_host, $ldap_base;

        # Assume uid=username,searchbase
        $ldap = ldap_connect($ldap_host);
        ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
        return @ldap_bind($ldap, 'uid=' . $username . ',' . $ldap_base, $passwd);
}

function change_ldap_passwd($username, $passwd, $new){
        global $ldap, $ldap_base;

        if ($ldap == null){
                // Odd, this should've been done already.
                if(!check_ldap_passwd($username, $passwd))
                        return NULL;
        }

        // Get the account's info
        $res = ldap_search($ldap, 'uid=' . $username . ',' . $ldap_base, '(objectClass=posixAccount)');
        if (ldap_count_entries($ldap, $res) > 1){
                die('Something is wrong- more than one search result.');
        } else if (ldap_count_entries($ldap, $res) == 0){
                die('Something is wrong- You logged in but I can\'t find you anymore.');
        }

        $entry = ldap_first_entry($ldap, $res);
        $userdn = ldap_get_dn($ldap, $entry);
        $obj = null;

        // Does this account already have objectClass: sambaSamAccount?
        if(!ldap_compare($ldap, $userdn, 'objectClass', 'sambaSamAccount')){
                // Have to get other objectClass values, too.
                $object = ldap_get_attributes($ldap, $entry);
                unset($object['objectClass']['count']);
                $obj['objectClass'] = $object['objectClass'];
                $obj['objectClass'][] = 'sambaSamAccount';
        }

        $now = time();
        $obj['userPassword'] = sshapasswd($new);
        $obj['sambaNTPassword'] = ntpasswd($new);
        $obj['sambaPwdLastSet'] = "$now";


        return @ldap_modify($ldap, $userdn, $obj);
}

function change_ldap_passwd_admin($username, $passwd){
        global $ldap, $ldap_base, $ldap_host, $admin_dn, $admin_pw;

        if ($ldap == null){
                // Odd, this should've been done already.
                $ldap = ldap_connect($ldap_host);
                ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);

                if (!@ldap_bind($ldap, $admin_dn, $admin_pw)){
                        my_die("<!-- check_ldap_user -->An error occurred.");
                }
        }


        // Get the account's info
        $res = ldap_search($ldap, 'uid=' . $username . ',' . $ldap_base, '(objectClass=posixAccount)');
        if (ldap_count_entries($ldap, $res) > 1){
                die('Something is wrong- more than one search result.');
        } else if (ldap_count_entries($ldap, $res) == 0){
                die('Something is wrong- You logged in but I can\'t find you anymore.');
        }

        $entry = ldap_first_entry($ldap, $res);
        $userdn = ldap_get_dn($ldap, $entry);
        $obj = null;

        // Does this account already have objectClass: sambaSamAccount?
        if(!ldap_compare($ldap, $userdn, 'objectClass', 'sambaSamAccount')){
                // Have to get other objectClass values, too.
                $object = ldap_get_attributes($ldap, $entry);
                unset($object['objectClass']['count']);
                $obj['objectClass'] = $object['objectClass'];
                $obj['objectClass'][] = 'sambaSamAccount';
        }

        $obj['userPassword'] = sshapasswd($passwd);
        $obj['sambaNTPassword'] = ntpasswd($passwd);

        echo "ssh: " . $obj['userPassword'] . " nt: " . $obj['sambaNTPassword'];

        return @ldap_modify($ldap, $userdn, $obj);
}

function check_nt_passwd($username, $password){
        global $ldap, $ldap_base, $ldap_host, $admin_dn, $admin_pw;

        $ldap = ldap_connect($ldap_host);
        ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);

        if (!@ldap_bind($ldap, $admin_dn, $admin_pw)){
                my_die("<!-- check_nt_password -->An error occurred.");
        }

        $res = ldap_search($ldap, 'uid=' . $username . ',' . $ldap_base, '(objectClass=posixAccount)');
        if (ldap_count_entries($ldap, $res) > 1){
                die('Something is wrong- more than one search result.');
        } else if (ldap_count_entries($ldap, $res) == 0){
                die('Something is wrong- You logged in but I can\'t find you anymore.');
        }

        $entry = ldap_first_entry($ldap, $res);
        $userdn = ldap_get_dn($ldap, $entry);
        $object = ldap_get_attributes($ldap, $entry);
        if (isset($object['sambaNTPassword'])){
                return checknt($password, $object['sambaNTPassword'][0]);
        } else {
                return null;
        }
}

function check_ldap_user($username){
        global $ldap, $ldap_base, $ldap_host, $admin_dn, $admin_pw;

        if ($ldap == null){
                // Odd, this should've been done already.
                $ldap = ldap_connect($ldap_host);
                ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);

                if (!@ldap_bind($ldap, $admin_dn, $admin_pw)){
                        my_die("<!-- check_ldap_user -->An error occurred.");
                }
        }

        $res = @ldap_search($ldap, 'uid=' . $username . ',' . $ldap_base, '(objectClass=posixAccount)');
        return @ldap_count_entries($ldap, $res) == 1;

}
@joergmschulz

This comment has been minimized.

Copy link

commented Apr 23, 2016

@SatheeshKumarG

This comment has been minimized.

Copy link

commented Jun 10, 2016

Hi,

I have tried running the above code on my box (was trying to change password), every time I get the below error.
Can you please help me to get it fixeD?

"Error E200 - Unable to connect to server, you may not change your password at this time, sorry.

Your password was not changed.

Thanks!

@prkulkar

This comment has been minimized.

Copy link

commented Jun 22, 2016

Hi.

I am running this script over SSL. first time i change the password it works fine. but i try to change it again it fails. saying user name or password is incorrect. also after changing the password i am not able to login to my application. can you please help here

@hotorodjeremy

This comment has been minimized.

Copy link

commented Jun 29, 2016

Hi I am getting an error when trying to change a password using this script.
I have added the ldap_bind functions and still get error
E201 - Your password cannot be change, please contact the administrator.

53 - Server is unwilling to perform

Your password was not changed.

`<?php

/**

  •          GNU GENERAL PUBLIC LICENSE
    
  •             Version 2, June 1991
    
  • Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
  • 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  • Everyone is permitted to copy and distribute verbatim copies
  • of this license document, but changing it is not allowed.
    */

$message = array();
$message_css = "";

function changePassword($user,$oldPassword,$newPassword,$newPasswordCnf){
global $message;
global $message_css;

$server = "ldaps://cobdc3.cob.lcl";
$ldapsport = 636;
$user = "account@cob.lcl";
$password = "accountpassword";
$dn = "ou=People,dc=example";
error_reporting(0);
ldap_connect($server);
$con = ldap_connect($server, $ldapsport)
or die("Could not connect to $ldaphost");
ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);
if ($con){
echo "Connected to LDAP on Secure Port Sucessfully!";
$ldap_bind = ldap_bind($con, $user, $password);
}
if ($ldap_bind){
echo "

LDAP bound Sucessfully!

";
}
// bind anon and find user by uid
$user_search = ldap_search($con,$dn,"(|(uid=$user)(mail=$user))");
$user_get = ldap_get_entries($con, $user_search);
$user_entry = ldap_first_entry($con, $user_search);
$user_dn = ldap_get_dn($con, $user_entry);
$user_id = $user_get[0]["uid"][0];
$user_givenName = $user_get[0]["givenName"][0];
$user_search_arry = array( "*", "ou", "uid", "mail", "passwordRetryCount", "passwordhistory" );
$user_search_filter = "(|(uid=$user_id)(mail=$user))";
$user_search_opt = ldap_search($con,$user_dn,$user_search_filter,$user_search_arry);
$user_get_opt = ldap_get_entries($con, $user_search_opt);
$passwordRetryCount = $user_get_opt[0]["passwordRetryCount"][0];
$passwordhistory = $user_get_opt[0]["passwordhistory"][0];

//$message[] = "Username: " . $user_id;
//$message[] = "DN: " . $user_dn;
//$message[] = "Current Pass: " . $oldPassword;
//$message[] = "New Pass: " . $newPassword;

/* Start the testing /
if ( $passwordRetryCount == 3 ) {
$message[] = "Error E101 - Your Account is Locked Out!!!";
return false;
}
if (ldap_bind($con, $user_dn, $oldPassword) === false) {
$message[] = "Error E101 - Current Username or Password is wrong.";
return false;
}
if ($newPassword != $newPasswordCnf ) {
$message[] = "Error E102 - Your New passwords do not match!";
return false;
}
$encoded_newPassword = "{SHA}" . base64_encode( pack( "H
", sha1( $newPassword ) ) );
$history_arr = ldap_get_values($con,$user_dn,"passwordhistory");
if ( $history_arr ) {
$message[] = "Error E102 - Your new password matches one of the last 10 passwords that you used, you MUST come up with a new password.";
return false;
}
if (strlen($newPassword) < 8 ) {
$message[] = "Error E103 - Your new password is too short.
Your password must be at least 8 characters long.";
return false;
}
if (!preg_match("/[0-9]/",$newPassword)) {
$message[] = "Error E104 - Your new password must contain at least one number.";
return false;
}
if (!preg_match("/[a-zA-Z]/",$newPassword)) {
$message[] = "Error E105 - Your new password must contain at least one letter.";
return false;
}
if (!preg_match("/[A-Z]/",$newPassword)) {
$message[] = "Error E106 - Your new password must contain at least one uppercase letter.";
return false;
}
if (!preg_match("/[a-z]/",$newPassword)) {
$message[] = "Error E107 - Your new password must contain at least one lowercase letter.";
return false;
}
if (!$user_get) {
$message[] = "Error E200 - Unable to connect to server, you may not change your password at this time, sorry.";
return false;
}
/* And Finally, Change the password */
$entry = array();
$entry["userPassword"] = "$encoded_newPassword";
$r = ldap_bind($con, $user, $password);
//$r = ldap_bind($con,$rootdn,$rootpwd);

$auth_entry = ldap_first_entry($con, $user_search);
$mail_addresses = ldap_get_values($con, $auth_entry, "mail");
$given_names = ldap_get_values($con, $auth_entry, "givenName");
$password_history = ldap_get_values($con, $auth_entry, "passwordhistory");
$mail_address = $mail_addresses[0];
$first_name = $given_names[0];

/* And Finally, Change the password */
$entry = array();
$entry["userPassword"] = "$encoded_newPassword";
$ldap_bind = ldap_bind($con, $user, $password);

if (ldap_modify($con,$user_dn,$entry) === false){
$error = ldap_error($con);
$errno = ldap_errno($con);
$message[] = "E201 - Your password cannot be change, please contact the administrator.";
$message[] = "$errno - $error";
} else {
$message_css = "yes";
mail($mail_address,"Password change notice","Dear $first_name,
Your password on http://support.example.com for account $user_id was just changed. If you did not make this change, please contact support@example.com.
If you were the one who changed your password, you may disregard this message.

Thanks
-Matt");
$message[] = "The password for $user_id has been changed.
An informational email as been sent to $mail_address.
Your new password is now fully Active.";
}
}

?>

<title>Password Change Page</title> <style type="text/css"> body { font-family: Verdana,Arial,Courier New; font-size: 0.7em; } th { text-align: right; padding: 0.8em; } #container { text-align: center; width: 500px; margin: 5% auto; } .msg_yes { margin: 0 auto; text-align: center; color: green; background: #D4EAD4; border: 1px solid green; border-radius: 10px; margin: 2px; } .msg_no { margin: 0 auto; text-align: center; color: red; background: #FFF0F0; border: 1px solid red; border-radius: 10px; margin: 2px; } </style>

Password Change Page

Your new password must be 8 characters long or longer and have at least:
one capital letter, one lowercase letter, & one number.
You must use a new password, your current password
can not be the same as your new password.

$one

"; } ?>
Username or Email Address:
Current password:
New password:
New password (again):
Cancel
` Could someone please help me to get this to work.
@Gc85

This comment has been minimized.

Copy link

commented Sep 15, 2016

I have tried the code above and keep getting and "Error E200 - Unable to connect to server, you may not change your password at this time, sorry."

We have modified AD to allow Anonymous connections as specified in: https://www.petri.com/anonymous_ldap_operations_in_windows_2003_ad , though we are running Server 2012.

If I do a bind with the following code as a user of AD, everything works fines:

$ldapserver = 'server.domain';
$ldapuser      = 'user@domain';
$ldappass     = 'password';
$ldaptree    = "OU=Users,DC=domain,DC=domain,DC=domain";
$loggedUser = "UserToFind";

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

echo "ldapcon: " . $ldapconn . "<br />";

if($ldapconn) {
    // binding to ldap server
    $ldapbind = ldap_bind($ldapconn, $ldapuser, $ldappass) or die ("Error trying to bind: ".ldap_error($ldapconn));
    // verify binding
    if ($ldapbind) {
        echo "LDAP bind successful...<br /><br />";
        $result = ldap_search($ldapconn,$ldaptree, "(cn=*)") or die ("Error in search query: ".ldap_error($ldapconn));
        $data = ldap_get_entries($ldapconn, $result);

        // SHOW ALL DATA
        echo '<h1>Dump all data</h1><pre>';
        for ($i=0; $i < $data["count"]; $i++)
        {
            if ($data[$i]["samaccountname"][0] == $loggedUser)
            {
                if ($data[$i]["badpwdcount"][0] > 0)
                {
                    echo "User: " . $data[$i]["samaccountname"][0] . " badpwdcount: " . $data[$i]["badpwdcount"][0] . "<br />";
                }
                else
                {
                    echo "User: " . $data[$i]["samaccountname"][0] . " Not locked." . "<br />";
                }
            }
        }

        for ($i=0; $i < $data["count"]; $i++)
        {
            if ($data[$i]["samaccountname"][0] == $loggedUser)
            {
                if ($data[$i]["lockouttime"][0] > 0)
                {
                    echo "User: " . $data[$i]["samaccountname"][0] . " lockouttime: " . $data[$i]["lockouttime"][0] . "<br />";
                }
                else
                {
                    echo "User: " . $data[$i]["samaccountname"][0] . " Lockout Time: " . $data[$i]["lockouttime"][0] . "<br />";
                }
            }
        }

        print_r($data);   
        echo '</pre>';

        // iterate over array and print data for each entry
        echo '<h1>Show me the users</h1>';
        for ($i=0; $i<$data["count"]; $i++) {
            //echo "dn is: ". $data[$i]["dn"] ."<br />";
            echo "User: ". $data[$i]["cn"][0] ."<br />";
            if(isset($data[$i]["mail"][0])) {
                echo "Email: ". $data[$i]["mail"][0] ."<br /><br />";
            } else {
                echo "Email: None<br /><br />";
            }
        }
        // print number of entries found
        echo "Number of entries found: " . ldap_count_entries($ldapconn, $result);
    } else {
        echo "LDAP bind failed...";
    }
}
// all done? clean up
ldap_close($ldapconn);

I can connect and find the specified user and see if their password has expired, or their account has been locked as this is exactly what I need to do, but if a user's password has expired, I need to redirect them to this page and allow them to change their password.

I enter the simple UserToFind along with current password and new password, without the domain added at the end, and have tried with the domain added but to no avail, line 34 (ldap_search) returns no results and nothing happens. I do echo the Resource ID# when doing ldap_connect. For my code, it will give me an ID#1 but this Password Change code returns an ID#4. What do these numbers mean as I have yet to find a decent explanation.

What do I need to change to allow this anonymous bind to work and to allow the user to change their password?

Using IIS 8.5 with PHP 7.0.7.

Any and all help will be much appriciated.

@stampycode

This comment has been minimized.

Copy link

commented Sep 4, 2017

Anyone using these functions needs to escape the username or email address used to build a filter, using the 'ldap_escape' function.
This is the basis for an LDAP query injection attack.
Also means if your username or email address has special chars in, they might otherwise just break the ldap filter.

(The ldap_escape function was added in PHP5.6)

Adjustment suggested on line 34:

  $user_esc = ldap_escape($user);
  $user_search = ldap_search($con,$dn,"(|(uid=$user_esc)(mail=$user_esc))");

Pre-PHP5.6 Alternative:

  $user_esc = str_replace(
    array( '*',   '(',   ')',   '\\',  null  ),
    array( '\2a', '\28', '\29', '\5c', '\00' ),
    $user
  );
  $user_search = ldap_search($con,$dn,"(|(uid=$user_esc)(mail=$user_esc))");
@amitvsipl

This comment has been minimized.

Copy link

commented Nov 13, 2017

Hi please help to resolve this.

Connected to LDAP on Secure Port Sucessfully!
LDAP bound Sucessfully!

I have changed below detail

$users = "username";
$password = "password";

error_reporting(0);
ldap_connect($server);
//$con = ldap_connect($server);

$con = ldap_connect($server, $ldapsport) or die("Could not connect");

ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);

if ($con){
echo "Connected to LDAP on Secure Port Sucessfully!";
$ldap_bind = ldap_bind($con, $users, $password);
}

  if ($ldap_bind){
      echo "LDAP bound Sucessfully!";
    }

// bind anon and find user by uid

echo $user;

$user_search = ldap_search($con,$dn,"(|(uid=$user)(mail=$user))");

print_r($user_search);


Username:

DN:

Current Pass: *************

New Pass: *************

E201 - Your password cannot be change, please contact the administrator.

1 - Operations error

Your password was not changed.

ldap_search not searching specific user.

Thanks

@Scottking92

This comment has been minimized.

Copy link

commented Jun 28, 2018

Hi,

Thanks for the code, works beautifully.

Just wondering if there is a way to update the "shadowLastChange" field to today date when the password is reset from this script?

Any help would be appreciated.

@Al3ajandro

This comment has been minimized.

Copy link

commented Apr 2, 2019

hi,
a questions. to connect to the LDAP and change password is neccesary using the master password of ldap database? or only my user of active directory? , thanks a lot

@jackhftang

This comment has been minimized.

Copy link

commented Jul 13, 2019

FYI, I made some modifications over this version. Some modification:

  1. use another bind DN (instead of anoymous to search)
  2. use pwdaccountlockedtime (instead of passwordRetryCount) for openldap.
  3. removed sending remail which I don't need.
  4. [fix] removed a redundent ldap_connect

https://gist.github.com/jackhftang/2592bb16971e4b60ce32022c48cc74e1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.