Change Password in Active Directory using LDAP/PHP/IIS/SSL
First of all, this may be less of a programming question and more of a how do I configure LDAPS question, but here goes...
Background Info:
I have two Windows 2008 R2 servers. One is a domain controller (DC) with Active Directory (AD) that I want to communicate with via LDAP. This one is named TestBox.TestDomain.local. The other server is running IIS, PHP (with ldap and openssl), and mySQL.
What is/isn't working:
I can successfully connect to the DC unsecured over port 389 and read/write data to AD. What I can't do is change or set user passwords since this requires a secure connection using LDAPS (LDAP w/ SSL) over port 636.
What I need help with:
I have tried installing Active Directory Certificate Services (AD CS) and configuring the DC to act as a Certificate Authority (CA) using information found here: http://technet.microsoft.com/en-us/library/cc770357(WS.10).aspx but no matter what I try I can't get a connection over LDAPS to work.
Sample Code:
Creating the LDAP Connection
function ldapConnect(){
$ip = "100.200.300.400"; // WAN IP goes here;
$ldap_url = "ldap://$ip";
$ldaps_url = "ldaps://$ip";
$ldap_domain = 'testdomain.local';
$ldap_dn = "dc=testdomain,dc=local";
// Unsecure - WORKS
$ldap_conn = ldap_connect( $ldap_url ) or die("Could not connect to LDAP server ($ldap_url)");
//alternate connection method
//$ldap_conn=ldap_connect( $ip, 389 ) or die("Could not connect to LDAP server (IP: $ip, PORT: 389)");
// Secure - DOESN'T WORK
//$ldap_conn = ldap_connect( $ldaps_url ) or die("Could not connect to LDAP server ($ldaps_url)");
//alternate connection method
//$ldap_conn=ldap_connect( $ip, 636 ) or die("Could not connect to LDAP server (IP: $ip, PORT: 636)");
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
$username = "AdminUser";
$password = "AdminPass";
// bind using admin username and password
// could also use dn... ie. CN=Administrator,CN=Users,DC=TestDomain,DC=local
$result = ldap_bind($ldap_conn, "$username@$ldap_domain", $password ) or die("<br>Error: Couldn't bind to server using supplied credentials!");
if($result){
return $ldap_conn;
}else{
die("<br>Error: Couldn't bind to server using supplied credentials!");
}
}
Adding a New User to Active Directory
function ldapAddUser($ldap_conn, $ou_dn, $firstName, $lastName, $username, $pwdtxt, $email){
$dn = "CN=$firstName $lastName,".$ou_dn;
## Create Unicode password
$newPassword = "\"" . $pwdtxt . "\"";
$len = strlen($newPassword);
$newPassw = "";
for($i=0;$i<$len;$i++) {
$newPassw .= "{$newPassword{$i}}\000";
}
$ldaprecord['cn'] = $firstName." ".$lastName;
$ldaprecord['displayName'] = $firstName." ".$lastName;
$ldaprecord['name'] = $firstName." ".$lastName;
$ldaprecord['givenName'] = $firstName;
$ldaprecord['sn'] = $lastName;
$ldaprecord['mail'] = $email;
$ldaprecord['objectclass'] = array("top","person","organizationalPerson","user");
$ldaprecord["sAMAccountName"] = $username;
//$ldaprecord["unicodepwd"] = $newPassw;
$ldaprecord["UserAccountControl"] = "544";
$r = ldap_add($ldap_conn开发者_开发问答, $dn, $ldaprecord);
// set password .. not sure if I need to base64 encode or not
$encodedPass = array('userpassword' => base64_encode($newPassw));
//$encodedPass = array('unicodepwd' => $newPassw);
echo "Change password ";
if(ldap_mod_replace ($ldap_conn, $dn, $encodedPass)){
echo "succeded";
}else{
echo "failed";
}
}
Just two pieces of advice:
- During the AD CS setup, in the Specify Setup Type page, click Enterprise, and then click Next.
- AD service is supposed to take himself his own certificate, but if it works like in Windows server 2003, you must reboot the server to make it work. Perhaps just stop and restart the service in W2K8 R2.
Afer that, you can just try to build a certificate and install it on the AD service account, like you can find it done with ADAM.
Did you create a certificate request for the secure Ldap with the correct OIDs?
here's my inf file:
[Version]
Signature="$Windows NT$
[NewRequest]
Subject = "CN=my-server.blahblah.com" ; must be the FQDN of host
Exportable = TRUE ; TRUE = Private key is exportable
KeyLength = 4096 ; Common key sizes: 512, 1024, 2048,
; 4096, 8192, 16384
KeySpec = 1 ; Key Exchange
KeyUsage = 0xF8 ; Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Key Agreement
MachineKeySet = True
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = CMC
; Omit entire section if CA is an enterprise CA
[EnhancedKeyUsageExtension]
OID=1.3.6.1.5.5.8.2.2
OID=1.3.6.1.5.5.7.3.1
OID=1.3.6.1.5.5.7.3.2
OID=1.3.6.1.5.5.7.3.3
OID=1.3.6.1.5.5.7.3.4
OID=1.3.6.1.5.5.7.3.5
OID=1.3.6.1.5.5.7.3.6
OID=1.3.6.1.5.5.7.3.7
OID=1.3.6.1.5.5.7.3.8
OID=1.3.6.1.5.5.7.3.9
OID=1.3.6.1.4.1.311.10.3.4
OID=1.3.6.1.4.1.311.54.1.2
[RequestAttributes]
CertificateTemplate = MySpecialTemplate ;Omit line if CA is a stand-alone CA
SAN="my-server.blahblah.com"
YOU SHOULD MAKE A TEMPLATE ON THE CA USING THE 2003 (NOT ALL MICROSOFT PRODUCTS CAN UTILIZE 2008 TEMPLATES -- I KNOW STUPID HUH) COPY IT FROM DOMAIN CONTROLLER AND THROW THE KITCHEN SINK AT THE OIDS
Just make your connection as trust all. Then it will no longer need certificates. Check out javax.net.sslTrustManager
.
精彩评论