Index: C:/ROS/reactos-clean/reactos/ntoskrnl/se/sd.c =================================================================== --- ntoskrnl/se/sd.c (revision 65197) +++ ntoskrnl/se/sd.c (working copy) @@ -1151,7 +1151,264 @@ return STATUS_SUCCESS; } +BOOLEAN +SepUseAce( + _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 = 0; + return TRUE; + } + return FALSE; + } + + if (AceFlags & NO_PROPAGATE_INHERIT_ACE) + { + if (AceFlags & CONTAINER_INHERIT_ACE) + { + *NewAceFlags = 0; + return TRUE; + } + return FALSE; + } + + if (AceFlags & CONTAINER_INHERIT_ACE) + { + *NewAceFlags = CONTAINER_INHERIT_ACE | (AceFlags & OBJECT_INHERIT_ACE); + return TRUE; + } + + if (AceFlags & OBJECT_INHERIT_ACE) + { + *NewAceFlags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; + 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 (!SepUseAce(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 AceFlags = 0 + * - 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 ? 0 : 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 IsInherited, + _In_ BOOLEAN IsDirectoryObject, + _In_ PGENERIC_MAPPING GenericMapping) +{ + PACL Acl; + NTSTATUS Status; + + 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); + if (*AclLength != sizeof(ACL)) + return ParentAcl; + } + + if (ExplicitPresent) + Acl = ExplicitAcl; + else + Acl = DefaultAcl; + } + + *IsInherited = FALSE; + *AclLength = 0; + if (Acl) + { + Status = SepPropagateAcl(NULL, + AclLength, + Acl, + Owner, + Group, + *IsInherited, + IsDirectoryObject, + GenericMapping); + NT_ASSERT(Status == STATUS_BUFFER_TOO_SMALL); + } + return Acl; +} + /* * @implemented */ @@ -1178,16 +1435,21 @@ ULONG DaclLength = 0; ULONG SaclLength = 0; ULONG Length = 0; - ULONG Control = 0; + SECURITY_DESCRIPTOR_CONTROL Control = 0; ULONG Current; PSID Owner = NULL; PSID Group = NULL; + PACL ExplicitAcl; + BOOLEAN ExplicitPresent; + BOOLEAN ExplicitDefaulted; + PACL ParentAcl; PACL Dacl = NULL; PACL Sacl = NULL; + BOOLEAN IsInherited; + NTSTATUS Status; DBG_UNREFERENCED_PARAMETER(ObjectType); DBG_UNREFERENCED_PARAMETER(AutoInheritFlags); - DBG_UNREFERENCED_PARAMETER(GenericMapping); UNREFERENCED_PARAMETER(PoolType); PAGED_CODE(); @@ -1222,9 +1484,8 @@ { DPRINT("Use default owner sid!\n"); Owner = SeLocalSystemSid; + Control |= SE_OWNER_DEFAULTED; } - - Control |= SE_OWNER_DEFAULTED; } OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4); @@ -1246,46 +1507,44 @@ { DPRINT("Use default group sid!\n"); Group = SeLocalSystemSid; + Control |= SE_GROUP_DEFAULTED; } - - Control |= SE_GROUP_DEFAULTED; } GroupLength = ROUND_UP(RtlLengthSid(Group), 4); - /* Inherit the DACL */ + DaclLength = 0; + + ExplicitAcl = NULL; + ExplicitPresent = FALSE; + ExplicitDefaulted = FALSE; if (ExplicitDescriptor != NULL && - (ExplicitDescriptor->Control & SE_DACL_PRESENT) && - !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED)) + (ExplicitDescriptor->Control & SE_DACL_PRESENT)) { - DPRINT("Use explicit DACL!\n"); - Dacl = SepGetDaclFromDescriptor(ExplicitDescriptor); - Control |= SE_DACL_PRESENT; + ExplicitAcl = SepGetDaclFromDescriptor(ExplicitDescriptor); + ExplicitPresent = TRUE; + if (ExplicitDescriptor->Control & SE_DACL_DEFAULTED) + ExplicitDefaulted = TRUE; } - else if (ParentDescriptor != NULL && - (ParentDescriptor->Control & SE_DACL_PRESENT)) + ParentAcl = NULL; + if (ParentDescriptor != NULL && + (ParentDescriptor->Control & SE_DACL_PRESENT)) { - DPRINT("Use parent DACL!\n"); - /* FIXME: Inherit */ - Dacl = SepGetDaclFromDescriptor(ParentDescriptor); - Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED); + ParentAcl = SepGetDaclFromDescriptor(ParentDescriptor); } - else if (Token != NULL && Token->DefaultDacl != NULL) - { - DPRINT("Use token default DACL!\n"); - /* FIXME: Inherit */ - Dacl = Token->DefaultDacl; - Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED); - } - else - { - DPRINT("Use NULL DACL!\n"); - Dacl = NULL; - Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED); - } + Dacl = SepSelectAcl(ExplicitAcl, + ExplicitPresent, + ExplicitDefaulted, + ParentAcl, + Token ? Token->DefaultDacl : NULL, + &DaclLength, + Owner, + Group, + &IsInherited, + IsDirectoryObject, + GenericMapping); + Control |= SE_DACL_PRESENT; - DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0; - /* Inherit the SACL */ if (ExplicitDescriptor != NULL && (ExplicitDescriptor->Control & SE_SACL_PRESENT) && @@ -1328,7 +1587,7 @@ RtlZeroMemory(Descriptor, Length); RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION); - Descriptor->Control = (USHORT)Control | SE_SELF_RELATIVE; + Descriptor->Control = Control | SE_SELF_RELATIVE; Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE); @@ -1341,7 +1600,15 @@ if (DaclLength != 0) { - RtlCopyMemory((PUCHAR)Descriptor + Current, Dacl, DaclLength); + Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current), + &DaclLength, + Dacl, + Owner, + Group, + IsInherited, + IsDirectoryObject, + GenericMapping); + NT_ASSERT(Status == STATUS_SUCCESS); Descriptor->Dacl = Current; Current += DaclLength; }