--- /dev/null
+/*
+ * 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 <thomas.faber@reactos.org>
+ */
+
+#include <kmt_test.h>
+#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);
+}
--- /dev/null
+/*
+ * 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 <thomas.faber@reactos.org>
+ */
+
+#include <kmt_test.h>
+#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);
+}