ltb-project / self-service-password

Web interface to change and reset password in an LDAP directory
https://self-service-password.readthedocs.io/en/latest/
GNU General Public License v3.0
1.13k stars 319 forks source link

Change expired password on OpenLDAP #96

Open sfieux opened 7 years ago

sfieux commented 7 years ago

Hi,

I'm trying to set up self-service-password so that users can change their own password on our openldap. This ldap is configured to make passwords expired after XX days and YY grace logins.

It works fine before password expiration, but I can't get it to work when user has an expired password and no more grace logins allowed, I still get the log message in httpd logs:

[error] [client 1.2.3.4] LDAP - Bind error 49  (Invalid credentials), referer: https://my-server.example.com/pwdchange/index.php

I tried with both possible who_change_password values, no success. I tried the $ad_options['change_expired_password'] = true; no success - I guess it's only working for AD. The $ldap_binddn I tried is the olcRootDN on the openldap database, it has all read and modification rights, so it should be able to check userPassword value without binding to it.

Did I miss something? Would you know how I can reset an expired password?

Many thanks for your support,

sfieux

coudot commented 7 years ago

Indeed, as PHP-LDAP cannot deal with password policy control, we can't id password is expired in OpenLDAP.

I don't see a simple solution for the moment.

Note that this works well with other languages. I implemented it with Perl in LemonLDAP::NG.

sfieux commented 7 years ago

Sucks for me then...

One option would be to edit change.php to read the userPassword field as Manager, hash the old password using the same method/salt, and check that tboth hashes match.

Maybe change the config file to only do that when a specific option is set, and make sure to check that the user isn't locked out because of too many failed logins...

Not sure I'll have the time to implement this, but I hope I will. Would you be interested in a pull request?

coudot commented 7 years ago

Reading the password value inside the directory to compare it to password is really a bad practice, you bypass brute force protection of password policy be doing it.

You can indeed do it to fit your needs but I don't think I can merge this feature. But I understand your issue and know that we should find a solution. I need to check if PHP-LDAP API has not any way to get the expiration information.

sfieux commented 7 years ago

Indeed, a correct implementation for this - one not bypassing bruteforce protection - would have to:

I don't know much about other ldap implementations, but it seems that my "check that the account isn't locked" part is getting very openldap-specific. Since I have neither the knowledge to do a multi-ldap-source implementation nor the possibility to test it, I'll probably write it for myself :)

Anyway, an ssh connexion with openldap-registered users knows the difference between invalid password (rejecting connexion) and expired password (requesting password change), so the openldap somehow provides enought informations to PAM to make the difference. I don't know if php-ldap supports this though...

coudot commented 7 years ago

PAM-LDAP is compatible with password policy, this is why it works. PHP-LDAP is not.

Your implementation proposition is good, except that checking pwdLockoutDuration is not necessary: if the account is still locked after the first bind, then the lock status is valid.

coudot commented 3 years ago

We now have ppolicy control support (#156), but we only catch modification issues (password too short, too weak, in history).

We could also display if password is expired or account is locked. And rewrite #114 to adapt it to new code.