PDA

View Full Version : How to add user to active directory.


panfl
Nov 16th, 2006, 02:37 AM
Now I can add user in sun one directory server.
But can not add to MS Active Directory.
It seems that spring-ldap can not get "UserPassword" attribute from Active Directory.
My code:


protected void mapToContext(User user, DirContextAdapter context) {
context.setAttributeValue("givenname",user.getFirstName() + " " + user.getLastName() );
context.setAttributeValue("cn", user.getUsername() );
context.setAttributeValue("userPassword", user.getConfirmPassword().getBytes());
}



Exception occured at
context.setAttributeValue("userPassword", user.getConfirmPassword().getBytes());

rasky
Nov 17th, 2006, 06:24 AM
It would be easier to track down the problem with a complete stack trace. Could you please include one?

karldmoore
Nov 17th, 2006, 04:52 PM
For active directory passwords don't you work with "unicodePwd" rather than "userPassword".

ulsa
Nov 18th, 2006, 06:28 AM
You could try changing the password line to the following:


context.setAttributeValue("unicodePwd",
DirectoryUtility.createUnicodePassword(user.getCon firmPassword()));


The DirectoryUtility class could look something like this:


public class DirectoryUtility {

public static byte[] createUnicodePassword(String password) {
return toUnicodeBytes(doubleQuoteString(password));
}

private static byte[] toUnicodeBytes(String str) {
byte[] unicodeBytes = null;
try {
byte[] unicodeBytesWithQuotes = str.getBytes("Unicode");
unicodeBytes = new byte[unicodeBytesWithQuotes.length - 2];
System.arraycopy(
unicodeBytesWithQuotes,
2,
unicodeBytes,
0,
unicodeBytesWithQuotes.length - 2);
} catch (UnsupportedEncodingException e) {
// This should never happen.
e.printStackTrace();
}
return unicodeBytes;
}

private static String doubleQuoteString(String str) {
StringBuffer sb = new StringBuffer();
sb.append("\"");
sb.append(str);
sb.append("\"");
return sb.toString();
}
}

panfl
Nov 21st, 2006, 12:45 AM
Before I add user, I want to check whether the user exist.
I use:
ldapTemplate.search("",filter.encode(),new UserAttributesMapper());

I got exception:

java.lang.NullPointerException
at org.springframework.ldap.LdapTemplate$9.executeWit hContext(LdapTemplate.java:682)
at org.springframework.ldap.LdapTemplate.executeWithC ontext(LdapTemplate.java:641)
at org.springframework.ldap.LdapTemplate.executeReadO nly(LdapTemplate.java:628)
at org.springframework.ldap.LdapTemplate.lookup(LdapT emplate.java:678)


The excpetion occured in UserAttributeMapper.mapFromAttribute method.
private class UserAttributesMapper implements AttributesMapper {

public Object mapFromAttributes(Attributes attrs) throws NamingException {
User user = new User();
Log.info(CLASS_NAME+ " UserAttributesMapper.mapFromAttributes attrs.toString()="+attrs.toString()) ;

user.setUsername((String)attrs.get("cn").get());
user.setFirstName((String)attrs.get("givenName").get());
user.setLastName((String)attrs.get("sn").get());
user.setPassword(attrs.get("unicodePwd").get().toString());

return user;

}
}

In out log, I find there do not exist "unicodePwd" field in attrs.
my log:
DEBUG [http-8080-Processor22] - UserAttributesMapper.mapFromAttributes attrs.toStrin
g()={displayname=displayName: admin admin, givenname=givenName: admin, samaccounttype=sAMAccountType: 805306368, primarygroup
id=primaryGroupID: 513, objectclass=objectClass: top, person, organizationalPerson, user, admincount=adminCount: 1, badpasswo
rdtime=badPasswordTime: 128084908723125000, objectcategory=objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=TEST,DC=co
m, cn=cn: admin, useraccountcontrol=userAccountControl: 66048, userprincipalname=userPrincipalName: admin@TEST.com, codepage=
codePage: 0, distinguishedname=distinguishedName: CN=admin,CN=Users,DC=TEST,DC=com, whenchanged=whenChanged: 20061120083724.0
Z, whencreated=whenCreated: 20061115062602.0Z, pwdlastset=pwdLastSet: 128084854443593750, logoncount=logonCount: 1, accountex
pires=accountExpires: 9223372036854775807, lastlogoff=lastLogoff: 0, objectguid=objectGUID: ?>?vn?K???As?bH, sn=sn: admin, l
astlogon=lastLogon: 128084908756093750, usnchanged=uSNChanged: 9922343, usncreated=uSNCreated: 9921268, objectsid=objectSid:
  ~jA????~?j , countrycode=countryCode: 0, samaccountname=sAMAccountName: admin, instancetype=instanceType: 4,
memberof=memberOf: CN=Administrators,CN=Builtin,DC=TEST,DC=com, badpwdcount=badPwdCount: 0, name=name: admin}

rasky
Nov 21st, 2006, 03:46 AM
It's quite possible that the unicode password Attribute will only be returned under spacial circumstances. E.g. administrator privileges might be required, or it might be an operational attribute, in which case you'll need to ask for it specifically (using one of the methods which take an array of Attribute names).

