Sample Java application that retrieves group membership of an Active Directory user account.

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 https://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.

https://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;
     
    }

}

memberof.java