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 **********************************************************/
33 SepGetGroupFromDescriptor(PVOID _Descriptor
)
35 PISECURITY_DESCRIPTOR Descriptor
= (PISECURITY_DESCRIPTOR
)_Descriptor
;
36 PISECURITY_DESCRIPTOR_RELATIVE SdRel
;
38 if (Descriptor
->Control
& SE_SELF_RELATIVE
)
40 SdRel
= (PISECURITY_DESCRIPTOR_RELATIVE
)Descriptor
;
41 return (PSID
)((ULONG_PTR
)Descriptor
+ SdRel
->Group
);
45 return Descriptor
->Group
;
51 SepGetOwnerFromDescriptor(PVOID _Descriptor
)
53 PISECURITY_DESCRIPTOR Descriptor
= (PISECURITY_DESCRIPTOR
)_Descriptor
;
54 PISECURITY_DESCRIPTOR_RELATIVE SdRel
;
56 if (Descriptor
->Control
& SE_SELF_RELATIVE
)
58 SdRel
= (PISECURITY_DESCRIPTOR_RELATIVE
)Descriptor
;
59 return (PSID
)((ULONG_PTR
)Descriptor
+ SdRel
->Owner
);
63 return Descriptor
->Owner
;
69 SepGetDaclFromDescriptor(PVOID _Descriptor
)
71 PISECURITY_DESCRIPTOR Descriptor
= (PISECURITY_DESCRIPTOR
)_Descriptor
;
72 PISECURITY_DESCRIPTOR_RELATIVE SdRel
;
74 if (Descriptor
->Control
& SE_SELF_RELATIVE
)
76 SdRel
= (PISECURITY_DESCRIPTOR_RELATIVE
)Descriptor
;
77 return (PACL
)((ULONG_PTR
)Descriptor
+ SdRel
->Dacl
);
81 return Descriptor
->Dacl
;
87 SepGetSaclFromDescriptor(PVOID _Descriptor
)
89 PISECURITY_DESCRIPTOR Descriptor
= (PISECURITY_DESCRIPTOR
)_Descriptor
;
90 PISECURITY_DESCRIPTOR_RELATIVE SdRel
;
92 if (Descriptor
->Control
& SE_SELF_RELATIVE
)
94 SdRel
= (PISECURITY_DESCRIPTOR_RELATIVE
)Descriptor
;
95 return (PACL
)((ULONG_PTR
)Descriptor
+ SdRel
->Sacl
);
99 return Descriptor
->Sacl
;
108 /* Create PublicDefaultSd */
109 SePublicDefaultSd
= ExAllocatePoolWithTag(PagedPool
,
110 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
111 if (SePublicDefaultSd
== NULL
)
114 RtlCreateSecurityDescriptor(SePublicDefaultSd
,
115 SECURITY_DESCRIPTOR_REVISION
);
116 RtlSetDaclSecurityDescriptor(SePublicDefaultSd
,
121 /* Create PublicDefaultUnrestrictedSd */
122 SePublicDefaultUnrestrictedSd
= ExAllocatePoolWithTag(PagedPool
,
123 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
124 if (SePublicDefaultUnrestrictedSd
== NULL
)
127 RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd
,
128 SECURITY_DESCRIPTOR_REVISION
);
129 RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd
,
131 SePublicDefaultUnrestrictedDacl
,
134 /* Create PublicOpenSd */
135 SePublicOpenSd
= ExAllocatePoolWithTag(PagedPool
,
136 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
137 if (SePublicOpenSd
== NULL
)
140 RtlCreateSecurityDescriptor(SePublicOpenSd
,
141 SECURITY_DESCRIPTOR_REVISION
);
142 RtlSetDaclSecurityDescriptor(SePublicOpenSd
,
147 /* Create PublicOpenUnrestrictedSd */
148 SePublicOpenUnrestrictedSd
= ExAllocatePoolWithTag(PagedPool
,
149 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
150 if (SePublicOpenUnrestrictedSd
== NULL
)
153 RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd
,
154 SECURITY_DESCRIPTOR_REVISION
);
155 RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd
,
157 SePublicOpenUnrestrictedDacl
,
160 /* Create SystemDefaultSd */
161 SeSystemDefaultSd
= ExAllocatePoolWithTag(PagedPool
,
162 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
163 if (SeSystemDefaultSd
== NULL
)
166 RtlCreateSecurityDescriptor(SeSystemDefaultSd
,
167 SECURITY_DESCRIPTOR_REVISION
);
168 RtlSetDaclSecurityDescriptor(SeSystemDefaultSd
,
173 /* Create UnrestrictedSd */
174 SeUnrestrictedSd
= ExAllocatePoolWithTag(PagedPool
,
175 sizeof(SECURITY_DESCRIPTOR
), TAG_SD
);
176 if (SeUnrestrictedSd
== NULL
)
179 RtlCreateSecurityDescriptor(SeUnrestrictedSd
,
180 SECURITY_DESCRIPTOR_REVISION
);
181 RtlSetDaclSecurityDescriptor(SeUnrestrictedSd
,
191 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation
,
192 PISECURITY_DESCRIPTOR SecurityDescriptor
,
199 PISECURITY_DESCRIPTOR_RELATIVE SdRel
= (PISECURITY_DESCRIPTOR_RELATIVE
)SecurityDescriptor
;
201 DPRINT("SeSetWorldSecurityDescriptor() called\n");
203 if (SecurityInformation
== 0)
205 return STATUS_ACCESS_DENIED
;
208 /* calculate the minimum size of the buffer */
209 SidSize
= RtlLengthSid(SeWorldSid
);
210 SdSize
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
211 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
213 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
215 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
217 SdSize
+= sizeof(ACL
) + sizeof(ACE
) + SidSize
;
220 if (*BufferLength
< SdSize
)
222 *BufferLength
= SdSize
;
223 return STATUS_BUFFER_TOO_SMALL
;
226 *BufferLength
= SdSize
;
228 Status
= RtlCreateSecurityDescriptorRelative(SdRel
,
229 SECURITY_DESCRIPTOR_REVISION
);
230 if (!NT_SUCCESS(Status
))
235 Current
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
237 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
239 RtlCopyMemory((PUCHAR
)SdRel
+ Current
, SeWorldSid
, SidSize
);
240 SdRel
->Owner
= Current
;
244 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
246 RtlCopyMemory((PUCHAR
)SdRel
+ Current
, SeWorldSid
, SidSize
);
247 SdRel
->Group
= Current
;
251 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
253 PACL Dacl
= (PACL
)((PUCHAR
)SdRel
+ Current
);
254 SdRel
->Control
|= SE_DACL_PRESENT
;
256 Status
= RtlCreateAcl(Dacl
,
257 sizeof(ACL
) + sizeof(ACE
) + SidSize
,
259 if (!NT_SUCCESS(Status
))
262 Status
= RtlAddAccessAllowedAce(Dacl
,
266 if (!NT_SUCCESS(Status
))
269 SdRel
->Dacl
= Current
;
272 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
274 /* FIXME - SdRel->Control |= SE_SACL_PRESENT; */
277 return STATUS_SUCCESS
;
283 SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
284 IN KPROCESSOR_MODE AccessMode
,
285 IN POOL_TYPE PoolType
,
286 IN BOOLEAN CaptureIfKernel
,
287 OUT PSECURITY_QUALITY_OF_SERVICE
*CapturedSecurityQualityOfService
,
288 OUT PBOOLEAN Present
)
290 PSECURITY_QUALITY_OF_SERVICE CapturedQos
;
291 NTSTATUS Status
= STATUS_SUCCESS
;
295 ASSERT(CapturedSecurityQualityOfService
);
298 if (ObjectAttributes
!= NULL
)
300 if (AccessMode
!= KernelMode
)
302 SECURITY_QUALITY_OF_SERVICE SafeQos
;
306 ProbeForRead(ObjectAttributes
,
307 sizeof(OBJECT_ATTRIBUTES
),
309 if (ObjectAttributes
->Length
== sizeof(OBJECT_ATTRIBUTES
))
311 if (ObjectAttributes
->SecurityQualityOfService
!= NULL
)
313 ProbeForRead(ObjectAttributes
->SecurityQualityOfService
,
314 sizeof(SECURITY_QUALITY_OF_SERVICE
),
317 if (((PSECURITY_QUALITY_OF_SERVICE
)ObjectAttributes
->SecurityQualityOfService
)->Length
==
318 sizeof(SECURITY_QUALITY_OF_SERVICE
))
321 * Don't allocate memory here because ExAllocate should bugcheck
322 * the system if it's buggy, SEH would catch that! So make a local
323 * copy of the qos structure.
325 RtlCopyMemory(&SafeQos
,
326 ObjectAttributes
->SecurityQualityOfService
,
327 sizeof(SECURITY_QUALITY_OF_SERVICE
));
332 Status
= STATUS_INVALID_PARAMETER
;
337 *CapturedSecurityQualityOfService
= NULL
;
343 Status
= STATUS_INVALID_PARAMETER
;
346 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
348 Status
= _SEH2_GetExceptionCode();
352 if (NT_SUCCESS(Status
))
356 CapturedQos
= ExAllocatePool(PoolType
,
357 sizeof(SECURITY_QUALITY_OF_SERVICE
));
358 if (CapturedQos
!= NULL
)
360 RtlCopyMemory(CapturedQos
,
362 sizeof(SECURITY_QUALITY_OF_SERVICE
));
363 *CapturedSecurityQualityOfService
= CapturedQos
;
367 Status
= STATUS_INSUFFICIENT_RESOURCES
;
372 *CapturedSecurityQualityOfService
= NULL
;
378 if (ObjectAttributes
->Length
== sizeof(OBJECT_ATTRIBUTES
))
382 if (ObjectAttributes
->SecurityQualityOfService
!= NULL
)
384 if (((PSECURITY_QUALITY_OF_SERVICE
)ObjectAttributes
->SecurityQualityOfService
)->Length
==
385 sizeof(SECURITY_QUALITY_OF_SERVICE
))
387 CapturedQos
= ExAllocatePool(PoolType
,
388 sizeof(SECURITY_QUALITY_OF_SERVICE
));
389 if (CapturedQos
!= NULL
)
391 RtlCopyMemory(CapturedQos
,
392 ObjectAttributes
->SecurityQualityOfService
,
393 sizeof(SECURITY_QUALITY_OF_SERVICE
));
394 *CapturedSecurityQualityOfService
= CapturedQos
;
399 Status
= STATUS_INSUFFICIENT_RESOURCES
;
404 Status
= STATUS_INVALID_PARAMETER
;
409 *CapturedSecurityQualityOfService
= NULL
;
415 *CapturedSecurityQualityOfService
= (PSECURITY_QUALITY_OF_SERVICE
)ObjectAttributes
->SecurityQualityOfService
;
416 *Present
= (ObjectAttributes
->SecurityQualityOfService
!= NULL
);
421 Status
= STATUS_INVALID_PARAMETER
;
427 *CapturedSecurityQualityOfService
= NULL
;
437 SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL
,
438 IN KPROCESSOR_MODE AccessMode
,
439 IN BOOLEAN CaptureIfKernel
)
443 if (CapturedSecurityQualityOfService
!= NULL
&&
444 (AccessMode
!= KernelMode
|| CaptureIfKernel
))
446 ExFreePool(CapturedSecurityQualityOfService
);
450 /* PUBLIC FUNCTIONS ***********************************************************/
457 KPROCESSOR_MODE ProcessorMode
)
467 if (ProcessorMode
!= KernelMode
)
469 /* Securely access the buffers! */
470 *OutSAC
= ProbeForReadUchar(&Sid
->SubAuthorityCount
);
471 Size
= RtlLengthRequiredSid(*OutSAC
);
472 ProbeForRead(Sid
, Size
, sizeof(ULONG
));
476 *OutSAC
= Sid
->SubAuthorityCount
;
477 Size
= RtlLengthRequiredSid(*OutSAC
);
487 KPROCESSOR_MODE ProcessorMode
)
493 if (ProcessorMode
== KernelMode
) return Acl
->AclSize
;
495 /* Probe the buffers! */
496 Size
= ProbeForReadUshort(&Acl
->AclSize
);
497 ProbeForRead(Acl
, Size
, sizeof(ULONG
));
504 SeCaptureSecurityDescriptor(
505 IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor
,
506 IN KPROCESSOR_MODE CurrentMode
,
507 IN POOL_TYPE PoolType
,
508 IN BOOLEAN CaptureIfKernel
,
509 OUT PSECURITY_DESCRIPTOR
*CapturedSecurityDescriptor
)
511 PISECURITY_DESCRIPTOR OriginalDescriptor
= _OriginalSecurityDescriptor
;
512 SECURITY_DESCRIPTOR DescriptorCopy
;
513 PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor
;
514 ULONG OwnerSAC
= 0, GroupSAC
= 0;
515 ULONG OwnerSize
= 0, GroupSize
= 0;
516 ULONG SaclSize
= 0, DaclSize
= 0;
517 ULONG DescriptorSize
= 0;
520 if (!OriginalDescriptor
)
522 /* Nothing to do... */
523 *CapturedSecurityDescriptor
= NULL
;
524 return STATUS_SUCCESS
;
528 if (CurrentMode
== KernelMode
&& !CaptureIfKernel
)
530 /* Check descriptor version */
531 if (OriginalDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
533 return STATUS_UNKNOWN_REVISION
;
536 *CapturedSecurityDescriptor
= _OriginalSecurityDescriptor
;
537 return STATUS_SUCCESS
;
542 if (CurrentMode
!= KernelMode
)
544 ProbeForRead(OriginalDescriptor
,
545 sizeof(SECURITY_DESCRIPTOR_RELATIVE
),
549 /* Check the descriptor version */
550 if (OriginalDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
552 _SEH2_YIELD(return STATUS_UNKNOWN_REVISION
);
555 if (CurrentMode
!= KernelMode
)
557 /* Get the size of the descriptor */
558 DescriptorSize
= (OriginalDescriptor
->Control
& SE_SELF_RELATIVE
) ?
559 sizeof(SECURITY_DESCRIPTOR_RELATIVE
) : sizeof(SECURITY_DESCRIPTOR
);
561 /* Probe the entire security descriptor structure. The SIDs
562 * and ACLs will be probed and copied later though */
563 ProbeForRead(OriginalDescriptor
, DescriptorSize
, sizeof(ULONG
));
566 /* Now capture all fields and convert to an absolute descriptor */
567 DescriptorCopy
.Revision
= OriginalDescriptor
->Revision
;
568 DescriptorCopy
.Sbz1
= OriginalDescriptor
->Sbz1
;
569 DescriptorCopy
.Control
= OriginalDescriptor
->Control
& ~SE_SELF_RELATIVE
;
570 DescriptorCopy
.Owner
= SepGetOwnerFromDescriptor(OriginalDescriptor
);
571 DescriptorCopy
.Group
= SepGetGroupFromDescriptor(OriginalDescriptor
);
572 DescriptorCopy
.Sacl
= SepGetSaclFromDescriptor(OriginalDescriptor
);
573 DescriptorCopy
.Dacl
= SepGetDaclFromDescriptor(OriginalDescriptor
);
574 DescriptorSize
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
576 /* Determine owner and group sizes */
577 OwnerSize
= DetermineSIDSize(DescriptorCopy
.Owner
, &OwnerSAC
, CurrentMode
);
578 DescriptorSize
+= ROUND_UP(OwnerSize
, sizeof(ULONG
));
579 GroupSize
= DetermineSIDSize(DescriptorCopy
.Group
, &GroupSAC
, CurrentMode
);
580 DescriptorSize
+= ROUND_UP(GroupSize
, sizeof(ULONG
));
582 /* Determine the size of the ACLs */
583 if (DescriptorCopy
.Control
& SE_SACL_PRESENT
)
585 /* Get the size and probe if user mode */
586 SaclSize
= DetermineACLSize(DescriptorCopy
.Sacl
, CurrentMode
);
587 DescriptorSize
+= ROUND_UP(SaclSize
, sizeof(ULONG
));
590 if (DescriptorCopy
.Control
& SE_DACL_PRESENT
)
592 /* Get the size and probe if user mode */
593 DaclSize
= DetermineACLSize(DescriptorCopy
.Dacl
, CurrentMode
);
594 DescriptorSize
+= ROUND_UP(DaclSize
, sizeof(ULONG
));
597 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
599 _SEH2_YIELD(return _SEH2_GetExceptionCode());
604 * Allocate enough memory to store a complete copy of a self-relative
605 * security descriptor
607 NewDescriptor
= ExAllocatePoolWithTag(PoolType
,
610 if (!NewDescriptor
) return STATUS_INSUFFICIENT_RESOURCES
;
612 RtlZeroMemory(NewDescriptor
, DescriptorSize
);
613 NewDescriptor
->Revision
= DescriptorCopy
.Revision
;
614 NewDescriptor
->Sbz1
= DescriptorCopy
.Sbz1
;
615 NewDescriptor
->Control
= DescriptorCopy
.Control
| SE_SELF_RELATIVE
;
620 * Setup the offsets and copy the SIDs and ACLs to the new
621 * self-relative security descriptor. Probing the pointers is not
622 * neccessary anymore as we did that when collecting the sizes!
623 * Make sure to validate the SIDs and ACLs *again* as they could have
624 * been modified in the meanwhile!
626 Offset
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
628 if (DescriptorCopy
.Owner
)
630 if (!RtlValidSid(DescriptorCopy
.Owner
)) RtlRaiseStatus(STATUS_INVALID_SID
);
631 NewDescriptor
->Owner
= Offset
;
632 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
633 DescriptorCopy
.Owner
,
635 Offset
+= ROUND_UP(OwnerSize
, sizeof(ULONG
));
638 if (DescriptorCopy
.Group
)
640 if (!RtlValidSid(DescriptorCopy
.Group
)) RtlRaiseStatus(STATUS_INVALID_SID
);
641 NewDescriptor
->Group
= Offset
;
642 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
643 DescriptorCopy
.Group
,
645 Offset
+= ROUND_UP(GroupSize
, sizeof(ULONG
));
648 if (DescriptorCopy
.Sacl
)
650 if (!RtlValidAcl(DescriptorCopy
.Sacl
)) RtlRaiseStatus(STATUS_INVALID_ACL
);
651 NewDescriptor
->Sacl
= Offset
;
652 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
655 Offset
+= ROUND_UP(SaclSize
, sizeof(ULONG
));
658 if (DescriptorCopy
.Dacl
)
660 if (!RtlValidAcl(DescriptorCopy
.Dacl
)) RtlRaiseStatus(STATUS_INVALID_ACL
);
661 NewDescriptor
->Dacl
= Offset
;
662 RtlCopyMemory((PUCHAR
)NewDescriptor
+ Offset
,
665 Offset
+= ROUND_UP(DaclSize
, sizeof(ULONG
));
668 /* Make sure the size was correct */
669 ASSERT(Offset
== DescriptorSize
);
671 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
673 /* We failed to copy the data to the new descriptor */
674 ExFreePoolWithTag(NewDescriptor
, TAG_SD
);
675 _SEH2_YIELD(return _SEH2_GetExceptionCode());
680 * We're finally done!
681 * Copy the pointer to the captured descriptor to to the caller.
683 *CapturedSecurityDescriptor
= NewDescriptor
;
684 return STATUS_SUCCESS
;
691 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation
,
692 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
693 IN OUT PULONG Length
,
694 IN PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor OPTIONAL
)
696 PISECURITY_DESCRIPTOR ObjectSd
;
697 PISECURITY_DESCRIPTOR_RELATIVE RelSD
;
702 ULONG OwnerLength
= 0;
703 ULONG GroupLength
= 0;
704 ULONG DaclLength
= 0;
705 ULONG SaclLength
= 0;
710 RelSD
= (PISECURITY_DESCRIPTOR_RELATIVE
)SecurityDescriptor
;
712 if (*ObjectsSecurityDescriptor
== NULL
)
714 if (*Length
< sizeof(SECURITY_DESCRIPTOR_RELATIVE
))
716 *Length
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
717 return STATUS_BUFFER_TOO_SMALL
;
720 *Length
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
721 RtlCreateSecurityDescriptorRelative(RelSD
,
722 SECURITY_DESCRIPTOR_REVISION
);
723 return STATUS_SUCCESS
;
726 ObjectSd
= *ObjectsSecurityDescriptor
;
728 /* Calculate the required security descriptor length */
729 Control
= SE_SELF_RELATIVE
;
730 if ((*SecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
731 (ObjectSd
->Owner
!= NULL
))
733 Owner
= (PSID
)((ULONG_PTR
)ObjectSd
->Owner
+ (ULONG_PTR
)ObjectSd
);
734 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
735 Control
|= (ObjectSd
->Control
& SE_OWNER_DEFAULTED
);
738 if ((*SecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
739 (ObjectSd
->Group
!= NULL
))
741 Group
= (PSID
)((ULONG_PTR
)ObjectSd
->Group
+ (ULONG_PTR
)ObjectSd
);
742 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
743 Control
|= (ObjectSd
->Control
& SE_GROUP_DEFAULTED
);
746 if ((*SecurityInformation
& DACL_SECURITY_INFORMATION
) &&
747 (ObjectSd
->Control
& SE_DACL_PRESENT
))
749 if (ObjectSd
->Dacl
!= NULL
)
751 Dacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Dacl
+ (ULONG_PTR
)ObjectSd
);
752 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
755 Control
|= (ObjectSd
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
758 if ((*SecurityInformation
& SACL_SECURITY_INFORMATION
) &&
759 (ObjectSd
->Control
& SE_SACL_PRESENT
))
761 if (ObjectSd
->Sacl
!= NULL
)
763 Sacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Sacl
+ (ULONG_PTR
)ObjectSd
);
764 SaclLength
= ROUND_UP(Sacl
->AclSize
, 4);
767 Control
|= (ObjectSd
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
770 SdLength
= OwnerLength
+ GroupLength
+ DaclLength
+
771 SaclLength
+ sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
772 if (*Length
< SdLength
)
775 return STATUS_BUFFER_TOO_SMALL
;
778 /* Build the new security descrtiptor */
779 RtlCreateSecurityDescriptorRelative(RelSD
,
780 SECURITY_DESCRIPTOR_REVISION
);
781 RelSD
->Control
= (USHORT
)Control
;
783 Current
= (ULONG_PTR
)(RelSD
+ 1);
785 if (OwnerLength
!= 0)
787 RtlCopyMemory((PVOID
)Current
,
790 RelSD
->Owner
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
791 Current
+= OwnerLength
;
794 if (GroupLength
!= 0)
796 RtlCopyMemory((PVOID
)Current
,
799 RelSD
->Group
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
800 Current
+= GroupLength
;
805 RtlCopyMemory((PVOID
)Current
,
808 RelSD
->Dacl
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
809 Current
+= DaclLength
;
814 RtlCopyMemory((PVOID
)Current
,
817 RelSD
->Sacl
= (ULONG
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
818 Current
+= SaclLength
;
823 return STATUS_SUCCESS
;
831 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
,
832 IN KPROCESSOR_MODE CurrentMode
,
833 IN BOOLEAN CaptureIfKernelMode
)
838 * WARNING! You need to call this function with the same value for CurrentMode
839 * and CaptureIfKernelMode that you previously passed to
840 * SeCaptureSecurityDescriptor() in order to avoid memory leaks!
842 if (CapturedSecurityDescriptor
!= NULL
&&
843 (CurrentMode
!= KernelMode
||
844 (CurrentMode
== KernelMode
&& CaptureIfKernelMode
)))
846 /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
847 ExFreePoolWithTag(CapturedSecurityDescriptor
, TAG_SD
);
850 return STATUS_SUCCESS
;
857 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL
,
858 IN PSECURITY_INFORMATION _SecurityInformation
,
859 IN PSECURITY_DESCRIPTOR _SecurityDescriptor
,
860 IN OUT PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
,
861 IN POOL_TYPE PoolType
,
862 IN PGENERIC_MAPPING GenericMapping
)
864 PISECURITY_DESCRIPTOR_RELATIVE ObjectSd
;
865 PISECURITY_DESCRIPTOR_RELATIVE NewSd
;
866 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
867 PISECURITY_DESCRIPTOR_RELATIVE RelSD
= (PISECURITY_DESCRIPTOR_RELATIVE
)SecurityDescriptor
;
872 ULONG OwnerLength
= 0;
873 ULONG GroupLength
= 0;
874 ULONG DaclLength
= 0;
875 ULONG SaclLength
= 0;
878 SECURITY_INFORMATION SecurityInformation
;
880 ObjectSd
= *ObjectsSecurityDescriptor
;
881 ASSERT(ObjectSd
->Control
& SE_SELF_RELATIVE
);
883 /* The object does not have a security descriptor. */
885 return STATUS_NO_SECURITY_ON_OBJECT
;
887 SecurityInformation
= *_SecurityInformation
;
889 /* Get owner and owner size */
890 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
892 if (SecurityDescriptor
->Owner
!= NULL
)
894 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
895 Owner
= (PSID
)((ULONG_PTR
)RelSD
->Owner
+
896 (ULONG_PTR
)SecurityDescriptor
);
898 Owner
= (PSID
)SecurityDescriptor
->Owner
;
899 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
902 Control
|= (SecurityDescriptor
->Control
& SE_OWNER_DEFAULTED
);
908 Owner
= (PSID
)((ULONG_PTR
)ObjectSd
->Owner
+ (ULONG_PTR
)ObjectSd
);
909 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
912 Control
|= (ObjectSd
->Control
& SE_OWNER_DEFAULTED
);
915 /* Get group and group size */
916 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
918 if (SecurityDescriptor
->Group
!= NULL
)
920 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
921 Group
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Group
+
922 (ULONG_PTR
)SecurityDescriptor
);
924 Group
= (PSID
)SecurityDescriptor
->Group
;
925 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
928 Control
|= (SecurityDescriptor
->Control
& SE_GROUP_DEFAULTED
);
934 Group
= (PSID
)((ULONG_PTR
)ObjectSd
->Group
+ (ULONG_PTR
)ObjectSd
);
935 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
938 Control
|= (ObjectSd
->Control
& SE_GROUP_DEFAULTED
);
941 /* Get DACL and DACL size */
942 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
944 if ((SecurityDescriptor
->Control
& SE_DACL_PRESENT
) &&
945 (SecurityDescriptor
->Dacl
!= NULL
))
947 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
948 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
->Dacl
+
949 (ULONG_PTR
)SecurityDescriptor
);
951 Dacl
= (PACL
)SecurityDescriptor
->Dacl
;
953 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
956 Control
|= (SecurityDescriptor
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
960 if ((ObjectSd
->Control
& SE_DACL_PRESENT
) && (ObjectSd
->Dacl
))
962 Dacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Dacl
+ (ULONG_PTR
)ObjectSd
);
963 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
966 Control
|= (ObjectSd
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
969 /* Get SACL and SACL size */
970 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
972 if ((SecurityDescriptor
->Control
& SE_SACL_PRESENT
) &&
973 (SecurityDescriptor
->Sacl
!= NULL
))
975 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
976 Sacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
->Sacl
+
977 (ULONG_PTR
)SecurityDescriptor
);
979 Sacl
= (PACL
)SecurityDescriptor
->Sacl
;
980 SaclLength
= ROUND_UP((ULONG
)Sacl
->AclSize
, 4);
983 Control
|= (SecurityDescriptor
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
987 if ((ObjectSd
->Control
& SE_SACL_PRESENT
) && (ObjectSd
->Sacl
))
989 Sacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Sacl
+ (ULONG_PTR
)ObjectSd
);
990 SaclLength
= ROUND_UP((ULONG
)Sacl
->AclSize
, 4);
993 Control
|= (ObjectSd
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
996 NewSd
= ExAllocatePool(NonPagedPool
,
997 sizeof(SECURITY_DESCRIPTOR_RELATIVE
) + OwnerLength
+ GroupLength
+
998 DaclLength
+ SaclLength
);
1001 ObDereferenceObject(Object
);
1002 return STATUS_INSUFFICIENT_RESOURCES
;
1005 RtlCreateSecurityDescriptor(NewSd
,
1006 SECURITY_DESCRIPTOR_REVISION1
);
1008 /* We always build a self-relative descriptor */
1009 NewSd
->Control
= (USHORT
)Control
| SE_SELF_RELATIVE
;
1011 Current
= sizeof(SECURITY_DESCRIPTOR
);
1013 if (OwnerLength
!= 0)
1015 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Owner
, OwnerLength
);
1016 NewSd
->Owner
= Current
;
1017 Current
+= OwnerLength
;
1020 if (GroupLength
!= 0)
1022 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Group
, GroupLength
);
1023 NewSd
->Group
= Current
;
1024 Current
+= GroupLength
;
1027 if (DaclLength
!= 0)
1029 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Dacl
, DaclLength
);
1030 NewSd
->Dacl
= Current
;
1031 Current
+= DaclLength
;
1034 if (SaclLength
!= 0)
1036 RtlCopyMemory((PUCHAR
)NewSd
+ Current
, Sacl
, SaclLength
);
1037 NewSd
->Sacl
= Current
;
1038 Current
+= SaclLength
;
1041 *ObjectsSecurityDescriptor
= NewSd
;
1042 return STATUS_SUCCESS
;
1050 SeSetSecurityDescriptorInfoEx(IN PVOID Object OPTIONAL
,
1051 IN PSECURITY_INFORMATION SecurityInformation
,
1052 IN PSECURITY_DESCRIPTOR ModificationDescriptor
,
1053 IN OUT PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
,
1054 IN ULONG AutoInheritFlags
,
1055 IN POOL_TYPE PoolType
,
1056 IN PGENERIC_MAPPING GenericMapping
)
1058 PISECURITY_DESCRIPTOR ObjectSd
= *ObjectsSecurityDescriptor
;
1060 /* The object does not have a security descriptor. */
1062 return STATUS_NO_SECURITY_ON_OBJECT
;
1065 return STATUS_NOT_IMPLEMENTED
;
1073 SeValidSecurityDescriptor(IN ULONG Length
,
1074 IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
1079 PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor
= _SecurityDescriptor
;
1081 if (Length
< SECURITY_DESCRIPTOR_MIN_LENGTH
)
1083 DPRINT1("Invalid Security Descriptor revision\n");
1087 if (SecurityDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
1089 DPRINT1("Invalid Security Descriptor revision\n");
1093 if (!(SecurityDescriptor
->Control
& SE_SELF_RELATIVE
))
1095 DPRINT1("No self-relative Security Descriptor\n");
1099 SdLength
= sizeof(SECURITY_DESCRIPTOR
);
1101 /* Check Owner SID */
1102 if (SecurityDescriptor
->Owner
)
1104 DPRINT1("No Owner SID\n");
1108 if (SecurityDescriptor
->Owner
% sizeof(ULONG
))
1110 DPRINT1("Invalid Owner SID alignment\n");
1114 Sid
= (PISID
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Owner
);
1115 if (Sid
->Revision
!= SID_REVISION
)
1117 DPRINT1("Invalid Owner SID revision\n");
1121 SdLength
+= (sizeof(SID
) + (Sid
->SubAuthorityCount
- 1) * sizeof(ULONG
));
1122 if (Length
< SdLength
)
1124 DPRINT1("Invalid Owner SID size\n");
1128 /* Check Group SID */
1129 if (SecurityDescriptor
->Group
)
1131 if (SecurityDescriptor
->Group
% sizeof(ULONG
))
1133 DPRINT1("Invalid Group SID alignment\n");
1137 Sid
= (PSID
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Group
);
1138 if (Sid
->Revision
!= SID_REVISION
)
1140 DPRINT1("Invalid Group SID revision\n");
1144 SdLength
+= (sizeof(SID
) + (Sid
->SubAuthorityCount
- 1) * sizeof(ULONG
));
1145 if (Length
< SdLength
)
1147 DPRINT1("Invalid Group SID size\n");
1153 if (SecurityDescriptor
->Dacl
)
1155 if (SecurityDescriptor
->Dacl
% sizeof(ULONG
))
1157 DPRINT1("Invalid DACL alignment\n");
1161 Acl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Dacl
);
1162 if ((Acl
->AclRevision
< MIN_ACL_REVISION
) &&
1163 (Acl
->AclRevision
> MAX_ACL_REVISION
))
1165 DPRINT1("Invalid DACL revision\n");
1169 SdLength
+= Acl
->AclSize
;
1170 if (Length
< SdLength
)
1172 DPRINT1("Invalid DACL size\n");
1178 if (SecurityDescriptor
->Sacl
)
1180 if (SecurityDescriptor
->Sacl
% sizeof(ULONG
))
1182 DPRINT1("Invalid SACL alignment\n");
1186 Acl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SecurityDescriptor
->Sacl
);
1187 if ((Acl
->AclRevision
< MIN_ACL_REVISION
) ||
1188 (Acl
->AclRevision
> MAX_ACL_REVISION
))
1190 DPRINT1("Invalid SACL revision\n");
1194 SdLength
+= Acl
->AclSize
;
1195 if (Length
< SdLength
)
1197 DPRINT1("Invalid SACL size\n");
1209 SeDeassignSecurity(PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
1213 if (*SecurityDescriptor
!= NULL
)
1215 ExFreePoolWithTag(*SecurityDescriptor
, TAG_SD
);
1216 *SecurityDescriptor
= NULL
;
1219 return STATUS_SUCCESS
;
1228 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL
,
1229 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL
,
1230 OUT PSECURITY_DESCRIPTOR
*NewDescriptor
,
1231 IN GUID
*ObjectType OPTIONAL
,
1232 IN BOOLEAN IsDirectoryObject
,
1233 IN ULONG AutoInheritFlags
,
1234 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
1235 IN PGENERIC_MAPPING GenericMapping
,
1236 IN POOL_TYPE PoolType
)
1239 return STATUS_NOT_IMPLEMENTED
;
1246 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL
,
1247 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL
,
1248 PSECURITY_DESCRIPTOR
*NewDescriptor
,
1249 BOOLEAN IsDirectoryObject
,
1250 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
1251 PGENERIC_MAPPING GenericMapping
,
1254 PISECURITY_DESCRIPTOR ParentDescriptor
= _ParentDescriptor
;
1255 PISECURITY_DESCRIPTOR ExplicitDescriptor
= _ExplicitDescriptor
;
1256 PISECURITY_DESCRIPTOR_RELATIVE Descriptor
;
1258 ULONG OwnerLength
= 0;
1259 ULONG GroupLength
= 0;
1260 ULONG DaclLength
= 0;
1261 ULONG SaclLength
= 0;
1272 /* Lock subject context */
1273 SeLockSubjectContext(SubjectContext
);
1275 if (SubjectContext
->ClientToken
!= NULL
)
1277 Token
= SubjectContext
->ClientToken
;
1281 Token
= SubjectContext
->PrimaryToken
;
1284 /* Inherit the Owner SID */
1285 if (ExplicitDescriptor
!= NULL
)
1287 DPRINT("Use explicit owner sid!\n");
1288 Owner
= SepGetOwnerFromDescriptor(ExplicitDescriptor
);
1295 DPRINT("Use token owner sid!\n");
1296 Owner
= Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
1300 DPRINT("Use default owner sid!\n");
1301 Owner
= SeLocalSystemSid
;
1304 Control
|= SE_OWNER_DEFAULTED
;
1307 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
1309 /* Inherit the Group SID */
1310 if (ExplicitDescriptor
!= NULL
)
1312 Group
= SepGetGroupFromDescriptor(ExplicitDescriptor
);
1319 DPRINT("Use token group sid!\n");
1320 Group
= Token
->PrimaryGroup
;
1324 DPRINT("Use default group sid!\n");
1325 Group
= SeLocalSystemSid
;
1328 Control
|= SE_GROUP_DEFAULTED
;
1331 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
1333 /* Inherit the DACL */
1334 if (ExplicitDescriptor
!= NULL
&&
1335 (ExplicitDescriptor
->Control
& SE_DACL_PRESENT
) &&
1336 !(ExplicitDescriptor
->Control
& SE_DACL_DEFAULTED
))
1338 DPRINT("Use explicit DACL!\n");
1339 Dacl
= SepGetDaclFromDescriptor(ExplicitDescriptor
);
1340 Control
|= SE_DACL_PRESENT
;
1342 else if (ParentDescriptor
!= NULL
&&
1343 (ParentDescriptor
->Control
& SE_DACL_PRESENT
))
1345 DPRINT("Use parent DACL!\n");
1346 /* FIXME: Inherit */
1347 Dacl
= SepGetDaclFromDescriptor(ParentDescriptor
);
1348 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
1350 else if (Token
!= NULL
&& Token
->DefaultDacl
!= NULL
)
1352 DPRINT("Use token default DACL!\n");
1353 /* FIXME: Inherit */
1354 Dacl
= Token
->DefaultDacl
;
1355 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
1359 DPRINT("Use NULL DACL!\n");
1361 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
1364 DaclLength
= (Dacl
!= NULL
) ? ROUND_UP(Dacl
->AclSize
, 4) : 0;
1366 /* Inherit the SACL */
1367 if (ExplicitDescriptor
!= NULL
&&
1368 (ExplicitDescriptor
->Control
& SE_SACL_PRESENT
) &&
1369 !(ExplicitDescriptor
->Control
& SE_SACL_DEFAULTED
))
1371 DPRINT("Use explicit SACL!\n");
1372 Sacl
= SepGetSaclFromDescriptor(ExplicitDescriptor
);
1373 Control
|= SE_SACL_PRESENT
;
1375 else if (ParentDescriptor
!= NULL
&&
1376 (ParentDescriptor
->Control
& SE_SACL_PRESENT
))
1378 DPRINT("Use parent SACL!\n");
1379 /* FIXME: Inherit */
1380 Sacl
= SepGetSaclFromDescriptor(ParentDescriptor
);
1381 Control
|= (SE_SACL_PRESENT
| SE_SACL_DEFAULTED
);
1384 SaclLength
= (Sacl
!= NULL
) ? ROUND_UP(Sacl
->AclSize
, 4) : 0;
1386 /* Allocate and initialize the new security descriptor */
1387 Length
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
) +
1388 OwnerLength
+ GroupLength
+ DaclLength
+ SaclLength
;
1390 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
1391 sizeof(SECURITY_DESCRIPTOR
),
1397 Descriptor
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_SD
);
1398 if (Descriptor
== NULL
)
1400 DPRINT1("ExAlloctePool() failed\n");
1401 /* FIXME: Unlock subject context */
1402 return STATUS_INSUFFICIENT_RESOURCES
;
1405 RtlZeroMemory(Descriptor
, Length
);
1406 RtlCreateSecurityDescriptor(Descriptor
, SECURITY_DESCRIPTOR_REVISION
);
1408 Descriptor
->Control
= (USHORT
)Control
| SE_SELF_RELATIVE
;
1410 Current
= sizeof(SECURITY_DESCRIPTOR_RELATIVE
);
1412 if (SaclLength
!= 0)
1414 RtlCopyMemory((PUCHAR
)Descriptor
+ Current
, Sacl
, SaclLength
);
1415 Descriptor
->Sacl
= Current
;
1416 Current
+= SaclLength
;
1419 if (DaclLength
!= 0)
1421 RtlCopyMemory((PUCHAR
)Descriptor
+ Current
, Dacl
, DaclLength
);
1422 Descriptor
->Dacl
= Current
;
1423 Current
+= DaclLength
;
1426 if (OwnerLength
!= 0)
1428 RtlCopyMemory((PUCHAR
)Descriptor
+ Current
, Owner
, OwnerLength
);
1429 Descriptor
->Owner
= Current
;
1430 Current
+= OwnerLength
;
1431 DPRINT("Owner of %x at %x\n", Descriptor
, Descriptor
->Owner
);
1435 DPRINT("Owner of %x is zero length\n", Descriptor
);
1438 if (GroupLength
!= 0)
1440 RtlCopyMemory((PUCHAR
)Descriptor
+ Current
, Group
, GroupLength
);
1441 Descriptor
->Group
= Current
;
1444 /* Unlock subject context */
1445 SeUnlockSubjectContext(SubjectContext
);
1447 *NewDescriptor
= Descriptor
;
1449 DPRINT("Descrptor %x\n", Descriptor
);
1450 ASSERT(RtlLengthSecurityDescriptor(Descriptor
));
1452 return STATUS_SUCCESS
;