mirror of
https://github.com/reactos/reactos.git
synced 2024-11-27 13:33:32 +08:00
[NTDLL_APITEST] Write tests for NtAccessCheckByTypeResultList
This commit is contained in:
parent
fd2e4437a8
commit
8a61e1c33c
@ -11,6 +11,7 @@ list(APPEND SOURCE
|
||||
locale.c
|
||||
NtAcceptConnectPort.c
|
||||
NtAccessCheckByType.c
|
||||
NtAccessCheckByTypeResultList.c
|
||||
NtAdjustGroupsToken.c
|
||||
NtAdjustPrivilegesToken.c
|
||||
NtAllocateVirtualMemory.c
|
||||
|
692
modules/rostests/apitests/ntdll/NtAccessCheckByTypeResultList.c
Normal file
692
modules/rostests/apitests/ntdll/NtAccessCheckByTypeResultList.c
Normal file
@ -0,0 +1,692 @@
|
||||
/*
|
||||
* PROJECT: ReactOS API tests
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Tests for the NtAccessCheckByTypeResultList API
|
||||
* COPYRIGHT: Copyright 2023 George Bișoc <george.bisoc@reactos.org>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
static GENERIC_MAPPING RegMapping = {KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS};
|
||||
static GUID ObjectType = {0x12345678, 0x1234, 0x5678, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}};
|
||||
static GUID ChildObjectType = {0x23456789, 0x2345, 0x6786, {0x2, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}};
|
||||
static SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
|
||||
static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
|
||||
|
||||
static
|
||||
HANDLE
|
||||
GetTokenProcess(
|
||||
_In_ BOOLEAN WantImpersonateLevel,
|
||||
_In_ BOOLEAN WantImpersonateType)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE Token;
|
||||
HANDLE DuplicatedToken;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
SECURITY_QUALITY_OF_SERVICE Sqos;
|
||||
|
||||
Status = NtOpenProcessToken(NtCurrentProcess(),
|
||||
TOKEN_QUERY | TOKEN_DUPLICATE,
|
||||
&Token);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
trace("Failed to get current process token (Status 0x%08lx)\n", Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
||||
Sqos.ImpersonationLevel = WantImpersonateLevel ? SecurityImpersonation : SecurityAnonymous;
|
||||
Sqos.ContextTrackingMode = 0;
|
||||
Sqos.EffectiveOnly = FALSE;
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
ObjectAttributes.SecurityQualityOfService = &Sqos;
|
||||
|
||||
Status = NtDuplicateToken(Token,
|
||||
TOKEN_QUERY | TOKEN_DUPLICATE,
|
||||
&ObjectAttributes,
|
||||
FALSE,
|
||||
WantImpersonateType ? TokenImpersonation : TokenPrimary,
|
||||
&DuplicatedToken);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
trace("Failed to duplicate token (Status 0x%08lx)\n", Status);
|
||||
NtClose(Token);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return DuplicatedToken;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
ParamValidationNoObjsList(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
NTSTATUS AccessStatus;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
PPRIVILEGE_SET PrivilegeSet = NULL;
|
||||
ULONG PrivilegeSetLength;
|
||||
HANDLE Token = NULL;
|
||||
SECURITY_DESCRIPTOR Sd;
|
||||
|
||||
PrivilegeSetLength = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
|
||||
PrivilegeSet = RtlAllocateHeap(RtlGetProcessHeap(), 0, PrivilegeSetLength);
|
||||
if (PrivilegeSet == NULL)
|
||||
{
|
||||
skip("Failed to allocate PrivilegeSet, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Token = GetTokenProcess(TRUE, TRUE);
|
||||
if (Token == NULL)
|
||||
{
|
||||
skip("Failed to get token, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlCreateSecurityDescriptor(&Sd, SECURITY_DESCRIPTOR_REVISION);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create a security descriptor, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
RtlSetGroupSecurityDescriptor(&Sd, NULL, FALSE);
|
||||
RtlSetOwnerSecurityDescriptor(&Sd, NULL, FALSE);
|
||||
RtlSetDaclSecurityDescriptor(&Sd, FALSE, NULL, FALSE);
|
||||
|
||||
/* The function expects an object type list */
|
||||
Status = NtAccessCheckByTypeResultList(&Sd,
|
||||
NULL,
|
||||
Token,
|
||||
MAXIMUM_ALLOWED,
|
||||
NULL,
|
||||
0,
|
||||
&RegMapping,
|
||||
PrivilegeSet,
|
||||
&PrivilegeSetLength,
|
||||
&GrantedAccess,
|
||||
&AccessStatus);
|
||||
ok_hex(Status, STATUS_INVALID_PARAMETER);
|
||||
|
||||
Quit:
|
||||
if (Token)
|
||||
{
|
||||
NtClose(Token);
|
||||
}
|
||||
|
||||
if (PrivilegeSet)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, PrivilegeSet);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
PrintAccessStatusAndGrantedAccess(
|
||||
_In_ PNTSTATUS AccessStatus,
|
||||
_In_ PACCESS_MASK GrantedAccess,
|
||||
_In_ ULONG ObjectTypeListLength)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
trace("===== OBJECT ACCESS & STATUS LIST =====\n");
|
||||
for (i = 0; i < ObjectTypeListLength; i++)
|
||||
{
|
||||
trace("OBJ #%lu, access status 0x%08lx, granted access 0x%08lx\n", i, AccessStatus[i], GrantedAccess[i]);
|
||||
}
|
||||
trace("\n");
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
GrantedAccessTests(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
NTSTATUS AccessStatus[6];
|
||||
ACCESS_MASK GrantedAccess[6];
|
||||
PPRIVILEGE_SET PrivilegeSet = NULL;
|
||||
ULONG PrivilegeSetLength;
|
||||
HANDLE Token = NULL;
|
||||
PACL Dacl = NULL;
|
||||
ULONG DaclSize;
|
||||
ULONG i;
|
||||
SECURITY_DESCRIPTOR Sd;
|
||||
OBJECT_TYPE_LIST ObjTypeList[6];
|
||||
PSID EveryoneSid = NULL, AdminSid = NULL, UsersSid = NULL;
|
||||
GUID ChildObjectType2 = {0x34578901, 0x3456, 0x7896, {0x3, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00}};
|
||||
GUID ChildObjectType3 = {0x45678901, 0x4567, 0x1122, {0x4, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x01}};
|
||||
GUID ChildObjectType4 = {0x56788901, 0x1111, 0x2222, {0x5, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x02}};
|
||||
GUID ChildObjectType5 = {0x67901234, 0x2222, 0x3333, {0x4, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x03}};
|
||||
|
||||
/* Allocate all the stuff we need */
|
||||
PrivilegeSetLength = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
|
||||
PrivilegeSet = RtlAllocateHeap(RtlGetProcessHeap(), 0, PrivilegeSetLength);
|
||||
if (PrivilegeSet == NULL)
|
||||
{
|
||||
skip("Failed to allocate PrivilegeSet, skipping tests\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Status = RtlAllocateAndInitializeSid(&WorldAuthority,
|
||||
1,
|
||||
SECURITY_WORLD_RID,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&EveryoneSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create Everyone SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlAllocateAndInitializeSid(&NtAuthority,
|
||||
2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_ADMINS,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&AdminSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create Admins SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlAllocateAndInitializeSid(&NtAuthority,
|
||||
2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_USERS,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&UsersSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create User SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Token = GetTokenProcess(TRUE, TRUE);
|
||||
if (Token == NULL)
|
||||
{
|
||||
skip("Failed to get token, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlCreateSecurityDescriptor(&Sd, SECURITY_DESCRIPTOR_REVISION);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create a security descriptor, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
DaclSize = sizeof(ACL) +
|
||||
sizeof(ACCESS_ALLOWED_OBJECT_ACE) + RtlLengthSid(AdminSid) +
|
||||
sizeof(ACCESS_ALLOWED_OBJECT_ACE) + RtlLengthSid(EveryoneSid) +
|
||||
sizeof(ACCESS_ALLOWED_OBJECT_ACE) + RtlLengthSid(EveryoneSid);
|
||||
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
DaclSize);
|
||||
if (Dacl == NULL)
|
||||
{
|
||||
skip("Failed to allocate memory for DACL, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlCreateAcl(Dacl,
|
||||
DaclSize,
|
||||
ACL_REVISION4);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create DACL, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Admins have full access over the key object, everyone else can only read from
|
||||
* it and can only query the value from the child sub-object.
|
||||
*/
|
||||
Status = RtlAddAccessAllowedObjectAce(Dacl,
|
||||
ACL_REVISION4,
|
||||
0,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectType,
|
||||
NULL,
|
||||
AdminSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to add allowed object ACE for Admins SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlAddAccessAllowedObjectAce(Dacl,
|
||||
ACL_REVISION4,
|
||||
0,
|
||||
KEY_READ,
|
||||
&ObjectType,
|
||||
NULL,
|
||||
EveryoneSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to add allowed object ACE for Everyone SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlAddAccessAllowedObjectAce(Dacl,
|
||||
ACL_REVISION4,
|
||||
0,
|
||||
KEY_QUERY_VALUE,
|
||||
&ChildObjectType,
|
||||
NULL,
|
||||
EveryoneSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to add allowed object ACE for Everyone SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Setup the descriptor */
|
||||
RtlSetGroupSecurityDescriptor(&Sd, UsersSid, FALSE);
|
||||
RtlSetOwnerSecurityDescriptor(&Sd, AdminSid, FALSE);
|
||||
RtlSetDaclSecurityDescriptor(&Sd, TRUE, Dacl, FALSE);
|
||||
|
||||
/* Setup the object type list */
|
||||
ObjTypeList[0].Level = ACCESS_OBJECT_GUID;
|
||||
ObjTypeList[0].Sbz = 0;
|
||||
ObjTypeList[0].ObjectType = &ObjectType;
|
||||
|
||||
ObjTypeList[1].Level = ACCESS_PROPERTY_SET_GUID;
|
||||
ObjTypeList[1].Sbz = 0;
|
||||
ObjTypeList[1].ObjectType = &ChildObjectType;
|
||||
|
||||
ObjTypeList[2].Level = ACCESS_PROPERTY_GUID;
|
||||
ObjTypeList[2].Sbz = 0;
|
||||
ObjTypeList[2].ObjectType = &ChildObjectType2;
|
||||
|
||||
ObjTypeList[3].Level = ACCESS_PROPERTY_GUID;
|
||||
ObjTypeList[3].Sbz = 0;
|
||||
ObjTypeList[3].ObjectType = &ChildObjectType3;
|
||||
|
||||
ObjTypeList[4].Level = ACCESS_PROPERTY_SET_GUID;
|
||||
ObjTypeList[4].Sbz = 0;
|
||||
ObjTypeList[4].ObjectType = &ChildObjectType4;
|
||||
|
||||
ObjTypeList[5].Level = ACCESS_PROPERTY_GUID;
|
||||
ObjTypeList[5].Sbz = 0;
|
||||
ObjTypeList[5].ObjectType = &ChildObjectType5;
|
||||
|
||||
/* Admins should be granted every access */
|
||||
Status = NtAccessCheckByTypeResultList(&Sd,
|
||||
NULL,
|
||||
Token,
|
||||
MAXIMUM_ALLOWED,
|
||||
ObjTypeList,
|
||||
RTL_NUMBER_OF(ObjTypeList),
|
||||
&RegMapping,
|
||||
PrivilegeSet,
|
||||
&PrivilegeSetLength,
|
||||
GrantedAccess,
|
||||
AccessStatus);
|
||||
ok_hex(Status, STATUS_SUCCESS);
|
||||
|
||||
PrintAccessStatusAndGrantedAccess(AccessStatus, GrantedAccess, RTL_NUMBER_OF(ObjTypeList));
|
||||
for (i = 0; i < RTL_NUMBER_OF(ObjTypeList); i++)
|
||||
{
|
||||
ok(AccessStatus[i] == STATUS_SUCCESS, "Expected STATUS_SUCCESS but got 0x%08lx\n", AccessStatus[i]);
|
||||
ok(GrantedAccess[i] == KEY_ALL_ACCESS, "Expected KEY_ALL_ACCESS but got 0x%08lx\n", GrantedAccess[i]);
|
||||
}
|
||||
|
||||
/* Everyone else can only read */
|
||||
Status = NtAccessCheckByTypeResultList(&Sd,
|
||||
NULL,
|
||||
Token,
|
||||
KEY_READ,
|
||||
ObjTypeList,
|
||||
RTL_NUMBER_OF(ObjTypeList),
|
||||
&RegMapping,
|
||||
PrivilegeSet,
|
||||
&PrivilegeSetLength,
|
||||
GrantedAccess,
|
||||
AccessStatus);
|
||||
ok_hex(Status, STATUS_SUCCESS);
|
||||
|
||||
PrintAccessStatusAndGrantedAccess(AccessStatus, GrantedAccess, RTL_NUMBER_OF(ObjTypeList));
|
||||
for (i = 0; i < RTL_NUMBER_OF(ObjTypeList); i++)
|
||||
{
|
||||
ok(AccessStatus[i] == STATUS_SUCCESS, "Expected STATUS_SUCCESS but got 0x%08lx\n", AccessStatus[i]);
|
||||
ok(GrantedAccess[i] == KEY_READ, "Expected KEY_READ but got 0x%08lx\n", GrantedAccess[i]);
|
||||
}
|
||||
|
||||
/* Everyone else can only query a registry value from the child object */
|
||||
Status = NtAccessCheckByTypeResultList(&Sd,
|
||||
NULL,
|
||||
Token,
|
||||
KEY_QUERY_VALUE,
|
||||
ObjTypeList,
|
||||
RTL_NUMBER_OF(ObjTypeList),
|
||||
&RegMapping,
|
||||
PrivilegeSet,
|
||||
&PrivilegeSetLength,
|
||||
GrantedAccess,
|
||||
AccessStatus);
|
||||
ok_hex(Status, STATUS_SUCCESS);
|
||||
|
||||
PrintAccessStatusAndGrantedAccess(AccessStatus, GrantedAccess, RTL_NUMBER_OF(ObjTypeList));
|
||||
for (i = 0; i < RTL_NUMBER_OF(ObjTypeList); i++)
|
||||
{
|
||||
ok(AccessStatus[i] == STATUS_SUCCESS, "Expected STATUS_SUCCESS but got 0x%08lx\n", AccessStatus[i]);
|
||||
ok(GrantedAccess[i] == KEY_QUERY_VALUE, "Expected KEY_QUERY_VALUE but got 0x%08lx\n", GrantedAccess[i]);
|
||||
}
|
||||
|
||||
Quit:
|
||||
if (Dacl)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
|
||||
}
|
||||
|
||||
if (Token)
|
||||
{
|
||||
NtClose(Token);
|
||||
}
|
||||
|
||||
if (UsersSid)
|
||||
{
|
||||
RtlFreeSid(UsersSid);
|
||||
}
|
||||
|
||||
if (AdminSid)
|
||||
{
|
||||
RtlFreeSid(AdminSid);
|
||||
}
|
||||
|
||||
if (EveryoneSid)
|
||||
{
|
||||
RtlFreeSid(EveryoneSid);
|
||||
}
|
||||
|
||||
if (PrivilegeSet)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, PrivilegeSet);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
DenyAccessTests(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
NTSTATUS AccessStatus[6];
|
||||
ACCESS_MASK GrantedAccess[6];
|
||||
PPRIVILEGE_SET PrivilegeSet = NULL;
|
||||
ULONG PrivilegeSetLength;
|
||||
HANDLE Token = NULL;
|
||||
PACL Dacl = NULL;
|
||||
ULONG DaclSize;
|
||||
ULONG i;
|
||||
SECURITY_DESCRIPTOR Sd;
|
||||
OBJECT_TYPE_LIST ObjTypeList[6];
|
||||
PSID EveryoneSid = NULL, AdminSid = NULL, UsersSid = NULL;
|
||||
GUID ChildObjectType2 = {0x34578901, 0x3456, 0x7896, {0x3, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00}};
|
||||
GUID ChildObjectType3 = {0x45678901, 0x4567, 0x1122, {0x4, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x01}};
|
||||
GUID ChildObjectType4 = {0x56788901, 0x1111, 0x2222, {0x5, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x02}};
|
||||
GUID ChildObjectType5 = {0x67901234, 0x2222, 0x3333, {0x4, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x03}};
|
||||
|
||||
/* Allocate all the stuff we need */
|
||||
PrivilegeSetLength = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
|
||||
PrivilegeSet = RtlAllocateHeap(RtlGetProcessHeap(), 0, PrivilegeSetLength);
|
||||
if (PrivilegeSet == NULL)
|
||||
{
|
||||
skip("Failed to allocate PrivilegeSet, skipping tests\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Status = RtlAllocateAndInitializeSid(&WorldAuthority,
|
||||
1,
|
||||
SECURITY_WORLD_RID,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&EveryoneSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create Everyone SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlAllocateAndInitializeSid(&NtAuthority,
|
||||
2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_ADMINS,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&AdminSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create Admins SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlAllocateAndInitializeSid(&NtAuthority,
|
||||
2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_USERS,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&UsersSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create User SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Token = GetTokenProcess(TRUE, TRUE);
|
||||
if (Token == NULL)
|
||||
{
|
||||
skip("Failed to get token, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlCreateSecurityDescriptor(&Sd, SECURITY_DESCRIPTOR_REVISION);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create a security descriptor, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
DaclSize = sizeof(ACL) +
|
||||
sizeof(ACCESS_DENIED_OBJECT_ACE) + RtlLengthSid(AdminSid) +
|
||||
sizeof(ACCESS_DENIED_OBJECT_ACE) + RtlLengthSid(EveryoneSid) +
|
||||
sizeof(ACCESS_ALLOWED_OBJECT_ACE) + RtlLengthSid(EveryoneSid);
|
||||
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
DaclSize);
|
||||
if (Dacl == NULL)
|
||||
{
|
||||
skip("Failed to allocate memory for DACL, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlCreateAcl(Dacl,
|
||||
DaclSize,
|
||||
ACL_REVISION4);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to create DACL, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Admins can't read the main object, whereas everyone else can't write
|
||||
* into the child object.
|
||||
*/
|
||||
Status = RtlAddAccessDeniedObjectAce(Dacl,
|
||||
ACL_REVISION4,
|
||||
0,
|
||||
KEY_READ,
|
||||
&ObjectType,
|
||||
NULL,
|
||||
AdminSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to add deny object ACE for Admins SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Status = RtlAddAccessDeniedObjectAce(Dacl,
|
||||
ACL_REVISION4,
|
||||
0,
|
||||
KEY_WRITE,
|
||||
&ChildObjectType,
|
||||
NULL,
|
||||
EveryoneSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
skip("Failed to add deny object ACE for Everyone SID, skipping tests\n");
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Setup the descriptor */
|
||||
RtlSetGroupSecurityDescriptor(&Sd, UsersSid, FALSE);
|
||||
RtlSetOwnerSecurityDescriptor(&Sd, AdminSid, FALSE);
|
||||
RtlSetDaclSecurityDescriptor(&Sd, TRUE, Dacl, FALSE);
|
||||
|
||||
/* Setup the object type list */
|
||||
ObjTypeList[0].Level = ACCESS_OBJECT_GUID;
|
||||
ObjTypeList[0].Sbz = 0;
|
||||
ObjTypeList[0].ObjectType = &ObjectType;
|
||||
|
||||
ObjTypeList[1].Level = ACCESS_PROPERTY_SET_GUID;
|
||||
ObjTypeList[1].Sbz = 0;
|
||||
ObjTypeList[1].ObjectType = &ChildObjectType;
|
||||
|
||||
ObjTypeList[2].Level = ACCESS_PROPERTY_GUID;
|
||||
ObjTypeList[2].Sbz = 0;
|
||||
ObjTypeList[2].ObjectType = &ChildObjectType2;
|
||||
|
||||
ObjTypeList[3].Level = ACCESS_PROPERTY_GUID;
|
||||
ObjTypeList[3].Sbz = 0;
|
||||
ObjTypeList[3].ObjectType = &ChildObjectType3;
|
||||
|
||||
ObjTypeList[4].Level = ACCESS_PROPERTY_SET_GUID;
|
||||
ObjTypeList[4].Sbz = 0;
|
||||
ObjTypeList[4].ObjectType = &ChildObjectType4;
|
||||
|
||||
ObjTypeList[5].Level = ACCESS_PROPERTY_GUID;
|
||||
ObjTypeList[5].Sbz = 0;
|
||||
ObjTypeList[5].ObjectType = &ChildObjectType5;
|
||||
|
||||
/*
|
||||
* Admins shouldn't be able to read from the main object.
|
||||
* NtAccessCheckByTypeResultList will return partial rights
|
||||
* that have been granted to the caller even if the caller
|
||||
* did not get all the rights he wanted.
|
||||
*/
|
||||
Status = NtAccessCheckByTypeResultList(&Sd,
|
||||
NULL,
|
||||
Token,
|
||||
KEY_READ,
|
||||
ObjTypeList,
|
||||
RTL_NUMBER_OF(ObjTypeList),
|
||||
&RegMapping,
|
||||
PrivilegeSet,
|
||||
&PrivilegeSetLength,
|
||||
GrantedAccess,
|
||||
AccessStatus);
|
||||
ok_hex(Status, STATUS_SUCCESS);
|
||||
|
||||
PrintAccessStatusAndGrantedAccess(AccessStatus, GrantedAccess, RTL_NUMBER_OF(ObjTypeList));
|
||||
for (i = 0; i < RTL_NUMBER_OF(ObjTypeList); i++)
|
||||
{
|
||||
ok(AccessStatus[i] == STATUS_ACCESS_DENIED, "Expected STATUS_ACCESS_DENIED but got 0x%08lx\n", AccessStatus[i]);
|
||||
ok(GrantedAccess[i] == READ_CONTROL, "Expected READ_CONTROL as given partial right but got 0x%08lx\n", GrantedAccess[i]);
|
||||
}
|
||||
|
||||
/* Everyone else can't write into the child object */
|
||||
Status = NtAccessCheckByTypeResultList(&Sd,
|
||||
NULL,
|
||||
Token,
|
||||
KEY_WRITE,
|
||||
ObjTypeList,
|
||||
RTL_NUMBER_OF(ObjTypeList),
|
||||
&RegMapping,
|
||||
PrivilegeSet,
|
||||
&PrivilegeSetLength,
|
||||
GrantedAccess,
|
||||
AccessStatus);
|
||||
ok_hex(Status, STATUS_SUCCESS);
|
||||
|
||||
PrintAccessStatusAndGrantedAccess(AccessStatus, GrantedAccess, RTL_NUMBER_OF(ObjTypeList));
|
||||
for (i = 0; i < RTL_NUMBER_OF(ObjTypeList); i++)
|
||||
{
|
||||
ok(AccessStatus[i] == STATUS_ACCESS_DENIED, "Expected STATUS_ACCESS_DENIED but got 0x%08lx\n", AccessStatus[i]);
|
||||
ok(GrantedAccess[i] == READ_CONTROL, "Expected READ_CONTROL as given partial right but got 0x%08lx\n", GrantedAccess[i]);
|
||||
}
|
||||
|
||||
Quit:
|
||||
if (Dacl)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
|
||||
}
|
||||
|
||||
if (Token)
|
||||
{
|
||||
NtClose(Token);
|
||||
}
|
||||
|
||||
if (UsersSid)
|
||||
{
|
||||
RtlFreeSid(UsersSid);
|
||||
}
|
||||
|
||||
if (AdminSid)
|
||||
{
|
||||
RtlFreeSid(AdminSid);
|
||||
}
|
||||
|
||||
if (EveryoneSid)
|
||||
{
|
||||
RtlFreeSid(EveryoneSid);
|
||||
}
|
||||
|
||||
if (PrivilegeSet)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, PrivilegeSet);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(NtAccessCheckByTypeResultList)
|
||||
{
|
||||
ParamValidationNoObjsList();
|
||||
GrantedAccessTests();
|
||||
DenyAccessTests();
|
||||
}
|
@ -7,6 +7,7 @@ extern void func_LdrEnumResources(void);
|
||||
extern void func_load_notifications(void);
|
||||
extern void func_NtAcceptConnectPort(void);
|
||||
extern void func_NtAccessCheckByType(void);
|
||||
extern void func_NtAccessCheckByTypeResultList(void);
|
||||
extern void func_NtAdjustGroupsToken(void);
|
||||
extern void func_NtAdjustPrivilegesToken(void);
|
||||
extern void func_NtAllocateVirtualMemory(void);
|
||||
@ -101,6 +102,7 @@ const struct test winetest_testlist[] =
|
||||
{ "load_notifications", func_load_notifications },
|
||||
{ "NtAcceptConnectPort", func_NtAcceptConnectPort },
|
||||
{ "NtAccessCheckByType", func_NtAccessCheckByType },
|
||||
{ "NtAccessCheckByTypeResultList", func_NtAccessCheckByTypeResultList },
|
||||
{ "NtAdjustGroupsToken", func_NtAdjustGroupsToken },
|
||||
{ "NtAdjustPrivilegesToken", func_NtAdjustPrivilegesToken },
|
||||
{ "NtAllocateVirtualMemory", func_NtAllocateVirtualMemory },
|
||||
|
Loading…
Reference in New Issue
Block a user