mlarchet
Nov 21st, 2006, 08:42 AM
unicodePwd is only a writable attribute (only by admin user and via LDAPS connection).

It's used internally to update the real userPassword attribute which is invisible even for admin user.

russpitre
Nov 30th, 2006, 10:52 AM
I'm not sure if this helps but it may be worth looking at.

http://forum.java.sun.com/thread.jspa?threadID=592611&tstart=50

And for more AD information take a look at his other threads. He seems pretty knowledgable about AD

http://forum.java.sun.com/profile.jspa?userID=488701


Russ

panfl
Dec 4th, 2006, 10:01 PM
Thank you very mush guys.

After I setup LDAPS in my domain controller, I can add user to AD already.

But I find all of the added user are disabled.
Anybody meet this problem before?

ulsa
Dec 5th, 2006, 01:30 AM
I believe it's the userAccountControl (http://support.microsoft.com/kb/305144) field that controls this, among many other aspects. It's a bitfield and the second bit controls enabled/disabled.

In other words, if you currently have say 546 (512+32+2) in userAccountControl for your disabled users, you should instead set it to 544 (512+32).

panfl
Dec 7th, 2006, 05:15 AM
Thank you ulsa.

After I add below code, I can add user successfully.
context.setAttributeValue("userAccountControl",Integer.toString(UF_NORMAL_ACCOUNT));


Now problem is when I update user password, I get below exception:

org.springframework.ldap.UncategorizedLdapExceptio n: Operation failed; nested exception is javax.naming.directory.AttributeInUseException: [LDAP: error code 20
- 0000207E: AtrErr: DSID-03190617, #1:
0: 0000207E: DSID-03190617, problem 1006 (ATT_OR_VALUE_EXISTS), data 0, Att 9005a (unicodePwd)
]
javax.naming.directory.AttributeInUseException: [LDAP: error code 20 - 0000207E: AtrErr: DSID-03190617, #1:
0: 0000207E: DSID-03190617, problem 1006 (ATT_OR_VALUE_EXISTS), data 0, Att 9005a (unicodePwd)
]; remaining name 'cn=test'
at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.jav a:2972)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCt x.java:2934)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCt x.java:2740)
at com.sun.jndi.ldap.LdapCtx.c_modifyAttributes(LdapC tx.java:1440)
at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_mod ifyAttributes(ComponentDirContext.java:255)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContex t.modifyAttributes(PartialCompositeDirContext.java :172)
at javax.naming.directory.InitialDirContext.modifyAtt ributes(InitialDirContext.java:151)
at org.springframework.ldap.LdapTemplate$13.executeWi thContext(LdapTemplate.java:741)
at org.springframework.ldap.LdapTemplate.executeWithC ontext(LdapTemplate.java:641)
at org.springframework.ldap.LdapTemplate.executeReadW rite(LdapTemplate.java:636)
at org.springframework.ldap.LdapTemplate.modifyAttrib utes(LdapTemplate.java:738)


My code:

context.setAttributeValue("unicodePwd",LDAPUtil.createUnicodePassword((String) obj));
ldapTemplate.modifyAttributes(dn, context.getModificationItems());

ulsa
Dec 7th, 2006, 09:02 AM
Please check the contents of getModificationItems and post the results here.

panfl
Dec 7th, 2006, 08:20 PM
I add code:

ModificationItem[] milist= context.getModificationItems();
Log.debug( CLASS_NAME + " saveUser (User user) milist.length=" + milist.length);
for(int i=0;i<milist.length ;i++)
{
ModificationItem mi=milist[i];

Log.debug( CLASS_NAME + " saveUser (User user) mi.toString()=" + mi.toString());

}

The log is:


DEBUG [http-8080-Processor20] -
ldap.UserDAOLDAP saveUser (User user) milist.length=1
2006-12-08, 09:11:53 mcap_log debug
DEBUG [http-8080-Processor20] -
ldap.UserDAOLDAP saveUser (User user) mi.toString()=Add attribute: unicodePwd: [B@75725e


I think the problem is "Add attribute", how to set it as "Update attribute"?

ulsa
Dec 8th, 2006, 12:02 AM
The problem seems to be that Active Directory doesn't allow the attribute to be read, and thus gives us the false impression that it doesn't exist. Spring LDAP then believes the attribute should be added, but since the attribute in fact does exist, the ADD operation fails.

This can be avoided by forcing a REPLACE operation for this specific attribute. This will require significant changes in getModificationItems. A short-term solution is to manually change the operation for this attribute from DirContext.ADD_ATTRIBUTE to DirContext.REPLACE_ATTRIBUTE.

panfl
Dec 8th, 2006, 01:33 AM
:D
After I add below code all works. Thank you very much


ModificationItem[] milist= context.getModificationItems();
Log.debug( CLASS_NAME + " saveUser (User user) milist.length=" + milist.length);

for(int i=0;i<milist.length ;i++)
{
ModificationItem mi=milist[i];
Attribute attr=mi.getAttribute();
if("unicodePwd".equalsIgnoreCase(attr.getID()))
{
mi=new ModificationItem(DirContext.REPLACE_ATTRIBUTE ,attr);
milist[i]=mi;
break;
}
}

ldapTemplate.modifyAttributes(dn, milist);