Can I change myself Active Directory password from LDAP (without administrative account)

xtern picture xtern · Mar 14, 2012 · Viewed 10.6k times · Source

I don't (and will not) have administators account. I want to change myself (user) password in Active Directory from java. How can I do this?

Using code from web:

private void changePass() throws Exception {
    String oldpass = this.encodePassword("oldpass!");
    String newpass = this.encodePassword("newpass!");
    Attribute oldattr = new BasicAttribute("unicodePwd", oldpass);
    Attribute newattr = new BasicAttribute("unicodePwd", newpass);
    ModificationItem olditem = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, oldattr);
    ModificationItem newitem = new ModificationItem(DirContext.ADD_ATTRIBUTE, newattr);
    ModificationItem repitem = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, newattr);
    ModificationItem[] mods = new ModificationItem[2];
    mods[0] = olditem;
    mods[1] = newitem;
    // ldapTemplate.modifyAttributes("cn=administrator,cn=Users", mods);
    ldapTemplate.modifyAttributes("cn=smith,cn=Users", new ModificationItem[] { repitem });
}

here is the contextSource

<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
    <property name="url" value="ldap://ldapserver:389"/>
    <property name="base" value="dc=company,dc=com"/>
    <property name="userDn" value="smith@company"/>
    <property name="password" value="oldpass"/>
</bean>

I got:

LDAP: error code 32 - 0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT), data 0, best match of:
'CN=Users,DC=company,DC=com'

if I change userDn to "cn=smith" I got:

LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error

Maybe my problem is that I do not understand how is LDAP working? Is it possible (change user password by using user-account) or not? And, if it is possible, can I check account locked / expires with same privileges?

UPDATE / RESOLVE

thank you very match for your help. That was very helpful too me.

for future searchers:

NO_OBJECT - means that ACtive Directory cannot find object (my cn=Users,cn=Smith) To find fully qualified canonical path to user catalogue you can use user attribute "distinguishedName" (in my, worstest case it is "cn=John\, Smith",ou=Contractors,ou=User Accounts,ou=Accounts")

then I got:

WILL_NOT_PERFORM - this can mean different type of things. In my case there was wrong object type, but, possible other cases, as described below - not SSL connection (not ldaps://), and others.

then:

INSUFF_ACCESS_RIGHTS - user (not administrator doesn't have right to REPLACE-password attribute), to change password he must enter old password and new password, and then REMOVE old and ADD new.

Attribute oldattr = new BasicAttribute("unicodePwd", oldQuotedPassword.getBytes("UTF-16LE"));
Attribute newattr = new BasicAttribute("unicodePwd", newQuotedPassword.getBytes("UTF-16LE"));
ModificationItem olditem = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, oldattr);
ModificationItem newitem = new ModificationItem(DirContext.ADD_ATTRIBUTE, newattr);
ldapTemplate.modifyAttributes("cn=John\\, Smith,ou=Contractors,ou=User Accounts,ou=Accounts", new ModificationItem[] { olditem, newitem });

problem 1005 (CONSTRAINT_ATT_TYPE) - if old password wrong

btw

javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name '/' - when searching person/user global (for example, in authenticate-method) ldapTemplate.setIgnorePartialResultException(true); can fix it

Answer

ShaMan-H_Fel picture ShaMan-H_Fel · Mar 14, 2012

Yes you can, however it is somewhat tricky.

First to change the password you must connect via LDAPS not LDAP. That is with TLS or SSL (at least 128 bit) connection. Here is an example how this can be done with JNDI.

Second you must pass the password as UTF-16LE encoded byte array. But before you encode it you should enclose it in double quotes. So here is an example:

String pass = "\"" + "newpass" + "\"";
byte[] password = pass.getBytes("UTF-16LE");
// You will need to handle UnsupportedEncodingException here