Поделиться через


Check membership of a group from user’s process access token

Question may be, I need to check If the user belong to a particular group or not? There are NetUser* APIs available in NetApi32.lib to list the groups a user belong to a group. You can actually check but then you will need to compare the string of the group you are interested to check and the list returned by the NetApi. Please see the sample available on NetUserGetGroups Function. This approach can be acceptable in some scenarios, but may not work in other.

In a domain environment, there are two domains A and B and have trust relationship in between them. An user of domain A, logged on to a machine in domain B. The application running as domainA\UserA, calls NetUserGetGroups to get the global groups of the user, for any purpose. Generally it should work fine and works fine, I have tested it on many environments, but this approach may fail as well. If the domain where the query should go, has not opened the port ( by firewall ) the API is going to use, then API will not able to get the list of groups for the user. To solve the problem, you need to open the port, which may not be possible because the management of DC on other end not want to do it at all. Now, How to solve it?

When the user logs on providing credentials, authenticated by the AD on DC successfully, gets the logon token, profile is loaded, desktop is created etc etc. The logon token has the information about the user, for what groups it belong to. When user launched any application, it will be launched by this logon token. So, the information about the groups is already within the process itself. You can check it with a tool called whoami (/all) in Windows directory. If we have any API to read this list then we don’t have to go to network again or use NetAPIs. GetTokenInformation Function can be used to list the groups and for other purposes. Is there an API to actually check if the user belong to a particular group? CheckTokenMembership Function can be used for this purpose. API does not look for the group by its name, but by SID. If we have the name, we can convert to SID and pass to CheckTokenMembership. Demo sample code will look like below--

 #include<windows.h>
#include<Sddl.h>
#pragma comment(lib,"Advapi32.lib")
int main (int argc, CHAR * argv[]) 
{
BOOL bStatus;
BOOL bIsMember;
SID_NAME_USE sid_name_use;
DWORD dwDomainNameSize;
TCHAR tszDomainName [256];
PSID pSidToCheck;
DWORD cbsid=1024;
LPBYTE pPDC = NULL;
HANDLE hToken;

    if (argc != 2){
        printf("\nUSAGE: %ls grouptocheck\n\n", argv[0]);
        return 1;
    }

    bStatus = OpenProcessToken(OpenProcess(GENERIC_ALL, FALSE, GetCurrentProcessId()), GENERIC_ALL, &hToken);
    if (!bStatus){
        printf("OpenProcessToken failed: %u\n", GetLastError());
        return 1;
    }

    pSidToCheck = malloc (cbsid );
    dwDomainNameSize = sizeof(tszDomainName);
    bStatus = LookupAccountName(
        NULL,       // address of string for system name
        argv[1],      // address of string for account name
        pSidToCheck,      // address of security identifier
        &cbsid,      // address of size of security identifier
        tszDomainName,      // address of string for referenced domain 
        &dwDomainNameSize,      // address of size of domain string
        &sid_name_use       // address of SID-type indicator
    );

    if (!bStatus){
        printf("LookupAccountName failed: %u\n", GetLastError());
        return 1;
    }

    bStatus = CheckTokenMembership(/*hToken*/ NULL, pSidToCheck, &bIsMember);
    if (!bStatus){
        printf("CheckTokenMembership failed: %u\n", GetLastError());
        return 1;
    }

    if (bIsMember)
        printf("The user is a member of the group.\n");
    else
        printf("The user is NOT a member of the group.\n");    
    
    return 0;

}

Nitin Dhawan

Windows SDK - Microsoft