LDAP-Active Directory authentication, Part 3

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
replace unicodePwd:
"
modifying entry "CN=Boba Fett,OU=Utility,OU=Users,DC=example,DC=com"
modify complete
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
changetype: modify
replace: unicodePwd
unicodePwd::IgBhAGIAYwBkAGUAZgBnAGgAIgA=
-

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.

Grr…

Update – Click the “ldap” tag below to see all the LDAP-related posts, including the solution to changing AD passwords via a browser.

Advertisements

One thought on “LDAP-Active Directory authentication, Part 3”

  1. From Microsoft:

    There are two ways to modify the unicodePwd attribute. The first is analogous to a typical user change-password operation. In this case, the modify request must contain both a delete operation and an add operation. The delete operation must contain the current password enclosed in quotation marks and be Base64 encoded as described in RFC 1521. The add operation must contain the new password enclosed in quotation marks and be Base64 encoded.

    This, however, doesn’t work when I bind as the user, only when I bind as an admin.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s