Jasper
Jasper

Reputation: 8705

Changing Active Directory user password from java program

I have Active Directory, with Users in it, i am trying to change a users password from a Java Program as follows:

Properties prop = new Properties();
prop.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
prop.put(Context.SECURITY_AUTHENTICATION, "simple");
prop.put(Context.SECURITY_PRINCIPAL,"user1");
prop.put(Context.SECURITY_CREDENTIALS,"pass1");
prop.put(Context.SECURITY_PROTOCOL,"ADSecurityProtocol");
prop.put(Context.PROVIDER_URL, "ldap://host:389/OU=My Org,DC=domain,DC=com");
try
{
     LdapContext ctx =new InitialLdapContext(prop,null);
     String oldPassword="pass1";
     String newPassword="passnew1";
     ModificationItem[] mods = new ModificationItem[2];
     String oldQuotedPassword = "\"" + oldPassword + "\"";
     byte[] oldUnicodePassword = oldQuotedPassword.getBytes("UTF-16LE");
     String newQuotedPassword = "\"" + newPassword + "\"";
     byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");

     mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
                   new BasicAttribute("unicodePwd", oldUnicodePassword));
     mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE,
                   new BasicAttribute("unicodePwd", newUnicodePassword));

     String theUserName="CN="+"user1"+",OU=My Org,DC=domain,DC=com";
     // Perform the update
     ctx.modifyAttributes(theUserName, mods);
     System.out.println("Changed Password for successfully");
     ctx.close();
}
     catch (Exception e) {
          System.err.println("Problem changing password: " + e);
}

The error message i get is:

Problem changing password: javax.naming.NamingException: 
[LDAP: error code 1 - 000020D6: SvcErr: DSID-031007DB, 
problem 5012 (DIR_ERROR), data 0]; remaining name 
'CN=user1,OU=My Org,DC=domain,DC=com'

Edit 1:

Based on Suggestions i have tried this with port 636 and ldaps as well:

prop.put(Context.PROVIDER_URL, "ldap://host:636/OU=My Org,DC=domain,DC=com");  
Also tried
prop.put(Context.PROVIDER_URL, "ldaps://host:636/OU=My Org,DC=domain,DC=com");  

I am getting MalformedURLException: Invalid URI: 
Invalid URI: Org,DC=domain,DC=com] 

When i try (not sure if anything is listening on 636, it appears it is tho):

$ telnet LDAPHost 636
Escape character is '^]'.
Connection closed by foreign host.

Edit2:

Changed:
 prop.put(Context.PROVIDER_URL, "ldap://host:636/OU=My Org,DC=domain,DC=com");  
to:
 prop.put(Context.PROVIDER_URL, "ldap://host:636/OU=My%20Org,DC=domain,DC=com"); 

The error is:

javax.naming.CommunicationException: simple bind failed: host:636 
[Root exception is java.net.SocketException: Connection reset]

Probably the LDAP Server is not even listening on ssl port: 636

Upvotes: 4

Views: 27075

Answers (5)

Eng.Fouad
Eng.Fouad

Reputation: 117675

If you are on Windows, then you can call NetUserChangePassword() function that is available inside netapi32.dll.

Using JNA, the code will be like this:

public static int changeActiveDirectoryUserPassword(String activeDirectoryIP, String username, String oldPassword, String newPassword)
{
    int status = Netapi32.INSTANCE.NetUserChangePassword(activeDirectoryIP, username, oldPassword, newPassword);

    switch(status)
    {
        case WinError.ERROR_INVALID_PARAMETER: // The parameter is incorrect
        case WinError.ERROR_ACCESS_DENIED: // The user does not have access to the requested information
        case WinError.ERROR_INVALID_PASSWORD: // The user has entered an invalid password
        case LMErr.NERR_InvalidComputer: // The computer name is invalid
        case LMErr.NERR_NotPrimary: // The operation is allowed only on the primary domain controller of the domain
        case LMErr.NERR_UserNotFound: // The user name could not be found
        case LMErr.NERR_PasswordTooShort: // The password is shorter than required. (The password could also be too
                                          // long, be too recent in its change history, not have enough unique
                                          // characters, or not meet another password policy requirement.)
        case LMErr.NERR_Success: // function succeeds
        default: return status;
    }
}

Note: Unlike the ldap approach, this approach will work even if the old password is already expired.

Upvotes: 1

alexanderarda
alexanderarda

Reputation: 400

You have to change the attribute. Try to change unicodePwd withuserpassword

from :

 mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
               new BasicAttribute("unicodePwd", oldUnicodePassword));
 mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE,
               new BasicAttribute("unicodePwd", newUnicodePassword));

to :

mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
                   new BasicAttribute("userpassword", oldUnicodePassword));
mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE,
                   new BasicAttribute("userpassword", newUnicodePassword));

Upvotes: 0

Bruno Medeiros
Bruno Medeiros

Reputation: 2399

Basically, you need to modify the unicodePwd attribute of the user.

I use AWS Simple AD implementation and, as it is based on Samba 4, this attribute doesn't work. You need to use clearTextPassword in this case. See my blog post about it: http://blog.techutils.space/2016/02/changing-samba4-aws-simple-ad-user.html

Note: AWS Simple AD doesn't support SSL yet, so find a way to mitigate this risk.

Upvotes: 0

Ozzy
Ozzy

Reputation: 21

The JVM executing the password change call needs to be trusted by the directory service provider. This means importing a certificate generated from AD into the JVM trust store.

Upvotes: 2

zagyi
zagyi

Reputation: 17528

[The unicodePwd] attribute can be written under restricted conditions [...] In order to modify this attribute, the client must have a 128-bit Secure Socket Layer (SSL) connection to the server.

You only have a plain unsecure ldap:// connection instead of ldaps://, so that won't work according to the above restrictions.

See more details at: http://support.microsoft.com/kb/269190

Upvotes: 6

Related Questions