Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206/* * 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>#include "../../ntoskrnl/include/internal/se.h"#define NDEBUG#include <debug.h>
/* PRIVATE FUNCTIONS **********************************************************/
BOOLEANNTAPIRtlpValidateSDOffsetAndSize(IN ULONG Offset, IN ULONG Length, IN ULONG MinLength, OUT PULONG MaxLength){ /* Assume failure */ *MaxLength = 0;
/* Reject out of bounds lengths */ if (Offset < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) return FALSE; if (Offset >= Length) return FALSE;
/* Reject insufficient lengths */ if ((Length - Offset) < MinLength) return FALSE;
/* Reject unaligned offsets */ if (ALIGN_DOWN(Offset, ULONG) != Offset) return FALSE;
/* Return length that is safe to read */ *MaxLength = Length - Offset; return TRUE;}
VOIDNTAPIRtlpQuerySecurityDescriptor(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();
/* Get the owner */ *Owner = SepGetOwnerFromDescriptor(SecurityDescriptor); if (*Owner) { /* There's an owner, so align the size */ *OwnerSize = ROUND_UP(RtlLengthSid(*Owner), sizeof(ULONG)); } else { /* No owner, no size */ *OwnerSize = 0; }
/* Get the group */ *PrimaryGroup = SepGetGroupFromDescriptor(SecurityDescriptor); if (*PrimaryGroup) { /* There's a group, so align the size */ *PrimaryGroupSize = ROUND_UP(RtlLengthSid(*PrimaryGroup), sizeof(ULONG)); } else { /* No group, no size */ *PrimaryGroupSize = 0; }
/* Get the DACL */ *Dacl = SepGetDaclFromDescriptor(SecurityDescriptor); if (*Dacl) { /* There's a DACL, align the size */ *DaclSize = ROUND_UP((*Dacl)->AclSize, sizeof(ULONG)); } else { /* No DACL, no size */ *DaclSize = 0; }
/* Get the SACL */ *Sacl = SepGetSaclFromDescriptor(SecurityDescriptor); if (*Sacl) { /* There's a SACL, align the size */ *SaclSize = ROUND_UP((*Sacl)->AclSize, sizeof(ULONG)); } else { /* No SACL, no size */ *SaclSize = 0; }}
/* PUBLIC FUNCTIONS ***********************************************************/
/* * @implemented */NTSTATUSNTAPIRtlCreateSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Revision){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Fail on invalid revisions */ if (Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Setup an empty SD */ RtlZeroMemory(Sd, sizeof(*Sd)); Sd->Revision = SECURITY_DESCRIPTOR_REVISION;
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSNTAPIRtlCreateSecurityDescriptorRelative(IN PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, IN ULONG Revision){ PAGED_CODE_RTL();
/* Fail on invalid revisions */ if (Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Setup an empty SD */ RtlZeroMemory(SecurityDescriptor, sizeof(*SecurityDescriptor)); SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION; SecurityDescriptor->Control = SE_SELF_RELATIVE;
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */ULONGNTAPIRtlLengthSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor){ PISECURITY_DESCRIPTOR Sd; PSID Owner, Group; PACL Sacl, Dacl; ULONG Length; PAGED_CODE_RTL();
/* Start with the initial length of the SD itself */ Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; if (Sd->Control & SE_SELF_RELATIVE) { Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); } else { Length = sizeof(SECURITY_DESCRIPTOR); }
/* Add the length of the individual subcomponents */ 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 the final length */ return Length;}
/* * @implemented */NTSTATUSNTAPIRtlGetDaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PBOOLEAN DaclPresent, OUT PACL* Dacl, OUT PBOOLEAN DaclDefaulted){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Fail on invalid revisions */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Is there a DACL? */ *DaclPresent = (Sd->Control & SE_DACL_PRESENT) == SE_DACL_PRESENT; if (*DaclPresent) { /* Yes, return it, and check if defaulted */ *Dacl = SepGetDaclFromDescriptor(Sd); *DaclDefaulted = (Sd->Control & SE_DACL_DEFAULTED) == SE_DACL_DEFAULTED; }
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSNTAPIRtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PBOOLEAN SaclPresent, OUT PACL* Sacl, OUT PBOOLEAN SaclDefaulted){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Fail on invalid revisions */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Is there a SACL? */ *SaclPresent = (Sd->Control & SE_SACL_PRESENT) == SE_SACL_PRESENT; if (*SaclPresent) { /* Yes, return it, and check if defaulted */ *Sacl = SepGetSaclFromDescriptor(Sd); *SaclDefaulted = (Sd->Control & SE_SACL_DEFAULTED) == SE_SACL_DEFAULTED; }
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSNTAPIRtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID* Owner, OUT PBOOLEAN OwnerDefaulted){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Get the owner and if defaulted */ *Owner = SepGetOwnerFromDescriptor(Sd); *OwnerDefaulted = (Sd->Control & SE_OWNER_DEFAULTED) == SE_OWNER_DEFAULTED;
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSNTAPIRtlGetGroupSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID* Group, OUT PBOOLEAN GroupDefaulted){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Get the group and if defaulted */ *Group = SepGetGroupFromDescriptor(Sd); *GroupDefaulted = (Sd->Control & SE_GROUP_DEFAULTED) == SE_GROUP_DEFAULTED;
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSNTAPIRtlSetDaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN DaclPresent, IN PACL Dacl, IN BOOLEAN DaclDefaulted){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Fail on relative descriptors */ if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
/* Is there a DACL? */ if (!DaclPresent) { /* Caller is destroying the DACL, unset the flag and we're done */ Sd->Control = Sd->Control & ~SE_DACL_PRESENT; return STATUS_SUCCESS; }
/* Caller is setting a new DACL, set the pointer and flag */ Sd->Dacl = Dacl; Sd->Control |= SE_DACL_PRESENT;
/* Set if defaulted */ Sd->Control &= ~SE_DACL_DEFAULTED; if (DaclDefaulted) Sd->Control |= SE_DACL_DEFAULTED;
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSNTAPIRtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN SaclPresent, IN PACL Sacl, IN BOOLEAN SaclDefaulted){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Fail on relative descriptors */ if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
/* Is there a SACL? */ if (!SaclPresent) { /* Caller is clearing the SACL, unset the flag and we're done */ Sd->Control = Sd->Control & ~SE_SACL_PRESENT; return STATUS_SUCCESS; }
/* Caller is setting a new SACL, set it and the flag */ Sd->Sacl = Sacl; Sd->Control |= SE_SACL_PRESENT;
/* Set if defaulted */ Sd->Control &= ~SE_SACL_DEFAULTED; if (SaclDefaulted) Sd->Control |= SE_SACL_DEFAULTED;
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSNTAPIRtlSetOwnerSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID Owner, IN BOOLEAN OwnerDefaulted){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Fail on relative descriptors */ if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
/* Owner being set or cleared */ Sd->Owner = Owner;
/* Set if defaulted */ Sd->Control &= ~SE_OWNER_DEFAULTED; if (OwnerDefaulted) Sd->Control |= SE_OWNER_DEFAULTED;
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSNTAPIRtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID Group, IN BOOLEAN GroupDefaulted){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Fail on relative descriptors */ if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
/* Group being set or cleared */ Sd->Group = Group;
/* Set if defaulted */ Sd->Control &= ~SE_GROUP_DEFAULTED; if (GroupDefaulted) Sd->Control |= SE_GROUP_DEFAULTED;
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSNTAPIRtlGetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSECURITY_DESCRIPTOR_CONTROL Control, OUT PULONG Revision){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Read current revision, even if invalid */ *Revision = Sd->Revision;
/* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Read current control */ *Control = Sd->Control;
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */NTSTATUSNTAPIRtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
/* Check for invalid bits */ 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)) { /* Fail */ return STATUS_INVALID_PARAMETER; }
/* Zero the 'bits of interest' */ Sd->Control &= ~ControlBitsOfInterest;
/* Set the 'bits to set' */ Sd->Control |= (ControlBitsToSet & ControlBitsOfInterest);
/* All good */ return STATUS_SUCCESS;}
/* * @implemented */BOOLEANNTAPIRtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PUCHAR RMControl){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Check if there's no valid RM control */ if (!(Sd->Control & SE_RM_CONTROL_VALID)) { /* Fail and return nothing */ *RMControl = 0; return FALSE; }
/* Return it, ironically the member is "should be zero" */ *RMControl = Sd->Sbz1; return TRUE;}
/* * @implemented */VOIDNTAPIRtlSetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PUCHAR RMControl){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* RM Control is being cleared or set */ if (!RMControl) { /* Clear it */ Sd->Control &= ~SE_RM_CONTROL_VALID; Sd->Sbz1 = 0; } else { /* Set it */ Sd->Control |= SE_RM_CONTROL_VALID; Sd->Sbz1 = *RMControl; }}
/* * @implemented */NTSTATUSNTAPIRtlSetAttributesSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN SECURITY_DESCRIPTOR_CONTROL Control, OUT PULONG Revision){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PAGED_CODE_RTL();
/* Always return revision, even if invalid */ *Revision = Sd->Revision;
/* Fail on invalid revision */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
/* Mask out flags which are not attributes */ 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;
/* Call the newer API */ return RtlSetControlSecurityDescriptor(SecurityDescriptor, Control, Control);}
/* * @implemented */NTSTATUSNTAPIRtlCopySecurityDescriptor(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;}
/* * @implemented */NTSTATUSNTAPIRtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, IN PULONG BufferLength){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)AbsoluteSecurityDescriptor; PAGED_CODE_RTL();
/* Can't already be relative */ if (Sd->Control & SE_SELF_RELATIVE) return STATUS_BAD_DESCRIPTOR_FORMAT;
/* Call the other API */ return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor, SelfRelativeSecurityDescriptor, BufferLength);}
/* * @implemented */NTSTATUSNTAPIRtlMakeSelfRelativeSD(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();
/* Query all components */ RtlpQuerySecurityDescriptor(SecurityDescriptor, &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, SecurityDescriptor, 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;}
/* * @implemented */NTSTATUSNTAPIRtlSelfRelativeToAbsoluteSD(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 */NTSTATUSNTAPIRtlSelfRelativeToAbsoluteSD2(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 */BOOLEANNTAPIRtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor){ PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; PSID Owner, Group; PACL Sacl, Dacl; PAGED_CODE_RTL();
_SEH2_TRY { /* Fail on bad revisions */ if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) _SEH2_YIELD(return FALSE);
/* Owner SID must be valid if present */ Owner = SepGetOwnerFromDescriptor(Sd); if ((Owner) && (!RtlValidSid(Owner))) _SEH2_YIELD(return FALSE);
/* Group SID must be valid if present */ Group = SepGetGroupFromDescriptor(Sd); if ((Group) && (!RtlValidSid(Group))) _SEH2_YIELD(return FALSE);
/* DACL must be valid if present */ Dacl = SepGetDaclFromDescriptor(Sd); if ((Dacl) && (!RtlValidAcl(Dacl))) _SEH2_YIELD(return FALSE);
/* SACL must be valid if present */ Sacl = SepGetSaclFromDescriptor(Sd); if ((Sacl) && (!RtlValidAcl(Sacl))) _SEH2_YIELD(return FALSE); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Access fault, bail out */ _SEH2_YIELD(return FALSE); } _SEH2_END;
/* All good */ return TRUE;}
/* * @implemented */BOOLEANNTAPIRtlValidRelativeSecurityDescriptor(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();
/* Note that Windows allows no DACL/SACL even if RequiredInfo wants it */
/* Do we have enough space, is the revision vaild, and is this SD relative? */ if ((SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) || (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) || !(Sd->Control & SE_SELF_RELATIVE)) { /* Nope, bail out */ return FALSE; }
/* Is there an owner? */ if (Sd->Owner) { /* Try to access it */ if (!RtlpValidateSDOffsetAndSize(Sd->Owner, SecurityDescriptorLength, sizeof(SID), &Length)) { /* It's beyond the buffer, fail */ return FALSE; }
/* Read the owner, check if it's valid and if the buffer contains it */ Owner = (PSID)((ULONG_PTR)Sd->Owner + (ULONG_PTR)Sd); if (!RtlValidSid(Owner) || (Length < RtlLengthSid(Owner))) return FALSE; } else if (RequiredInformation & OWNER_SECURITY_INFORMATION) { /* No owner but the caller expects one, fail */ return FALSE; }
/* Is there a group? */ if (Sd->Group) { /* Try to access it */ if (!RtlpValidateSDOffsetAndSize(Sd->Group, SecurityDescriptorLength, sizeof(SID), &Length)) { /* It's beyond the buffer, fail */ return FALSE; }
/* Read the group, check if it's valid and if the buffer contains it */ Group = (PSID)((ULONG_PTR)Sd->Group + (ULONG_PTR)Sd); if (!RtlValidSid(Group) || (Length < RtlLengthSid(Group))) return FALSE; } else if (RequiredInformation & GROUP_SECURITY_INFORMATION) { /* No group, but the caller expects one, fail */ return FALSE; }
/* Is there a DACL? */ if ((Sd->Control & SE_DACL_PRESENT) == SE_DACL_PRESENT) { /* Try to access it */ if (!RtlpValidateSDOffsetAndSize(Sd->Dacl, SecurityDescriptorLength, sizeof(ACL), &Length)) { /* It's beyond the buffer, fail */ return FALSE; }
/* Read the DACL, check if it's valid and if the buffer contains it */ Dacl = (PSID)((ULONG_PTR)Sd->Dacl + (ULONG_PTR)Sd); if (!(RtlValidAcl(Dacl)) || (Length < Dacl->AclSize)) return FALSE; }
/* Is there a SACL? */ if ((Sd->Control & SE_SACL_PRESENT) == SE_SACL_PRESENT) { /* Try to access it */ if (!RtlpValidateSDOffsetAndSize(Sd->Sacl, SecurityDescriptorLength, sizeof(ACL), &Length)) { /* It's beyond the buffer, fail */ return FALSE; }
/* Read the SACL, check if it's valid and if the buffer contains it */ Sacl = (PSID)((ULONG_PTR)Sd->Sacl + (ULONG_PTR)Sd); if (!(RtlValidAcl(Sacl)) || (Length < Sacl->AclSize)) return FALSE; }
/* All good */ return TRUE;}
/* EOF */