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
= ExAllocatePoolWithTag(PoolType
,
285 sizeof(SECURITY_QUALITY_OF_SERVICE
),
287 if (CapturedQos
!= NULL
)
289 RtlCopyMemory(CapturedQos
,
291 sizeof(SECURITY_QUALITY_OF_SERVICE
));
292 *CapturedSecurityQualityOfService
= CapturedQos
;
296 Status
= STATUS_INSUFFICIENT_RESOURCES
;
301 *CapturedSecurityQualityOfService
= NULL
;
307 if (ObjectAttributes
->Length
== sizeof(OBJECT_ATTRIBUTES
))
311 if (ObjectAttributes
->SecurityQualityOfService
!= NULL
)
313 if (((PSECURITY_QUALITY_OF_SERVICE
)ObjectAttributes
->SecurityQualityOfService
)->Length
==
314 sizeof(SECURITY_QUALITY_OF_SERVICE
))
316 CapturedQos
= ExAllocatePoolWithTag(PoolType
,
317 sizeof(SECURITY_QUALITY_OF_SERVICE
),
319 if (CapturedQos
!= NULL
)
321 RtlCopyMemory(CapturedQos
,
322 ObjectAttributes
->SecurityQualityOfService
,
323 sizeof(SECURITY_QUALITY_OF_SERVICE
));
324 *CapturedSecurityQualityOfService
= CapturedQos
;
329 Status
= STATUS_INSUFFICIENT_RESOURCES
;
334 Status
= STATUS_INVALID_PARAMETER
;
339 *CapturedSecurityQualityOfService
= NULL
;
345 *CapturedSecurityQualityOfService
= (PSECURITY_QUALITY_OF_SERVICE
)ObjectAttributes
->SecurityQualityOfService
;
346 *Present
= (ObjectAttributes
->SecurityQualityOfService
!= NULL
);
351 Status
= STATUS_INVALID_PARAMETER
;
357 *CapturedSecurityQualityOfService
= NULL
;
367 SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL
,
368 IN KPROCESSOR_MODE AccessMode
,
369 IN BOOLEAN CaptureIfKernel
)
373 if (CapturedSecurityQualityOfService
!= NULL
&&
374 (AccessMode
!= KernelMode
|| CaptureIfKernel
))
376 ExFreePoolWithTag(CapturedSecurityQualityOfService
, TAG_QOS
);
380 /* PUBLIC FUNCTIONS ***********************************************************/
387 KPROCESSOR_MODE ProcessorMode
)
397 if (ProcessorMode
!= KernelMode
)
399 /* Securely access the buffers! */
400 *OutSAC
= ProbeForReadUchar(&Sid
->SubAuthorityCount
);
401 Size
= RtlLengthRequiredSid(*OutSAC
);
402 ProbeForRead(Sid
, Size
, sizeof(ULONG
));
406 *OutSAC
= Sid
->SubAuthorityCount
;
407 Size
= RtlLengthRequiredSid(*OutSAC
);
417 KPROCESSOR_MODE ProcessorMode
)
423 if (ProcessorMode
== KernelMode
) return Acl
->AclSize
;
425 /* Probe the buffers! */
426 Size
= ProbeForReadUshort(&Acl
->AclSize
);
427 ProbeForRead(Acl
, Size
, sizeof(ULONG
));
434 SeCaptureSecurityDescriptor(
435 IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor
,
436 IN KPROCESSOR_MODE CurrentMode
,
437 IN POOL_TYPE PoolType
,
438 IN BOOLEAN CaptureIfKernel
,
439 OUT PSECURITY_DESCRIPTOR
*CapturedSecurityDescriptor
)
441 PISECURITY_DESCRIPTOR OriginalDescriptor
= _OriginalSecurityDescriptor
;
442 SECURITY_DESCRIPTOR DescriptorCopy
;
443 PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor
;
444 ULONG OwnerSAC
= 0, GroupSAC
= 0;
445 ULONG OwnerSize
= 0, GroupSize
= 0;
446 ULONG SaclSize
= 0, DaclSize
= 0;
447 ULONG DescriptorSize
= 0;
450 if (!OriginalDescriptor
)
452 /* Nothing to do... */
453 *CapturedSecurityDescriptor
= NULL
;
454 return STATUS_SUCCESS
;
458 if (CurrentMode
== KernelMode
&& !CaptureIfKernel
)
460 /* Check descriptor version */
461 if (OriginalDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
463 return STATUS_UNKNOWN_REVISION
;
466 *CapturedSecurityDescriptor
= _OriginalSecurityDescriptor
;
467 return STATUS_SUCCESS
;
472 if (CurrentMode
!= KernelMode
)
474 ProbeForRead(OriginalDescriptor
,
475 sizeof(SECURITY_DESCRIPTOR_RELATIVE
),
479 /* Check the descriptor version */
480 if (OriginalDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
482 _SEH2_YIELD(return STATUS_UNKNOWN_REVISION
);
485 if (CurrentMode
!= KernelMode
)
487 /* Get the size of the descriptor */
488 DescriptorSize
= (OriginalDescriptor
->Control
& SE_SELF_RELATIVE
) ?
489 sizeof(SECURITY_DESCRIPTOR_RELATIVE
) : sizeof(SECURITY_DESCRIPTOR
);
491 /* Probe the entire security descriptor structure. The SIDs
492 * and ACLs will be probed and copied later though */
493 ProbeForRead(OriginalDescriptor
, DescriptorSize
, sizeof(ULONG
));
496 /* Now capture all fields and convert to an absolute descriptor */
497 DescriptorCopy
.Revision
= OriginalDescriptor
->Revision
;
498 DescriptorCopy
.Sbz1
= OriginalDescriptor
->Sbz1
;
499 DescriptorCopy
.Control
= OriginalDescriptor
->Control
& ~SE_SELF_RELATIVE
;
500 DescriptorCopy
.Owner
= SepGetOwnerFromDescriptor(OriginalDescriptor
);
501 DescriptorCopy
.Group
= SepGetGroupFromDescriptor(OriginalDescriptor
);
502 DescriptorCopy
.Sacl
= SepGetSaclFromDescriptor(OriginalDescriptor
);
503 DescriptorCopy
.Dacl
= SepGetDaclFromDescriptor(OriginalDescriptor
);
504 DescriptorSize
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
506 /* Determine owner and group sizes */
507 OwnerSize
= DetermineSIDSize(DescriptorCopy
.Owner
, &OwnerSAC
, CurrentMode
);
508 DescriptorSize
+= ROUND_UP(OwnerSize
, sizeof(ULONG
));
509 GroupSize
= DetermineSIDSize(DescriptorCopy
.Group
, &GroupSAC
, CurrentMode
);
510 DescriptorSize
+= ROUND_UP(GroupSize
, sizeof(ULONG
));
512 /* Determine the size of the ACLs */
513 if (DescriptorCopy
.Control
& SE_SACL_PRESENT
)
515 /* Get the size and probe if user mode */
516 SaclSize
= DetermineACLSize(DescriptorCopy
.Sacl
, CurrentMode
);
517 DescriptorSize
+= ROUND_UP(SaclSize
, sizeof(ULONG
));
520 if (DescriptorCopy
.Control
& SE_DACL_PRESENT
)
522 /* Get the size and probe if user mode */
523 DaclSize
= DetermineACLSize(DescriptorCopy
.Dacl
, CurrentMode
);
524 DescriptorSize
+= ROUND_UP(DaclSize
, sizeof(ULONG
));
527 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
529 _SEH2_YIELD(return _SEH2_GetExceptionCode());
534 * Allocate enough memory to store a complete copy of a self-relative
535 * security descriptor
537 NewDescriptor
= ExAllocatePoolWithTag(PoolType
,
540 if (!NewDescriptor
) return STATUS_INSUFFICIENT_RESOURCES
;
542 RtlZeroMemory(NewDescriptor
, DescriptorSize
);
543 NewDescriptor
->Revision
= DescriptorCopy
.Revision
;
544 NewDescriptor
->Sbz1
= DescriptorCopy
.Sbz1
;
545 NewDescriptor
->Control
= DescriptorCopy
.Control
| SE_SELF_RELATIVE
;
550 * Setup the offsets and copy the SIDs and ACLs to the new
551 * self-relative security descriptor. Probing the pointers is not
552 * neccessary anymore as we did that when collecting the sizes!
553 * Make sure to validate the SIDs and ACLs *again* as they could have
554 * been modified in the meanwhile!
556 Offset
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
558 if (DescriptorCopy
.Owner
)
560 if (!RtlValidSid(DescriptorCopy
.Owner
)) RtlRaiseStatus(STATUS_INVALID_SID
);
561 NewDescriptor
->Owner
= Offset
;
562 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
563 DescriptorCopy
.Owner
,
565 Offset
+= ROUND_UP(OwnerSize
, sizeof(ULONG
));
568 if (DescriptorCopy
.Group
)
570 if (!RtlValidSid(DescriptorCopy
.Group
)) RtlRaiseStatus(STATUS_INVALID_SID
);
571 NewDescriptor
->Group
= Offset
;
572 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
573 DescriptorCopy
.Group
,
575 Offset
+= ROUND_UP(GroupSize
, sizeof(ULONG
));
578 if (DescriptorCopy
.Sacl
)
580 if (!RtlValidAcl(DescriptorCopy
.Sacl
)) RtlRaiseStatus(STATUS_INVALID_ACL
);
581 NewDescriptor
->Sacl
= Offset
;
582 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
585 Offset
+= ROUND_UP(SaclSize
, sizeof(ULONG
));
588 if (DescriptorCopy
.Dacl
)
590 if (!RtlValidAcl(DescriptorCopy
.Dacl
)) RtlRaiseStatus(STATUS_INVALID_ACL
);
591 NewDescriptor
->Dacl
= Offset
;
592 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
595 Offset
+= ROUND_UP(DaclSize
, sizeof(ULONG
));
598 /* Make sure the size was correct */
599 ASSERT(Offset
== DescriptorSize
);
601 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
603 /* We failed to copy the data to the new descriptor */
604 ExFreePoolWithTag(NewDescriptor
, TAG_SD
);
605 _SEH2_YIELD(return _SEH2_GetExceptionCode());
610 * We're finally done!
611 * Copy the pointer to the captured descriptor to to the caller.
613 *CapturedSecurityDescriptor
= NewDescriptor
;
614 return STATUS_SUCCESS
;
620 _IRQL_requires_max_(PASSIVE_LEVEL
)
623 SeQuerySecurityDescriptorInfo(
624 _In_ PSECURITY_INFORMATION SecurityInformation
,
625 _Out_writes_bytes_(*Length
) PSECURITY_DESCRIPTOR SecurityDescriptor
,
626 _Inout_ PULONG Length
,
627 _Inout_ PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
)
629 PISECURITY_DESCRIPTOR ObjectSd
;
630 PISECURITY_DESCRIPTOR_RELATIVE RelSD
;
635 ULONG OwnerLength
= 0;
636 ULONG GroupLength
= 0;
637 ULONG DaclLength
= 0;
638 ULONG SaclLength
= 0;
639 SECURITY_DESCRIPTOR_CONTROL Control
= 0;
645 RelSD
= (PISECURITY_DESCRIPTOR_RELATIVE
)SecurityDescriptor
;
647 if (*ObjectsSecurityDescriptor
== NULL
)
649 if (*Length
< sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
651 *Length
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
652 return STATUS_BUFFER_TOO_SMALL
;
655 *Length
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
656 RtlCreateSecurityDescriptorRelative(RelSD
,
657 SECURITY_DESCRIPTOR_REVISION
);
658 return STATUS_SUCCESS
;
661 ObjectSd
= *ObjectsSecurityDescriptor
;
663 /* Calculate the required security descriptor length */
664 Control
= SE_SELF_RELATIVE
;
665 if ((*SecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
666 (ObjectSd
->Owner
!= NULL
))
668 Owner
= (PSID
)((ULONG_PTR
)ObjectSd
->Owner
+ (ULONG_PTR
)ObjectSd
);
669 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
670 Control
|= (ObjectSd
->Control
& SE_OWNER_DEFAULTED
);
673 if ((*SecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
674 (ObjectSd
->Group
!= NULL
))
676 Group
= (PSID
)((ULONG_PTR
)ObjectSd
->Group
+ (ULONG_PTR
)ObjectSd
);
677 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
678 Control
|= (ObjectSd
->Control
& SE_GROUP_DEFAULTED
);
681 if ((*SecurityInformation
& DACL_SECURITY_INFORMATION
) &&
682 (ObjectSd
->Control
& SE_DACL_PRESENT
))
684 if (ObjectSd
->Dacl
!= NULL
)
686 Dacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Dacl
+ (ULONG_PTR
)ObjectSd
);
687 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
690 Control
|= (ObjectSd
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
693 if ((*SecurityInformation
& SACL_SECURITY_INFORMATION
) &&
694 (ObjectSd
->Control
& SE_SACL_PRESENT
))
696 if (ObjectSd
->Sacl
!= NULL
)
698 Sacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Sacl
+ (ULONG_PTR
)ObjectSd
);
699 SaclLength
= ROUND_UP(Sacl
->AclSize
, 4);
702 Control
|= (ObjectSd
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
705 SdLength
= OwnerLength
+ GroupLength
+ DaclLength
+
706 SaclLength
+ sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
707 if (*Length
< SdLength
)
710 return STATUS_BUFFER_TOO_SMALL
;
713 /* Build the new security descrtiptor */
714 RtlCreateSecurityDescriptorRelative(RelSD
,
715 SECURITY_DESCRIPTOR_REVISION
);
716 RelSD
->Control
= Control
;
718 Current
= (ULONG_PTR
)(RelSD
+ 1);
720 if (OwnerLength
!= 0)
722 RtlCopyMemory((PVOID
)Current
,
725 RelSD
->Owner
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
726 Current
+= OwnerLength
;
729 if (GroupLength
!= 0)
731 RtlCopyMemory((PVOID
)Current
,
734 RelSD
->Group
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
735 Current
+= GroupLength
;
740 RtlCopyMemory((PVOID
)Current
,
743 RelSD
->Dacl
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
744 Current
+= DaclLength
;
749 RtlCopyMemory((PVOID
)Current
,
752 RelSD
->Sacl
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
753 Current
+= SaclLength
;
758 return STATUS_SUCCESS
;
766 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
,
767 IN KPROCESSOR_MODE CurrentMode
,
768 IN BOOLEAN CaptureIfKernelMode
)
773 * WARNING! You need to call this function with the same value for CurrentMode
774 * and CaptureIfKernelMode that you previously passed to
775 * SeCaptureSecurityDescriptor() in order to avoid memory leaks!
777 if (CapturedSecurityDescriptor
!= NULL
&&
778 (CurrentMode
!= KernelMode
||
779 (CurrentMode
== KernelMode
&& CaptureIfKernelMode
)))
781 /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
782 ExFreePoolWithTag(CapturedSecurityDescriptor
, TAG_SD
);
785 return STATUS_SUCCESS
;
791 _IRQL_requires_max_(PASSIVE_LEVEL
)
794 SeSetSecurityDescriptorInfo(
795 _In_opt_ PVOID Object
,
796 _In_ PSECURITY_INFORMATION SecurityInformation
,
797 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
798 _Inout_ PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
,
799 _In_ POOL_TYPE PoolType
,
800 _In_ PGENERIC_MAPPING GenericMapping
)
804 return SeSetSecurityDescriptorInfoEx(Object
,
807 ObjectsSecurityDescriptor
,
816 _IRQL_requires_max_(PASSIVE_LEVEL
)
819 SeSetSecurityDescriptorInfoEx(
820 _In_opt_ PVOID Object
,
821 _In_ PSECURITY_INFORMATION _SecurityInformation
,
822 _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor
,
823 _Inout_ PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
,
824 _In_ ULONG AutoInheritFlags
,
825 _In_ POOL_TYPE PoolType
,
826 _In_ PGENERIC_MAPPING GenericMapping
)
828 PISECURITY_DESCRIPTOR_RELATIVE ObjectSd
;
829 PISECURITY_DESCRIPTOR_RELATIVE NewSd
;
830 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
839 SECURITY_DESCRIPTOR_CONTROL Control
= 0;
841 SECURITY_INFORMATION SecurityInformation
;
845 ObjectSd
= *ObjectsSecurityDescriptor
;
847 /* The object does not have a security descriptor. */
849 return STATUS_NO_SECURITY_ON_OBJECT
;
851 ASSERT(ObjectSd
->Control
& SE_SELF_RELATIVE
);
853 SecurityInformation
= *_SecurityInformation
;
855 /* Get owner and owner size */
856 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
858 Owner
= SepGetOwnerFromDescriptor(SecurityDescriptor
);
859 Control
|= (SecurityDescriptor
->Control
& SE_OWNER_DEFAULTED
);
863 Owner
= SepGetOwnerFromDescriptor(ObjectSd
);
864 Control
|= (ObjectSd
->Control
& SE_OWNER_DEFAULTED
);
866 OwnerLength
= Owner
? RtlLengthSid(Owner
) : 0;
867 ASSERT(OwnerLength
% sizeof(ULONG
) == 0);
869 /* Get group and group size */
870 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
872 Group
= SepGetGroupFromDescriptor(SecurityDescriptor
);
873 Control
|= (SecurityDescriptor
->Control
& SE_GROUP_DEFAULTED
);
877 Group
= SepGetGroupFromDescriptor(ObjectSd
);
878 Control
|= (ObjectSd
->Control
& SE_GROUP_DEFAULTED
);
880 GroupLength
= Group
? RtlLengthSid(Group
) : 0;
881 ASSERT(GroupLength
% sizeof(ULONG
) == 0);
883 /* Get DACL and DACL size */
884 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
886 Dacl
= SepGetDaclFromDescriptor(SecurityDescriptor
);
887 Control
|= (SecurityDescriptor
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
891 Dacl
= SepGetDaclFromDescriptor(ObjectSd
);
892 Control
|= (ObjectSd
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
894 DaclLength
= Dacl
? ROUND_UP((ULONG
)Dacl
->AclSize
, 4) : 0;
896 /* Get SACL and SACL size */
897 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
899 Sacl
= SepGetSaclFromDescriptor(SecurityDescriptor
);
900 Control
|= (SecurityDescriptor
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
904 Sacl
= SepGetSaclFromDescriptor(ObjectSd
);
905 Control
|= (ObjectSd
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
907 SaclLength
= Sacl
? ROUND_UP((ULONG
)Sacl
->AclSize
, 4) : 0;
909 NewSd
= ExAllocatePoolWithTag(NonPagedPool
,
910 sizeof(SECURITY_DESCRIPTOR_RELATIVE
) +
911 OwnerLength
+ GroupLength
+
912 DaclLength
+ SaclLength
,
916 return STATUS_INSUFFICIENT_RESOURCES
;
919 RtlCreateSecurityDescriptorRelative(NewSd
, SECURITY_DESCRIPTOR_REVISION1
);
921 Current
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
923 if (OwnerLength
!= 0)
925 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Owner
, OwnerLength
);
926 NewSd
->Owner
= Current
;
927 Current
+= OwnerLength
;
930 if (GroupLength
!= 0)
932 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Group
, GroupLength
);
933 NewSd
->Group
= Current
;
934 Current
+= GroupLength
;
939 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Dacl
, DaclLength
);
940 NewSd
->Dacl
= Current
;
941 Current
+= DaclLength
;
946 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Sacl
, SaclLength
);
947 NewSd
->Sacl
= Current
;
948 Current
+= SaclLength
;
951 *ObjectsSecurityDescriptor
= NewSd
;
952 return STATUS_SUCCESS
;
960 SeValidSecurityDescriptor(IN ULONG Length
,
961 IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
966 PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor
= _SecurityDescriptor
;
968 if (Length
< SECURITY_DESCRIPTOR_MIN_LENGTH
)
970 DPRINT1("Invalid Security Descriptor revision\n");
974 if (SecurityDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
976 DPRINT1("Invalid Security Descriptor revision\n");
980 if (!(SecurityDescriptor
->Control
& SE_SELF_RELATIVE
))
982 DPRINT1("No self-relative Security Descriptor\n");
986 SdLength
= sizeof(SECURITY_DESCRIPTOR
);
988 /* Check Owner SID */
989 if (!SecurityDescriptor
->Owner
)
991 DPRINT1("No Owner SID\n");
995 if (SecurityDescriptor
->Owner
% sizeof(ULONG
))
997 DPRINT1("Invalid Owner SID alignment\n");
1001 Sid
= (PISID
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Owner
);
1002 if (Sid
->Revision
!= SID_REVISION
)
1004 DPRINT1("Invalid Owner SID revision\n");
1008 SdLength
+= (sizeof(SID
) + (Sid
->SubAuthorityCount
- 1) * sizeof(ULONG
));
1009 if (Length
< SdLength
)
1011 DPRINT1("Invalid Owner SID size\n");
1015 /* Check Group SID */
1016 if (SecurityDescriptor
->Group
)
1018 if (SecurityDescriptor
->Group
% sizeof(ULONG
))
1020 DPRINT1("Invalid Group SID alignment\n");
1024 Sid
= (PSID
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Group
);
1025 if (Sid
->Revision
!= SID_REVISION
)
1027 DPRINT1("Invalid Group SID revision\n");
1031 SdLength
+= (sizeof(SID
) + (Sid
->SubAuthorityCount
- 1) * sizeof(ULONG
));
1032 if (Length
< SdLength
)
1034 DPRINT1("Invalid Group SID size\n");
1040 if (SecurityDescriptor
->Dacl
)
1042 if (SecurityDescriptor
->Dacl
% sizeof(ULONG
))
1044 DPRINT1("Invalid DACL alignment\n");
1048 Acl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Dacl
);
1049 if ((Acl
->AclRevision
< MIN_ACL_REVISION
) ||
1050 (Acl
->AclRevision
> MAX_ACL_REVISION
))
1052 DPRINT1("Invalid DACL revision\n");
1056 SdLength
+= Acl
->AclSize
;
1057 if (Length
< SdLength
)
1059 DPRINT1("Invalid DACL size\n");
1065 if (SecurityDescriptor
->Sacl
)
1067 if (SecurityDescriptor
->Sacl
% sizeof(ULONG
))
1069 DPRINT1("Invalid SACL alignment\n");
1073 Acl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Sacl
);
1074 if ((Acl
->AclRevision
< MIN_ACL_REVISION
) ||
1075 (Acl
->AclRevision
> MAX_ACL_REVISION
))
1077 DPRINT1("Invalid SACL revision\n");
1081 SdLength
+= Acl
->AclSize
;
1082 if (Length
< SdLength
)
1084 DPRINT1("Invalid SACL size\n");
1095 _IRQL_requires_max_(PASSIVE_LEVEL
)
1099 _Inout_ PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
1103 if (*SecurityDescriptor
!= NULL
)
1105 ExFreePoolWithTag(*SecurityDescriptor
, TAG_SD
);
1106 *SecurityDescriptor
= NULL
;
1109 return STATUS_SUCCESS
;
1115 _IRQL_requires_max_(PASSIVE_LEVEL
)
1119 _In_opt_ PSECURITY_DESCRIPTOR _ParentDescriptor
,
1120 _In_opt_ PSECURITY_DESCRIPTOR _ExplicitDescriptor
,
1121 _Out_ PSECURITY_DESCRIPTOR
*NewDescriptor
,
1122 _In_opt_ GUID
*ObjectType
,
1123 _In_ BOOLEAN IsDirectoryObject
,
1124 _In_ ULONG AutoInheritFlags
,
1125 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext
,
1126 _In_ PGENERIC_MAPPING GenericMapping
,
1127 _In_ POOL_TYPE PoolType
)
1129 PISECURITY_DESCRIPTOR ParentDescriptor
= _ParentDescriptor
;
1130 PISECURITY_DESCRIPTOR ExplicitDescriptor
= _ExplicitDescriptor
;
1131 PISECURITY_DESCRIPTOR_RELATIVE Descriptor
;
1138 SECURITY_DESCRIPTOR_CONTROL Control
= 0;
1143 BOOLEAN ExplicitPresent
;
1144 BOOLEAN ExplicitDefaulted
;
1148 BOOLEAN DaclIsInherited
;
1149 BOOLEAN SaclIsInherited
;
1150 BOOLEAN DaclPresent
;
1151 BOOLEAN SaclPresent
;
1154 DBG_UNREFERENCED_PARAMETER(ObjectType
);
1155 DBG_UNREFERENCED_PARAMETER(AutoInheritFlags
);
1156 UNREFERENCED_PARAMETER(PoolType
);
1160 *NewDescriptor
= NULL
;
1162 if (!ARGUMENT_PRESENT(SubjectContext
))
1164 return STATUS_NO_TOKEN
;
1167 /* Lock subject context */
1168 SeLockSubjectContext(SubjectContext
);
1170 if (SubjectContext
->ClientToken
!= NULL
)
1172 Token
= SubjectContext
->ClientToken
;
1176 Token
= SubjectContext
->PrimaryToken
;
1179 /* Inherit the Owner SID */
1180 if (ExplicitDescriptor
!= NULL
)
1182 DPRINT("Use explicit owner sid!\n");
1183 Owner
= SepGetOwnerFromDescriptor(ExplicitDescriptor
);
1187 if (AutoInheritFlags
& 0x20 /* FIXME: SEF_DEFAULT_OWNER_FROM_PARENT */)
1189 DPRINT("Use parent owner sid!\n");
1190 if (!ARGUMENT_PRESENT(ParentDescriptor
))
1192 SeUnlockSubjectContext(SubjectContext
);
1193 return STATUS_INVALID_OWNER
;
1196 Owner
= SepGetOwnerFromDescriptor(ParentDescriptor
);
1199 SeUnlockSubjectContext(SubjectContext
);
1200 return STATUS_INVALID_OWNER
;
1205 DPRINT("Use token owner sid!\n");
1206 Owner
= Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
1209 OwnerLength
= RtlLengthSid(Owner
);
1210 ASSERT(OwnerLength
% sizeof(ULONG
) == 0);
1212 /* Inherit the Group SID */
1213 if (ExplicitDescriptor
!= NULL
)
1215 Group
= SepGetGroupFromDescriptor(ExplicitDescriptor
);
1219 if (AutoInheritFlags
& 0x40 /* FIXME: SEF_DEFAULT_GROUP_FROM_PARENT */)
1221 DPRINT("Use parent group sid!\n");
1222 if (!ARGUMENT_PRESENT(ParentDescriptor
))
1224 SeUnlockSubjectContext(SubjectContext
);
1225 return STATUS_INVALID_PRIMARY_GROUP
;
1228 Group
= SepGetGroupFromDescriptor(ParentDescriptor
);
1231 SeUnlockSubjectContext(SubjectContext
);
1232 return STATUS_INVALID_PRIMARY_GROUP
;
1237 DPRINT("Use token group sid!\n");
1238 Group
= Token
->PrimaryGroup
;
1243 SeUnlockSubjectContext(SubjectContext
);
1244 return STATUS_INVALID_PRIMARY_GROUP
;
1246 GroupLength
= RtlLengthSid(Group
);
1247 ASSERT(GroupLength
% sizeof(ULONG
) == 0);
1249 /* Inherit the DACL */
1252 ExplicitPresent
= FALSE
;
1253 ExplicitDefaulted
= FALSE
;
1254 if (ExplicitDescriptor
!= NULL
&&
1255 (ExplicitDescriptor
->Control
& SE_DACL_PRESENT
))
1257 ExplicitAcl
= SepGetDaclFromDescriptor(ExplicitDescriptor
);
1258 ExplicitPresent
= TRUE
;
1259 if (ExplicitDescriptor
->Control
& SE_DACL_DEFAULTED
)
1260 ExplicitDefaulted
= TRUE
;
1263 if (ParentDescriptor
!= NULL
&&
1264 (ParentDescriptor
->Control
& SE_DACL_PRESENT
))
1266 ParentAcl
= SepGetDaclFromDescriptor(ParentDescriptor
);
1268 Dacl
= SepSelectAcl(ExplicitAcl
,
1281 Control
|= SE_DACL_PRESENT
;
1282 ASSERT(DaclLength
% sizeof(ULONG
) == 0);
1284 /* Inherit the SACL */
1287 ExplicitPresent
= FALSE
;
1288 ExplicitDefaulted
= FALSE
;
1289 if (ExplicitDescriptor
!= NULL
&&
1290 (ExplicitDescriptor
->Control
& SE_SACL_PRESENT
))
1292 ExplicitAcl
= SepGetSaclFromDescriptor(ExplicitDescriptor
);
1293 ExplicitPresent
= TRUE
;
1294 if (ExplicitDescriptor
->Control
& SE_SACL_DEFAULTED
)
1295 ExplicitDefaulted
= TRUE
;
1298 if (ParentDescriptor
!= NULL
&&
1299 (ParentDescriptor
->Control
& SE_SACL_PRESENT
))
1301 ParentAcl
= SepGetSaclFromDescriptor(ParentDescriptor
);
1303 Sacl
= SepSelectAcl(ExplicitAcl
,
1316 Control
|= SE_SACL_PRESENT
;
1317 ASSERT(SaclLength
% sizeof(ULONG
) == 0);
1319 /* Allocate and initialize the new security descriptor */
1320 Length
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
) +
1321 OwnerLength
+ GroupLength
+ DaclLength
+ SaclLength
;
1323 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n",
1324 sizeof(SECURITY_DESCRIPTOR
),
1330 Descriptor
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_SD
);
1331 if (Descriptor
== NULL
)
1333 DPRINT1("ExAlloctePool() failed\n");
1334 SeUnlockSubjectContext(SubjectContext
);
1335 return STATUS_INSUFFICIENT_RESOURCES
;
1338 RtlZeroMemory(Descriptor
, Length
);
1339 RtlCreateSecurityDescriptor(Descriptor
, SECURITY_DESCRIPTOR_REVISION
);
1341 Descriptor
->Control
= Control
| SE_SELF_RELATIVE
;
1343 Current
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
1345 if (SaclLength
!= 0)
1347 Status
= SepPropagateAcl((PACL
)((PUCHAR
)Descriptor
+ Current
),
1355 ASSERT(Status
== STATUS_SUCCESS
);
1356 Descriptor
->Sacl
= Current
;
1357 Current
+= SaclLength
;
1360 if (DaclLength
!= 0)
1362 Status
= SepPropagateAcl((PACL
)((PUCHAR
)Descriptor
+ Current
),
1370 ASSERT(Status
== STATUS_SUCCESS
);
1371 Descriptor
->Dacl
= Current
;
1372 Current
+= DaclLength
;
1375 if (OwnerLength
!= 0)
1377 RtlCopyMemory((PUCHAR
)Descriptor
+ Current
, Owner
, OwnerLength
);
1378 Descriptor
->Owner
= Current
;
1379 Current
+= OwnerLength
;
1380 DPRINT("Owner of %p at %x\n", Descriptor
, Descriptor
->Owner
);
1384 DPRINT("Owner of %p is zero length\n", Descriptor
);
1387 if (GroupLength
!= 0)
1389 RtlCopyMemory((PUCHAR
)Descriptor
+ Current
, Group
, GroupLength
);
1390 Descriptor
->Group
= Current
;
1393 /* Unlock subject context */
1394 SeUnlockSubjectContext(SubjectContext
);
1396 *NewDescriptor
= Descriptor
;
1398 DPRINT("Descriptor %p\n", Descriptor
);
1399 ASSERT(RtlLengthSecurityDescriptor(Descriptor
));
1401 return STATUS_SUCCESS
;
1407 _IRQL_requires_max_(PASSIVE_LEVEL
)
1411 _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor
,
1412 _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor
,
1413 _Out_ PSECURITY_DESCRIPTOR
*NewDescriptor
,
1414 _In_ BOOLEAN IsDirectoryObject
,
1415 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext
,
1416 _In_ PGENERIC_MAPPING GenericMapping
,
1417 _In_ POOL_TYPE PoolType
)
1421 return SeAssignSecurityEx(ParentDescriptor
,
1435 _IRQL_requires_max_(PASSIVE_LEVEL
)
1438 SeComputeQuotaInformationSize(
1439 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
1440 _Out_ PULONG QuotaInfoSize
)
1449 /* Validate security descriptor revision */
1450 if (((PISECURITY_DESCRIPTOR
)SecurityDescriptor
)->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
1452 return STATUS_UNKNOWN_REVISION
;
1455 /* Get group and DACL, if any */
1456 Group
= SepGetGroupFromDescriptor(SecurityDescriptor
);
1457 Dacl
= SepGetDaclFromDescriptor(SecurityDescriptor
);
1459 /* Return SID length if any */
1462 *QuotaInfoSize
= ALIGN_UP_BY(RtlLengthSid(Group
), sizeof(ULONG
));
1465 /* Return DACL if any */
1468 *QuotaInfoSize
+= ALIGN_UP_BY(Dacl
->AclSize
, sizeof(ULONG
));
1471 return STATUS_SUCCESS
;