This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm
Many Java applications now utilize Active Directory as a source of authentication, in some situations it may be required to set Active Directory password from within Java applications. I encountered a scenario where majority of the users of a Java application were on Active Directory, but for a small percentage of users that do not log-in to Active Directory from their desktops we needed to provide a functionality within the application to set user passwords.
Active Directory Domain Controllers will only allow password set operations over an SSL channel, therefore both parties should have a common trusted root certificate in their certificate stores. The simplest way to accomplish this is to export a trusted root certificate from a Domain Controller and import it into Java certificate store on the client machine.
Active Directory Domain Controllers automatically enroll for domain controller certificate and utilize it for secure LDAP communications if Active Directory integrated Microsoft Certificate Server is deployed within the Forest. So in other words, if you deployed Microsoft Certificate Server in Active Directory integrated mode, then you don't need to do anything else on Active Directory side, all domain controllers will use SSL on port 636.
For instructions on how to setup Microsoft Certificate Server follow this link .
On the client side we need to import a mutually trusted root certificate into Java certificate store. In our case we will export the root certificate issued by Microsoft Certificate Server and import it into Java store on the client.
1. On a Domain Controller log-in as an administrator and open Internet Explorer. Go to Tools->Internet Options->Content and click on Certificates
2. Switch to Trusted Root Certificate Authorities Tab and Select the certificate issued by your Active Directory integrated Certificate Server. Click on Export
3. Choose Base-64 encoded X.509(.CER)
4. Specify file name for the exported certificate
5. Finish the export and copy the exported .cer file to the Java client machine
6. At the client machine execute the following command.
Note the location of the jks file, you will need to reference it later on in the code.
Alias and keystore password are arbitrary values
Now that SSL staff is out of the way compile this sample code and run it from the Java client
This code was developed by Jeremy Mortis here is link to the original code
import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.ldap.*;
import java.util.*;
import java.security.*;
public class ADConnection {
DirContext ldapContext;
String baseName = ",cn=users,DC=fabrikam,DC=com";
String serverIP = "10.1.1.7";
public ADConnection() {
try {
Hashtable ldapEnv = new Hashtable(11);
ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
ldapEnv.put(Context.PROVIDER_URL, "ldap://" + serverIP + ":636");
ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
ldapEnv.put(Context.SECURITY_PRINCIPAL, "cn=administrator" + baseName);
ldapEnv.put(Context.SECURITY_CREDENTIALS, "PA$$w0rd");
ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
ldapContext = new InitialDirContext(ldapEnv);
}
catch (Exception e) {
System.out.println(" bind error: " + e);
e.printStackTrace();
System.exit(-1);
}
}
public void updatePassword(String username, String password) {
try {
String quotedPassword = "\"" + password + "\"";
char unicodePwd[] = quotedPassword.toCharArray();
byte pwdArray[] = new byte[unicodePwd.length * 2];
for (int i=0; i<unicodePwd.length; i++) {
pwdArray[i*2 + 1] = (byte) (unicodePwd[i] >>> 8);
pwdArray[i*2 + 0] = (byte) (unicodePwd[i] & 0xff);
}
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("UnicodePwd", pwdArray));
ldapContext.modifyAttributes("cn=" + username + baseName, mods);
}
catch (Exception e) {
System.out.println("update password error: " + e);
System.exit(-1);
}
}
public static void main(String[] args) {
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
// the keystore that holds trusted root certificates
System.setProperty("javax.net.ssl.trustStore", "c:\\myCaCerts.jks");
System.setProperty("javax.net.debug", "all");
ADConnection adc = new ADConnection();
adc.updatePassword("Java User2", "pass@word3");
}
}