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
This is a sample Java application that utilizes JNDI to access Active Directory and retrieves group membership of a user. This application uses computed tokenGroups attribute of a user object in order to get complete list of groups a user belongs to, including membership acquired through nested groups and built-in groups (ex. Domain Users).
Credits
There is almost no my code in this sample. I constructed this application by pulling together snippets from various posts on the Naming and Directory (JNDI) Forum , but since it took me a while to pull this all together I think there may be a value of having such useful sample all in one place.
Specifically I used the post (see link below) by Steven Adler. Steven also provided me with a function to convert binary value of a SID into its string representation. I needed this function since tokenGroups stores group SIDs in binary format.
http://forum.java.sun.com/thread.jspa?threadID=581444&tstart=150
package adconnection;
import java.util.Hashtable;
import javax.naming.*;
import javax.naming.ldap.*;
import javax.naming.directory.*;
public class memberof {
public static void main (String[] args) {
Hashtable env = new Hashtable();
String adminName = "CN=Administrator,CN=Users,DC=ADATUM,DC=COM";
String adminPassword = "XXXXXXXXXXX";
String ldapURL = "ldap://adfsaccount.adatum.com:389";
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
//set security credentials, note using simple cleartext authentication
env.put(Context.SECURITY_AUTHENTICATION,"simple");
env.put(Context.SECURITY_PRINCIPAL,adminName);
env.put(Context.SECURITY_CREDENTIALS,adminPassword);
//connect to my domain controller
env.put(Context.PROVIDER_URL,ldapURL);
//specify attributes to be returned in binary format
env.put("java.naming.ldap.attributes.binary","tokenGroups");
try {
//Create the initial directory context
LdapContext ctx = new InitialLdapContext(env,null);
//Create the search controls
SearchControls userSearchCtls = new SearchControls();
//Specify the search scope
userSearchCtls.setSearchScope(SearchControls.OBJECT_SCOPE);
//specify the LDAP search filter to find the user in question
String userSearchFilter = "(objectClass=user)";
//paceholder for an LDAP filter that will store SIDs of the groups the user belongs to
StringBuffer groupsSearchFilter = new StringBuffer();
groupsSearchFilter.append("(|");
//Specify the Base for the search
String userSearchBase = "CN=Alex Tcherni,CN=Users,DC=adatum,DC=com";
//Specify the attributes to return
String userReturnedAtts[]={"tokenGroups"};
userSearchCtls.setReturningAttributes(userReturnedAtts);
//Search for objects using the filter
NamingEnumeration userAnswer = ctx.search(userSearchBase, userSearchFilter, userSearchCtls);
//Loop through the search results
while (userAnswer.hasMoreElements()) {
SearchResult sr = (SearchResult)userAnswer.next();
Attributes attrs = sr.getAttributes();
if (attrs != null) {
try {
for (NamingEnumeration ae = attrs.getAll();ae.hasMore();) {
Attribute attr = (Attribute)ae.next();
for (NamingEnumeration e = attr.getAll();e.hasMore();) {
byte[] sid = (byte[])e.next();
groupsSearchFilter.append("(objectSid=" + binarySidToStringSid(sid) + ")");
}
groupsSearchFilter.append(")");
}
}
catch (NamingException e) {
System.err.println("Problem listing membership: " + e);
}
}
}
// Search for groups the user belongs to in order to get their names
//Create the search controls
SearchControls groupsSearchCtls = new SearchControls();
//Specify the search scope
groupsSearchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
//Specify the Base for the search
String groupsSearchBase = "DC=adatum,DC=com";
//Specify the attributes to return
String groupsReturnedAtts[]={"sAMAccountName"};
groupsSearchCtls.setReturningAttributes(groupsReturnedAtts);
//Search for objects using the filter
NamingEnumeration groupsAnswer = ctx.search(groupsSearchBase, groupsSearchFilter.toString(), groupsSearchCtls);
//Loop through the search results
while (groupsAnswer.hasMoreElements()) {
SearchResult sr = (SearchResult)groupsAnswer.next();
Attributes attrs = sr.getAttributes();
if (attrs != null) {
System.out.println(attrs.get("sAMAccountName").get());
}
}
ctx.close();
}
catch (NamingException e) {
System.err.println("Problem searching directory: " + e);
}
}
public static final String binarySidToStringSid( byte[] SID ) {
String strSID = "";
//convert the SID into string format
long version;
long authority;
long count;
long rid;
strSID = "S";
version = SID[0];
strSID = strSID + "-" + Long.toString(version);
authority = SID[4];
for (int i = 0;i<4;i++) {
authority <<= 8;
authority += SID[4+i] & 0xFF;
}
strSID = strSID + "-" + Long.toString(authority);
count = SID[2];
count <<= 8;
count += SID[1] & 0xFF;
for (int j=0;j<count;j++) {
rid = SID[11 + (j*4)] & 0xFF;
for (int k=1;k<4;k++) {
rid <<= 8;
rid += SID[11-k + (j*4)] & 0xFF;
}
strSID = strSID + "-" + Long.toString(rid);
}
return strSID;
}
}