2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/sd.c
5 * PURPOSE: Security manager
7 * PROGRAMMERS: David Welch <welch@cwcom.net>
10 /* INCLUDES *******************************************************************/
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, SepInitSDs)
20 /* GLOBALS ********************************************************************/
22 PSECURITY_DESCRIPTOR SePublicDefaultSd
= NULL
;
23 PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd
= NULL
;
24 PSECURITY_DESCRIPTOR SePublicOpenSd
= NULL
;
25 PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd
= NULL
;
26 PSECURITY_DESCRIPTOR SeSystemDefaultSd
= NULL
;
27 PSECURITY_DESCRIPTOR SeUnrestrictedSd
= NULL
;
29 /* PRIVATE FUNCTIONS **********************************************************/
36 /* Create PublicDefaultSd */
37 SePublicDefaultSd
= ExAllocatePoolWithTag(PagedPool
,
38 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
39 if (SePublicDefaultSd
== NULL
)
42 RtlCreateSecurityDescriptor(SePublicDefaultSd
,
43 SECURITY_DESCRIPTOR_REVISION
);
44 RtlSetDaclSecurityDescriptor(SePublicDefaultSd
,
49 /* Create PublicDefaultUnrestrictedSd */
50 SePublicDefaultUnrestrictedSd
= ExAllocatePoolWithTag(PagedPool
,
51 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
52 if (SePublicDefaultUnrestrictedSd
== NULL
)
55 RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd
,
56 SECURITY_DESCRIPTOR_REVISION
);
57 RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd
,
59 SePublicDefaultUnrestrictedDacl
,
62 /* Create PublicOpenSd */
63 SePublicOpenSd
= ExAllocatePoolWithTag(PagedPool
,
64 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
65 if (SePublicOpenSd
== NULL
)
68 RtlCreateSecurityDescriptor(SePublicOpenSd
,
69 SECURITY_DESCRIPTOR_REVISION
);
70 RtlSetDaclSecurityDescriptor(SePublicOpenSd
,
75 /* Create PublicOpenUnrestrictedSd */
76 SePublicOpenUnrestrictedSd
= ExAllocatePoolWithTag(PagedPool
,
77 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
78 if (SePublicOpenUnrestrictedSd
== NULL
)
81 RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd
,
82 SECURITY_DESCRIPTOR_REVISION
);
83 RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd
,
85 SePublicOpenUnrestrictedDacl
,
88 /* Create SystemDefaultSd */
89 SeSystemDefaultSd
= ExAllocatePoolWithTag(PagedPool
,
90 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
91 if (SeSystemDefaultSd
== NULL
)
94 RtlCreateSecurityDescriptor(SeSystemDefaultSd
,
95 SECURITY_DESCRIPTOR_REVISION
);
96 RtlSetDaclSecurityDescriptor(SeSystemDefaultSd
,
101 /* Create UnrestrictedSd */
102 SeUnrestrictedSd
= ExAllocatePoolWithTag(PagedPool
,
103 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
104 if (SeUnrestrictedSd
== NULL
)
107 RtlCreateSecurityDescriptor(SeUnrestrictedSd
,
108 SECURITY_DESCRIPTOR_REVISION
);
109 RtlSetDaclSecurityDescriptor(SeUnrestrictedSd
,
119 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation
,
120 PISECURITY_DESCRIPTOR SecurityDescriptor
,
127 PISECURITY_DESCRIPTOR_RELATIVE SdRel
= (PISECURITY_DESCRIPTOR_RELATIVE
)SecurityDescriptor
;
129 DPRINT("SeSetWorldSecurityDescriptor() called\n");
131 if (SecurityInformation
== 0)
133 return STATUS_ACCESS_DENIED
;
136 /* calculate the minimum size of the buffer */
137 SidSize
= RtlLengthSid(SeWorldSid
);
138 SdSize
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
139 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
141 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
143 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
145 SdSize
+= sizeof(ACL
) + sizeof(ACE
) + SidSize
;
148 if (*BufferLength
< SdSize
)
150 *BufferLength
= SdSize
;
151 return STATUS_BUFFER_TOO_SMALL
;
154 *BufferLength
= SdSize
;
156 Status
= RtlCreateSecurityDescriptorRelative(SdRel
,
157 SECURITY_DESCRIPTOR_REVISION
);
158 if (!NT_SUCCESS(Status
))
163 Current
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
165 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
167 RtlCopyMemory((PUCHAR
)SdRel
+ Current
, SeWorldSid
, SidSize
);
168 SdRel
->Owner
= Current
;
172 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
174 RtlCopyMemory((PUCHAR
)SdRel
+ Current
, SeWorldSid
, SidSize
);
175 SdRel
->Group
= Current
;
179 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
181 PACL Dacl
= (PACL
)((PUCHAR
)SdRel
+ Current
);
182 SdRel
->Control
|= SE_DACL_PRESENT
;
184 Status
= RtlCreateAcl(Dacl
,
185 sizeof(ACL
) + sizeof(ACE
) + SidSize
,
187 if (!NT_SUCCESS(Status
))
190 Status
= RtlAddAccessAllowedAce(Dacl
,
194 if (!NT_SUCCESS(Status
))
197 SdRel
->Dacl
= Current
;
200 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
202 /* FIXME - SdRel->Control |= SE_SACL_PRESENT; */
205 return STATUS_SUCCESS
;
211 SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
212 IN KPROCESSOR_MODE AccessMode
,
213 IN POOL_TYPE PoolType
,
214 IN BOOLEAN CaptureIfKernel
,
215 OUT PSECURITY_QUALITY_OF_SERVICE
*CapturedSecurityQualityOfService
,
216 OUT PBOOLEAN Present
)
218 PSECURITY_QUALITY_OF_SERVICE CapturedQos
;
219 NTSTATUS Status
= STATUS_SUCCESS
;
223 ASSERT(CapturedSecurityQualityOfService
);
226 if (ObjectAttributes
!= NULL
)
228 if (AccessMode
!= KernelMode
)
230 SECURITY_QUALITY_OF_SERVICE SafeQos
;
234 ProbeForRead(ObjectAttributes
,
235 sizeof(OBJECT_ATTRIBUTES
),
237 if (ObjectAttributes
->Length
== sizeof(OBJECT_ATTRIBUTES
))
239 if (ObjectAttributes
->SecurityQualityOfService
!= NULL
)
241 ProbeForRead(ObjectAttributes
->SecurityQualityOfService
,
242 sizeof(SECURITY_QUALITY_OF_SERVICE
),
245 if (((PSECURITY_QUALITY_OF_SERVICE
)ObjectAttributes
->SecurityQualityOfService
)->Length
==
246 sizeof(SECURITY_QUALITY_OF_SERVICE
))
249 * Don't allocate memory here because ExAllocate should bugcheck
250 * the system if it's buggy, SEH would catch that! So make a local
251 * copy of the qos structure.
253 RtlCopyMemory(&SafeQos
,
254 ObjectAttributes
->SecurityQualityOfService
,
255 sizeof(SECURITY_QUALITY_OF_SERVICE
));
260 Status
= STATUS_INVALID_PARAMETER
;
265 *CapturedSecurityQualityOfService
= NULL
;
271 Status
= STATUS_INVALID_PARAMETER
;
274 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
276 Status
= _SEH2_GetExceptionCode();
280 if (NT_SUCCESS(Status
))
284 CapturedQos
= ExAllocatePool(PoolType
,
285 sizeof(SECURITY_QUALITY_OF_SERVICE
));
286 if (CapturedQos
!= NULL
)
288 RtlCopyMemory(CapturedQos
,
290 sizeof(SECURITY_QUALITY_OF_SERVICE
));
291 *CapturedSecurityQualityOfService
= CapturedQos
;
295 Status
= STATUS_INSUFFICIENT_RESOURCES
;
300 *CapturedSecurityQualityOfService
= NULL
;
306 if (ObjectAttributes
->Length
== sizeof(OBJECT_ATTRIBUTES
))
310 if (ObjectAttributes
->SecurityQualityOfService
!= NULL
)
312 if (((PSECURITY_QUALITY_OF_SERVICE
)ObjectAttributes
->SecurityQualityOfService
)->Length
==
313 sizeof(SECURITY_QUALITY_OF_SERVICE
))
315 CapturedQos
= ExAllocatePool(PoolType
,
316 sizeof(SECURITY_QUALITY_OF_SERVICE
));
317 if (CapturedQos
!= NULL
)
319 RtlCopyMemory(CapturedQos
,
320 ObjectAttributes
->SecurityQualityOfService
,
321 sizeof(SECURITY_QUALITY_OF_SERVICE
));
322 *CapturedSecurityQualityOfService
= CapturedQos
;
327 Status
= STATUS_INSUFFICIENT_RESOURCES
;
332 Status
= STATUS_INVALID_PARAMETER
;
337 *CapturedSecurityQualityOfService
= NULL
;
343 *CapturedSecurityQualityOfService
= (PSECURITY_QUALITY_OF_SERVICE
)ObjectAttributes
->SecurityQualityOfService
;
344 *Present
= (ObjectAttributes
->SecurityQualityOfService
!= NULL
);
349 Status
= STATUS_INVALID_PARAMETER
;
355 *CapturedSecurityQualityOfService
= NULL
;
365 SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL
,
366 IN KPROCESSOR_MODE AccessMode
,
367 IN BOOLEAN CaptureIfKernel
)
371 if (CapturedSecurityQualityOfService
!= NULL
&&
372 (AccessMode
!= KernelMode
|| CaptureIfKernel
))
374 ExFreePool(CapturedSecurityQualityOfService
);
378 /* PUBLIC FUNCTIONS ***********************************************************/
385 KPROCESSOR_MODE ProcessorMode
)
395 if (ProcessorMode
!= KernelMode
)
397 /* Securely access the buffers! */
398 *OutSAC
= ProbeForReadUchar(&Sid
->SubAuthorityCount
);
399 Size
= RtlLengthRequiredSid(*OutSAC
);
400 ProbeForRead(Sid
, Size
, sizeof(ULONG
));
404 *OutSAC
= Sid
->SubAuthorityCount
;
405 Size
= RtlLengthRequiredSid(*OutSAC
);
415 KPROCESSOR_MODE ProcessorMode
)
421 if (ProcessorMode
== KernelMode
) return Acl
->AclSize
;
423 /* Probe the buffers! */
424 Size
= ProbeForReadUshort(&Acl
->AclSize
);
425 ProbeForRead(Acl
, Size
, sizeof(ULONG
));
432 SeCaptureSecurityDescriptor(
433 IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor
,
434 IN KPROCESSOR_MODE CurrentMode
,
435 IN POOL_TYPE PoolType
,
436 IN BOOLEAN CaptureIfKernel
,
437 OUT PSECURITY_DESCRIPTOR
*CapturedSecurityDescriptor
)
439 PISECURITY_DESCRIPTOR OriginalDescriptor
= _OriginalSecurityDescriptor
;
440 SECURITY_DESCRIPTOR DescriptorCopy
;
441 PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor
;
442 ULONG OwnerSAC
= 0, GroupSAC
= 0;
443 ULONG OwnerSize
= 0, GroupSize
= 0;
444 ULONG SaclSize
= 0, DaclSize
= 0;
445 ULONG DescriptorSize
= 0;
448 if (!OriginalDescriptor
)
450 /* Nothing to do... */
451 *CapturedSecurityDescriptor
= NULL
;
452 return STATUS_SUCCESS
;
456 if (CurrentMode
== KernelMode
&& !CaptureIfKernel
)
458 /* Check descriptor version */
459 if (OriginalDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
461 return STATUS_UNKNOWN_REVISION
;
464 *CapturedSecurityDescriptor
= _OriginalSecurityDescriptor
;
465 return STATUS_SUCCESS
;
470 if (CurrentMode
!= KernelMode
)
472 ProbeForRead(OriginalDescriptor
,
473 sizeof(SECURITY_DESCRIPTOR_RELATIVE
),
477 /* Check the descriptor version */
478 if (OriginalDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
480 _SEH2_YIELD(return STATUS_UNKNOWN_REVISION
);
483 if (CurrentMode
!= KernelMode
)
485 /* Get the size of the descriptor */
486 DescriptorSize
= (OriginalDescriptor
->Control
& SE_SELF_RELATIVE
) ?
487 sizeof(SECURITY_DESCRIPTOR_RELATIVE
) : sizeof(SECURITY_DESCRIPTOR
);
489 /* Probe the entire security descriptor structure. The SIDs
490 * and ACLs will be probed and copied later though */
491 ProbeForRead(OriginalDescriptor
, DescriptorSize
, sizeof(ULONG
));
494 /* Now capture all fields and convert to an absolute descriptor */
495 DescriptorCopy
.Revision
= OriginalDescriptor
->Revision
;
496 DescriptorCopy
.Sbz1
= OriginalDescriptor
->Sbz1
;
497 DescriptorCopy
.Control
= OriginalDescriptor
->Control
& ~SE_SELF_RELATIVE
;
498 DescriptorCopy
.Owner
= SepGetOwnerFromDescriptor(OriginalDescriptor
);
499 DescriptorCopy
.Group
= SepGetGroupFromDescriptor(OriginalDescriptor
);
500 DescriptorCopy
.Sacl
= SepGetSaclFromDescriptor(OriginalDescriptor
);
501 DescriptorCopy
.Dacl
= SepGetDaclFromDescriptor(OriginalDescriptor
);
502 DescriptorSize
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
504 /* Determine owner and group sizes */
505 OwnerSize
= DetermineSIDSize(DescriptorCopy
.Owner
, &OwnerSAC
, CurrentMode
);
506 DescriptorSize
+= ROUND_UP(OwnerSize
, sizeof(ULONG
));
507 GroupSize
= DetermineSIDSize(DescriptorCopy
.Group
, &GroupSAC
, CurrentMode
);
508 DescriptorSize
+= ROUND_UP(GroupSize
, sizeof(ULONG
));
510 /* Determine the size of the ACLs */
511 if (DescriptorCopy
.Control
& SE_SACL_PRESENT
)
513 /* Get the size and probe if user mode */
514 SaclSize
= DetermineACLSize(DescriptorCopy
.Sacl
, CurrentMode
);
515 DescriptorSize
+= ROUND_UP(SaclSize
, sizeof(ULONG
));
518 if (DescriptorCopy
.Control
& SE_DACL_PRESENT
)
520 /* Get the size and probe if user mode */
521 DaclSize
= DetermineACLSize(DescriptorCopy
.Dacl
, CurrentMode
);
522 DescriptorSize
+= ROUND_UP(DaclSize
, sizeof(ULONG
));
525 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
527 _SEH2_YIELD(return _SEH2_GetExceptionCode());
532 * Allocate enough memory to store a complete copy of a self-relative
533 * security descriptor
535 NewDescriptor
= ExAllocatePoolWithTag(PoolType
,
538 if (!NewDescriptor
) return STATUS_INSUFFICIENT_RESOURCES
;
540 RtlZeroMemory(NewDescriptor
, DescriptorSize
);
541 NewDescriptor
->Revision
= DescriptorCopy
.Revision
;
542 NewDescriptor
->Sbz1
= DescriptorCopy
.Sbz1
;
543 NewDescriptor
->Control
= DescriptorCopy
.Control
| SE_SELF_RELATIVE
;
548 * Setup the offsets and copy the SIDs and ACLs to the new
549 * self-relative security descriptor. Probing the pointers is not
550 * neccessary anymore as we did that when collecting the sizes!
551 * Make sure to validate the SIDs and ACLs *again* as they could have
552 * been modified in the meanwhile!
554 Offset
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
556 if (DescriptorCopy
.Owner
)
558 if (!RtlValidSid(DescriptorCopy
.Owner
)) RtlRaiseStatus(STATUS_INVALID_SID
);
559 NewDescriptor
->Owner
= Offset
;
560 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
561 DescriptorCopy
.Owner
,
563 Offset
+= ROUND_UP(OwnerSize
, sizeof(ULONG
));
566 if (DescriptorCopy
.Group
)
568 if (!RtlValidSid(DescriptorCopy
.Group
)) RtlRaiseStatus(STATUS_INVALID_SID
);
569 NewDescriptor
->Group
= Offset
;
570 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
571 DescriptorCopy
.Group
,
573 Offset
+= ROUND_UP(GroupSize
, sizeof(ULONG
));
576 if (DescriptorCopy
.Sacl
)
578 if (!RtlValidAcl(DescriptorCopy
.Sacl
)) RtlRaiseStatus(STATUS_INVALID_ACL
);
579 NewDescriptor
->Sacl
= Offset
;
580 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
583 Offset
+= ROUND_UP(SaclSize
, sizeof(ULONG
));
586 if (DescriptorCopy
.Dacl
)
588 if (!RtlValidAcl(DescriptorCopy
.Dacl
)) RtlRaiseStatus(STATUS_INVALID_ACL
);
589 NewDescriptor
->Dacl
= Offset
;
590 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
593 Offset
+= ROUND_UP(DaclSize
, sizeof(ULONG
));
596 /* Make sure the size was correct */
597 ASSERT(Offset
== DescriptorSize
);
599 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
601 /* We failed to copy the data to the new descriptor */
602 ExFreePoolWithTag(NewDescriptor
, TAG_SD
);
603 _SEH2_YIELD(return _SEH2_GetExceptionCode());
608 * We're finally done!
609 * Copy the pointer to the captured descriptor to to the caller.
611 *CapturedSecurityDescriptor
= NewDescriptor
;
612 return STATUS_SUCCESS
;
618 _IRQL_requires_max_(PASSIVE_LEVEL
)
621 SeQuerySecurityDescriptorInfo(
622 _In_ PSECURITY_INFORMATION SecurityInformation
,
623 _Out_writes_bytes_(*Length
) PSECURITY_DESCRIPTOR SecurityDescriptor
,
624 _Inout_ PULONG Length
,
625 _Inout_ PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
)
627 PISECURITY_DESCRIPTOR ObjectSd
;
628 PISECURITY_DESCRIPTOR_RELATIVE RelSD
;
633 ULONG OwnerLength
= 0;
634 ULONG GroupLength
= 0;
635 ULONG DaclLength
= 0;
636 ULONG SaclLength
= 0;
643 RelSD
= (PISECURITY_DESCRIPTOR_RELATIVE
)SecurityDescriptor
;
645 if (*ObjectsSecurityDescriptor
== NULL
)
647 if (*Length
< sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
649 *Length
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
650 return STATUS_BUFFER_TOO_SMALL
;
653 *Length
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
654 RtlCreateSecurityDescriptorRelative(RelSD
,
655 SECURITY_DESCRIPTOR_REVISION
);
656 return STATUS_SUCCESS
;
659 ObjectSd
= *ObjectsSecurityDescriptor
;
661 /* Calculate the required security descriptor length */
662 Control
= SE_SELF_RELATIVE
;
663 if ((*SecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
664 (ObjectSd
->Owner
!= NULL
))
666 Owner
= (PSID
)((ULONG_PTR
)ObjectSd
->Owner
+ (ULONG_PTR
)ObjectSd
);
667 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
668 Control
|= (ObjectSd
->Control
& SE_OWNER_DEFAULTED
);
671 if ((*SecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
672 (ObjectSd
->Group
!= NULL
))
674 Group
= (PSID
)((ULONG_PTR
)ObjectSd
->Group
+ (ULONG_PTR
)ObjectSd
);
675 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
676 Control
|= (ObjectSd
->Control
& SE_GROUP_DEFAULTED
);
679 if ((*SecurityInformation
& DACL_SECURITY_INFORMATION
) &&
680 (ObjectSd
->Control
& SE_DACL_PRESENT
))
682 if (ObjectSd
->Dacl
!= NULL
)
684 Dacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Dacl
+ (ULONG_PTR
)ObjectSd
);
685 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
688 Control
|= (ObjectSd
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
691 if ((*SecurityInformation
& SACL_SECURITY_INFORMATION
) &&
692 (ObjectSd
->Control
& SE_SACL_PRESENT
))
694 if (ObjectSd
->Sacl
!= NULL
)
696 Sacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Sacl
+ (ULONG_PTR
)ObjectSd
);
697 SaclLength
= ROUND_UP(Sacl
->AclSize
, 4);
700 Control
|= (ObjectSd
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
703 SdLength
= OwnerLength
+ GroupLength
+ DaclLength
+
704 SaclLength
+ sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
705 if (*Length
< SdLength
)
708 return STATUS_BUFFER_TOO_SMALL
;
711 /* Build the new security descrtiptor */
712 RtlCreateSecurityDescriptorRelative(RelSD
,
713 SECURITY_DESCRIPTOR_REVISION
);
714 RelSD
->Control
= (USHORT
)Control
;
716 Current
= (ULONG_PTR
)(RelSD
+ 1);
718 if (OwnerLength
!= 0)
720 RtlCopyMemory((PVOID
)Current
,
723 RelSD
->Owner
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
724 Current
+= OwnerLength
;
727 if (GroupLength
!= 0)
729 RtlCopyMemory((PVOID
)Current
,
732 RelSD
->Group
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
733 Current
+= GroupLength
;
738 RtlCopyMemory((PVOID
)Current
,
741 RelSD
->Dacl
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
742 Current
+= DaclLength
;
747 RtlCopyMemory((PVOID
)Current
,
750 RelSD
->Sacl
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
751 Current
+= SaclLength
;
756 return STATUS_SUCCESS
;
764 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
,
765 IN KPROCESSOR_MODE CurrentMode
,
766 IN BOOLEAN CaptureIfKernelMode
)
771 * WARNING! You need to call this function with the same value for CurrentMode
772 * and CaptureIfKernelMode that you previously passed to
773 * SeCaptureSecurityDescriptor() in order to avoid memory leaks!
775 if (CapturedSecurityDescriptor
!= NULL
&&
776 (CurrentMode
!= KernelMode
||
777 (CurrentMode
== KernelMode
&& CaptureIfKernelMode
)))
779 /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
780 ExFreePoolWithTag(CapturedSecurityDescriptor
, TAG_SD
);
783 return STATUS_SUCCESS
;
789 _IRQL_requires_max_(PASSIVE_LEVEL
)
792 SeSetSecurityDescriptorInfo(
793 _In_opt_ PVOID Object
,
794 _In_ PSECURITY_INFORMATION SecurityInformation
,
795 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
796 _Inout_ PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
,
797 _In_ POOL_TYPE PoolType
,
798 _In_ PGENERIC_MAPPING GenericMapping
)
802 return SeSetSecurityDescriptorInfoEx(Object
,
805 ObjectsSecurityDescriptor
,
814 _IRQL_requires_max_(PASSIVE_LEVEL
)
817 SeSetSecurityDescriptorInfoEx(
818 _In_opt_ PVOID Object
,
819 _In_ PSECURITY_INFORMATION _SecurityInformation
,
820 _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor
,
821 _Inout_ PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
,
822 _In_ ULONG AutoInheritFlags
,
823 _In_ POOL_TYPE PoolType
,
824 _In_ PGENERIC_MAPPING GenericMapping
)
826 PISECURITY_DESCRIPTOR_RELATIVE ObjectSd
;
827 PISECURITY_DESCRIPTOR_RELATIVE NewSd
;
828 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
829 PISECURITY_DESCRIPTOR_RELATIVE RelSD
= (PISECURITY_DESCRIPTOR_RELATIVE
)SecurityDescriptor
;
834 ULONG OwnerLength
= 0;
835 ULONG GroupLength
= 0;
836 ULONG DaclLength
= 0;
837 ULONG SaclLength
= 0;
840 SECURITY_INFORMATION SecurityInformation
;
844 ObjectSd
= *ObjectsSecurityDescriptor
;
846 /* The object does not have a security descriptor. */
848 return STATUS_NO_SECURITY_ON_OBJECT
;
850 ASSERT(ObjectSd
->Control
& SE_SELF_RELATIVE
);
852 SecurityInformation
= *_SecurityInformation
;
854 /* Get owner and owner size */
855 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
857 if (SecurityDescriptor
->Owner
!= NULL
)
859 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
860 Owner
= (PSID
)((ULONG_PTR
)RelSD
->Owner
+
861 (ULONG_PTR
)SecurityDescriptor
);
863 Owner
= (PSID
)SecurityDescriptor
->Owner
;
864 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
867 Control
|= (SecurityDescriptor
->Control
& SE_OWNER_DEFAULTED
);
873 Owner
= (PSID
)((ULONG_PTR
)ObjectSd
->Owner
+ (ULONG_PTR
)ObjectSd
);
874 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
877 Control
|= (ObjectSd
->Control
& SE_OWNER_DEFAULTED
);
880 /* Get group and group size */
881 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
883 if (SecurityDescriptor
->Group
!= NULL
)
885 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
886 Group
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Group
+
887 (ULONG_PTR
)SecurityDescriptor
);
889 Group
= (PSID
)SecurityDescriptor
->Group
;
890 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
893 Control
|= (SecurityDescriptor
->Control
& SE_GROUP_DEFAULTED
);
899 Group
= (PSID
)((ULONG_PTR
)ObjectSd
->Group
+ (ULONG_PTR
)ObjectSd
);
900 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
903 Control
|= (ObjectSd
->Control
& SE_GROUP_DEFAULTED
);
906 /* Get DACL and DACL size */
907 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
909 if ((SecurityDescriptor
->Control
& SE_DACL_PRESENT
) &&
910 (SecurityDescriptor
->Dacl
!= NULL
))
912 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
913 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
->Dacl
+
914 (ULONG_PTR
)SecurityDescriptor
);
916 Dacl
= (PACL
)SecurityDescriptor
->Dacl
;
918 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
921 Control
|= (SecurityDescriptor
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
925 if ((ObjectSd
->Control
& SE_DACL_PRESENT
) && (ObjectSd
->Dacl
))
927 Dacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Dacl
+ (ULONG_PTR
)ObjectSd
);
928 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
931 Control
|= (ObjectSd
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
934 /* Get SACL and SACL size */
935 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
937 if ((SecurityDescriptor
->Control
& SE_SACL_PRESENT
) &&
938 (SecurityDescriptor
->Sacl
!= NULL
))
940 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
941 Sacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
->Sacl
+
942 (ULONG_PTR
)SecurityDescriptor
);
944 Sacl
= (PACL
)SecurityDescriptor
->Sacl
;
945 SaclLength
= ROUND_UP((ULONG
)Sacl
->AclSize
, 4);
948 Control
|= (SecurityDescriptor
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
952 if ((ObjectSd
->Control
& SE_SACL_PRESENT
) && (ObjectSd
->Sacl
))
954 Sacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Sacl
+ (ULONG_PTR
)ObjectSd
);
955 SaclLength
= ROUND_UP((ULONG
)Sacl
->AclSize
, 4);
958 Control
|= (ObjectSd
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
961 NewSd
= ExAllocatePool(NonPagedPool
,
962 sizeof(SECURITY_DESCRIPTOR_RELATIVE
) + OwnerLength
+ GroupLength
+
963 DaclLength
+ SaclLength
);
966 ObDereferenceObject(Object
);
967 return STATUS_INSUFFICIENT_RESOURCES
;
970 RtlCreateSecurityDescriptor(NewSd
,
971 SECURITY_DESCRIPTOR_REVISION1
);
973 /* We always build a self-relative descriptor */
974 NewSd
->Control
= (USHORT
)Control
| SE_SELF_RELATIVE
;
976 Current
= sizeof(SECURITY_DESCRIPTOR
);
978 if (OwnerLength
!= 0)
980 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Owner
, OwnerLength
);
981 NewSd
->Owner
= Current
;
982 Current
+= OwnerLength
;
985 if (GroupLength
!= 0)
987 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Group
, GroupLength
);
988 NewSd
->Group
= Current
;
989 Current
+= GroupLength
;
994 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Dacl
, DaclLength
);
995 NewSd
->Dacl
= Current
;
996 Current
+= DaclLength
;
1001 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Sacl
, SaclLength
);
1002 NewSd
->Sacl
= Current
;
1003 Current
+= SaclLength
;
1006 *ObjectsSecurityDescriptor
= NewSd
;
1007 return STATUS_SUCCESS
;
1015 SeValidSecurityDescriptor(IN ULONG Length
,
1016 IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
1021 PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor
= _SecurityDescriptor
;
1023 if (Length
< SECURITY_DESCRIPTOR_MIN_LENGTH
)
1025 DPRINT1("Invalid Security Descriptor revision\n");
1029 if (SecurityDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
1031 DPRINT1("Invalid Security Descriptor revision\n");
1035 if (!(SecurityDescriptor
->Control
& SE_SELF_RELATIVE
))
1037 DPRINT1("No self-relative Security Descriptor\n");
1041 SdLength
= sizeof(SECURITY_DESCRIPTOR
);
1043 /* Check Owner SID */
1044 if (SecurityDescriptor
->Owner
)
1046 DPRINT1("No Owner SID\n");
1050 if (SecurityDescriptor
->Owner
% sizeof(ULONG
))
1052 DPRINT1("Invalid Owner SID alignment\n");
1056 Sid
= (PISID
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Owner
);
1057 if (Sid
->Revision
!= SID_REVISION
)
1059 DPRINT1("Invalid Owner SID revision\n");
1063 SdLength
+= (sizeof(SID
) + (Sid
->SubAuthorityCount
- 1) * sizeof(ULONG
));
1064 if (Length
< SdLength
)
1066 DPRINT1("Invalid Owner SID size\n");
1070 /* Check Group SID */
1071 if (SecurityDescriptor
->Group
)
1073 if (SecurityDescriptor
->Group
% sizeof(ULONG
))
1075 DPRINT1("Invalid Group SID alignment\n");
1079 Sid
= (PSID
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Group
);
1080 if (Sid
->Revision
!= SID_REVISION
)
1082 DPRINT1("Invalid Group SID revision\n");
1086 SdLength
+= (sizeof(SID
) + (Sid
->SubAuthorityCount
- 1) * sizeof(ULONG
));
1087 if (Length
< SdLength
)
1089 DPRINT1("Invalid Group SID size\n");
1095 if (SecurityDescriptor
->Dacl
)
1097 if (SecurityDescriptor
->Dacl
% sizeof(ULONG
))
1099 DPRINT1("Invalid DACL alignment\n");
1103 Acl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Dacl
);
1104 if ((Acl
->AclRevision
< MIN_ACL_REVISION
) ||
1105 (Acl
->AclRevision
> MAX_ACL_REVISION
))
1107 DPRINT1("Invalid DACL revision\n");
1111 SdLength
+= Acl
->AclSize
;
1112 if (Length
< SdLength
)
1114 DPRINT1("Invalid DACL size\n");
1120 if (SecurityDescriptor
->Sacl
)
1122 if (SecurityDescriptor
->Sacl
% sizeof(ULONG
))
1124 DPRINT1("Invalid SACL alignment\n");
1128 Acl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Sacl
);
1129 if ((Acl
->AclRevision
< MIN_ACL_REVISION
) ||
1130 (Acl
->AclRevision
> MAX_ACL_REVISION
))
1132 DPRINT1("Invalid SACL revision\n");
1136 SdLength
+= Acl
->AclSize
;
1137 if (Length
< SdLength
)
1139 DPRINT1("Invalid SACL size\n");
1150 _IRQL_requires_max_(PASSIVE_LEVEL
)
1154 _Inout_ PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
1158 if (*SecurityDescriptor
!= NULL
)
1160 ExFreePoolWithTag(*SecurityDescriptor
, TAG_SD
);
1161 *SecurityDescriptor
= NULL
;
1164 return STATUS_SUCCESS
;
1171 _IRQL_requires_max_(PASSIVE_LEVEL
)
1175 _In_opt_ PSECURITY_DESCRIPTOR _ParentDescriptor
,
1176 _In_opt_ PSECURITY_DESCRIPTOR _ExplicitDescriptor
,
1177 _Out_ PSECURITY_DESCRIPTOR
*NewDescriptor
,
1178 _In_opt_ GUID
*ObjectType
,
1179 _In_ BOOLEAN IsDirectoryObject
,
1180 _In_ ULONG AutoInheritFlags
,
1181 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext
,
1182 _In_ PGENERIC_MAPPING GenericMapping
,
1183 _In_ POOL_TYPE PoolType
)
1185 PISECURITY_DESCRIPTOR ParentDescriptor
= _ParentDescriptor
;
1186 PISECURITY_DESCRIPTOR ExplicitDescriptor
= _ExplicitDescriptor
;
1187 PISECURITY_DESCRIPTOR_RELATIVE Descriptor
;
1194 SECURITY_DESCRIPTOR_CONTROL Control
= 0;
1201 DBG_UNREFERENCED_PARAMETER(ObjectType
);
1202 DBG_UNREFERENCED_PARAMETER(AutoInheritFlags
);
1203 DBG_UNREFERENCED_PARAMETER(GenericMapping
);
1204 UNREFERENCED_PARAMETER(PoolType
);
1208 *NewDescriptor
= NULL
;
1210 if (!ARGUMENT_PRESENT(SubjectContext
))
1212 return STATUS_NO_TOKEN
;
1215 /* Lock subject context */
1216 SeLockSubjectContext(SubjectContext
);
1218 if (SubjectContext
->ClientToken
!= NULL
)
1220 Token
= SubjectContext
->ClientToken
;
1224 Token
= SubjectContext
->PrimaryToken
;
1227 /* Inherit the Owner SID */
1228 if (ExplicitDescriptor
!= NULL
)
1230 DPRINT("Use explicit owner sid!\n");
1231 Owner
= SepGetOwnerFromDescriptor(ExplicitDescriptor
);
1235 DPRINT("Use token owner sid!\n");
1236 Owner
= Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
1239 OwnerLength
= RtlLengthSid(Owner
);
1240 NT_ASSERT(OwnerLength
% sizeof(ULONG
) == 0);
1242 /* Inherit the Group SID */
1243 if (ExplicitDescriptor
!= NULL
)
1245 Group
= SepGetGroupFromDescriptor(ExplicitDescriptor
);
1249 DPRINT("Use token group sid!\n");
1250 Group
= Token
->PrimaryGroup
;
1254 SeUnlockSubjectContext(SubjectContext
);
1255 return STATUS_INVALID_PRIMARY_GROUP
;
1258 GroupLength
= RtlLengthSid(Group
);
1259 NT_ASSERT(GroupLength
% sizeof(ULONG
) == 0);
1261 /* Inherit the DACL */
1262 if (ExplicitDescriptor
!= NULL
&&
1263 (ExplicitDescriptor
->Control
& SE_DACL_PRESENT
) &&
1264 !(ExplicitDescriptor
->Control
& SE_DACL_DEFAULTED
))
1266 DPRINT("Use explicit DACL!\n");
1267 Dacl
= SepGetDaclFromDescriptor(ExplicitDescriptor
);
1268 Control
|= SE_DACL_PRESENT
;
1270 else if (ParentDescriptor
!= NULL
&&
1271 (ParentDescriptor
->Control
& SE_DACL_PRESENT
))
1273 DPRINT("Use parent DACL!\n");
1274 /* FIXME: Inherit */
1275 Dacl
= SepGetDaclFromDescriptor(ParentDescriptor
);
1276 Control
|= SE_DACL_PRESENT
;
1278 else if (Token
->DefaultDacl
)
1280 DPRINT("Use token default DACL!\n");
1281 Dacl
= Token
->DefaultDacl
;
1282 Control
|= SE_DACL_PRESENT
;
1285 DaclLength
= (Dacl
!= NULL
) ? Dacl
->AclSize
: 0;
1286 NT_ASSERT(DaclLength
% sizeof(ULONG
) == 0);
1288 /* Inherit the SACL */
1289 if (ExplicitDescriptor
!= NULL
&&
1290 (ExplicitDescriptor
->Control
& SE_SACL_PRESENT
) &&
1291 !(ExplicitDescriptor
->Control
& SE_SACL_DEFAULTED
))
1293 DPRINT("Use explicit SACL!\n");
1294 Sacl
= SepGetSaclFromDescriptor(ExplicitDescriptor
);
1295 Control
|= SE_SACL_PRESENT
;
1297 else if (ParentDescriptor
!= NULL
&&
1298 (ParentDescriptor
->Control
& SE_SACL_PRESENT
))
1300 DPRINT("Use parent SACL!\n");
1301 /* FIXME: Inherit */
1302 Sacl
= SepGetSaclFromDescriptor(ParentDescriptor
);
1303 Control
|= SE_SACL_PRESENT
;
1306 SaclLength
= (Sacl
!= NULL
) ? Sacl
->AclSize
: 0;
1307 NT_ASSERT(SaclLength
% sizeof(ULONG
) == 0);
1309 /* Allocate and initialize the new security descriptor */
1310 Length
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
) +
1311 OwnerLength
+ GroupLength
+ DaclLength
+ SaclLength
;
1313 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n",
1314 sizeof(SECURITY_DESCRIPTOR
),
1320 Descriptor
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_SD
);
1321 if (Descriptor
== NULL
)
1323 DPRINT1("ExAlloctePool() failed\n");
1324 SeUnlockSubjectContext(SubjectContext
);
1325 return STATUS_INSUFFICIENT_RESOURCES
;
1328 RtlZeroMemory(Descriptor
, Length
);
1329 RtlCreateSecurityDescriptor(Descriptor
, SECURITY_DESCRIPTOR_REVISION
);
1331 Descriptor
->Control
= Control
| SE_SELF_RELATIVE
;
1333 Current
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
1335 if (SaclLength
!= 0)
1337 RtlCopyMemory((PUCHAR
)Descriptor
+ Current
, Sacl
, SaclLength
);
1338 Descriptor
->Sacl
= Current
;
1339 Current
+= SaclLength
;
1342 if (DaclLength
!= 0)
1344 RtlCopyMemory((PUCHAR
)Descriptor
+ Current
, Dacl
, DaclLength
);
1345 Descriptor
->Dacl
= Current
;
1346 Current
+= DaclLength
;
1349 if (OwnerLength
!= 0)
1351 RtlCopyMemory((PUCHAR
)Descriptor
+ Current
, Owner
, OwnerLength
);
1352 Descriptor
->Owner
= Current
;
1353 Current
+= OwnerLength
;
1354 DPRINT("Owner of %p at %x\n", Descriptor
, Descriptor
->Owner
);
1358 DPRINT("Owner of %p is zero length\n", Descriptor
);
1361 if (GroupLength
!= 0)
1363 RtlCopyMemory((PUCHAR
)Descriptor
+ Current
, Group
, GroupLength
);
1364 Descriptor
->Group
= Current
;
1367 /* Unlock subject context */
1368 SeUnlockSubjectContext(SubjectContext
);
1370 *NewDescriptor
= Descriptor
;
1372 DPRINT("Descriptor %p\n", Descriptor
);
1373 ASSERT(RtlLengthSecurityDescriptor(Descriptor
));
1375 return STATUS_SUCCESS
;
1381 _IRQL_requires_max_(PASSIVE_LEVEL
)
1385 _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor
,
1386 _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor
,
1387 _Out_ PSECURITY_DESCRIPTOR
*NewDescriptor
,
1388 _In_ BOOLEAN IsDirectoryObject
,
1389 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext
,
1390 _In_ PGENERIC_MAPPING GenericMapping
,
1391 _In_ POOL_TYPE PoolType
)
1395 return SeAssignSecurityEx(ParentDescriptor
,