* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* PURPOSE: Security descriptor functions
* FILE: lib/rtl/sd.c
* PROGRAMER: David Welch <welch@cwcom.net>
*/
#include <rtl.h>
#include "../../ntoskrnl/include/internal/se.h"
#define NDEBUG
#include <debug.h>
BOOLEAN
NTAPI
RtlpValidateSDOffsetAndSize(IN ULONG Offset,
IN ULONG Length,
IN ULONG MinLength,
OUT PULONG MaxLength)
{
*MaxLength = 0;
if (Offset < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) return FALSE;
if (Offset >= Length) return FALSE;
if ((Length - Offset) < MinLength) return FALSE;
if (ALIGN_DOWN(Offset, ULONG) != Offset) return FALSE;
*MaxLength = Length - Offset;
return TRUE;
}
VOID
NTAPI
RtlpQuerySecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
OUT PSID *Owner,
OUT PULONG OwnerSize,
OUT PSID *PrimaryGroup,
OUT PULONG PrimaryGroupSize,
OUT PACL *Dacl,
OUT PULONG DaclSize,
OUT PACL *Sacl,
OUT PULONG SaclSize)
{
PAGED_CODE_RTL();
*Owner = SepGetOwnerFromDescriptor(SecurityDescriptor);
if (*Owner)
{
*OwnerSize = ROUND_UP(RtlLengthSid(*Owner), sizeof(ULONG));
}
else
{
*OwnerSize = 0;
}
*PrimaryGroup = SepGetGroupFromDescriptor(SecurityDescriptor);
if (*PrimaryGroup)
{
*PrimaryGroupSize = ROUND_UP(RtlLengthSid(*PrimaryGroup), sizeof(ULONG));
}
else
{
*PrimaryGroupSize = 0;
}
*Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
if (*Dacl)
{
*DaclSize = ROUND_UP((*Dacl)->AclSize, sizeof(ULONG));
}
else
{
*DaclSize = 0;
}
*Sacl = SepGetSaclFromDescriptor(SecurityDescriptor);
if (*Sacl)
{
*SaclSize = ROUND_UP((*Sacl)->AclSize, sizeof(ULONG));
}
else
{
*SaclSize = 0;
}
}
* @implemented
*/
NTSTATUS
NTAPI
RtlCreateSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN ULONG Revision)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
RtlZeroMemory(Sd, sizeof(*Sd));
Sd->Revision = SECURITY_DESCRIPTOR_REVISION;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlCreateSecurityDescriptorRelative(IN PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor,
IN ULONG Revision)
{
PAGED_CODE_RTL();
if (Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
RtlZeroMemory(SecurityDescriptor, sizeof(*SecurityDescriptor));
SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
SecurityDescriptor->Control = SE_SELF_RELATIVE;
return STATUS_SUCCESS;
}
* @implemented
*/
ULONG
NTAPI
RtlLengthSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
{
PISECURITY_DESCRIPTOR Sd;
PSID Owner, Group;
PACL Sacl, Dacl;
ULONG Length;
PAGED_CODE_RTL();
Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
if (Sd->Control & SE_SELF_RELATIVE)
{
Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
}
else
{
Length = sizeof(SECURITY_DESCRIPTOR);
}
Owner = SepGetOwnerFromDescriptor(Sd);
if (Owner) Length += ROUND_UP(RtlLengthSid(Owner), sizeof(ULONG));
Group = SepGetGroupFromDescriptor(Sd);
if (Group) Length += ROUND_UP(RtlLengthSid(Group), sizeof(ULONG));
Dacl = SepGetDaclFromDescriptor(Sd);
if (Dacl) Length += ROUND_UP(Dacl->AclSize, sizeof(ULONG));
Sacl = SepGetSaclFromDescriptor(Sd);
if (Sacl) Length += ROUND_UP(Sacl->AclSize, sizeof(ULONG));
return Length;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlGetDaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
OUT PBOOLEAN DaclPresent,
OUT PACL* Dacl,
OUT PBOOLEAN DaclDefaulted)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
*DaclPresent = (Sd->Control & SE_DACL_PRESENT) == SE_DACL_PRESENT;
if (*DaclPresent)
{
*Dacl = SepGetDaclFromDescriptor(Sd);
*DaclDefaulted = (Sd->Control & SE_DACL_DEFAULTED) == SE_DACL_DEFAULTED;
}
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
OUT PBOOLEAN SaclPresent,
OUT PACL* Sacl,
OUT PBOOLEAN SaclDefaulted)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
*SaclPresent = (Sd->Control & SE_SACL_PRESENT) == SE_SACL_PRESENT;
if (*SaclPresent)
{
*Sacl = SepGetSaclFromDescriptor(Sd);
*SaclDefaulted = (Sd->Control & SE_SACL_DEFAULTED) == SE_SACL_DEFAULTED;
}
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
OUT PSID* Owner,
OUT PBOOLEAN OwnerDefaulted)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
*Owner = SepGetOwnerFromDescriptor(Sd);
*OwnerDefaulted = (Sd->Control & SE_OWNER_DEFAULTED) == SE_OWNER_DEFAULTED;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlGetGroupSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
OUT PSID* Group,
OUT PBOOLEAN GroupDefaulted)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
*Group = SepGetGroupFromDescriptor(Sd);
*GroupDefaulted = (Sd->Control & SE_GROUP_DEFAULTED) == SE_GROUP_DEFAULTED;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlSetDaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
IN BOOLEAN DaclPresent,
IN PACL Dacl,
IN BOOLEAN DaclDefaulted)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
if (!DaclPresent)
{
Sd->Control = Sd->Control & ~SE_DACL_PRESENT;
return STATUS_SUCCESS;
}
Sd->Dacl = Dacl;
Sd->Control |= SE_DACL_PRESENT;
Sd->Control &= ~SE_DACL_DEFAULTED;
if (DaclDefaulted) Sd->Control |= SE_DACL_DEFAULTED;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
IN BOOLEAN SaclPresent,
IN PACL Sacl,
IN BOOLEAN SaclDefaulted)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
if (!SaclPresent)
{
Sd->Control = Sd->Control & ~SE_SACL_PRESENT;
return STATUS_SUCCESS;
}
Sd->Sacl = Sacl;
Sd->Control |= SE_SACL_PRESENT;
Sd->Control &= ~SE_SACL_DEFAULTED;
if (SaclDefaulted) Sd->Control |= SE_SACL_DEFAULTED;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlSetOwnerSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
IN PSID Owner,
IN BOOLEAN OwnerDefaulted)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
Sd->Owner = Owner;
Sd->Control &= ~SE_OWNER_DEFAULTED;
if (OwnerDefaulted) Sd->Control |= SE_OWNER_DEFAULTED;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
IN PSID Group,
IN BOOLEAN GroupDefaulted)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
Sd->Group = Group;
Sd->Control &= ~SE_GROUP_DEFAULTED;
if (GroupDefaulted) Sd->Control |= SE_GROUP_DEFAULTED;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlGetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
OUT PSECURITY_DESCRIPTOR_CONTROL Control,
OUT PULONG Revision)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
*Revision = Sd->Revision;
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
*Control = Sd->Control;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
if ((ControlBitsOfInterest & ~(SE_DACL_UNTRUSTED |
SE_SERVER_SECURITY |
SE_DACL_AUTO_INHERIT_REQ |
SE_SACL_AUTO_INHERIT_REQ |
SE_DACL_AUTO_INHERITED |
SE_SACL_AUTO_INHERITED |
SE_DACL_PROTECTED |
SE_SACL_PROTECTED)) ||
(ControlBitsToSet & ~ControlBitsOfInterest))
{
return STATUS_INVALID_PARAMETER;
}
Sd->Control &= ~ControlBitsOfInterest;
Sd->Control |= (ControlBitsToSet & ControlBitsOfInterest);
return STATUS_SUCCESS;
}
* @implemented
*/
BOOLEAN
NTAPI
RtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
OUT PUCHAR RMControl)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (!(Sd->Control & SE_RM_CONTROL_VALID))
{
*RMControl = 0;
return FALSE;
}
*RMControl = Sd->Sbz1;
return TRUE;
}
* @implemented
*/
VOID
NTAPI
RtlSetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN PUCHAR RMControl)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
if (!RMControl)
{
Sd->Control &= ~SE_RM_CONTROL_VALID;
Sd->Sbz1 = 0;
}
else
{
Sd->Control |= SE_RM_CONTROL_VALID;
Sd->Sbz1 = *RMControl;
}
}
* @implemented
*/
NTSTATUS
NTAPI
RtlSetAttributesSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN SECURITY_DESCRIPTOR_CONTROL Control,
OUT PULONG Revision)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PAGED_CODE_RTL();
*Revision = Sd->Revision;
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
Control &= SE_DACL_UNTRUSTED |
SE_SERVER_SECURITY |
SE_DACL_AUTO_INHERIT_REQ |
SE_SACL_AUTO_INHERIT_REQ |
SE_DACL_AUTO_INHERITED |
SE_SACL_AUTO_INHERITED |
SE_DACL_PROTECTED |
SE_SACL_PROTECTED;
return RtlSetControlSecurityDescriptor(SecurityDescriptor, Control, Control);
}
* @implemented
*/
NTSTATUS
NTAPI
RtlCopySecurityDescriptor(IN PSECURITY_DESCRIPTOR pSourceSecurityDescriptor,
OUT PSECURITY_DESCRIPTOR *pDestinationSecurityDescriptor)
{
PSID Owner, Group;
PACL Dacl, Sacl;
DWORD OwnerLength, GroupLength, DaclLength, SaclLength, TotalLength;
PISECURITY_DESCRIPTOR Sd = pSourceSecurityDescriptor;
RtlpQuerySecurityDescriptor(Sd,
&Owner,
&OwnerLength,
&Group,
&GroupLength,
&Dacl,
&DaclLength,
&Sacl,
&SaclLength);
TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
OwnerLength +
GroupLength +
DaclLength +
SaclLength;
*pDestinationSecurityDescriptor = RtlAllocateHeap(RtlGetProcessHeap(),
0,
TotalLength);
if (*pDestinationSecurityDescriptor == NULL) return STATUS_NO_MEMORY;
RtlCopyMemory(*pDestinationSecurityDescriptor, Sd, TotalLength);
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
IN PULONG BufferLength)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)AbsoluteSecurityDescriptor;
PAGED_CODE_RTL();
if (Sd->Control & SE_SELF_RELATIVE) return STATUS_BAD_DESCRIPTOR_FORMAT;
return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
SelfRelativeSecurityDescriptor,
BufferLength);
}
* @implemented
*/
NTSTATUS
NTAPI
RtlMakeSelfRelativeSD(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
IN OUT PULONG BufferLength)
{
PSID Owner, Group;
PACL Sacl, Dacl;
ULONG OwnerLength, GroupLength, SaclLength, DaclLength, TotalLength;
ULONG_PTR Current;
PISECURITY_DESCRIPTOR_RELATIVE RelSd = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
PAGED_CODE_RTL();
RtlpQuerySecurityDescriptor(SecurityDescriptor,
&Owner,
&OwnerLength,
&Group,
&GroupLength,
&Dacl,
&DaclLength,
&Sacl,
&SaclLength);
TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
OwnerLength +
GroupLength +
SaclLength +
DaclLength;
if (*BufferLength < TotalLength)
{
*BufferLength = TotalLength;
return STATUS_BUFFER_TOO_SMALL;
}
RtlZeroMemory(RelSd, TotalLength);
RtlCopyMemory(RelSd,
SecurityDescriptor,
FIELD_OFFSET(SECURITY_DESCRIPTOR_RELATIVE, Owner));
Current = (ULONG_PTR)(RelSd + 1);
if (SaclLength)
{
RtlCopyMemory((PVOID)Current, Sacl, SaclLength);
RelSd->Sacl = (ULONG_PTR)Current - (ULONG_PTR)RelSd;
Current += SaclLength;
}
if (DaclLength)
{
RtlCopyMemory((PVOID)Current, Dacl, DaclLength);
RelSd->Dacl = (ULONG_PTR)Current - (ULONG_PTR)RelSd;
Current += DaclLength;
}
if (OwnerLength)
{
RtlCopyMemory((PVOID)Current, Owner, OwnerLength);
RelSd->Owner = (ULONG_PTR)Current - (ULONG_PTR)RelSd;
Current += OwnerLength;
}
if (GroupLength)
{
RtlCopyMemory((PVOID)Current, Group, GroupLength);
RelSd->Group = (ULONG_PTR)Current - (ULONG_PTR)RelSd;
}
RelSd->Control |= SE_SELF_RELATIVE;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlSelfRelativeToAbsoluteSD(IN PSECURITY_DESCRIPTOR SelfRelativeSD,
OUT PSECURITY_DESCRIPTOR AbsoluteSD,
IN PULONG AbsoluteSDSize,
IN PACL Dacl,
IN PULONG DaclSize,
IN PACL Sacl,
IN PULONG SaclSize,
IN PSID Owner,
IN PULONG OwnerSize,
IN PSID PrimaryGroup,
IN PULONG PrimaryGroupSize)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)AbsoluteSD;
PISECURITY_DESCRIPTOR RelSd = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
ULONG OwnerLength, GroupLength, DaclLength, SaclLength;
PSID pOwner, pGroup;
PACL pDacl, pSacl;
PAGED_CODE_RTL();
if (!(RelSd->Control & SE_SELF_RELATIVE)) return STATUS_BAD_DESCRIPTOR_FORMAT;
RtlpQuerySecurityDescriptor(RelSd,
&pOwner,
&OwnerLength,
&pGroup,
&GroupLength,
&pDacl,
&DaclLength,
&pSacl,
&SaclLength);
if (!(Sd) ||
(sizeof(SECURITY_DESCRIPTOR) > *AbsoluteSDSize) ||
(OwnerLength > *OwnerSize) ||
(GroupLength > *PrimaryGroupSize) ||
(DaclLength > *DaclSize) ||
(SaclLength > *SaclSize))
{
*AbsoluteSDSize = sizeof(SECURITY_DESCRIPTOR);
*OwnerSize = OwnerLength;
*PrimaryGroupSize = GroupLength;
*DaclSize = DaclLength;
*SaclSize = SaclLength;
return STATUS_BUFFER_TOO_SMALL;
}
RtlMoveMemory(Sd, RelSd, sizeof(SECURITY_DESCRIPTOR_RELATIVE));
Sd->Owner = NULL;
Sd->Group = NULL;
Sd->Sacl = NULL;
Sd->Dacl = NULL;
Sd->Control &= ~SE_SELF_RELATIVE;
if (pOwner)
{
RtlMoveMemory(Owner, pOwner, RtlLengthSid(pOwner));
Sd->Owner = Owner;
}
if (pGroup)
{
RtlMoveMemory(PrimaryGroup, pGroup, RtlLengthSid(pGroup));
Sd->Group = PrimaryGroup;
}
if (pDacl)
{
RtlMoveMemory(Dacl, pDacl, pDacl->AclSize);
Sd->Dacl = Dacl;
}
if (pSacl)
{
RtlMoveMemory(Sacl, pSacl, pSacl->AclSize);
Sd->Sacl = Sacl;
}
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlSelfRelativeToAbsoluteSD2(IN OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
OUT PULONG BufferSize)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
PISECURITY_DESCRIPTOR_RELATIVE RelSd = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
PVOID DataStart, DataEnd;
LONG MoveDelta;
ULONG DataSize, OwnerLength, GroupLength, DaclLength, SaclLength;
PSID pOwner, pGroup;
PACL pDacl, pSacl;
PAGED_CODE_RTL();
if (!RelSd) return STATUS_INVALID_PARAMETER_1;
if (!BufferSize) return STATUS_INVALID_PARAMETER_2;
if (!(RelSd->Control & SE_SELF_RELATIVE)) return STATUS_BAD_DESCRIPTOR_FORMAT;
RtlpQuerySecurityDescriptor(Sd,
&pOwner,
&OwnerLength,
&pGroup,
&GroupLength,
&pDacl,
&DaclLength,
&pSacl,
&SaclLength);
* Check if there's a difference in structure layout between relatiev and
* absolute descriptors. On 32-bit, there won't be, since an offset is the
* same size as a pointer (32-bit), but on 64-bit, the offsets remain 32-bit
* as they are not SIZE_T, but ULONG, while the pointers now become 64-bit
* and thus the structure is different */
MoveDelta = sizeof(SECURITY_DESCRIPTOR) - sizeof(SECURITY_DESCRIPTOR_RELATIVE);
if (!MoveDelta)
{
Sd->Control &= ~SE_SELF_RELATIVE;
ASSERT(sizeof(Sd->Owner) == sizeof(RelSd->Owner));
ASSERT(sizeof(Sd->Group) == sizeof(RelSd->Group));
ASSERT(sizeof(Sd->Sacl) == sizeof(RelSd->Sacl));
ASSERT(sizeof(Sd->Dacl) == sizeof(RelSd->Dacl));
Sd->Owner = pOwner;
Sd->Group = pGroup;
Sd->Sacl = pSacl;
Sd->Dacl = pDacl;
return STATUS_SUCCESS;
}
* Calculate the start and end of the data area, we simply just move the
* data by the difference between the size of the relative and absolute
* security descriptor structure
*/
DataStart = pOwner;
DataEnd = (PVOID)((ULONG_PTR)pOwner + OwnerLength);
if (pGroup)
{
if (((ULONG_PTR)pGroup < (ULONG_PTR)DataStart) || !DataStart)
{
DataStart = pGroup;
}
if (((ULONG_PTR)pGroup + GroupLength > (ULONG_PTR)DataEnd) || !DataEnd)
{
DataEnd = (PVOID)((ULONG_PTR)pGroup + GroupLength);
}
}
if (pDacl)
{
if (((ULONG_PTR)pDacl < (ULONG_PTR)DataStart) || !DataStart)
{
DataStart = pDacl;
}
if (((ULONG_PTR)pDacl + DaclLength > (ULONG_PTR)DataEnd) || !DataEnd)
{
DataEnd = (PVOID)((ULONG_PTR)pDacl + DaclLength);
}
}
if (pSacl)
{
if (((ULONG_PTR)pSacl < (ULONG_PTR)DataStart) || !DataStart)
{
DataStart = pSacl;
}
if (((ULONG_PTR)pSacl + SaclLength > (ULONG_PTR)DataEnd) || !DataEnd)
{
DataEnd = (PVOID)((ULONG_PTR)pSacl + SaclLength);
}
}
ASSERT((ULONG_PTR)DataEnd >= (ULONG_PTR)DataStart);
DataSize = (ULONG)((ULONG_PTR)DataEnd - (ULONG_PTR)DataStart);
if (*BufferSize < sizeof(SECURITY_DESCRIPTOR) + DataSize)
{
*BufferSize = sizeof(SECURITY_DESCRIPTOR) + DataSize;
return STATUS_BUFFER_TOO_SMALL;
}
if (DataSize)
{
* There must be at least one SID or ACL in the security descriptor!
* Also the data area must be located somewhere after the end of the
* SECURITY_DESCRIPTOR_RELATIVE structure
*/
ASSERT(DataStart != NULL);
ASSERT((ULONG_PTR)DataStart >= (ULONG_PTR)(RelSd + 1));
RtlMoveMemory((PVOID)(Sd + 1),
DataStart,
DataSize);
}
if (pOwner)
{
Sd->Owner = (PSID)((LONG_PTR)pOwner + MoveDelta);
}
else
{
Sd->Owner = NULL;
}
if (pGroup)
{
Sd->Group = (PSID)((LONG_PTR)pGroup + MoveDelta);
}
else
{
Sd->Group = NULL;
}
if (pSacl)
{
Sd->Sacl = (PACL)((LONG_PTR)pSacl + MoveDelta);
}
else
{
Sd->Sacl = NULL;
}
if (pDacl)
{
Sd->Dacl = (PACL)((LONG_PTR)pDacl + MoveDelta);
}
else
{
Sd->Dacl = NULL;
}
Sd->Control &= ~SE_SELF_RELATIVE;
return STATUS_SUCCESS;
}
* @implemented
*/
BOOLEAN
NTAPI
RtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
{
PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
PSID Owner, Group;
PACL Sacl, Dacl;
PAGED_CODE_RTL();
_SEH2_TRY
{
if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) _SEH2_YIELD(return FALSE);
Owner = SepGetOwnerFromDescriptor(Sd);
if ((Owner) && (!RtlValidSid(Owner))) _SEH2_YIELD(return FALSE);
Group = SepGetGroupFromDescriptor(Sd);
if ((Group) && (!RtlValidSid(Group))) _SEH2_YIELD(return FALSE);
Dacl = SepGetDaclFromDescriptor(Sd);
if ((Dacl) && (!RtlValidAcl(Dacl))) _SEH2_YIELD(return FALSE);
Sacl = SepGetSaclFromDescriptor(Sd);
if ((Sacl) && (!RtlValidAcl(Sacl))) _SEH2_YIELD(return FALSE);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return FALSE);
}
_SEH2_END;
return TRUE;
}
* @implemented
*/
BOOLEAN
NTAPI
RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInput,
IN ULONG SecurityDescriptorLength,
IN SECURITY_INFORMATION RequiredInformation)
{
PISECURITY_DESCRIPTOR_RELATIVE Sd = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptorInput;
PSID Owner, Group;
PACL Dacl, Sacl;
ULONG Length;
PAGED_CODE_RTL();
if ((SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) ||
(Sd->Revision != SECURITY_DESCRIPTOR_REVISION) ||
!(Sd->Control & SE_SELF_RELATIVE))
{
return FALSE;
}
if (Sd->Owner)
{
if (!RtlpValidateSDOffsetAndSize(Sd->Owner,
SecurityDescriptorLength,
sizeof(SID),
&Length))
{
return FALSE;
}
Owner = (PSID)((ULONG_PTR)Sd->Owner + (ULONG_PTR)Sd);
if (!RtlValidSid(Owner) || (Length < RtlLengthSid(Owner))) return FALSE;
}
else if (RequiredInformation & OWNER_SECURITY_INFORMATION)
{
return FALSE;
}
if (Sd->Group)
{
if (!RtlpValidateSDOffsetAndSize(Sd->Group,
SecurityDescriptorLength,
sizeof(SID),
&Length))
{
return FALSE;
}
Group = (PSID)((ULONG_PTR)Sd->Group + (ULONG_PTR)Sd);
if (!RtlValidSid(Group) || (Length < RtlLengthSid(Group))) return FALSE;
}
else if (RequiredInformation & GROUP_SECURITY_INFORMATION)
{
return FALSE;
}
if ((Sd->Control & SE_DACL_PRESENT) == SE_DACL_PRESENT)
{
if (!RtlpValidateSDOffsetAndSize(Sd->Dacl,
SecurityDescriptorLength,
sizeof(ACL),
&Length))
{
return FALSE;
}
Dacl = (PSID)((ULONG_PTR)Sd->Dacl + (ULONG_PTR)Sd);
if (!(RtlValidAcl(Dacl)) || (Length < Dacl->AclSize)) return FALSE;
}
if ((Sd->Control & SE_SACL_PRESENT) == SE_SACL_PRESENT)
{
if (!RtlpValidateSDOffsetAndSize(Sd->Sacl,
SecurityDescriptorLength,
sizeof(ACL),
&Length))
{
return FALSE;
}
Sacl = (PSID)((ULONG_PTR)Sd->Sacl + (ULONG_PTR)Sd);
if (!(RtlValidAcl(Sacl)) || (Length < Sacl->AclSize)) return FALSE;
}
return TRUE;
}