3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/sd.c
6 * PURPOSE: Security manager
8 * PROGRAMMERS: David Welch <welch@cwcom.net>
11 /* INCLUDES *****************************************************************/
14 #include <internal/debug.h>
16 /* GLOBALS ******************************************************************/
18 PSECURITY_DESCRIPTOR SePublicDefaultSd
= NULL
;
19 PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd
= NULL
;
20 PSECURITY_DESCRIPTOR SePublicOpenSd
= NULL
;
21 PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd
= NULL
;
22 PSECURITY_DESCRIPTOR SeSystemDefaultSd
= NULL
;
23 PSECURITY_DESCRIPTOR SeUnrestrictedSd
= NULL
;
25 /* FUNCTIONS ***************************************************************/
30 /* Create PublicDefaultSd */
31 SePublicDefaultSd
= ExAllocatePool(NonPagedPool
,
32 sizeof(SECURITY_DESCRIPTOR
));
33 if (SePublicDefaultSd
== NULL
)
36 RtlCreateSecurityDescriptor(SePublicDefaultSd
,
37 SECURITY_DESCRIPTOR_REVISION
);
38 RtlSetDaclSecurityDescriptor(SePublicDefaultSd
,
43 /* Create PublicDefaultUnrestrictedSd */
44 SePublicDefaultUnrestrictedSd
= ExAllocatePool(NonPagedPool
,
45 sizeof(SECURITY_DESCRIPTOR
));
46 if (SePublicDefaultUnrestrictedSd
== NULL
)
49 RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd
,
50 SECURITY_DESCRIPTOR_REVISION
);
51 RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd
,
53 SePublicDefaultUnrestrictedDacl
,
56 /* Create PublicOpenSd */
57 SePublicOpenSd
= ExAllocatePool(NonPagedPool
,
58 sizeof(SECURITY_DESCRIPTOR
));
59 if (SePublicOpenSd
== NULL
)
62 RtlCreateSecurityDescriptor(SePublicOpenSd
,
63 SECURITY_DESCRIPTOR_REVISION
);
64 RtlSetDaclSecurityDescriptor(SePublicOpenSd
,
69 /* Create PublicOpenUnrestrictedSd */
70 SePublicOpenUnrestrictedSd
= ExAllocatePool(NonPagedPool
,
71 sizeof(SECURITY_DESCRIPTOR
));
72 if (SePublicOpenUnrestrictedSd
== NULL
)
75 RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd
,
76 SECURITY_DESCRIPTOR_REVISION
);
77 RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd
,
79 SePublicOpenUnrestrictedDacl
,
82 /* Create SystemDefaultSd */
83 SeSystemDefaultSd
= ExAllocatePool(NonPagedPool
,
84 sizeof(SECURITY_DESCRIPTOR
));
85 if (SeSystemDefaultSd
== NULL
)
88 RtlCreateSecurityDescriptor(SeSystemDefaultSd
,
89 SECURITY_DESCRIPTOR_REVISION
);
90 RtlSetDaclSecurityDescriptor(SeSystemDefaultSd
,
95 /* Create UnrestrictedSd */
96 SeUnrestrictedSd
= ExAllocatePool(NonPagedPool
,
97 sizeof(SECURITY_DESCRIPTOR
));
98 if (SeUnrestrictedSd
== NULL
)
101 RtlCreateSecurityDescriptor(SeUnrestrictedSd
,
102 SECURITY_DESCRIPTOR_REVISION
);
103 RtlSetDaclSecurityDescriptor(SeUnrestrictedSd
,
116 SeCaptureSecurityDescriptor(
117 IN PSECURITY_DESCRIPTOR OriginalSecurityDescriptor
,
118 IN KPROCESSOR_MODE CurrentMode
,
119 IN POOL_TYPE PoolType
,
120 IN BOOLEAN CaptureIfKernel
,
121 OUT PSECURITY_DESCRIPTOR
*CapturedSecurityDescriptor
124 SECURITY_DESCRIPTOR DescriptorCopy
;
125 PSECURITY_DESCRIPTOR NewDescriptor
;
126 ULONG OwnerSAC
= 0, GroupSAC
= 0;
127 ULONG OwnerSize
= 0, GroupSize
= 0;
128 ULONG SaclSize
= 0, DaclSize
= 0;
129 ULONG DescriptorSize
= sizeof(SECURITY_DESCRIPTOR
);
130 NTSTATUS Status
= STATUS_SUCCESS
;
132 if(OriginalSecurityDescriptor
!= NULL
)
134 if(CurrentMode
!= KernelMode
)
138 ProbeForRead(OriginalSecurityDescriptor
,
139 sizeof(SECURITY_DESCRIPTOR
),
142 /* make a copy on the stack */
143 DescriptorCopy
= *OriginalSecurityDescriptor
;
147 Status
= _SEH_GetExceptionCode();
151 if(!NT_SUCCESS(Status
))
156 else if(!CaptureIfKernel
)
158 if(OriginalSecurityDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
160 return STATUS_UNKNOWN_REVISION
;
163 *CapturedSecurityDescriptor
= OriginalSecurityDescriptor
;
164 return STATUS_SUCCESS
;
168 /* make a copy on the stack */
169 DescriptorCopy
= *OriginalSecurityDescriptor
;
172 if(DescriptorCopy
.Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
174 return STATUS_UNKNOWN_REVISION
;
177 if(DescriptorCopy
.Control
& SE_SELF_RELATIVE
)
179 /* in case we're dealing with a self-relative descriptor, do a basic convert
180 to an absolute descriptor. We do this so we can simply access the data
181 using the pointers without calculating them again. */
182 DescriptorCopy
.Control
&= ~SE_SELF_RELATIVE
;
183 if(DescriptorCopy
.Owner
!= NULL
)
185 DescriptorCopy
.Owner
= (PSID
)((ULONG_PTR
)OriginalSecurityDescriptor
+ (ULONG_PTR
)DescriptorCopy
.Owner
);
187 if(DescriptorCopy
.Group
!= NULL
)
189 DescriptorCopy
.Group
= (PSID
)((ULONG_PTR
)OriginalSecurityDescriptor
+ (ULONG_PTR
)DescriptorCopy
.Group
);
191 if(DescriptorCopy
.Dacl
!= NULL
)
193 DescriptorCopy
.Dacl
= (PACL
)((ULONG_PTR
)OriginalSecurityDescriptor
+ (ULONG_PTR
)DescriptorCopy
.Dacl
);
195 if(DescriptorCopy
.Sacl
!= NULL
)
197 DescriptorCopy
.Sacl
= (PACL
)((ULONG_PTR
)OriginalSecurityDescriptor
+ (ULONG_PTR
)DescriptorCopy
.Sacl
);
201 /* determine the size of the SIDs */
202 #define DetermineSIDSize(SidType) \
204 if(DescriptorCopy.SidType != NULL) \
206 SID *SidType = (SID*)DescriptorCopy.SidType; \
208 if(CurrentMode != KernelMode) \
210 /* securely access the buffers! */ \
213 ProbeForRead(&SidType->SubAuthorityCount, \
214 sizeof(SidType->SubAuthorityCount), \
216 SidType##SAC = SidType->SubAuthorityCount; \
217 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
218 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
219 ProbeForRead(SidType, \
222 if(!RtlValidSid(SidType)) \
224 Status = STATUS_INVALID_SID; \
229 Status = _SEH_GetExceptionCode(); \
233 if(!NT_SUCCESS(Status)) \
240 SidType##SAC = SidType->SubAuthorityCount; \
241 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
242 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
247 DetermineSIDSize(Owner
);
248 DetermineSIDSize(Group
);
250 /* determine the size of the ACLs */
251 #define DetermineACLSize(AclType, AclFlag) \
253 if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \
254 DescriptorCopy.AclType != NULL) \
256 PACL AclType = (PACL)DescriptorCopy.AclType; \
258 if(CurrentMode != KernelMode) \
260 /* securely access the buffers! */ \
263 ProbeForRead(&AclType->AclSize, \
264 sizeof(AclType->AclSize), \
266 AclType##Size = AclType->AclSize; \
267 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
268 ProbeForRead(AclType, \
271 if(!RtlValidAcl(AclType)) \
273 Status = STATUS_INVALID_ACL; \
278 Status = _SEH_GetExceptionCode(); \
282 if(!NT_SUCCESS(Status)) \
289 AclType##Size = AclType->AclSize; \
290 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
295 DescriptorCopy.AclType = NULL; \
299 DetermineACLSize(Sacl
, SACL
);
300 DetermineACLSize(Dacl
, DACL
);
302 /* allocate enough memory to store a complete copy of a self-relative
303 security descriptor */
304 NewDescriptor
= ExAllocatePool(PoolType
,
306 if(NewDescriptor
!= NULL
)
308 ULONG_PTR Offset
= sizeof(SECURITY_DESCRIPTOR
);
310 NewDescriptor
->Revision
= DescriptorCopy
.Revision
;
311 NewDescriptor
->Sbz1
= DescriptorCopy
.Sbz1
;
312 NewDescriptor
->Control
= DescriptorCopy
.Control
| SE_SELF_RELATIVE
;
316 /* setup the offsets and copy the SIDs and ACLs to the new
317 self-relative security descriptor. Probing the pointers is not
318 neccessary anymore as we did that when collecting the sizes! */
319 #define CopySIDOrACL(Type) \
321 if(DescriptorCopy.Type != NULL) \
323 NewDescriptor->Type = (PVOID)Offset; \
324 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
325 (ULONG_PTR)NewDescriptor->Type), \
326 DescriptorCopy.Type, \
328 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
339 Status
= _SEH_GetExceptionCode();
343 if(NT_SUCCESS(Status
))
345 /* we're finally done! copy the pointer to the captured descriptor to
347 *CapturedSecurityDescriptor
= NewDescriptor
;
348 return STATUS_SUCCESS
;
352 /* we failed to copy the data to the new descriptor */
353 ExFreePool(NewDescriptor
);
358 Status
= STATUS_INSUFFICIENT_RESOURCES
;
363 /* nothing to do... */
364 *CapturedSecurityDescriptor
= NULL
;
374 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation
,
375 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
376 IN OUT PULONG Length
,
377 IN PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor OPTIONAL
)
379 PSECURITY_DESCRIPTOR ObjectSd
;
384 ULONG OwnerLength
= 0;
385 ULONG GroupLength
= 0;
386 ULONG DaclLength
= 0;
387 ULONG SaclLength
= 0;
392 if (*ObjectsSecurityDescriptor
== NULL
)
394 if (*Length
< sizeof(SECURITY_DESCRIPTOR
))
396 *Length
= sizeof(SECURITY_DESCRIPTOR
);
397 return STATUS_BUFFER_TOO_SMALL
;
400 *Length
= sizeof(SECURITY_DESCRIPTOR
);
401 RtlCreateSecurityDescriptor(SecurityDescriptor
,
402 SECURITY_DESCRIPTOR_REVISION
);
403 SecurityDescriptor
->Control
|= SE_SELF_RELATIVE
;
404 return STATUS_SUCCESS
;
407 ObjectSd
= *ObjectsSecurityDescriptor
;
409 /* Calculate the required security descriptor length */
410 Control
= SE_SELF_RELATIVE
;
411 if ((*SecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
412 (ObjectSd
->Owner
!= NULL
))
414 Owner
= (PSID
)((ULONG_PTR
)ObjectSd
->Owner
+ (ULONG_PTR
)ObjectSd
);
415 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
416 Control
|= (ObjectSd
->Control
& SE_OWNER_DEFAULTED
);
419 if ((*SecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
420 (ObjectSd
->Group
!= NULL
))
422 Group
= (PSID
)((ULONG_PTR
)ObjectSd
->Group
+ (ULONG_PTR
)ObjectSd
);
423 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
424 Control
|= (ObjectSd
->Control
& SE_GROUP_DEFAULTED
);
427 if ((*SecurityInformation
& DACL_SECURITY_INFORMATION
) &&
428 (ObjectSd
->Control
& SE_DACL_PRESENT
))
430 if (ObjectSd
->Dacl
!= NULL
)
432 Dacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Dacl
+ (ULONG_PTR
)ObjectSd
);
433 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
435 Control
|= (ObjectSd
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
438 if ((*SecurityInformation
& SACL_SECURITY_INFORMATION
) &&
439 (ObjectSd
->Control
& SE_SACL_PRESENT
))
441 if (ObjectSd
->Sacl
!= NULL
)
443 Sacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Sacl
+ (ULONG_PTR
)ObjectSd
);
444 SaclLength
= ROUND_UP(Sacl
->AclSize
, 4);
446 Control
|= (ObjectSd
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
449 SdLength
= OwnerLength
+ GroupLength
+ DaclLength
+
450 SaclLength
+ sizeof(SECURITY_DESCRIPTOR
);
451 if (*Length
< sizeof(SECURITY_DESCRIPTOR
))
454 return STATUS_BUFFER_TOO_SMALL
;
457 /* Build the new security descrtiptor */
458 RtlCreateSecurityDescriptor(SecurityDescriptor
,
459 SECURITY_DESCRIPTOR_REVISION
);
460 SecurityDescriptor
->Control
= Control
;
462 Current
= (ULONG_PTR
)SecurityDescriptor
+ sizeof(SECURITY_DESCRIPTOR
);
464 if (OwnerLength
!= 0)
466 RtlCopyMemory((PVOID
)Current
,
469 SecurityDescriptor
->Owner
= (PSID
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
470 Current
+= OwnerLength
;
473 if (GroupLength
!= 0)
475 RtlCopyMemory((PVOID
)Current
,
478 SecurityDescriptor
->Group
= (PSID
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
479 Current
+= GroupLength
;
484 RtlCopyMemory((PVOID
)Current
,
487 SecurityDescriptor
->Dacl
= (PACL
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
488 Current
+= DaclLength
;
493 RtlCopyMemory((PVOID
)Current
,
496 SecurityDescriptor
->Sacl
= (PACL
)(Current
- (ULONG_PTR
)SecurityDescriptor
);
497 Current
+= SaclLength
;
502 return STATUS_SUCCESS
;
510 SeReleaseSecurityDescriptor(
511 IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
,
512 IN KPROCESSOR_MODE CurrentMode
,
513 IN BOOLEAN CaptureIfKernelMode
516 /* WARNING! You need to call this function with the same value for CurrentMode
517 and CaptureIfKernelMode that you previously passed to
518 SeCaptureSecurityDescriptor() in order to avoid memory leaks! */
519 if(CapturedSecurityDescriptor
!= NULL
&&
520 (CurrentMode
== UserMode
||
521 (CurrentMode
== KernelMode
&& CaptureIfKernelMode
)))
523 /* only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
524 ExFreePool(CapturedSecurityDescriptor
);
527 return STATUS_SUCCESS
;
534 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL
,
535 IN PSECURITY_INFORMATION SecurityInformation
,
536 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
537 IN OUT PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
,
538 IN POOL_TYPE PoolType
,
539 IN PGENERIC_MAPPING GenericMapping
)
542 return STATUS_NOT_IMPLEMENTED
;
550 SeSetSecurityDescriptorInfoEx(
551 IN PVOID Object OPTIONAL
,
552 IN PSECURITY_INFORMATION SecurityInformation
,
553 IN PSECURITY_DESCRIPTOR ModificationDescriptor
,
554 IN OUT PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
,
555 IN ULONG AutoInheritFlags
,
556 IN POOL_TYPE PoolType
,
557 IN PGENERIC_MAPPING GenericMapping
561 return STATUS_NOT_IMPLEMENTED
;
569 SeValidSecurityDescriptor(IN ULONG Length
,
570 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
576 if (Length
< SECURITY_DESCRIPTOR_MIN_LENGTH
)
578 DPRINT1("Invalid Security Descriptor revision\n");
582 if (SecurityDescriptor
->Revision
!= SECURITY_DESCRIPTOR_REVISION1
)
584 DPRINT1("Invalid Security Descriptor revision\n");
588 if (!(SecurityDescriptor
->Control
& SE_SELF_RELATIVE
))
590 DPRINT1("No self-relative Security Descriptor\n");
594 SdLength
= sizeof(SECURITY_DESCRIPTOR
);
596 /* Check Owner SID */
597 if (SecurityDescriptor
->Owner
== NULL
)
599 DPRINT1("No Owner SID\n");
603 if ((ULONG_PTR
)SecurityDescriptor
->Owner
% sizeof(ULONG
))
605 DPRINT1("Invalid Owner SID alignment\n");
609 Sid
= (PISID
)((ULONG_PTR
)SecurityDescriptor
+ (ULONG_PTR
)SecurityDescriptor
->Owner
);
610 if (Sid
->Revision
!= SID_REVISION
)
612 DPRINT1("Invalid Owner SID revision\n");
616 SdLength
+= (sizeof(SID
) + (Sid
->SubAuthorityCount
- 1) * sizeof(ULONG
));
617 if (Length
< SdLength
)
619 DPRINT1("Invalid Owner SID size\n");
623 /* Check Group SID */
624 if (SecurityDescriptor
->Group
!= NULL
)
626 if ((ULONG_PTR
)SecurityDescriptor
->Group
% sizeof(ULONG
))
628 DPRINT1("Invalid Group SID alignment\n");
632 Sid
= (PSID
)((ULONG_PTR
)SecurityDescriptor
+ (ULONG_PTR
)SecurityDescriptor
->Group
);
633 if (Sid
->Revision
!= SID_REVISION
)
635 DPRINT1("Invalid Group SID revision\n");
639 SdLength
+= (sizeof(SID
) + (Sid
->SubAuthorityCount
- 1) * sizeof(ULONG
));
640 if (Length
< SdLength
)
642 DPRINT1("Invalid Group SID size\n");
648 if (SecurityDescriptor
->Dacl
!= NULL
)
650 if ((ULONG_PTR
)SecurityDescriptor
->Dacl
% sizeof(ULONG
))
652 DPRINT1("Invalid DACL alignment\n");
656 Acl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ (ULONG_PTR
)SecurityDescriptor
->Dacl
);
657 if ((Acl
->AclRevision
< MIN_ACL_REVISION
) &&
658 (Acl
->AclRevision
> MAX_ACL_REVISION
))
660 DPRINT1("Invalid DACL revision\n");
664 SdLength
+= Acl
->AclSize
;
665 if (Length
< SdLength
)
667 DPRINT1("Invalid DACL size\n");
673 if (SecurityDescriptor
->Sacl
!= NULL
)
675 if ((ULONG_PTR
)SecurityDescriptor
->Sacl
% sizeof(ULONG
))
677 DPRINT1("Invalid SACL alignment\n");
681 Acl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ (ULONG_PTR
)SecurityDescriptor
->Sacl
);
682 if ((Acl
->AclRevision
< MIN_ACL_REVISION
) ||
683 (Acl
->AclRevision
> MAX_ACL_REVISION
))
685 DPRINT1("Invalid SACL revision\n");
689 SdLength
+= Acl
->AclSize
;
690 if (Length
< SdLength
)
692 DPRINT1("Invalid SACL size\n");