Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@mattrude
Created October 31, 2010 23:49
Show Gist options
  • Star 82 You must be signed in to star a gist
  • Fork 47 You must be signed in to fork a gist
  • Save mattrude/657334 to your computer and use it in GitHub Desktop.
Save mattrude/657334 to your computer and use it in GitHub Desktop.
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>
@amitvsipl
Copy link

amitvsipl 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
Copy link

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
Copy link

Al3ajandro 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
Copy link

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

@huSSooxXx
Copy link

Thank you so much. Working perfectly

@wl-sre
Copy link

wl-sre commented May 26, 2020

@ALL
hello,every , could anyone explain the line with "Your new password matches one of the last 10 passwords that you used, you MUST come up with a new password" to me ?
appreciate your help!
I can not understand how to test the new-password with the history

@cmacias00
Copy link

cmacias00 commented Jun 5, 2020

@ALL
hello,every , could anyone explain the line with "Your new password matches one of the last 10 passwords that you used, you MUST come up with a new password" to me ?
appreciate your help!
I can not understand how to test the new-password with the history

Hi,

I think it's incomplete.
This worked for me:

$result = "";
$search = ldap_read($con, $user_dn, "(objectClass=*)", array("pwdHistory"));
$entry = ldap_first_entry($con, $search);
$password_history = ldap_get_values($con, $entry, "pwdHistory");

foreach ($password_history as $pass) {
    preg_match('/{SSHA}(\S+)/', $pass, $matches);
    $hash_history=$matches[0];
    $salt = substr(base64_decode(substr($hash_history,6)),20);
    $encrypted_password = '{SSHA}' . base64_encode(sha1( $newPassword.$salt, TRUE ). $salt);
    if ($hash_history == $encrypted_password)
        $result="pwdused";
}

if ($result) {
    $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;
}

I hope this will help you

@mattrude
Copy link
Author

mattrude commented Jun 6, 2020 via email

@qquattog
Copy link

Hello @mattrude,
I have a problem when I use URI connection
$server = "ldaps://x.x.x.x:636";
and use this logic to test if it connects:
$con=ldap_connect($server) or die("Could not connect");

it does connect but records of a legit ldap user will not be found.
"Error E101 - Current Username or Password is wrong.";

But if I change $server = "ldaps://x.x.x.x:636"; to $server = "x.x.x.x"; it will find the user and the password.

My LDAP is already with a certificate and is running ok.
ldap.conf
URI ldaps://x.x.x.x:636
TLS_CACERTDIR /etc/openldap/cacerts
TLS_CACERT /etc/openldap/cacerts/server.crt
TLS_REQCERT allow

Hope you can give light to this matter.
Thanks in advance. You have a good code to share.

@Nha-Krul
Copy link

Very good work!! Thanks

@SumairaButt
Copy link

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

50 - Insufficient access

Your password was not changed.

i am getting this error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment