/* * @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; /* Get all the components */ RtlpQuerySecurityDescriptor(Sd, &Owner, &OwnerLength, &Group, &GroupLength, &Dacl, &DaclLength, &Sacl, &SaclLength); /* Add up their lengths */ TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + OwnerLength + GroupLength + DaclLength + SaclLength; /* Allocate a copy */ *pDestinationSecurityDescriptor = RtlAllocateHeap(RtlGetProcessHeap(), 0, TotalLength); if (*pDestinationSecurityDescriptor == NULL) return STATUS_NO_MEMORY; /* Copy the old in the new */ RtlCopyMemory(*pDestinationSecurityDescriptor, Sd, TotalLength); /* All good */ return STATUS_SUCCESS; }
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()
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 ); }
/* * @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(); /* Need input */ if (!RelSd) return STATUS_INVALID_PARAMETER_1; /* Need to know how much space we have */ if (!BufferSize) return STATUS_INVALID_PARAMETER_2; /* Input must be relative */ if (!(RelSd->Control & SE_SELF_RELATIVE)) return STATUS_BAD_DESCRIPTOR_FORMAT; /* Query all the component sizes */ 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) { /* So on 32-bit, simply clear the flag... */ Sd->Control &= ~SE_SELF_RELATIVE; /* Ensure we're *really* on 32-bit */ 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)); /* And simply set pointers where there used to be offsets */ 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); /* Is there a group? */ if (pGroup) { /* Is the group higher than where we started? */ if (((ULONG_PTR)pGroup < (ULONG_PTR)DataStart) || !DataStart) { /* Update the start pointer */ DataStart = pGroup; } /* Is the group beyond where we ended? */ if (((ULONG_PTR)pGroup + GroupLength > (ULONG_PTR)DataEnd) || !DataEnd) { /* Update the end pointer */ DataEnd = (PVOID)((ULONG_PTR)pGroup + GroupLength); } } /* Is there a DACL? */ if (pDacl) { /* Is the DACL higher than where we started? */ if (((ULONG_PTR)pDacl < (ULONG_PTR)DataStart) || !DataStart) { /* Update the start pointer */ DataStart = pDacl; } /* Is the DACL beyond where we ended? */ if (((ULONG_PTR)pDacl + DaclLength > (ULONG_PTR)DataEnd) || !DataEnd) { /* Update the end pointer */ DataEnd = (PVOID)((ULONG_PTR)pDacl + DaclLength); } } /* Is there a SACL? */ if (pSacl) { /* Is the SACL higher than where we started? */ if (((ULONG_PTR)pSacl < (ULONG_PTR)DataStart) || !DataStart) { /* Update the start pointer */ DataStart = pSacl; } /* Is the SACL beyond where we ended? */ if (((ULONG_PTR)pSacl + SaclLength > (ULONG_PTR)DataEnd) || !DataEnd) { /* Update the end pointer */ DataEnd = (PVOID)((ULONG_PTR)pSacl + SaclLength); } } /* Sanity check */ ASSERT((ULONG_PTR)DataEnd >= (ULONG_PTR)DataStart); /* Now compute the difference between relative and absolute */ DataSize = (ULONG)((ULONG_PTR)DataEnd - (ULONG_PTR)DataStart); /* Is the new buffer large enough for this difference? */ if (*BufferSize < sizeof(SECURITY_DESCRIPTOR) + DataSize) { /* Nope, bail out */ *BufferSize = sizeof(SECURITY_DESCRIPTOR) + DataSize; return STATUS_BUFFER_TOO_SMALL; } /* Is there anything actually to copy? */ 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)); /* It's time to move the data */ RtlMoveMemory((PVOID)(Sd + 1), DataStart, DataSize); } /* Is there an owner? */ if (pOwner) { /* Set the pointer to the relative position */ Sd->Owner = (PSID)((LONG_PTR)pOwner + MoveDelta); } else { /* No owner, clear the pointer */ Sd->Owner = NULL; } /* Is there a group */ if (pGroup) { /* Set the pointer to the relative position */ Sd->Group = (PSID)((LONG_PTR)pGroup + MoveDelta); } else { /* No group, clear the pointer */ Sd->Group = NULL; } /* Is there a SACL? */ if (pSacl) { /* Set the pointer to the relative position */ Sd->Sacl = (PACL)((LONG_PTR)pSacl + MoveDelta); } else { /* No SACL, clear the pointer */ Sd->Sacl = NULL; } /* Is there a DACL? */ if (pDacl) { /* Set the pointer to the relative position */ Sd->Dacl = (PACL)((LONG_PTR)pDacl + MoveDelta); } else { /* No DACL, clear the pointer */ Sd->Dacl = NULL; } /* Clear the self-relative flag */ Sd->Control &= ~SE_SELF_RELATIVE; /* All good */ 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(); /* Must be relative, otherwiise fail */ if (!(RelSd->Control & SE_SELF_RELATIVE)) return STATUS_BAD_DESCRIPTOR_FORMAT; /* Get all the components */ RtlpQuerySecurityDescriptor(RelSd, &pOwner, &OwnerLength, &pGroup, &GroupLength, &pDacl, &DaclLength, &pSacl, &SaclLength); /* Fail if there's not enough space */ if (!(Sd) || (sizeof(SECURITY_DESCRIPTOR) > *AbsoluteSDSize) || (OwnerLength > *OwnerSize) || (GroupLength > *PrimaryGroupSize) || (DaclLength > *DaclSize) || (SaclLength > *SaclSize)) { /* Return how much space is needed for each components */ *AbsoluteSDSize = sizeof(SECURITY_DESCRIPTOR); *OwnerSize = OwnerLength; *PrimaryGroupSize = GroupLength; *DaclSize = DaclLength; *SaclSize = SaclLength; return STATUS_BUFFER_TOO_SMALL; } /* Copy the header fields */ RtlMoveMemory(Sd, RelSd, sizeof(SECURITY_DESCRIPTOR_RELATIVE)); /* Wipe out the pointers and the relative flag */ Sd->Owner = NULL; Sd->Group = NULL; Sd->Sacl = NULL; Sd->Dacl = NULL; Sd->Control &= ~SE_SELF_RELATIVE; /* Is there an owner? */ if (pOwner) { /* Copy it */ RtlMoveMemory(Owner, pOwner, RtlLengthSid(pOwner)); Sd->Owner = Owner; } /* Is there a group? */ if (pGroup) { /* Copy it */ RtlMoveMemory(PrimaryGroup, pGroup, RtlLengthSid(pGroup)); Sd->Group = PrimaryGroup; } /* Is there a DACL? */ if (pDacl) { /* Copy it */ RtlMoveMemory(Dacl, pDacl, pDacl->AclSize); Sd->Dacl = Dacl; } /* Is there a SACL? */ if (pSacl) { /* Copy it */ RtlMoveMemory(Sacl, pSacl, pSacl->AclSize); Sd->Sacl = Sacl; } /* All good */ return STATUS_SUCCESS; }
/* * @implemented */ NTSTATUS NTAPI RtlMakeSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSD, 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 Sd = (PISECURITY_DESCRIPTOR)AbsoluteSD; PISECURITY_DESCRIPTOR_RELATIVE RelSd = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD; PAGED_CODE_RTL(); /* Query all components */ RtlpQuerySecurityDescriptor(Sd, &Owner, &OwnerLength, &Group, &GroupLength, &Dacl, &DaclLength, &Sacl, &SaclLength); /* Calculate final length */ TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + OwnerLength + GroupLength + SaclLength + DaclLength; /* Is there enough space? */ if (*BufferLength < TotalLength) { /* Nope, return how much is needed */ *BufferLength = TotalLength; return STATUS_BUFFER_TOO_SMALL; } /* Start fresh */ RtlZeroMemory(RelSd, TotalLength); /* Copy the header fields */ RtlCopyMemory(RelSd, Sd, FIELD_OFFSET(SECURITY_DESCRIPTOR_RELATIVE, Owner)); /* Set the current copy pointer */ Current = (ULONG_PTR)(RelSd + 1); /* Is there a SACL? */ if (SaclLength) { /* Copy it */ RtlCopyMemory((PVOID)Current, Sacl, SaclLength); RelSd->Sacl = (ULONG_PTR)Current - (ULONG_PTR)RelSd; Current += SaclLength; } /* Is there a DACL? */ if (DaclLength) { /* Copy it */ RtlCopyMemory((PVOID)Current, Dacl, DaclLength); RelSd->Dacl = (ULONG_PTR)Current - (ULONG_PTR)RelSd; Current += DaclLength; } /* Is there an owner? */ if (OwnerLength) { /* Copy it */ RtlCopyMemory((PVOID)Current, Owner, OwnerLength); RelSd->Owner = (ULONG_PTR)Current - (ULONG_PTR)RelSd; Current += OwnerLength; } /* Is there a group? */ if (GroupLength) { /* Copy it */ RtlCopyMemory((PVOID)Current, Group, GroupLength); RelSd->Group = (ULONG_PTR)Current - (ULONG_PTR)RelSd; } /* Mark it as relative */ RelSd->Control |= SE_SELF_RELATIVE; /* All good */ return STATUS_SUCCESS; }