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
,
186 InitializeObjectAttributes(&ObjectAttributes
,
191 Status
= ZwCreateDirectoryObject(&DirectoryHandle
,
192 DIRECTORY_ALL_ACCESS
,
194 if (!NT_SUCCESS(Status
))
196 DPRINT1("Failed to create 'Security' directory!\n");
200 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
201 RtlInitUnicodeString(&Name
,
202 L
"\\LSA_AUTHENTICATION_INITALIZED");
203 InitializeObjectAttributes(&ObjectAttributes
,
208 Status
= ZwCreateEvent(&EventHandle
,
211 SynchronizationEvent
,
213 if (!NT_SUCCESS(Status
))
215 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
216 NtClose(DirectoryHandle
);
220 ZwClose(EventHandle
);
221 ZwClose(DirectoryHandle
);
223 /* FIXME: Create SRM port and listener thread */
230 SeDefaultObjectMethod(IN PVOID Object
,
231 IN SECURITY_OPERATION_CODE OperationType
,
232 IN PSECURITY_INFORMATION SecurityInformation
,
233 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
234 IN OUT PULONG ReturnLength OPTIONAL
,
235 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
236 IN POOL_TYPE PoolType
,
237 IN PGENERIC_MAPPING GenericMapping
)
241 /* Select the operation type */
242 switch (OperationType
)
244 /* Setting a new descriptor */
245 case SetSecurityDescriptor
:
248 ASSERT((PoolType
== PagedPool
) || (PoolType
== NonPagedPool
));
250 /* Set the information */
251 return ObSetSecurityDescriptorInfo(Object
,
254 OldSecurityDescriptor
,
258 case QuerySecurityDescriptor
:
260 /* Query the information */
261 return ObQuerySecurityDescriptorInfo(Object
,
265 OldSecurityDescriptor
);
267 case DeleteSecurityDescriptor
:
270 return ObDeassignSecurity(OldSecurityDescriptor
);
272 case AssignSecurityDescriptor
:
275 ObAssignObjectSecurityDescriptor(Object
, SecurityDescriptor
, PoolType
);
276 return STATUS_SUCCESS
;
281 KeBugCheckEx(SECURITY_SYSTEM
, 0, STATUS_INVALID_PARAMETER
, 0, 0);
284 /* Should never reach here */
286 return STATUS_SUCCESS
;
290 SepSidInToken(PACCESS_TOKEN _Token
,
294 PTOKEN Token
= (PTOKEN
)_Token
;
299 if (!(SidInTokenCalls
% 10000)) DPRINT1("SidInToken Calls: %d\n", SidInTokenCalls
);
301 if (Token
->UserAndGroupCount
== 0)
306 for (i
=0; i
<Token
->UserAndGroupCount
; i
++)
308 if (RtlEqualSid(Sid
, Token
->UserAndGroups
[i
].Sid
))
310 if ((i
== 0)|| (Token
->UserAndGroups
[i
].Attributes
& SE_GROUP_ENABLED
))
323 SepTokenIsOwner(PACCESS_TOKEN Token
,
324 PSECURITY_DESCRIPTOR SecurityDescriptor
)
330 Status
= RtlGetOwnerSecurityDescriptor(SecurityDescriptor
,
333 if (!NT_SUCCESS(Status
))
335 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status
);
341 DPRINT1("Owner Sid is NULL\n");
345 return SepSidInToken(Token
, Sid
);
350 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
351 OUT PACCESS_MASK DesiredAccess
)
355 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
|
356 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
))
358 *DesiredAccess
|= READ_CONTROL
;
361 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
363 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
369 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
370 OUT PACCESS_MASK DesiredAccess
)
374 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
376 *DesiredAccess
|= WRITE_OWNER
;
379 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
381 *DesiredAccess
|= WRITE_DAC
;
384 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
386 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
391 #define OLD_ACCESS_CHECK
394 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
395 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
396 IN ACCESS_MASK DesiredAccess
,
397 IN ACCESS_MASK PreviouslyGrantedAccess
,
398 OUT PPRIVILEGE_SET
* Privileges
,
399 IN PGENERIC_MAPPING GenericMapping
,
400 IN KPROCESSOR_MODE AccessMode
,
401 OUT PACCESS_MASK GrantedAccess
,
402 OUT PNTSTATUS AccessStatus
)
404 LUID_AND_ATTRIBUTES Privilege
;
405 #ifdef OLD_ACCESS_CHECK
406 ACCESS_MASK CurrentAccess
, AccessMask
;
408 ACCESS_MASK RemainingAccess
;
409 ACCESS_MASK TempAccess
;
410 ACCESS_MASK TempGrantedAccess
= 0;
411 ACCESS_MASK TempDeniedAccess
= 0;
422 /* Check for no access desired */
425 /* Check if we had no previous access */
426 if (!PreviouslyGrantedAccess
)
428 /* Then there's nothing to give */
429 *AccessStatus
= STATUS_ACCESS_DENIED
;
433 /* Return the previous access only */
434 *GrantedAccess
= PreviouslyGrantedAccess
;
435 *AccessStatus
= STATUS_SUCCESS
;
440 /* Map given accesses */
441 RtlMapGenericMask(&DesiredAccess
, GenericMapping
);
442 if (PreviouslyGrantedAccess
)
443 RtlMapGenericMask(&PreviouslyGrantedAccess
, GenericMapping
);
445 #ifdef OLD_ACCESS_CHECK
446 CurrentAccess
= PreviouslyGrantedAccess
;
448 /* Initialize remaining access rights */
449 RemainingAccess
= DesiredAccess
;
451 Token
= SubjectSecurityContext
->ClientToken
?
452 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
454 /* Check for system security access */
455 if (RemainingAccess
& ACCESS_SYSTEM_SECURITY
)
457 Privilege
.Luid
= SeSecurityPrivilege
;
458 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
460 /* Fail if we do not the SeSecurityPrivilege */
461 if (!SepPrivilegeCheck(Token
,
464 PRIVILEGE_SET_ALL_NECESSARY
,
467 *AccessStatus
= STATUS_PRIVILEGE_NOT_HELD
;
471 /* Adjust access rights */
472 RemainingAccess
&= ~ACCESS_SYSTEM_SECURITY
;
473 PreviouslyGrantedAccess
|= ACCESS_SYSTEM_SECURITY
;
475 /* Succeed if there are no more rights to grant */
476 if (RemainingAccess
== 0)
478 *GrantedAccess
= PreviouslyGrantedAccess
;
479 *AccessStatus
= STATUS_SUCCESS
;
485 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
489 if (!NT_SUCCESS(Status
))
491 *AccessStatus
= Status
;
495 /* RULE 1: Grant desired access if the object is unprotected */
496 if (Present
== FALSE
|| Dacl
== NULL
)
498 if (DesiredAccess
& MAXIMUM_ALLOWED
)
500 *GrantedAccess
= GenericMapping
->GenericAll
;
501 *GrantedAccess
|= (DesiredAccess
& ~MAXIMUM_ALLOWED
);
505 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
508 *AccessStatus
= STATUS_SUCCESS
;
512 #ifdef OLD_ACCESS_CHECK
513 CurrentAccess
= PreviouslyGrantedAccess
;
516 /* RULE 2: Check token for 'take ownership' privilege */
517 if (DesiredAccess
& WRITE_OWNER
)
519 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
520 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
522 if (SepPrivilegeCheck(Token
,
525 PRIVILEGE_SET_ALL_NECESSARY
,
528 /* Adjust access rights */
529 RemainingAccess
&= ~WRITE_OWNER
;
530 PreviouslyGrantedAccess
|= WRITE_OWNER
;
531 #ifdef OLD_ACCESS_CHECK
532 CurrentAccess
|= WRITE_OWNER
;
535 /* Succeed if there are no more rights to grant */
536 if (RemainingAccess
== 0)
538 *GrantedAccess
= PreviouslyGrantedAccess
;
539 *AccessStatus
= STATUS_SUCCESS
;
545 /* Deny access if the DACL is empty */
546 if (Dacl
->AceCount
== 0)
548 if (RemainingAccess
== MAXIMUM_ALLOWED
&& PreviouslyGrantedAccess
!= 0)
550 *GrantedAccess
= PreviouslyGrantedAccess
;
551 *AccessStatus
= STATUS_SUCCESS
;
557 *AccessStatus
= STATUS_ACCESS_DENIED
;
562 /* Fail if DACL is absent */
563 if (Present
== FALSE
)
566 *AccessStatus
= STATUS_ACCESS_DENIED
;
570 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
571 if (DesiredAccess
& MAXIMUM_ALLOWED
)
573 CurrentAce
= (PACE
)(Dacl
+ 1);
574 for (i
= 0; i
< Dacl
->AceCount
; i
++)
576 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
578 Sid
= (PSID
)(CurrentAce
+ 1);
579 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
581 if (SepSidInToken(Token
, Sid
))
583 /* Map access rights from the ACE */
584 TempAccess
= CurrentAce
->AccessMask
;
585 RtlMapGenericMask(&TempAccess
, GenericMapping
);
587 /* Deny access rights that have not been granted yet */
588 TempDeniedAccess
|= (TempAccess
& ~TempGrantedAccess
);
591 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
593 if (SepSidInToken(Token
, Sid
))
595 /* Map access rights from the ACE */
596 TempAccess
= CurrentAce
->AccessMask
;
597 RtlMapGenericMask(&TempAccess
, GenericMapping
);
599 /* Grant access rights that have not been denied yet */
600 TempGrantedAccess
|= (TempAccess
& ~TempDeniedAccess
);
605 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
609 /* Get the next ACE */
610 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
613 /* Fail if some rights have not been granted */
614 RemainingAccess
&= ~(MAXIMUM_ALLOWED
| TempGrantedAccess
);
615 if (RemainingAccess
!= 0)
618 *AccessStatus
= STATUS_ACCESS_DENIED
;
622 /* Set granted access right and access status */
623 *GrantedAccess
= TempGrantedAccess
| PreviouslyGrantedAccess
;
624 if (*GrantedAccess
!= 0)
626 *AccessStatus
= STATUS_SUCCESS
;
631 *AccessStatus
= STATUS_ACCESS_DENIED
;
636 /* RULE 4: Grant rights according to the DACL */
637 CurrentAce
= (PACE
)(Dacl
+ 1);
638 for (i
= 0; i
< Dacl
->AceCount
; i
++)
640 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
642 Sid
= (PSID
)(CurrentAce
+ 1);
643 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
645 if (SepSidInToken(Token
, Sid
))
647 #ifdef OLD_ACCESS_CHECK
649 *AccessStatus
= STATUS_ACCESS_DENIED
;
652 /* Map access rights from the ACE */
653 TempAccess
= CurrentAce
->AccessMask
;
654 RtlMapGenericMask(&TempAccess
, GenericMapping
);
656 /* Leave if a remaining right must be denied */
657 if (RemainingAccess
& TempAccess
)
662 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
664 if (SepSidInToken(Token
, Sid
))
666 #ifdef OLD_ACCESS_CHECK
667 AccessMask
= CurrentAce
->AccessMask
;
668 RtlMapGenericMask(&AccessMask
, GenericMapping
);
669 CurrentAccess
|= AccessMask
;
671 /* Map access rights from the ACE */
672 TempAccess
= CurrentAce
->AccessMask
;
673 RtlMapGenericMask(&TempAccess
, GenericMapping
);
675 /* Remove granted rights */
676 RemainingAccess
&= ~TempAccess
;
682 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
686 /* Get the next ACE */
687 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
690 #ifdef OLD_ACCESS_CHECK
691 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
692 CurrentAccess
, DesiredAccess
);
694 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
696 if ((*GrantedAccess
& ~VALID_INHERIT_FLAGS
) ==
697 (DesiredAccess
& ~VALID_INHERIT_FLAGS
))
699 *AccessStatus
= STATUS_SUCCESS
;
704 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
705 *GrantedAccess
, DesiredAccess
, GenericMapping
);
706 //*AccessStatus = STATUS_ACCESS_DENIED;
708 *AccessStatus
= STATUS_SUCCESS
;
712 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
713 DesiredAccess
, PreviouslyGrantedAccess
, RemainingAccess
);
715 /* Fail if some rights have not been granted */
716 if (RemainingAccess
!= 0)
719 *AccessStatus
= STATUS_ACCESS_DENIED
;
723 /* Set granted access rights */
724 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
726 DPRINT("GrantedAccess %08lx\n", *GrantedAccess
);
728 /* Fail if no rights have been granted */
729 if (*GrantedAccess
== 0)
731 *AccessStatus
= STATUS_ACCESS_DENIED
;
735 *AccessStatus
= STATUS_SUCCESS
;
741 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
743 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
746 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
747 Owner
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Owner
+
748 (ULONG_PTR
)SecurityDescriptor
);
750 Owner
= (PSID
)SecurityDescriptor
->Owner
;
756 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
758 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
761 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
762 Group
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Group
+
763 (ULONG_PTR
)SecurityDescriptor
);
765 Group
= (PSID
)SecurityDescriptor
->Group
;
771 /* PUBLIC FUNCTIONS ***********************************************************/
778 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
779 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
780 IN BOOLEAN SubjectContextLocked
,
781 IN ACCESS_MASK DesiredAccess
,
782 IN ACCESS_MASK PreviouslyGrantedAccess
,
783 OUT PPRIVILEGE_SET
* Privileges
,
784 IN PGENERIC_MAPPING GenericMapping
,
785 IN KPROCESSOR_MODE AccessMode
,
786 OUT PACCESS_MASK GrantedAccess
,
787 OUT PNTSTATUS AccessStatus
)
793 /* Check if this is kernel mode */
794 if (AccessMode
== KernelMode
)
796 /* Check if kernel wants everything */
797 if (DesiredAccess
& MAXIMUM_ALLOWED
)
800 *GrantedAccess
= GenericMapping
->GenericAll
;
801 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
802 *GrantedAccess
|= PreviouslyGrantedAccess
;
806 /* Give the desired and previous access */
807 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
811 *AccessStatus
= STATUS_SUCCESS
;
815 /* Check if we didn't get an SD */
816 if (!SecurityDescriptor
)
818 /* Automatic failure */
819 *AccessStatus
= STATUS_ACCESS_DENIED
;
823 /* Check for invalid impersonation */
824 if ((SubjectSecurityContext
->ClientToken
) &&
825 (SubjectSecurityContext
->ImpersonationLevel
< SecurityImpersonation
))
827 *AccessStatus
= STATUS_BAD_IMPERSONATION_LEVEL
;
831 /* Acquire the lock if needed */
832 if (!SubjectContextLocked
)
833 SeLockSubjectContext(SubjectSecurityContext
);
835 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
836 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
838 PACCESS_TOKEN Token
= SubjectSecurityContext
->ClientToken
?
839 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
841 if (SepTokenIsOwner(Token
,
844 if (DesiredAccess
& MAXIMUM_ALLOWED
)
845 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
847 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
849 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
853 if (DesiredAccess
== 0)
855 *GrantedAccess
= PreviouslyGrantedAccess
;
856 *AccessStatus
= STATUS_SUCCESS
;
861 /* Call the internal function */
862 ret
= SepAccessCheck(SecurityDescriptor
,
863 SubjectSecurityContext
,
865 PreviouslyGrantedAccess
,
873 /* Release the lock if needed */
874 if (!SubjectContextLocked
)
875 SeUnlockSubjectContext(SubjectSecurityContext
);
880 /* SYSTEM CALLS ***************************************************************/
887 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
888 IN HANDLE TokenHandle
,
889 IN ACCESS_MASK DesiredAccess
,
890 IN PGENERIC_MAPPING GenericMapping
,
891 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL
,
892 IN OUT PULONG PrivilegeSetLength
,
893 OUT PACCESS_MASK GrantedAccess
,
894 OUT PNTSTATUS AccessStatus
)
896 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
= NULL
;
897 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
;
898 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
899 ACCESS_MASK PreviouslyGrantedAccess
= 0;
904 /* Check if this is kernel mode */
905 if (PreviousMode
== KernelMode
)
907 /* Check if kernel wants everything */
908 if (DesiredAccess
& MAXIMUM_ALLOWED
)
911 *GrantedAccess
= GenericMapping
->GenericAll
;
912 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
916 /* Just give the desired access */
917 *GrantedAccess
= DesiredAccess
;
921 *AccessStatus
= STATUS_SUCCESS
;
922 return STATUS_SUCCESS
;
925 /* Protect probe in SEH */
928 /* Probe all pointers */
929 ProbeForRead(GenericMapping
, sizeof(GENERIC_MAPPING
), sizeof(ULONG
));
930 ProbeForRead(PrivilegeSetLength
, sizeof(ULONG
), sizeof(ULONG
));
931 ProbeForWrite(PrivilegeSet
, *PrivilegeSetLength
, sizeof(ULONG
));
932 ProbeForWrite(GrantedAccess
, sizeof(ACCESS_MASK
), sizeof(ULONG
));
933 ProbeForWrite(AccessStatus
, sizeof(NTSTATUS
), sizeof(ULONG
));
935 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
937 /* Return the exception code */
938 _SEH2_YIELD(return _SEH2_GetExceptionCode());
942 /* Check for unmapped access rights */
943 if (DesiredAccess
& (GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
| GENERIC_ALL
))
944 return STATUS_GENERIC_NOT_MAPPED
;
946 /* Reference the token */
947 Status
= ObReferenceObjectByHandle(TokenHandle
,
953 if (!NT_SUCCESS(Status
))
955 DPRINT("Failed to reference token (Status %lx)\n", Status
);
959 /* Check token type */
960 if (Token
->TokenType
!= TokenImpersonation
)
962 DPRINT("No impersonation token\n");
963 ObDereferenceObject(Token
);
964 return STATUS_NO_IMPERSONATION_TOKEN
;
967 /* Check the impersonation level */
968 if (Token
->ImpersonationLevel
< SecurityIdentification
)
970 DPRINT("Impersonation level < SecurityIdentification\n");
971 ObDereferenceObject(Token
);
972 return STATUS_BAD_IMPERSONATION_LEVEL
;
975 /* Capture the security descriptor */
976 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
980 &CapturedSecurityDescriptor
);
981 if (!NT_SUCCESS(Status
))
983 DPRINT("Failed to capture the Security Descriptor\n");
984 ObDereferenceObject(Token
);
988 /* Check the captured security descriptor */
989 if (CapturedSecurityDescriptor
== NULL
)
991 DPRINT("Security Descriptor is NULL\n");
992 ObDereferenceObject(Token
);
993 return STATUS_INVALID_SECURITY_DESCR
;
996 /* Check security descriptor for valid owner and group */
997 if (SepGetSDOwner(SecurityDescriptor
) == NULL
|| // FIXME: use CapturedSecurityDescriptor
998 SepGetSDGroup(SecurityDescriptor
) == NULL
) // FIXME: use CapturedSecurityDescriptor
1000 DPRINT("Security Descriptor does not have a valid group or owner\n");
1001 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
1004 ObDereferenceObject(Token
);
1005 return STATUS_INVALID_SECURITY_DESCR
;
1008 /* Set up the subject context, and lock it */
1009 SubjectSecurityContext
.ClientToken
= Token
;
1010 SubjectSecurityContext
.ImpersonationLevel
= Token
->ImpersonationLevel
;
1011 SubjectSecurityContext
.PrimaryToken
= NULL
;
1012 SubjectSecurityContext
.ProcessAuditId
= NULL
;
1013 SeLockSubjectContext(&SubjectSecurityContext
);
1015 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
1016 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
1018 if (SepTokenIsOwner(Token
, SecurityDescriptor
)) // FIXME: use CapturedSecurityDescriptor
1020 if (DesiredAccess
& MAXIMUM_ALLOWED
)
1021 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
1023 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
1025 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
1029 if (DesiredAccess
== 0)
1031 *GrantedAccess
= PreviouslyGrantedAccess
;
1032 *AccessStatus
= STATUS_SUCCESS
;
1036 /* Now perform the access check */
1037 SepAccessCheck(SecurityDescriptor
, // FIXME: use CapturedSecurityDescriptor
1038 &SubjectSecurityContext
,
1040 PreviouslyGrantedAccess
,
1041 &PrivilegeSet
, //FIXME
1048 /* Unlock subject context */
1049 SeUnlockSubjectContext(&SubjectSecurityContext
);
1051 /* Release the captured security descriptor */
1052 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
1056 /* Dereference the token */
1057 ObDereferenceObject(Token
);
1059 /* Check succeeded */
1060 return STATUS_SUCCESS
;
1066 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1067 IN PSID PrincipalSelfSid
,
1068 IN HANDLE ClientToken
,
1069 IN ACCESS_MASK DesiredAccess
,
1070 IN POBJECT_TYPE_LIST ObjectTypeList
,
1071 IN ULONG ObjectTypeLength
,
1072 IN PGENERIC_MAPPING GenericMapping
,
1073 IN PPRIVILEGE_SET PrivilegeSet
,
1074 IN ULONG PrivilegeSetLength
,
1075 OUT PACCESS_MASK GrantedAccess
,
1076 OUT PNTSTATUS AccessStatus
)
1079 return STATUS_NOT_IMPLEMENTED
;
1084 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1086 IN PUNICODE_STRING ObjectTypeName
,
1087 IN PUNICODE_STRING ObjectName
,
1088 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1089 IN PSID PrincipalSelfSid
,
1090 IN ACCESS_MASK DesiredAccess
,
1091 IN AUDIT_EVENT_TYPE AuditType
,
1093 IN POBJECT_TYPE_LIST ObjectTypeList
,
1094 IN ULONG ObjectTypeLength
,
1095 IN PGENERIC_MAPPING GenericMapping
,
1096 IN BOOLEAN ObjectCreation
,
1097 OUT PACCESS_MASK GrantedAccess
,
1098 OUT PNTSTATUS AccessStatus
,
1099 OUT PBOOLEAN GenerateOnClose
)
1102 return STATUS_NOT_IMPLEMENTED
;
1107 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1108 IN PSID PrincipalSelfSid
,
1109 IN HANDLE ClientToken
,
1110 IN ACCESS_MASK DesiredAccess
,
1111 IN POBJECT_TYPE_LIST ObjectTypeList
,
1112 IN ULONG ObjectTypeLength
,
1113 IN PGENERIC_MAPPING GenericMapping
,
1114 IN PPRIVILEGE_SET PrivilegeSet
,
1115 IN ULONG PrivilegeSetLength
,
1116 OUT PACCESS_MASK GrantedAccess
,
1117 OUT PNTSTATUS AccessStatus
)
1120 return STATUS_NOT_IMPLEMENTED
;
1125 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1127 IN PUNICODE_STRING ObjectTypeName
,
1128 IN PUNICODE_STRING ObjectName
,
1129 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1130 IN PSID PrincipalSelfSid
,
1131 IN ACCESS_MASK DesiredAccess
,
1132 IN AUDIT_EVENT_TYPE AuditType
,
1134 IN POBJECT_TYPE_LIST ObjectTypeList
,
1135 IN ULONG ObjectTypeLength
,
1136 IN PGENERIC_MAPPING GenericMapping
,
1137 IN BOOLEAN ObjectCreation
,
1138 OUT PACCESS_MASK GrantedAccess
,
1139 OUT PNTSTATUS AccessStatus
,
1140 OUT PBOOLEAN GenerateOnClose
)
1143 return STATUS_NOT_IMPLEMENTED
;
1148 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName
,
1150 IN HANDLE ClientToken
,
1151 IN PUNICODE_STRING ObjectTypeName
,
1152 IN PUNICODE_STRING ObjectName
,
1153 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1154 IN PSID PrincipalSelfSid
,
1155 IN ACCESS_MASK DesiredAccess
,
1156 IN AUDIT_EVENT_TYPE AuditType
,
1158 IN POBJECT_TYPE_LIST ObjectTypeList
,
1159 IN ULONG ObjectTypeLength
,
1160 IN PGENERIC_MAPPING GenericMapping
,
1161 IN BOOLEAN ObjectCreation
,
1162 OUT PACCESS_MASK GrantedAccess
,
1163 OUT PNTSTATUS AccessStatus
,
1164 OUT PBOOLEAN GenerateOnClose
)
1167 return STATUS_NOT_IMPLEMENTED
;