mirror of
https://github.com/reactos/reactos.git
synced 2024-11-09 08:08:38 +00:00
6afbc8f483
svn path=/branches/reactos-yarotows/; revision=45219
1176 lines
30 KiB
C
1176 lines
30 KiB
C
/*
|
|
* 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>
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <rtl.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
|
|
static VOID
|
|
RtlpQuerySecurityDescriptorPointers(IN PISECURITY_DESCRIPTOR SecurityDescriptor,
|
|
OUT PSID *Owner OPTIONAL,
|
|
OUT PSID *Group OPTIONAL,
|
|
OUT PACL *Sacl OPTIONAL,
|
|
OUT PACL *Dacl OPTIONAL)
|
|
{
|
|
if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
|
|
{
|
|
PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
|
|
if(Owner != NULL)
|
|
{
|
|
*Owner = ((RelSD->Owner != 0) ? (PSID)((ULONG_PTR)RelSD + RelSD->Owner) : NULL);
|
|
}
|
|
if(Group != NULL)
|
|
{
|
|
*Group = ((RelSD->Group != 0) ? (PSID)((ULONG_PTR)RelSD + RelSD->Group) : NULL);
|
|
}
|
|
if(Sacl != NULL)
|
|
{
|
|
*Sacl = (((RelSD->Control & SE_SACL_PRESENT) && (RelSD->Sacl != 0)) ?
|
|
(PSID)((ULONG_PTR)RelSD + RelSD->Sacl) : NULL);
|
|
}
|
|
if(Dacl != NULL)
|
|
{
|
|
*Dacl = (((RelSD->Control & SE_DACL_PRESENT) && (RelSD->Dacl != 0)) ?
|
|
(PSID)((ULONG_PTR)RelSD + RelSD->Dacl) : NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(Owner != NULL)
|
|
{
|
|
*Owner = SecurityDescriptor->Owner;
|
|
}
|
|
if(Group != NULL)
|
|
{
|
|
*Group = SecurityDescriptor->Group;
|
|
}
|
|
if(Sacl != NULL)
|
|
{
|
|
*Sacl = ((SecurityDescriptor->Control & SE_SACL_PRESENT) ? SecurityDescriptor->Sacl : NULL);
|
|
}
|
|
if(Dacl != NULL)
|
|
{
|
|
*Dacl = ((SecurityDescriptor->Control & SE_DACL_PRESENT) ? SecurityDescriptor->Dacl : NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID
|
|
RtlpQuerySecurityDescriptor(PISECURITY_DESCRIPTOR SecurityDescriptor,
|
|
PSID* Owner,
|
|
PULONG OwnerLength,
|
|
PSID* Group,
|
|
PULONG GroupLength,
|
|
PACL* Dacl,
|
|
PULONG DaclLength,
|
|
PACL* Sacl,
|
|
PULONG SaclLength)
|
|
{
|
|
RtlpQuerySecurityDescriptorPointers(SecurityDescriptor,
|
|
Owner,
|
|
Group,
|
|
Sacl,
|
|
Dacl);
|
|
|
|
if (Owner != NULL)
|
|
{
|
|
*OwnerLength = ((*Owner != NULL) ? ROUND_UP(RtlLengthSid(*Owner), 4) : 0);
|
|
}
|
|
|
|
if (Group != NULL)
|
|
{
|
|
*GroupLength = ((*Group != NULL) ? ROUND_UP(RtlLengthSid(*Group), 4) : 0);
|
|
}
|
|
|
|
if (Dacl != NULL)
|
|
{
|
|
*DaclLength = ((*Dacl != NULL) ? ROUND_UP((*Dacl)->AclSize, 4) : 0);
|
|
}
|
|
|
|
if (Sacl != NULL)
|
|
{
|
|
*SaclLength = ((*Sacl != NULL) ? ROUND_UP((*Sacl)->AclSize, 4) : 0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlCreateSecurityDescriptor(OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
IN ULONG Revision)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
pSD->Revision = Revision;
|
|
pSD->Sbz1 = 0;
|
|
pSD->Control = 0;
|
|
pSD->Owner = NULL;
|
|
pSD->Group = NULL;
|
|
pSD->Sacl = NULL;
|
|
pSD->Dacl = NULL;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlCopySecurityDescriptor(IN PSECURITY_DESCRIPTOR pSourceSecurityDescriptor,
|
|
OUT PSECURITY_DESCRIPTOR pDestinationSecurityDescriptor)
|
|
{
|
|
PSID Owner = NULL, Group = NULL;
|
|
PACL Dacl = NULL, Sacl = NULL;
|
|
BOOLEAN Defaulted, Present;
|
|
DWORD OwnerLength, GroupLength;
|
|
PISECURITY_DESCRIPTOR srcSD = pSourceSecurityDescriptor;
|
|
PISECURITY_DESCRIPTOR destSD = pDestinationSecurityDescriptor;
|
|
|
|
if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
|
|
return STATUS_UNKNOWN_REVISION;
|
|
|
|
/* Copy non relative dependent data */
|
|
destSD->Revision = srcSD->Revision;
|
|
destSD->Sbz1 = srcSD->Sbz1;
|
|
destSD->Control = srcSD->Control;
|
|
|
|
/* Read relative data */
|
|
RtlGetOwnerSecurityDescriptor(srcSD, &Owner, &Defaulted);
|
|
OwnerLength = RtlLengthSid(Owner);
|
|
RtlGetGroupSecurityDescriptor(srcSD, &Group, &Defaulted);
|
|
GroupLength = RtlLengthSid(Group);
|
|
RtlGetDaclSecurityDescriptor(srcSD, &Present, &Dacl, &Defaulted);
|
|
RtlGetSaclSecurityDescriptor(srcSD, &Present, &Sacl, &Defaulted);
|
|
|
|
if (srcSD->Control & SE_SELF_RELATIVE)
|
|
{
|
|
destSD->Owner = srcSD->Owner;
|
|
RtlCopySid(OwnerLength, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
|
|
|
|
destSD->Group = srcSD->Group;
|
|
RtlCopySid(GroupLength, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
|
|
|
|
if (srcSD->Control & SE_DACL_PRESENT)
|
|
{
|
|
destSD->Dacl = srcSD->Dacl;
|
|
|
|
if(srcSD->Dacl != NULL && RtlValidAcl(srcSD->Dacl))
|
|
{
|
|
RtlCopyMemory(((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl, Dacl->AclSize);
|
|
}
|
|
}
|
|
|
|
if (srcSD->Control & SE_SACL_PRESENT)
|
|
{
|
|
destSD->Sacl = srcSD->Sacl;
|
|
|
|
if(srcSD->Sacl != NULL && RtlValidAcl(srcSD->Sacl))
|
|
{
|
|
RtlCopyMemory(((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl, Sacl->AclSize);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RtlCopySid(OwnerLength, destSD->Owner, Owner);
|
|
RtlCopySid(GroupLength, destSD->Group, Group);
|
|
|
|
if (srcSD->Control & SE_DACL_PRESENT)
|
|
{
|
|
destSD->Dacl = RtlAllocateHeap(RtlGetProcessHeap(), 0, Dacl->AclSize);
|
|
|
|
if(srcSD->Dacl != NULL && RtlValidAcl(srcSD->Dacl))
|
|
{
|
|
RtlCopyMemory(destSD->Dacl, Dacl, Dacl->AclSize);
|
|
}
|
|
}
|
|
|
|
if (srcSD->Control & SE_SACL_PRESENT)
|
|
{
|
|
destSD->Sacl = RtlAllocateHeap(RtlGetProcessHeap(), 0, Sacl->AclSize);
|
|
|
|
if(srcSD->Sacl != NULL && RtlValidAcl(srcSD->Sacl))
|
|
{
|
|
RtlCopyMemory(destSD->Sacl, Sacl, Sacl->AclSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS NTAPI
|
|
RtlCreateSecurityDescriptorRelative (OUT PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor,
|
|
IN ULONG Revision)
|
|
{
|
|
PAGED_CODE_RTL();
|
|
|
|
if (Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
SecurityDescriptor->Revision = Revision;
|
|
SecurityDescriptor->Sbz1 = 0;
|
|
SecurityDescriptor->Control = SE_SELF_RELATIVE;
|
|
SecurityDescriptor->Owner = 0;
|
|
SecurityDescriptor->Group = 0;
|
|
SecurityDescriptor->Sacl = 0;
|
|
SecurityDescriptor->Dacl = 0;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ULONG NTAPI
|
|
RtlLengthSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
|
|
{
|
|
PSID Owner, Group;
|
|
PACL Sacl, Dacl;
|
|
ULONG Length = sizeof(SECURITY_DESCRIPTOR);
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
RtlpQuerySecurityDescriptorPointers((PISECURITY_DESCRIPTOR)SecurityDescriptor,
|
|
&Owner,
|
|
&Group,
|
|
&Sacl,
|
|
&Dacl);
|
|
|
|
if (Owner != NULL)
|
|
{
|
|
Length += ROUND_UP(RtlLengthSid(Owner), 4);
|
|
}
|
|
|
|
if (Group != NULL)
|
|
{
|
|
Length += ROUND_UP(RtlLengthSid(Group), 4);
|
|
}
|
|
|
|
if (Dacl != NULL)
|
|
{
|
|
Length += ROUND_UP(Dacl->AclSize, 4);
|
|
}
|
|
|
|
if (Sacl != NULL)
|
|
{
|
|
Length += ROUND_UP(Sacl->AclSize, 4);
|
|
}
|
|
|
|
return Length;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlGetDaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
OUT PBOOLEAN DaclPresent,
|
|
OUT PACL* Dacl,
|
|
OUT PBOOLEAN DaclDefaulted)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
if (!(pSD->Control & SE_DACL_PRESENT))
|
|
{
|
|
*DaclPresent = FALSE;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
*DaclPresent = TRUE;
|
|
|
|
RtlpQuerySecurityDescriptorPointers(pSD,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
Dacl);
|
|
|
|
*DaclDefaulted = ((pSD->Control & SE_DACL_DEFAULTED) ? TRUE : FALSE);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlSetDaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
IN BOOLEAN DaclPresent,
|
|
IN PACL Dacl,
|
|
IN BOOLEAN DaclDefaulted)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
if (pSD->Control & SE_SELF_RELATIVE)
|
|
{
|
|
return STATUS_BAD_DESCRIPTOR_FORMAT;
|
|
}
|
|
|
|
if (!DaclPresent)
|
|
{
|
|
pSD->Control = pSD->Control & ~(SE_DACL_PRESENT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
pSD->Dacl = Dacl;
|
|
pSD->Control |= SE_DACL_PRESENT;
|
|
pSD->Control &= ~(SE_DACL_DEFAULTED);
|
|
|
|
if (DaclDefaulted)
|
|
{
|
|
pSD->Control |= SE_DACL_DEFAULTED;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOLEAN NTAPI
|
|
RtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
PSID Owner, Group;
|
|
PACL Sacl, Dacl;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
RtlpQuerySecurityDescriptorPointers(pSD,
|
|
&Owner,
|
|
&Group,
|
|
&Sacl,
|
|
&Dacl);
|
|
|
|
if ((Owner != NULL && !RtlValidSid(Owner)) ||
|
|
(Group != NULL && !RtlValidSid(Group)) ||
|
|
(Sacl != NULL && !RtlValidAcl(Sacl)) ||
|
|
(Dacl != NULL && !RtlValidAcl(Dacl)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlSetOwnerSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
IN PSID Owner,
|
|
IN BOOLEAN OwnerDefaulted)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
if (pSD->Control & SE_SELF_RELATIVE)
|
|
{
|
|
return STATUS_BAD_DESCRIPTOR_FORMAT;
|
|
}
|
|
|
|
pSD->Owner = Owner;
|
|
pSD->Control &= ~(SE_OWNER_DEFAULTED);
|
|
|
|
if (OwnerDefaulted)
|
|
{
|
|
pSD->Control |= SE_OWNER_DEFAULTED;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
OUT PSID* Owner,
|
|
OUT PBOOLEAN OwnerDefaulted)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
RtlpQuerySecurityDescriptorPointers(pSD,
|
|
Owner,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
*OwnerDefaulted = ((pSD->Control & SE_OWNER_DEFAULTED) ? TRUE : FALSE);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
IN PSID Group,
|
|
IN BOOLEAN GroupDefaulted)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
if (pSD->Control & SE_SELF_RELATIVE)
|
|
{
|
|
return STATUS_BAD_DESCRIPTOR_FORMAT;
|
|
}
|
|
|
|
pSD->Group = Group;
|
|
pSD->Control &= ~(SE_GROUP_DEFAULTED);
|
|
if (GroupDefaulted)
|
|
{
|
|
pSD->Control |= SE_GROUP_DEFAULTED;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlGetGroupSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
OUT PSID* Group,
|
|
OUT PBOOLEAN GroupDefaulted)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
RtlpQuerySecurityDescriptorPointers(pSD,
|
|
NULL,
|
|
Group,
|
|
NULL,
|
|
NULL);
|
|
|
|
*GroupDefaulted = ((pSD->Control & SE_GROUP_DEFAULTED) ? TRUE : FALSE);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlMakeSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSD,
|
|
OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
|
|
IN OUT PULONG BufferLength)
|
|
{
|
|
PSID Owner;
|
|
PSID Group;
|
|
PACL Sacl;
|
|
PACL Dacl;
|
|
ULONG OwnerLength;
|
|
ULONG GroupLength;
|
|
ULONG SaclLength;
|
|
ULONG DaclLength;
|
|
ULONG TotalLength;
|
|
ULONG_PTR Current;
|
|
PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)AbsoluteSD;
|
|
PISECURITY_DESCRIPTOR_RELATIVE pRelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
RtlpQuerySecurityDescriptor(pAbsSD,
|
|
&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(pRelSD,
|
|
TotalLength);
|
|
|
|
pRelSD->Revision = pAbsSD->Revision;
|
|
pRelSD->Sbz1 = pAbsSD->Sbz1;
|
|
pRelSD->Control = pAbsSD->Control | SE_SELF_RELATIVE;
|
|
|
|
Current = (ULONG_PTR)(pRelSD + 1);
|
|
|
|
if (SaclLength != 0)
|
|
{
|
|
RtlCopyMemory((PVOID)Current,
|
|
Sacl,
|
|
SaclLength);
|
|
pRelSD->Sacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
|
|
Current += SaclLength;
|
|
}
|
|
|
|
if (DaclLength != 0)
|
|
{
|
|
RtlCopyMemory((PVOID)Current,
|
|
Dacl,
|
|
DaclLength);
|
|
pRelSD->Dacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
|
|
Current += DaclLength;
|
|
}
|
|
|
|
if (OwnerLength != 0)
|
|
{
|
|
RtlCopyMemory((PVOID)Current,
|
|
Owner,
|
|
OwnerLength);
|
|
pRelSD->Owner = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
|
|
Current += OwnerLength;
|
|
}
|
|
|
|
if (GroupLength != 0)
|
|
{
|
|
RtlCopyMemory((PVOID)Current,
|
|
Group,
|
|
GroupLength);
|
|
pRelSD->Group = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)pRelSD);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
|
|
IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
|
|
IN PULONG BufferLength)
|
|
{
|
|
PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)AbsoluteSecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pAbsSD->Control & SE_SELF_RELATIVE)
|
|
{
|
|
return STATUS_BAD_DESCRIPTOR_FORMAT;
|
|
}
|
|
|
|
return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
|
|
SelfRelativeSecurityDescriptor,
|
|
BufferLength);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlGetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
OUT PSECURITY_DESCRIPTOR_CONTROL Control,
|
|
OUT PULONG Revision)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
*Revision = pSD->Revision;
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
*Control = pSD->Control;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
|
|
IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
|
|
{
|
|
SECURITY_DESCRIPTOR_CONTROL const immutable
|
|
= SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
|
|
| SE_DACL_PRESENT | SE_DACL_DEFAULTED
|
|
| SE_SACL_PRESENT | SE_SACL_DEFAULTED
|
|
| SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
|
|
;
|
|
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* Zero the 'bits of interest' */
|
|
pSD->Control &= ~ControlBitsOfInterest;
|
|
|
|
/* Set the 'bits to set' */
|
|
pSD->Control |= (ControlBitsToSet & ControlBitsOfInterest);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
OUT PBOOLEAN SaclPresent,
|
|
OUT PACL *Sacl,
|
|
OUT PBOOLEAN SaclDefaulted)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
if (!(pSD->Control & SE_SACL_PRESENT))
|
|
{
|
|
*SaclPresent = FALSE;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
*SaclPresent = TRUE;
|
|
|
|
RtlpQuerySecurityDescriptorPointers(pSD,
|
|
NULL,
|
|
NULL,
|
|
Sacl,
|
|
NULL);
|
|
|
|
*SaclDefaulted = ((pSD->Control & SE_SACL_DEFAULTED) ? TRUE : FALSE);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
IN BOOLEAN SaclPresent,
|
|
IN PACL Sacl,
|
|
IN BOOLEAN SaclDefaulted)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
if (pSD->Control & SE_SELF_RELATIVE)
|
|
{
|
|
return STATUS_BAD_DESCRIPTOR_FORMAT;
|
|
}
|
|
|
|
if (!SaclPresent)
|
|
{
|
|
pSD->Control &= ~(SE_SACL_PRESENT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
pSD->Sacl = Sacl;
|
|
pSD->Control |= SE_SACL_PRESENT;
|
|
pSD->Control &= ~(SE_SACL_DEFAULTED);
|
|
|
|
if (SaclDefaulted)
|
|
{
|
|
pSD->Control |= SE_SACL_DEFAULTED;
|
|
}
|
|
|
|
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 pAbsSD = (PISECURITY_DESCRIPTOR)AbsoluteSD;
|
|
PISECURITY_DESCRIPTOR pRelSD = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
|
|
ULONG OwnerLength;
|
|
ULONG GroupLength;
|
|
ULONG DaclLength;
|
|
ULONG SaclLength;
|
|
PSID pOwner;
|
|
PSID pGroup;
|
|
PACL pDacl;
|
|
PACL pSacl;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (pRelSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
|
|
if (!(pRelSD->Control & SE_SELF_RELATIVE))
|
|
{
|
|
return STATUS_BAD_DESCRIPTOR_FORMAT;
|
|
}
|
|
|
|
RtlpQuerySecurityDescriptor (pRelSD,
|
|
&pOwner,
|
|
&OwnerLength,
|
|
&pGroup,
|
|
&GroupLength,
|
|
&pDacl,
|
|
&DaclLength,
|
|
&pSacl,
|
|
&SaclLength);
|
|
|
|
if (OwnerLength > *OwnerSize ||
|
|
GroupLength > *PrimaryGroupSize ||
|
|
DaclLength > *DaclSize ||
|
|
SaclLength > *SaclSize)
|
|
{
|
|
*OwnerSize = OwnerLength;
|
|
*PrimaryGroupSize = GroupLength;
|
|
*DaclSize = DaclLength;
|
|
*SaclSize = SaclLength;
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
RtlCopyMemory (Owner, pOwner, OwnerLength);
|
|
RtlCopyMemory (PrimaryGroup, pGroup, GroupLength);
|
|
RtlCopyMemory (Dacl, pDacl, DaclLength);
|
|
RtlCopyMemory (Sacl, pSacl, SaclLength);
|
|
|
|
pAbsSD->Revision = pRelSD->Revision;
|
|
pAbsSD->Sbz1 = pRelSD->Sbz1;
|
|
pAbsSD->Control = pRelSD->Control & ~SE_SELF_RELATIVE;
|
|
pAbsSD->Owner = Owner;
|
|
pAbsSD->Group = PrimaryGroup;
|
|
pAbsSD->Dacl = Dacl;
|
|
pAbsSD->Sacl = Sacl;
|
|
|
|
*OwnerSize = OwnerLength;
|
|
*PrimaryGroupSize = GroupLength;
|
|
*DaclSize = DaclLength;
|
|
*SaclSize = SaclLength;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlSelfRelativeToAbsoluteSD2(IN OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
|
|
OUT PULONG BufferSize)
|
|
{
|
|
PISECURITY_DESCRIPTOR pAbsSD = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
|
|
PISECURITY_DESCRIPTOR_RELATIVE pRelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
|
|
#ifdef _WIN64
|
|
PVOID DataStart, DataEnd;
|
|
ULONG DataSize;
|
|
LONG MoveDelta;
|
|
ULONG OwnerLength;
|
|
ULONG GroupLength;
|
|
ULONG DaclLength;
|
|
ULONG SaclLength;
|
|
#endif
|
|
PSID pOwner;
|
|
PSID pGroup;
|
|
PACL pDacl;
|
|
PACL pSacl;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (SelfRelativeSD == NULL)
|
|
{
|
|
return STATUS_INVALID_PARAMETER_1;
|
|
}
|
|
if (BufferSize == NULL)
|
|
{
|
|
return STATUS_INVALID_PARAMETER_2;
|
|
}
|
|
|
|
if (pRelSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
{
|
|
return STATUS_UNKNOWN_REVISION;
|
|
}
|
|
if (!(pRelSD->Control & SE_SELF_RELATIVE))
|
|
{
|
|
return STATUS_BAD_DESCRIPTOR_FORMAT;
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
|
|
RtlpQuerySecurityDescriptor((PISECURITY_DESCRIPTOR)pRelSD,
|
|
&pOwner,
|
|
&OwnerLength,
|
|
&pGroup,
|
|
&GroupLength,
|
|
&pDacl,
|
|
&DaclLength,
|
|
&pSacl,
|
|
&SaclLength);
|
|
|
|
/* 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 != NULL)
|
|
{
|
|
if (((ULONG_PTR)pGroup < (ULONG_PTR)DataStart) || DataStart == NULL)
|
|
DataStart = pGroup;
|
|
if (((ULONG_PTR)pGroup + GroupLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
|
|
DataEnd = (PVOID)((ULONG_PTR)pGroup + GroupLength);
|
|
}
|
|
if (pDacl != NULL)
|
|
{
|
|
if (((ULONG_PTR)pDacl < (ULONG_PTR)DataStart) || DataStart == NULL)
|
|
DataStart = pDacl;
|
|
if (((ULONG_PTR)pDacl + DaclLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
|
|
DataEnd = (PVOID)((ULONG_PTR)pDacl + DaclLength);
|
|
}
|
|
if (pSacl != NULL)
|
|
{
|
|
if (((ULONG_PTR)pSacl < (ULONG_PTR)DataStart) || DataStart == NULL)
|
|
DataStart = pSacl;
|
|
if (((ULONG_PTR)pSacl + SaclLength > (ULONG_PTR)DataEnd) || DataEnd == NULL)
|
|
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 != 0)
|
|
{
|
|
/* if DataSize != 0 ther 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)(pRelSD + 1));
|
|
|
|
/* it's time to move the data */
|
|
RtlMoveMemory((PVOID)(pAbsSD + 1),
|
|
DataStart,
|
|
DataSize);
|
|
|
|
MoveDelta = (LONG)((LONG_PTR)(pAbsSD + 1) - (LONG_PTR)DataStart);
|
|
|
|
/* adjust the pointers if neccessary */
|
|
if (pOwner != NULL)
|
|
pAbsSD->Owner = (PSID)((LONG_PTR)pOwner + MoveDelta);
|
|
else
|
|
pAbsSD->Owner = NULL;
|
|
|
|
if (pGroup != NULL)
|
|
pAbsSD->Group = (PSID)((LONG_PTR)pGroup + MoveDelta);
|
|
else
|
|
pAbsSD->Group = NULL;
|
|
|
|
if (pSacl != NULL)
|
|
pAbsSD->Sacl = (PACL)((LONG_PTR)pSacl + MoveDelta);
|
|
else
|
|
pAbsSD->Sacl = NULL;
|
|
|
|
if (pDacl != NULL)
|
|
pAbsSD->Dacl = (PACL)((LONG_PTR)pDacl + MoveDelta);
|
|
else
|
|
pAbsSD->Dacl = NULL;
|
|
}
|
|
else
|
|
{
|
|
/* all pointers must be NULL! */
|
|
ASSERT(pOwner == NULL);
|
|
ASSERT(pGroup == NULL);
|
|
ASSERT(pSacl == NULL);
|
|
ASSERT(pDacl == NULL);
|
|
|
|
pAbsSD->Owner = NULL;
|
|
pAbsSD->Group = NULL;
|
|
pAbsSD->Sacl = NULL;
|
|
pAbsSD->Dacl = NULL;
|
|
}
|
|
|
|
/* clear the self-relative flag */
|
|
pAbsSD->Control &= ~SE_SELF_RELATIVE;
|
|
|
|
#else
|
|
|
|
RtlpQuerySecurityDescriptorPointers((PISECURITY_DESCRIPTOR)pRelSD,
|
|
&pOwner,
|
|
&pGroup,
|
|
&pSacl,
|
|
&pDacl);
|
|
|
|
/* clear the self-relative flag and simply convert the offsets to pointers */
|
|
pAbsSD->Control &= ~SE_SELF_RELATIVE;
|
|
pAbsSD->Owner = pOwner;
|
|
pAbsSD->Group = pGroup;
|
|
pAbsSD->Sacl = pSacl;
|
|
pAbsSD->Dacl = pDacl;
|
|
|
|
#endif
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOLEAN NTAPI
|
|
RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInput,
|
|
IN ULONG SecurityDescriptorLength,
|
|
IN SECURITY_INFORMATION RequiredInformation)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptorInput;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE) ||
|
|
pSD->Revision != SECURITY_DESCRIPTOR_REVISION1 ||
|
|
!(pSD->Control & SE_SELF_RELATIVE))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (pSD->Owner != 0)
|
|
{
|
|
PSID Owner = (PSID)((ULONG_PTR)pSD->Owner + (ULONG_PTR)pSD);
|
|
if (!RtlValidSid(Owner))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if (RequiredInformation & OWNER_SECURITY_INFORMATION)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (pSD->Group != 0)
|
|
{
|
|
PSID Group = (PSID)((ULONG_PTR)pSD->Group + (ULONG_PTR)pSD);
|
|
if (!RtlValidSid(Group))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if (RequiredInformation & GROUP_SECURITY_INFORMATION)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (pSD->Control & SE_DACL_PRESENT)
|
|
{
|
|
if (pSD->Dacl != 0 &&
|
|
!RtlValidAcl((PACL)((ULONG_PTR)pSD->Dacl + (ULONG_PTR)pSD)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if (RequiredInformation & DACL_SECURITY_INFORMATION)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (pSD->Control & SE_SACL_PRESENT)
|
|
{
|
|
if (pSD->Sacl != 0 &&
|
|
!RtlValidAcl((PACL)((ULONG_PTR)pSD->Sacl + (ULONG_PTR)pSD)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if (RequiredInformation & SACL_SECURITY_INFORMATION)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOLEAN NTAPI
|
|
RtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
OUT PUCHAR RMControl)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (!(pSD->Control & SE_RM_CONTROL_VALID))
|
|
{
|
|
*RMControl = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
*RMControl = pSD->Sbz1;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
VOID NTAPI
|
|
RtlSetSecurityDescriptorRMControl(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
IN PUCHAR RMControl)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
if (RMControl == NULL)
|
|
{
|
|
pSD->Control &= ~SE_RM_CONTROL_VALID;
|
|
pSD->Sbz1 = 0;
|
|
}
|
|
else
|
|
{
|
|
pSD->Control |= SE_RM_CONTROL_VALID;
|
|
pSD->Sbz1 = *RMControl;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS NTAPI
|
|
RtlSetAttributesSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
IN SECURITY_DESCRIPTOR_CONTROL Control,
|
|
OUT PULONG Revision)
|
|
{
|
|
PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|
|
|
PAGED_CODE_RTL();
|
|
|
|
*Revision = pSD->Revision;
|
|
|
|
if (pSD->Revision != SECURITY_DESCRIPTOR_REVISION1)
|
|
return STATUS_UNKNOWN_REVISION;
|
|
|
|
Control &=
|
|
~(SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED | SE_DACL_PRESENT |
|
|
SE_DACL_DEFAULTED | SE_SACL_PRESENT | SE_SACL_DEFAULTED |
|
|
SE_RM_CONTROL_VALID | SE_SELF_RELATIVE);
|
|
|
|
return RtlSetControlSecurityDescriptor(SecurityDescriptor,
|
|
Control,
|
|
Control);
|
|
}
|
|
|
|
/* EOF */
|