We use LDAP (Samba) for authentication and now I want to make user able to change their password. I'm using this script:
$username = $request->request->get('username');
$oldpasswd = $request->request->get('oldpasswd');
$newpasswd = $request->request->get('newpasswd');
$userPassword = mb_convert_encoding('"'.$newpasswd.'"', 'utf-16le');
$ldapPasswd = $this->getParameter('LDAP_PASSWD');
$ldap->bind("CN=LDAPADMIN,CN=Users,DC=DOMAIN,DC=net", $ldapPasswd);
$query = $ldap->query('CN=users,DC=DOMAIN,DC=net', "(&(objectclass=person)(sAMAccountName=$username))");
$result = $query->execute()->toArray();
$entry = $result[0];
$newEntry = new Entry($entry->getDn(), [
'unicodePwd' => [$userPassword],
]);
$ldap->getEntryManager()->update($newEntry);
It is working ok but with this, all security settings are not valid: Don't repeat password, password length > 6 characters etc etc... And, the script uses an Adminstrator account to change password.Is there any other way to update the user password using user account for that and validating password security configs?
CodePudding user response:
Based on your code, it seems you're using Symfony and you have an Active Directory server.
Your code is doing a "password reset", which is something an administrator would do if a user forgets their password. It requires administrative rights and does not require knowing the previous password, and thus it does not enforce previous history.
What you want to do is a "password change". The documentation for unicodePwd explains how to do this:
If the Modify request contains a delete operation containing a value Vdel for unicodePwd followed by an add operation containing a value Vadd for unicodePwd, the server considers the request to be a request to change the password. The server decodes Vadd and Vdel using the password decoding procedure documented later in this section. Vdel is the old password, while Vadd is the new password.
In LDAP, this is called a "batch request", which contains both a delete instruction and an add instruction, all in the same single request to the server. The Symfony documentation includes a section on how to do Batch Updating. In your case, it should look something like this:
$username = $request->request->get('username');
$oldpasswd = $request->request->get('oldpasswd');
$newpasswd = $request->request->get('newpasswd');
$oldUserPassword = mb_convert_encoding('"'.$oldpasswd.'"', 'utf-16le');
$userPassword = mb_convert_encoding('"'.$newpasswd.'"', 'utf-16le');
$ldapPasswd = $this->getParameter('LDAP_PASSWD');
$ldap->bind("CN=LDAPADMIN,CN=Users,DC=DOMAIN,DC=net", $ldapPasswd);
$query = $ldap->query('CN=users,DC=DOMAIN,DC=net', "(&(objectclass=person)(sAMAccountName=$username))");
$result = $query->execute()->toArray();
$entry = $result[0];
$entryManager->applyOperations($entry->getDn(), [
new UpdateOperation(LDAP_MODIFY_BATCH_REMOVE, 'unicodePwd', $oldUserPassword),
new UpdateOperation(LDAP_MODIFY_BATCH_ADD, 'unicodePwd', $userPassword),
]);
Notice that you have to encode the old password the same way you encoded the new password.
