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
)
124 OBJECT_ATTRIBUTES ObjectAttributes
;
126 HANDLE SecurityHandle
;
132 /* Insert the system token into the tree */
133 Status
= ObInsertObject((PVOID
)(PsGetCurrentProcess()->Token
.Value
&
140 ASSERT(NT_SUCCESS(Status
));
142 /* TODO: Create a security desscriptor for the directory */
144 /* Create '\Security' directory */
145 RtlInitUnicodeString(&Name
, L
"\\Security");
146 InitializeObjectAttributes(&ObjectAttributes
,
148 OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
152 Status
= ZwCreateDirectoryObject(&SecurityHandle
,
153 DIRECTORY_ALL_ACCESS
,
155 ASSERT(NT_SUCCESS(Status
));
157 /* Create 'LSA_AUTHENTICATION_INITIALIZED' event */
158 RtlInitUnicodeString(&Name
, L
"LSA_AUTHENTICATION_INITIALIZED");
159 InitializeObjectAttributes(&ObjectAttributes
,
161 OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
165 Status
= ZwCreateEvent(&EventHandle
,
170 ASSERT(NT_SUCCESS(Status
));
172 Status
= ZwClose(EventHandle
);
173 ASSERT(NT_SUCCESS(Status
));
175 Status
= ZwClose(SecurityHandle
);
176 ASSERT(NT_SUCCESS(Status
));
186 /* Check the initialization phase */
187 switch (ExpInitializationPhase
)
192 return SepInitializationPhase0();
197 return SepInitializationPhase1();
201 /* Don't know any other phase! Bugcheck! */
202 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL
,
204 ExpInitializationPhase
,
213 SeDefaultObjectMethod(IN PVOID Object
,
214 IN SECURITY_OPERATION_CODE OperationType
,
215 IN PSECURITY_INFORMATION SecurityInformation
,
216 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
217 IN OUT PULONG ReturnLength OPTIONAL
,
218 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
219 IN POOL_TYPE PoolType
,
220 IN PGENERIC_MAPPING GenericMapping
)
224 /* Select the operation type */
225 switch (OperationType
)
227 /* Setting a new descriptor */
228 case SetSecurityDescriptor
:
231 ASSERT((PoolType
== PagedPool
) || (PoolType
== NonPagedPool
));
233 /* Set the information */
234 return ObSetSecurityDescriptorInfo(Object
,
237 OldSecurityDescriptor
,
241 case QuerySecurityDescriptor
:
243 /* Query the information */
244 return ObQuerySecurityDescriptorInfo(Object
,
248 OldSecurityDescriptor
);
250 case DeleteSecurityDescriptor
:
253 return ObDeassignSecurity(OldSecurityDescriptor
);
255 case AssignSecurityDescriptor
:
258 ObAssignObjectSecurityDescriptor(Object
, SecurityDescriptor
, PoolType
);
259 return STATUS_SUCCESS
;
264 KeBugCheckEx(SECURITY_SYSTEM
, 0, STATUS_INVALID_PARAMETER
, 0, 0);
267 /* Should never reach here */
269 return STATUS_SUCCESS
;
274 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
275 OUT PACCESS_MASK DesiredAccess
)
279 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
|
280 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
))
282 *DesiredAccess
|= READ_CONTROL
;
285 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
287 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
293 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
294 OUT PACCESS_MASK DesiredAccess
)
298 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
300 *DesiredAccess
|= WRITE_OWNER
;
303 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
305 *DesiredAccess
|= WRITE_DAC
;
308 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
310 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
315 #define OLD_ACCESS_CHECK
318 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
319 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
320 IN ACCESS_MASK DesiredAccess
,
321 IN ACCESS_MASK PreviouslyGrantedAccess
,
322 OUT PPRIVILEGE_SET
* Privileges
,
323 IN PGENERIC_MAPPING GenericMapping
,
324 IN KPROCESSOR_MODE AccessMode
,
325 OUT PACCESS_MASK GrantedAccess
,
326 OUT PNTSTATUS AccessStatus
)
328 LUID_AND_ATTRIBUTES Privilege
;
329 #ifdef OLD_ACCESS_CHECK
330 ACCESS_MASK CurrentAccess
, AccessMask
;
332 ACCESS_MASK RemainingAccess
;
333 ACCESS_MASK TempAccess
;
334 ACCESS_MASK TempGrantedAccess
= 0;
335 ACCESS_MASK TempDeniedAccess
= 0;
346 /* Check for no access desired */
349 /* Check if we had no previous access */
350 if (!PreviouslyGrantedAccess
)
352 /* Then there's nothing to give */
353 *AccessStatus
= STATUS_ACCESS_DENIED
;
357 /* Return the previous access only */
358 *GrantedAccess
= PreviouslyGrantedAccess
;
359 *AccessStatus
= STATUS_SUCCESS
;
364 /* Map given accesses */
365 RtlMapGenericMask(&DesiredAccess
, GenericMapping
);
366 if (PreviouslyGrantedAccess
)
367 RtlMapGenericMask(&PreviouslyGrantedAccess
, GenericMapping
);
369 #ifdef OLD_ACCESS_CHECK
370 CurrentAccess
= PreviouslyGrantedAccess
;
372 /* Initialize remaining access rights */
373 RemainingAccess
= DesiredAccess
;
375 Token
= SubjectSecurityContext
->ClientToken
?
376 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
378 /* Check for system security access */
379 if (RemainingAccess
& ACCESS_SYSTEM_SECURITY
)
381 Privilege
.Luid
= SeSecurityPrivilege
;
382 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
384 /* Fail if we do not the SeSecurityPrivilege */
385 if (!SepPrivilegeCheck(Token
,
388 PRIVILEGE_SET_ALL_NECESSARY
,
391 *AccessStatus
= STATUS_PRIVILEGE_NOT_HELD
;
395 /* Adjust access rights */
396 RemainingAccess
&= ~ACCESS_SYSTEM_SECURITY
;
397 PreviouslyGrantedAccess
|= ACCESS_SYSTEM_SECURITY
;
399 /* Succeed if there are no more rights to grant */
400 if (RemainingAccess
== 0)
402 *GrantedAccess
= PreviouslyGrantedAccess
;
403 *AccessStatus
= STATUS_SUCCESS
;
409 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
413 if (!NT_SUCCESS(Status
))
415 *AccessStatus
= Status
;
419 /* RULE 1: Grant desired access if the object is unprotected */
420 if (Present
== FALSE
|| Dacl
== NULL
)
422 if (DesiredAccess
& MAXIMUM_ALLOWED
)
424 *GrantedAccess
= GenericMapping
->GenericAll
;
425 *GrantedAccess
|= (DesiredAccess
& ~MAXIMUM_ALLOWED
);
429 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
432 *AccessStatus
= STATUS_SUCCESS
;
436 #ifdef OLD_ACCESS_CHECK
437 CurrentAccess
= PreviouslyGrantedAccess
;
440 /* RULE 2: Check token for 'take ownership' privilege */
441 if (DesiredAccess
& WRITE_OWNER
)
443 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
444 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
446 if (SepPrivilegeCheck(Token
,
449 PRIVILEGE_SET_ALL_NECESSARY
,
452 /* Adjust access rights */
453 RemainingAccess
&= ~WRITE_OWNER
;
454 PreviouslyGrantedAccess
|= WRITE_OWNER
;
455 #ifdef OLD_ACCESS_CHECK
456 CurrentAccess
|= WRITE_OWNER
;
459 /* Succeed if there are no more rights to grant */
460 if (RemainingAccess
== 0)
462 *GrantedAccess
= PreviouslyGrantedAccess
;
463 *AccessStatus
= STATUS_SUCCESS
;
469 /* Deny access if the DACL is empty */
470 if (Dacl
->AceCount
== 0)
472 if (RemainingAccess
== MAXIMUM_ALLOWED
&& PreviouslyGrantedAccess
!= 0)
474 *GrantedAccess
= PreviouslyGrantedAccess
;
475 *AccessStatus
= STATUS_SUCCESS
;
481 *AccessStatus
= STATUS_ACCESS_DENIED
;
486 /* Fail if DACL is absent */
487 if (Present
== FALSE
)
490 *AccessStatus
= STATUS_ACCESS_DENIED
;
494 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
495 if (DesiredAccess
& MAXIMUM_ALLOWED
)
497 CurrentAce
= (PACE
)(Dacl
+ 1);
498 for (i
= 0; i
< Dacl
->AceCount
; i
++)
500 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
502 Sid
= (PSID
)(CurrentAce
+ 1);
503 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
505 if (SepSidInToken(Token
, Sid
))
507 /* Map access rights from the ACE */
508 TempAccess
= CurrentAce
->AccessMask
;
509 RtlMapGenericMask(&TempAccess
, GenericMapping
);
511 /* Deny access rights that have not been granted yet */
512 TempDeniedAccess
|= (TempAccess
& ~TempGrantedAccess
);
515 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
517 if (SepSidInToken(Token
, Sid
))
519 /* Map access rights from the ACE */
520 TempAccess
= CurrentAce
->AccessMask
;
521 RtlMapGenericMask(&TempAccess
, GenericMapping
);
523 /* Grant access rights that have not been denied yet */
524 TempGrantedAccess
|= (TempAccess
& ~TempDeniedAccess
);
529 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
533 /* Get the next ACE */
534 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
537 /* Fail if some rights have not been granted */
538 RemainingAccess
&= ~(MAXIMUM_ALLOWED
| TempGrantedAccess
);
539 if (RemainingAccess
!= 0)
542 *AccessStatus
= STATUS_ACCESS_DENIED
;
546 /* Set granted access right and access status */
547 *GrantedAccess
= TempGrantedAccess
| PreviouslyGrantedAccess
;
548 if (*GrantedAccess
!= 0)
550 *AccessStatus
= STATUS_SUCCESS
;
555 *AccessStatus
= STATUS_ACCESS_DENIED
;
560 /* RULE 4: Grant rights according to the DACL */
561 CurrentAce
= (PACE
)(Dacl
+ 1);
562 for (i
= 0; i
< Dacl
->AceCount
; i
++)
564 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
566 Sid
= (PSID
)(CurrentAce
+ 1);
567 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
569 if (SepSidInToken(Token
, Sid
))
571 #ifdef OLD_ACCESS_CHECK
573 *AccessStatus
= STATUS_ACCESS_DENIED
;
576 /* Map access rights from the ACE */
577 TempAccess
= CurrentAce
->AccessMask
;
578 RtlMapGenericMask(&TempAccess
, GenericMapping
);
580 /* Leave if a remaining right must be denied */
581 if (RemainingAccess
& TempAccess
)
586 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
588 if (SepSidInToken(Token
, Sid
))
590 #ifdef OLD_ACCESS_CHECK
591 AccessMask
= CurrentAce
->AccessMask
;
592 RtlMapGenericMask(&AccessMask
, GenericMapping
);
593 CurrentAccess
|= AccessMask
;
595 /* Map access rights from the ACE */
596 TempAccess
= CurrentAce
->AccessMask
;
597 RtlMapGenericMask(&TempAccess
, GenericMapping
);
599 /* Remove granted rights */
600 RemainingAccess
&= ~TempAccess
;
606 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
610 /* Get the next ACE */
611 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
614 #ifdef OLD_ACCESS_CHECK
615 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
616 CurrentAccess
, DesiredAccess
);
618 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
620 if ((*GrantedAccess
& ~VALID_INHERIT_FLAGS
) ==
621 (DesiredAccess
& ~VALID_INHERIT_FLAGS
))
623 *AccessStatus
= STATUS_SUCCESS
;
628 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
629 *GrantedAccess
, DesiredAccess
, GenericMapping
);
630 //*AccessStatus = STATUS_ACCESS_DENIED;
632 *GrantedAccess
= DesiredAccess
;
633 *AccessStatus
= STATUS_SUCCESS
;
637 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
638 DesiredAccess
, PreviouslyGrantedAccess
, RemainingAccess
);
640 /* Fail if some rights have not been granted */
641 if (RemainingAccess
!= 0)
644 *AccessStatus
= STATUS_ACCESS_DENIED
;
648 /* Set granted access rights */
649 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
651 DPRINT("GrantedAccess %08lx\n", *GrantedAccess
);
653 /* Fail if no rights have been granted */
654 if (*GrantedAccess
== 0)
656 *AccessStatus
= STATUS_ACCESS_DENIED
;
660 *AccessStatus
= STATUS_SUCCESS
;
666 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
668 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
671 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
672 Owner
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Owner
+
673 (ULONG_PTR
)SecurityDescriptor
);
675 Owner
= (PSID
)SecurityDescriptor
->Owner
;
681 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
683 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
686 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
687 Group
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Group
+
688 (ULONG_PTR
)SecurityDescriptor
);
690 Group
= (PSID
)SecurityDescriptor
->Group
;
696 /* PUBLIC FUNCTIONS ***********************************************************/
703 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
704 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
705 IN BOOLEAN SubjectContextLocked
,
706 IN ACCESS_MASK DesiredAccess
,
707 IN ACCESS_MASK PreviouslyGrantedAccess
,
708 OUT PPRIVILEGE_SET
* Privileges
,
709 IN PGENERIC_MAPPING GenericMapping
,
710 IN KPROCESSOR_MODE AccessMode
,
711 OUT PACCESS_MASK GrantedAccess
,
712 OUT PNTSTATUS AccessStatus
)
718 /* Check if this is kernel mode */
719 if (AccessMode
== KernelMode
)
721 /* Check if kernel wants everything */
722 if (DesiredAccess
& MAXIMUM_ALLOWED
)
725 *GrantedAccess
= GenericMapping
->GenericAll
;
726 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
727 *GrantedAccess
|= PreviouslyGrantedAccess
;
731 /* Give the desired and previous access */
732 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
736 *AccessStatus
= STATUS_SUCCESS
;
740 /* Check if we didn't get an SD */
741 if (!SecurityDescriptor
)
743 /* Automatic failure */
744 *AccessStatus
= STATUS_ACCESS_DENIED
;
748 /* Check for invalid impersonation */
749 if ((SubjectSecurityContext
->ClientToken
) &&
750 (SubjectSecurityContext
->ImpersonationLevel
< SecurityImpersonation
))
752 *AccessStatus
= STATUS_BAD_IMPERSONATION_LEVEL
;
756 /* Acquire the lock if needed */
757 if (!SubjectContextLocked
)
758 SeLockSubjectContext(SubjectSecurityContext
);
760 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
761 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
763 PACCESS_TOKEN Token
= SubjectSecurityContext
->ClientToken
?
764 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
766 if (SepTokenIsOwner(Token
,
770 if (DesiredAccess
& MAXIMUM_ALLOWED
)
771 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
773 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
775 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
779 if (DesiredAccess
== 0)
781 *GrantedAccess
= PreviouslyGrantedAccess
;
782 *AccessStatus
= STATUS_SUCCESS
;
787 /* Call the internal function */
788 ret
= SepAccessCheck(SecurityDescriptor
,
789 SubjectSecurityContext
,
791 PreviouslyGrantedAccess
,
799 /* Release the lock if needed */
800 if (!SubjectContextLocked
)
801 SeUnlockSubjectContext(SubjectSecurityContext
);
811 SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
812 IN PACCESS_STATE AccessState
,
813 IN ACCESS_MASK DesiredAccess
,
814 IN KPROCESSOR_MODE AccessMode
)
822 NT_ASSERT(AccessMode
!= KernelMode
);
824 if (SecurityDescriptor
== NULL
)
828 Dacl
= SepGetDaclFromDescriptor(SecurityDescriptor
);
829 /* If no DACL, grant access */
837 /* Can't perform the check on restricted token */
838 if (AccessState
->Flags
& TOKEN_IS_RESTRICTED
)
841 /* Browse the ACEs */
842 for (AceIndex
= 0, Ace
= (PKNOWN_ACE
)((ULONG_PTR
)Dacl
+ sizeof(ACL
));
843 AceIndex
< Dacl
->AceCount
;
844 AceIndex
++, Ace
= (PKNOWN_ACE
)((ULONG_PTR
)Ace
+ Ace
->Header
.AceSize
))
846 if (Ace
->Header
.AceFlags
& INHERIT_ONLY_ACE
)
849 /* If access-allowed ACE */
850 if (Ace
->Header
.AceType
& ACCESS_ALLOWED_ACE_TYPE
)
852 /* Check if all accesses are granted */
853 if (!(Ace
->Mask
& DesiredAccess
))
856 /* Check SID and grant access if matching */
857 if (RtlEqualSid(SeWorldSid
, &(Ace
->SidStart
)))
860 /* If access-denied ACE */
861 else if (Ace
->Header
.AceType
& ACCESS_DENIED_ACE_TYPE
)
863 /* Here, only check if it denies all the access wanted and deny if so */
864 if (Ace
->Mask
& DesiredAccess
)
873 /* SYSTEM CALLS ***************************************************************/
880 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
881 IN HANDLE TokenHandle
,
882 IN ACCESS_MASK DesiredAccess
,
883 IN PGENERIC_MAPPING GenericMapping
,
884 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL
,
885 IN OUT PULONG PrivilegeSetLength
,
886 OUT PACCESS_MASK GrantedAccess
,
887 OUT PNTSTATUS AccessStatus
)
889 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
= NULL
;
890 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
;
891 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
892 ACCESS_MASK PreviouslyGrantedAccess
= 0;
897 /* Check if this is kernel mode */
898 if (PreviousMode
== KernelMode
)
900 /* Check if kernel wants everything */
901 if (DesiredAccess
& MAXIMUM_ALLOWED
)
904 *GrantedAccess
= GenericMapping
->GenericAll
;
905 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
909 /* Just give the desired access */
910 *GrantedAccess
= DesiredAccess
;
914 *AccessStatus
= STATUS_SUCCESS
;
915 return STATUS_SUCCESS
;
918 /* Protect probe in SEH */
921 /* Probe all pointers */
922 ProbeForRead(GenericMapping
, sizeof(GENERIC_MAPPING
), sizeof(ULONG
));
923 ProbeForRead(PrivilegeSetLength
, sizeof(ULONG
), sizeof(ULONG
));
924 ProbeForWrite(PrivilegeSet
, *PrivilegeSetLength
, sizeof(ULONG
));
925 ProbeForWrite(GrantedAccess
, sizeof(ACCESS_MASK
), sizeof(ULONG
));
926 ProbeForWrite(AccessStatus
, sizeof(NTSTATUS
), sizeof(ULONG
));
928 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
930 /* Return the exception code */
931 _SEH2_YIELD(return _SEH2_GetExceptionCode());
935 /* Check for unmapped access rights */
936 if (DesiredAccess
& (GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
| GENERIC_ALL
))
937 return STATUS_GENERIC_NOT_MAPPED
;
939 /* Reference the token */
940 Status
= ObReferenceObjectByHandle(TokenHandle
,
946 if (!NT_SUCCESS(Status
))
948 DPRINT("Failed to reference token (Status %lx)\n", Status
);
952 /* Check token type */
953 if (Token
->TokenType
!= TokenImpersonation
)
955 DPRINT("No impersonation token\n");
956 ObDereferenceObject(Token
);
957 return STATUS_NO_IMPERSONATION_TOKEN
;
960 /* Check the impersonation level */
961 if (Token
->ImpersonationLevel
< SecurityIdentification
)
963 DPRINT("Impersonation level < SecurityIdentification\n");
964 ObDereferenceObject(Token
);
965 return STATUS_BAD_IMPERSONATION_LEVEL
;
968 /* Capture the security descriptor */
969 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
973 &CapturedSecurityDescriptor
);
974 if (!NT_SUCCESS(Status
))
976 DPRINT("Failed to capture the Security Descriptor\n");
977 ObDereferenceObject(Token
);
981 /* Check the captured security descriptor */
982 if (CapturedSecurityDescriptor
== NULL
)
984 DPRINT("Security Descriptor is NULL\n");
985 ObDereferenceObject(Token
);
986 return STATUS_INVALID_SECURITY_DESCR
;
989 /* Check security descriptor for valid owner and group */
990 if (SepGetSDOwner(SecurityDescriptor
) == NULL
|| // FIXME: use CapturedSecurityDescriptor
991 SepGetSDGroup(SecurityDescriptor
) == NULL
) // FIXME: use CapturedSecurityDescriptor
993 DPRINT("Security Descriptor does not have a valid group or owner\n");
994 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
997 ObDereferenceObject(Token
);
998 return STATUS_INVALID_SECURITY_DESCR
;
1001 /* Set up the subject context, and lock it */
1002 SeCaptureSubjectContext(&SubjectSecurityContext
);
1004 /* Lock the token */
1005 SepAcquireTokenLockShared(Token
);
1007 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
1008 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
1010 if (SepTokenIsOwner(Token
, SecurityDescriptor
, FALSE
)) // FIXME: use CapturedSecurityDescriptor
1012 if (DesiredAccess
& MAXIMUM_ALLOWED
)
1013 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
1015 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
1017 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
1021 if (DesiredAccess
== 0)
1023 *GrantedAccess
= PreviouslyGrantedAccess
;
1024 *AccessStatus
= STATUS_SUCCESS
;
1028 /* Now perform the access check */
1029 SepAccessCheck(SecurityDescriptor
, // FIXME: use CapturedSecurityDescriptor
1030 &SubjectSecurityContext
,
1032 PreviouslyGrantedAccess
,
1033 &PrivilegeSet
, //FIXME
1040 /* Release subject context and unlock the token */
1041 SeReleaseSubjectContext(&SubjectSecurityContext
);
1042 SepReleaseTokenLock(Token
);
1044 /* Release the captured security descriptor */
1045 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
1049 /* Dereference the token */
1050 ObDereferenceObject(Token
);
1052 /* Check succeeded */
1053 return STATUS_SUCCESS
;
1059 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1060 IN PSID PrincipalSelfSid
,
1061 IN HANDLE ClientToken
,
1062 IN ACCESS_MASK DesiredAccess
,
1063 IN POBJECT_TYPE_LIST ObjectTypeList
,
1064 IN ULONG ObjectTypeLength
,
1065 IN PGENERIC_MAPPING GenericMapping
,
1066 IN PPRIVILEGE_SET PrivilegeSet
,
1067 IN OUT PULONG PrivilegeSetLength
,
1068 OUT PACCESS_MASK GrantedAccess
,
1069 OUT PNTSTATUS AccessStatus
)
1072 return STATUS_NOT_IMPLEMENTED
;
1077 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1078 IN PSID PrincipalSelfSid
,
1079 IN HANDLE ClientToken
,
1080 IN ACCESS_MASK DesiredAccess
,
1081 IN POBJECT_TYPE_LIST ObjectTypeList
,
1082 IN ULONG ObjectTypeLength
,
1083 IN PGENERIC_MAPPING GenericMapping
,
1084 IN PPRIVILEGE_SET PrivilegeSet
,
1085 IN OUT PULONG PrivilegeSetLength
,
1086 OUT PACCESS_MASK GrantedAccess
,
1087 OUT PNTSTATUS AccessStatus
)
1090 return STATUS_NOT_IMPLEMENTED
;