Author: tfaber
Date: Tue Nov 4 22:44:50 2014
New Revision: 65259
URL:
http://svn.reactos.org/svn/reactos?rev=65259&view=rev
Log:
[NTOS:SE]
- Implement ACL inheritance for SeAssignSecurityEx
CORE-8745 #resolve
Modified:
trunk/reactos/ntoskrnl/include/internal/se.h
trunk/reactos/ntoskrnl/se/acl.c
trunk/reactos/ntoskrnl/se/sd.c
Modified: trunk/reactos/ntoskrnl/include/internal/se.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/se.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/se.h [iso-8859-1] Tue Nov 4 22:44:50 2014
@@ -489,6 +489,32 @@
);
NTSTATUS
+SepPropagateAcl(
+ _Out_writes_bytes_opt_(DaclLength) PACL AclDest,
+ _Inout_ PULONG AclLength,
+ _In_reads_bytes_(AclSource->AclSize) PACL AclSource,
+ _In_ PSID Owner,
+ _In_ PSID Group,
+ _In_ BOOLEAN IsInherited,
+ _In_ BOOLEAN IsDirectoryObject,
+ _In_ PGENERIC_MAPPING GenericMapping);
+
+PACL
+SepSelectAcl(
+ _In_opt_ PACL ExplicitAcl,
+ _In_ BOOLEAN ExplicitPresent,
+ _In_ BOOLEAN ExplicitDefaulted,
+ _In_opt_ PACL ParentAcl,
+ _In_opt_ PACL DefaultAcl,
+ _Out_ PULONG AclLength,
+ _In_ PSID Owner,
+ _In_ PSID Group,
+ _Out_ PBOOLEAN AclPresent,
+ _Out_ PBOOLEAN IsInherited,
+ _In_ BOOLEAN IsDirectoryObject,
+ _In_ PGENERIC_MAPPING GenericMapping);
+
+NTSTATUS
NTAPI
SeDefaultObjectMethod(
PVOID Object,
Modified: trunk/reactos/ntoskrnl/se/acl.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/acl.c?rev=6525…
==============================================================================
--- trunk/reactos/ntoskrnl/se/acl.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/se/acl.c [iso-8859-1] Tue Nov 4 22:44:50 2014
@@ -367,4 +367,280 @@
}
}
+BOOLEAN
+SepShouldPropagateAce(
+ _In_ UCHAR AceFlags,
+ _Out_ PUCHAR NewAceFlags,
+ _In_ BOOLEAN IsInherited,
+ _In_ BOOLEAN IsDirectoryObject)
+{
+ if (!IsInherited)
+ {
+ *NewAceFlags = AceFlags;
+ return TRUE;
+ }
+
+ if (!IsDirectoryObject)
+ {
+ if (AceFlags & OBJECT_INHERIT_ACE)
+ {
+ *NewAceFlags = AceFlags & ~VALID_INHERIT_FLAGS;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ if (AceFlags & NO_PROPAGATE_INHERIT_ACE)
+ {
+ if (AceFlags & CONTAINER_INHERIT_ACE)
+ {
+ *NewAceFlags = AceFlags & ~VALID_INHERIT_FLAGS;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ if (AceFlags & CONTAINER_INHERIT_ACE)
+ {
+ *NewAceFlags = CONTAINER_INHERIT_ACE | (AceFlags & OBJECT_INHERIT_ACE) |
(AceFlags & ~VALID_INHERIT_FLAGS);
+ return TRUE;
+ }
+
+ if (AceFlags & OBJECT_INHERIT_ACE)
+ {
+ *NewAceFlags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | (AceFlags &
~VALID_INHERIT_FLAGS);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+NTSTATUS
+SepPropagateAcl(
+ _Out_writes_bytes_opt_(DaclLength) PACL AclDest,
+ _Inout_ PULONG AclLength,
+ _In_reads_bytes_(AclSource->AclSize) PACL AclSource,
+ _In_ PSID Owner,
+ _In_ PSID Group,
+ _In_ BOOLEAN IsInherited,
+ _In_ BOOLEAN IsDirectoryObject,
+ _In_ PGENERIC_MAPPING GenericMapping)
+{
+ ACCESS_MASK Mask;
+ PACCESS_ALLOWED_ACE AceSource;
+ PACCESS_ALLOWED_ACE AceDest;
+ PUCHAR CurrentDest;
+ PUCHAR CurrentSource;
+ ULONG i;
+ ULONG Written;
+ UCHAR AceFlags;
+ USHORT AceSize;
+ USHORT AceCount = 0;
+ PSID Sid;
+ BOOLEAN WriteTwoAces;
+
+ if (AclSource->AclRevision != ACL_REVISION)
+ {
+ NT_ASSERT(AclSource->AclRevision == ACL_REVISION);
+ return STATUS_UNKNOWN_REVISION;
+ }
+
+ NT_ASSERT(AclSource->AclSize % sizeof(ULONG) == 0);
+ NT_ASSERT(AclSource->Sbz1 == 0);
+ NT_ASSERT(AclSource->Sbz2 == 0);
+
+ Written = 0;
+ if (*AclLength >= Written + sizeof(ACL))
+ {
+ RtlCopyMemory(AclDest,
+ AclSource,
+ sizeof(ACL));
+ }
+ Written += sizeof(ACL);
+
+ CurrentDest = (PUCHAR)(AclDest + 1);
+ CurrentSource = (PUCHAR)(AclSource + 1);
+ for (i = 0; i < AclSource->AceCount; i++)
+ {
+ NT_ASSERT((ULONG_PTR)CurrentDest % sizeof(ULONG) == 0);
+ NT_ASSERT((ULONG_PTR)CurrentSource % sizeof(ULONG) == 0);
+ AceDest = (PACCESS_ALLOWED_ACE)CurrentDest;
+ AceSource = (PACCESS_ALLOWED_ACE)CurrentSource;
+
+ /* These all have the same structure */
+ NT_ASSERT(AceSource->Header.AceType == ACCESS_ALLOWED_ACE_TYPE ||
+ AceSource->Header.AceType == ACCESS_DENIED_ACE_TYPE ||
+ AceSource->Header.AceType == SYSTEM_AUDIT_ACE_TYPE);
+
+ NT_ASSERT(AceSource->Header.AceSize % sizeof(ULONG) == 0);
+ NT_ASSERT(AceSource->Header.AceSize >= sizeof(*AceSource));
+ if (!SepShouldPropagateAce(AceSource->Header.AceFlags,
+ &AceFlags,
+ IsInherited,
+ IsDirectoryObject))
+ {
+ CurrentSource += AceSource->Header.AceSize;
+ continue;
+ }
+
+ /* FIXME: filter out duplicate ACEs */
+ AceSize = AceSource->Header.AceSize;
+ Mask = AceSource->Mask;
+ Sid = (PSID)&AceSource->SidStart;
+ NT_ASSERT(AceSize >= FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
RtlLengthSid(Sid));
+
+ WriteTwoAces = FALSE;
+ /* Map effective ACE to specific rights */
+ if (!(AceFlags & INHERIT_ONLY_ACE))
+ {
+ RtlMapGenericMask(&Mask, GenericMapping);
+ Mask &= GenericMapping->GenericAll;
+
+ if (IsInherited)
+ {
+ if (RtlEqualSid(Sid, SeCreatorOwnerSid))
+ Sid = Owner;
+ else if (RtlEqualSid(Sid, SeCreatorGroupSid))
+ Sid = Group;
+ AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
RtlLengthSid(Sid);
+
+ /*
+ * A generic container ACE becomes two ACEs:
+ * - a specific effective ACE with no inheritance flags
+ * - an inherit-only ACE that keeps the generic rights
+ */
+ if (IsDirectoryObject &&
+ (AceFlags & CONTAINER_INHERIT_ACE) &&
+ (Mask != AceSource->Mask || Sid !=
(PSID)&AceSource->SidStart))
+ {
+ WriteTwoAces = TRUE;
+ }
+ }
+ }
+
+ while (1)
+ {
+ if (*AclLength >= Written + AceSize)
+ {
+ AceDest->Header.AceType = AceSource->Header.AceType;
+ AceDest->Header.AceFlags = WriteTwoAces ? AceFlags &
~VALID_INHERIT_FLAGS
+ : AceFlags;
+ AceDest->Header.AceSize = AceSize;
+ AceDest->Mask = Mask;
+ RtlCopySid(AceSize - FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart),
+ (PSID)&AceDest->SidStart,
+ Sid);
+ }
+ Written += AceSize;
+
+ AceCount++;
+ CurrentDest += AceSize;
+
+ if (!WriteTwoAces)
+ break;
+
+ /* Second ACE keeps all the generics from the source ACE */
+ WriteTwoAces = FALSE;
+ AceDest = (PACCESS_ALLOWED_ACE)CurrentDest;
+ AceSize = AceSource->Header.AceSize;
+ Mask = AceSource->Mask;
+ Sid = (PSID)&AceSource->SidStart;
+ AceFlags |= INHERIT_ONLY_ACE;
+ }
+
+ CurrentSource += AceSource->Header.AceSize;
+ }
+
+ if (*AclLength >= sizeof(ACL))
+ {
+ AclDest->AceCount = AceCount;
+ AclDest->AclSize = Written;
+ }
+
+ if (Written > *AclLength)
+ {
+ *AclLength = Written;
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ *AclLength = Written;
+ return STATUS_SUCCESS;
+}
+
+PACL
+SepSelectAcl(
+ _In_opt_ PACL ExplicitAcl,
+ _In_ BOOLEAN ExplicitPresent,
+ _In_ BOOLEAN ExplicitDefaulted,
+ _In_opt_ PACL ParentAcl,
+ _In_opt_ PACL DefaultAcl,
+ _Out_ PULONG AclLength,
+ _In_ PSID Owner,
+ _In_ PSID Group,
+ _Out_ PBOOLEAN AclPresent,
+ _Out_ PBOOLEAN IsInherited,
+ _In_ BOOLEAN IsDirectoryObject,
+ _In_ PGENERIC_MAPPING GenericMapping)
+{
+ PACL Acl;
+ NTSTATUS Status;
+
+ *AclPresent = TRUE;
+ if (ExplicitPresent && !ExplicitDefaulted)
+ {
+ Acl = ExplicitAcl;
+ }
+ else
+ {
+ if (ParentAcl)
+ {
+ *IsInherited = TRUE;
+ *AclLength = 0;
+ Status = SepPropagateAcl(NULL,
+ AclLength,
+ ParentAcl,
+ Owner,
+ Group,
+ *IsInherited,
+ IsDirectoryObject,
+ GenericMapping);
+ NT_ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
+
+ /* Use the parent ACL only if it's not empty */
+ if (*AclLength != sizeof(ACL))
+ return ParentAcl;
+ }
+
+ if (ExplicitPresent)
+ {
+ Acl = ExplicitAcl;
+ }
+ else if (DefaultAcl)
+ {
+ Acl = DefaultAcl;
+ }
+ else
+ {
+ *AclPresent = FALSE;
+ Acl = NULL;
+ }
+ }
+
+ *IsInherited = FALSE;
+ *AclLength = 0;
+ if (Acl)
+ {
+ /* Get the length */
+ Status = SepPropagateAcl(NULL,
+ AclLength,
+ Acl,
+ Owner,
+ Group,
+ *IsInherited,
+ IsDirectoryObject,
+ GenericMapping);
+ NT_ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
+ }
+ return Acl;
+}
+
/* EOF */
Modified: trunk/reactos/ntoskrnl/se/sd.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/sd.c?rev=65259…
==============================================================================
--- trunk/reactos/ntoskrnl/se/sd.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/se/sd.c [iso-8859-1] Tue Nov 4 22:44:50 2014
@@ -1109,7 +1109,6 @@
return STATUS_SUCCESS;
}
-
/*
* @implemented
*/
@@ -1140,12 +1139,20 @@
ULONG Current;
PSID Owner = NULL;
PSID Group = NULL;
+ PACL ExplicitAcl;
+ BOOLEAN ExplicitPresent;
+ BOOLEAN ExplicitDefaulted;
+ PACL ParentAcl;
PACL Dacl = NULL;
PACL Sacl = NULL;
+ BOOLEAN DaclIsInherited;
+ BOOLEAN SaclIsInherited;
+ BOOLEAN DaclPresent;
+ BOOLEAN SaclPresent;
+ NTSTATUS Status;
DBG_UNREFERENCED_PARAMETER(ObjectType);
DBG_UNREFERENCED_PARAMETER(AutoInheritFlags);
- DBG_UNREFERENCED_PARAMETER(GenericMapping);
UNREFERENCED_PARAMETER(PoolType);
PAGED_CODE();
@@ -1180,7 +1187,6 @@
DPRINT("Use token owner sid!\n");
Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
}
-
OwnerLength = RtlLengthSid(Owner);
NT_ASSERT(OwnerLength % sizeof(ULONG) == 0);
@@ -1199,56 +1205,77 @@
SeUnlockSubjectContext(SubjectContext);
return STATUS_INVALID_PRIMARY_GROUP;
}
-
GroupLength = RtlLengthSid(Group);
NT_ASSERT(GroupLength % sizeof(ULONG) == 0);
/* Inherit the DACL */
+ DaclLength = 0;
+ ExplicitAcl = NULL;
+ ExplicitPresent = FALSE;
+ ExplicitDefaulted = FALSE;
if (ExplicitDescriptor != NULL &&
- (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
- !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
- {
- DPRINT("Use explicit DACL!\n");
- Dacl = SepGetDaclFromDescriptor(ExplicitDescriptor);
+ (ExplicitDescriptor->Control & SE_DACL_PRESENT))
+ {
+ ExplicitAcl = SepGetDaclFromDescriptor(ExplicitDescriptor);
+ ExplicitPresent = TRUE;
+ if (ExplicitDescriptor->Control & SE_DACL_DEFAULTED)
+ ExplicitDefaulted = TRUE;
+ }
+ ParentAcl = NULL;
+ if (ParentDescriptor != NULL &&
+ (ParentDescriptor->Control & SE_DACL_PRESENT))
+ {
+ ParentAcl = SepGetDaclFromDescriptor(ParentDescriptor);
+ }
+ Dacl = SepSelectAcl(ExplicitAcl,
+ ExplicitPresent,
+ ExplicitDefaulted,
+ ParentAcl,
+ Token->DefaultDacl,
+ &DaclLength,
+ Owner,
+ Group,
+ &DaclPresent,
+ &DaclIsInherited,
+ IsDirectoryObject,
+ GenericMapping);
+ if (DaclPresent)
Control |= SE_DACL_PRESENT;
- }
- else if (ParentDescriptor != NULL &&
- (ParentDescriptor->Control & SE_DACL_PRESENT))
- {
- DPRINT("Use parent DACL!\n");
- /* FIXME: Inherit */
- Dacl = SepGetDaclFromDescriptor(ParentDescriptor);
- Control |= SE_DACL_PRESENT;
- }
- else if (Token->DefaultDacl)
- {
- DPRINT("Use token default DACL!\n");
- Dacl = Token->DefaultDacl;
- Control |= SE_DACL_PRESENT;
- }
-
- DaclLength = (Dacl != NULL) ? Dacl->AclSize : 0;
NT_ASSERT(DaclLength % sizeof(ULONG) == 0);
/* Inherit the SACL */
+ SaclLength = 0;
+ ExplicitAcl = NULL;
+ ExplicitPresent = FALSE;
+ ExplicitDefaulted = FALSE;
if (ExplicitDescriptor != NULL &&
- (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
- !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
- {
- DPRINT("Use explicit SACL!\n");
- Sacl = SepGetSaclFromDescriptor(ExplicitDescriptor);
+ (ExplicitDescriptor->Control & SE_SACL_PRESENT))
+ {
+ ExplicitAcl = SepGetSaclFromDescriptor(ExplicitDescriptor);
+ ExplicitPresent = TRUE;
+ if (ExplicitDescriptor->Control & SE_SACL_DEFAULTED)
+ ExplicitDefaulted = TRUE;
+ }
+ ParentAcl = NULL;
+ if (ParentDescriptor != NULL &&
+ (ParentDescriptor->Control & SE_SACL_PRESENT))
+ {
+ ParentAcl = SepGetSaclFromDescriptor(ParentDescriptor);
+ }
+ Sacl = SepSelectAcl(ExplicitAcl,
+ ExplicitPresent,
+ ExplicitDefaulted,
+ ParentAcl,
+ NULL,
+ &SaclLength,
+ Owner,
+ Group,
+ &SaclPresent,
+ &SaclIsInherited,
+ IsDirectoryObject,
+ GenericMapping);
+ if (SaclPresent)
Control |= SE_SACL_PRESENT;
- }
- else if (ParentDescriptor != NULL &&
- (ParentDescriptor->Control & SE_SACL_PRESENT))
- {
- DPRINT("Use parent SACL!\n");
- /* FIXME: Inherit */
- Sacl = SepGetSaclFromDescriptor(ParentDescriptor);
- Control |= SE_SACL_PRESENT;
- }
-
- SaclLength = (Sacl != NULL) ? Sacl->AclSize : 0;
NT_ASSERT(SaclLength % sizeof(ULONG) == 0);
/* Allocate and initialize the new security descriptor */
@@ -1279,14 +1306,30 @@
if (SaclLength != 0)
{
- RtlCopyMemory((PUCHAR)Descriptor + Current, Sacl, SaclLength);
+ Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
+ &SaclLength,
+ Sacl,
+ Owner,
+ Group,
+ SaclIsInherited,
+ IsDirectoryObject,
+ GenericMapping);
+ NT_ASSERT(Status == STATUS_SUCCESS);
Descriptor->Sacl = Current;
Current += SaclLength;
}
if (DaclLength != 0)
{
- RtlCopyMemory((PUCHAR)Descriptor + Current, Dacl, DaclLength);
+ Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
+ &DaclLength,
+ Dacl,
+ Owner,
+ Group,
+ DaclIsInherited,
+ IsDirectoryObject,
+ GenericMapping);
+ NT_ASSERT(Status == STATUS_SUCCESS);
Descriptor->Dacl = Current;
Current += DaclLength;
}