2 out of 4 rated this helpful - Rate this topic

CheckTokenMembership function

Applies to: desktop apps only

The CheckTokenMembership function determines whether a specified security identifier (SID) is enabled in an access token. If you want to determine group membership for app container tokens, you need to use the CheckTokenMembershipEx function.

Syntax

BOOL WINAPI CheckTokenMembership(
  __in_opt  HANDLE TokenHandle,
  __in      PSID SidToCheck,
  __out     PBOOL IsMember
);

Parameters

TokenHandle [in, optional]

A handle to an access token. The handle must have TOKEN_QUERY access to the token. The token must be an impersonation token.

If TokenHandle is NULL, CheckTokenMembership uses the impersonation token of the calling thread. If the thread is not impersonating, the function duplicates the thread's primary token to create an impersonation token.

SidToCheck [in]

A pointer to a SID structure. The CheckTokenMembership function checks for the presence of this SID in the user and group SIDs of the access token.

IsMember [out]

A pointer to a variable that receives the results of the check. If the SID is present and has the SE_GROUP_ENABLED attribute, IsMember returns TRUE; otherwise, it returns FALSE.

Return value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

Remarks

The CheckTokenMembership function simplifies the process of determining whether a SID is both present and enabled in an access token.

Even if a SID is present in the token, the system may not use the SID in an access check. The SID may be disabled or have the SE_GROUP_USE_FOR_DENY_ONLY attribute. The system uses only enabled SIDs to grant access when performing an access check. For more information, see SID Attributes in an Access Token.

If TokenHandle is a restricted token, or if TokenHandle is NULL and the current effective token of the calling thread is a restricted token, CheckTokenMembership also checks whether the SID is present in the list of restricting SIDs.

Examples

The following example shows checking a token for membership in the Administrators local group.


BOOL IsUserAdmin(VOID)
/*++ 
Routine Description: This routine returns TRUE if the caller's
process is a member of the Administrators local group. Caller is NOT
expected to be impersonating anyone and is expected to be able to
open its own process and process token. 
Arguments: None. 
Return Value: 
   TRUE - Caller has Administrators local group. 
   FALSE - Caller does not have Administrators local group. --
*/ 
{
BOOL b;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup; 
b = AllocateAndInitializeSid(
    &NtAuthority,
    2,
    SECURITY_BUILTIN_DOMAIN_RID,
    DOMAIN_ALIAS_RID_ADMINS,
    0, 0, 0, 0, 0, 0,
    &AdministratorsGroup); 
if(b) 
{
    if (!CheckTokenMembership( NULL, AdministratorsGroup, &b)) 
    {
         b = FALSE;
    } 
    FreeSid(AdministratorsGroup); 
}

return(b);
}


Requirements

Minimum supported client

Windows XP

Minimum supported server

Windows Server 2003

Header

Winbase.h (include Windows.h)

Library

Advapi32.lib

DLL

Advapi32.dll

See also

Access Control Overview
Basic Access Control Functions
AccessCheck
CheckTokenMembershipEx
CreateRestrictedToken

 

 

Send comments about this topic to Microsoft

Build date: 3/7/2012

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
UAC Integrity Level Caveat
Although WHOAMI.EXE /GROUPS shows an SID for Mandatory Labels like Medium Integrity Level S-1-16-8192 and High Integrity Level S-1-16-12288, these SID's are not recognized by CheckTokenMembership.  To check for integrity level you need to make calls to the functions GetTokenInformation and GetSidSubAuthority.  See sample code in the following:

http://www.codeproject.com/KB/vista-security/UACSelfElevation.aspx

Vista and Windows 7 UAC caveats
WHOAMI.EXE  /GROUPS will show the following for an account in the local administrator group when run from a process that does not have elevated integrity level:
Group Name                  Type  SID                 Attributes
BUILTIN\Administrators  Alias  S-1-5-32-544  Group used for deny only
Mandatory Label\High Mandatory Level  Label S-1-16-8192  Mandatory group, Enabled by default, Enabled group

For an elevated process it shows:
BUILTIN\Administrators  Alias  S-1-5-32-544  Mandatory group, Enabled by default, Enabled group, Group owner
Mandatory Label\High Mandatory Level  Label S-1-16-12288  Mandatory group, Enabled by default, Enabled group

With UAC enabled and a process run by an admin account that is not elevated to high integrity level, CheckTokenMembership logically returns False due to the "Group used for deny only" attribute.  When the process is elevated, CheckTokenMembership returns true.

Note that you get the same behavior for a Domain Admin account which displays in WHOAMI /groups for an offline logon to a workstation as follows:
Group Name                  Type                       SID                                                               Attributes
                                      Unknown SID type  S-1-5-21-xxxxxxxxx-xxxxxxx-xxxxxxxxxx-512  Mandatory group, Enabled by default, Enabled group

For the SID of a domain admin account with a Medium Integrity Level process, when passed to CheckTokenMembership, the IsMember return value is False.  In an elevated process when the Domain Admin SID is passed to CheckTokenMembership the IsMember return value is True.  This indicates consistent behavior for CheckTokenMembership but inconsistent behavior/output for WHOAMI.

In addition, if a non-admin domain group is added to the BUILTIN\Administrators group of the workstation, then WHOAMI and CheckTokenMembership consistently show the group as enabled whether the process is elevated or not. 


IsUserAdmin works strange
IsUserAdmin example provided returns false for my admin account under Vista with UAC disabled. However the following example returns true:
BOOL IsUserAdmin(HANDLE hToken)
{
HANDLE hAccessToken;
UCHAR InfoBuffer[4096];
PTOKEN_GROUPS ptgGroups = (PTOKEN_GROUPS)InfoBuffer;
DWORD dwInfoBufferSize;
PSID psidAdministrators;
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
UINT x;
BOOL bSuccess;


if (hToken)
hAccessToken = hToken;
else
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&hAccessToken))
// return(FALSE);
return(TRUE);

bSuccess =GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,
sizeof(InfoBuffer), &dwInfoBufferSize);

CloseHandle(hAccessToken);

if( !bSuccess )
// return FALSE;
return(TRUE);

if(!AllocateAndInitializeSid(&siaNtAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&psidAdministrators))
// return FALSE;
return(TRUE);

// assume that we don't find the admin SID.
bSuccess = FALSE;

for(x=0;x<ptgGroups->GroupCount;x++)
{
if(EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) )
{
bSuccess = TRUE;
break;
}
}
FreeSid(psidAdministrators);
return bSuccess;
}