mirror of
https://github.com/reactos/reactos.git
synced 2024-06-26 07:51:52 +00:00
[NTOS:SE]
- Implement ACL inheritance for SeAssignSecurityEx CORE-8745 #resolve svn path=/trunk/; revision=65259
This commit is contained in:
parent
418629f6a9
commit
ca809b6cdc
|
@ -488,6 +488,32 @@ SepReleaseAcl(
|
|||
IN BOOLEAN CaptureIfKernel
|
||||
);
|
||||
|
||||
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(
|
||||
|
|
|
@ -367,4 +367,280 @@ SepReleaseAcl(IN PACL CapturedAcl,
|
|||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
|
|
|
@ -1109,7 +1109,6 @@ SeDeassignSecurity(
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -1140,12 +1139,20 @@ SeAssignSecurityEx(
|
|||
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 @@ SeAssignSecurityEx(
|
|||
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 @@ SeAssignSecurityEx(
|
|||
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))
|
||||
(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;
|
||||
ParentAcl = SepGetDaclFromDescriptor(ParentDescriptor);
|
||||
}
|
||||
else if (Token->DefaultDacl)
|
||||
{
|
||||
DPRINT("Use token default DACL!\n");
|
||||
Dacl = Token->DefaultDacl;
|
||||
Dacl = SepSelectAcl(ExplicitAcl,
|
||||
ExplicitPresent,
|
||||
ExplicitDefaulted,
|
||||
ParentAcl,
|
||||
Token->DefaultDacl,
|
||||
&DaclLength,
|
||||
Owner,
|
||||
Group,
|
||||
&DaclPresent,
|
||||
&DaclIsInherited,
|
||||
IsDirectoryObject,
|
||||
GenericMapping);
|
||||
if (DaclPresent)
|
||||
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))
|
||||
(ExplicitDescriptor->Control & SE_SACL_PRESENT))
|
||||
{
|
||||
DPRINT("Use explicit SACL!\n");
|
||||
Sacl = SepGetSaclFromDescriptor(ExplicitDescriptor);
|
||||
Control |= SE_SACL_PRESENT;
|
||||
ExplicitAcl = SepGetSaclFromDescriptor(ExplicitDescriptor);
|
||||
ExplicitPresent = TRUE;
|
||||
if (ExplicitDescriptor->Control & SE_SACL_DEFAULTED)
|
||||
ExplicitDefaulted = TRUE;
|
||||
}
|
||||
else if (ParentDescriptor != NULL &&
|
||||
(ParentDescriptor->Control & SE_SACL_PRESENT))
|
||||
ParentAcl = NULL;
|
||||
if (ParentDescriptor != NULL &&
|
||||
(ParentDescriptor->Control & SE_SACL_PRESENT))
|
||||
{
|
||||
DPRINT("Use parent SACL!\n");
|
||||
/* FIXME: Inherit */
|
||||
Sacl = SepGetSaclFromDescriptor(ParentDescriptor);
|
||||
Control |= SE_SACL_PRESENT;
|
||||
ParentAcl = SepGetSaclFromDescriptor(ParentDescriptor);
|
||||
}
|
||||
|
||||
SaclLength = (Sacl != NULL) ? Sacl->AclSize : 0;
|
||||
Sacl = SepSelectAcl(ExplicitAcl,
|
||||
ExplicitPresent,
|
||||
ExplicitDefaulted,
|
||||
ParentAcl,
|
||||
NULL,
|
||||
&SaclLength,
|
||||
Owner,
|
||||
Group,
|
||||
&SaclPresent,
|
||||
&SaclIsInherited,
|
||||
IsDirectoryObject,
|
||||
GenericMapping);
|
||||
if (SaclPresent)
|
||||
Control |= SE_SACL_PRESENT;
|
||||
NT_ASSERT(SaclLength % sizeof(ULONG) == 0);
|
||||
|
||||
/* Allocate and initialize the new security descriptor */
|
||||
|
@ -1279,14 +1306,30 @@ SeAssignSecurityEx(
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue