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
;
89 SepInitializationPhase0(VOID
)
94 if (!SepInitSecurityIDs()) return FALSE
;
95 if (!SepInitDACLs()) return FALSE
;
96 if (!SepInitSDs()) return FALSE
;
98 if (!SepInitExports()) return FALSE
;
100 /* Initialize the subject context lock */
101 ExInitializeResource(&SepSubjectContextLock
);
103 /* Initialize token objects */
104 SepInitializeTokenImplementation();
106 /* Clear impersonation info for the idle thread */
107 PsGetCurrentThread()->ImpersonationInfo
= NULL
;
108 PspClearCrossThreadFlag(PsGetCurrentThread(),
109 CT_ACTIVE_IMPERSONATION_INFO_BIT
);
111 /* Initialize the boot token */
112 ObInitializeFastReference(&PsGetCurrentProcess()->Token
, NULL
);
113 ObInitializeFastReference(&PsGetCurrentProcess()->Token
,
114 SepCreateSystemProcessToken());
120 SepInitializationPhase1(VOID
)
126 /* Insert the system token into the tree */
127 Status
= ObInsertObject((PVOID
)(PsGetCurrentProcess()->Token
.Value
&
134 ASSERT(NT_SUCCESS(Status
));
136 /* FIXME: TODO \\ Security directory */
144 /* Check the initialization phase */
145 switch (ExpInitializationPhase
)
150 return SepInitializationPhase0();
155 return SepInitializationPhase1();
159 /* Don't know any other phase! Bugcheck! */
160 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL
,
162 ExpInitializationPhase
,
173 OBJECT_ATTRIBUTES ObjectAttributes
;
175 HANDLE DirectoryHandle
;
179 /* Create '\Security' directory */
180 RtlInitUnicodeString(&Name
,
182 InitializeObjectAttributes(&ObjectAttributes
,
187 Status
= ZwCreateDirectoryObject(&DirectoryHandle
,
188 DIRECTORY_ALL_ACCESS
,
190 if (!NT_SUCCESS(Status
))
192 DPRINT1("Failed to create 'Security' directory!\n");
196 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
197 RtlInitUnicodeString(&Name
,
198 L
"\\LSA_AUTHENTICATION_INITALIZED");
199 InitializeObjectAttributes(&ObjectAttributes
,
204 Status
= ZwCreateEvent(&EventHandle
,
207 SynchronizationEvent
,
209 if (!NT_SUCCESS(Status
))
211 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
212 NtClose(DirectoryHandle
);
216 ZwClose(EventHandle
);
217 ZwClose(DirectoryHandle
);
219 /* FIXME: Create SRM port and listener thread */
226 SeDefaultObjectMethod(IN PVOID Object
,
227 IN SECURITY_OPERATION_CODE OperationType
,
228 IN PSECURITY_INFORMATION SecurityInformation
,
229 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
230 IN OUT PULONG ReturnLength OPTIONAL
,
231 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
232 IN POOL_TYPE PoolType
,
233 IN PGENERIC_MAPPING GenericMapping
)
237 /* Select the operation type */
238 switch (OperationType
)
240 /* Setting a new descriptor */
241 case SetSecurityDescriptor
:
244 ASSERT((PoolType
== PagedPool
) || (PoolType
== NonPagedPool
));
246 /* Set the information */
247 return ObSetSecurityDescriptorInfo(Object
,
250 OldSecurityDescriptor
,
254 case QuerySecurityDescriptor
:
256 /* Query the information */
257 return ObQuerySecurityDescriptorInfo(Object
,
261 OldSecurityDescriptor
);
263 case DeleteSecurityDescriptor
:
266 return ObDeassignSecurity(OldSecurityDescriptor
);
268 case AssignSecurityDescriptor
:
271 ObAssignObjectSecurityDescriptor(Object
, SecurityDescriptor
, PoolType
);
272 return STATUS_SUCCESS
;
277 KeBugCheckEx(SECURITY_SYSTEM
, 0, STATUS_INVALID_PARAMETER
, 0, 0);
280 /* Should never reach here */
282 return STATUS_SUCCESS
;
286 SepSidInToken(PACCESS_TOKEN _Token
,
290 PTOKEN Token
= (PTOKEN
)_Token
;
295 if (!(SidInTokenCalls
% 10000)) DPRINT1("SidInToken Calls: %d\n", SidInTokenCalls
);
297 if (Token
->UserAndGroupCount
== 0)
302 for (i
=0; i
<Token
->UserAndGroupCount
; i
++)
304 if (RtlEqualSid(Sid
, Token
->UserAndGroups
[i
].Sid
))
306 if ((i
== 0)|| (Token
->UserAndGroups
[i
].Attributes
& SE_GROUP_ENABLED
))
319 SepTokenIsOwner(PACCESS_TOKEN Token
,
320 PSECURITY_DESCRIPTOR SecurityDescriptor
)
326 Status
= RtlGetOwnerSecurityDescriptor(SecurityDescriptor
,
329 if (!NT_SUCCESS(Status
))
331 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status
);
337 DPRINT1("Owner Sid is NULL\n");
341 return SepSidInToken(Token
, Sid
);
346 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
347 OUT PACCESS_MASK DesiredAccess
)
351 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
|
352 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
))
354 *DesiredAccess
|= READ_CONTROL
;
357 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
359 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
365 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
366 OUT PACCESS_MASK DesiredAccess
)
370 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
372 *DesiredAccess
|= WRITE_OWNER
;
375 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
377 *DesiredAccess
|= WRITE_DAC
;
380 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
382 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
387 #define OLD_ACCESS_CHECK
390 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
391 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
392 IN ACCESS_MASK DesiredAccess
,
393 IN ACCESS_MASK PreviouslyGrantedAccess
,
394 OUT PPRIVILEGE_SET
* Privileges
,
395 IN PGENERIC_MAPPING GenericMapping
,
396 IN KPROCESSOR_MODE AccessMode
,
397 OUT PACCESS_MASK GrantedAccess
,
398 OUT PNTSTATUS AccessStatus
)
400 LUID_AND_ATTRIBUTES Privilege
;
401 #ifdef OLD_ACCESS_CHECK
402 ACCESS_MASK CurrentAccess
, AccessMask
;
404 ACCESS_MASK RemainingAccess
;
405 ACCESS_MASK TempAccess
;
406 ACCESS_MASK TempGrantedAccess
= 0;
407 ACCESS_MASK TempDeniedAccess
= 0;
418 /* Check for no access desired */
421 /* Check if we had no previous access */
422 if (!PreviouslyGrantedAccess
)
424 /* Then there's nothing to give */
425 *AccessStatus
= STATUS_ACCESS_DENIED
;
429 /* Return the previous access only */
430 *GrantedAccess
= PreviouslyGrantedAccess
;
431 *AccessStatus
= STATUS_SUCCESS
;
436 /* Map given accesses */
437 RtlMapGenericMask(&DesiredAccess
, GenericMapping
);
438 if (PreviouslyGrantedAccess
)
439 RtlMapGenericMask(&PreviouslyGrantedAccess
, GenericMapping
);
441 #ifdef OLD_ACCESS_CHECK
442 CurrentAccess
= PreviouslyGrantedAccess
;
444 /* Initialize remaining access rights */
445 RemainingAccess
= DesiredAccess
;
447 Token
= SubjectSecurityContext
->ClientToken
?
448 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
450 /* Check for system security access */
451 if (RemainingAccess
& ACCESS_SYSTEM_SECURITY
)
453 Privilege
.Luid
= SeSecurityPrivilege
;
454 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
456 /* Fail if we do not the SeSecurityPrivilege */
457 if (!SepPrivilegeCheck(Token
,
460 PRIVILEGE_SET_ALL_NECESSARY
,
463 *AccessStatus
= STATUS_PRIVILEGE_NOT_HELD
;
467 /* Adjust access rights */
468 RemainingAccess
&= ~ACCESS_SYSTEM_SECURITY
;
469 PreviouslyGrantedAccess
|= ACCESS_SYSTEM_SECURITY
;
471 /* Succeed if there are no more rights to grant */
472 if (RemainingAccess
== 0)
474 *GrantedAccess
= PreviouslyGrantedAccess
;
475 *AccessStatus
= STATUS_SUCCESS
;
481 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
485 if (!NT_SUCCESS(Status
))
487 *AccessStatus
= Status
;
491 /* RULE 1: Grant desired access if the object is unprotected */
492 if (Present
== FALSE
|| Dacl
== NULL
)
494 if (DesiredAccess
& MAXIMUM_ALLOWED
)
496 *GrantedAccess
= GenericMapping
->GenericAll
;
497 *GrantedAccess
|= (DesiredAccess
& ~MAXIMUM_ALLOWED
);
501 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
504 *AccessStatus
= STATUS_SUCCESS
;
508 #ifdef OLD_ACCESS_CHECK
509 CurrentAccess
= PreviouslyGrantedAccess
;
512 /* RULE 2: Check token for 'take ownership' privilege */
513 if (DesiredAccess
& WRITE_OWNER
)
515 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
516 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
518 if (SepPrivilegeCheck(Token
,
521 PRIVILEGE_SET_ALL_NECESSARY
,
524 /* Adjust access rights */
525 RemainingAccess
&= ~WRITE_OWNER
;
526 PreviouslyGrantedAccess
|= WRITE_OWNER
;
527 #ifdef OLD_ACCESS_CHECK
528 CurrentAccess
|= WRITE_OWNER
;
531 /* Succeed if there are no more rights to grant */
532 if (RemainingAccess
== 0)
534 *GrantedAccess
= PreviouslyGrantedAccess
;
535 *AccessStatus
= STATUS_SUCCESS
;
541 /* Deny access if the DACL is empty */
542 if (Dacl
->AceCount
== 0)
544 if (RemainingAccess
== MAXIMUM_ALLOWED
&& PreviouslyGrantedAccess
!= 0)
546 *GrantedAccess
= PreviouslyGrantedAccess
;
547 *AccessStatus
= STATUS_SUCCESS
;
553 *AccessStatus
= STATUS_ACCESS_DENIED
;
558 /* Fail if DACL is absent */
559 if (Present
== FALSE
)
562 *AccessStatus
= STATUS_ACCESS_DENIED
;
566 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
567 if (DesiredAccess
& MAXIMUM_ALLOWED
)
569 CurrentAce
= (PACE
)(Dacl
+ 1);
570 for (i
= 0; i
< Dacl
->AceCount
; i
++)
572 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
574 Sid
= (PSID
)(CurrentAce
+ 1);
575 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
577 if (SepSidInToken(Token
, Sid
))
579 /* Map access rights from the ACE */
580 TempAccess
= CurrentAce
->AccessMask
;
581 RtlMapGenericMask(&TempAccess
, GenericMapping
);
583 /* Deny access rights that have not been granted yet */
584 TempDeniedAccess
|= (TempAccess
& ~TempGrantedAccess
);
587 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
589 if (SepSidInToken(Token
, Sid
))
591 /* Map access rights from the ACE */
592 TempAccess
= CurrentAce
->AccessMask
;
593 RtlMapGenericMask(&TempAccess
, GenericMapping
);
595 /* Grant access rights that have not been denied yet */
596 TempGrantedAccess
|= (TempAccess
& ~TempDeniedAccess
);
601 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
605 /* Get the next ACE */
606 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
609 /* Fail if some rights have not been granted */
610 RemainingAccess
&= ~(MAXIMUM_ALLOWED
| TempGrantedAccess
);
611 if (RemainingAccess
!= 0)
614 *AccessStatus
= STATUS_ACCESS_DENIED
;
618 /* Set granted access right and access status */
619 *GrantedAccess
= TempGrantedAccess
| PreviouslyGrantedAccess
;
620 if (*GrantedAccess
!= 0)
622 *AccessStatus
= STATUS_SUCCESS
;
627 *AccessStatus
= STATUS_ACCESS_DENIED
;
632 /* RULE 4: Grant rights according to the DACL */
633 CurrentAce
= (PACE
)(Dacl
+ 1);
634 for (i
= 0; i
< Dacl
->AceCount
; i
++)
636 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
638 Sid
= (PSID
)(CurrentAce
+ 1);
639 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
641 if (SepSidInToken(Token
, Sid
))
643 #ifdef OLD_ACCESS_CHECK
645 *AccessStatus
= STATUS_ACCESS_DENIED
;
648 /* Map access rights from the ACE */
649 TempAccess
= CurrentAce
->AccessMask
;
650 RtlMapGenericMask(&TempAccess
, GenericMapping
);
652 /* Leave if a remaining right must be denied */
653 if (RemainingAccess
& TempAccess
)
658 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
660 if (SepSidInToken(Token
, Sid
))
662 #ifdef OLD_ACCESS_CHECK
663 AccessMask
= CurrentAce
->AccessMask
;
664 RtlMapGenericMask(&AccessMask
, GenericMapping
);
665 CurrentAccess
|= AccessMask
;
667 /* Map access rights from the ACE */
668 TempAccess
= CurrentAce
->AccessMask
;
669 RtlMapGenericMask(&TempAccess
, GenericMapping
);
671 /* Remove granted rights */
672 RemainingAccess
&= ~TempAccess
;
678 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
682 /* Get the next ACE */
683 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
686 #ifdef OLD_ACCESS_CHECK
687 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
688 CurrentAccess
, DesiredAccess
);
690 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
692 if ((*GrantedAccess
& ~VALID_INHERIT_FLAGS
) ==
693 (DesiredAccess
& ~VALID_INHERIT_FLAGS
))
695 *AccessStatus
= STATUS_SUCCESS
;
700 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
701 *GrantedAccess
, DesiredAccess
, GenericMapping
);
702 //*AccessStatus = STATUS_ACCESS_DENIED;
704 *AccessStatus
= STATUS_SUCCESS
;
708 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
709 DesiredAccess
, PreviouslyGrantedAccess
, RemainingAccess
);
711 /* Fail if some rights have not been granted */
712 if (RemainingAccess
!= 0)
715 *AccessStatus
= STATUS_ACCESS_DENIED
;
719 /* Set granted access rights */
720 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
722 DPRINT("GrantedAccess %08lx\n", *GrantedAccess
);
724 /* Fail if no rights have been granted */
725 if (*GrantedAccess
== 0)
727 *AccessStatus
= STATUS_ACCESS_DENIED
;
731 *AccessStatus
= STATUS_SUCCESS
;
737 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
739 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
742 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
743 Owner
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Owner
+
744 (ULONG_PTR
)SecurityDescriptor
);
746 Owner
= (PSID
)SecurityDescriptor
->Owner
;
752 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
754 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
757 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
758 Group
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Group
+
759 (ULONG_PTR
)SecurityDescriptor
);
761 Group
= (PSID
)SecurityDescriptor
->Group
;
767 /* PUBLIC FUNCTIONS ***********************************************************/
774 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
775 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
776 IN BOOLEAN SubjectContextLocked
,
777 IN ACCESS_MASK DesiredAccess
,
778 IN ACCESS_MASK PreviouslyGrantedAccess
,
779 OUT PPRIVILEGE_SET
* Privileges
,
780 IN PGENERIC_MAPPING GenericMapping
,
781 IN KPROCESSOR_MODE AccessMode
,
782 OUT PACCESS_MASK GrantedAccess
,
783 OUT PNTSTATUS AccessStatus
)
789 /* Check if this is kernel mode */
790 if (AccessMode
== KernelMode
)
792 /* Check if kernel wants everything */
793 if (DesiredAccess
& MAXIMUM_ALLOWED
)
796 *GrantedAccess
= GenericMapping
->GenericAll
;
797 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
798 *GrantedAccess
|= PreviouslyGrantedAccess
;
802 /* Give the desired and previous access */
803 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
807 *AccessStatus
= STATUS_SUCCESS
;
811 /* Check if we didn't get an SD */
812 if (!SecurityDescriptor
)
814 /* Automatic failure */
815 *AccessStatus
= STATUS_ACCESS_DENIED
;
819 /* Check for invalid impersonation */
820 if ((SubjectSecurityContext
->ClientToken
) &&
821 (SubjectSecurityContext
->ImpersonationLevel
< SecurityImpersonation
))
823 *AccessStatus
= STATUS_BAD_IMPERSONATION_LEVEL
;
827 /* Acquire the lock if needed */
828 if (!SubjectContextLocked
)
829 SeLockSubjectContext(SubjectSecurityContext
);
831 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
832 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
834 PACCESS_TOKEN Token
= SubjectSecurityContext
->ClientToken
?
835 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
837 if (SepTokenIsOwner(Token
,
840 if (DesiredAccess
& MAXIMUM_ALLOWED
)
841 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
843 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
845 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
849 if (DesiredAccess
== 0)
851 *GrantedAccess
= PreviouslyGrantedAccess
;
852 *AccessStatus
= STATUS_SUCCESS
;
857 /* Call the internal function */
858 ret
= SepAccessCheck(SecurityDescriptor
,
859 SubjectSecurityContext
,
861 PreviouslyGrantedAccess
,
869 /* Release the lock if needed */
870 if (!SubjectContextLocked
)
871 SeUnlockSubjectContext(SubjectSecurityContext
);
876 /* SYSTEM CALLS ***************************************************************/
883 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
884 IN HANDLE TokenHandle
,
885 IN ACCESS_MASK DesiredAccess
,
886 IN PGENERIC_MAPPING GenericMapping
,
887 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL
,
888 IN OUT PULONG PrivilegeSetLength
,
889 OUT PACCESS_MASK GrantedAccess
,
890 OUT PNTSTATUS AccessStatus
)
892 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
= NULL
;
893 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
;
894 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
895 ACCESS_MASK PreviouslyGrantedAccess
= 0;
900 /* Check if this is kernel mode */
901 if (PreviousMode
== KernelMode
)
903 /* Check if kernel wants everything */
904 if (DesiredAccess
& MAXIMUM_ALLOWED
)
907 *GrantedAccess
= GenericMapping
->GenericAll
;
908 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
912 /* Just give the desired access */
913 *GrantedAccess
= DesiredAccess
;
917 *AccessStatus
= STATUS_SUCCESS
;
918 return STATUS_SUCCESS
;
921 /* Protect probe in SEH */
924 /* Probe all pointers */
925 ProbeForRead(GenericMapping
, sizeof(GENERIC_MAPPING
), sizeof(ULONG
));
926 ProbeForRead(PrivilegeSetLength
, sizeof(ULONG
), sizeof(ULONG
));
927 ProbeForWrite(PrivilegeSet
, *PrivilegeSetLength
, sizeof(ULONG
));
928 ProbeForWrite(GrantedAccess
, sizeof(ACCESS_MASK
), sizeof(ULONG
));
929 ProbeForWrite(AccessStatus
, sizeof(NTSTATUS
), sizeof(ULONG
));
931 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
933 /* Return the exception code */
934 _SEH2_YIELD(return _SEH2_GetExceptionCode());
938 /* Check for unmapped access rights */
939 if (DesiredAccess
& (GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
| GENERIC_ALL
))
940 return STATUS_GENERIC_NOT_MAPPED
;
942 /* Reference the token */
943 Status
= ObReferenceObjectByHandle(TokenHandle
,
949 if (!NT_SUCCESS(Status
))
951 DPRINT("Failed to reference token (Status %lx)\n", Status
);
955 /* Check token type */
956 if (Token
->TokenType
!= TokenImpersonation
)
958 DPRINT("No impersonation token\n");
959 ObDereferenceObject(Token
);
960 return STATUS_NO_IMPERSONATION_TOKEN
;
963 /* Check the impersonation level */
964 if (Token
->ImpersonationLevel
< SecurityIdentification
)
966 DPRINT("Impersonation level < SecurityIdentification\n");
967 ObDereferenceObject(Token
);
968 return STATUS_BAD_IMPERSONATION_LEVEL
;
971 /* Capture the security descriptor */
972 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
976 &CapturedSecurityDescriptor
);
977 if (!NT_SUCCESS(Status
))
979 DPRINT("Failed to capture the Security Descriptor\n");
980 ObDereferenceObject(Token
);
984 /* Check the captured security descriptor */
985 if (CapturedSecurityDescriptor
== NULL
)
987 DPRINT("Security Descriptor is NULL\n");
988 ObDereferenceObject(Token
);
989 return STATUS_INVALID_SECURITY_DESCR
;
992 /* Check security descriptor for valid owner and group */
993 if (SepGetSDOwner(SecurityDescriptor
) == NULL
|| // FIXME: use CapturedSecurityDescriptor
994 SepGetSDGroup(SecurityDescriptor
) == NULL
) // FIXME: use CapturedSecurityDescriptor
996 DPRINT("Security Descriptor does not have a valid group or owner\n");
997 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
1000 ObDereferenceObject(Token
);
1001 return STATUS_INVALID_SECURITY_DESCR
;
1004 /* Set up the subject context, and lock it */
1005 SubjectSecurityContext
.ClientToken
= Token
;
1006 SubjectSecurityContext
.ImpersonationLevel
= Token
->ImpersonationLevel
;
1007 SubjectSecurityContext
.PrimaryToken
= NULL
;
1008 SubjectSecurityContext
.ProcessAuditId
= NULL
;
1009 SeLockSubjectContext(&SubjectSecurityContext
);
1011 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
1012 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
1014 if (SepTokenIsOwner(Token
, SecurityDescriptor
)) // FIXME: use CapturedSecurityDescriptor
1016 if (DesiredAccess
& MAXIMUM_ALLOWED
)
1017 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
1019 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
1021 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
1025 if (DesiredAccess
== 0)
1027 *GrantedAccess
= PreviouslyGrantedAccess
;
1028 *AccessStatus
= STATUS_SUCCESS
;
1032 /* Now perform the access check */
1033 SepAccessCheck(SecurityDescriptor
, // FIXME: use CapturedSecurityDescriptor
1034 &SubjectSecurityContext
,
1036 PreviouslyGrantedAccess
,
1037 &PrivilegeSet
, //FIXME
1044 /* Unlock subject context */
1045 SeUnlockSubjectContext(&SubjectSecurityContext
);
1047 /* Release the captured security descriptor */
1048 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
1052 /* Dereference the token */
1053 ObDereferenceObject(Token
);
1055 /* Check succeeded */
1056 return STATUS_SUCCESS
;
1062 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1063 IN PSID PrincipalSelfSid
,
1064 IN HANDLE ClientToken
,
1065 IN ACCESS_MASK DesiredAccess
,
1066 IN POBJECT_TYPE_LIST ObjectTypeList
,
1067 IN ULONG ObjectTypeLength
,
1068 IN PGENERIC_MAPPING GenericMapping
,
1069 IN PPRIVILEGE_SET PrivilegeSet
,
1070 IN ULONG PrivilegeSetLength
,
1071 OUT PACCESS_MASK GrantedAccess
,
1072 OUT PNTSTATUS AccessStatus
)
1075 return STATUS_NOT_IMPLEMENTED
;
1080 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1082 IN PUNICODE_STRING ObjectTypeName
,
1083 IN PUNICODE_STRING ObjectName
,
1084 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1085 IN PSID PrincipalSelfSid
,
1086 IN ACCESS_MASK DesiredAccess
,
1087 IN AUDIT_EVENT_TYPE AuditType
,
1089 IN POBJECT_TYPE_LIST ObjectTypeList
,
1090 IN ULONG ObjectTypeLength
,
1091 IN PGENERIC_MAPPING GenericMapping
,
1092 IN BOOLEAN ObjectCreation
,
1093 OUT PACCESS_MASK GrantedAccess
,
1094 OUT PNTSTATUS AccessStatus
,
1095 OUT PBOOLEAN GenerateOnClose
)
1098 return STATUS_NOT_IMPLEMENTED
;
1103 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1104 IN PSID PrincipalSelfSid
,
1105 IN HANDLE ClientToken
,
1106 IN ACCESS_MASK DesiredAccess
,
1107 IN POBJECT_TYPE_LIST ObjectTypeList
,
1108 IN ULONG ObjectTypeLength
,
1109 IN PGENERIC_MAPPING GenericMapping
,
1110 IN PPRIVILEGE_SET PrivilegeSet
,
1111 IN ULONG PrivilegeSetLength
,
1112 OUT PACCESS_MASK GrantedAccess
,
1113 OUT PNTSTATUS AccessStatus
)
1116 return STATUS_NOT_IMPLEMENTED
;
1121 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1123 IN PUNICODE_STRING ObjectTypeName
,
1124 IN PUNICODE_STRING ObjectName
,
1125 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1126 IN PSID PrincipalSelfSid
,
1127 IN ACCESS_MASK DesiredAccess
,
1128 IN AUDIT_EVENT_TYPE AuditType
,
1130 IN POBJECT_TYPE_LIST ObjectTypeList
,
1131 IN ULONG ObjectTypeLength
,
1132 IN PGENERIC_MAPPING GenericMapping
,
1133 IN BOOLEAN ObjectCreation
,
1134 OUT PACCESS_MASK GrantedAccess
,
1135 OUT PNTSTATUS AccessStatus
,
1136 OUT PBOOLEAN GenerateOnClose
)
1139 return STATUS_NOT_IMPLEMENTED
;
1144 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName
,
1146 IN HANDLE ClientToken
,
1147 IN PUNICODE_STRING ObjectTypeName
,
1148 IN PUNICODE_STRING ObjectName
,
1149 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1150 IN PSID PrincipalSelfSid
,
1151 IN ACCESS_MASK DesiredAccess
,
1152 IN AUDIT_EVENT_TYPE AuditType
,
1154 IN POBJECT_TYPE_LIST ObjectTypeList
,
1155 IN ULONG ObjectTypeLength
,
1156 IN PGENERIC_MAPPING GenericMapping
,
1157 IN BOOLEAN ObjectCreation
,
1158 OUT PACCESS_MASK GrantedAccess
,
1159 OUT PNTSTATUS AccessStatus
,
1160 OUT PBOOLEAN GenerateOnClose
)
1163 return STATUS_NOT_IMPLEMENTED
;