From 561bed7b55ea36aecbfcda4da919bc5a77d43636 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sun, 8 Oct 2017 11:06:20 +0100 Subject: [PATCH] [ADVAPI32_WINETEST] Sync with Wine Staging 2.16. CORE-13762 --- .../winetests/advapi32/CMakeLists.txt | 2 +- .../rostests/winetests/advapi32/eventlog.c | 4 - .../rostests/winetests/advapi32/registry.c | 199 ++- .../rostests/winetests/advapi32/security.c | 1418 +++++++++++------ 4 files changed, 1151 insertions(+), 472 deletions(-) diff --git a/modules/rostests/winetests/advapi32/CMakeLists.txt b/modules/rostests/winetests/advapi32/CMakeLists.txt index d6958f4c634..5005dd5adfe 100644 --- a/modules/rostests/winetests/advapi32/CMakeLists.txt +++ b/modules/rostests/winetests/advapi32/CMakeLists.txt @@ -22,5 +22,5 @@ if(NOT MSVC) endif() set_module_type(advapi32_winetest win32cui) -add_importlibs(advapi32_winetest advapi32 ole32 msvcrt kernel32 ntdll) +add_importlibs(advapi32_winetest advapi32 ole32 user32 msvcrt kernel32 ntdll) add_rostests_file(TARGET advapi32_winetest) diff --git a/modules/rostests/winetests/advapi32/eventlog.c b/modules/rostests/winetests/advapi32/eventlog.c index be9b4673ae8..8c78dcf73f5 100644 --- a/modules/rostests/winetests/advapi32/eventlog.c +++ b/modules/rostests/winetests/advapi32/eventlog.c @@ -1209,11 +1209,7 @@ static void test_start_trace(void) ret = StartTraceA(&handle, sessionname, properties); todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret); -#ifndef __REACTOS__ - properties->Wnode.Guid = (GUID){0}; -#else memset(&properties->Wnode.Guid, 0, sizeof(properties->Wnode.Guid)); -#endif properties->LogFileNameOffset = 0; ret = StartTraceA(&handle, sessionname, properties); diff --git a/modules/rostests/winetests/advapi32/registry.c b/modules/rostests/winetests/advapi32/registry.c index 8af1ebf938b..053113a2936 100644 --- a/modules/rostests/winetests/advapi32/registry.c +++ b/modules/rostests/winetests/advapi32/registry.c @@ -3523,40 +3523,76 @@ static void test_RegNotifyChangeKeyValue(void) CloseHandle(event); } +static const char *dbgstr_longlong(ULONGLONG ll) +{ + static char buf[16][64]; + static int idx; + + idx &= 0x0f; + + if (sizeof(ll) > sizeof(unsigned long) && ll >> 32) + sprintf(buf[idx], "0x%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll); + else + sprintf(buf[idx], "0x%08lx", (unsigned long)ll); + + return buf[idx++]; +} + +#define cmp_li(a, b, c) cmp_li_real(a, b, c, __LINE__) +static void cmp_li_real(LARGE_INTEGER *l1, LARGE_INTEGER *l2, LONGLONG slack, int line) +{ + LONGLONG diff = l2->QuadPart - l1->QuadPart; + if (diff < 0) diff = -diff; + ok_(__FILE__, line)(diff <= slack, "values don't match: %s/%s\n", + dbgstr_longlong(l1->QuadPart), dbgstr_longlong(l2->QuadPart)); +} + static void test_RegQueryValueExPerformanceData(void) { - DWORD cbData, len; + static const WCHAR globalW[] = { 'G','l','o','b','a','l',0 }; + static const WCHAR dummyW[5] = { 'd','u','m','m','y' }; + static const char * const names[] = { NULL, "", "Global", "2" "invalid counter name" }; + DWORD cbData, len, i, type; BYTE *value; DWORD dwret; LONG limit = 6; PERF_DATA_BLOCK *pdb; + HKEY hkey; + BYTE buf[256 + sizeof(PERF_DATA_BLOCK)]; /* Test with data == NULL */ dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, NULL, &cbData ); - todo_wine ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret ); + ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret ); + + dwret = RegQueryValueExW( HKEY_PERFORMANCE_DATA, globalW, NULL, NULL, NULL, &cbData ); + ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret ); /* Test ERROR_MORE_DATA, start with small buffer */ len = 10; value = HeapAlloc(GetProcessHeap(), 0, len); cbData = len; - dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, value, &cbData ); - todo_wine ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret ); + type = 0xdeadbeef; + dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData ); + ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret ); + ok(type == REG_BINARY, "got %u\n", type); while( dwret == ERROR_MORE_DATA && limit) { len = len * 10; value = HeapReAlloc( GetProcessHeap(), 0, value, len ); cbData = len; - dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, value, &cbData ); + type = 0xdeadbeef; + dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData ); limit--; } ok(limit > 0, "too many times ERROR_MORE_DATA returned\n"); - todo_wine ok(dwret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", dwret); + ok(dwret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", dwret); + ok(type == REG_BINARY, "got %u\n", type); /* Check returned data */ if (dwret == ERROR_SUCCESS) { - todo_wine ok(len >= sizeof(PERF_DATA_BLOCK), "got size %d\n", len); + ok(len >= sizeof(PERF_DATA_BLOCK), "got size %d\n", len); if (len >= sizeof(PERF_DATA_BLOCK)) { pdb = (PERF_DATA_BLOCK*) value; ok(pdb->Signature[0] == 'P', "expected Signature[0] = 'P', got 0x%x\n", pdb->Signature[0]); @@ -3568,8 +3604,155 @@ static void test_RegQueryValueExPerformanceData(void) } HeapFree(GetProcessHeap(), 0, value); -} + for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) + { + cbData = 0xdeadbeef; + dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData); + ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); + ok(cbData == 0, "got %u\n", cbData); + + cbData = 0; + dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData); + ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); + ok(cbData == 0, "got %u\n", cbData); + + cbData = 0xdeadbeef; + dwret = RegQueryValueExA(HKEY_PERFORMANCE_TEXT, names[i], NULL, NULL, NULL, &cbData); +todo_wine + ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); + ok(cbData == 0, "got %u\n", cbData); + + cbData = 0; + dwret = RegQueryValueExA(HKEY_PERFORMANCE_TEXT, names[i], NULL, NULL, NULL, &cbData); +todo_wine + ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); + ok(cbData == 0, "got %u\n", cbData); + + cbData = 0xdeadbeef; + dwret = RegQueryValueExA(HKEY_PERFORMANCE_NLSTEXT, names[i], NULL, NULL, NULL, &cbData); +todo_wine + ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); + ok(cbData == 0, "got %u\n", cbData); + + cbData = 0; + dwret = RegQueryValueExA(HKEY_PERFORMANCE_NLSTEXT, names[i], NULL, NULL, NULL, &cbData); +todo_wine + ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); + ok(cbData == 0, "got %u\n", cbData); + } + + memset(buf, 0x77, sizeof(buf)); + type = 0xdeadbeef; + cbData = sizeof(buf); + dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "invalid counter name", NULL, &type, buf, &cbData); + ok(dwret == ERROR_SUCCESS, "got %u\n", dwret); + ok(type == REG_BINARY, "got %u\n", type); + if (dwret == ERROR_SUCCESS) + { + SYSTEMTIME st; + WCHAR sysname[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD sysname_len; + LARGE_INTEGER counter, freq, ftime; + + GetSystemTime(&st); + GetSystemTimeAsFileTime((FILETIME *)&ftime); + QueryPerformanceCounter(&counter); + QueryPerformanceFrequency(&freq); + + sysname_len = MAX_COMPUTERNAME_LENGTH + 1; + GetComputerNameW(sysname, &sysname_len); + + pdb = (PERF_DATA_BLOCK *)buf; + ok(pdb->Signature[0] == 'P', "got '%c'\n", pdb->Signature[0]); + ok(pdb->Signature[1] == 'E', "got '%c'\n", pdb->Signature[1]); + ok(pdb->Signature[2] == 'R', "got '%c'\n", pdb->Signature[2]); + ok(pdb->Signature[3] == 'F', "got '%c'\n", pdb->Signature[3]); + + ok(pdb->LittleEndian == 1, "got %u\n", pdb->LittleEndian); + ok(pdb->Version == 1, "got %u\n", pdb->Version); + ok(pdb->Revision == 1, "got %u\n", pdb->Revision); + len = (sizeof(*pdb) + pdb->SystemNameLength + 7) & ~7; + ok(pdb->TotalByteLength == len, "got %u vs %u\n", pdb->TotalByteLength, len); + ok(pdb->HeaderLength == pdb->TotalByteLength, "got %u\n", pdb->HeaderLength); + ok(pdb->NumObjectTypes == 0, "got %u\n", pdb->NumObjectTypes); +todo_wine + ok(pdb->DefaultObject != 0, "got %u\n", pdb->DefaultObject); + ok(pdb->SystemTime.wYear == st.wYear, "got %u\n", pdb->SystemTime.wYear); + ok(pdb->SystemTime.wMonth == st.wMonth, "got %u\n", pdb->SystemTime.wMonth); + ok(pdb->SystemTime.wDayOfWeek == st.wDayOfWeek, "got %u\n", pdb->SystemTime.wDayOfWeek); + ok(pdb->SystemTime.wDay == st.wDay, "got %u\n", pdb->SystemTime.wDay); + if (U(pdb->PerfTime).LowPart != 0x77777777) /* TestBot is broken */ + cmp_li(&pdb->PerfTime, &counter, freq.QuadPart); + if (U(pdb->PerfFreq).LowPart != 0x77777777) /* TestBot is broken */ + cmp_li(&pdb->PerfFreq, &freq, 0); + cmp_li(&pdb->PerfTime100nSec, &ftime, 200000); /* TestBot needs huge slack value */ + ok(pdb->SystemNameLength == (sysname_len + 1) * sizeof(WCHAR), "expected %u, got %u\n", + (sysname_len + 1) * sizeof(WCHAR), pdb->SystemNameLength); + ok(pdb->SystemNameOffset == sizeof(*pdb), "got %u\n", pdb->SystemNameOffset); + ok(!lstrcmpW(sysname, (LPCWSTR)(pdb + 1)), "%s != %s\n", + wine_dbgstr_w(sysname), wine_dbgstr_w((LPCWSTR)(pdb + 1))); + + len = pdb->TotalByteLength - (sizeof(*pdb) + pdb->SystemNameLength); + if (len) + { + BYTE remainder[8], *p; + + memset(remainder, 0x77, sizeof(remainder)); + p = buf + sizeof(*pdb) + pdb->SystemNameLength; + ok(!memcmp(p, remainder, len), "remainder: %02x,%02x...\n", p[0], p[1]); + } + } + + dwret = RegOpenKeyA(HKEY_PERFORMANCE_DATA, NULL, &hkey); +todo_wine + ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); + + dwret = RegOpenKeyA(HKEY_PERFORMANCE_DATA, "Global", &hkey); +todo_wine + ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); + + dwret = RegOpenKeyExA(HKEY_PERFORMANCE_DATA, "Global", 0, KEY_READ, &hkey); +todo_wine + ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); + + dwret = RegQueryValueA(HKEY_PERFORMANCE_DATA, "Global", NULL, (LONG *)&cbData); +todo_wine + ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); + + dwret = RegSetValueA(HKEY_PERFORMANCE_DATA, "Global", REG_SZ, "dummy", 4); +todo_wine + ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); + + dwret = RegSetValueExA(HKEY_PERFORMANCE_DATA, "Global", 0, REG_SZ, (const BYTE *)"dummy", 40); +todo_wine + ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); + + cbData = sizeof(buf); + dwret = RegEnumKeyA(HKEY_PERFORMANCE_DATA, 0, (LPSTR)buf, cbData); +todo_wine + ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); + + cbData = sizeof(buf); + dwret = RegEnumValueA(HKEY_PERFORMANCE_DATA, 0, (LPSTR)buf, &cbData, NULL, NULL, NULL, NULL); +todo_wine + ok(dwret == ERROR_MORE_DATA, "got %u\n", dwret); +todo_wine + ok(cbData == sizeof(buf), "got %u\n", cbData); + + dwret = RegEnumValueA(HKEY_PERFORMANCE_DATA, 0, NULL, &cbData, NULL, NULL, NULL, NULL); + ok(dwret == ERROR_INVALID_PARAMETER, "got %u\n", dwret); + + if (pRegSetKeyValueW) + { + dwret = pRegSetKeyValueW(HKEY_PERFORMANCE_DATA, NULL, globalW, REG_SZ, dummyW, sizeof(dummyW)); +todo_wine + ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); + } + + dwret = RegCloseKey(HKEY_PERFORMANCE_DATA); + ok(dwret == ERROR_SUCCESS, "got %u\n", dwret); +} START_TEST(registry) { diff --git a/modules/rostests/winetests/advapi32/security.c b/modules/rostests/winetests/advapi32/security.c index d03796964ba..7ca17b71e85 100644 --- a/modules/rostests/winetests/advapi32/security.c +++ b/modules/rostests/winetests/advapi32/security.c @@ -89,7 +89,6 @@ static VOID (WINAPI *pBuildTrusteeWithObjectsAndSidA)( PTRUSTEEA pTrustee, PSID pSid ); static LPSTR (WINAPI *pGetTrusteeNameA)( PTRUSTEEA pTrustee ); static BOOL (WINAPI *pMakeSelfRelativeSD)( PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, LPDWORD ); -static BOOL (WINAPI *pConvertSidToStringSidA)( PSID pSid, LPSTR *str ); static BOOL (WINAPI *pConvertStringSidToSidA)( LPCSTR str, PSID pSid ); static BOOL (WINAPI *pCheckTokenMembership)(HANDLE, PSID, PBOOL); static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD, @@ -157,9 +156,8 @@ static const char* debugstr_sid(PSID sid) DWORD le = GetLastError(); char* res = debugsid_str[debugsid_index]; debugsid_index = (debugsid_index + 1) % SID_SLOTS; - if (!pConvertSidToStringSidA) - strcpy(res, "missing ConvertSidToStringSidA"); - else if (!pConvertSidToStringSidA(sid, &sidstr)) + + if (!ConvertSidToStringSidA(sid, &sidstr)) sprintf(res, "ConvertSidToStringSidA failed le=%u", GetLastError()); else if (strlen(sidstr) > sizeof(*debugsid_str) - 1) { @@ -218,14 +216,13 @@ static void init(void) pGetSecurityInfo = (void *)GetProcAddress(hmod, "GetSecurityInfo"); pSetSecurityInfo = (void *)GetProcAddress(hmod, "SetSecurityInfo"); pCreateRestrictedToken = (void *)GetProcAddress(hmod, "CreateRestrictedToken"); - pConvertSidToStringSidA = (void *)GetProcAddress(hmod, "ConvertSidToStringSidA"); pConvertStringSidToSidA = (void *)GetProcAddress(hmod, "ConvertStringSidToSidA"); pGetAclInformation = (void *)GetProcAddress(hmod, "GetAclInformation"); pGetAce = (void *)GetProcAddress(hmod, "GetAce"); pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid"); pGetSidIdentifierAuthority = (void *)GetProcAddress(hmod, "GetSidIdentifierAuthority"); - pGetExplicitEntriesFromAclW = (void *)GetProcAddress(hmod, "GetExplicitEntriesFromAclW"); pDuplicateTokenEx = (void *)GetProcAddress(hmod, "DuplicateTokenEx"); + pGetExplicitEntriesFromAclW = (void *)GetProcAddress(hmod, "GetExplicitEntriesFromAclW"); myARGC = winetest_get_mainargs( &myARGV ); } @@ -363,7 +360,7 @@ static void test_sid(void) BOOL r; LPSTR str; - if( !pConvertSidToStringSidA || !pConvertStringSidToSidA ) + if( !pConvertStringSidToSidA ) { win_skip("ConvertSidToStringSidA or ConvertStringSidToSidA not available\n"); return; @@ -407,7 +404,7 @@ static void test_sid(void) r = AllocateAndInitializeSid( &refs[i].auth, 1,1,0,0,0,0,0,0,0, &psid ); ok( r, "failed to allocate sid\n" ); - r = pConvertSidToStringSidA( psid, &str ); + r = ConvertSidToStringSidA( psid, &str ); ok( r, "failed to convert sid\n" ); if (r) { @@ -475,7 +472,7 @@ static void test_sid(void) *GetSidSubAuthority(psid, n) = 0; } - r = pConvertSidToStringSidA(psid, &sid_string); + r = ConvertSidToStringSidA(psid, &sid_string); ok(r, "%s: ConvertSidToStringSid error %u\n", strsid_table[i].str, GetLastError()); if (winetest_debug > 1) trace("%s => %s\n", strsid_table[i].str, sid_string); @@ -484,7 +481,7 @@ static void test_sid(void) r = pCreateWellKnownSid(strsid_table[i].sid_type, domain_sid, buf, &size); ok(r, "%u: CreateWellKnownSid(%u) error %u\n", i, strsid_table[i].sid_type, GetLastError()); - r = pConvertSidToStringSidA(buf, &well_known_sid_string); + r = ConvertSidToStringSidA(buf, &well_known_sid_string); ok(r, "%u: ConvertSidToStringSi(%u) error %u\n", i, strsid_table[i].sid_type, GetLastError()); if (winetest_debug > 1) trace("%u => %s\n", strsid_table[i].sid_type, well_known_sid_string); @@ -1821,12 +1818,6 @@ static void test_token_attr(void) CloseHandle(Token); } - if(!pConvertSidToStringSidA) - { - win_skip("ConvertSidToStringSidA is not available\n"); - return; - } - SetLastError(0xdeadbeef); ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &Token); ok(ret, "OpenProcessToken failed with error %d\n", GetLastError()); @@ -1877,7 +1868,7 @@ static void test_token_attr(void) ret = LookupAccountSidA(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse); if (ret) { - pConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString); + ConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString); trace("%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes); LocalFree(SidString); } @@ -1894,7 +1885,7 @@ static void test_token_attr(void) ok(ret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); - pConvertSidToStringSidA(User->User.Sid, &SidString); + ConvertSidToStringSidA(User->User.Sid, &SidString); trace("TokenUser: %s attr: 0x%08x\n", SidString, User->User.Attributes); LocalFree(SidString); HeapFree(GetProcessHeap(), 0, User); @@ -2009,7 +2000,7 @@ typedef union _MAX_SID static void test_sid_str(PSID * sid) { char *str_sid; - BOOL ret = pConvertSidToStringSidA(sid, &str_sid); + BOOL ret = ConvertSidToStringSidA(sid, &str_sid); ok(ret, "ConvertSidToStringSidA() failed: %d\n", GetLastError()); if (ret) { @@ -2126,7 +2117,7 @@ static void test_CreateWellKnownSid(void) ok(pCreateWellKnownSid(i, value->without_domain ? NULL : domainsid, sid_buffer, &cb), "Couldn't create well known sid %u\n", i); expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d"); ok(IsValidSid(sid_buffer), "The sid is not valid\n"); - ok(pConvertSidToStringSidA(sid_buffer, &str), "Couldn't convert SID to string\n"); + ok(ConvertSidToStringSidA(sid_buffer, &str), "Couldn't convert SID to string\n"); ok(strcmp(str, value->sid_string) == 0, "%d: SID mismatch - expected %s, got %s\n", i, value->sid_string, str); LocalFree(str); @@ -2349,7 +2340,7 @@ static void test_LookupAccountSid(void) } HeapFree(GetProcessHeap(), 0, ptiUser); - if (pCreateWellKnownSid && pConvertSidToStringSidA) + if (pCreateWellKnownSid) { trace("Well Known SIDs:\n"); for (i = 0; i <= 84; i++) @@ -2357,7 +2348,7 @@ static void test_LookupAccountSid(void) size = SECURITY_MAX_SID_SIZE; if (pCreateWellKnownSid(i, NULL, &max_sid.sid, &size)) { - if (pConvertSidToStringSidA(&max_sid.sid, &str_sidA)) + if (ConvertSidToStringSidA(&max_sid.sid, &str_sidA)) { acc_sizeA = MAX_PATH; dom_sizeA = MAX_PATH; @@ -3770,7 +3761,6 @@ static void test_CreateDirectoryA(void) ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); - todo_wine ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); LocalFree(pSD); @@ -3905,6 +3895,7 @@ static void test_CreateDirectoryA(void) ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); ok(bret, "GetAclInformation failed\n"); + todo_wine ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); LocalFree(pSD); @@ -4281,7 +4272,7 @@ static void test_GetNamedSecurityInfoA(void) if (bret) admins_ace_id = i; } ok(users_ace_id != -1 || broken(users_ace_id == -1) /* win2k */, - "Bultin Users ACE not found.\n"); + "Builtin Users ACE not found.\n"); if (users_ace_id != -1) { bret = pGetAce(pDacl, users_ace_id, (VOID **)&ace); @@ -4298,7 +4289,7 @@ static void test_GetNamedSecurityInfoA(void) "Builtin Users ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, GENERIC_READ); } - ok(admins_ace_id != -1, "Bultin Admins ACE not found.\n"); + ok(admins_ace_id != -1, "Builtin Admins ACE not found.\n"); if (admins_ace_id != -1) { bret = pGetAce(pDacl, admins_ace_id, (VOID **)&ace); @@ -5309,10 +5300,13 @@ static void test_GetUserNameW(void) static void test_CreateRestrictedToken(void) { + TOKEN_PRIMARY_GROUP *primary_group, *primary_group2; HANDLE process_token, token, r_token; PTOKEN_GROUPS token_groups, groups2; SID_AND_ATTRIBUTES sattr; SECURITY_IMPERSONATION_LEVEL level; + TOKEN_PRIVILEGES *privs; + PRIVILEGE_SET privset; TOKEN_TYPE type; BOOL is_member; DWORD size; @@ -5328,7 +5322,7 @@ static void test_CreateRestrictedToken(void) ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token); ok(ret, "got error %d\n", GetLastError()); - ret = DuplicateTokenEx(process_token, TOKEN_DUPLICATE|TOKEN_ADJUST_GROUPS|TOKEN_QUERY, + ret = DuplicateTokenEx(process_token, TOKEN_DUPLICATE|TOKEN_ADJUST_GROUPS|TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, NULL, SecurityImpersonation, TokenImpersonation, &token); ok(ret, "got error %d\n", GetLastError()); @@ -5359,11 +5353,21 @@ static void test_CreateRestrictedToken(void) ok(ret, "got error %d\n", GetLastError()); ok(is_member, "not a member\n"); - /* disable a SID in new token */ + privset.PrivilegeCount = 1; + privset.Control = PRIVILEGE_SET_ALL_NECESSARY; + ret = LookupPrivilegeValueA(NULL, "SeChangeNotifyPrivilege", &privset.Privilege[0].Luid); + ok(ret, "got error %d\n", GetLastError()); + + is_member = FALSE; + ret = PrivilegeCheck(token, &privset, &is_member); + ok(ret, "got error %d\n", GetLastError()); + ok(is_member, "Expected SeChangeNotifyPrivilege to be enabled\n"); + + /* disable a SID and a privilege in new token */ sattr.Sid = token_groups->Groups[i].Sid; sattr.Attributes = 0; r_token = NULL; - ret = pCreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token); + ret = pCreateRestrictedToken(token, 0, 1, &sattr, 1, &privset.Privilege[0], 0, NULL, &r_token); ok(ret, "got error %d\n", GetLastError()); if (ret) @@ -5372,7 +5376,7 @@ static void test_CreateRestrictedToken(void) is_member = TRUE; ret = pCheckTokenMembership(r_token, token_groups->Groups[i].Sid, &is_member); ok(ret, "got error %d\n", GetLastError()); - todo_wine ok(!is_member, "not a member\n"); + ok(!is_member, "not a member\n"); ret = GetTokenInformation(r_token, TokenGroups, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n", @@ -5387,9 +5391,9 @@ static void test_CreateRestrictedToken(void) break; } - todo_wine ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY, + ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY, "got wrong attributes\n"); - todo_wine ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0, + ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0, "got wrong attributes\n"); HeapFree(GetProcessHeap(), 0, groups2); @@ -5403,10 +5407,73 @@ static void test_CreateRestrictedToken(void) ret = GetTokenInformation(r_token, TokenImpersonationLevel, &level, size, &size); ok(ret, "got error %d\n", GetLastError()); ok(level == SecurityImpersonation, "got level %u\n", type); + + is_member = TRUE; + ret = PrivilegeCheck(r_token, &privset, &is_member); + ok(ret, "got error %d\n", GetLastError()); + ok(!is_member, "Expected SeChangeNotifyPrivilege not to be enabled\n"); + + ret = GetTokenInformation(r_token, TokenPrivileges, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n", + ret, GetLastError()); + privs = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetTokenInformation(r_token, TokenPrivileges, privs, size, &size); + ok(ret, "got error %d\n", GetLastError()); + + is_member = FALSE; + for (j = 0; j < privs->PrivilegeCount; j++) + { + if (RtlEqualLuid(&privs->Privileges[j].Luid, &privset.Privilege[0].Luid)) + { + is_member = TRUE; + break; + } + } + + ok(!is_member, "Expected not to find privilege\n"); + HeapFree(GetProcessHeap(), 0, privs); } HeapFree(GetProcessHeap(), 0, token_groups); CloseHandle(r_token); + + ret = GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n", + ret, GetLastError()); + primary_group = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetTokenInformation(token, TokenPrimaryGroup, primary_group, size, &size); + ok(ret, "got error %d\n", GetLastError()); + + /* disable primary group */ + sattr.Sid = primary_group->PrimaryGroup; + sattr.Attributes = 0; + r_token = NULL; + ret = pCreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token); + ok(ret, "got error %d\n", GetLastError()); + + if (ret) + { + is_member = TRUE; + ret = pCheckTokenMembership(r_token, primary_group->PrimaryGroup, &is_member); + ok(ret, "got error %d\n", GetLastError()); + ok(!is_member, "not a member\n"); + + ret = GetTokenInformation(r_token, TokenPrimaryGroup, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n", + ret, GetLastError()); + primary_group2 = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetTokenInformation(r_token, TokenPrimaryGroup, primary_group2, size, &size); + ok(ret, "got error %d\n", GetLastError()); + + ok(EqualSid(primary_group2->PrimaryGroup, primary_group->PrimaryGroup), + "Expected same primary group\n"); + + HeapFree(GetProcessHeap(), 0, primary_group2); + } + + HeapFree(GetProcessHeap(), 0, primary_group); + CloseHandle(r_token); + CloseHandle(token); CloseHandle(process_token); } @@ -6189,7 +6256,8 @@ static void test_process_access(void) case GENERIC_WRITE: ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_TERMINATE) /* before Vista */ || - access == (map[i].mapped | PROCESS_SET_LIMITED_INFORMATION) /* win8 */, + access == (map[i].mapped | PROCESS_SET_LIMITED_INFORMATION) /* win8 */ || + access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SET_LIMITED_INFORMATION) /* Win10 Anniversary Update */, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); break; case GENERIC_EXECUTE: @@ -6411,7 +6479,7 @@ static void test_default_dacl_owner_sid(void) static void test_AdjustTokenPrivileges(void) { - TOKEN_PRIVILEGES tp, prev; + TOKEN_PRIVILEGES tp; HANDLE token; DWORD len; LUID luid; @@ -6439,7 +6507,8 @@ static void test_AdjustTokenPrivileges(void) tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = 0; - AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prev, NULL); + ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); + ok(ret, "got %d\n", ret); CloseHandle(token); } @@ -6495,18 +6564,19 @@ static void test_AddMandatoryAce(void) {SECURITY_MANDATORY_LOW_RID}}; static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_MEDIUM_RID}}; - static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, - {SECURITY_MANDATORY_HIGH_RID}}; - SYSTEM_MANDATORY_LABEL_ACE *ace; + static SID_IDENTIFIER_AUTHORITY sia_world = {SECURITY_WORLD_SID_AUTHORITY}; char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; SECURITY_DESCRIPTOR *sd2, *sd = (SECURITY_DESCRIPTOR *)&buffer_sd; - SECURITY_ATTRIBUTES sa; - char buffer_acl[256]; - ACL *pAcl = (ACL *)&buffer_acl; - ACL *sAcl; BOOL defaulted, present, ret, found, found2; - HANDLE handle; + ACL_SIZE_INFORMATION acl_size_info; + SYSTEM_MANDATORY_LABEL_ACE *ace; + char buffer_acl[256]; + ACL *acl = (ACL *)&buffer_acl; + SECURITY_ATTRIBUTES sa; DWORD index, size; + HANDLE handle; + SID *everyone; + ACL *sacl; if (!pAddMandatoryAce) { @@ -6515,50 +6585,48 @@ static void test_AddMandatoryAce(void) } ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); - ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError()); + ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError()); - sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = sd; - sa.bInheritHandle = FALSE; + sa.bInheritHandle = FALSE; handle = CreateEventA(&sa, TRUE, TRUE, "test_event"); ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError()); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); + "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError()); sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); - sAcl = (void *)0xdeadbeef; + sacl = (void *)0xdeadbeef; present = TRUE; - defaulted = TRUE; - ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted); - ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError()); - ok(!present, "sAcl is present\n"); - ok(sAcl == (void *)0xdeadbeef, "sAcl is set\n"); - todo_wine ok(!defaulted, "sAcl defaulted\n"); + ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(!present, "SACL is present\n"); + ok(sacl == (void *)0xdeadbeef, "SACL is set\n"); HeapFree(GetProcessHeap(), 0, sd2); CloseHandle(handle); - ret = InitializeAcl(pAcl, 256, ACL_REVISION); + ret = InitializeAcl(acl, 256, ACL_REVISION); ok(ret, "InitializeAcl failed with %u\n", GetLastError()); SetLastError(0xdeadbeef); - ret = pAddMandatoryAce(pAcl, ACL_REVISION, 0, 0x1234, &low_level); + ret = pAddMandatoryAce(acl, ACL_REVISION, 0, 0x1234, &low_level); ok(!ret, "AddMandatoryAce succeeded\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u\n", GetLastError()); - ret = pAddMandatoryAce(pAcl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level); + ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level); ok(ret, "AddMandatoryAce failed with %u\n", GetLastError()); index = 0; found = FALSE; - while (pGetAce( pAcl, index++, (void **)&ace )) + while (pGetAce(acl, index++, (void **)&ace)) { if (ace->Header.AceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE) continue; ok(ace->Header.AceFlags == 0, "Expected flags 0, got %x\n", ace->Header.AceFlags); @@ -6569,192 +6637,184 @@ static void test_AddMandatoryAce(void) } ok(found, "Could not find mandatory label ace\n"); - ret = SetSecurityDescriptorSacl(sd, TRUE, pAcl, FALSE); - ok(ret, "SetSecurityDescriptorSacl failed with %u\n", GetLastError()); + ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE); + ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError()); handle = CreateEventA(&sa, TRUE, TRUE, "test_event"); ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError()); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); + "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError()); sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); - sAcl = (void *)0xdeadbeef; + sacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; - ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted); - ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError()); - ok(present, "sAcl not present\n"); - ok(sAcl != (void *)0xdeadbeef, "sAcl not set\n"); - ok(!defaulted, "sAcl defaulted\n"); + ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "SACL not present\n"); + ok(sacl != (void *)0xdeadbeef, "SACL not set\n"); + ok(!defaulted, "SACL defaulted\n"); + ret = pGetAclInformation(sacl, &acl_size_info, sizeof(acl_size_info), AclSizeInformation); + ok(ret, "GetAclInformation failed with error %u\n", GetLastError()); + ok(acl_size_info.AceCount == 1, "SACL contains an unexpected ACE count %u\n", acl_size_info.AceCount); - index = 0; - found = FALSE; - while (pGetAce( sAcl, index++, (void **)&ace )) - { - if (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE) - { - found = TRUE; - ok(ace->Header.AceFlags == 0, "Expected 0 as flags, got %x\n", ace->Header.AceFlags); - ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, - "Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as flag, got %x\n", ace->Mask); - ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n"); - } - } - ok(found, "Could not find mandatory label\n"); + ret = pGetAce(sacl, 0, (void **)&ace); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + ok (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType); + ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags); + ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask); + ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n"); HeapFree(GetProcessHeap(), 0, sd2); - ret = pAddMandatoryAce(pAcl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level); - ok(ret, "AddMandatoryAce failed with %u\n", GetLastError()); + ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level); + ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError()); ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); + ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError()); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); + "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError()); sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); - sAcl = (void *)0xdeadbeef; + sacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; - ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted); - ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError()); - ok(present, "sAcl not present\n"); - ok(sAcl != (void *)0xdeadbeef, "sAcl not set\n"); - ok(sAcl->AceCount == 2, "Expected 2 ACEs, got %d\n", sAcl->AceCount); - ok(!defaulted, "sAcl defaulted\n"); + ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "SACL not present\n"); + ok(sacl != (void *)0xdeadbeef, "SACL not set\n"); + ok(sacl->AceCount == 2, "Expected 2 ACEs, got %d\n", sacl->AceCount); + ok(!defaulted, "SACL defaulted\n"); index = 0; found = found2 = FALSE; - while (pGetAce( sAcl, index++, (void **)&ace )) + while (pGetAce(sacl, index++, (void **)&ace)) { if (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE) { if (EqualSid(&ace->SidStart, &low_level)) { found = TRUE; - ok(ace->Header.AceFlags == 0, "Expected 0 as flags, got %x\n", ace->Header.AceFlags); + ok(!ace->Header.AceFlags, "Expected 0 as flags, got %#x\n", ace->Header.AceFlags); ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, - "Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as flag, got %x\n", ace->Mask); + "Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as mask, got %#x\n", ace->Mask); } if (EqualSid(&ace->SidStart, &medium_level)) { found2 = TRUE; - ok(ace->Header.AceFlags == 0, "Expected 0 as flags, got %x\n", ace->Header.AceFlags); + ok(!ace->Header.AceFlags, "Expected 0 as flags, got %#x\n", ace->Header.AceFlags); ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, - "Expected SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP as flag, got %x\n", ace->Mask); + "Expected SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP as mask, got %#x\n", ace->Mask); } } } ok(found, "Could not find low mandatory label\n"); ok(found2, "Could not find medium mandatory label\n"); - HeapFree( GetProcessHeap(), 0, sd2); + HeapFree(GetProcessHeap(), 0, sd2); ret = SetSecurityDescriptorSacl(sd, FALSE, NULL, FALSE); - ok(ret, "SetSecurityDescriptorSacl failed with %u\n", GetLastError()); + ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); + ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError()); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); - sAcl = (void *)0xdeadbeef; + sacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; - ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted); - ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError()); - ok(present, "sAcl not present\n"); - ok(sAcl != (void *)0xdeadbeef, "sAcl not set\n"); - ok(sAcl->AceCount == 0, "Expected 0 ACEs, got %d\n", sAcl->AceCount); - ok(!defaulted, "sAcl defaulted\n"); + ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "SACL not present\n"); + ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n"); + ok(!defaulted, "SACL defaulted\n"); + ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount); HeapFree(GetProcessHeap(), 0, sd2); - ret = InitializeAcl(pAcl, 256, ACL_REVISION); - ok(ret, "InitializeAcl failed with %u\n", GetLastError()); + ret = InitializeAcl(acl, 256, ACL_REVISION); + ok(ret, "InitializeAcl failed with error %u\n", GetLastError()); - ret = pAddMandatoryAce(pAcl, ACL_REVISION3, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level); - ok(ret, "AddMandatoryAce failed with %u\n", GetLastError()); + ret = pAddMandatoryAce(acl, ACL_REVISION3, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level); + ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError()); - ret = SetSecurityDescriptorSacl(sd, TRUE, pAcl, FALSE); - ok(ret, "SetSecurityDescriptorSacl failed with %u\n", GetLastError()); + ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE); + ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError()); ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); + ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError()); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); - sAcl = (void *)0xdeadbeef; + sacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; - ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted); - ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError()); - ok(present, "sAcl not present\n"); - ok(sAcl != (void *)0xdeadbeef, "sAcl not set\n"); - ok(sAcl->AclRevision == ACL_REVISION3, "Expected revision 3, got %d\n", sAcl->AclRevision); - ok(!defaulted, "sAcl defaulted\n"); + ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "SACL not present\n"); + ok(sacl != (void *)0xdeadbeef, "SACL not set\n"); + ok(sacl->AclRevision == ACL_REVISION3, "Expected revision 3, got %d\n", sacl->AclRevision); + ok(!defaulted, "SACL defaulted\n"); HeapFree(GetProcessHeap(), 0, sd2); - CloseHandle(handle); - ret = OpenProcessToken(GetCurrentProcess(), READ_CONTROL, &handle); - ok(ret, "got %d with %d (expected TRUE)\n", ret, GetLastError()); + ret = InitializeAcl(acl, 256, ACL_REVISION); + ok(ret, "InitializeAcl failed with error %u\n", GetLastError()); + + ret = AllocateAndInitializeSid(&sia_world, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, (void **)&everyone); + ok(ret, "AllocateAndInitializeSid failed with error %u\n", GetLastError()); + + ret = AddAccessAllowedAce(acl, ACL_REVISION, KEY_READ, everyone); + ok(ret, "AddAccessAllowedAce failed with error %u\n", GetLastError()); + + ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE); + ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + + ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd); + ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError()); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); sd2 = HeapAlloc(GetProcessHeap(), 0, size); ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); - sAcl = (void *)0xdeadbeef; + sacl = (void *)0xdeadbeef; present = FALSE; defaulted = TRUE; - ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted); - ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError()); - ok(present, "sAcl not present\n"); - ok(sAcl != (void *)0xdeadbeef, "sAcl not set\n"); - ok(sAcl->AceCount == 1, "Expected 1 ACEs, got %d\n", sAcl->AceCount); - ok(!defaulted, "sAcl defaulted\n"); - - index = 0; - found = FALSE; - while (pGetAce( sAcl, index++, (void **)&ace )) - { - if (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE && - (EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level))) - { - found = TRUE; - ok(ace->Header.AceFlags == 0, "Expected 0 as flags, got %x\n", ace->Header.AceFlags); - ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, - "Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as flag, got %x\n", ace->Mask); - } - } - ok(found, "Could not find medium/high mandatory label\n"); + ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "SACL not present\n"); + ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n"); + ok(!defaulted, "SACL defaulted\n"); + ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount); + FreeSid(everyone); HeapFree(GetProcessHeap(), 0, sd2); CloseHandle(handle); } @@ -7054,6 +7114,745 @@ static void test_maximum_allowed(void) CloseHandle(handle); } +static void test_token_label(void) +{ + static SID medium_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, + {SECURITY_MANDATORY_MEDIUM_RID}}; + static SID high_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, + {SECURITY_MANDATORY_HIGH_RID}}; + SECURITY_DESCRIPTOR_CONTROL control; + SYSTEM_MANDATORY_LABEL_ACE *ace; + BOOL ret, present, defaulted; + SECURITY_DESCRIPTOR *sd; + ACL *sacl = NULL, *dacl; + DWORD size, revision; + HANDLE token; + char *str; + SID *sid; + + ret = OpenProcessToken(GetCurrentProcess(), READ_CONTROL | WRITE_OWNER, &token); + ok(ret, "OpenProcessToken failed with error %u\n", GetLastError()); + + ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); + + sd = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + ret = GetSecurityDescriptorControl(sd, &control, &revision); + ok(ret, "GetSecurityDescriptorControl failed with error %u\n", GetLastError()); + todo_wine ok(control == (SE_SELF_RELATIVE | SE_SACL_AUTO_INHERITED | SE_SACL_PRESENT) || + broken(control == SE_SELF_RELATIVE) /* WinXP, Win2003 */, + "Unexpected security descriptor control %#x\n", control); + ok(revision == 1, "Unexpected security descriptor revision %u\n", revision); + + sid = (void *)0xdeadbeef; + defaulted = TRUE; + ret = GetSecurityDescriptorOwner(sd, (void **)&sid, &defaulted); + ok(ret, "GetSecurityDescriptorOwner failed with error %u\n", GetLastError()); + ok(!sid, "Owner present\n"); + ok(!defaulted, "Owner defaulted\n"); + + sid = (void *)0xdeadbeef; + defaulted = TRUE; + ret = GetSecurityDescriptorGroup(sd, (void **)&sid, &defaulted); + ok(ret, "GetSecurityDescriptorGroup failed with error %u\n", GetLastError()); + ok(!sid, "Group present\n"); + ok(!defaulted, "Group defaulted\n"); + + ret = GetSecurityDescriptorSacl(sd, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present || broken(!present) /* WinXP, Win2003 */, "No SACL in the security descriptor\n"); + ok(sacl || broken(!sacl) /* WinXP, Win2003 */, "NULL SACL in the security descriptor\n"); + + if (present) + { + ok(!defaulted, "SACL defaulted\n"); + ok(sacl->AceCount == 1, "SACL contains an unexpected ACE count %u\n", sacl->AceCount); + + ret = pGetAce(sacl, 0, (void **)&ace); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + + ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, + "Unexpected ACE type %#x\n", ace->Header.AceType); + ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags); + ok(ace->Header.AceSize, "Unexpected ACE size %u\n", ace->Header.AceSize); + ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask); + + sid = (SID *)&ace->SidStart; + ConvertSidToStringSidA(sid, &str); + ok(EqualSid(sid, &medium_sid) || EqualSid(sid, &high_sid), "Got unexpected SID %s\n", str); + LocalFree(str); + } + + ret = GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted); + ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); + todo_wine ok(!present, "DACL present\n"); + + HeapFree(GetProcessHeap(), 0, sd); + CloseHandle(token); +} + +static void test_token_security_descriptor(void) +{ + static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, + {SECURITY_MANDATORY_LOW_RID}}; + static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, + {SECURITY_MANDATORY_MEDIUM_RID}}; + static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, + {SECURITY_MANDATORY_HIGH_RID}}; + char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; + SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd, *sd2, *sd3; + char buffer_acl[256], buffer[MAX_PATH]; + ACL *acl = (ACL *)&buffer_acl, *acl2, *acl_child, *sacl; + BOOL defaulted, present, ret, found; + HANDLE token, token2, token3, token4, token5, token6; + EXPLICIT_ACCESSW exp_access; + TOKEN_MANDATORY_LABEL *tml; + BYTE buffer_integrity[64]; + PROCESS_INFORMATION info; + DWORD size, index, retd; + ACCESS_ALLOWED_ACE *ace; + SECURITY_ATTRIBUTES sa; + STARTUPINFOA startup; + PSID psid; + + if (!pDuplicateTokenEx || !pConvertStringSidToSidA || !pAddAccessAllowedAceEx || !pGetAce + || !pSetEntriesInAclW) + { + win_skip("Some functions not available\n"); + return; + } + + /* Test whether we can create tokens with security descriptors */ + ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); + ok(ret, "OpenProcessToken failed with error %u\n", GetLastError()); + + ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); + ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError()); + + ret = InitializeAcl(acl, 256, ACL_REVISION); + ok(ret, "InitializeAcl failed with error %u\n", GetLastError()); + + ret = pConvertStringSidToSidA("S-1-5-6", &psid); + ok(ret, "ConvertStringSidToSidA failed with error %u\n", GetLastError()); + + ret = pAddAccessAllowedAceEx(acl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, GENERIC_ALL, psid); + ok(ret, "AddAccessAllowedAceEx failed with error %u\n", GetLastError()); + + ret = SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE); + ok(ret, "SetSecurityDescriptorDacl failed with error %u\n", GetLastError()); + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = sd; + sa.bInheritHandle = FALSE; + + ret = pDuplicateTokenEx(token, MAXIMUM_ALLOWED, &sa, SecurityImpersonation, TokenImpersonation, &token2); + ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError()); + + ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); + + sd2 = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, sd2, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + acl2 = (void *)0xdeadbeef; + present = FALSE; + defaulted = TRUE; + ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted); + ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); + ok(present, "acl2 not present\n"); + ok(acl2 != (void *)0xdeadbeef, "acl2 not set\n"); + ok(acl2->AceCount == 1, "Expected 1 ACE, got %d\n", acl2->AceCount); + ok(!defaulted, "acl2 defaulted\n"); + + ret = pGetAce(acl2, 0, (void **)&ace); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + ok(ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType); + ok(EqualSid(&ace->SidStart, psid), "Expected access allowed ACE\n"); + ok(ace->Header.AceFlags == NO_PROPAGATE_INHERIT_ACE, + "Expected NO_PROPAGATE_INHERIT_ACE as flags, got %x\n", ace->Header.AceFlags); + + HeapFree(GetProcessHeap(), 0, sd2); + + /* Duplicate token without security attributes. + * Tokens do not inherit the security descriptor in DuplicateToken. */ + ret = pDuplicateTokenEx(token2, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &token3); + ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError()); + + ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); + + sd2 = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, sd2, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + acl2 = (void *)0xdeadbeef; + present = FALSE; + defaulted = TRUE; + ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted); + ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); + ok(present, "DACL not present\n"); + + if (present) + { + ok(acl2 != (void *)0xdeadbeef, "DACL not set\n"); + ok(!defaulted, "DACL defaulted\n"); + + index = 0; + found = FALSE; + while (pGetAce(acl2, index++, (void **)&ace)) + { + if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid)) + found = TRUE; + } + ok(!found, "Access allowed ACE was inherited\n"); + } + + HeapFree(GetProcessHeap(), 0, sd2); + + /* When creating a child process, the process does inherit the token of + * the parent but not the DACL of the token */ + ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); + + sd2 = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd2, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + acl2 = (void *)0xdeadbeef; + present = FALSE; + defaulted = TRUE; + ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted); + ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); + ok(present, "DACL not present\n"); + ok(acl2 != (void *)0xdeadbeef, "DACL not set\n"); + ok(!defaulted, "DACL defaulted\n"); + + exp_access.grfAccessPermissions = GENERIC_ALL; + exp_access.grfAccessMode = GRANT_ACCESS; + exp_access.grfInheritance = NO_PROPAGATE_INHERIT_ACE; + exp_access.Trustee.pMultipleTrustee = NULL; + exp_access.Trustee.TrusteeForm = TRUSTEE_IS_SID; + exp_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + exp_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + exp_access.Trustee.ptstrName = (void*)psid; + + retd = pSetEntriesInAclW(1, &exp_access, acl2, &acl_child); + ok(retd == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", retd); + + memset(sd, 0, sizeof(buffer_sd)); + ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); + ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError()); + + ret = SetSecurityDescriptorDacl(sd, TRUE, acl_child, FALSE); + ok(ret, "SetSecurityDescriptorDacl failed with error %u\n", GetLastError()); + + ret = SetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd); + ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError()); + + /* The security label is also not inherited */ + if (pAddMandatoryAce) + { + memset(buffer_integrity, 0, sizeof(buffer_integrity)); + ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); + ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); + tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; + ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level), + "Expected medium or high integrity level\n"); + + if (EqualSid(tml->Label.Sid, &high_level)) + { + DWORD process_id; + HANDLE process; + HWND shell; + + /* This test tries to get a medium token and then impersonates this token. The + * idea is to check whether the sd label of a newly created token depends on the + * current active token or the integrity level of the newly created token. */ + + /* Steal process token of the explorer.exe process */ + shell = GetShellWindow(); + todo_wine ok(shell != NULL, "Failed to get shell window\n"); + if (!shell) shell = GetDesktopWindow(); /* FIXME: Workaround for Wine */ + ok(GetWindowThreadProcessId(shell, &process_id), + "Failed to get process id of shell window: %u\n", GetLastError()); + process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process_id); + ok(process != NULL, "Failed to open process: %u\n", GetLastError()); + ok(OpenProcessToken(process, TOKEN_ALL_ACCESS, &token4), + "Failed to open process token: %u\n", GetLastError()); + CloseHandle(process); + + /* Check TokenIntegrityLevel and LABEL_SECURITY_INFORMATION of explorer.exe token */ + memset(buffer_integrity, 0, sizeof(buffer_integrity)); + ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); + ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); + tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; + ok(EqualSid(tml->Label.Sid, &medium_level), "Expected medium integrity level\n"); + + size = 0; + ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError()); + + sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); + ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + sacl = NULL; + ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "No SACL in the security descriptor\n"); + ok(sacl != NULL, "NULL SACL in the security descriptor\n"); + + if (sacl) + { + ret = pGetAce(sacl, 0, (void **)&ace); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, + "Unexpected ACE type %#x\n", ace->Header.AceType); + ok(EqualSid(&ace->SidStart, &medium_level), + "Expected medium integrity level\n"); + } + + HeapFree(GetProcessHeap(), 0, sd3); + + /* Start child process with the explorer.exe token */ + memset(&startup, 0, sizeof(startup)); + startup.cb = sizeof(startup); + startup.dwFlags = STARTF_USESHOWWINDOW; + startup.wShowWindow = SW_SHOWNORMAL; + + sprintf(buffer, "%s tests/security.c test_token_sd_medium", myARGV[0]); + ret = CreateProcessAsUserA(token4, NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info); + ok(ret || GetLastError() == ERROR_PRIVILEGE_NOT_HELD, + "CreateProcess failed with error %u\n", GetLastError()); + if (ret) + { + winetest_wait_child_process(info.hProcess); + CloseHandle(info.hProcess); + CloseHandle(info.hThread); + } + else + win_skip("Skipping test for creating process with medium level token\n"); + + ret = DuplicateTokenEx(token4, 0, NULL, SecurityImpersonation, TokenImpersonation, &token5); + ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError()); + ret = SetThreadToken(NULL, token5); + ok(ret, "SetThreadToken failed with error %u\n", GetLastError()); + CloseHandle(token4); + + /* Restrict current process token while impersonating a medium integrity token */ + ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token6); + ok(ret, "CreateRestrictedToken failed with error %u\n", GetLastError()); + + memset(buffer_integrity, 0, sizeof(buffer_integrity)); + ret = GetTokenInformation(token6, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); + ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); + tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; + ok(EqualSid(tml->Label.Sid, &high_level), "Expected high integrity level\n"); + + size = 0; + ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError()); + + sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); + ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + sacl = NULL; + ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "No SACL in the security descriptor\n"); + ok(sacl != NULL, "NULL SACL in the security descriptor\n"); + + if (sacl) + { + ret = pGetAce(sacl, 0, (void **)&ace); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, + "Unexpected ACE type %#x\n", ace->Header.AceType); + ok(EqualSid(&ace->SidStart, &medium_level), + "Expected medium integrity level\n"); + } + + HeapFree(GetProcessHeap(), 0, sd3); + RevertToSelf(); + CloseHandle(token5); + + /* Start child process with the restricted token */ + sprintf(buffer, "%s tests/security.c test_token_sd_restricted", myARGV[0]); + ret = CreateProcessAsUserA(token6, NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info); + ok(ret, "CreateProcess failed with error %u\n", GetLastError()); + winetest_wait_child_process(info.hProcess); + CloseHandle(info.hProcess); + CloseHandle(info.hThread); + CloseHandle(token6); + + /* DuplicateTokenEx should assign security label even when SA points to empty SD */ + memset(sd, 0, sizeof(buffer_sd)); + ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); + ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError()); + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = sd; + sa.bInheritHandle = FALSE; + + ret = DuplicateTokenEx(token, 0, &sa, 0, TokenPrimary, &token6); + ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError()); + + size = 0; + ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError()); + + sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); + ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + sacl = NULL; + ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "No SACL in the security descriptor\n"); + ok(sacl != NULL, "NULL SACL in the security descriptor\n"); + + if (sacl) + { + ret = pGetAce(sacl, 0, (void **)&ace); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, + "Unexpected ACE type %#x\n", ace->Header.AceType); + ok(EqualSid(&ace->SidStart, &high_level), + "Expected high integrity level\n"); + } + + HeapFree(GetProcessHeap(), 0, sd3); + CloseHandle(token6); + } + else + skip("Skipping test, running without admin rights\n"); + + ret = InitializeAcl(acl, 256, ACL_REVISION); + ok(ret, "InitializeAcl failed with error %u\n", GetLastError()); + + ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level); + ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError()); + + memset(sd, 0, sizeof(buffer_sd)); + ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); + ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError()); + + ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE); + ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + + ret = SetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd); + ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError()); + + /* changing the label of the security descriptor does not change the integrity level of the token itself */ + memset(buffer_integrity, 0, sizeof(buffer_integrity)); + ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); + ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); + tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; + ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level), + "Expected medium or high integrity level\n"); + + /* restricting / duplicating a token resets the mandatory sd label */ + ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token4); + ok(ret, "CreateRestrictedToken failed with error %u\n", GetLastError()); + + memset(buffer_integrity, 0, sizeof(buffer_integrity)); + ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); + ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); + tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; + ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level), + "Expected medium or high integrity level\n"); + + size = 0; + ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError()); + + sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); + ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "No SACL in the security descriptor\n"); + ok(sacl != NULL, "NULL SACL in the security descriptor\n"); + + if (sacl) + { + ret = pGetAce(sacl, 0, (void **)&ace); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, + "Unexpected ACE type %#x\n", ace->Header.AceType); + ok(EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level), + "Low integrity level should not have been inherited\n"); + } + + HeapFree(GetProcessHeap(), 0, sd3); + CloseHandle(token4); + + ret = DuplicateTokenEx(token, 0, NULL, 0, TokenPrimary, &token4); + ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError()); + + memset(buffer_integrity, 0, sizeof(buffer_integrity)); + ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); + ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); + tml = (TOKEN_MANDATORY_LABEL*) buffer_integrity; + ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level), + "Expected medium or high integrity level\n"); + + size = 0; + ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError()); + + sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); + ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + sacl = NULL; + ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "No SACL in the security descriptor\n"); + ok(sacl != NULL, "NULL SACL in the security descriptor\n"); + + if (sacl) + { + ret = pGetAce(sacl, 0, (void **)&ace); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, + "Unexpected ACE type %#x\n", ace->Header.AceType); + ok(EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level), + "Low integrity level should not have been inherited\n"); + } + + HeapFree(GetProcessHeap(), 0, sd3); + CloseHandle(token4); + } + else + win_skip("SYSTEM_MANDATORY_LABEL not supported\n"); + + /* Start child process with our modified token */ + memset(&startup, 0, sizeof(startup)); + startup.cb = sizeof(startup); + startup.dwFlags = STARTF_USESHOWWINDOW; + startup.wShowWindow = SW_SHOWNORMAL; + + sprintf(buffer, "%s tests/security.c test_token_sd", myARGV[0]); + ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info); + ok(ret, "CreateProcess failed with error %u\n", GetLastError()); + winetest_wait_child_process(info.hProcess); + CloseHandle(info.hProcess); + CloseHandle(info.hThread); + + LocalFree(acl_child); + LocalFree(psid); + + CloseHandle(token3); + CloseHandle(token2); + CloseHandle(token); +} + +static void test_child_token_sd(void) +{ + static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, + {SECURITY_MANDATORY_LOW_RID}}; + SYSTEM_MANDATORY_LABEL_ACE *ace_label; + BOOL ret, present, defaulted; + ACCESS_ALLOWED_ACE *acc_ace; + SECURITY_DESCRIPTOR *sd; + DWORD size, i; + HANDLE token; + PSID psid; + ACL *acl; + + ret = pConvertStringSidToSidA("S-1-5-6", &psid); + ok(ret, "ConvertStringSidToSidA failed with error %u\n", GetLastError()); + + ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); + ok(ret, "OpenProcessToken failed with error %u\n", GetLastError()); + + ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); + + sd = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + acl = NULL; + present = FALSE; + defaulted = TRUE; + ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted); + ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); + ok(present, "DACL not present\n"); + ok(acl && acl != (void *)0xdeadbeef, "Got invalid DACL\n"); + ok(!defaulted, "DACL defaulted\n"); + + ok(acl->AceCount, "Expected at least one ACE\n"); + for (i = 0; i < acl->AceCount; i++) + { + ok(pGetAce(acl, i, (void **)&acc_ace), "GetAce failed with error %u\n", GetLastError()); + ok(acc_ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE || !EqualSid(&acc_ace->SidStart, psid), + "ACE inherited from the parent\n"); + } + + LocalFree(psid); + HeapFree(GetProcessHeap(), 0, sd); + + if (!pAddMandatoryAce) + { + win_skip("SYSTEM_MANDATORY_LABEL not supported\n"); + return; + } + + ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); + + sd = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + acl = NULL; + present = FALSE; + defaulted = TRUE; + ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "SACL not present\n"); + ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n"); + ok(!defaulted, "SACL defaulted\n"); + ok(acl->AceCount == 1, "Expected exactly one ACE\n"); + ret = pGetAce(acl, 0, (void **)&ace_label); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, + "Unexpected ACE type %#x\n", ace_label->Header.AceType); + ok(!EqualSid(&ace_label->SidStart, &low_level), + "Low integrity level should not have been inherited\n"); + + HeapFree(GetProcessHeap(), 0, sd); +} + +static void test_child_token_sd_restricted(void) +{ + static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, + {SECURITY_MANDATORY_HIGH_RID}}; + SYSTEM_MANDATORY_LABEL_ACE *ace_label; + BOOL ret, present, defaulted; + TOKEN_MANDATORY_LABEL *tml; + BYTE buffer_integrity[64]; + SECURITY_DESCRIPTOR *sd; + HANDLE token; + DWORD size; + ACL *acl; + + if (!pAddMandatoryAce) + { + win_skip("SYSTEM_MANDATORY_LABEL not supported\n"); + return; + } + + ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); + ok(ret, "OpenProcessToken failed with error %u\n", GetLastError()); + + ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); + + sd = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + acl = NULL; + present = FALSE; + defaulted = TRUE; + ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "SACL not present\n"); + ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n"); + ok(!defaulted, "SACL defaulted\n"); + ok(acl->AceCount == 1, "Expected exactly one ACE\n"); + ret = pGetAce(acl, 0, (void **)&ace_label); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, + "Unexpected ACE type %#x\n", ace_label->Header.AceType); + ok(EqualSid(&ace_label->SidStart, &high_level), + "Expected high integrity level\n"); + + memset(buffer_integrity, 0, sizeof(buffer_integrity)); + ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); + ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); + tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; + ok(EqualSid(tml->Label.Sid, &high_level), "Expected high integrity level\n"); + + HeapFree(GetProcessHeap(), 0, sd); +} + +static void test_child_token_sd_medium(void) +{ + static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, + {SECURITY_MANDATORY_MEDIUM_RID}}; + SYSTEM_MANDATORY_LABEL_ACE *ace_label; + BOOL ret, present, defaulted; + TOKEN_MANDATORY_LABEL *tml; + BYTE buffer_integrity[64]; + SECURITY_DESCRIPTOR *sd; + HANDLE token; + DWORD size; + ACL *acl; + + if (!pAddMandatoryAce) + { + win_skip("SYSTEM_MANDATORY_LABEL not supported\n"); + return; + } + + ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); + ok(ret, "OpenProcessToken failed with error %u\n", GetLastError()); + + ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError()); + + sd = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size); + ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError()); + + acl = NULL; + present = FALSE; + defaulted = TRUE; + ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted); + ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError()); + ok(present, "SACL not present\n"); + ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n"); + ok(!defaulted, "SACL defaulted\n"); + ok(acl->AceCount == 1, "Expected exactly one ACE\n"); + ret = pGetAce(acl, 0, (void **)&ace_label); + ok(ret, "GetAce failed with error %u\n", GetLastError()); + ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, + "Unexpected ACE type %#x\n", ace_label->Header.AceType); + ok(EqualSid(&ace_label->SidStart, &medium_level), + "Expected medium integrity level\n"); + + memset(buffer_integrity, 0, sizeof(buffer_integrity)); + ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size); + ok(ret, "GetTokenInformation failed with error %u\n", GetLastError()); + tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity; + ok(EqualSid(tml->Label.Sid, &medium_level), "Expected medium integrity level\n"); + + HeapFree(GetProcessHeap(), 0, sd); +} + static void test_GetExplicitEntriesFromAclW(void) { static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'}; @@ -7193,310 +7992,6 @@ static void test_GetExplicitEntriesFromAclW(void) HeapFree(GetProcessHeap(), 0, old_acl); } -static void test_token_security_descriptor(void) -{ - static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, - {SECURITY_MANDATORY_LOW_RID}}; - ACCESS_ALLOWED_ACE *ace; - char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; - SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd, *sd2; - char buffer_acl[256], buffer[MAX_PATH]; - ACL *pAcl = (ACL *)&buffer_acl, *pAcl2, *pAclChild; - BOOL defaulted, present, ret, found; - HANDLE token, token2, token3; - EXPLICIT_ACCESSW exp_access; - PROCESS_INFORMATION info; - SECURITY_ATTRIBUTES sa; - DWORD size, index, retd; - STARTUPINFOA startup; - PSID psid; - - if (!pDuplicateTokenEx || !pConvertStringSidToSidA || !pAddAccessAllowedAceEx || !pGetAce || !pSetEntriesInAclW) - { - win_skip("Some functions not available\n"); - return; - } - - /* Test whether we can create tokens with security descriptors */ - ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); - ok(ret, "OpenProcessToken failed with error %u\n", GetLastError()); - - ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); - ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError()); - - ret = InitializeAcl(pAcl, 256, ACL_REVISION); - ok(ret, "InitializeAcl failed with %u\n", GetLastError()); - - ret = pConvertStringSidToSidA("S-1-5-6", &psid); - ok(ret, "ConvertStringSidToSidA failed with %u\n", GetLastError()); - - ret = pAddAccessAllowedAceEx(pAcl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, GENERIC_ALL, psid); - ok(ret, "AddAccessAllowedAceEx failed with %u\n", GetLastError()); - - ret = SetSecurityDescriptorDacl(sd, TRUE, pAcl, FALSE); - ok(ret, "SetSecurityDescriptorDacl failed with %u\n", GetLastError()); - - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = sd; - sa.bInheritHandle = FALSE; - - ret = pDuplicateTokenEx(token, MAXIMUM_ALLOWED, &sa, SecurityImpersonation, TokenImpersonation, &token2); - ok(ret, "DuplicateTokenEx failed with %u\n", GetLastError()); - - ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, NULL, 0, &size); - ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); - - sd2 = HeapAlloc(GetProcessHeap(), 0, size); - ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, sd2, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); - - pAcl2 = (void *)0xdeadbeef; - present = FALSE; - defaulted = TRUE; - ret = GetSecurityDescriptorDacl(sd2, &present, &pAcl2, &defaulted); - ok(ret, "GetSecurityDescriptorDacl failed with %u\n", GetLastError()); - ok(present, "pAcl2 not present\n"); - ok(pAcl2 != (void *)0xdeadbeef, "pAcl2 not set\n"); - ok(pAcl2->AceCount == 1, "Expected 1 ACEs, got %d\n", pAcl2->AceCount); - ok(!defaulted, "pAcl2 defaulted\n"); - - index = 0; - found = FALSE; - while (pGetAce( pAcl2, index++, (void **)&ace )) - { - if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid)) - { - found = TRUE; - ok(ace->Header.AceFlags == NO_PROPAGATE_INHERIT_ACE, - "Expected NO_PROPAGATE_INHERIT_ACE as flags, got %x\n", ace->Header.AceFlags); - } - } - ok(found, "Could not find access allowed ace\n"); - - HeapFree( GetProcessHeap(), 0, sd2); - - /* Duplicate token without security attributes. - * Tokens do not inherit the security descriptor when calling DuplicateToken, - * see https://blogs.msdn.microsoft.com/oldnewthing/20160512-00/?p=93447 - */ - ret = pDuplicateTokenEx(token2, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &token3); - ok(ret, "DuplicateTokenEx failed with %u\n", GetLastError()); - - ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, NULL, 0, &size); - ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); - - sd2 = HeapAlloc(GetProcessHeap(), 0, size); - ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, sd2, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); - - pAcl2 = (void *)0xdeadbeef; - present = FALSE; - defaulted = TRUE; - ret = GetSecurityDescriptorDacl(sd2, &present, &pAcl2, &defaulted); - ok(ret, "GetSecurityDescriptorDacl failed with %u\n", GetLastError()); - todo_wine - ok(present, "pAcl2 not present\n"); - ok(pAcl2 != (void *)0xdeadbeef, "pAcl2 not set\n"); - ok(!defaulted, "pAcl2 defaulted\n"); - - if (pAcl2) - { - index = 0; - found = FALSE; - while (pGetAce( pAcl2, index++, (void **)&ace )) - { - if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid)) - found = TRUE; - } - ok(!found, "Access allowed ace got inherited!\n"); - } - - HeapFree(GetProcessHeap(), 0, sd2); - - /* When creating a child process, the process does only inherit the - * Token of the parent, but not the DACL of the token. - */ - ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size); - ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); - - sd2 = HeapAlloc(GetProcessHeap(), 0, size); - ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd2, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); - - pAcl2 = (void *)0xdeadbeef; - present = FALSE; - defaulted = TRUE; - ret = GetSecurityDescriptorDacl(sd2, &present, &pAcl2, &defaulted); - ok(ret, "GetSecurityDescriptorDacl failed with %u\n", GetLastError()); - ok(present, "pAcl2 not present\n"); - ok(pAcl2 != (void *)0xdeadbeef, "pAcl2 not set\n"); - ok(!defaulted, "pAcl2 defaulted\n"); - - /* check that the ace we add for testing does not already exist! */ - if (pAcl2) - { - index = 0; - found = FALSE; - while (pGetAce( pAcl2, index++, (void **)&ace )) - { - if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid)) - found = TRUE; - } - ok(!found, "Test ace does already exist!\n"); - } - - exp_access.grfAccessPermissions = GENERIC_ALL; - exp_access.grfAccessMode = GRANT_ACCESS; - exp_access.grfInheritance = NO_PROPAGATE_INHERIT_ACE; - exp_access.Trustee.pMultipleTrustee = NULL; - exp_access.Trustee.TrusteeForm = TRUSTEE_IS_SID; - exp_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; - exp_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; - exp_access.Trustee.ptstrName = (void*)psid; - - retd = pSetEntriesInAclW(1, &exp_access, pAcl2, &pAclChild); - ok(retd == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", retd); - - memset(sd, 0, sizeof(buffer_sd)); - ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); - ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError()); - - ret = SetSecurityDescriptorDacl(sd, TRUE, pAclChild, FALSE); - ok(ret, "SetSecurityDescriptorDacl failed with %u\n", GetLastError()); - - ret = SetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd); - ok(ret, "SetKernelObjectSecurity failed with %u\n", GetLastError()); - - /* The security label is also not inherited */ - if (pAddMandatoryAce) - { - ret = InitializeAcl(pAcl, 256, ACL_REVISION); - ok(ret, "InitializeAcl failed with %u\n", GetLastError()); - - ret = pAddMandatoryAce(pAcl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level); - ok(ret, "AddMandatoryAce failed with %u\n", GetLastError()); - - memset(sd, 0, sizeof(buffer_sd)); - ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); - ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError()); - - ret = SetSecurityDescriptorSacl(sd, TRUE, pAcl, FALSE); - ok(ret, "SetSecurityDescriptorSacl failed with %u\n", GetLastError()); - - ret = SetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd); - ok(ret, "SetKernelObjectSecurity failed with %u\n", GetLastError()); - } - else - win_skip("SYSTEM_MANDATORY_LABEL not supported\n"); - - /* start child process with our modified token */ - memset(&startup, 0, sizeof(startup)); - startup.cb = sizeof(startup); - startup.dwFlags = STARTF_USESHOWWINDOW; - startup.wShowWindow = SW_SHOWNORMAL; - - sprintf(buffer, "%s tests/security.c test_token_sd", myARGV[0]); - ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info); - ok(ret, "CreateProcess failed with error %u\n", GetLastError()); - winetest_wait_child_process(info.hProcess); - CloseHandle(info.hProcess); - CloseHandle(info.hThread); - - LocalFree(pAclChild); - LocalFree(psid); - - CloseHandle(token3); - CloseHandle(token2); - CloseHandle(token); -} - -static void test_child_token_sd(void) -{ - static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, - {SECURITY_MANDATORY_LOW_RID}}; - SYSTEM_MANDATORY_LABEL_ACE *ace_label; - BOOL ret, present, defaulted, found; - ACCESS_ALLOWED_ACE *ace_acc; - SECURITY_DESCRIPTOR *sd; - DWORD size, index; - HANDLE token; - ACL *pAcl; - PSID psid; - - ret = pConvertStringSidToSidA("S-1-5-6", &psid); - ok(ret, "ConvertStringSidToSidA failed with %u\n", GetLastError()); - - ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); - ok(ret, "OpenProcessToken failed with error %u\n", GetLastError()); - - ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size); - ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); - - sd = HeapAlloc(GetProcessHeap(), 0, size); - ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); - - pAcl = NULL; - present = FALSE; - defaulted = TRUE; - ret = GetSecurityDescriptorDacl(sd, &present, &pAcl, &defaulted); - ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError()); - - index = 0; - found = FALSE; - if (present && pAcl) - { - ok(pAcl->AceCount > 0, "Expected at least one ACE\n"); - while (pGetAce( pAcl, index++, (void **)&ace_acc )) - { - if (ace_acc->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace_acc->SidStart, psid)) - found = TRUE; - } - } - ok(!found, "The ACE should not haven been inherited from the parent\n"); - - LocalFree(psid); - HeapFree(GetProcessHeap(), 0, sd); - - if (!pAddMandatoryAce) - { - win_skip("SYSTEM_MANDATORY_LABEL not supported\n"); - return; - } - - ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size); - ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "GetKernelObjectSecurity failed with %u\n", GetLastError()); - - sd = HeapAlloc(GetProcessHeap(), 0, size); - ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size); - ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError()); - - pAcl = NULL; - present = FALSE; - defaulted = TRUE; - ret = GetSecurityDescriptorSacl(sd, &present, &pAcl, &defaulted); - ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError()); - - index = 0; - found = FALSE; - if (present && pAcl) - { - while (pGetAce( pAcl, index++, (void **)&ace_label )) - { - if (ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE && EqualSid(&ace_label->SidStart, &low_level)) - found = TRUE; - } - } - ok(!found, "Low integrity level should not have been inherited\n"); - - HeapFree(GetProcessHeap(), 0, sd); -} - static void test_BuildSecurityDescriptorW(void) { SECURITY_DESCRIPTOR old_sd, *new_sd, *rel_sd; @@ -7544,6 +8039,10 @@ START_TEST(security) { if (!strcmp(myARGV[2], "test_token_sd")) test_child_token_sd(); + else if (!strcmp(myARGV[2], "test_token_sd_restricted")) + test_child_token_sd_restricted(); + else if (!strcmp(myARGV[2], "test_token_sd_medium")) + test_child_token_sd_medium(); else test_process_security_child(); return; @@ -7587,9 +8086,10 @@ START_TEST(security) test_GetSidIdentifierAuthority(); test_pseudo_tokens(); test_maximum_allowed(); + test_token_label(); test_GetExplicitEntriesFromAclW(); test_BuildSecurityDescriptorW(); - /* must be the last test, modifies process token */ + /* Must be the last test, modifies process token */ test_token_security_descriptor(); }