5

I'm using the System.DirectoryServices.AccountManagement namespace to find domain users and their corresponding AD security groups. This works well.

I'm also using that namespace to query the local security groups on a remote server. I am able to find a security group and then list the users of that group no problem.

What I'm having issues with is displaying which LOCAL groups a DOMAIN user belongs to:

PrincipalContext localmachine = new PrincipalContext(ContextType.Machine, "ServerName");
PrincipalContext domain = new PrincipalContext(ContextType.Domain);

// find the user using the domain context (Works fine)
UserPrincipal user = UserPrincipal.FindByIdentity(domain, userName);

// if found - grab its groups
if (user != null)
{
    // The get groups method is the only method that would accept a new context
    PrincipalSearchResult<Principal> groups = user.GetGroups(localMachine);

    // no groups are returned .... removed rest of code
}

I'm attempting to use the GetGroups method passing in the localMachine PrincipalContext but no groups are returned.

The users exists only in the Domain AD. There is not an entry for this user in the local users on the localMachine. The domain users are added to local security groups.

Any ideas? I'd like to be able to pull a list of all local groups this domain user belongs to and then see if a certain groups exists in that list. The only option that is working now is for me to search certain groups on the system and see if the domain user belongs to that group.

Logan Garland
  • 242
  • 4
  • 12
  • Similar question here - hopefully of some use - http://stackoverflow.com/questions/4809460/determine-nested-groups-of-windowsidentity-instance – dash Jun 26 '12 at 22:24
  • I have tried doing it that way. The FindByIdentity method returns null when looking for the user on the machine. I presume this is because there isn't an actual local user created. It is a domain user. I've tried passing in the user name with and without the domain prepended. – Logan Garland Jun 26 '12 at 22:32
  • Digging through some old code, I find that I'd done it exactly the way you described; enumerating the local machine groups (via DirectorySearcher), and then enumerating those to see if I can find a group the user is a member of. We had a pretty shallow hierarchy, too. Sorry can't be of more help. – dash Jun 26 '12 at 22:51
  • Are you sure the user is a member of a local group, or could it be that the user is a member of a domain group that is a member of a local group. Therefore you would have to find all of the domain groups the user is a member of, and find all of the local groups that each of these domain groups is a member of. EDIT: Actually I did a test with a domain user in a local group and got the same result as you - ie. no result – Michael Jun 27 '12 at 01:09
  • Please refer to this Stack link.. http://stackoverflow.com/questions/12453804/how-to-set-up-access-for-users-in-active-directory-group/12491528#12491528 – RL89 Sep 20 '12 at 10:02

2 Answers2

3

The following code will return the local groups that a domain user is member of:

        PrincipalContext domain = new PrincipalContext(ContextType.Domain);
        UserPrincipal user = UserPrincipal.FindByIdentity(domain, userName);
        foreach (GroupPrincipal group in user.GetAuthorizationGroups())
        {
            if (group.Context.ConnectedServer == serverName)
                Console.Out.WriteLine("{0}\\{1}", group.Context.Name, group.SamAccountName);
        }
Michael
  • 8,891
  • 3
  • 29
  • 42
  • 1
    This code from my local machine only returns one connected server for about 30 groups. I expected the GetAuthorizationGroups() method to only return groups from the Context specified in the UserPrincipal object. Does that method also query the machine the code is running on? – Logan Garland Jun 27 '12 at 20:38
3

I know my answer is late, but this worked for me (after I tried all sorts of permutations):

private static IList<string> GetUserLocalGroups(string userAccountName, string computerName, string domainName)
{
  List<string> groups = new List<string>();

  // We have to deal with a local computer
  DirectoryEntry root = new DirectoryEntry(String.Format("WinNT://{0},Computer", computerName), null, null, AuthenticationTypes.Secure);


  foreach (DirectoryEntry groupDirectoryEntry in root.Children)
  {
    if (groupDirectoryEntry.SchemaClassName != "Group")
      continue;

    string groupName = groupDirectoryEntry.Name;
    Console.WriteLine("Checking: {0}", groupName);
    if (IsUserMemberOfGroup(groupDirectoryEntry, String.Format("WinNT://{0}/{1}", domainName, userAccountName)))
    {
      groups.Add(groupName);
    }
  }

  return groups;
}

private static bool IsUserMemberOfGroup(DirectoryEntry group, string userPath)
{
  return (bool)group.Invoke(
      "IsMember",
      new object[] { userPath }
      );
}

The call is something like this:

GetUserLocalGroups("samaccountname", "computerName.yourdomain", "yourdomain");
boggy
  • 3,674
  • 3
  • 33
  • 56