So I got everything working with .htaccess and AD/LDAP authentication. Just add LDAPVerifyServerCert Off to the httpd config to let Apache authenticate against an AD server with a self-signed certificate (without dealing with the annoyance of putting the cert on each Apache server).
With that piece of the puzzle largely solved, I moved on to another: how will users change their passwords (which are all stored in Active Directory)? For users running Windows this is pretty trivial — they can do it right in Windows when they’re logged into the domain. But what about Linux users? I figured the easiest thing to do would be to make a web form to do this. The user would login (with the http/LDAP auth I previously setup) and the form would ask for their password (twice) and update it in Active Directory. Sounds pretty simple to me. I think if this were OpenLDAP it probably would be, but being AD, it’s not.
I’d already spent an hour or two writing the script (in PHP) when I was able to test its basic functionality. What I got was this:
Warning: ldap_mod_replace() [function.ldap-mod-replace]: Modify: Insufficient access in /home/evan/public_html/authtest/index.php
After some hair pulling I realized that I was binding with my “dummy” user when attempting to change the password. I figured the solution would be to re-bind as the user whose password I was attempting to change, which is what I did. I verified that the new bind worked, but I still couldn’t change the password. I decided to fall back to command line and started issuing some ldapmodify commands to see what I could and couldn’t do as the user. For whatever reason, it appears that even though the user CAN change his password in AD (the “user cannot change password” setting is NOT selected — I checked), the user cannot change his password through LDAP.
$ ldapmodify -vv -x -d8 -D "CN=Boba Fett,OU=Utility,OU=Users,DC=example,DC=com" -w secret -H ldaps://activedirectory.example.com -f bfett.ldif
ldap_initialize( ldaps://activedirectory.example.com )
TLS certificate verification: Error, unable to get local issuer certificate
request done: ld 0x9dd86e8 msgid 1
modifying entry "CN=Boba Fett,OU=Utility,OU=Users,DC=example,DC=com"
request done: ld 0x9dd86e8 msgid 2
ldapmodify: Insufficient access (50)
additional info: 00000005: SecErr: DSID-031A0F44, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0
I Googled for the error code – DSID-031A0F44 – and found a couple of threads about people with the same problem, but no solutions.
The LDIF file I fed in looks like this:
dn: CN=Boba Fett,OU=Utility,OU=Users,DC=example,DC=com
When I run the same command with my own DN/password for binding it works fine (though I did discover that you can assign multiple values to unicodePwd, meaning that, until I fixed it, the test user had two valid passwords, which seems like a bug on Microsoft’s part), I assume because I’m a domain admin. An “easy” out would be simply to have the script bind as a domain admin, but that means I’d be hardcoding a Domain Admin password in the script, which I’m against. I’ll have to put some more thought into this. Maybe Linux users will just have to log in to a Windows workstation to change their passwords. That’s not ideal, but it does already work.
Update – Click the “ldap” tag below to see all the LDAP-related posts, including the solution to changing AD passwords via a browser.