2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/semgr.c
5 * PURPOSE: Security manager
7 * PROGRAMMERS: No programmer listed.
10 /* INCLUDES *******************************************************************/
16 /* GLOBALS ********************************************************************/
18 PSE_EXPORTS SeExports
= NULL
;
19 SE_EXPORTS SepExports
;
20 ULONG SidInTokenCalls
= 0;
22 extern ULONG ExpInitializationPhase
;
23 extern ERESOURCE SepSubjectContextLock
;
25 /* PRIVATE FUNCTIONS **********************************************************/
31 SepExports
.SeCreateTokenPrivilege
= SeCreateTokenPrivilege
;
32 SepExports
.SeAssignPrimaryTokenPrivilege
= SeAssignPrimaryTokenPrivilege
;
33 SepExports
.SeLockMemoryPrivilege
= SeLockMemoryPrivilege
;
34 SepExports
.SeIncreaseQuotaPrivilege
= SeIncreaseQuotaPrivilege
;
35 SepExports
.SeUnsolicitedInputPrivilege
= SeUnsolicitedInputPrivilege
;
36 SepExports
.SeTcbPrivilege
= SeTcbPrivilege
;
37 SepExports
.SeSecurityPrivilege
= SeSecurityPrivilege
;
38 SepExports
.SeTakeOwnershipPrivilege
= SeTakeOwnershipPrivilege
;
39 SepExports
.SeLoadDriverPrivilege
= SeLoadDriverPrivilege
;
40 SepExports
.SeCreatePagefilePrivilege
= SeCreatePagefilePrivilege
;
41 SepExports
.SeIncreaseBasePriorityPrivilege
= SeIncreaseBasePriorityPrivilege
;
42 SepExports
.SeSystemProfilePrivilege
= SeSystemProfilePrivilege
;
43 SepExports
.SeSystemtimePrivilege
= SeSystemtimePrivilege
;
44 SepExports
.SeProfileSingleProcessPrivilege
= SeProfileSingleProcessPrivilege
;
45 SepExports
.SeCreatePermanentPrivilege
= SeCreatePermanentPrivilege
;
46 SepExports
.SeBackupPrivilege
= SeBackupPrivilege
;
47 SepExports
.SeRestorePrivilege
= SeRestorePrivilege
;
48 SepExports
.SeShutdownPrivilege
= SeShutdownPrivilege
;
49 SepExports
.SeDebugPrivilege
= SeDebugPrivilege
;
50 SepExports
.SeAuditPrivilege
= SeAuditPrivilege
;
51 SepExports
.SeSystemEnvironmentPrivilege
= SeSystemEnvironmentPrivilege
;
52 SepExports
.SeChangeNotifyPrivilege
= SeChangeNotifyPrivilege
;
53 SepExports
.SeRemoteShutdownPrivilege
= SeRemoteShutdownPrivilege
;
55 SepExports
.SeNullSid
= SeNullSid
;
56 SepExports
.SeWorldSid
= SeWorldSid
;
57 SepExports
.SeLocalSid
= SeLocalSid
;
58 SepExports
.SeCreatorOwnerSid
= SeCreatorOwnerSid
;
59 SepExports
.SeCreatorGroupSid
= SeCreatorGroupSid
;
60 SepExports
.SeNtAuthoritySid
= SeNtAuthoritySid
;
61 SepExports
.SeDialupSid
= SeDialupSid
;
62 SepExports
.SeNetworkSid
= SeNetworkSid
;
63 SepExports
.SeBatchSid
= SeBatchSid
;
64 SepExports
.SeInteractiveSid
= SeInteractiveSid
;
65 SepExports
.SeLocalSystemSid
= SeLocalSystemSid
;
66 SepExports
.SeAliasAdminsSid
= SeAliasAdminsSid
;
67 SepExports
.SeAliasUsersSid
= SeAliasUsersSid
;
68 SepExports
.SeAliasGuestsSid
= SeAliasGuestsSid
;
69 SepExports
.SeAliasPowerUsersSid
= SeAliasPowerUsersSid
;
70 SepExports
.SeAliasAccountOpsSid
= SeAliasAccountOpsSid
;
71 SepExports
.SeAliasSystemOpsSid
= SeAliasSystemOpsSid
;
72 SepExports
.SeAliasPrintOpsSid
= SeAliasPrintOpsSid
;
73 SepExports
.SeAliasBackupOpsSid
= SeAliasBackupOpsSid
;
74 SepExports
.SeAuthenticatedUsersSid
= SeAuthenticatedUsersSid
;
75 SepExports
.SeRestrictedSid
= SeRestrictedSid
;
76 SepExports
.SeAnonymousLogonSid
= SeAnonymousLogonSid
;
78 SepExports
.SeUndockPrivilege
= SeUndockPrivilege
;
79 SepExports
.SeSyncAgentPrivilege
= SeSyncAgentPrivilege
;
80 SepExports
.SeEnableDelegationPrivilege
= SeEnableDelegationPrivilege
;
82 SeExports
= &SepExports
;
90 SepInitializationPhase0(VOID
)
95 if (!SepInitSecurityIDs()) return FALSE
;
96 if (!SepInitDACLs()) return FALSE
;
97 if (!SepInitSDs()) return FALSE
;
99 if (!SepInitExports()) return FALSE
;
101 /* Initialize the subject context lock */
102 ExInitializeResource(&SepSubjectContextLock
);
104 /* Initialize token objects */
105 SepInitializeTokenImplementation();
107 /* Clear impersonation info for the idle thread */
108 PsGetCurrentThread()->ImpersonationInfo
= NULL
;
109 PspClearCrossThreadFlag(PsGetCurrentThread(),
110 CT_ACTIVE_IMPERSONATION_INFO_BIT
);
112 /* Initialize the boot token */
113 ObInitializeFastReference(&PsGetCurrentProcess()->Token
, NULL
);
114 ObInitializeFastReference(&PsGetCurrentProcess()->Token
,
115 SepCreateSystemProcessToken());
122 SepInitializationPhase1(VOID
)
128 /* Insert the system token into the tree */
129 Status
= ObInsertObject((PVOID
)(PsGetCurrentProcess()->Token
.Value
&
136 ASSERT(NT_SUCCESS(Status
));
138 /* FIXME: TODO \\ Security directory */
147 /* Check the initialization phase */
148 switch (ExpInitializationPhase
)
153 return SepInitializationPhase0();
158 return SepInitializationPhase1();
162 /* Don't know any other phase! Bugcheck! */
163 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL
,
165 ExpInitializationPhase
,
177 OBJECT_ATTRIBUTES ObjectAttributes
;
179 HANDLE DirectoryHandle
;
183 /* Create '\Security' directory */
184 RtlInitUnicodeString(&Name
, L
"\\Security");
185 InitializeObjectAttributes(&ObjectAttributes
,
190 Status
= ZwCreateDirectoryObject(&DirectoryHandle
,
191 DIRECTORY_ALL_ACCESS
,
193 if (!NT_SUCCESS(Status
))
195 DPRINT1("Failed to create 'Security' directory!\n");
199 /* Create 'LSA_AUTHENTICATION_INITIALIZED' event */
200 RtlInitUnicodeString(&Name
, L
"\\LSA_AUTHENTICATION_INITIALIZED");
201 InitializeObjectAttributes(&ObjectAttributes
,
206 Status
= ZwCreateEvent(&EventHandle
,
209 SynchronizationEvent
,
211 if (!NT_SUCCESS(Status
))
213 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITIALIZED' event!\n");
214 NtClose(DirectoryHandle
);
218 ZwClose(EventHandle
);
219 ZwClose(DirectoryHandle
);
221 /* FIXME: Create SRM port and listener thread */
228 SeDefaultObjectMethod(IN PVOID Object
,
229 IN SECURITY_OPERATION_CODE OperationType
,
230 IN PSECURITY_INFORMATION SecurityInformation
,
231 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
232 IN OUT PULONG ReturnLength OPTIONAL
,
233 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
234 IN POOL_TYPE PoolType
,
235 IN PGENERIC_MAPPING GenericMapping
)
239 /* Select the operation type */
240 switch (OperationType
)
242 /* Setting a new descriptor */
243 case SetSecurityDescriptor
:
246 ASSERT((PoolType
== PagedPool
) || (PoolType
== NonPagedPool
));
248 /* Set the information */
249 return ObSetSecurityDescriptorInfo(Object
,
252 OldSecurityDescriptor
,
256 case QuerySecurityDescriptor
:
258 /* Query the information */
259 return ObQuerySecurityDescriptorInfo(Object
,
263 OldSecurityDescriptor
);
265 case DeleteSecurityDescriptor
:
268 return ObDeassignSecurity(OldSecurityDescriptor
);
270 case AssignSecurityDescriptor
:
273 ObAssignObjectSecurityDescriptor(Object
, SecurityDescriptor
, PoolType
);
274 return STATUS_SUCCESS
;
279 KeBugCheckEx(SECURITY_SYSTEM
, 0, STATUS_INVALID_PARAMETER
, 0, 0);
282 /* Should never reach here */
284 return STATUS_SUCCESS
;
289 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
290 OUT PACCESS_MASK DesiredAccess
)
294 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
|
295 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
))
297 *DesiredAccess
|= READ_CONTROL
;
300 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
302 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
308 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
309 OUT PACCESS_MASK DesiredAccess
)
313 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
315 *DesiredAccess
|= WRITE_OWNER
;
318 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
320 *DesiredAccess
|= WRITE_DAC
;
323 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
325 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
330 #define OLD_ACCESS_CHECK
333 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
334 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
335 IN ACCESS_MASK DesiredAccess
,
336 IN ACCESS_MASK PreviouslyGrantedAccess
,
337 OUT PPRIVILEGE_SET
* Privileges
,
338 IN PGENERIC_MAPPING GenericMapping
,
339 IN KPROCESSOR_MODE AccessMode
,
340 OUT PACCESS_MASK GrantedAccess
,
341 OUT PNTSTATUS AccessStatus
)
343 LUID_AND_ATTRIBUTES Privilege
;
344 #ifdef OLD_ACCESS_CHECK
345 ACCESS_MASK CurrentAccess
, AccessMask
;
347 ACCESS_MASK RemainingAccess
;
348 ACCESS_MASK TempAccess
;
349 ACCESS_MASK TempGrantedAccess
= 0;
350 ACCESS_MASK TempDeniedAccess
= 0;
361 /* Check for no access desired */
364 /* Check if we had no previous access */
365 if (!PreviouslyGrantedAccess
)
367 /* Then there's nothing to give */
368 *AccessStatus
= STATUS_ACCESS_DENIED
;
372 /* Return the previous access only */
373 *GrantedAccess
= PreviouslyGrantedAccess
;
374 *AccessStatus
= STATUS_SUCCESS
;
379 /* Map given accesses */
380 RtlMapGenericMask(&DesiredAccess
, GenericMapping
);
381 if (PreviouslyGrantedAccess
)
382 RtlMapGenericMask(&PreviouslyGrantedAccess
, GenericMapping
);
384 #ifdef OLD_ACCESS_CHECK
385 CurrentAccess
= PreviouslyGrantedAccess
;
387 /* Initialize remaining access rights */
388 RemainingAccess
= DesiredAccess
;
390 Token
= SubjectSecurityContext
->ClientToken
?
391 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
393 /* Check for system security access */
394 if (RemainingAccess
& ACCESS_SYSTEM_SECURITY
)
396 Privilege
.Luid
= SeSecurityPrivilege
;
397 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
399 /* Fail if we do not the SeSecurityPrivilege */
400 if (!SepPrivilegeCheck(Token
,
403 PRIVILEGE_SET_ALL_NECESSARY
,
406 *AccessStatus
= STATUS_PRIVILEGE_NOT_HELD
;
410 /* Adjust access rights */
411 RemainingAccess
&= ~ACCESS_SYSTEM_SECURITY
;
412 PreviouslyGrantedAccess
|= ACCESS_SYSTEM_SECURITY
;
414 /* Succeed if there are no more rights to grant */
415 if (RemainingAccess
== 0)
417 *GrantedAccess
= PreviouslyGrantedAccess
;
418 *AccessStatus
= STATUS_SUCCESS
;
424 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
428 if (!NT_SUCCESS(Status
))
430 *AccessStatus
= Status
;
434 /* RULE 1: Grant desired access if the object is unprotected */
435 if (Present
== FALSE
|| Dacl
== NULL
)
437 if (DesiredAccess
& MAXIMUM_ALLOWED
)
439 *GrantedAccess
= GenericMapping
->GenericAll
;
440 *GrantedAccess
|= (DesiredAccess
& ~MAXIMUM_ALLOWED
);
444 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
447 *AccessStatus
= STATUS_SUCCESS
;
451 #ifdef OLD_ACCESS_CHECK
452 CurrentAccess
= PreviouslyGrantedAccess
;
455 /* RULE 2: Check token for 'take ownership' privilege */
456 if (DesiredAccess
& WRITE_OWNER
)
458 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
459 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
461 if (SepPrivilegeCheck(Token
,
464 PRIVILEGE_SET_ALL_NECESSARY
,
467 /* Adjust access rights */
468 RemainingAccess
&= ~WRITE_OWNER
;
469 PreviouslyGrantedAccess
|= WRITE_OWNER
;
470 #ifdef OLD_ACCESS_CHECK
471 CurrentAccess
|= WRITE_OWNER
;
474 /* Succeed if there are no more rights to grant */
475 if (RemainingAccess
== 0)
477 *GrantedAccess
= PreviouslyGrantedAccess
;
478 *AccessStatus
= STATUS_SUCCESS
;
484 /* Deny access if the DACL is empty */
485 if (Dacl
->AceCount
== 0)
487 if (RemainingAccess
== MAXIMUM_ALLOWED
&& PreviouslyGrantedAccess
!= 0)
489 *GrantedAccess
= PreviouslyGrantedAccess
;
490 *AccessStatus
= STATUS_SUCCESS
;
496 *AccessStatus
= STATUS_ACCESS_DENIED
;
501 /* Fail if DACL is absent */
502 if (Present
== FALSE
)
505 *AccessStatus
= STATUS_ACCESS_DENIED
;
509 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
510 if (DesiredAccess
& MAXIMUM_ALLOWED
)
512 CurrentAce
= (PACE
)(Dacl
+ 1);
513 for (i
= 0; i
< Dacl
->AceCount
; i
++)
515 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
517 Sid
= (PSID
)(CurrentAce
+ 1);
518 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
520 if (SepSidInToken(Token
, Sid
))
522 /* Map access rights from the ACE */
523 TempAccess
= CurrentAce
->AccessMask
;
524 RtlMapGenericMask(&TempAccess
, GenericMapping
);
526 /* Deny access rights that have not been granted yet */
527 TempDeniedAccess
|= (TempAccess
& ~TempGrantedAccess
);
530 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
532 if (SepSidInToken(Token
, Sid
))
534 /* Map access rights from the ACE */
535 TempAccess
= CurrentAce
->AccessMask
;
536 RtlMapGenericMask(&TempAccess
, GenericMapping
);
538 /* Grant access rights that have not been denied yet */
539 TempGrantedAccess
|= (TempAccess
& ~TempDeniedAccess
);
544 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
548 /* Get the next ACE */
549 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
552 /* Fail if some rights have not been granted */
553 RemainingAccess
&= ~(MAXIMUM_ALLOWED
| TempGrantedAccess
);
554 if (RemainingAccess
!= 0)
557 *AccessStatus
= STATUS_ACCESS_DENIED
;
561 /* Set granted access right and access status */
562 *GrantedAccess
= TempGrantedAccess
| PreviouslyGrantedAccess
;
563 if (*GrantedAccess
!= 0)
565 *AccessStatus
= STATUS_SUCCESS
;
570 *AccessStatus
= STATUS_ACCESS_DENIED
;
575 /* RULE 4: Grant rights according to the DACL */
576 CurrentAce
= (PACE
)(Dacl
+ 1);
577 for (i
= 0; i
< Dacl
->AceCount
; i
++)
579 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
581 Sid
= (PSID
)(CurrentAce
+ 1);
582 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
584 if (SepSidInToken(Token
, Sid
))
586 #ifdef OLD_ACCESS_CHECK
588 *AccessStatus
= STATUS_ACCESS_DENIED
;
591 /* Map access rights from the ACE */
592 TempAccess
= CurrentAce
->AccessMask
;
593 RtlMapGenericMask(&TempAccess
, GenericMapping
);
595 /* Leave if a remaining right must be denied */
596 if (RemainingAccess
& TempAccess
)
601 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
603 if (SepSidInToken(Token
, Sid
))
605 #ifdef OLD_ACCESS_CHECK
606 AccessMask
= CurrentAce
->AccessMask
;
607 RtlMapGenericMask(&AccessMask
, GenericMapping
);
608 CurrentAccess
|= AccessMask
;
610 /* Map access rights from the ACE */
611 TempAccess
= CurrentAce
->AccessMask
;
612 RtlMapGenericMask(&TempAccess
, GenericMapping
);
614 /* Remove granted rights */
615 RemainingAccess
&= ~TempAccess
;
621 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
625 /* Get the next ACE */
626 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
629 #ifdef OLD_ACCESS_CHECK
630 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
631 CurrentAccess
, DesiredAccess
);
633 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
635 if ((*GrantedAccess
& ~VALID_INHERIT_FLAGS
) ==
636 (DesiredAccess
& ~VALID_INHERIT_FLAGS
))
638 *AccessStatus
= STATUS_SUCCESS
;
643 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
644 *GrantedAccess
, DesiredAccess
, GenericMapping
);
645 //*AccessStatus = STATUS_ACCESS_DENIED;
647 *GrantedAccess
= DesiredAccess
;
648 *AccessStatus
= STATUS_SUCCESS
;
652 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
653 DesiredAccess
, PreviouslyGrantedAccess
, RemainingAccess
);
655 /* Fail if some rights have not been granted */
656 if (RemainingAccess
!= 0)
659 *AccessStatus
= STATUS_ACCESS_DENIED
;
663 /* Set granted access rights */
664 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
666 DPRINT("GrantedAccess %08lx\n", *GrantedAccess
);
668 /* Fail if no rights have been granted */
669 if (*GrantedAccess
== 0)
671 *AccessStatus
= STATUS_ACCESS_DENIED
;
675 *AccessStatus
= STATUS_SUCCESS
;
681 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
683 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
686 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
687 Owner
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Owner
+
688 (ULONG_PTR
)SecurityDescriptor
);
690 Owner
= (PSID
)SecurityDescriptor
->Owner
;
696 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
698 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
701 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
702 Group
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Group
+
703 (ULONG_PTR
)SecurityDescriptor
);
705 Group
= (PSID
)SecurityDescriptor
->Group
;
711 /* PUBLIC FUNCTIONS ***********************************************************/
718 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
719 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
720 IN BOOLEAN SubjectContextLocked
,
721 IN ACCESS_MASK DesiredAccess
,
722 IN ACCESS_MASK PreviouslyGrantedAccess
,
723 OUT PPRIVILEGE_SET
* Privileges
,
724 IN PGENERIC_MAPPING GenericMapping
,
725 IN KPROCESSOR_MODE AccessMode
,
726 OUT PACCESS_MASK GrantedAccess
,
727 OUT PNTSTATUS AccessStatus
)
733 /* Check if this is kernel mode */
734 if (AccessMode
== KernelMode
)
736 /* Check if kernel wants everything */
737 if (DesiredAccess
& MAXIMUM_ALLOWED
)
740 *GrantedAccess
= GenericMapping
->GenericAll
;
741 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
742 *GrantedAccess
|= PreviouslyGrantedAccess
;
746 /* Give the desired and previous access */
747 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
751 *AccessStatus
= STATUS_SUCCESS
;
755 /* Check if we didn't get an SD */
756 if (!SecurityDescriptor
)
758 /* Automatic failure */
759 *AccessStatus
= STATUS_ACCESS_DENIED
;
763 /* Check for invalid impersonation */
764 if ((SubjectSecurityContext
->ClientToken
) &&
765 (SubjectSecurityContext
->ImpersonationLevel
< SecurityImpersonation
))
767 *AccessStatus
= STATUS_BAD_IMPERSONATION_LEVEL
;
771 /* Acquire the lock if needed */
772 if (!SubjectContextLocked
)
773 SeLockSubjectContext(SubjectSecurityContext
);
775 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
776 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
778 PACCESS_TOKEN Token
= SubjectSecurityContext
->ClientToken
?
779 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
781 if (SepTokenIsOwner(Token
,
785 if (DesiredAccess
& MAXIMUM_ALLOWED
)
786 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
788 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
790 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
794 if (DesiredAccess
== 0)
796 *GrantedAccess
= PreviouslyGrantedAccess
;
797 *AccessStatus
= STATUS_SUCCESS
;
802 /* Call the internal function */
803 ret
= SepAccessCheck(SecurityDescriptor
,
804 SubjectSecurityContext
,
806 PreviouslyGrantedAccess
,
814 /* Release the lock if needed */
815 if (!SubjectContextLocked
)
816 SeUnlockSubjectContext(SubjectSecurityContext
);
826 SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
827 IN PACCESS_STATE AccessState
,
828 IN ACCESS_MASK DesiredAccess
,
829 IN KPROCESSOR_MODE AccessMode
)
837 NT_ASSERT(AccessMode
!= KernelMode
);
839 if (SecurityDescriptor
== NULL
)
843 Dacl
= SepGetDaclFromDescriptor(SecurityDescriptor
);
844 /* If no DACL, grant access */
852 /* Can't perform the check on restricted token */
853 if (AccessState
->Flags
& TOKEN_IS_RESTRICTED
)
856 /* Browse the ACEs */
857 for (AceIndex
= 0, Ace
= (PKNOWN_ACE
)((ULONG_PTR
)Dacl
+ sizeof(ACL
));
858 AceIndex
< Dacl
->AceCount
;
859 AceIndex
++, Ace
= (PKNOWN_ACE
)((ULONG_PTR
)Ace
+ Ace
->Header
.AceSize
))
861 if (Ace
->Header
.AceFlags
& INHERIT_ONLY_ACE
)
864 /* If access-allowed ACE */
865 if (Ace
->Header
.AceType
& ACCESS_ALLOWED_ACE_TYPE
)
867 /* Check if all accesses are granted */
868 if (!(Ace
->Mask
& DesiredAccess
))
871 /* Check SID and grant access if matching */
872 if (RtlEqualSid(SeWorldSid
, &(Ace
->SidStart
)))
875 /* If access-denied ACE */
876 else if (Ace
->Header
.AceType
& ACCESS_DENIED_ACE_TYPE
)
878 /* Here, only check if it denies all the access wanted and deny if so */
879 if (Ace
->Mask
& DesiredAccess
)
888 /* SYSTEM CALLS ***************************************************************/
895 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
896 IN HANDLE TokenHandle
,
897 IN ACCESS_MASK DesiredAccess
,
898 IN PGENERIC_MAPPING GenericMapping
,
899 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL
,
900 IN OUT PULONG PrivilegeSetLength
,
901 OUT PACCESS_MASK GrantedAccess
,
902 OUT PNTSTATUS AccessStatus
)
904 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
= NULL
;
905 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
;
906 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
907 ACCESS_MASK PreviouslyGrantedAccess
= 0;
912 /* Check if this is kernel mode */
913 if (PreviousMode
== KernelMode
)
915 /* Check if kernel wants everything */
916 if (DesiredAccess
& MAXIMUM_ALLOWED
)
919 *GrantedAccess
= GenericMapping
->GenericAll
;
920 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
924 /* Just give the desired access */
925 *GrantedAccess
= DesiredAccess
;
929 *AccessStatus
= STATUS_SUCCESS
;
930 return STATUS_SUCCESS
;
933 /* Protect probe in SEH */
936 /* Probe all pointers */
937 ProbeForRead(GenericMapping
, sizeof(GENERIC_MAPPING
), sizeof(ULONG
));
938 ProbeForRead(PrivilegeSetLength
, sizeof(ULONG
), sizeof(ULONG
));
939 ProbeForWrite(PrivilegeSet
, *PrivilegeSetLength
, sizeof(ULONG
));
940 ProbeForWrite(GrantedAccess
, sizeof(ACCESS_MASK
), sizeof(ULONG
));
941 ProbeForWrite(AccessStatus
, sizeof(NTSTATUS
), sizeof(ULONG
));
943 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
945 /* Return the exception code */
946 _SEH2_YIELD(return _SEH2_GetExceptionCode());
950 /* Check for unmapped access rights */
951 if (DesiredAccess
& (GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
| GENERIC_ALL
))
952 return STATUS_GENERIC_NOT_MAPPED
;
954 /* Reference the token */
955 Status
= ObReferenceObjectByHandle(TokenHandle
,
961 if (!NT_SUCCESS(Status
))
963 DPRINT("Failed to reference token (Status %lx)\n", Status
);
967 /* Check token type */
968 if (Token
->TokenType
!= TokenImpersonation
)
970 DPRINT("No impersonation token\n");
971 ObDereferenceObject(Token
);
972 return STATUS_NO_IMPERSONATION_TOKEN
;
975 /* Check the impersonation level */
976 if (Token
->ImpersonationLevel
< SecurityIdentification
)
978 DPRINT("Impersonation level < SecurityIdentification\n");
979 ObDereferenceObject(Token
);
980 return STATUS_BAD_IMPERSONATION_LEVEL
;
983 /* Capture the security descriptor */
984 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
988 &CapturedSecurityDescriptor
);
989 if (!NT_SUCCESS(Status
))
991 DPRINT("Failed to capture the Security Descriptor\n");
992 ObDereferenceObject(Token
);
996 /* Check the captured security descriptor */
997 if (CapturedSecurityDescriptor
== NULL
)
999 DPRINT("Security Descriptor is NULL\n");
1000 ObDereferenceObject(Token
);
1001 return STATUS_INVALID_SECURITY_DESCR
;
1004 /* Check security descriptor for valid owner and group */
1005 if (SepGetSDOwner(SecurityDescriptor
) == NULL
|| // FIXME: use CapturedSecurityDescriptor
1006 SepGetSDGroup(SecurityDescriptor
) == NULL
) // FIXME: use CapturedSecurityDescriptor
1008 DPRINT("Security Descriptor does not have a valid group or owner\n");
1009 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
1012 ObDereferenceObject(Token
);
1013 return STATUS_INVALID_SECURITY_DESCR
;
1016 /* Set up the subject context, and lock it */
1017 SeCaptureSubjectContext(&SubjectSecurityContext
);
1019 /* Lock the token */
1020 SepAcquireTokenLockShared(Token
);
1022 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
1023 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
1025 if (SepTokenIsOwner(Token
, SecurityDescriptor
, FALSE
)) // FIXME: use CapturedSecurityDescriptor
1027 if (DesiredAccess
& MAXIMUM_ALLOWED
)
1028 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
1030 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
1032 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
1036 if (DesiredAccess
== 0)
1038 *GrantedAccess
= PreviouslyGrantedAccess
;
1039 *AccessStatus
= STATUS_SUCCESS
;
1043 /* Now perform the access check */
1044 SepAccessCheck(SecurityDescriptor
, // FIXME: use CapturedSecurityDescriptor
1045 &SubjectSecurityContext
,
1047 PreviouslyGrantedAccess
,
1048 &PrivilegeSet
, //FIXME
1055 /* Release subject context and unlock the token */
1056 SeReleaseSubjectContext(&SubjectSecurityContext
);
1057 SepReleaseTokenLock(Token
);
1059 /* Release the captured security descriptor */
1060 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
1064 /* Dereference the token */
1065 ObDereferenceObject(Token
);
1067 /* Check succeeded */
1068 return STATUS_SUCCESS
;
1074 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1075 IN PSID PrincipalSelfSid
,
1076 IN HANDLE ClientToken
,
1077 IN ACCESS_MASK DesiredAccess
,
1078 IN POBJECT_TYPE_LIST ObjectTypeList
,
1079 IN ULONG ObjectTypeLength
,
1080 IN PGENERIC_MAPPING GenericMapping
,
1081 IN PPRIVILEGE_SET PrivilegeSet
,
1082 IN OUT PULONG PrivilegeSetLength
,
1083 OUT PACCESS_MASK GrantedAccess
,
1084 OUT PNTSTATUS AccessStatus
)
1087 return STATUS_NOT_IMPLEMENTED
;
1092 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1094 IN PUNICODE_STRING ObjectTypeName
,
1095 IN PUNICODE_STRING ObjectName
,
1096 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1097 IN PSID PrincipalSelfSid
,
1098 IN ACCESS_MASK DesiredAccess
,
1099 IN AUDIT_EVENT_TYPE AuditType
,
1101 IN POBJECT_TYPE_LIST ObjectTypeList
,
1102 IN ULONG ObjectTypeLength
,
1103 IN PGENERIC_MAPPING GenericMapping
,
1104 IN BOOLEAN ObjectCreation
,
1105 OUT PACCESS_MASK GrantedAccess
,
1106 OUT PNTSTATUS AccessStatus
,
1107 OUT PBOOLEAN GenerateOnClose
)
1110 return STATUS_NOT_IMPLEMENTED
;
1115 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1116 IN PSID PrincipalSelfSid
,
1117 IN HANDLE ClientToken
,
1118 IN ACCESS_MASK DesiredAccess
,
1119 IN POBJECT_TYPE_LIST ObjectTypeList
,
1120 IN ULONG ObjectTypeLength
,
1121 IN PGENERIC_MAPPING GenericMapping
,
1122 IN PPRIVILEGE_SET PrivilegeSet
,
1123 IN OUT PULONG PrivilegeSetLength
,
1124 OUT PACCESS_MASK GrantedAccess
,
1125 OUT PNTSTATUS AccessStatus
)
1128 return STATUS_NOT_IMPLEMENTED
;
1133 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1135 IN PUNICODE_STRING ObjectTypeName
,
1136 IN PUNICODE_STRING ObjectName
,
1137 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1138 IN PSID PrincipalSelfSid
,
1139 IN ACCESS_MASK DesiredAccess
,
1140 IN AUDIT_EVENT_TYPE AuditType
,
1142 IN POBJECT_TYPE_LIST ObjectTypeList
,
1143 IN ULONG ObjectTypeLength
,
1144 IN PGENERIC_MAPPING GenericMapping
,
1145 IN BOOLEAN ObjectCreation
,
1146 OUT PACCESS_MASK GrantedAccess
,
1147 OUT PNTSTATUS AccessStatus
,
1148 OUT PBOOLEAN GenerateOnClose
)
1151 return STATUS_NOT_IMPLEMENTED
;
1156 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName
,
1158 IN HANDLE ClientToken
,
1159 IN PUNICODE_STRING ObjectTypeName
,
1160 IN PUNICODE_STRING ObjectName
,
1161 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1162 IN PSID PrincipalSelfSid
,
1163 IN ACCESS_MASK DesiredAccess
,
1164 IN AUDIT_EVENT_TYPE AuditType
,
1166 IN POBJECT_TYPE_LIST ObjectTypeList
,
1167 IN ULONG ObjectTypeLength
,
1168 IN PGENERIC_MAPPING GenericMapping
,
1169 IN BOOLEAN ObjectCreation
,
1170 OUT PACCESS_MASK GrantedAccess
,
1171 OUT PNTSTATUS AccessStatus
,
1172 OUT PBOOLEAN GenerateOnClose
)
1175 return STATUS_NOT_IMPLEMENTED
;