From 418629f6a904fa942c658db77046f904f048da84 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Tue, 4 Nov 2014 22:42:15 +0000 Subject: [PATCH] [KMTESTS:SE] - Add a test for SeAssignSecurity[Ex] CORE-8745 svn path=/trunk/; revision=65258 --- rostests/kmtests/CMakeLists.txt | 2 + rostests/kmtests/kmtest_drv/testlist.c | 2 + rostests/kmtests/ntos_se/SeHelpers.c | 194 +++++ rostests/kmtests/ntos_se/SeInheritance.c | 880 +++++++++++++++++++++++ rostests/kmtests/ntos_se/se.h | 63 ++ 5 files changed, 1141 insertions(+) create mode 100644 rostests/kmtests/ntos_se/SeHelpers.c create mode 100644 rostests/kmtests/ntos_se/SeInheritance.c create mode 100644 rostests/kmtests/ntos_se/se.h diff --git a/rostests/kmtests/CMakeLists.txt b/rostests/kmtests/CMakeLists.txt index 8de380d3bed..969ba8b99d7 100644 --- a/rostests/kmtests/CMakeLists.txt +++ b/rostests/kmtests/CMakeLists.txt @@ -71,6 +71,8 @@ list(APPEND KMTEST_DRV_SOURCE ntos_ob/ObType.c ntos_ob/ObTypes.c ntos_ps/PsNotify.c + ntos_se/SeHelpers.c + ntos_se/SeInheritance.c ntos_se/SeQueryInfoToken.c ${COMMON_SOURCE} diff --git a/rostests/kmtests/kmtest_drv/testlist.c b/rostests/kmtests/kmtest_drv/testlist.c index f1795f02748..bcf1e9b2333 100644 --- a/rostests/kmtests/kmtest_drv/testlist.c +++ b/rostests/kmtests/kmtest_drv/testlist.c @@ -50,6 +50,7 @@ KMT_TESTFUNC Test_ObTypeClean; KMT_TESTFUNC Test_ObTypeNoClean; KMT_TESTFUNC Test_ObTypes; KMT_TESTFUNC Test_PsNotify; +KMT_TESTFUNC Test_SeInheritance; KMT_TESTFUNC Test_SeQueryInfoToken; KMT_TESTFUNC Test_RtlAvlTree; KMT_TESTFUNC Test_RtlException; @@ -107,6 +108,7 @@ const KMT_TEST TestList[] = { "-ObTypeNoClean", Test_ObTypeNoClean }, { "ObTypes", Test_ObTypes }, { "PsNotify", Test_PsNotify }, + { "SeInheritance", Test_SeInheritance }, { "-SeQueryInfoToken", Test_SeQueryInfoToken }, { "RtlAvlTreeKM", Test_RtlAvlTree }, { "RtlExceptionKM", Test_RtlException }, diff --git a/rostests/kmtests/ntos_se/SeHelpers.c b/rostests/kmtests/ntos_se/SeHelpers.c new file mode 100644 index 00000000000..c6575a891be --- /dev/null +++ b/rostests/kmtests/ntos_se/SeHelpers.c @@ -0,0 +1,194 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Kernel-Mode Test Suite Helper functions for Se tests + * PROGRAMMER: Thomas Faber + */ + +#include +#include "se.h" + +NTSTATUS +RtlxAddAuditAccessAceEx( + _Inout_ PACL Acl, + _In_ ULONG Revision, + _In_ ULONG Flags, + _In_ ACCESS_MASK AccessMask, + _In_ PSID Sid, + _In_ BOOLEAN Success, + _In_ BOOLEAN Failure) +{ + NTSTATUS Status; + USHORT AceSize; + PSYSTEM_AUDIT_ACE Ace; + + if (Success) Flags |= SUCCESSFUL_ACCESS_ACE_FLAG; + if (Failure) Flags |= FAILED_ACCESS_ACE_FLAG; + + AceSize = FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + RtlLengthSid(Sid); + Ace = ExAllocatePoolWithTag(PagedPool, AceSize, 'cAmK'); + if (!Ace) + return STATUS_INSUFFICIENT_RESOURCES; + Ace->Header.AceType = SYSTEM_AUDIT_ACE_TYPE; + Ace->Header.AceFlags = Flags; + Ace->Header.AceSize = AceSize; + Ace->Mask = AccessMask; + Status = RtlCopySid(AceSize - FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart), + (PSID)&Ace->SidStart, + Sid); + ASSERT(NT_SUCCESS(Status)); + if (NT_SUCCESS(Status)) + { + Status = RtlAddAce(Acl, + Revision, + MAXULONG, + Ace, + AceSize); + } + ExFreePoolWithTag(Ace, 'cAmK'); + return Status; +} + +VOID +CheckSid__( + _In_ PSID Sid, + _In_ ULONG SidSize, + _In_ PISID ExpectedSid, + _In_ PCSTR FileAndLine) +{ + BOOLEAN Okay; + ULONG Length; + + KmtOk(Sid != NULL, FileAndLine, "Sid is NULL\n"); + if (KmtSkip(Sid != NULL, FileAndLine, "No Sid\n")) + return; + if (KmtSkip(SidSize >= sizeof(ULONG), FileAndLine, "Sid too small: %lu\n", SidSize)) + return; + Okay = RtlValidSid(Sid); + KmtOk(Okay == TRUE, FileAndLine, "Invalid Sid\n"); + if (KmtSkip(Okay, FileAndLine, "Invalid Sid\n")) + return; + + Length = RtlLengthSid(Sid); + KmtOk(SidSize >= Length, FileAndLine, "SidSize %lu too small, need %lu\n", SidSize, Length); + if (KmtSkip(SidSize >= Length, FileAndLine, "Sid too small\n")) + return; + Okay = RtlEqualSid(Sid, ExpectedSid); + KmtOk(Okay, FileAndLine, "Sids %p and %p not equal\n", Sid, ExpectedSid); + if (!Okay) + { + WCHAR Buffer1[128]; + WCHAR Buffer2[128]; + UNICODE_STRING SidString1, SidString2; + RtlInitEmptyUnicodeString(&SidString1, Buffer1, sizeof(Buffer1)); + RtlInitEmptyUnicodeString(&SidString2, Buffer2, sizeof(Buffer2)); + (void)RtlConvertSidToUnicodeString(&SidString1, Sid, FALSE); + (void)RtlConvertSidToUnicodeString(&SidString2, ExpectedSid, FALSE); + KmtOk(0, FileAndLine, "Got %wZ, expected %wZ\n", &SidString1, &SidString2); + } +} + +VOID +VCheckAcl__( + _In_ PACL Acl, + _In_ ULONG AceCount, + _In_ PCSTR FileAndLine, + _In_ va_list Arguments) +{ + ULONG i; + ULONG Offset; + PACE_HEADER AceHeader; + INT AceType; + INT AceFlags; + ACCESS_MASK Mask; + PISID Sid; + PACCESS_ALLOWED_ACE AllowedAce; + PACCESS_DENIED_ACE DeniedAce; + PSYSTEM_AUDIT_ACE AuditAce; + + KmtOk(Acl != NULL, FileAndLine, "Acl is NULL\n"); + if (KmtSkip(Acl != NULL, FileAndLine, "No ACL\n")) + return; + KmtOk((ULONG_PTR)Acl % sizeof(ULONG) == 0, FileAndLine, "Unaligned ACL %p\n", Acl); + KmtOk(Acl->AclRevision == ACL_REVISION, FileAndLine, "AclRevision is %u\n", Acl->AclRevision); + KmtOk(Acl->Sbz1 == 0, FileAndLine, "Sbz1 is %u\n", Acl->Sbz1); + KmtOk(Acl->Sbz2 == 0, FileAndLine, "Sbz2 is %u\n", Acl->Sbz2); + KmtOk(Acl->AclSize >= sizeof(*Acl), FileAndLine, "AclSize too small: %u\n", Acl->AclSize); + KmtOk(Acl->AceCount == AceCount, FileAndLine, "AceCount is %u, expected %lu\n", Acl->AceCount, AceCount); + Offset = sizeof(*Acl); + for (i = 0; i < Acl->AceCount; i++) + { + KmtOk(Acl->AclSize >= Offset + sizeof(*AceHeader), FileAndLine, "AclSize too small (%u) at Offset %lu, ACE #%lu\n", Acl->AclSize, Offset, i); + if (Acl->AclSize < Offset + sizeof(*AceHeader)) + break; + AceHeader = (PACE_HEADER)((PUCHAR)Acl + Offset); + KmtOk((ULONG_PTR)AceHeader % sizeof(ULONG) == 0, FileAndLine, "[%lu] Unaligned ACE %p\n", i, AceHeader); + KmtOk(AceHeader->AceSize % sizeof(ULONG) == 0, FileAndLine, "[%lu] Unaligned ACE size %u\n", i, AceHeader->AceSize); + KmtOk(Acl->AclSize >= Offset + AceHeader->AceSize, FileAndLine, "[%lu] AclSize too small (%u) at Offset %lu\n", i, Acl->AclSize, Offset); + if (Acl->AclSize < Offset + AceHeader->AceSize) + break; + Offset += AceHeader->AceSize; + if (i >= AceCount) + continue; + AceType = va_arg(Arguments, INT); + AceFlags = va_arg(Arguments, INT); + KmtOk(AceHeader->AceType == AceType, FileAndLine, "[%lu] AceType is %u, expected %u\n", i, AceHeader->AceType, AceType); + KmtOk(AceHeader->AceFlags == AceFlags, FileAndLine, "[%lu] AceFlags is 0x%x, expected 0x%x\n", i, AceHeader->AceFlags, AceFlags); + if (AceType == ACCESS_ALLOWED_ACE_TYPE) + { + Sid = va_arg(Arguments, PSID); + Mask = va_arg(Arguments, INT); + KmtOk(AceHeader->AceSize >= sizeof(*AllowedAce), FileAndLine, "[%lu] AllowedAce AceSize too small: %u\n", i, AceHeader->AceSize); + if (AceHeader->AceSize < sizeof(*AllowedAce)) + continue; + AllowedAce = (PACCESS_ALLOWED_ACE)AceHeader; + KmtOk(AllowedAce->Mask == Mask, FileAndLine, "[%lu] AllowedAce Mask is 0x%lx, expected 0x%lx\n", i, AllowedAce->Mask, Mask); + CheckSid__((PSID)&AllowedAce->SidStart, + AceHeader->AceSize - FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart), + Sid, + FileAndLine); + } + else if (AceType == ACCESS_DENIED_ACE_TYPE) + { + Sid = va_arg(Arguments, PSID); + Mask = va_arg(Arguments, INT); + KmtOk(AceHeader->AceSize >= sizeof(*DeniedAce), FileAndLine, "[%lu] DeniedAce AceSize too small: %u\n", i, AceHeader->AceSize); + if (AceHeader->AceSize < sizeof(*DeniedAce)) + continue; + DeniedAce = (PACCESS_DENIED_ACE)AceHeader; + KmtOk(DeniedAce->Mask == Mask, FileAndLine, "[%lu] DeniedAce Mask is 0x%lx, expected 0x%lx\n", i, DeniedAce->Mask, Mask); + CheckSid__((PSID)&DeniedAce->SidStart, + AceHeader->AceSize - FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart), + Sid, + FileAndLine); + } + else if (AceType == SYSTEM_AUDIT_ACE_TYPE) + { + Sid = va_arg(Arguments, PSID); + Mask = va_arg(Arguments, INT); + KmtOk(AceHeader->AceSize >= sizeof(*AuditAce), FileAndLine, "[%lu] AuditAce AceSize too small: %u\n", i, AceHeader->AceSize); + if (AceHeader->AceSize < sizeof(*AuditAce)) + continue; + AuditAce = (PSYSTEM_AUDIT_ACE)AceHeader; + KmtOk(AuditAce->Mask == Mask, FileAndLine, "[%lu] AuditAce Mask is 0x%lx, expected 0x%lx\n", i, AuditAce->Mask, Mask); + CheckSid__((PSID)&AuditAce->SidStart, + AceHeader->AceSize - FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart), + Sid, + FileAndLine); + } + } +} + +VOID +CheckAcl__( + _In_ PACL Acl, + _In_ ULONG AceCount, + _In_ PCSTR FileAndLine, + ...) +{ + va_list Arguments; + + va_start(Arguments, FileAndLine); + VCheckAcl__(Acl, AceCount, FileAndLine, Arguments); + va_end(Arguments); +} diff --git a/rostests/kmtests/ntos_se/SeInheritance.c b/rostests/kmtests/ntos_se/SeInheritance.c new file mode 100644 index 00000000000..773311925c3 --- /dev/null +++ b/rostests/kmtests/ntos_se/SeInheritance.c @@ -0,0 +1,880 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Kernel-Mode Test for object security inheritance + * PROGRAMMER: Thomas Faber + */ + +#include +#include "se.h" + +static GENERIC_MAPPING GenericMapping = +{ + STANDARD_RIGHTS_READ | 0x1001, + STANDARD_RIGHTS_WRITE | 0x2002, + STANDARD_RIGHTS_EXECUTE | 0x4004, + STANDARD_RIGHTS_ALL | 0x800F, +}; + +static +VOID +TestSeAssignSecurity( + _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext) +{ + NTSTATUS Status; + PTOKEN Token; + PSECURITY_DESCRIPTOR SecurityDescriptor; + SECURITY_DESCRIPTOR ParentDescriptor; + SECURITY_DESCRIPTOR ExplicitDescriptor; + ACL EmptyAcl; + PACL Acl; + PACL Acl2; + ULONG AclSize; + ULONG UsingDefault; + ULONG CanInherit; + ULONG AceFlags; + ULONG AceFlags2; + ULONG Access; + PSID GenericSid; + PSID GenericSid2; + ACCESS_MASK GenericMask; + ACCESS_MASK GenericMask2; + PSID SpecificSid; + ACCESS_MASK SpecificMask; + ACCESS_MASK SpecificMask2; + BOOLEAN ParentUsable; + + Token = SubjectContext->PrimaryToken; + CheckAcl(Token->DefaultDacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, GENERIC_ALL, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, GENERIC_READ | GENERIC_EXECUTE | STANDARD_RIGHTS_READ); + CheckSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid, NO_SIZE, SeExports->SeAliasAdminsSid); + CheckSid(Token->PrimaryGroup, NO_SIZE, SeExports->SeLocalSystemSid); +// Flags with no effect on current tests: SEF_SACL_AUTO_INHERIT, SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT +#define StartTestAssign(Parent, Explicit, IsDir, GotDacl, GotSacl) \ + SecurityDescriptor = NULL; \ + Status = SeAssignSecurity (Parent, \ + Explicit, \ + &SecurityDescriptor, \ + /*NULL,*/ \ + IsDir, \ + /*0,*/ \ + SubjectContext, \ + &GenericMapping, \ + PagedPool); \ + ok_eq_hex(Status, STATUS_SUCCESS); \ + if (!skip(NT_SUCCESS(Status), "No security\n")) \ + { \ + PACL Dacl, Sacl; \ + PSID Owner, Group; \ + BOOLEAN Present; \ + BOOLEAN DaclDefaulted, SaclDefaulted; \ + BOOLEAN OwnerDefaulted, GroupDefaulted; \ + Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, \ + &Present, \ + &Dacl, \ + &DaclDefaulted); \ + ok_eq_hex(Status, STATUS_SUCCESS); \ + ok_eq_uint(Present, GotDacl); \ + if (!NT_SUCCESS(Status) || !Present) \ + Dacl = NULL; \ + Status = RtlGetSaclSecurityDescriptor(SecurityDescriptor, \ + &Present, \ + &Sacl, \ + &SaclDefaulted); \ + ok_eq_hex(Status, STATUS_SUCCESS); \ + ok_eq_uint(Present, GotSacl); \ + if (!NT_SUCCESS(Status) || !Present) \ + Sacl = NULL; \ + Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor, \ + &Owner, \ + &OwnerDefaulted); \ + ok_eq_hex(Status, STATUS_SUCCESS); \ + if (skip(NT_SUCCESS(Status), "No owner\n")) \ + Owner = NULL; \ + Status = RtlGetGroupSecurityDescriptor(SecurityDescriptor, \ + &Group, \ + &GroupDefaulted); \ + ok_eq_hex(Status, STATUS_SUCCESS); \ + if (skip(NT_SUCCESS(Status), "No group\n")) \ + Group = NULL; + +#define EndTestAssign() \ + SeDeassignSecurity(&SecurityDescriptor); \ + } +#define StartTestAssignLoop(Parent, Explicit) \ + { \ + BOOLEAN IsDir; \ + BOOLEAN UsingParent; \ + BOOLEAN UsingExplicit; \ + for (IsDir = FALSE; IsDir <= TRUE; IsDir++) \ + { \ + for (UsingParent = FALSE; UsingParent <= TRUE; UsingParent++) \ + { \ + for (UsingExplicit = FALSE; UsingExplicit <= TRUE; UsingExplicit++) \ + { \ + StartTestAssign(UsingParent ? Parent : NULL, \ + UsingExplicit ? Explicit : NULL, \ + IsDir, \ + TRUE, \ + FALSE) +#define EndTestAssignLoop() \ + EndTestAssign() \ + } \ + } \ + } \ + } +#define TestAssignExpectDefault(Parent, Explicit, IsDir) \ + StartTestAssign(Parent, Explicit, IsDir, TRUE, FALSE) \ + ok_eq_uint(DaclDefaulted, FALSE); \ + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, \ + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); \ + ok_eq_uint(OwnerDefaulted, FALSE); \ + CheckSid(Owner, NO_SIZE, Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); \ + ok_eq_uint(GroupDefaulted, FALSE); \ + CheckSid(Group, NO_SIZE, Token->PrimaryGroup); \ + EndTestAssign() +#define TestAssignExpectDefaultAll() \ + TestAssignExpectDefault(&ParentDescriptor, NULL, FALSE) \ + TestAssignExpectDefault(&ParentDescriptor, NULL, TRUE) \ + TestAssignExpectDefault(NULL, &ExplicitDescriptor, FALSE) \ + TestAssignExpectDefault(NULL, &ExplicitDescriptor, TRUE) \ + TestAssignExpectDefault(&ParentDescriptor, &ExplicitDescriptor, FALSE) \ + TestAssignExpectDefault(&ParentDescriptor, &ExplicitDescriptor, TRUE) + + TestAssignExpectDefault(NULL, NULL, FALSE) + TestAssignExpectDefault(NULL, NULL, TRUE) + + /* Empty parent/explicit descriptors */ + Status = RtlCreateSecurityDescriptor(&ParentDescriptor, + SECURITY_DESCRIPTOR_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlCreateSecurityDescriptor(&ExplicitDescriptor, + SECURITY_DESCRIPTOR_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + TestAssignExpectDefaultAll() + + /* NULL DACL in parent/explicit descriptor */ + for (UsingDefault = FALSE; UsingDefault <= TRUE; UsingDefault++) + { + Status = RtlSetDaclSecurityDescriptor(&ParentDescriptor, + TRUE, + NULL, + UsingDefault); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + NULL, + UsingDefault); + ok_eq_hex(Status, STATUS_SUCCESS); + StartTestAssignLoop(&ParentDescriptor, &ExplicitDescriptor) + //trace("Explicit %u, Parent %u, Dir %u, Default %u\n", UsingExplicit, UsingParent, IsDir, UsingDefault); + ok_eq_uint(DaclDefaulted, FALSE); + if (UsingExplicit) + { + ok(Dacl == NULL, "Dacl = %p\n", Dacl); + } + else + { + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + } + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, SeExports->SeAliasAdminsSid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, SeExports->SeLocalSystemSid); + EndTestAssignLoop() + } + + /* Empty default DACL in parent/explicit descriptor */ + for (UsingDefault = FALSE; UsingDefault <= TRUE; UsingDefault++) + { + Status = RtlCreateAcl(&EmptyAcl, sizeof(EmptyAcl), ACL_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ParentDescriptor, + TRUE, + &EmptyAcl, + UsingDefault); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + &EmptyAcl, + UsingDefault); + ok_eq_hex(Status, STATUS_SUCCESS); + StartTestAssignLoop(&ParentDescriptor, &ExplicitDescriptor) + //trace("Explicit %u, Parent %u, Dir %u, Default %u\n", UsingExplicit, UsingParent, IsDir, UsingDefault); + ok_eq_uint(DaclDefaulted, FALSE); + if (UsingExplicit) + { + CheckAcl(Dacl, 0); + } + else + { + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + } + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, SeExports->SeAliasAdminsSid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, SeExports->SeLocalSystemSid); + EndTestAssignLoop() + } + + + AclSize = sizeof(ACL) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + RtlLengthSid(SeExports->SeWorldSid); + Acl = ExAllocatePoolWithTag(PagedPool, AclSize, 'ASmK'); + if (skip(Acl != NULL, "Out of memory\n")) + return; + + Acl2 = ExAllocatePoolWithTag(PagedPool, AclSize, 'ASmK'); + if (skip(Acl2 != NULL, "Out of memory\n")) + { + ExFreePoolWithTag(Acl, 'ASmK'); + return; + } + + /* Simple DACL in parent/explicit descriptor */ + for (UsingDefault = 0; UsingDefault <= 3; UsingDefault++) + { + Status = RtlCreateAcl(Acl, AclSize, ACL_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlAddAccessAllowedAceEx(Acl, ACL_REVISION, 0, READ_CONTROL, SeExports->SeWorldSid); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ParentDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 1)); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 2)); + ok_eq_hex(Status, STATUS_SUCCESS); + StartTestAssignLoop(&ParentDescriptor, &ExplicitDescriptor) + //trace("Explicit %u, Parent %u, Dir %u, Default %u\n", UsingExplicit, UsingParent, IsDir, UsingDefault); + ok_eq_uint(DaclDefaulted, FALSE); + if (UsingExplicit) + { + CheckAcl(Dacl, 1, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeWorldSid, READ_CONTROL); + } + else + { + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + } + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, SeExports->SeAliasAdminsSid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, SeExports->SeLocalSystemSid); + EndTestAssignLoop() + } + + /* Object-inheritable DACL in parent/explicit descriptor */ + for (UsingDefault = 0; UsingDefault <= 3; UsingDefault++) + { + Status = RtlCreateAcl(Acl, AclSize, ACL_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlAddAccessAllowedAceEx(Acl, ACL_REVISION, OBJECT_INHERIT_ACE, READ_CONTROL, SeExports->SeWorldSid); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ParentDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 1)); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 2)); + ok_eq_hex(Status, STATUS_SUCCESS); + StartTestAssignLoop(&ParentDescriptor, &ExplicitDescriptor) + //trace("Explicit %u, Parent %u, Dir %u, Default %u\n", UsingExplicit, UsingParent, IsDir, UsingDefault); + ok_eq_uint(DaclDefaulted, FALSE); + if (UsingExplicit && (!UsingParent || !FlagOn(UsingDefault, 2))) + { + CheckAcl(Dacl, 1, ACCESS_ALLOWED_ACE_TYPE, OBJECT_INHERIT_ACE, SeExports->SeWorldSid, READ_CONTROL); + } + else if (UsingParent) + { + CheckAcl(Dacl, 1, ACCESS_ALLOWED_ACE_TYPE, IsDir ? INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE : 0, SeExports->SeWorldSid, READ_CONTROL); + } + else + { + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + } + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, SeExports->SeAliasAdminsSid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, SeExports->SeLocalSystemSid); + EndTestAssignLoop() + } + + /* Container-inheritable DACL in parent/explicit descriptor */ + for (UsingDefault = 0; UsingDefault <= 3; UsingDefault++) + { + Status = RtlCreateAcl(Acl, AclSize, ACL_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlAddAccessAllowedAceEx(Acl, ACL_REVISION, CONTAINER_INHERIT_ACE, READ_CONTROL, SeExports->SeWorldSid); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ParentDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 1)); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 2)); + ok_eq_hex(Status, STATUS_SUCCESS); + StartTestAssignLoop(&ParentDescriptor, &ExplicitDescriptor) + //trace("Explicit %u, Parent %u, Dir %u, Default %u\n", UsingExplicit, UsingParent, IsDir, UsingDefault); + ok_eq_uint(DaclDefaulted, FALSE); + if (UsingExplicit || (UsingParent && IsDir)) + { + CheckAcl(Dacl, 1, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE, SeExports->SeWorldSid, READ_CONTROL); + } + else + { + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + } + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, SeExports->SeAliasAdminsSid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, SeExports->SeLocalSystemSid); + EndTestAssignLoop() + } + + /* Fully inheritable DACL in parent/explicit descriptor */ + for (UsingDefault = 0; UsingDefault <= 3; UsingDefault++) + { + Status = RtlCreateAcl(Acl, AclSize, ACL_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlAddAccessAllowedAceEx(Acl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, READ_CONTROL, SeExports->SeWorldSid); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ParentDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 1)); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 2)); + ok_eq_hex(Status, STATUS_SUCCESS); + StartTestAssignLoop(&ParentDescriptor, &ExplicitDescriptor) + //trace("Explicit %u, Parent %u, Dir %u, Default %u\n", UsingExplicit, UsingParent, IsDir, UsingDefault); + ok_eq_uint(DaclDefaulted, FALSE); + if (UsingExplicit && (!UsingParent || !FlagOn(UsingDefault, 2))) + { + CheckAcl(Dacl, 1, ACCESS_ALLOWED_ACE_TYPE, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, SeExports->SeWorldSid, READ_CONTROL); + } + else if (UsingParent) + { + CheckAcl(Dacl, 1, ACCESS_ALLOWED_ACE_TYPE, IsDir ? OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE : 0, SeExports->SeWorldSid, READ_CONTROL); + } + else + { + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + } + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, SeExports->SeAliasAdminsSid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, SeExports->SeLocalSystemSid); + EndTestAssignLoop() + } + + /* Different DACLs in parent and explicit descriptors */ + for (Access = 0; Access <= 1; Access++) + { + if (Access == 1) + { + GenericSid = SeExports->SeCreatorOwnerSid; + SpecificSid = SeExports->SeAliasAdminsSid; + GenericMask = GENERIC_READ; + SpecificMask = STANDARD_RIGHTS_READ | 0x0001; + GenericSid2 = SeExports->SeCreatorGroupSid; + GenericMask2 = GENERIC_EXECUTE; + SpecificMask2 = STANDARD_RIGHTS_EXECUTE | 0x0004; + } + else + { + GenericSid = SeExports->SeWorldSid; + SpecificSid = SeExports->SeWorldSid; + GenericMask = READ_CONTROL; + SpecificMask = READ_CONTROL; + GenericSid2 = SeExports->SeLocalSystemSid; + GenericMask2 = SYNCHRONIZE; + SpecificMask2 = SYNCHRONIZE; + } + for (CanInherit = 0; CanInherit <= 255; CanInherit++) + { + for (UsingDefault = 0; UsingDefault <= 3; UsingDefault++) + { + Status = RtlCreateAcl(Acl, AclSize, ACL_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + AceFlags = CanInherit & 0xf; + Status = RtlAddAccessAllowedAceEx(Acl, ACL_REVISION, AceFlags, GenericMask, GenericSid); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlCreateAcl(Acl2, AclSize, ACL_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + AceFlags2 = CanInherit >> 4; + Status = RtlAddAccessAllowedAceEx(Acl2, ACL_REVISION, AceFlags2, GenericMask2, GenericSid2); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ParentDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 1)); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + Acl2, + BooleanFlagOn(UsingDefault, 2)); + ok_eq_hex(Status, STATUS_SUCCESS); + StartTestAssignLoop(&ParentDescriptor, &ExplicitDescriptor) + //trace("Explicit %u, Parent %u, Dir %u, Default %u, Inherit %u, Access %u\n", UsingExplicit, UsingParent, IsDir, UsingDefault, CanInherit, Access); + ok_eq_uint(DaclDefaulted, FALSE); + ParentUsable = UsingParent; + if (!IsDir && !FlagOn(AceFlags, OBJECT_INHERIT_ACE)) + ParentUsable = FALSE; + else if (IsDir && !FlagOn(AceFlags, CONTAINER_INHERIT_ACE) && + (!FlagOn(AceFlags, OBJECT_INHERIT_ACE) || FlagOn(AceFlags, NO_PROPAGATE_INHERIT_ACE))) + ParentUsable = FALSE; + + if (UsingExplicit && (!FlagOn(UsingDefault, 2) || !ParentUsable)) + { + CheckAcl(Dacl, 1, ACCESS_ALLOWED_ACE_TYPE, AceFlags2, GenericSid2, FlagOn(AceFlags2, INHERIT_ONLY_ACE) ? GenericMask2 : SpecificMask2); + } + else if (ParentUsable) + { + if (IsDir && !FlagOn(AceFlags, NO_PROPAGATE_INHERIT_ACE)) + { + if (FlagOn(AceFlags, CONTAINER_INHERIT_ACE) && (SpecificMask != GenericMask || SpecificSid != GenericSid)) + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SpecificSid, SpecificMask, + ACCESS_ALLOWED_ACE_TYPE, INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | (AceFlags & OBJECT_INHERIT_ACE), GenericSid, GenericMask); + else + CheckAcl(Dacl, 1, ACCESS_ALLOWED_ACE_TYPE, (FlagOn(AceFlags, CONTAINER_INHERIT_ACE) ? 0 : INHERIT_ONLY_ACE) | + (AceFlags & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE)), GenericSid, GenericMask); + } + else + CheckAcl(Dacl, 1, ACCESS_ALLOWED_ACE_TYPE, 0, SpecificSid, SpecificMask); + } + else + { + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + } + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, SeExports->SeAliasAdminsSid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, SeExports->SeLocalSystemSid); + EndTestAssignLoop() + } + } + } + + /* NULL parameters */ + ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + KmtStartSeh() + Status = SeAssignSecurity(NULL, + NULL, + NULL, + FALSE, + SubjectContext, + &GenericMapping, + PagedPool); + KmtEndSeh(STATUS_ACCESS_VIOLATION); + ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + + SecurityDescriptor = KmtInvalidPointer; + KmtStartSeh() + Status = SeAssignSecurity(NULL, + NULL, + &SecurityDescriptor, + FALSE, + NULL, + &GenericMapping, + PagedPool); + ok_eq_hex(Status, STATUS_NO_TOKEN); + KmtEndSeh(STATUS_SUCCESS); + ok_eq_pointer(SecurityDescriptor, NULL); + ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + + ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + KmtStartSeh() + Status = SeAssignSecurity(NULL, + NULL, + NULL, + FALSE, + NULL, + &GenericMapping, + PagedPool); + KmtEndSeh(STATUS_ACCESS_VIOLATION); + ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + + /* Test with Token == NULL */ + if (1) + { + /* Crash in SeLockSubjectContext while holding a critical region */ + SubjectContext->PrimaryToken = NULL; + KmtStartSeh() + SecurityDescriptor = KmtInvalidPointer; + Status = SeAssignSecurity(NULL, + NULL, + &SecurityDescriptor, + FALSE, + SubjectContext, + &GenericMapping, + PagedPool); + KmtEndSeh(STATUS_ACCESS_VIOLATION) + ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + KeLeaveCriticalRegion(); + ok_eq_pointer(SecurityDescriptor, KmtInvalidPointer); + SubjectContext->PrimaryToken = Token; + } + ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + + /* Test with NULL owner in Token */ + if (1) + { + /* Crash after locking the subject context */ + PSID OldOwner; + OldOwner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid; + Token->UserAndGroups[Token->DefaultOwnerIndex].Sid = NULL; + KmtStartSeh() + SecurityDescriptor = KmtInvalidPointer; + Status = SeAssignSecurity(NULL, + NULL, + &SecurityDescriptor, + FALSE, + SubjectContext, + &GenericMapping, + PagedPool); + KmtEndSeh(STATUS_ACCESS_VIOLATION) + ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + SeUnlockSubjectContext(SubjectContext); + ok_eq_pointer(SecurityDescriptor, KmtInvalidPointer); + Token->UserAndGroups[Token->DefaultOwnerIndex].Sid = OldOwner; + } + ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + + /* Test with NULL group in Token */ + if (1) + { + PSID OldGroup; + OldGroup = Token->PrimaryGroup; + Token->PrimaryGroup = NULL; + KmtStartSeh() + SecurityDescriptor = KmtInvalidPointer; + Status = SeAssignSecurity(NULL, + NULL, + &SecurityDescriptor, + FALSE, + SubjectContext, + &GenericMapping, + PagedPool); + ok_eq_hex(Status, STATUS_INVALID_PRIMARY_GROUP); + ok_eq_pointer(SecurityDescriptor, NULL); + SeDeassignSecurity(&SecurityDescriptor); + KmtEndSeh(STATUS_SUCCESS); + Token->PrimaryGroup = OldGroup; + } + ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + + /* Test with NULL DACL in Token */ + if (1) + { + PACL OldDacl; + OldDacl = Token->DefaultDacl; + Token->DefaultDacl = NULL; + KmtStartSeh() + StartTestAssign(NULL, NULL, FALSE, FALSE, FALSE) + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, Token->PrimaryGroup); + EndTestAssign() + KmtEndSeh(STATUS_SUCCESS); + Token->DefaultDacl = OldDacl; + } + ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + + /* SEF_DEFAULT_OWNER_FROM_PARENT/SEF_DEFAULT_GROUP_FROM_PARENT */ + SecurityDescriptor = KmtInvalidPointer; + Status = SeAssignSecurityEx(NULL, + NULL, + &SecurityDescriptor, + NULL, + FALSE, + SEF_DEFAULT_OWNER_FROM_PARENT, + SubjectContext, + &GenericMapping, + PagedPool); + ok_eq_hex(Status, STATUS_INVALID_OWNER); + ok_eq_pointer(SecurityDescriptor, NULL); + SeDeassignSecurity(&SecurityDescriptor); + SecurityDescriptor = KmtInvalidPointer; + Status = SeAssignSecurityEx(NULL, + NULL, + &SecurityDescriptor, + NULL, + FALSE, + SEF_DEFAULT_GROUP_FROM_PARENT, + SubjectContext, + &GenericMapping, + PagedPool); + ok_eq_hex(Status, STATUS_INVALID_PRIMARY_GROUP); + ok_eq_pointer(SecurityDescriptor, NULL); + SeDeassignSecurity(&SecurityDescriptor); + SecurityDescriptor = KmtInvalidPointer; + Status = SeAssignSecurityEx(NULL, + NULL, + &SecurityDescriptor, + NULL, + FALSE, + SEF_DEFAULT_OWNER_FROM_PARENT | SEF_DEFAULT_GROUP_FROM_PARENT, + SubjectContext, + &GenericMapping, + PagedPool); + ok_eq_hex(Status, STATUS_INVALID_OWNER); + ok_eq_pointer(SecurityDescriptor, NULL); + SeDeassignSecurity(&SecurityDescriptor); + + /* Quick test whether inheritance for SACLs behaves the same as DACLs */ + Status = RtlSetDaclSecurityDescriptor(&ParentDescriptor, + FALSE, + NULL, + FALSE); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetDaclSecurityDescriptor(&ExplicitDescriptor, + FALSE, + NULL, + FALSE); + ok_eq_hex(Status, STATUS_SUCCESS); + for (UsingDefault = 0; UsingDefault <= 3; UsingDefault++) + { + Status = RtlSetSaclSecurityDescriptor(&ParentDescriptor, + TRUE, + NULL, + BooleanFlagOn(UsingDefault, 1)); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetSaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + NULL, + BooleanFlagOn(UsingDefault, 2)); + ok_eq_hex(Status, STATUS_SUCCESS); + + TestAssignExpectDefault(&ParentDescriptor, NULL, FALSE) + TestAssignExpectDefault(&ParentDescriptor, NULL, TRUE) + StartTestAssign(NULL, &ExplicitDescriptor, FALSE, TRUE, TRUE) + ok_eq_uint(DaclDefaulted, FALSE); + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + ok_eq_uint(SaclDefaulted, FALSE); + ok_eq_pointer(Sacl, NULL); + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, Token->PrimaryGroup); + EndTestAssign() + } + + for (UsingDefault = 0; UsingDefault <= 3; UsingDefault++) + { + Status = RtlSetSaclSecurityDescriptor(&ParentDescriptor, + TRUE, + &EmptyAcl, + BooleanFlagOn(UsingDefault, 1)); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetSaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + &EmptyAcl, + BooleanFlagOn(UsingDefault, 2)); + ok_eq_hex(Status, STATUS_SUCCESS); + + TestAssignExpectDefault(&ParentDescriptor, NULL, FALSE) + TestAssignExpectDefault(&ParentDescriptor, NULL, TRUE) + StartTestAssign(NULL, &ExplicitDescriptor, FALSE, TRUE, TRUE) + ok_eq_uint(DaclDefaulted, FALSE); + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + ok_eq_uint(SaclDefaulted, FALSE); + CheckAcl(Sacl, 0); + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, Token->PrimaryGroup); + EndTestAssign() + } + + for (UsingDefault = 0; UsingDefault <= 3; UsingDefault++) + { + Status = RtlCreateAcl(Acl, AclSize, ACL_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlxAddAuditAccessAceEx(Acl, ACL_REVISION, 0, READ_CONTROL, SeExports->SeWorldSid, TRUE, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetSaclSecurityDescriptor(&ParentDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 1)); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetSaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 2)); + ok_eq_hex(Status, STATUS_SUCCESS); + + TestAssignExpectDefault(&ParentDescriptor, NULL, FALSE) + TestAssignExpectDefault(&ParentDescriptor, NULL, TRUE) + StartTestAssign(NULL, &ExplicitDescriptor, FALSE, TRUE, TRUE) + ok_eq_uint(DaclDefaulted, FALSE); + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + ok_eq_uint(SaclDefaulted, FALSE); + CheckAcl(Sacl, 1, SYSTEM_AUDIT_ACE_TYPE, SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG, SeExports->SeWorldSid, READ_CONTROL); + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, Token->PrimaryGroup); + EndTestAssign() + } + + for (UsingDefault = 0; UsingDefault <= 3; UsingDefault++) + { + Status = RtlCreateAcl(Acl, AclSize, ACL_REVISION); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlxAddAuditAccessAceEx(Acl, ACL_REVISION, OBJECT_INHERIT_ACE, READ_CONTROL, SeExports->SeCreatorOwnerSid, TRUE, TRUE); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetSaclSecurityDescriptor(&ParentDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 1)); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = RtlSetSaclSecurityDescriptor(&ExplicitDescriptor, + TRUE, + Acl, + BooleanFlagOn(UsingDefault, 2)); + ok_eq_hex(Status, STATUS_SUCCESS); + + StartTestAssign(&ParentDescriptor, NULL, FALSE, TRUE, TRUE) + ok_eq_uint(DaclDefaulted, FALSE); + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + ok_eq_uint(SaclDefaulted, FALSE); + CheckAcl(Sacl, 1, SYSTEM_AUDIT_ACE_TYPE, SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG, Token->UserAndGroups[Token->DefaultOwnerIndex].Sid, READ_CONTROL); + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, Token->PrimaryGroup); + EndTestAssign() + StartTestAssign(NULL, &ExplicitDescriptor, FALSE, TRUE, TRUE) + ok_eq_uint(DaclDefaulted, FALSE); + CheckAcl(Dacl, 2, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, STANDARD_RIGHTS_ALL | 0x800F, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, STANDARD_RIGHTS_READ | 0x0005); + ok_eq_uint(SaclDefaulted, FALSE); + CheckAcl(Sacl, 1, SYSTEM_AUDIT_ACE_TYPE, OBJECT_INHERIT_ACE | SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG, SeExports->SeCreatorOwnerSid, READ_CONTROL); + ok_eq_uint(OwnerDefaulted, FALSE); + CheckSid(Owner, NO_SIZE, Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); + ok_eq_uint(GroupDefaulted, FALSE); + CheckSid(Group, NO_SIZE, Token->PrimaryGroup); + EndTestAssign() + } + + /* TODO: Test duplicate ACEs */ + /* TODO: Test INHERITED_ACE flag */ + /* TODO: Test invalid ACE flags */ + /* TODO: Test more AutoInheritFlags values */ + + ExFreePoolWithTag(Acl2, 'ASmK'); + ExFreePoolWithTag(Acl, 'ASmK'); +} + +static +VOID +NTAPI +SystemThread( + _In_ PVOID Context) +{ + SECURITY_SUBJECT_CONTEXT SubjectContext; + ok_eq_pointer(Context, NULL); + + SeCaptureSubjectContext(&SubjectContext); + TestSeAssignSecurity(&SubjectContext); + /* TODO: Test SeSetSecurityDescrptorInfo[Ex] */ + SeReleaseSubjectContext(&SubjectContext); +} + +static +VOID +TestObRootSecurity(VOID) +{ + NTSTATUS Status; + UNICODE_STRING ObjectPath = RTL_CONSTANT_STRING(L"\\"); + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE Handle; + PVOID RootDirectory; + PSECURITY_DESCRIPTOR SecurityDescriptor; + BOOLEAN MemoryAllocated; + PACL Acl; + BOOLEAN Present; + BOOLEAN Defaulted; + + InitializeObjectAttributes(&ObjectAttributes, + &ObjectPath, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenDirectoryObject(&Handle, + 0, + &ObjectAttributes); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No handle\n")) + return; + Status = ObReferenceObjectByHandle(Handle, + 0, + NULL, + KernelMode, + &RootDirectory, + NULL); + ObCloseHandle(Handle, KernelMode); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No object\n")) + return; + Status = ObGetObjectSecurity(RootDirectory, + &SecurityDescriptor, + &MemoryAllocated); + ObDereferenceObject(RootDirectory); + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No security\n")) + return; + Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, + &Present, + &Acl, + &Defaulted); + ok_eq_hex(Status, STATUS_SUCCESS); + ok_eq_uint(Present, TRUE); + if (!skip(NT_SUCCESS(Status) && Present, "No DACL\n")) + { + ok_eq_uint(Defaulted, FALSE); + CheckAcl(Acl, 4, ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeWorldSid, STANDARD_RIGHTS_READ | DIRECTORY_TRAVERSE | DIRECTORY_QUERY, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeLocalSystemSid, DIRECTORY_ALL_ACCESS, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeAliasAdminsSid, DIRECTORY_ALL_ACCESS, + ACCESS_ALLOWED_ACE_TYPE, 0, SeExports->SeRestrictedSid, STANDARD_RIGHTS_READ | DIRECTORY_TRAVERSE | DIRECTORY_QUERY); + } + Status = RtlGetSaclSecurityDescriptor(SecurityDescriptor, + &Present, + &Acl, + &Defaulted); + ok_eq_hex(Status, STATUS_SUCCESS); + ok_eq_uint(Present, FALSE); + ObReleaseObjectSecurity(SecurityDescriptor, MemoryAllocated); +} + +START_TEST(SeInheritance) +{ + PKTHREAD Thread; + + TestObRootSecurity(); + Thread = KmtStartThread(SystemThread, NULL); + KmtFinishThread(Thread, NULL); +} diff --git a/rostests/kmtests/ntos_se/se.h b/rostests/kmtests/ntos_se/se.h new file mode 100644 index 00000000000..758c4bc0266 --- /dev/null +++ b/rostests/kmtests/ntos_se/se.h @@ -0,0 +1,63 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Kernel-Mode Test Suite Se helper declarations + * PROGRAMMER: Thomas Faber + */ + +#ifndef _KMTEST_SE_H_ +#define _KMTEST_SE_H_ + +/* FIXME: belongs in ntifs.h or something */ +#define SEF_DACL_AUTO_INHERIT 1 +#define SEF_SACL_AUTO_INHERIT 2 +#define SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT 4 +#define SEF_AVOID_PRIVILEGE_CHECK 8 +#define SEF_AVOID_OWNER_CHECK 16 +#define SEF_DEFAULT_OWNER_FROM_PARENT 32 +#define SEF_DEFAULT_GROUP_FROM_PARENT 64 +#define SEF_MACL_NO_WRITE_UP 256 +#define SEF_MACL_NO_READ_UP 512 +#define SEF_MACL_NO_EXECUTE_UP 1024 +#define SEF_AI_USE_EXTRA_PARAMS 2048 +#define SEF_AVOID_OWNER_RESTRICTION 4096 +#define SEF_MACL_VALID_FLAGS (SEF_MACL_NO_WRITE_UP | SEF_MACL_NO_READ_UP | SEF_MACL_NO_EXECUTE_UP) + +NTSTATUS +RtlxAddAuditAccessAceEx( + _Inout_ PACL Acl, + _In_ ULONG Revision, + _In_ ULONG Flags, + _In_ ACCESS_MASK AccessMask, + _In_ PSID Sid, + _In_ BOOLEAN Success, + _In_ BOOLEAN Failure); + +#define NO_SIZE ((ULONG)-1) + +#define CheckSid(Sid, SidSize, ExpectedSid) CheckSid_(Sid, SidSize, ExpectedSid, __FILE__, __LINE__) +#define CheckSid_(Sid, SidSize, ExpectedSid, file, line) CheckSid__(Sid, SidSize, ExpectedSid, file ":" KMT_STRINGIZE(line)) +VOID +CheckSid__( + _In_ PSID Sid, + _In_ ULONG SidSize, + _In_ PISID ExpectedSid, + _In_ PCSTR FileAndLine); + +VOID +VCheckAcl__( + _In_ PACL Acl, + _In_ ULONG AceCount, + _In_ PCSTR FileAndLine, + _In_ va_list Arguments); + +#define CheckAcl(Acl, AceCount, ...) CheckAcl_(Acl, AceCount, __FILE__, __LINE__, ##__VA_ARGS__) +#define CheckAcl_(Acl, AceCount, file, line, ...) CheckAcl__(Acl, AceCount, file ":" KMT_STRINGIZE(line), ##__VA_ARGS__) +VOID +CheckAcl__( + _In_ PACL Acl, + _In_ ULONG AceCount, + _In_ PCSTR FileAndLine, + ...); + +#endif /* !defined _KMTEST_SE_H_ */ -- 2.17.1