diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index ba90ad061f2..db7d028efc5 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -622,13 +622,55 @@ AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges, * Failure: FALSE. */ BOOL WINAPI -CheckTokenMembership( HANDLE TokenHandle, PSID SidToCheck, - PBOOL IsMember ) +CheckTokenMembership( HANDLE token, PSID sid_to_check, + PBOOL is_member ) { - FIXME("(%p %p %p) stub!\n", TokenHandle, SidToCheck, IsMember); + PTOKEN_GROUPS token_groups; + DWORD size, i; - *IsMember = TRUE; - return(TRUE); + TRACE("(%p %s %p)\n", token, debugstr_sid(sid_to_check), is_member); + + *is_member = FALSE; + + if (!token) + { + if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token)) + return FALSE; + } + + if (!GetTokenInformation(token, TokenGroups, NULL, 0, &size)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return FALSE; + } + + token_groups = HeapAlloc(GetProcessHeap(), 0, size); + if (!token_groups) + return FALSE; + + if (!GetTokenInformation(token, TokenGroups, token_groups, size, &size)) + { + HeapFree(GetProcessHeap(), 0, token_groups); + return FALSE; + } + + for (i = 0; i < token_groups->GroupCount; i++) + { + TRACE("Groups[%d]: {0x%x, %s}\n", i, + token_groups->Groups[i].Attributes, + debugstr_sid(token_groups->Groups[i].Sid)); + if ((token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) && + EqualSid(sid_to_check, token_groups->Groups[i].Sid)) + { + *is_member = TRUE; + TRACE("sid enabled and found in token\n"); + break; + } + } + + HeapFree(GetProcessHeap(), 0, token_groups); + + return TRUE; } /****************************************************************************** diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index f6104333674..1ca5a01d89f 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -3200,6 +3200,49 @@ static void test_GetSidSubAuthority(void) LocalFree(psid); } +static void test_CheckTokenMembership(void) +{ + PTOKEN_GROUPS token_groups; + DWORD size; + HANDLE token; + BOOL is_member; + BOOL ret; + DWORD i; + + ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token); + ok(ret, "OpenProcessToken failed with error %d\n", GetLastError()); + + /* groups */ + ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "GetTokenInformation(TokenGroups) %s with error %d\n", + ret ? "succeeded" : "failed", GetLastError()); + token_groups = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size); + ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError()); + + for (i = 0; i < token_groups->GroupCount; i++) + { + if (token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) + break; + } + + if (i == token_groups->GroupCount) + { + HeapFree(GetProcessHeap(), 0, token_groups); + CloseHandle(token); + skip("user not a member of any group\n"); + return; + } + + ret = CheckTokenMembership(token, token_groups->Groups[i].Sid, &is_member); + ok(ret, "CheckTokenMembership failed with error %d\n", GetLastError()); + ok(is_member, "CheckTokenMembership should have detected sid as member"); + + HeapFree(GetProcessHeap(), 0, token_groups); + CloseHandle(token); +} + START_TEST(security) { init(); @@ -3230,4 +3273,5 @@ START_TEST(security) test_acls(); test_GetSecurityInfo(); test_GetSidSubAuthority(); + test_CheckTokenMembership(); }