Helpful Information
 
 
Category: LDAP Programming
Modifying Active Directory passwords through PHP and IIS

I have written a script to reset a user's Windows password through PHP. I've used LDAP to access and modify other information in Active Directory, but am unable to change the user's password (unicodePwd) field.

The script connects and binds successfully, but throws the following error when it tries to ldap_modify the password attribute:

Modify: Server is unwilling to perform.

It has no problem modifying other Active Directory fields.

I am running PHP 4.3 on a Windows 2000 machine running IIS 5.0 which connects to a domain controller that has an SSL certificate given by our domain's certificate authority server.

The SSL certificate meets all of MS's requirements outlined in:

http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B321051

and all of the SSL certificate requirements described in this pdf:

http://www.w2k.vt.edu/docs/MSVT_Certificates.pdf

I've seen other people connecting to LDAP with ldaps://domain.com. This, however, will always fail to bind for me. Connecting as ldap://domain.com (no 's') succeeds.

However, the ldp.exe tool MS mentions appears to connect and communicate on the LDAPS port 636 flawlessly. The Windows system event logs indicate that SChannel handshaking is completed successfully.

I am unsure if it is a problem in the SSL certificate, in PHP's configuration, or something else.

I have searched extensively but have not found any definitive answer or guide to this problem on the internet.

Any takers?

John Van Atta

BTT anyone gotten this ssl-ldap thingy to work if so details please :) I made my own CA from the domain controller still no dice.




Originally posted by johnvanatta
I have written a script to reset a user's Windows password through PHP. I've used LDAP to access and modify other information in Active Directory, but am unable to change the user's password (unicodePwd) field.

The script connects and binds successfully, but throws the following error when it tries to ldap_modify the password attribute:

Modify: Server is unwilling to perform.

It has no problem modifying other Active Directory fields.

I am running PHP 4.3 on a Windows 2000 machine running IIS 5.0 which connects to a domain controller that has an SSL certificate given by our domain's certificate authority server.

The SSL certificate meets all of MS's requirements outlined in:

http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B321051

and all of the SSL certificate requirements described in this pdf:

http://www.w2k.vt.edu/docs/MSVT_Certificates.pdf

I've seen other people connecting to LDAP with ldaps://domain.com. This, however, will always fail to bind for me. Connecting as ldap://domain.com (no 's') succeeds.

However, the ldp.exe tool MS mentions appears to connect and communicate on the LDAPS port 636 flawlessly. The Windows system event logs indicate that SChannel handshaking is completed successfully.

I am unsure if it is a problem in the SSL certificate, in PHP's configuration, or something else.

I have searched extensively but have not found any definitive answer or guide to this problem on the internet.

Any takers?

John Van Atta

