4

Given a group name and a user account, I would like to know if the supplied user belongs to a particular group. The user can be a local user or a domain user and the group could be a local group or a domain group and the group could also be nested inside other groups. In short I am looking for a function like bool IsUserMemberOf(User, Group) that will internally call the appropriate Win32 APIs to do the search. I guess the process making the above query should have the necessary privileges to query local and AD groups. I guess runing the process under enterprise admin account should do the job of querying any DCs in the forest but may not work for machines that are not part of a domain. Any ideas on what account this querying process should run so that it can query the LSA as well as the AD?

Mormegil
  • 7,955
  • 4
  • 42
  • 77
msvcyc
  • 2,569
  • 4
  • 24
  • 30

3 Answers3

1

You need to read up on GetTokenInformation (TOKEN_USER), AllocateAndInitializeSid and CheckTokenMemberShip.

rtn
  • 127,556
  • 20
  • 111
  • 121
  • The answer was never accepted, possibly because the OP was in the same situation I'm in: I don't have a token, just a SID & name each for the account and group. Is there any way of getting a token without knowing the password? Or, is there an LSA function that will do it with just the SID? I'm still stuck after hunting. – Nicholas Wilson Dec 19 '12 at 11:22
  • I'm in the same position, there are two microsoft official examples, neither work, both always return administrator group for every user. – Owl Dec 01 '17 at 10:50
1

UserPrincipal.IsMemberOf(GroupPrincipal) "returns a Boolean value that specifies whether the principal is a member of the specified group".

Mark Brackett
  • 84,552
  • 17
  • 108
  • 152
1

Magnus is right, you must use CheckTokenMembership

You can find a sample in UnlockPolicy.c (download the full source here), function ShouldUnlockForUser and UsagerEstDansGroupe (excuse my French;).

Here is the guts of it :

HRESULT IsUserInGroup(HANDLE user, const wchar_t* groupe)
{
    HRESULT result = E_FAIL;
    SID_NAME_USE snu;
    WCHAR szDomain[256];
    DWORD dwSidSize = 0;
    DWORD dwSize = sizeof szDomain / sizeof * szDomain;

    if ((LookupAccountNameW(NULL, groupe, 0, &dwSidSize, szDomain, &dwSize, &snu) == 0)
            && (ERROR_INSUFFICIENT_BUFFER == GetLastError()))
    {
        SID* pSid = (SID*)malloc(dwSidSize);

        if (LookupAccountNameW(NULL, groupe, pSid, &dwSidSize, szDomain, &dwSize, &snu))
        {
            BOOL b;

            if (CheckTokenMembership(user, pSid, &b))
            {
                if (b == TRUE)
                {
                    result = S_OK;
                }
            }
            else
            {
                result = S_FALSE;
            }
        }

        //Si tout vas bien (la presque totalitée des cas), on delete notre pointeur
        //avec le bon operateur.
        free(pSid);
    }

    return result;
}
ixe013
  • 9,559
  • 3
  • 46
  • 77
  • What is a "handle" ? Is there some way to convert a username to a handle? – Owl Dec 01 '17 at 10:49
  • A handle is returned by a method that either authenticates the user (like `LogonUser`) or retreives it from the current context (like `WTSQueryUserToken`). Which one to use greatly depends on context... Ask a question, the SO community will provide more helpful answer ! – ixe013 Dec 02 '17 at 15:29
  • 2
    Note this wont work for an administrator. Administrators are only in the group when the priveledges are escalated. – Owl Dec 05 '17 at 13:29