2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Security descriptor functions
6 * PROGRAMER: David Welch <welch@cwcom.net>
9 /* INCLUDES *****************************************************************/
12 #include "../../ntoskrnl/include/internal/se.h"
16 /* PRIVATE FUNCTIONS **********************************************************/
20 RtlpValidateSDOffsetAndSize(IN ULONG Offset
,
28 /* Reject out of bounds lengths */
29 if (Offset
< sizeof(SECURITY_DESCRIPTOR_RELATIVE
)) return FALSE
;
30 if (Offset
>= Length
) return FALSE
;
32 /* Reject insufficient lengths */
33 if ((Length
- Offset
) < MinLength
) return FALSE
;
35 /* Reject unaligned offsets */
36 if (ALIGN_DOWN(Offset
, ULONG
) != Offset
) return FALSE
;
38 /* Return length that is safe to read */
39 *MaxLength
= Length
- Offset
;
45 RtlpQuerySecurityDescriptor(IN PISECURITY_DESCRIPTOR SecurityDescriptor
,
48 OUT PSID
*PrimaryGroup
,
49 OUT PULONG PrimaryGroupSize
,
58 *Owner
= SepGetOwnerFromDescriptor(SecurityDescriptor
);
61 /* There's an owner, so align the size */
62 *OwnerSize
= ROUND_UP(RtlLengthSid(*Owner
), sizeof(ULONG
));
66 /* No owner, no size */
71 *PrimaryGroup
= SepGetGroupFromDescriptor(SecurityDescriptor
);
74 /* There's a group, so align the size */
75 *PrimaryGroupSize
= ROUND_UP(RtlLengthSid(*PrimaryGroup
), sizeof(ULONG
));
79 /* No group, no size */
80 *PrimaryGroupSize
= 0;
84 *Dacl
= SepGetDaclFromDescriptor(SecurityDescriptor
);
87 /* There's a DACL, align the size */
88 *DaclSize
= ROUND_UP((*Dacl
)->AclSize
, sizeof(ULONG
));
92 /* No DACL, no size */
97 *Sacl
= SepGetSaclFromDescriptor(SecurityDescriptor
);
100 /* There's a SACL, align the size */
101 *SaclSize
= ROUND_UP((*Sacl
)->AclSize
, sizeof(ULONG
));
105 /* No SACL, no size */
110 /* PUBLIC FUNCTIONS ***********************************************************/
117 RtlCreateSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
120 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
123 /* Fail on invalid revisions */
124 if (Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
126 /* Setup an empty SD */
127 RtlZeroMemory(Sd
, sizeof(*Sd
));
128 Sd
->Revision
= SECURITY_DESCRIPTOR_REVISION
;
131 return STATUS_SUCCESS
;
139 RtlCreateSecurityDescriptorRelative(IN PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor
,
144 /* Fail on invalid revisions */
145 if (Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
147 /* Setup an empty SD */
148 RtlZeroMemory(SecurityDescriptor
, sizeof(*SecurityDescriptor
));
149 SecurityDescriptor
->Revision
= SECURITY_DESCRIPTOR_REVISION
;
150 SecurityDescriptor
->Control
= SE_SELF_RELATIVE
;
153 return STATUS_SUCCESS
;
161 RtlLengthSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
163 PISECURITY_DESCRIPTOR Sd
;
169 /* Start with the initial length of the SD itself */
170 Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
171 if (Sd
->Control
& SE_SELF_RELATIVE
)
173 Length
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
177 Length
= sizeof(SECURITY_DESCRIPTOR
);
180 /* Add the length of the individual subcomponents */
181 Owner
= SepGetOwnerFromDescriptor(Sd
);
182 if (Owner
) Length
+= ROUND_UP(RtlLengthSid(Owner
), sizeof(ULONG
));
183 Group
= SepGetGroupFromDescriptor(Sd
);
184 if (Group
) Length
+= ROUND_UP(RtlLengthSid(Group
), sizeof(ULONG
));
185 Dacl
= SepGetDaclFromDescriptor(Sd
);
186 if (Dacl
) Length
+= ROUND_UP(Dacl
->AclSize
, sizeof(ULONG
));
187 Sacl
= SepGetSaclFromDescriptor(Sd
);
188 if (Sacl
) Length
+= ROUND_UP(Sacl
->AclSize
, sizeof(ULONG
));
190 /* Return the final length */
199 RtlGetDaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
200 OUT PBOOLEAN DaclPresent
,
202 OUT PBOOLEAN DaclDefaulted
)
204 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
207 /* Fail on invalid revisions */
208 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
210 /* Is there a DACL? */
211 *DaclPresent
= (Sd
->Control
& SE_DACL_PRESENT
) == SE_DACL_PRESENT
;
214 /* Yes, return it, and check if defaulted */
215 *Dacl
= SepGetDaclFromDescriptor(Sd
);
216 *DaclDefaulted
= (Sd
->Control
& SE_DACL_DEFAULTED
) == SE_DACL_DEFAULTED
;
220 return STATUS_SUCCESS
;
228 RtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
229 OUT PBOOLEAN SaclPresent
,
231 OUT PBOOLEAN SaclDefaulted
)
233 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
236 /* Fail on invalid revisions */
237 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
239 /* Is there a SACL? */
240 *SaclPresent
= (Sd
->Control
& SE_SACL_PRESENT
) == SE_SACL_PRESENT
;
243 /* Yes, return it, and check if defaulted */
244 *Sacl
= SepGetSaclFromDescriptor(Sd
);
245 *SaclDefaulted
= (Sd
->Control
& SE_SACL_DEFAULTED
) == SE_SACL_DEFAULTED
;
249 return STATUS_SUCCESS
;
257 RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
259 OUT PBOOLEAN OwnerDefaulted
)
261 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
264 /* Fail on invalid revision */
265 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
267 /* Get the owner and if defaulted */
268 *Owner
= SepGetOwnerFromDescriptor(Sd
);
269 *OwnerDefaulted
= (Sd
->Control
& SE_OWNER_DEFAULTED
) == SE_OWNER_DEFAULTED
;
272 return STATUS_SUCCESS
;
280 RtlGetGroupSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
282 OUT PBOOLEAN GroupDefaulted
)
284 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
287 /* Fail on invalid revision */
288 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
290 /* Get the group and if defaulted */
291 *Group
= SepGetGroupFromDescriptor(Sd
);
292 *GroupDefaulted
= (Sd
->Control
& SE_GROUP_DEFAULTED
) == SE_GROUP_DEFAULTED
;
295 return STATUS_SUCCESS
;
303 RtlSetDaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
304 IN BOOLEAN DaclPresent
,
306 IN BOOLEAN DaclDefaulted
)
308 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
311 /* Fail on invalid revision */
312 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
314 /* Fail on relative descriptors */
315 if (Sd
->Control
& SE_SELF_RELATIVE
) return STATUS_INVALID_SECURITY_DESCR
;
317 /* Is there a DACL? */
320 /* Caller is destroying the DACL, unset the flag and we're done */
321 Sd
->Control
= Sd
->Control
& ~SE_DACL_PRESENT
;
322 return STATUS_SUCCESS
;
325 /* Caller is setting a new DACL, set the pointer and flag */
327 Sd
->Control
|= SE_DACL_PRESENT
;
329 /* Set if defaulted */
330 Sd
->Control
&= ~SE_DACL_DEFAULTED
;
331 if (DaclDefaulted
) Sd
->Control
|= SE_DACL_DEFAULTED
;
334 return STATUS_SUCCESS
;
342 RtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
343 IN BOOLEAN SaclPresent
,
345 IN BOOLEAN SaclDefaulted
)
347 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
350 /* Fail on invalid revision */
351 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
353 /* Fail on relative descriptors */
354 if (Sd
->Control
& SE_SELF_RELATIVE
) return STATUS_INVALID_SECURITY_DESCR
;
356 /* Is there a SACL? */
359 /* Caller is clearing the SACL, unset the flag and we're done */
360 Sd
->Control
= Sd
->Control
& ~SE_SACL_PRESENT
;
361 return STATUS_SUCCESS
;
364 /* Caller is setting a new SACL, set it and the flag */
366 Sd
->Control
|= SE_SACL_PRESENT
;
368 /* Set if defaulted */
369 Sd
->Control
&= ~SE_SACL_DEFAULTED
;
370 if (SaclDefaulted
) Sd
->Control
|= SE_SACL_DEFAULTED
;
373 return STATUS_SUCCESS
;
381 RtlSetOwnerSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
383 IN BOOLEAN OwnerDefaulted
)
385 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
388 /* Fail on invalid revision */
389 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
391 /* Fail on relative descriptors */
392 if (Sd
->Control
& SE_SELF_RELATIVE
) return STATUS_INVALID_SECURITY_DESCR
;
394 /* Owner being set or cleared */
397 /* Set if defaulted */
398 Sd
->Control
&= ~SE_OWNER_DEFAULTED
;
399 if (OwnerDefaulted
) Sd
->Control
|= SE_OWNER_DEFAULTED
;
402 return STATUS_SUCCESS
;
410 RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
412 IN BOOLEAN GroupDefaulted
)
414 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
417 /* Fail on invalid revision */
418 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
420 /* Fail on relative descriptors */
421 if (Sd
->Control
& SE_SELF_RELATIVE
) return STATUS_INVALID_SECURITY_DESCR
;
423 /* Group being set or cleared */
426 /* Set if defaulted */
427 Sd
->Control
&= ~SE_GROUP_DEFAULTED
;
428 if (GroupDefaulted
) Sd
->Control
|= SE_GROUP_DEFAULTED
;
431 return STATUS_SUCCESS
;
439 RtlGetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
440 OUT PSECURITY_DESCRIPTOR_CONTROL Control
,
443 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
446 /* Read current revision, even if invalid */
447 *Revision
= Sd
->Revision
;
449 /* Fail on invalid revision */
450 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
452 /* Read current control */
453 *Control
= Sd
->Control
;
456 return STATUS_SUCCESS
;
464 RtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
465 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest
,
466 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet
)
468 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
470 /* Check for invalid bits */
471 if ((ControlBitsOfInterest
& ~(SE_DACL_UNTRUSTED
|
473 SE_DACL_AUTO_INHERIT_REQ
|
474 SE_SACL_AUTO_INHERIT_REQ
|
475 SE_DACL_AUTO_INHERITED
|
476 SE_SACL_AUTO_INHERITED
|
478 SE_SACL_PROTECTED
)) ||
479 (ControlBitsToSet
& ~ControlBitsOfInterest
))
482 return STATUS_INVALID_PARAMETER
;
485 /* Zero the 'bits of interest' */
486 Sd
->Control
&= ~ControlBitsOfInterest
;
488 /* Set the 'bits to set' */
489 Sd
->Control
|= (ControlBitsToSet
& ControlBitsOfInterest
);
492 return STATUS_SUCCESS
;
500 RtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
501 OUT PUCHAR RMControl
)
503 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
506 /* Check if there's no valid RM control */
507 if (!(Sd
->Control
& SE_RM_CONTROL_VALID
))
509 /* Fail and return nothing */
514 /* Return it, ironically the member is "should be zero" */
515 *RMControl
= Sd
->Sbz1
;
524 RtlSetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
527 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
530 /* RM Control is being cleared or set */
534 Sd
->Control
&= ~SE_RM_CONTROL_VALID
;
540 Sd
->Control
|= SE_RM_CONTROL_VALID
;
541 Sd
->Sbz1
= *RMControl
;
550 RtlSetAttributesSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
551 IN SECURITY_DESCRIPTOR_CONTROL Control
,
554 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
557 /* Always return revision, even if invalid */
558 *Revision
= Sd
->Revision
;
560 /* Fail on invalid revision */
561 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) return STATUS_UNKNOWN_REVISION
;
563 /* Mask out flags which are not attributes */
564 Control
&= SE_DACL_UNTRUSTED
|
566 SE_DACL_AUTO_INHERIT_REQ
|
567 SE_SACL_AUTO_INHERIT_REQ
|
568 SE_DACL_AUTO_INHERITED
|
569 SE_SACL_AUTO_INHERITED
|
573 /* Call the newer API */
574 return RtlSetControlSecurityDescriptor(SecurityDescriptor
, Control
, Control
);
582 RtlCopySecurityDescriptor(IN PSECURITY_DESCRIPTOR pSourceSecurityDescriptor
,
583 OUT PSECURITY_DESCRIPTOR
*pDestinationSecurityDescriptor
)
587 DWORD OwnerLength
, GroupLength
, DaclLength
, SaclLength
, TotalLength
;
588 PISECURITY_DESCRIPTOR Sd
= pSourceSecurityDescriptor
;
590 /* Get all the components */
591 RtlpQuerySecurityDescriptor(Sd
,
601 /* Add up their lengths */
602 TotalLength
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
) +
608 /* Allocate a copy */
609 *pDestinationSecurityDescriptor
= RtlAllocateHeap(RtlGetProcessHeap(),
612 if (*pDestinationSecurityDescriptor
== NULL
) return STATUS_NO_MEMORY
;
614 /* Copy the old in the new */
615 RtlCopyMemory(*pDestinationSecurityDescriptor
, Sd
, TotalLength
);
618 return STATUS_SUCCESS
;
626 RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor
,
627 IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor
,
628 IN PULONG BufferLength
)
630 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)AbsoluteSecurityDescriptor
;
633 /* Can't already be relative */
634 if (Sd
->Control
& SE_SELF_RELATIVE
) return STATUS_BAD_DESCRIPTOR_FORMAT
;
636 /* Call the other API */
637 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor
,
638 SelfRelativeSecurityDescriptor
,
647 RtlMakeSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSD
,
648 OUT PSECURITY_DESCRIPTOR SelfRelativeSD
,
649 IN OUT PULONG BufferLength
)
653 ULONG OwnerLength
, GroupLength
, SaclLength
, DaclLength
, TotalLength
;
655 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)AbsoluteSD
;
656 PISECURITY_DESCRIPTOR_RELATIVE RelSd
= (PISECURITY_DESCRIPTOR_RELATIVE
)SelfRelativeSD
;
659 /* Query all components */
660 RtlpQuerySecurityDescriptor(Sd
,
670 /* Calculate final length */
671 TotalLength
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
) +
677 /* Is there enough space? */
678 if (*BufferLength
< TotalLength
)
680 /* Nope, return how much is needed */
681 *BufferLength
= TotalLength
;
682 return STATUS_BUFFER_TOO_SMALL
;
686 RtlZeroMemory(RelSd
, TotalLength
);
688 /* Copy the header fields */
691 FIELD_OFFSET(SECURITY_DESCRIPTOR_RELATIVE
, Owner
));
693 /* Set the current copy pointer */
694 Current
= (ULONG_PTR
)(RelSd
+ 1);
696 /* Is there a SACL? */
700 RtlCopyMemory((PVOID
)Current
, Sacl
, SaclLength
);
701 RelSd
->Sacl
= (ULONG_PTR
)Current
- (ULONG_PTR
)RelSd
;
702 Current
+= SaclLength
;
705 /* Is there a DACL? */
709 RtlCopyMemory((PVOID
)Current
, Dacl
, DaclLength
);
710 RelSd
->Dacl
= (ULONG_PTR
)Current
- (ULONG_PTR
)RelSd
;
711 Current
+= DaclLength
;
714 /* Is there an owner? */
718 RtlCopyMemory((PVOID
)Current
, Owner
, OwnerLength
);
719 RelSd
->Owner
= (ULONG_PTR
)Current
- (ULONG_PTR
)RelSd
;
720 Current
+= OwnerLength
;
723 /* Is there a group? */
727 RtlCopyMemory((PVOID
)Current
, Group
, GroupLength
);
728 RelSd
->Group
= (ULONG_PTR
)Current
- (ULONG_PTR
)RelSd
;
731 /* Mark it as relative */
732 RelSd
->Control
|= SE_SELF_RELATIVE
;
735 return STATUS_SUCCESS
;
743 RtlSelfRelativeToAbsoluteSD(IN PSECURITY_DESCRIPTOR SelfRelativeSD
,
744 OUT PSECURITY_DESCRIPTOR AbsoluteSD
,
745 IN PULONG AbsoluteSDSize
,
752 IN PSID PrimaryGroup
,
753 IN PULONG PrimaryGroupSize
)
755 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)AbsoluteSD
;
756 PISECURITY_DESCRIPTOR RelSd
= (PISECURITY_DESCRIPTOR
)SelfRelativeSD
;
757 ULONG OwnerLength
, GroupLength
, DaclLength
, SaclLength
;
762 /* Must be relative, otherwiise fail */
763 if (!(RelSd
->Control
& SE_SELF_RELATIVE
)) return STATUS_BAD_DESCRIPTOR_FORMAT
;
765 /* Get all the components */
766 RtlpQuerySecurityDescriptor(RelSd
,
776 /* Fail if there's not enough space */
778 (sizeof(SECURITY_DESCRIPTOR
) > *AbsoluteSDSize
) ||
779 (OwnerLength
> *OwnerSize
) ||
780 (GroupLength
> *PrimaryGroupSize
) ||
781 (DaclLength
> *DaclSize
) ||
782 (SaclLength
> *SaclSize
))
784 /* Return how much space is needed for each components */
785 *AbsoluteSDSize
= sizeof(SECURITY_DESCRIPTOR
);
786 *OwnerSize
= OwnerLength
;
787 *PrimaryGroupSize
= GroupLength
;
788 *DaclSize
= DaclLength
;
789 *SaclSize
= SaclLength
;
790 return STATUS_BUFFER_TOO_SMALL
;
793 /* Copy the header fields */
794 RtlMoveMemory(Sd
, RelSd
, sizeof(SECURITY_DESCRIPTOR_RELATIVE
));
796 /* Wipe out the pointers and the relative flag */
801 Sd
->Control
&= ~SE_SELF_RELATIVE
;
803 /* Is there an owner? */
807 RtlMoveMemory(Owner
, pOwner
, RtlLengthSid(pOwner
));
811 /* Is there a group? */
815 RtlMoveMemory(PrimaryGroup
, pGroup
, RtlLengthSid(pGroup
));
816 Sd
->Group
= PrimaryGroup
;
819 /* Is there a DACL? */
823 RtlMoveMemory(Dacl
, pDacl
, pDacl
->AclSize
);
827 /* Is there a SACL? */
831 RtlMoveMemory(Sacl
, pSacl
, pSacl
->AclSize
);
836 return STATUS_SUCCESS
;
844 RtlSelfRelativeToAbsoluteSD2(IN OUT PSECURITY_DESCRIPTOR SelfRelativeSD
,
845 OUT PULONG BufferSize
)
847 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SelfRelativeSD
;
848 PISECURITY_DESCRIPTOR_RELATIVE RelSd
= (PISECURITY_DESCRIPTOR_RELATIVE
)SelfRelativeSD
;
849 PVOID DataStart
, DataEnd
;
851 ULONG DataSize
, OwnerLength
, GroupLength
, DaclLength
, SaclLength
;
857 if (!RelSd
) return STATUS_INVALID_PARAMETER_1
;
859 /* Need to know how much space we have */
860 if (!BufferSize
) return STATUS_INVALID_PARAMETER_2
;
862 /* Input must be relative */
863 if (!(RelSd
->Control
& SE_SELF_RELATIVE
)) return STATUS_BAD_DESCRIPTOR_FORMAT
;
865 /* Query all the component sizes */
866 RtlpQuerySecurityDescriptor(Sd
,
877 * Check if there's a difference in structure layout between relatiev and
878 * absolute descriptors. On 32-bit, there won't be, since an offset is the
879 * same size as a pointer (32-bit), but on 64-bit, the offsets remain 32-bit
880 * as they are not SIZE_T, but ULONG, while the pointers now become 64-bit
881 * and thus the structure is different */
882 MoveDelta
= sizeof(SECURITY_DESCRIPTOR
) - sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
885 /* So on 32-bit, simply clear the flag... */
886 Sd
->Control
&= ~SE_SELF_RELATIVE
;
888 /* Ensure we're *really* on 32-bit */
889 ASSERT(sizeof(Sd
->Owner
) == sizeof(RelSd
->Owner
));
890 ASSERT(sizeof(Sd
->Group
) == sizeof(RelSd
->Group
));
891 ASSERT(sizeof(Sd
->Sacl
) == sizeof(RelSd
->Sacl
));
892 ASSERT(sizeof(Sd
->Dacl
) == sizeof(RelSd
->Dacl
));
894 /* And simply set pointers where there used to be offsets */
899 return STATUS_SUCCESS
;
903 * Calculate the start and end of the data area, we simply just move the
904 * data by the difference between the size of the relative and absolute
905 * security descriptor structure
908 DataEnd
= (PVOID
)((ULONG_PTR
)pOwner
+ OwnerLength
);
910 /* Is there a group? */
913 /* Is the group higher than where we started? */
914 if (((ULONG_PTR
)pGroup
< (ULONG_PTR
)DataStart
) || !DataStart
)
916 /* Update the start pointer */
920 /* Is the group beyond where we ended? */
921 if (((ULONG_PTR
)pGroup
+ GroupLength
> (ULONG_PTR
)DataEnd
) || !DataEnd
)
923 /* Update the end pointer */
924 DataEnd
= (PVOID
)((ULONG_PTR
)pGroup
+ GroupLength
);
928 /* Is there a DACL? */
931 /* Is the DACL higher than where we started? */
932 if (((ULONG_PTR
)pDacl
< (ULONG_PTR
)DataStart
) || !DataStart
)
934 /* Update the start pointer */
938 /* Is the DACL beyond where we ended? */
939 if (((ULONG_PTR
)pDacl
+ DaclLength
> (ULONG_PTR
)DataEnd
) || !DataEnd
)
941 /* Update the end pointer */
942 DataEnd
= (PVOID
)((ULONG_PTR
)pDacl
+ DaclLength
);
946 /* Is there a SACL? */
949 /* Is the SACL higher than where we started? */
950 if (((ULONG_PTR
)pSacl
< (ULONG_PTR
)DataStart
) || !DataStart
)
952 /* Update the start pointer */
956 /* Is the SACL beyond where we ended? */
957 if (((ULONG_PTR
)pSacl
+ SaclLength
> (ULONG_PTR
)DataEnd
) || !DataEnd
)
959 /* Update the end pointer */
960 DataEnd
= (PVOID
)((ULONG_PTR
)pSacl
+ SaclLength
);
965 ASSERT((ULONG_PTR
)DataEnd
>= (ULONG_PTR
)DataStart
);
967 /* Now compute the difference between relative and absolute */
968 DataSize
= (ULONG
)((ULONG_PTR
)DataEnd
- (ULONG_PTR
)DataStart
);
970 /* Is the new buffer large enough for this difference? */
971 if (*BufferSize
< sizeof(SECURITY_DESCRIPTOR
) + DataSize
)
974 *BufferSize
= sizeof(SECURITY_DESCRIPTOR
) + DataSize
;
975 return STATUS_BUFFER_TOO_SMALL
;
978 /* Is there anything actually to copy? */
982 * There must be at least one SID or ACL in the security descriptor!
983 * Also the data area must be located somewhere after the end of the
984 * SECURITY_DESCRIPTOR_RELATIVE structure
986 ASSERT(DataStart
!= NULL
);
987 ASSERT((ULONG_PTR
)DataStart
>= (ULONG_PTR
)(RelSd
+ 1));
989 /* It's time to move the data */
990 RtlMoveMemory((PVOID
)(Sd
+ 1),
995 /* Is there an owner? */
998 /* Set the pointer to the relative position */
999 Sd
->Owner
= (PSID
)((LONG_PTR
)pOwner
+ MoveDelta
);
1003 /* No owner, clear the pointer */
1007 /* Is there a group */
1010 /* Set the pointer to the relative position */
1011 Sd
->Group
= (PSID
)((LONG_PTR
)pGroup
+ MoveDelta
);
1015 /* No group, clear the pointer */
1019 /* Is there a SACL? */
1022 /* Set the pointer to the relative position */
1023 Sd
->Sacl
= (PACL
)((LONG_PTR
)pSacl
+ MoveDelta
);
1027 /* No SACL, clear the pointer */
1031 /* Is there a DACL? */
1034 /* Set the pointer to the relative position */
1035 Sd
->Dacl
= (PACL
)((LONG_PTR
)pDacl
+ MoveDelta
);
1039 /* No DACL, clear the pointer */
1043 /* Clear the self-relative flag */
1044 Sd
->Control
&= ~SE_SELF_RELATIVE
;
1047 return STATUS_SUCCESS
;
1055 RtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
1057 PISECURITY_DESCRIPTOR Sd
= (PISECURITY_DESCRIPTOR
)SecurityDescriptor
;
1064 /* Fail on bad revisions */
1065 if (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) _SEH2_YIELD(return FALSE
);
1067 /* Owner SID must be valid if present */
1068 Owner
= SepGetOwnerFromDescriptor(Sd
);
1069 if ((Owner
) && (!RtlValidSid(Owner
))) _SEH2_YIELD(return FALSE
);
1071 /* Group SID must be valid if present */
1072 Group
= SepGetGroupFromDescriptor(Sd
);
1073 if ((Group
) && (!RtlValidSid(Group
))) _SEH2_YIELD(return FALSE
);
1075 /* DACL must be valid if present */
1076 Dacl
= SepGetDaclFromDescriptor(Sd
);
1077 if ((Dacl
) && (!RtlValidAcl(Dacl
))) _SEH2_YIELD(return FALSE
);
1079 /* SACL must be valid if present */
1080 Sacl
= SepGetSaclFromDescriptor(Sd
);
1081 if ((Sacl
) && (!RtlValidAcl(Sacl
))) _SEH2_YIELD(return FALSE
);
1083 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1085 /* Access fault, bail out */
1086 _SEH2_YIELD(return FALSE
);
1099 RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInput
,
1100 IN ULONG SecurityDescriptorLength
,
1101 IN SECURITY_INFORMATION RequiredInformation
)
1103 PISECURITY_DESCRIPTOR_RELATIVE Sd
= (PISECURITY_DESCRIPTOR_RELATIVE
)SecurityDescriptorInput
;
1109 /* Note that Windows allows no DACL/SACL even if RequiredInfo wants it */
1111 /* Do we have enough space, is the revision vaild, and is this SD relative? */
1112 if ((SecurityDescriptorLength
< sizeof(SECURITY_DESCRIPTOR_RELATIVE
)) ||
1113 (Sd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
) ||
1114 !(Sd
->Control
& SE_SELF_RELATIVE
))
1116 /* Nope, bail out */
1120 /* Is there an owner? */
1123 /* Try to access it */
1124 if (!RtlpValidateSDOffsetAndSize(Sd
->Owner
,
1125 SecurityDescriptorLength
,
1129 /* It's beyond the buffer, fail */
1133 /* Read the owner, check if it's valid and if the buffer contains it */
1134 Owner
= (PSID
)((ULONG_PTR
)Sd
->Owner
+ (ULONG_PTR
)Sd
);
1135 if (!RtlValidSid(Owner
) || (Length
< RtlLengthSid(Owner
))) return FALSE
;
1137 else if (RequiredInformation
& OWNER_SECURITY_INFORMATION
)
1139 /* No owner but the caller expects one, fail */
1143 /* Is there a group? */
1146 /* Try to access it */
1147 if (!RtlpValidateSDOffsetAndSize(Sd
->Group
,
1148 SecurityDescriptorLength
,
1152 /* It's beyond the buffer, fail */
1156 /* Read the group, check if it's valid and if the buffer contains it */
1157 Group
= (PSID
)((ULONG_PTR
)Sd
->Group
+ (ULONG_PTR
)Sd
);
1158 if (!RtlValidSid(Group
) || (Length
< RtlLengthSid(Group
))) return FALSE
;
1160 else if (RequiredInformation
& GROUP_SECURITY_INFORMATION
)
1162 /* No group, but the caller expects one, fail */
1166 /* Is there a DACL? */
1167 if ((Sd
->Control
& SE_DACL_PRESENT
) == SE_DACL_PRESENT
)
1169 /* Try to access it */
1170 if (!RtlpValidateSDOffsetAndSize(Sd
->Dacl
,
1171 SecurityDescriptorLength
,
1175 /* It's beyond the buffer, fail */
1179 /* Read the DACL, check if it's valid and if the buffer contains it */
1180 Dacl
= (PSID
)((ULONG_PTR
)Sd
->Dacl
+ (ULONG_PTR
)Sd
);
1181 if (!(RtlValidAcl(Dacl
)) || (Length
< Dacl
->AclSize
)) return FALSE
;
1184 /* Is there a SACL? */
1185 if ((Sd
->Control
& SE_SACL_PRESENT
) == SE_SACL_PRESENT
)
1187 /* Try to access it */
1188 if (!RtlpValidateSDOffsetAndSize(Sd
->Sacl
,
1189 SecurityDescriptorLength
,
1193 /* It's beyond the buffer, fail */
1197 /* Read the SACL, check if it's valid and if the buffer contains it */
1198 Sacl
= (PSID
)((ULONG_PTR
)Sd
->Sacl
+ (ULONG_PTR
)Sd
);
1199 if (!(RtlValidAcl(Sacl
)) || (Length
< Sacl
->AclSize
)) return FALSE
;