You need to connect to the LDAP on port 636 (i.e. ldap://myserver:636) you also need to change your server to generate certificates. Visit http://www.logicdevelopment.net/help/ssl.html for details on how to do this.

Boy, I sure would like to know how to update password in Active Directory using PHP. I guess no one knows?

Sorry - I haven't picked up PHP yet. I can do it in Perl, ASP and VB - but not in PHP ...

Best of luck ...

Boy, I sure would like to know how to update password in Active Directory using PHP. I guess no one knows?

What do you need to know? if it's an ssl server you have to do as spae0022 says connect on port 636. Read here http://us2.php.net/manual/en/function.ldap-connect.php you'll see that you must have LDAP compiled with SSL AND php has to be complied with SSL also if not it won't work.

I have been working with PHP for about two years now, and web development even longer than that. PHP and LDAP is easy for me, but I just can't seem to figure out how to update the unicodePwd field in Active Directory.

I know it has to be over LDAPS, but I don't know how to turn the password into unicode. I just want to hear from someone who knows how to do update the unicodePwd field in Active Directory; a search in Google turns up nothing.

I have been working with PHP for about two years now, and web development even longer than that. PHP and LDAP is easy for me, but I just can't seem to figure out how to update the unicodePwd field in Active Directory.

I know it has to be over LDAPS, but I don't know how to turn the password into unicode. I just want to hear from someone who knows how to do update the unicodePwd field in Active Directory; a search in Google turns up nothing.

ok that's clearer thanks, I haven't used active directory before so I didn't know they are stored in unicode.

What you are most likly looking for is multibyte strings (http://us3.php.net/manual/en/ref.mbstring.php) these allow you to convert charsets. You will have to install php with --enable-mbstring (if using windows there should be some similar option).



$tmp = mb_convert_encoding('password', 'UTF-8', 'ASCII');


The above code should convert from ASCII to UTF-8 this should be what you need for your password. Then just write it to the ldap field. Could be missing some stuff haven't had a need to use it.

I will try that, but first, I understand now that I need to establish a secure LDAP connection before I can write to the unicodePwd field in Active Directory. As soon as I get LDAPS working, then I'll try again.

By the way, the code I used to encode the password is:

$user['unicodePwd'] = "{md5}".base64_encode(pack("H*",md5($_POST['newpassword'])));

Anyway, thanx for the input...I'll play when I get a chance, and then I'll post to this thread for anyone interested...

Hello!
Were you able to get the code to work. I am also working on developing a web page to let users reset their passwords. If you have it in PHP that would be great.

Thanks.

By the way, I tried also connecting to Active Directory on TCP 3269. Global Catalog servers use this port for LDAPS. However, I still was unsuccessful. More fiddling, and I'll keep you all posted...

These are the articles that have helped a little:
http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B321051
http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q269/1/90.ASP&NoWebContent=1

I have been following this thread and am wondering if any progress has been made on the problem? I am having the same issue as the original poster - Server is unwilling to perform. Any help is greatly appreciated...

No, I have done everything right. I can verify that I have a secure connection to LDAP and everything. I have an idea it's the algorythm - I just can't figure out what the correct encodeing is for the passwords...

I found a work around to the problem. This works well in my environment but may not for others.

I found a perl script that does what we need here (http://cert.uni-stuttgart.de/archive/ntbugtraq/2003/05/msg00004.html). A modified it to fit my needs like so:



#!/usr/bin/perl -w

use strict;
use Net::LDAPS;

my($Ad, $mesg, $uid, $pass, $npass, $dn, $rtn, $binddn, $bindpw, $searchdn);

$uid = $ARGV[0];
$pass = $ARGV[1];
$binddn = $ARGV[2];
$bindpw = $ARGV[3];
$searchdn = $ARGV[4];

if (($uid eq '') or ($pass eq '')) {
exit 1;
}


# Bind to the AD server

$Ad = Net::LDAPS->new("YOURSERVER", version => 3) or exit 1;
$Ad->bind(dn => $binddn, password => $bindpw) or exit 1;


# Do a AD lookup to get the dn for this user
# then change their password.

$mesg = $Ad->search(base => $searchdn, filter => "cn=$uid");
if($mesg->count != 1) {
exit 1;
}

# Add quotes and uniCode
map { $npass .= "$_\000" } split(//, "\"$pass\"");

# Now change it
$dn = $mesg->entry(0)->dn;

$rtn = $Ad->modify($dn, replace => { "unicodePwd" => $npass });
if($rtn->{'resultCode'} != 0) {
exit 1;
}

exit 0;




Then you call it like so:



./changepw.pl accountCN NewPassword "AdminDN" AdminPassword "Search Base (i.e. DC=mydomain, DC=com)"


Then you can call the perl script from PHP and voila! The only bummer is that the passwords can temporarily be seen in the process table. I can think of numerous ways around it, perhaps sticking the passwords in a temporary file, changing the perl script to read them from the file, and deleting the file when you're done.

Anyway, hope that helps someone. :D

Here is the perl code converted to PHP. Let me know if it doesn't work. (if it doesn't then it's definity a problem with PHP)



$uid = 'accountCN';
$newPassword = 'newpassword';
$bindDn = 'BindDN';
$bindPassword = 'BindPass';
$baseDn = 'dc=mysite,dc=com';
$protocolVersion = 3;

$ldap = ldap_connect('localhost');
if (!ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, $protocolVersion))
{
exit('Failed to set protocol version to '.$protocolVersion);
}
// bind anonymously so that we can verify if the server really is running
ldap_bind($ldap);
if (ldap_errno($ldap) !== 0)
{
exit('Could not connect to LDAP server');
}

// now bind with the correct username and password
ldap_bind($ldap, $bindDn, $bindPassword);
if (ldap_errno($ldap) !== 0)
{
exit('ERROR: '.ldap_error($ldap));
}

$searchResults = ldap_search($ldap, $baseDn, 'cn='.$uid);
// no matching records
if ($searchResults === false)
{
exit('No user found');
}

if (!is_resource($searchResults))
{
exit('Error in search results.');
}

// create the unicode password
$len = strlen($newPassword);
$newPass = '"';
for ($i = 0; $i < $len; $i++)
{
$newPass .= "{$newPassword{$i}}\000";
}
$newPass .= '"';

$entry = ldap_first_entry($ldap, $searchResults);
if (!is_resource($entry))
{
exit('Couldn\'t get entry');
}
$userDn = ldap_get_dn($ldap, $entry);

ldap_modify($ldap, $userDn, array('unicodePwd' => $newPass));

I can verify that I have a secure connection to LDAP and everything.

Matt,

Did you need to do anything special to set up the SSL connection? I can't bind over SSL. I have verified that my DLLs are in the right place.

PHP 4.3.6
Apache/2.0.49
Windows 2000
OpenSSL 0.9.7c 30 Sep 2003

Geoff

what errors do you get?

Has anyone got it to work properly ?

I'm also working on user administration panel in PHP, when users are stored on an AD server.

Everything works fine except setting and changing the unicodePwd field.

I've lost several days to find out how to made it to work and still nothing. I'm really angry about that.

Everything works fine except setting and changing the unicodePwd field.


Did you see the recent posts using the perl script and/or the php converted perl script? That has worked for me, I'd be interested to know if others are having luck with it.

- Ben

Did you see the recent posts using the perl script and/or the php converted perl script? That has worked for me, I'd be interested to know if others are having luck with it.

- Ben

Any chance you can test the PHP script? I don't have AD so can't test it here.










privacy (GDPR)