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,130 @@ 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 & CONTAINER_INHERIT_ACE) + { + *NewAceFlags = AceFlags; + return TRUE; + } + + if (AceFlags & OBJECT_INHERIT_ACE) + { + *NewAceFlags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; + return TRUE; + } + + return FALSE; +} + +NTSTATUS +SepPropagateAcl( + _Out_writes_bytes_all_opt_(DaclLength) PACL AclDest, + _Inout_ PULONG AclLength, + _In_reads_bytes_(DaclLength) PACL AclSource, + _In_ BOOLEAN IsInherited, + _In_ BOOLEAN IsDirectoryObject, + _In_ PGENERIC_MAPPING GenericMapping) +{ + ACCESS_MASK Mask; + PACE_HEADER AceHeader; + PUCHAR CurrentDest; + PUCHAR CurrentSource; + ULONG i; + ULONG Written; + UCHAR AceFlags; + USHORT AceCount = 0; + + 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); + AceHeader = (PACE_HEADER)CurrentSource; + + NT_ASSERT(AceHeader->AceSize % sizeof(ULONG) == 0); + if (!SepUseAce(AceHeader->AceFlags, &AceFlags, IsInherited, IsDirectoryObject)) + { + CurrentSource += AceHeader->AceSize; + continue; + } + + /* FIXME: filter out duplicate ACEs */ + if (*AclLength >= Written + AceHeader->AceSize) + { + RtlCopyMemory(CurrentDest, + CurrentSource, + AceHeader->AceSize); + ((PACE_HEADER)CurrentDest)->AceFlags = AceFlags; + if (AceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE || + AceHeader->AceType == ACCESS_DENIED_ACE_TYPE) + { + Mask = ((PACCESS_ALLOWED_ACE)AceHeader)->Mask; + RtlMapGenericMask(&Mask, GenericMapping); + Mask &= GenericMapping->GenericAll; + ((PACCESS_ALLOWED_ACE)CurrentDest)->Mask = Mask; + } + } + AceCount++; + Written += AceHeader->AceSize; + CurrentSource += AceHeader->AceSize; + CurrentDest += AceHeader->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; +} + /* * @implemented */ @@ -1184,10 +1307,11 @@ PSID Group = NULL; PACL Dacl = NULL; PACL Sacl = NULL; + BOOLEAN IsInherited = FALSE; + NTSTATUS Status; DBG_UNREFERENCED_PARAMETER(ObjectType); DBG_UNREFERENCED_PARAMETER(AutoInheritFlags); - DBG_UNREFERENCED_PARAMETER(GenericMapping); UNREFERENCED_PARAMETER(PoolType); PAGED_CODE(); @@ -1222,9 +1346,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 +1369,129 @@ { DPRINT("Use default group sid!\n"); Group = SeLocalSystemSid; + Control |= SE_GROUP_DEFAULTED; } - - Control |= SE_GROUP_DEFAULTED; } GroupLength = ROUND_UP(RtlLengthSid(Group), 4); + DaclLength = 0; /* Inherit the DACL */ - if (ExplicitDescriptor != NULL && + if (!(Control & SE_DACL_PRESENT) && + ExplicitDescriptor != NULL && (ExplicitDescriptor->Control & SE_DACL_PRESENT) && !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED)) { DPRINT("Use explicit DACL!\n"); Dacl = SepGetDaclFromDescriptor(ExplicitDescriptor); + if (Dacl) + { + Status = SepPropagateAcl(NULL, + &DaclLength, + Dacl, + IsInherited, + IsDirectoryObject, + GenericMapping); + NT_ASSERT(Status == STATUS_BUFFER_TOO_SMALL); + } Control |= SE_DACL_PRESENT; } - else if (ParentDescriptor != NULL && - (ParentDescriptor->Control & SE_DACL_PRESENT)) + if (!(Control & SE_DACL_PRESENT) && + ParentDescriptor != NULL && + (ParentDescriptor->Control & SE_DACL_PRESENT) && + !(ParentDescriptor->Control & SE_DACL_DEFAULTED)) { DPRINT("Use parent DACL!\n"); - /* FIXME: Inherit */ Dacl = SepGetDaclFromDescriptor(ParentDescriptor); - Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED); + IsInherited = TRUE; + if (Dacl) + { + Status = SepPropagateAcl(NULL, + &DaclLength, + Dacl, + IsInherited, + IsDirectoryObject, + GenericMapping); + NT_ASSERT(Status == STATUS_BUFFER_TOO_SMALL); + if (DaclLength == sizeof(ACL)) + { + Dacl = NULL; + DaclLength = 0; + IsInherited = FALSE; + } + else + Control |= SE_DACL_PRESENT; + } } - else if (Token != NULL && Token->DefaultDacl != NULL) + if (!(Control & SE_DACL_PRESENT) && + ExplicitDescriptor != NULL && + (ExplicitDescriptor->Control & SE_DACL_PRESENT)) { + DPRINT("Use explicit DACL!\n"); + Dacl = SepGetDaclFromDescriptor(ExplicitDescriptor); + if (Dacl) + { + Status = SepPropagateAcl(NULL, + &DaclLength, + Dacl, + IsInherited, + IsDirectoryObject, + GenericMapping); + NT_ASSERT(Status == STATUS_BUFFER_TOO_SMALL); + } + Control |= SE_DACL_PRESENT; + } + if (!(Control & SE_DACL_PRESENT) && + ParentDescriptor != NULL && + (ParentDescriptor->Control & SE_DACL_PRESENT)) + { + DPRINT("Use parent DACL!\n"); + Dacl = SepGetDaclFromDescriptor(ParentDescriptor); + IsInherited = TRUE; + if (Dacl) + { + Status = SepPropagateAcl(NULL, + &DaclLength, + Dacl, + IsInherited, + IsDirectoryObject, + GenericMapping); + NT_ASSERT(Status == STATUS_BUFFER_TOO_SMALL); + if (DaclLength == sizeof(ACL)) + { + Dacl = NULL; + DaclLength = 0; + IsInherited = FALSE; + } + else + Control |= SE_DACL_PRESENT; + } + else + Control |= SE_DACL_PRESENT; + } + if (!(Control & SE_DACL_PRESENT) && + Token != NULL && Token->DefaultDacl != NULL) + { DPRINT("Use token default DACL!\n"); - /* FIXME: Inherit */ Dacl = Token->DefaultDacl; - Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED); + if (Dacl) + { + Status = SepPropagateAcl(NULL, + &DaclLength, + Dacl, + IsInherited, + IsDirectoryObject, + GenericMapping); + NT_ASSERT(Status == STATUS_BUFFER_TOO_SMALL); + Control |= SE_DACL_PRESENT; + } } - else + if (!(Control & SE_DACL_PRESENT)) { DPRINT("Use NULL DACL!\n"); - Dacl = NULL; - Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED); + Control |= SE_DACL_PRESENT | SE_DACL_DEFAULTED; } - DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0; - /* Inherit the SACL */ if (ExplicitDescriptor != NULL && (ExplicitDescriptor->Control & SE_SACL_PRESENT) && @@ -1341,7 +1547,13 @@ if (DaclLength != 0) { - RtlCopyMemory((PUCHAR)Descriptor + Current, Dacl, DaclLength); + Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current), + &DaclLength, + Dacl, + IsInherited, + IsDirectoryObject, + GenericMapping); + NT_ASSERT(Status == STATUS_SUCCESS); Descriptor->Dacl = Current; Current += DaclLength; }