727 lines
19 KiB
C
727 lines
19 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
rtlassig.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This Module implements many security rtl routines defined in ntseapi.h
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jim Kelly (JimK) 23-Mar-1990
|
|||
|
Robert Reichel (RobertRe) 1-Mar-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Pure Runtime Library Routine
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
#include "ntrtlp.h"
|
|||
|
#include "seopaque.h"
|
|||
|
#include "sertlp.h"
|
|||
|
|
|||
|
#if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
|
|||
|
#pragma alloc_text(PAGE,RtlSelfRelativeToAbsoluteSD)
|
|||
|
#pragma alloc_text(PAGE,RtlMakeSelfRelativeSD)
|
|||
|
#pragma alloc_text(PAGE,RtlpQuerySecurityDescriptor)
|
|||
|
#pragma alloc_text(PAGE,RtlAbsoluteToSelfRelativeSD)
|
|||
|
#pragma alloc_text(PAGE,RtlSelfRelativeToAbsoluteSD2)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Exported Procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RtlSelfRelativeToAbsoluteSD(
|
|||
|
IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
|
|||
|
OUT PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
|
|||
|
IN OUT PULONG AbsoluteSecurityDescriptorSize,
|
|||
|
IN OUT PACL Dacl,
|
|||
|
IN OUT PULONG DaclSize,
|
|||
|
IN OUT PACL Sacl,
|
|||
|
IN OUT PULONG SaclSize,
|
|||
|
IN OUT PSID Owner,
|
|||
|
IN OUT PULONG OwnerSize,
|
|||
|
IN OUT PSID PrimaryGroup,
|
|||
|
IN OUT PULONG PrimaryGroupSize
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Converts a security descriptor from self-relative format to absolute
|
|||
|
format
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SecurityDescriptor - Supplies a pointer to a security descriptor in
|
|||
|
Self-Relative format
|
|||
|
|
|||
|
AbsoluteSecurityDescriptor - A pointer to a buffer in which will be
|
|||
|
placed the main body of the Absolute format security descriptor.
|
|||
|
|
|||
|
Dacl - Supplies a pointer to a buffer that will contain the Dacl of the
|
|||
|
output descriptor. This pointer will be referenced by, not copied
|
|||
|
into, the output descriptor.
|
|||
|
|
|||
|
DaclSize - Supplies the size of the buffer pointed to by Dacl. In case
|
|||
|
of error, it will return the minimum size necessary to contain the
|
|||
|
Dacl.
|
|||
|
|
|||
|
Sacl - Supplies a pointer to a buffer that will contain the Sacl of the
|
|||
|
output descriptor. This pointer will be referenced by, not copied
|
|||
|
into, the output descriptor.
|
|||
|
|
|||
|
SaclSize - Supplies the size of the buffer pointed to by Sacl. In case
|
|||
|
of error, it will return the minimum size necessary to contain the
|
|||
|
Sacl.
|
|||
|
|
|||
|
Owner - Supplies a pointer to a buffer that will contain the Owner of
|
|||
|
the output descriptor. This pointer will be referenced by, not
|
|||
|
copied into, the output descriptor.
|
|||
|
|
|||
|
OwnerSize - Supplies the size of the buffer pointed to by Owner. In
|
|||
|
case of error, it will return the minimum size necessary to contain
|
|||
|
the Owner.
|
|||
|
|
|||
|
PrimaryGroup - Supplies a pointer to a buffer that will contain the
|
|||
|
PrimaryGroup of the output descriptor. This pointer will be
|
|||
|
referenced by, not copied into, the output descriptor.
|
|||
|
|
|||
|
PrimaryGroupSize - Supplies the size of the buffer pointed to by
|
|||
|
PrimaryGroup. In case of error, it will return the minimum size
|
|||
|
necessary to contain the PrimaryGroup.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS - Success
|
|||
|
|
|||
|
STATUS_BUFFER_TOO_SMALL - One of the buffers passed was too small.
|
|||
|
|
|||
|
STATUS_INVALID_OWNER - There was not a valid owner in the passed
|
|||
|
security descriptor.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG NewDaclSize;
|
|||
|
ULONG NewSaclSize;
|
|||
|
ULONG NewBodySize;
|
|||
|
ULONG NewOwnerSize;
|
|||
|
ULONG NewGroupSize;
|
|||
|
|
|||
|
PSID NewOwner;
|
|||
|
PSID NewGroup;
|
|||
|
PACL NewDacl;
|
|||
|
PACL NewSacl;
|
|||
|
|
|||
|
//
|
|||
|
// typecast security descriptors so we don't have to cast all over the place.
|
|||
|
//
|
|||
|
|
|||
|
PISECURITY_DESCRIPTOR OutSD =
|
|||
|
AbsoluteSecurityDescriptor;
|
|||
|
|
|||
|
PISECURITY_DESCRIPTOR InSD =
|
|||
|
(PISECURITY_DESCRIPTOR)SelfRelativeSecurityDescriptor;
|
|||
|
|
|||
|
|
|||
|
RTL_PAGED_CODE();
|
|||
|
|
|||
|
if ( !RtlpAreControlBitsSet( InSD, SE_SELF_RELATIVE) ) {
|
|||
|
return( STATUS_BAD_DESCRIPTOR_FORMAT );
|
|||
|
}
|
|||
|
|
|||
|
NewBodySize = sizeof(SECURITY_DESCRIPTOR);
|
|||
|
|
|||
|
RtlpQuerySecurityDescriptor(
|
|||
|
InSD,
|
|||
|
&NewOwner,
|
|||
|
&NewOwnerSize,
|
|||
|
&NewGroup,
|
|||
|
&NewGroupSize,
|
|||
|
&NewDacl,
|
|||
|
&NewDaclSize,
|
|||
|
&NewSacl,
|
|||
|
&NewSaclSize
|
|||
|
);
|
|||
|
|
|||
|
if ( (NewBodySize > *AbsoluteSecurityDescriptorSize) ||
|
|||
|
(NewOwnerSize > *OwnerSize ) ||
|
|||
|
(NewDaclSize > *DaclSize ) ||
|
|||
|
(NewSaclSize > *SaclSize ) ||
|
|||
|
(NewGroupSize > *PrimaryGroupSize ) ) {
|
|||
|
|
|||
|
*AbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
|
|||
|
*PrimaryGroupSize = NewGroupSize;
|
|||
|
*OwnerSize = NewOwnerSize;
|
|||
|
*SaclSize = NewSaclSize;
|
|||
|
*DaclSize = NewDaclSize;
|
|||
|
|
|||
|
return( STATUS_BUFFER_TOO_SMALL );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RtlMoveMemory( OutSD,
|
|||
|
InSD,
|
|||
|
sizeof(SECURITY_DESCRIPTOR_RELATIVE) );
|
|||
|
|
|||
|
OutSD->Owner = NULL;
|
|||
|
OutSD->Group = NULL;
|
|||
|
OutSD->Sacl = NULL;
|
|||
|
OutSD->Dacl = NULL;
|
|||
|
|
|||
|
RtlpClearControlBits( OutSD, SE_SELF_RELATIVE );
|
|||
|
|
|||
|
if (NewOwner != NULL) {
|
|||
|
RtlMoveMemory( Owner, NewOwner, SeLengthSid( NewOwner ));
|
|||
|
OutSD->Owner = Owner;
|
|||
|
}
|
|||
|
|
|||
|
if (NewGroup != NULL) {
|
|||
|
RtlMoveMemory( PrimaryGroup, NewGroup, SeLengthSid( NewGroup ));
|
|||
|
OutSD->Group = PrimaryGroup;
|
|||
|
}
|
|||
|
|
|||
|
if (NewSacl != NULL) {
|
|||
|
RtlMoveMemory( Sacl, NewSacl, NewSacl->AclSize );
|
|||
|
OutSD->Sacl = Sacl;
|
|||
|
}
|
|||
|
|
|||
|
if (NewDacl != NULL) {
|
|||
|
RtlMoveMemory( Dacl, NewDacl, NewDacl->AclSize );
|
|||
|
OutSD->Dacl = Dacl;
|
|||
|
}
|
|||
|
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RtlMakeSelfRelativeSD(
|
|||
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|||
|
IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
|
|||
|
IN OUT PULONG BufferLength
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Makes a copy of a security descriptor. The produced copy will be in self-relative
|
|||
|
form.
|
|||
|
|
|||
|
The security descriptor to be copied may be in either absolute or self-relative
|
|||
|
form.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SecurityDescriptor - Pointer to a security descriptor. This descriptor will not
|
|||
|
be modified.
|
|||
|
|
|||
|
SelfRelativeSecurityDescriptor - Pointer to a buffer that will contain
|
|||
|
the returned self-relative security descriptor.
|
|||
|
|
|||
|
BufferLength - Supplies the length of the buffer. If the supplied
|
|||
|
buffer is not large enough to hold the self-relative security
|
|||
|
descriptor, an error will be returned, and this field will return
|
|||
|
the minimum size required.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_BUFFER_TOO_SMALL - The supplied buffer was too small to contain
|
|||
|
the resultant security descriptor.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG NewDaclSize;
|
|||
|
ULONG NewSaclSize;
|
|||
|
ULONG NewOwnerSize;
|
|||
|
ULONG NewGroupSize;
|
|||
|
|
|||
|
ULONG AllocationSize;
|
|||
|
|
|||
|
PSID NewOwner;
|
|||
|
PSID NewGroup;
|
|||
|
PACL NewDacl;
|
|||
|
PACL NewSacl;
|
|||
|
|
|||
|
PCHAR Field;
|
|||
|
PCHAR Base;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Convert security descriptors to new data type so we don't
|
|||
|
// have to cast all over the place.
|
|||
|
//
|
|||
|
|
|||
|
PISECURITY_DESCRIPTOR_RELATIVE IResultantDescriptor =
|
|||
|
(PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSecurityDescriptor;
|
|||
|
|
|||
|
PISECURITY_DESCRIPTOR IPassedSecurityDescriptor =
|
|||
|
(PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|||
|
|
|||
|
|
|||
|
RtlpQuerySecurityDescriptor(
|
|||
|
IPassedSecurityDescriptor,
|
|||
|
&NewOwner,
|
|||
|
&NewOwnerSize,
|
|||
|
&NewGroup,
|
|||
|
&NewGroupSize,
|
|||
|
&NewDacl,
|
|||
|
&NewDaclSize,
|
|||
|
&NewSacl,
|
|||
|
&NewSaclSize
|
|||
|
);
|
|||
|
|
|||
|
RTL_PAGED_CODE();
|
|||
|
|
|||
|
AllocationSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
|
|||
|
NewOwnerSize +
|
|||
|
NewGroupSize +
|
|||
|
NewDaclSize +
|
|||
|
NewSaclSize ;
|
|||
|
|
|||
|
if (AllocationSize > *BufferLength) {
|
|||
|
*BufferLength = AllocationSize;
|
|||
|
return( STATUS_BUFFER_TOO_SMALL );
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory( IResultantDescriptor, AllocationSize );
|
|||
|
|
|||
|
RtlCopyMemory( IResultantDescriptor,
|
|||
|
IPassedSecurityDescriptor,
|
|||
|
FIELD_OFFSET( SECURITY_DESCRIPTOR_RELATIVE, Owner ));
|
|||
|
|
|||
|
|
|||
|
Base = (PCHAR)(IResultantDescriptor);
|
|||
|
Field = Base + (ULONG)sizeof(SECURITY_DESCRIPTOR_RELATIVE);
|
|||
|
|
|||
|
if (NewSaclSize > 0) {
|
|||
|
RtlCopyMemory( Field, NewSacl, NewSaclSize );
|
|||
|
IResultantDescriptor->Sacl = RtlPointerToOffset(Base,Field);
|
|||
|
Field += NewSaclSize;
|
|||
|
} else {
|
|||
|
IResultantDescriptor->Sacl = 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (NewDaclSize > 0) {
|
|||
|
RtlCopyMemory( Field, NewDacl, NewDaclSize );
|
|||
|
IResultantDescriptor->Dacl = RtlPointerToOffset(Base,Field);
|
|||
|
Field += NewDaclSize;
|
|||
|
} else {
|
|||
|
IResultantDescriptor->Dacl = 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if (NewOwnerSize > 0) {
|
|||
|
RtlCopyMemory( Field, NewOwner, NewOwnerSize );
|
|||
|
IResultantDescriptor->Owner = RtlPointerToOffset(Base,Field);
|
|||
|
Field += NewOwnerSize;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (NewGroupSize > 0) {
|
|||
|
RtlCopyMemory( Field, NewGroup, NewGroupSize );
|
|||
|
IResultantDescriptor->Group = RtlPointerToOffset(Base,Field);
|
|||
|
}
|
|||
|
|
|||
|
RtlpSetControlBits( IResultantDescriptor, SE_SELF_RELATIVE );
|
|||
|
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RtlAbsoluteToSelfRelativeSD(
|
|||
|
IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
|
|||
|
IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
|
|||
|
IN OUT PULONG BufferLength
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Converts a security descriptor in absolute form to one in self-relative
|
|||
|
form.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AbsoluteSecurityDescriptor - Pointer to an absolute format security
|
|||
|
descriptor. This descriptor will not be modified.
|
|||
|
|
|||
|
SelfRelativeSecurityDescriptor - Pointer to a buffer that will contain
|
|||
|
the returned self-relative security descriptor.
|
|||
|
|
|||
|
BufferLength - Supplies the length of the buffer. If the supplied
|
|||
|
buffer is not large enough to hold the self-relative security
|
|||
|
descriptor, an error will be returned, and this field will return
|
|||
|
the minimum size required.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_BUFFER_TOO_SMALL - The supplied buffer was too small to contain
|
|||
|
the resultant security descriptor.
|
|||
|
|
|||
|
STATUS_BAD_DESCRIPTOR_FORMAT - The supplied security descriptor was not
|
|||
|
in absolute form.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS NtStatus;
|
|||
|
|
|||
|
PISECURITY_DESCRIPTOR IAbsoluteSecurityDescriptor =
|
|||
|
(PISECURITY_DESCRIPTOR)AbsoluteSecurityDescriptor;
|
|||
|
|
|||
|
|
|||
|
RTL_PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Make sure the passed SD is absolute format, and then call
|
|||
|
// RtlMakeSelfRelativeSD() to do all the work.
|
|||
|
//
|
|||
|
|
|||
|
if ( RtlpAreControlBitsSet( IAbsoluteSecurityDescriptor, SE_SELF_RELATIVE) ) {
|
|||
|
return( STATUS_BAD_DESCRIPTOR_FORMAT );
|
|||
|
}
|
|||
|
|
|||
|
NtStatus = RtlMakeSelfRelativeSD(
|
|||
|
AbsoluteSecurityDescriptor,
|
|||
|
SelfRelativeSecurityDescriptor,
|
|||
|
BufferLength
|
|||
|
);
|
|||
|
|
|||
|
return( NtStatus );
|
|||
|
|
|||
|
}
|
|||
|
VOID
|
|||
|
RtlpQuerySecurityDescriptor(
|
|||
|
IN PISECURITY_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
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Returns the pieces of a security descriptor structure.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
SecurityDescriptor - Provides the security descriptor of interest.
|
|||
|
|
|||
|
Owner - Returns a pointer to the owner information contained in the
|
|||
|
security descriptor.
|
|||
|
|
|||
|
OwnerSize - Returns the size of the owner information.
|
|||
|
|
|||
|
PrimaryGroup - Returns a pointer to the primary group information.
|
|||
|
|
|||
|
PrimaryGroupSize - Returns the size of the primary group information.
|
|||
|
|
|||
|
Dacl - Returns a pointer to the Dacl.
|
|||
|
|
|||
|
DaclSize - Returns the size of the Dacl.
|
|||
|
|
|||
|
Sacl - Returns a pointer to the Sacl.
|
|||
|
|
|||
|
SaclSize - Returns the size of the Sacl.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
RTL_PAGED_CODE();
|
|||
|
|
|||
|
*Owner = RtlpOwnerAddrSecurityDescriptor( SecurityDescriptor );
|
|||
|
|
|||
|
if (*Owner != NULL) {
|
|||
|
*OwnerSize = LongAlignSize(SeLengthSid(*Owner));
|
|||
|
} else {
|
|||
|
*OwnerSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
*Dacl = RtlpDaclAddrSecurityDescriptor ( SecurityDescriptor );
|
|||
|
|
|||
|
if (*Dacl !=NULL) {
|
|||
|
*DaclSize = LongAlignSize((*Dacl)->AclSize);
|
|||
|
} else {
|
|||
|
*DaclSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
*PrimaryGroup = RtlpGroupAddrSecurityDescriptor( SecurityDescriptor );
|
|||
|
|
|||
|
if (*PrimaryGroup != NULL) {
|
|||
|
*PrimaryGroupSize = LongAlignSize(SeLengthSid(*PrimaryGroup));
|
|||
|
} else {
|
|||
|
*PrimaryGroupSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
*Sacl = RtlpSaclAddrSecurityDescriptor( SecurityDescriptor );
|
|||
|
|
|||
|
if (*Sacl != NULL) {
|
|||
|
*SaclSize = LongAlignSize((*Sacl)->AclSize);
|
|||
|
} else {
|
|||
|
*SaclSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
RtlSelfRelativeToAbsoluteSD2(
|
|||
|
IN OUT PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
|
|||
|
IN OUT PULONG pBufferSize
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Converts a security descriptor from self-relative format to absolute
|
|||
|
format using the memory allocated for the SelfRelativeSecurityDescriptor
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pSecurityDescriptor - Supplies a pointer to a security descriptor in
|
|||
|
Self-Relative format. If success, we return a absolute security
|
|||
|
descriptor where this pointer pointings.
|
|||
|
|
|||
|
pBufferSize - Supplies a pointer to the size of the
|
|||
|
buffer.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS - Success
|
|||
|
|
|||
|
STATUS_BAD_DESCRIPTOR_FORMAT - The passed descriptor is not a self-relative
|
|||
|
security descriptor.
|
|||
|
|
|||
|
STATUS_BUFFER_TOO_SMALL - The passed buffer is too small.
|
|||
|
|
|||
|
STATUS_INVALID_OWNER - There was not a valid owner in the passed
|
|||
|
security descriptor.
|
|||
|
|
|||
|
Notes: Despite some attempts to make this code as portable as possible and the
|
|||
|
utilization of C_ASSERT or ASSERT to detect the respect of these assumptions,
|
|||
|
this code is still making several assumptions about the format of the absolute
|
|||
|
and self-relative descriptors and their relationships: in terms of packing,
|
|||
|
fields definitions and locations in their respective structures.
|
|||
|
In particular, this code assumes that the only differences are due to differences
|
|||
|
in the types of the structure members and in the behaviour of the security descriptor
|
|||
|
query API.
|
|||
|
At this time, the only structure members that get read/updated are Owner, Group,
|
|||
|
Dacl and Sacl. If more members are added or displaced in the definitions of these
|
|||
|
structures, this code may have to be modified.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG_PTR ptr;
|
|||
|
PSID owner;
|
|||
|
PSID group;
|
|||
|
PACL dacl;
|
|||
|
PACL sacl;
|
|||
|
ULONG daclSize;
|
|||
|
ULONG saclSize;
|
|||
|
ULONG newBodySize;
|
|||
|
ULONG ownerSize;
|
|||
|
ULONG groupSize;
|
|||
|
ULONG newBufferSize;
|
|||
|
LONG deltaSize;
|
|||
|
|
|||
|
//
|
|||
|
// Typecast security descriptors so we don't have to cast all over the place.
|
|||
|
//
|
|||
|
|
|||
|
PISECURITY_DESCRIPTOR psd = (PISECURITY_DESCRIPTOR) pSelfRelativeSecurityDescriptor;
|
|||
|
PISECURITY_DESCRIPTOR_RELATIVE psdr = (PISECURITY_DESCRIPTOR_RELATIVE)pSelfRelativeSecurityDescriptor;
|
|||
|
|
|||
|
//
|
|||
|
// This code uses several assumptions about the absolute and self-relative formats of
|
|||
|
// security descriptors and the way they are packing in memory.
|
|||
|
// See Routine Description Notes.
|
|||
|
//
|
|||
|
|
|||
|
C_ASSERT( sizeof( SECURITY_DESCRIPTOR ) >= sizeof( SECURITY_DESCRIPTOR_RELATIVE ) );
|
|||
|
C_ASSERT( sizeof( psd->Control ) == sizeof( psdr->Control ) );
|
|||
|
C_ASSERT( FIELD_OFFSET( SECURITY_DESCRIPTOR, Control ) == FIELD_OFFSET( SECURITY_DESCRIPTOR_RELATIVE, Control ) );
|
|||
|
|
|||
|
RTL_PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Parameters check point
|
|||
|
//
|
|||
|
|
|||
|
if ( psd == (PISECURITY_DESCRIPTOR)0 ) {
|
|||
|
return( STATUS_INVALID_PARAMETER_1 );
|
|||
|
}
|
|||
|
if ( pBufferSize == (PULONG)0 ) {
|
|||
|
return( STATUS_INVALID_PARAMETER_2 );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the passed security descriptor is not self-relative, we return
|
|||
|
// an format error.
|
|||
|
//
|
|||
|
|
|||
|
if ( !RtlpAreControlBitsSet( psd, SE_SELF_RELATIVE) ) {
|
|||
|
return( STATUS_BAD_DESCRIPTOR_FORMAT );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Update local variables by querying the self-relative descriptor.
|
|||
|
//
|
|||
|
// Note that the returned size values are long-aligned.
|
|||
|
//
|
|||
|
|
|||
|
RtlpQuerySecurityDescriptor(
|
|||
|
psd,
|
|||
|
&owner,
|
|||
|
&ownerSize,
|
|||
|
&group,
|
|||
|
&groupSize,
|
|||
|
&dacl,
|
|||
|
&daclSize,
|
|||
|
&sacl,
|
|||
|
&saclSize
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Identical formats check:
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Determine the delta in size between the two formats of security descriptors
|
|||
|
//
|
|||
|
|
|||
|
deltaSize = sizeof( SECURITY_DESCRIPTOR ) - sizeof( SECURITY_DESCRIPTOR_RELATIVE );
|
|||
|
|
|||
|
//
|
|||
|
// If identical format:
|
|||
|
// - clear the SELF_RELATIVE flag
|
|||
|
// - update absolute descriptor members
|
|||
|
// - return SUCCESS.
|
|||
|
//
|
|||
|
|
|||
|
if ( deltaSize == 0 ) {
|
|||
|
|
|||
|
RtlpClearControlBits( psd, SE_SELF_RELATIVE );
|
|||
|
|
|||
|
//
|
|||
|
// Only the following fields are updated.
|
|||
|
//
|
|||
|
|
|||
|
ASSERT( sizeof( psd->Owner ) == sizeof( psdr->Owner ) );
|
|||
|
ASSERT( sizeof( psd->Group ) == sizeof( psdr->Group ) );
|
|||
|
ASSERT( sizeof( psd->Sacl ) == sizeof( psdr->Sacl ) );
|
|||
|
ASSERT( sizeof( psd->Dacl ) == sizeof( psdr->Dacl ) );
|
|||
|
|
|||
|
psd->Owner = owner;
|
|||
|
psd->Group = group;
|
|||
|
psd->Sacl = sacl;
|
|||
|
psd->Dacl = dacl;
|
|||
|
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Determine the required size for the absolute format:
|
|||
|
//
|
|||
|
|
|||
|
#define ULONG_PTR_SDEND( _Adr ) ( (ULONG_PTR)(_Adr) + (ULONG_PTR)(_Adr##Size) )
|
|||
|
|
|||
|
ptr = owner > group ? ULONG_PTR_SDEND( owner ) : ULONG_PTR_SDEND( group );
|
|||
|
ptr = ptr > (ULONG_PTR)dacl ? ptr : ULONG_PTR_SDEND( dacl );
|
|||
|
ptr = ptr > (ULONG_PTR)sacl ? ptr : ULONG_PTR_SDEND( sacl );
|
|||
|
|
|||
|
newBufferSize = sizeof( SECURITY_DESCRIPTOR );
|
|||
|
if ( ptr ) {
|
|||
|
|
|||
|
#define ULONG_ROUND_UP( x, y ) ((ULONG)(x) + ((y)-1) & ~((y)-1))
|
|||
|
|
|||
|
newBufferSize += ULONG_ROUND_UP( (ULONG_PTR)ptr - (ULONG_PTR)(psdr + 1), sizeof(PVOID) );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the specified buffer size is not big enough, let the caller know abour
|
|||
|
// the minimum size and return STATUS_BUFFER_TOO_SMALL.
|
|||
|
//
|
|||
|
|
|||
|
if ( newBufferSize > *pBufferSize ) {
|
|||
|
*pBufferSize = newBufferSize;
|
|||
|
return( STATUS_BUFFER_TOO_SMALL );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Update absolute security descriptor:
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Move the members of self-relative security descriptor in their
|
|||
|
// absolute format locations.
|
|||
|
//
|
|||
|
|
|||
|
if ( ptr ) {
|
|||
|
RtlMoveMemory( (PVOID)(psd + 1), (PVOID)(psdr + 1), newBufferSize - sizeof( SECURITY_DESCRIPTOR) );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Clear the self-relative flag
|
|||
|
//
|
|||
|
|
|||
|
RtlpClearControlBits( psd, SE_SELF_RELATIVE );
|
|||
|
|
|||
|
//
|
|||
|
// Only the following fields are updated.
|
|||
|
//
|
|||
|
|
|||
|
psd->Owner = (PSID)( owner ? (ULONG_PTR)owner + deltaSize : 0 );
|
|||
|
psd->Group = (PSID)( group ? (ULONG_PTR)group + deltaSize : 0 );
|
|||
|
psd->Sacl = (PACL)( sacl ? (ULONG_PTR)sacl + deltaSize : 0 );
|
|||
|
psd->Dacl = (PACL)( dacl ? (ULONG_PTR)dacl + deltaSize : 0 );
|
|||
|
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
|
|||
|
} // RtlSelfRelativeToAbsoluteSD2()
|
|||
|
|