3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/semgr.c
6 * PURPOSE: Security manager
8 * PROGRAMMERS: No programmer listed.
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS ******************************************************************/
19 PSE_EXPORTS SeExports
= NULL
;
20 SE_EXPORTS SepExports
;
22 static ERESOURCE SepSubjectContextLock
;
23 extern ULONG ExpInitializationPhase
;
26 /* PROTOTYPES ***************************************************************/
28 static BOOLEAN
SepInitExports(VOID
);
30 /* FUNCTIONS ****************************************************************/
34 SepInitializationPhase0(VOID
)
37 if (!SepInitSecurityIDs()) return FALSE
;
38 if (!SepInitDACLs()) return FALSE
;
39 if (!SepInitSDs()) return FALSE
;
41 if (!SepInitExports()) return FALSE
;
43 /* Initialize the subject context lock */
44 ExInitializeResource(&SepSubjectContextLock
);
46 /* Initialize token objects */
47 SepInitializeTokenImplementation();
49 /* Clear impersonation info for the idle thread */
50 PsGetCurrentThread()->ImpersonationInfo
= NULL
;
51 PspClearCrossThreadFlag(PsGetCurrentThread(),
52 CT_ACTIVE_IMPERSONATION_INFO_BIT
);
54 /* Initialize the boot token */
55 ObInitializeFastReference(&PsGetCurrentProcess()->Token
, NULL
);
56 ObInitializeFastReference(&PsGetCurrentProcess()->Token
,
57 SepCreateSystemProcessToken());
63 SepInitializationPhase1(VOID
)
68 /* Insert the system token into the tree */
69 Status
= ObInsertObject((PVOID
)(PsGetCurrentProcess()->Token
.Value
&
76 ASSERT(NT_SUCCESS(Status
));
78 /* FIXME: TODO \\ Security directory */
86 /* Check the initialization phase */
87 switch (ExpInitializationPhase
)
92 return SepInitializationPhase0();
97 return SepInitializationPhase1();
101 /* Don't know any other phase! Bugcheck! */
102 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL
,
104 ExpInitializationPhase
,
115 OBJECT_ATTRIBUTES ObjectAttributes
;
117 HANDLE DirectoryHandle
;
121 /* Create '\Security' directory */
122 RtlInitUnicodeString(&Name
,
124 InitializeObjectAttributes(&ObjectAttributes
,
129 Status
= ZwCreateDirectoryObject(&DirectoryHandle
,
130 DIRECTORY_ALL_ACCESS
,
132 if (!NT_SUCCESS(Status
))
134 DPRINT1("Failed to create 'Security' directory!\n");
138 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
139 RtlInitUnicodeString(&Name
,
140 L
"\\LSA_AUTHENTICATION_INITALIZED");
141 InitializeObjectAttributes(&ObjectAttributes
,
146 Status
= ZwCreateEvent(&EventHandle
,
149 SynchronizationEvent
,
151 if (!NT_SUCCESS(Status
))
153 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
154 NtClose(DirectoryHandle
);
158 ZwClose(EventHandle
);
159 ZwClose(DirectoryHandle
);
161 /* FIXME: Create SRM port and listener thread */
167 static BOOLEAN INIT_FUNCTION
170 SepExports
.SeCreateTokenPrivilege
= SeCreateTokenPrivilege
;
171 SepExports
.SeAssignPrimaryTokenPrivilege
= SeAssignPrimaryTokenPrivilege
;
172 SepExports
.SeLockMemoryPrivilege
= SeLockMemoryPrivilege
;
173 SepExports
.SeIncreaseQuotaPrivilege
= SeIncreaseQuotaPrivilege
;
174 SepExports
.SeUnsolicitedInputPrivilege
= SeUnsolicitedInputPrivilege
;
175 SepExports
.SeTcbPrivilege
= SeTcbPrivilege
;
176 SepExports
.SeSecurityPrivilege
= SeSecurityPrivilege
;
177 SepExports
.SeTakeOwnershipPrivilege
= SeTakeOwnershipPrivilege
;
178 SepExports
.SeLoadDriverPrivilege
= SeLoadDriverPrivilege
;
179 SepExports
.SeCreatePagefilePrivilege
= SeCreatePagefilePrivilege
;
180 SepExports
.SeIncreaseBasePriorityPrivilege
= SeIncreaseBasePriorityPrivilege
;
181 SepExports
.SeSystemProfilePrivilege
= SeSystemProfilePrivilege
;
182 SepExports
.SeSystemtimePrivilege
= SeSystemtimePrivilege
;
183 SepExports
.SeProfileSingleProcessPrivilege
= SeProfileSingleProcessPrivilege
;
184 SepExports
.SeCreatePermanentPrivilege
= SeCreatePermanentPrivilege
;
185 SepExports
.SeBackupPrivilege
= SeBackupPrivilege
;
186 SepExports
.SeRestorePrivilege
= SeRestorePrivilege
;
187 SepExports
.SeShutdownPrivilege
= SeShutdownPrivilege
;
188 SepExports
.SeDebugPrivilege
= SeDebugPrivilege
;
189 SepExports
.SeAuditPrivilege
= SeAuditPrivilege
;
190 SepExports
.SeSystemEnvironmentPrivilege
= SeSystemEnvironmentPrivilege
;
191 SepExports
.SeChangeNotifyPrivilege
= SeChangeNotifyPrivilege
;
192 SepExports
.SeRemoteShutdownPrivilege
= SeRemoteShutdownPrivilege
;
194 SepExports
.SeNullSid
= SeNullSid
;
195 SepExports
.SeWorldSid
= SeWorldSid
;
196 SepExports
.SeLocalSid
= SeLocalSid
;
197 SepExports
.SeCreatorOwnerSid
= SeCreatorOwnerSid
;
198 SepExports
.SeCreatorGroupSid
= SeCreatorGroupSid
;
199 SepExports
.SeNtAuthoritySid
= SeNtAuthoritySid
;
200 SepExports
.SeDialupSid
= SeDialupSid
;
201 SepExports
.SeNetworkSid
= SeNetworkSid
;
202 SepExports
.SeBatchSid
= SeBatchSid
;
203 SepExports
.SeInteractiveSid
= SeInteractiveSid
;
204 SepExports
.SeLocalSystemSid
= SeLocalSystemSid
;
205 SepExports
.SeAliasAdminsSid
= SeAliasAdminsSid
;
206 SepExports
.SeAliasUsersSid
= SeAliasUsersSid
;
207 SepExports
.SeAliasGuestsSid
= SeAliasGuestsSid
;
208 SepExports
.SeAliasPowerUsersSid
= SeAliasPowerUsersSid
;
209 SepExports
.SeAliasAccountOpsSid
= SeAliasAccountOpsSid
;
210 SepExports
.SeAliasSystemOpsSid
= SeAliasSystemOpsSid
;
211 SepExports
.SeAliasPrintOpsSid
= SeAliasPrintOpsSid
;
212 SepExports
.SeAliasBackupOpsSid
= SeAliasBackupOpsSid
;
213 SepExports
.SeAuthenticatedUsersSid
= SeAuthenticatedUsersSid
;
214 SepExports
.SeRestrictedSid
= SeRestrictedSid
;
215 SepExports
.SeAnonymousLogonSid
= SeAnonymousLogonSid
;
217 SepExports
.SeUndockPrivilege
= SeUndockPrivilege
;
218 SepExports
.SeSyncAgentPrivilege
= SeSyncAgentPrivilege
;
219 SepExports
.SeEnableDelegationPrivilege
= SeEnableDelegationPrivilege
;
221 SeExports
= &SepExports
;
226 VOID
SepReferenceLogonSession(PLUID AuthenticationId
)
231 VOID
SepDeReferenceLogonSession(PLUID AuthenticationId
)
238 SeDefaultObjectMethod(PVOID Object
,
239 SECURITY_OPERATION_CODE OperationType
,
240 PSECURITY_INFORMATION _SecurityInformation
,
241 PSECURITY_DESCRIPTOR _SecurityDescriptor
,
243 PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
245 PGENERIC_MAPPING GenericMapping
)
247 PISECURITY_DESCRIPTOR ObjectSd
;
248 PISECURITY_DESCRIPTOR NewSd
;
249 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
250 POBJECT_HEADER Header
= OBJECT_TO_OBJECT_HEADER(Object
);
255 ULONG OwnerLength
= 0;
256 ULONG GroupLength
= 0;
257 ULONG DaclLength
= 0;
258 ULONG SaclLength
= 0;
262 SECURITY_INFORMATION SecurityInformation
;
264 if (OperationType
== SetSecurityDescriptor
)
266 ObjectSd
= Header
->SecurityDescriptor
;
267 SecurityInformation
= *_SecurityInformation
;
269 /* Get owner and owner size */
270 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
272 if (SecurityDescriptor
->Owner
!= NULL
)
274 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
275 Owner
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Owner
+
276 (ULONG_PTR
)SecurityDescriptor
);
278 Owner
= (PSID
)SecurityDescriptor
->Owner
;
279 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
281 Control
|= (SecurityDescriptor
->Control
& SE_OWNER_DEFAULTED
);
285 if (ObjectSd
->Owner
!= NULL
)
287 Owner
= (PSID
)((ULONG_PTR
)ObjectSd
->Owner
+ (ULONG_PTR
)ObjectSd
);
288 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
290 Control
|= (ObjectSd
->Control
& SE_OWNER_DEFAULTED
);
293 /* Get group and group size */
294 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
296 if (SecurityDescriptor
->Group
!= NULL
)
298 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
299 Group
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Group
+
300 (ULONG_PTR
)SecurityDescriptor
);
302 Group
= (PSID
)SecurityDescriptor
->Group
;
303 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
305 Control
|= (SecurityDescriptor
->Control
& SE_GROUP_DEFAULTED
);
309 if (ObjectSd
->Group
!= NULL
)
311 Group
= (PSID
)((ULONG_PTR
)ObjectSd
->Group
+ (ULONG_PTR
)ObjectSd
);
312 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
314 Control
|= (ObjectSd
->Control
& SE_GROUP_DEFAULTED
);
317 /* Get DACL and DACL size */
318 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
320 if ((SecurityDescriptor
->Control
& SE_DACL_PRESENT
) &&
321 (SecurityDescriptor
->Dacl
!= NULL
))
323 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
324 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
->Dacl
+
325 (ULONG_PTR
)SecurityDescriptor
);
327 Dacl
= (PACL
)SecurityDescriptor
->Dacl
;
329 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
331 Control
|= (SecurityDescriptor
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
335 if ((ObjectSd
->Control
& SE_DACL_PRESENT
) &&
336 (ObjectSd
->Dacl
!= NULL
))
338 Dacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Dacl
+ (ULONG_PTR
)ObjectSd
);
339 DaclLength
= ROUND_UP((ULONG
)Dacl
->AclSize
, 4);
341 Control
|= (ObjectSd
->Control
& (SE_DACL_DEFAULTED
| SE_DACL_PRESENT
));
344 /* Get SACL and SACL size */
345 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
347 if ((SecurityDescriptor
->Control
& SE_SACL_PRESENT
) &&
348 (SecurityDescriptor
->Sacl
!= NULL
))
350 if( SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
351 Sacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
->Sacl
+
352 (ULONG_PTR
)SecurityDescriptor
);
354 Sacl
= (PACL
)SecurityDescriptor
->Sacl
;
355 SaclLength
= ROUND_UP((ULONG
)Sacl
->AclSize
, 4);
357 Control
|= (SecurityDescriptor
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
361 if ((ObjectSd
->Control
& SE_SACL_PRESENT
) &&
362 (ObjectSd
->Sacl
!= NULL
))
364 Sacl
= (PACL
)((ULONG_PTR
)ObjectSd
->Sacl
+ (ULONG_PTR
)ObjectSd
);
365 SaclLength
= ROUND_UP((ULONG
)Sacl
->AclSize
, 4);
367 Control
|= (ObjectSd
->Control
& (SE_SACL_DEFAULTED
| SE_SACL_PRESENT
));
370 NewSd
= ExAllocatePool(NonPagedPool
,
371 sizeof(SECURITY_DESCRIPTOR
) + OwnerLength
+ GroupLength
+
372 DaclLength
+ SaclLength
);
375 ObDereferenceObject(Object
);
376 return STATUS_INSUFFICIENT_RESOURCES
;
379 RtlCreateSecurityDescriptor(NewSd
,
380 SECURITY_DESCRIPTOR_REVISION1
);
381 /* We always build a self-relative descriptor */
382 NewSd
->Control
= (USHORT
)Control
| SE_SELF_RELATIVE
;
384 Current
= (ULONG_PTR
)NewSd
+ sizeof(SECURITY_DESCRIPTOR
);
386 if (OwnerLength
!= 0)
388 RtlCopyMemory((PVOID
)Current
,
391 NewSd
->Owner
= (PSID
)(Current
- (ULONG_PTR
)NewSd
);
392 Current
+= OwnerLength
;
395 if (GroupLength
!= 0)
397 RtlCopyMemory((PVOID
)Current
,
400 NewSd
->Group
= (PSID
)(Current
- (ULONG_PTR
)NewSd
);
401 Current
+= GroupLength
;
406 RtlCopyMemory((PVOID
)Current
,
409 NewSd
->Dacl
= (PACL
)(Current
- (ULONG_PTR
)NewSd
);
410 Current
+= DaclLength
;
415 RtlCopyMemory((PVOID
)Current
,
418 NewSd
->Sacl
= (PACL
)(Current
- (ULONG_PTR
)NewSd
);
419 Current
+= SaclLength
;
423 Status
= ObpAddSecurityDescriptor(NewSd
,
424 &Header
->SecurityDescriptor
);
425 if (NT_SUCCESS(Status
))
427 /* Remove the old security descriptor */
428 ObpRemoveSecurityDescriptor(ObjectSd
);
432 /* Restore the old security descriptor */
433 Header
->SecurityDescriptor
= ObjectSd
;
438 else if (OperationType
== QuerySecurityDescriptor
)
440 Status
= SeQuerySecurityDescriptorInfo(_SecurityInformation
,
443 &Header
->SecurityDescriptor
);
445 else if (OperationType
== AssignSecurityDescriptor
)
447 /* Assign the security descriptor to the object header */
448 Status
= ObpAddSecurityDescriptor(SecurityDescriptor
,
449 &Header
->SecurityDescriptor
);
453 return STATUS_SUCCESS
;
458 SeCaptureSubjectContextEx(IN PETHREAD Thread
,
459 IN PEPROCESS Process
,
460 OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
462 BOOLEAN CopyOnOpen
, EffectiveOnly
;
465 /* Save the unique ID */
466 SubjectContext
->ProcessAuditId
= Process
->UniqueProcessId
;
468 /* Check if we have a thread */
471 /* We don't, so no token */
472 SubjectContext
->ClientToken
= NULL
;
476 /* Get the impersonation token */
477 SubjectContext
->ClientToken
=
478 PsReferenceImpersonationToken(Thread
,
481 &SubjectContext
->ImpersonationLevel
);
484 /* Get the primary token */
485 SubjectContext
->PrimaryToken
= PsReferencePrimaryToken(Process
);
493 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext
)
495 /* Call the internal API */
496 SeCaptureSubjectContextEx(PsGetCurrentThread(),
497 PsGetCurrentProcess(),
506 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
510 KeEnterCriticalRegion();
511 ExAcquireResourceExclusiveLite(&SepSubjectContextLock
, TRUE
);
519 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
523 ExReleaseResourceLite(&SepSubjectContextLock
);
524 KeLeaveCriticalRegion();
532 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
536 if (SubjectContext
->PrimaryToken
!= NULL
)
538 ObFastDereferenceObject(&PsGetCurrentProcess()->Token
, SubjectContext
->PrimaryToken
);
541 if (SubjectContext
->ClientToken
!= NULL
)
543 ObDereferenceObject(SubjectContext
->ClientToken
);
552 SeDeassignSecurity(PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
556 if (*SecurityDescriptor
!= NULL
)
558 ExFreePool(*SecurityDescriptor
);
559 *SecurityDescriptor
= NULL
;
562 return STATUS_SUCCESS
;
570 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL
,
571 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL
,
572 OUT PSECURITY_DESCRIPTOR
*NewDescriptor
,
573 IN GUID
*ObjectType OPTIONAL
,
574 IN BOOLEAN IsDirectoryObject
,
575 IN ULONG AutoInheritFlags
,
576 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
577 IN PGENERIC_MAPPING GenericMapping
,
578 IN POOL_TYPE PoolType
)
581 return STATUS_NOT_IMPLEMENTED
;
586 * FUNCTION: Creates a security descriptor for a new object.
589 * ExplicitDescriptor =
591 * IsDirectoryObject =
600 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL
,
601 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL
,
602 PSECURITY_DESCRIPTOR
*NewDescriptor
,
603 BOOLEAN IsDirectoryObject
,
604 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
605 PGENERIC_MAPPING GenericMapping
,
608 PISECURITY_DESCRIPTOR ParentDescriptor
= _ParentDescriptor
;
609 PISECURITY_DESCRIPTOR ExplicitDescriptor
= _ExplicitDescriptor
;
610 PISECURITY_DESCRIPTOR Descriptor
;
612 ULONG OwnerLength
= 0;
613 ULONG GroupLength
= 0;
614 ULONG DaclLength
= 0;
615 ULONG SaclLength
= 0;
626 /* Lock subject context */
627 SeLockSubjectContext(SubjectContext
);
629 if (SubjectContext
->ClientToken
!= NULL
)
631 Token
= SubjectContext
->ClientToken
;
635 Token
= SubjectContext
->PrimaryToken
;
639 /* Inherit the Owner SID */
640 if (ExplicitDescriptor
!= NULL
&& ExplicitDescriptor
->Owner
!= NULL
)
642 DPRINT("Use explicit owner sid!\n");
643 Owner
= ExplicitDescriptor
->Owner
;
645 if (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
)
647 Owner
= (PSID
)(((ULONG_PTR
)Owner
) + (ULONG_PTR
)ExplicitDescriptor
);
655 DPRINT("Use token owner sid!\n");
656 Owner
= Token
->UserAndGroups
[Token
->DefaultOwnerIndex
].Sid
;
660 DPRINT("Use default owner sid!\n");
661 Owner
= SeLocalSystemSid
;
664 Control
|= SE_OWNER_DEFAULTED
;
667 OwnerLength
= ROUND_UP(RtlLengthSid(Owner
), 4);
670 /* Inherit the Group SID */
671 if (ExplicitDescriptor
!= NULL
&& ExplicitDescriptor
->Group
!= NULL
)
673 DPRINT("Use explicit group sid!\n");
674 Group
= ExplicitDescriptor
->Group
;
675 if (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
)
677 Group
= (PSID
)(((ULONG_PTR
)Group
) + (ULONG_PTR
)ExplicitDescriptor
);
684 DPRINT("Use token group sid!\n");
685 Group
= Token
->PrimaryGroup
;
689 DPRINT("Use default group sid!\n");
690 Group
= SeLocalSystemSid
;
693 Control
|= SE_OWNER_DEFAULTED
;
696 GroupLength
= ROUND_UP(RtlLengthSid(Group
), 4);
699 /* Inherit the DACL */
700 if (ExplicitDescriptor
!= NULL
&&
701 (ExplicitDescriptor
->Control
& SE_DACL_PRESENT
) &&
702 !(ExplicitDescriptor
->Control
& SE_DACL_DEFAULTED
))
704 DPRINT("Use explicit DACL!\n");
705 Dacl
= ExplicitDescriptor
->Dacl
;
706 if (Dacl
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
))
708 Dacl
= (PACL
)(((ULONG_PTR
)Dacl
) + (ULONG_PTR
)ExplicitDescriptor
);
711 Control
|= SE_DACL_PRESENT
;
713 else if (ParentDescriptor
!= NULL
&&
714 (ParentDescriptor
->Control
& SE_DACL_PRESENT
))
716 DPRINT("Use parent DACL!\n");
718 Dacl
= ParentDescriptor
->Dacl
;
719 if (Dacl
!= NULL
&& (ParentDescriptor
->Control
& SE_SELF_RELATIVE
))
721 Dacl
= (PACL
)(((ULONG_PTR
)Dacl
) + (ULONG_PTR
)ParentDescriptor
);
723 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
725 else if (Token
!= NULL
&& Token
->DefaultDacl
!= NULL
)
727 DPRINT("Use token default DACL!\n");
729 Dacl
= Token
->DefaultDacl
;
730 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
734 DPRINT("Use NULL DACL!\n");
736 Control
|= (SE_DACL_PRESENT
| SE_DACL_DEFAULTED
);
739 DaclLength
= (Dacl
!= NULL
) ? ROUND_UP(Dacl
->AclSize
, 4) : 0;
742 /* Inherit the SACL */
743 if (ExplicitDescriptor
!= NULL
&&
744 (ExplicitDescriptor
->Control
& SE_SACL_PRESENT
) &&
745 !(ExplicitDescriptor
->Control
& SE_SACL_DEFAULTED
))
747 DPRINT("Use explicit SACL!\n");
748 Sacl
= ExplicitDescriptor
->Sacl
;
749 if (Sacl
!= NULL
&& (ExplicitDescriptor
->Control
& SE_SELF_RELATIVE
))
751 Sacl
= (PACL
)(((ULONG_PTR
)Sacl
) + (ULONG_PTR
)ExplicitDescriptor
);
754 Control
|= SE_SACL_PRESENT
;
756 else if (ParentDescriptor
!= NULL
&&
757 (ParentDescriptor
->Control
& SE_SACL_PRESENT
))
759 DPRINT("Use parent SACL!\n");
761 Sacl
= ParentDescriptor
->Sacl
;
762 if (Sacl
!= NULL
&& (ParentDescriptor
->Control
& SE_SELF_RELATIVE
))
764 Sacl
= (PACL
)(((ULONG_PTR
)Sacl
) + (ULONG_PTR
)ParentDescriptor
);
766 Control
|= (SE_SACL_PRESENT
| SE_SACL_DEFAULTED
);
769 SaclLength
= (Sacl
!= NULL
) ? ROUND_UP(Sacl
->AclSize
, 4) : 0;
772 /* Allocate and initialize the new security descriptor */
773 Length
= sizeof(SECURITY_DESCRIPTOR
) +
774 OwnerLength
+ GroupLength
+ DaclLength
+ SaclLength
;
776 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
777 sizeof(SECURITY_DESCRIPTOR
),
783 Descriptor
= ExAllocatePool(PagedPool
,
785 if (Descriptor
== NULL
)
787 DPRINT1("ExAlloctePool() failed\n");
788 /* FIXME: Unlock subject context */
789 return STATUS_INSUFFICIENT_RESOURCES
;
792 RtlZeroMemory( Descriptor
, Length
);
793 RtlCreateSecurityDescriptor(Descriptor
,
794 SECURITY_DESCRIPTOR_REVISION
);
796 Descriptor
->Control
= (USHORT
)Control
| SE_SELF_RELATIVE
;
798 Current
= (ULONG_PTR
)Descriptor
+ sizeof(SECURITY_DESCRIPTOR
);
802 RtlCopyMemory((PVOID
)Current
,
805 Descriptor
->Sacl
= (PACL
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
806 Current
+= SaclLength
;
811 RtlCopyMemory((PVOID
)Current
,
814 Descriptor
->Dacl
= (PACL
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
815 Current
+= DaclLength
;
818 if (OwnerLength
!= 0)
820 RtlCopyMemory((PVOID
)Current
,
823 Descriptor
->Owner
= (PSID
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
824 Current
+= OwnerLength
;
825 DPRINT("Owner of %x at %x\n", Descriptor
, Descriptor
->Owner
);
828 DPRINT("Owner of %x is zero length\n", Descriptor
);
830 if (GroupLength
!= 0)
832 memmove((PVOID
)Current
,
835 Descriptor
->Group
= (PSID
)((ULONG_PTR
)Current
- (ULONG_PTR
)Descriptor
);
838 /* Unlock subject context */
839 SeUnlockSubjectContext(SubjectContext
);
841 *NewDescriptor
= Descriptor
;
843 DPRINT("Descrptor %x\n", Descriptor
);
844 ASSERT(RtlLengthSecurityDescriptor(Descriptor
));
846 return STATUS_SUCCESS
;
851 SepSidInToken(PACCESS_TOKEN _Token
,
855 PTOKEN Token
= (PTOKEN
)_Token
;
859 if (Token
->UserAndGroupCount
== 0)
864 for (i
=0; i
<Token
->UserAndGroupCount
; i
++)
866 if (RtlEqualSid(Sid
, Token
->UserAndGroups
[i
].Sid
))
868 if (Token
->UserAndGroups
[i
].Attributes
& SE_GROUP_ENABLED
)
882 * FUNCTION: Determines whether the requested access rights can be granted
883 * to an object protected by a security descriptor and an object owner
885 * SecurityDescriptor = Security descriptor protecting the object
886 * SubjectSecurityContext = Subject's captured security context
887 * SubjectContextLocked = Indicates the user's subject context is locked
888 * DesiredAccess = Access rights the caller is trying to acquire
889 * PreviouslyGrantedAccess = Specified the access rights already granted
891 * GenericMapping = Generic mapping associated with the object
892 * AccessMode = Access mode used for the check
893 * GrantedAccess (OUT) = On return specifies the access granted
894 * AccessStatus (OUT) = Status indicating why access was denied
895 * RETURNS: If access was granted, returns TRUE
900 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
901 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
902 IN BOOLEAN SubjectContextLocked
,
903 IN ACCESS_MASK DesiredAccess
,
904 IN ACCESS_MASK PreviouslyGrantedAccess
,
905 OUT PPRIVILEGE_SET
* Privileges
,
906 IN PGENERIC_MAPPING GenericMapping
,
907 IN KPROCESSOR_MODE AccessMode
,
908 OUT PACCESS_MASK GrantedAccess
,
909 OUT PNTSTATUS AccessStatus
)
911 LUID_AND_ATTRIBUTES Privilege
;
912 ACCESS_MASK CurrentAccess
, AccessMask
;
923 /* Check if this is kernel mode */
924 if (AccessMode
== KernelMode
)
926 /* Check if kernel wants everything */
927 if (DesiredAccess
& MAXIMUM_ALLOWED
)
930 *GrantedAccess
= GenericMapping
->GenericAll
;
931 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
932 *GrantedAccess
|= PreviouslyGrantedAccess
;
936 /* Give the desired and previous access */
937 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
941 *AccessStatus
= STATUS_SUCCESS
;
945 /* Check if we didn't get an SD */
946 if (!SecurityDescriptor
)
948 /* Automatic failure */
949 *AccessStatus
= STATUS_ACCESS_DENIED
;
953 /* Check for invalid impersonation */
954 if ((SubjectSecurityContext
->ClientToken
) &&
955 (SubjectSecurityContext
->ImpersonationLevel
< SecurityImpersonation
))
957 *AccessStatus
= STATUS_BAD_IMPERSONATION_LEVEL
;
961 /* Check for no access desired */
964 /* Check if we had no previous access */
965 if (!PreviouslyGrantedAccess
)
967 /* Then there's nothing to give */
968 *AccessStatus
= STATUS_ACCESS_DENIED
;
972 /* Return the previous access only */
973 *GrantedAccess
= PreviouslyGrantedAccess
;
974 *AccessStatus
= STATUS_SUCCESS
;
979 /* Acquire the lock if needed */
980 if (!SubjectContextLocked
) SeLockSubjectContext(SubjectSecurityContext
);
982 /* Map given accesses */
983 RtlMapGenericMask(&DesiredAccess
, GenericMapping
);
984 if (PreviouslyGrantedAccess
)
985 RtlMapGenericMask(&PreviouslyGrantedAccess
, GenericMapping
);
989 CurrentAccess
= PreviouslyGrantedAccess
;
993 Token
= SubjectSecurityContext
->ClientToken
?
994 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
997 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
1001 if (!NT_SUCCESS(Status
))
1003 if (SubjectContextLocked
== FALSE
)
1005 SeUnlockSubjectContext(SubjectSecurityContext
);
1008 *AccessStatus
= Status
;
1012 /* RULE 1: Grant desired access if the object is unprotected */
1013 if (Present
== TRUE
&& Dacl
== NULL
)
1015 if (SubjectContextLocked
== FALSE
)
1017 SeUnlockSubjectContext(SubjectSecurityContext
);
1020 *GrantedAccess
= DesiredAccess
;
1021 *AccessStatus
= STATUS_SUCCESS
;
1025 CurrentAccess
= PreviouslyGrantedAccess
;
1027 /* RULE 2: Check token for 'take ownership' privilege */
1028 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
1029 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
1031 if (SepPrivilegeCheck(Token
,
1034 PRIVILEGE_SET_ALL_NECESSARY
,
1037 CurrentAccess
|= WRITE_OWNER
;
1038 if ((DesiredAccess
& ~VALID_INHERIT_FLAGS
) ==
1039 (CurrentAccess
& ~VALID_INHERIT_FLAGS
))
1041 if (SubjectContextLocked
== FALSE
)
1043 SeUnlockSubjectContext(SubjectSecurityContext
);
1046 *GrantedAccess
= CurrentAccess
;
1047 *AccessStatus
= STATUS_SUCCESS
;
1052 /* RULE 3: Check whether the token is the owner */
1053 Status
= RtlGetOwnerSecurityDescriptor(SecurityDescriptor
,
1056 if (!NT_SUCCESS(Status
))
1058 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status
);
1059 if (SubjectContextLocked
== FALSE
)
1061 SeUnlockSubjectContext(SubjectSecurityContext
);
1064 *AccessStatus
= Status
;
1068 if (Sid
&& SepSidInToken(Token
, Sid
))
1070 CurrentAccess
|= (READ_CONTROL
| WRITE_DAC
);
1071 if ((DesiredAccess
& ~VALID_INHERIT_FLAGS
) ==
1072 (CurrentAccess
& ~VALID_INHERIT_FLAGS
))
1074 if (SubjectContextLocked
== FALSE
)
1076 SeUnlockSubjectContext(SubjectSecurityContext
);
1079 *GrantedAccess
= CurrentAccess
;
1080 *AccessStatus
= STATUS_SUCCESS
;
1085 /* Fail if DACL is absent */
1086 if (Present
== FALSE
)
1088 if (SubjectContextLocked
== FALSE
)
1090 SeUnlockSubjectContext(SubjectSecurityContext
);
1094 *AccessStatus
= STATUS_ACCESS_DENIED
;
1098 /* RULE 4: Grant rights according to the DACL */
1099 CurrentAce
= (PACE
)(Dacl
+ 1);
1100 for (i
= 0; i
< Dacl
->AceCount
; i
++)
1102 Sid
= (PSID
)(CurrentAce
+ 1);
1103 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
1105 if (SepSidInToken(Token
, Sid
))
1107 if (SubjectContextLocked
== FALSE
)
1109 SeUnlockSubjectContext(SubjectSecurityContext
);
1113 *AccessStatus
= STATUS_ACCESS_DENIED
;
1118 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
1120 if (SepSidInToken(Token
, Sid
))
1122 AccessMask
= CurrentAce
->AccessMask
;
1123 RtlMapGenericMask(&AccessMask
, GenericMapping
);
1124 CurrentAccess
|= AccessMask
;
1129 DPRINT1("Unknown Ace type 0x%lx\n", CurrentAce
->Header
.AceType
);
1131 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
1134 if (SubjectContextLocked
== FALSE
)
1136 SeUnlockSubjectContext(SubjectSecurityContext
);
1139 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
1140 CurrentAccess
, DesiredAccess
);
1142 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
1144 if (DesiredAccess
& MAXIMUM_ALLOWED
)
1146 *GrantedAccess
= CurrentAccess
;
1147 *AccessStatus
= STATUS_SUCCESS
;
1150 else if ((*GrantedAccess
& ~VALID_INHERIT_FLAGS
) ==
1151 (DesiredAccess
& ~VALID_INHERIT_FLAGS
))
1153 *AccessStatus
= STATUS_SUCCESS
;
1158 DPRINT1("Denying access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p)\n",
1159 *GrantedAccess
, DesiredAccess
, GenericMapping
);
1160 *AccessStatus
= STATUS_ACCESS_DENIED
;
1167 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1168 IN HANDLE TokenHandle
,
1169 IN ACCESS_MASK DesiredAccess
,
1170 IN PGENERIC_MAPPING GenericMapping
,
1171 OUT PPRIVILEGE_SET PrivilegeSet
,
1172 OUT PULONG ReturnLength
,
1173 OUT PACCESS_MASK GrantedAccess
,
1174 OUT PNTSTATUS AccessStatus
)
1176 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
= {0};
1177 KPROCESSOR_MODE PreviousMode
;
1183 DPRINT("NtAccessCheck() called\n");
1185 PreviousMode
= KeGetPreviousMode();
1186 if (PreviousMode
== KernelMode
)
1188 *GrantedAccess
= DesiredAccess
;
1189 *AccessStatus
= STATUS_SUCCESS
;
1190 return STATUS_SUCCESS
;
1193 Status
= ObReferenceObjectByHandle(TokenHandle
,
1199 if (!NT_SUCCESS(Status
))
1201 DPRINT1("Failed to reference token (Status %lx)\n", Status
);
1205 /* Check token type */
1206 if (Token
->TokenType
!= TokenImpersonation
)
1208 DPRINT1("No impersonation token\n");
1209 ObDereferenceObject(Token
);
1210 return STATUS_ACCESS_VIOLATION
;
1213 /* Check impersonation level */
1214 if (Token
->ImpersonationLevel
< SecurityAnonymous
)
1216 DPRINT1("Invalid impersonation level\n");
1217 ObDereferenceObject(Token
);
1218 return STATUS_ACCESS_VIOLATION
;
1221 SubjectSecurityContext
.ClientToken
= Token
;
1222 SubjectSecurityContext
.ImpersonationLevel
= Token
->ImpersonationLevel
;
1224 /* Lock subject context */
1225 SeLockSubjectContext(&SubjectSecurityContext
);
1227 if (SeAccessCheck(SecurityDescriptor
,
1228 &SubjectSecurityContext
,
1238 Status
= *AccessStatus
;
1242 Status
= STATUS_ACCESS_DENIED
;
1245 /* Unlock subject context */
1246 SeUnlockSubjectContext(&SubjectSecurityContext
);
1248 ObDereferenceObject(Token
);
1250 DPRINT("NtAccessCheck() done\n");
1257 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1258 IN PSID PrincipalSelfSid
,
1259 IN HANDLE ClientToken
,
1260 IN ACCESS_MASK DesiredAccess
,
1261 IN POBJECT_TYPE_LIST ObjectTypeList
,
1262 IN ULONG ObjectTypeLength
,
1263 IN PGENERIC_MAPPING GenericMapping
,
1264 IN PPRIVILEGE_SET PrivilegeSet
,
1265 IN ULONG PrivilegeSetLength
,
1266 OUT PACCESS_MASK GrantedAccess
,
1267 OUT PNTSTATUS AccessStatus
)
1270 return STATUS_NOT_IMPLEMENTED
;
1275 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1277 IN PUNICODE_STRING ObjectTypeName
,
1278 IN PUNICODE_STRING ObjectName
,
1279 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1280 IN PSID PrincipalSelfSid
,
1281 IN ACCESS_MASK DesiredAccess
,
1282 IN AUDIT_EVENT_TYPE AuditType
,
1284 IN POBJECT_TYPE_LIST ObjectTypeList
,
1285 IN ULONG ObjectTypeLength
,
1286 IN PGENERIC_MAPPING GenericMapping
,
1287 IN BOOLEAN ObjectCreation
,
1288 OUT PACCESS_MASK GrantedAccess
,
1289 OUT PNTSTATUS AccessStatus
,
1290 OUT PBOOLEAN GenerateOnClose
)
1293 return STATUS_NOT_IMPLEMENTED
;
1298 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1299 IN PSID PrincipalSelfSid
,
1300 IN HANDLE ClientToken
,
1301 IN ACCESS_MASK DesiredAccess
,
1302 IN POBJECT_TYPE_LIST ObjectTypeList
,
1303 IN ULONG ObjectTypeLength
,
1304 IN PGENERIC_MAPPING GenericMapping
,
1305 IN PPRIVILEGE_SET PrivilegeSet
,
1306 IN ULONG PrivilegeSetLength
,
1307 OUT PACCESS_MASK GrantedAccess
,
1308 OUT PNTSTATUS AccessStatus
)
1311 return STATUS_NOT_IMPLEMENTED
;
1316 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1318 IN PUNICODE_STRING ObjectTypeName
,
1319 IN PUNICODE_STRING ObjectName
,
1320 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1321 IN PSID PrincipalSelfSid
,
1322 IN ACCESS_MASK DesiredAccess
,
1323 IN AUDIT_EVENT_TYPE AuditType
,
1325 IN POBJECT_TYPE_LIST ObjectTypeList
,
1326 IN ULONG ObjectTypeLength
,
1327 IN PGENERIC_MAPPING GenericMapping
,
1328 IN BOOLEAN ObjectCreation
,
1329 OUT PACCESS_MASK GrantedAccess
,
1330 OUT PNTSTATUS AccessStatus
,
1331 OUT PBOOLEAN GenerateOnClose
)
1334 return STATUS_NOT_IMPLEMENTED
;
1339 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName
,
1341 IN HANDLE ClientToken
,
1342 IN PUNICODE_STRING ObjectTypeName
,
1343 IN PUNICODE_STRING ObjectName
,
1344 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1345 IN PSID PrincipalSelfSid
,
1346 IN ACCESS_MASK DesiredAccess
,
1347 IN AUDIT_EVENT_TYPE AuditType
,
1349 IN POBJECT_TYPE_LIST ObjectTypeList
,
1350 IN ULONG ObjectTypeLength
,
1351 IN PGENERIC_MAPPING GenericMapping
,
1352 IN BOOLEAN ObjectCreation
,
1353 OUT PACCESS_MASK GrantedAccess
,
1354 OUT PNTSTATUS AccessStatus
,
1355 OUT PBOOLEAN GenerateOnClose
)
1358 return STATUS_NOT_IMPLEMENTED
;
1362 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
1363 OUT PACCESS_MASK DesiredAccess
)
1365 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
|
1366 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
))
1368 *DesiredAccess
|= READ_CONTROL
;
1370 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
1372 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1377 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
1378 OUT PACCESS_MASK DesiredAccess
)
1380 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1382 *DesiredAccess
|= WRITE_OWNER
;
1384 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
1386 *DesiredAccess
|= WRITE_DAC
;
1388 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
1390 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;