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
;
21 extern ULONG ExpInitializationPhase
;
22 extern ERESOURCE SepSubjectContextLock
;
24 /* PRIVATE FUNCTIONS **********************************************************/
26 static BOOLEAN INIT_FUNCTION
29 SepExports
.SeCreateTokenPrivilege
= SeCreateTokenPrivilege
;
30 SepExports
.SeAssignPrimaryTokenPrivilege
= SeAssignPrimaryTokenPrivilege
;
31 SepExports
.SeLockMemoryPrivilege
= SeLockMemoryPrivilege
;
32 SepExports
.SeIncreaseQuotaPrivilege
= SeIncreaseQuotaPrivilege
;
33 SepExports
.SeUnsolicitedInputPrivilege
= SeUnsolicitedInputPrivilege
;
34 SepExports
.SeTcbPrivilege
= SeTcbPrivilege
;
35 SepExports
.SeSecurityPrivilege
= SeSecurityPrivilege
;
36 SepExports
.SeTakeOwnershipPrivilege
= SeTakeOwnershipPrivilege
;
37 SepExports
.SeLoadDriverPrivilege
= SeLoadDriverPrivilege
;
38 SepExports
.SeCreatePagefilePrivilege
= SeCreatePagefilePrivilege
;
39 SepExports
.SeIncreaseBasePriorityPrivilege
= SeIncreaseBasePriorityPrivilege
;
40 SepExports
.SeSystemProfilePrivilege
= SeSystemProfilePrivilege
;
41 SepExports
.SeSystemtimePrivilege
= SeSystemtimePrivilege
;
42 SepExports
.SeProfileSingleProcessPrivilege
= SeProfileSingleProcessPrivilege
;
43 SepExports
.SeCreatePermanentPrivilege
= SeCreatePermanentPrivilege
;
44 SepExports
.SeBackupPrivilege
= SeBackupPrivilege
;
45 SepExports
.SeRestorePrivilege
= SeRestorePrivilege
;
46 SepExports
.SeShutdownPrivilege
= SeShutdownPrivilege
;
47 SepExports
.SeDebugPrivilege
= SeDebugPrivilege
;
48 SepExports
.SeAuditPrivilege
= SeAuditPrivilege
;
49 SepExports
.SeSystemEnvironmentPrivilege
= SeSystemEnvironmentPrivilege
;
50 SepExports
.SeChangeNotifyPrivilege
= SeChangeNotifyPrivilege
;
51 SepExports
.SeRemoteShutdownPrivilege
= SeRemoteShutdownPrivilege
;
53 SepExports
.SeNullSid
= SeNullSid
;
54 SepExports
.SeWorldSid
= SeWorldSid
;
55 SepExports
.SeLocalSid
= SeLocalSid
;
56 SepExports
.SeCreatorOwnerSid
= SeCreatorOwnerSid
;
57 SepExports
.SeCreatorGroupSid
= SeCreatorGroupSid
;
58 SepExports
.SeNtAuthoritySid
= SeNtAuthoritySid
;
59 SepExports
.SeDialupSid
= SeDialupSid
;
60 SepExports
.SeNetworkSid
= SeNetworkSid
;
61 SepExports
.SeBatchSid
= SeBatchSid
;
62 SepExports
.SeInteractiveSid
= SeInteractiveSid
;
63 SepExports
.SeLocalSystemSid
= SeLocalSystemSid
;
64 SepExports
.SeAliasAdminsSid
= SeAliasAdminsSid
;
65 SepExports
.SeAliasUsersSid
= SeAliasUsersSid
;
66 SepExports
.SeAliasGuestsSid
= SeAliasGuestsSid
;
67 SepExports
.SeAliasPowerUsersSid
= SeAliasPowerUsersSid
;
68 SepExports
.SeAliasAccountOpsSid
= SeAliasAccountOpsSid
;
69 SepExports
.SeAliasSystemOpsSid
= SeAliasSystemOpsSid
;
70 SepExports
.SeAliasPrintOpsSid
= SeAliasPrintOpsSid
;
71 SepExports
.SeAliasBackupOpsSid
= SeAliasBackupOpsSid
;
72 SepExports
.SeAuthenticatedUsersSid
= SeAuthenticatedUsersSid
;
73 SepExports
.SeRestrictedSid
= SeRestrictedSid
;
74 SepExports
.SeAnonymousLogonSid
= SeAnonymousLogonSid
;
76 SepExports
.SeUndockPrivilege
= SeUndockPrivilege
;
77 SepExports
.SeSyncAgentPrivilege
= SeSyncAgentPrivilege
;
78 SepExports
.SeEnableDelegationPrivilege
= SeEnableDelegationPrivilege
;
80 SeExports
= &SepExports
;
87 SepInitializationPhase0(VOID
)
92 if (!SepInitSecurityIDs()) return FALSE
;
93 if (!SepInitDACLs()) return FALSE
;
94 if (!SepInitSDs()) return FALSE
;
96 if (!SepInitExports()) return FALSE
;
98 /* Initialize the subject context lock */
99 ExInitializeResource(&SepSubjectContextLock
);
101 /* Initialize token objects */
102 SepInitializeTokenImplementation();
104 /* Clear impersonation info for the idle thread */
105 PsGetCurrentThread()->ImpersonationInfo
= NULL
;
106 PspClearCrossThreadFlag(PsGetCurrentThread(),
107 CT_ACTIVE_IMPERSONATION_INFO_BIT
);
109 /* Initialize the boot token */
110 ObInitializeFastReference(&PsGetCurrentProcess()->Token
, NULL
);
111 ObInitializeFastReference(&PsGetCurrentProcess()->Token
,
112 SepCreateSystemProcessToken());
118 SepInitializationPhase1(VOID
)
123 /* Insert the system token into the tree */
124 Status
= ObInsertObject((PVOID
)(PsGetCurrentProcess()->Token
.Value
&
131 ASSERT(NT_SUCCESS(Status
));
133 /* FIXME: TODO \\ Security directory */
141 /* Check the initialization phase */
142 switch (ExpInitializationPhase
)
147 return SepInitializationPhase0();
152 return SepInitializationPhase1();
156 /* Don't know any other phase! Bugcheck! */
157 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL
,
159 ExpInitializationPhase
,
170 OBJECT_ATTRIBUTES ObjectAttributes
;
172 HANDLE DirectoryHandle
;
176 /* Create '\Security' directory */
177 RtlInitUnicodeString(&Name
,
179 InitializeObjectAttributes(&ObjectAttributes
,
184 Status
= ZwCreateDirectoryObject(&DirectoryHandle
,
185 DIRECTORY_ALL_ACCESS
,
187 if (!NT_SUCCESS(Status
))
189 DPRINT1("Failed to create 'Security' directory!\n");
193 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
194 RtlInitUnicodeString(&Name
,
195 L
"\\LSA_AUTHENTICATION_INITALIZED");
196 InitializeObjectAttributes(&ObjectAttributes
,
201 Status
= ZwCreateEvent(&EventHandle
,
204 SynchronizationEvent
,
206 if (!NT_SUCCESS(Status
))
208 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
209 NtClose(DirectoryHandle
);
213 ZwClose(EventHandle
);
214 ZwClose(DirectoryHandle
);
216 /* FIXME: Create SRM port and listener thread */
223 SeDefaultObjectMethod(IN PVOID Object
,
224 IN SECURITY_OPERATION_CODE OperationType
,
225 IN PSECURITY_INFORMATION SecurityInformation
,
226 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
227 IN OUT PULONG ReturnLength OPTIONAL
,
228 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
229 IN POOL_TYPE PoolType
,
230 IN PGENERIC_MAPPING GenericMapping
)
234 /* Select the operation type */
235 switch (OperationType
)
237 /* Setting a new descriptor */
238 case SetSecurityDescriptor
:
241 ASSERT((PoolType
== PagedPool
) || (PoolType
== NonPagedPool
));
243 /* Set the information */
244 return ObSetSecurityDescriptorInfo(Object
,
247 OldSecurityDescriptor
,
251 case QuerySecurityDescriptor
:
253 /* Query the information */
254 return ObQuerySecurityDescriptorInfo(Object
,
258 OldSecurityDescriptor
);
260 case DeleteSecurityDescriptor
:
263 return ObDeassignSecurity(OldSecurityDescriptor
);
265 case AssignSecurityDescriptor
:
268 ObAssignObjectSecurityDescriptor(Object
, SecurityDescriptor
, PoolType
);
269 return STATUS_SUCCESS
;
274 KeBugCheckEx(SECURITY_SYSTEM
, 0, STATUS_INVALID_PARAMETER
, 0, 0);
277 /* Should never reach here */
279 return STATUS_SUCCESS
;
282 ULONG SidInTokenCalls
= 0;
285 SepSidInToken(PACCESS_TOKEN _Token
,
289 PTOKEN Token
= (PTOKEN
)_Token
;
294 if (!(SidInTokenCalls
% 10000)) DPRINT1("SidInToken Calls: %d\n", SidInTokenCalls
);
296 if (Token
->UserAndGroupCount
== 0)
301 for (i
=0; i
<Token
->UserAndGroupCount
; i
++)
303 if (RtlEqualSid(Sid
, Token
->UserAndGroups
[i
].Sid
))
305 if ((i
== 0)|| (Token
->UserAndGroups
[i
].Attributes
& SE_GROUP_ENABLED
))
318 SepTokenIsOwner(PACCESS_TOKEN Token
,
319 PSECURITY_DESCRIPTOR SecurityDescriptor
)
325 Status
= RtlGetOwnerSecurityDescriptor(SecurityDescriptor
,
328 if (!NT_SUCCESS(Status
))
330 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status
);
336 DPRINT1("Owner Sid is NULL\n");
340 return SepSidInToken(Token
, Sid
);
344 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
345 OUT PACCESS_MASK DesiredAccess
)
349 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
|
350 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
))
352 *DesiredAccess
|= READ_CONTROL
;
354 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
356 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
361 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation
,
362 OUT PACCESS_MASK DesiredAccess
)
366 if (SecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
368 *DesiredAccess
|= WRITE_OWNER
;
370 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
372 *DesiredAccess
|= WRITE_DAC
;
374 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
376 *DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
381 #define OLD_ACCESS_CHECK
384 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
385 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
386 IN ACCESS_MASK DesiredAccess
,
387 IN ACCESS_MASK PreviouslyGrantedAccess
,
388 OUT PPRIVILEGE_SET
* Privileges
,
389 IN PGENERIC_MAPPING GenericMapping
,
390 IN KPROCESSOR_MODE AccessMode
,
391 OUT PACCESS_MASK GrantedAccess
,
392 OUT PNTSTATUS AccessStatus
)
394 LUID_AND_ATTRIBUTES Privilege
;
395 #ifdef OLD_ACCESS_CHECK
396 ACCESS_MASK CurrentAccess
, AccessMask
;
398 ACCESS_MASK RemainingAccess
;
399 ACCESS_MASK TempAccess
;
400 ACCESS_MASK TempGrantedAccess
= 0;
401 ACCESS_MASK TempDeniedAccess
= 0;
412 /* Check for no access desired */
415 /* Check if we had no previous access */
416 if (!PreviouslyGrantedAccess
)
418 /* Then there's nothing to give */
419 *AccessStatus
= STATUS_ACCESS_DENIED
;
423 /* Return the previous access only */
424 *GrantedAccess
= PreviouslyGrantedAccess
;
425 *AccessStatus
= STATUS_SUCCESS
;
430 /* Map given accesses */
431 RtlMapGenericMask(&DesiredAccess
, GenericMapping
);
432 if (PreviouslyGrantedAccess
)
433 RtlMapGenericMask(&PreviouslyGrantedAccess
, GenericMapping
);
435 #ifdef OLD_ACCESS_CHECK
436 CurrentAccess
= PreviouslyGrantedAccess
;
438 /* Initialize remaining access rights */
439 RemainingAccess
= DesiredAccess
;
441 Token
= SubjectSecurityContext
->ClientToken
?
442 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
444 /* Check for system security access */
445 if (RemainingAccess
& ACCESS_SYSTEM_SECURITY
)
447 Privilege
.Luid
= SeSecurityPrivilege
;
448 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
450 /* Fail if we do not the SeSecurityPrivilege */
451 if (!SepPrivilegeCheck(Token
,
454 PRIVILEGE_SET_ALL_NECESSARY
,
457 *AccessStatus
= STATUS_PRIVILEGE_NOT_HELD
;
461 /* Adjust access rights */
462 RemainingAccess
&= ~ACCESS_SYSTEM_SECURITY
;
463 PreviouslyGrantedAccess
|= ACCESS_SYSTEM_SECURITY
;
465 /* Succeed if there are no more rights to grant */
466 if (RemainingAccess
== 0)
468 *GrantedAccess
= PreviouslyGrantedAccess
;
469 *AccessStatus
= STATUS_SUCCESS
;
475 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
479 if (!NT_SUCCESS(Status
))
481 *AccessStatus
= Status
;
485 /* RULE 1: Grant desired access if the object is unprotected */
486 if (Present
== FALSE
|| Dacl
== NULL
)
488 if (DesiredAccess
& MAXIMUM_ALLOWED
)
490 *GrantedAccess
= GenericMapping
->GenericAll
;
491 *GrantedAccess
|= (DesiredAccess
& ~MAXIMUM_ALLOWED
);
495 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
498 *AccessStatus
= STATUS_SUCCESS
;
502 #ifdef OLD_ACCESS_CHECK
503 CurrentAccess
= PreviouslyGrantedAccess
;
506 /* RULE 2: Check token for 'take ownership' privilege */
507 if (DesiredAccess
& WRITE_OWNER
)
509 Privilege
.Luid
= SeTakeOwnershipPrivilege
;
510 Privilege
.Attributes
= SE_PRIVILEGE_ENABLED
;
512 if (SepPrivilegeCheck(Token
,
515 PRIVILEGE_SET_ALL_NECESSARY
,
518 /* Adjust access rights */
519 RemainingAccess
&= ~WRITE_OWNER
;
520 PreviouslyGrantedAccess
|= WRITE_OWNER
;
521 #ifdef OLD_ACCESS_CHECK
522 CurrentAccess
|= WRITE_OWNER
;
525 /* Succeed if there are no more rights to grant */
526 if (RemainingAccess
== 0)
528 *GrantedAccess
= PreviouslyGrantedAccess
;
529 *AccessStatus
= STATUS_SUCCESS
;
535 /* Deny access if the DACL is empty */
536 if (Dacl
->AceCount
== 0)
538 if (RemainingAccess
== MAXIMUM_ALLOWED
&& PreviouslyGrantedAccess
!= 0)
540 *GrantedAccess
= PreviouslyGrantedAccess
;
541 *AccessStatus
= STATUS_SUCCESS
;
547 *AccessStatus
= STATUS_ACCESS_DENIED
;
552 /* Fail if DACL is absent */
553 if (Present
== FALSE
)
556 *AccessStatus
= STATUS_ACCESS_DENIED
;
560 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
561 if (DesiredAccess
& MAXIMUM_ALLOWED
)
563 CurrentAce
= (PACE
)(Dacl
+ 1);
564 for (i
= 0; i
< Dacl
->AceCount
; i
++)
566 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
568 Sid
= (PSID
)(CurrentAce
+ 1);
569 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
571 if (SepSidInToken(Token
, Sid
))
573 /* Map access rights from the ACE */
574 TempAccess
= CurrentAce
->AccessMask
;
575 RtlMapGenericMask(&TempAccess
, GenericMapping
);
577 /* Deny access rights that have not been granted yet */
578 TempDeniedAccess
|= (TempAccess
& ~TempGrantedAccess
);
581 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
583 if (SepSidInToken(Token
, Sid
))
585 /* Map access rights from the ACE */
586 TempAccess
= CurrentAce
->AccessMask
;
587 RtlMapGenericMask(&TempAccess
, GenericMapping
);
589 /* Grant access rights that have not been denied yet */
590 TempGrantedAccess
|= (TempAccess
& ~TempDeniedAccess
);
595 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
599 /* Get the next ACE */
600 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
603 /* Fail if some rights have not been granted */
604 RemainingAccess
&= ~(MAXIMUM_ALLOWED
| TempGrantedAccess
);
605 if (RemainingAccess
!= 0)
608 *AccessStatus
= STATUS_ACCESS_DENIED
;
612 /* Set granted access right and access status */
613 *GrantedAccess
= TempGrantedAccess
| PreviouslyGrantedAccess
;
614 if (*GrantedAccess
!= 0)
616 *AccessStatus
= STATUS_SUCCESS
;
621 *AccessStatus
= STATUS_ACCESS_DENIED
;
626 /* RULE 4: Grant rights according to the DACL */
627 CurrentAce
= (PACE
)(Dacl
+ 1);
628 for (i
= 0; i
< Dacl
->AceCount
; i
++)
630 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
632 Sid
= (PSID
)(CurrentAce
+ 1);
633 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
635 if (SepSidInToken(Token
, Sid
))
637 #ifdef OLD_ACCESS_CHECK
639 *AccessStatus
= STATUS_ACCESS_DENIED
;
642 /* Map access rights from the ACE */
643 TempAccess
= CurrentAce
->AccessMask
;
644 RtlMapGenericMask(&TempAccess
, GenericMapping
);
646 /* Leave if a remaining right must be denied */
647 if (RemainingAccess
& TempAccess
)
652 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
654 if (SepSidInToken(Token
, Sid
))
656 #ifdef OLD_ACCESS_CHECK
657 AccessMask
= CurrentAce
->AccessMask
;
658 RtlMapGenericMask(&AccessMask
, GenericMapping
);
659 CurrentAccess
|= AccessMask
;
661 /* Map access rights from the ACE */
662 TempAccess
= CurrentAce
->AccessMask
;
663 RtlMapGenericMask(&TempAccess
, GenericMapping
);
665 /* Remove granted rights */
666 RemainingAccess
&= ~TempAccess
;
672 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
676 /* Get the next ACE */
677 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
680 #ifdef OLD_ACCESS_CHECK
681 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
682 CurrentAccess
, DesiredAccess
);
684 *GrantedAccess
= CurrentAccess
& DesiredAccess
;
686 if ((*GrantedAccess
& ~VALID_INHERIT_FLAGS
) ==
687 (DesiredAccess
& ~VALID_INHERIT_FLAGS
))
689 *AccessStatus
= STATUS_SUCCESS
;
694 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
695 *GrantedAccess
, DesiredAccess
, GenericMapping
);
696 //*AccessStatus = STATUS_ACCESS_DENIED;
698 *AccessStatus
= STATUS_SUCCESS
;
702 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
703 DesiredAccess
, PreviouslyGrantedAccess
, RemainingAccess
);
705 /* Fail if some rights have not been granted */
706 if (RemainingAccess
!= 0)
709 *AccessStatus
= STATUS_ACCESS_DENIED
;
713 /* Set granted access rights */
714 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
716 DPRINT("GrantedAccess %08lx\n", *GrantedAccess
);
718 /* Fail if no rights have been granted */
719 if (*GrantedAccess
== 0)
721 *AccessStatus
= STATUS_ACCESS_DENIED
;
725 *AccessStatus
= STATUS_SUCCESS
;
731 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
733 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
736 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
737 Owner
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Owner
+
738 (ULONG_PTR
)SecurityDescriptor
);
740 Owner
= (PSID
)SecurityDescriptor
->Owner
;
746 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
748 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
751 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
752 Group
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Group
+
753 (ULONG_PTR
)SecurityDescriptor
);
755 Group
= (PSID
)SecurityDescriptor
->Group
;
761 /* PUBLIC FUNCTIONS ***********************************************************/
767 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
768 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
769 IN BOOLEAN SubjectContextLocked
,
770 IN ACCESS_MASK DesiredAccess
,
771 IN ACCESS_MASK PreviouslyGrantedAccess
,
772 OUT PPRIVILEGE_SET
* Privileges
,
773 IN PGENERIC_MAPPING GenericMapping
,
774 IN KPROCESSOR_MODE AccessMode
,
775 OUT PACCESS_MASK GrantedAccess
,
776 OUT PNTSTATUS AccessStatus
)
782 /* Check if this is kernel mode */
783 if (AccessMode
== KernelMode
)
785 /* Check if kernel wants everything */
786 if (DesiredAccess
& MAXIMUM_ALLOWED
)
789 *GrantedAccess
= GenericMapping
->GenericAll
;
790 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
791 *GrantedAccess
|= PreviouslyGrantedAccess
;
795 /* Give the desired and previous access */
796 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
800 *AccessStatus
= STATUS_SUCCESS
;
804 /* Check if we didn't get an SD */
805 if (!SecurityDescriptor
)
807 /* Automatic failure */
808 *AccessStatus
= STATUS_ACCESS_DENIED
;
812 /* Check for invalid impersonation */
813 if ((SubjectSecurityContext
->ClientToken
) &&
814 (SubjectSecurityContext
->ImpersonationLevel
< SecurityImpersonation
))
816 *AccessStatus
= STATUS_BAD_IMPERSONATION_LEVEL
;
820 /* Acquire the lock if needed */
821 if (!SubjectContextLocked
)
822 SeLockSubjectContext(SubjectSecurityContext
);
824 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
825 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
827 PACCESS_TOKEN Token
= SubjectSecurityContext
->ClientToken
?
828 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
830 if (SepTokenIsOwner(Token
,
833 if (DesiredAccess
& MAXIMUM_ALLOWED
)
834 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
836 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
838 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
842 if (DesiredAccess
== 0)
844 *GrantedAccess
= PreviouslyGrantedAccess
;
845 *AccessStatus
= STATUS_SUCCESS
;
850 /* Call the internal function */
851 ret
= SepAccessCheck(SecurityDescriptor
,
852 SubjectSecurityContext
,
854 PreviouslyGrantedAccess
,
862 /* Release the lock if needed */
863 if (!SubjectContextLocked
)
864 SeUnlockSubjectContext(SubjectSecurityContext
);
869 /* SYSTEM CALLS ***************************************************************/
876 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
877 IN HANDLE TokenHandle
,
878 IN ACCESS_MASK DesiredAccess
,
879 IN PGENERIC_MAPPING GenericMapping
,
880 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL
,
881 IN OUT PULONG PrivilegeSetLength
,
882 OUT PACCESS_MASK GrantedAccess
,
883 OUT PNTSTATUS AccessStatus
)
885 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
= NULL
;
886 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
;
887 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
888 ACCESS_MASK PreviouslyGrantedAccess
= 0;
893 /* Check if this is kernel mode */
894 if (PreviousMode
== KernelMode
)
896 /* Check if kernel wants everything */
897 if (DesiredAccess
& MAXIMUM_ALLOWED
)
900 *GrantedAccess
= GenericMapping
->GenericAll
;
901 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
905 /* Just give the desired access */
906 *GrantedAccess
= DesiredAccess
;
910 *AccessStatus
= STATUS_SUCCESS
;
911 return STATUS_SUCCESS
;
914 /* Protect probe in SEH */
917 /* Probe all pointers */
918 ProbeForRead(GenericMapping
, sizeof(GENERIC_MAPPING
), sizeof(ULONG
));
919 ProbeForRead(PrivilegeSetLength
, sizeof(ULONG
), sizeof(ULONG
));
920 ProbeForWrite(PrivilegeSet
, *PrivilegeSetLength
, sizeof(ULONG
));
921 ProbeForWrite(GrantedAccess
, sizeof(ACCESS_MASK
), sizeof(ULONG
));
922 ProbeForWrite(AccessStatus
, sizeof(NTSTATUS
), sizeof(ULONG
));
924 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
926 /* Return the exception code */
927 _SEH2_YIELD(return _SEH2_GetExceptionCode());
931 /* Check for unmapped access rights */
932 if (DesiredAccess
& (GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
| GENERIC_ALL
))
933 return STATUS_GENERIC_NOT_MAPPED
;
935 /* Reference the token */
936 Status
= ObReferenceObjectByHandle(TokenHandle
,
942 if (!NT_SUCCESS(Status
))
944 DPRINT("Failed to reference token (Status %lx)\n", Status
);
948 /* Check token type */
949 if (Token
->TokenType
!= TokenImpersonation
)
951 DPRINT("No impersonation token\n");
952 ObDereferenceObject(Token
);
953 return STATUS_NO_IMPERSONATION_TOKEN
;
956 /* Check the impersonation level */
957 if (Token
->ImpersonationLevel
< SecurityIdentification
)
959 DPRINT("Impersonation level < SecurityIdentification\n");
960 ObDereferenceObject(Token
);
961 return STATUS_BAD_IMPERSONATION_LEVEL
;
964 /* Capture the security descriptor */
965 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
969 &CapturedSecurityDescriptor
);
970 if (!NT_SUCCESS(Status
))
972 DPRINT("Failed to capture the Security Descriptor\n");
973 ObDereferenceObject(Token
);
977 /* Check the captured security descriptor */
978 if (CapturedSecurityDescriptor
== NULL
)
980 DPRINT("Security Descriptor is NULL\n");
981 ObDereferenceObject(Token
);
982 return STATUS_INVALID_SECURITY_DESCR
;
985 /* Check security descriptor for valid owner and group */
986 if (SepGetSDOwner(SecurityDescriptor
) == NULL
|| // FIXME: use CapturedSecurityDescriptor
987 SepGetSDGroup(SecurityDescriptor
) == NULL
) // FIXME: use CapturedSecurityDescriptor
989 DPRINT("Security Descriptor does not have a valid group or owner\n");
990 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
993 ObDereferenceObject(Token
);
994 return STATUS_INVALID_SECURITY_DESCR
;
997 /* Set up the subject context, and lock it */
998 SubjectSecurityContext
.ClientToken
= Token
;
999 SubjectSecurityContext
.ImpersonationLevel
= Token
->ImpersonationLevel
;
1000 SubjectSecurityContext
.PrimaryToken
= NULL
;
1001 SubjectSecurityContext
.ProcessAuditId
= NULL
;
1002 SeLockSubjectContext(&SubjectSecurityContext
);
1004 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
1005 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
1007 if (SepTokenIsOwner(Token
, SecurityDescriptor
)) // FIXME: use CapturedSecurityDescriptor
1009 if (DesiredAccess
& MAXIMUM_ALLOWED
)
1010 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
1012 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
1014 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
1018 if (DesiredAccess
== 0)
1020 *GrantedAccess
= PreviouslyGrantedAccess
;
1021 *AccessStatus
= STATUS_SUCCESS
;
1025 /* Now perform the access check */
1026 SepAccessCheck(SecurityDescriptor
, // FIXME: use CapturedSecurityDescriptor
1027 &SubjectSecurityContext
,
1029 PreviouslyGrantedAccess
,
1030 &PrivilegeSet
, //FIXME
1037 /* Unlock subject context */
1038 SeUnlockSubjectContext(&SubjectSecurityContext
);
1040 /* Release the captured security descriptor */
1041 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
1045 /* Dereference the token */
1046 ObDereferenceObject(Token
);
1048 /* Check succeeded */
1049 return STATUS_SUCCESS
;
1055 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1056 IN PSID PrincipalSelfSid
,
1057 IN HANDLE ClientToken
,
1058 IN ACCESS_MASK DesiredAccess
,
1059 IN POBJECT_TYPE_LIST ObjectTypeList
,
1060 IN ULONG ObjectTypeLength
,
1061 IN PGENERIC_MAPPING GenericMapping
,
1062 IN PPRIVILEGE_SET PrivilegeSet
,
1063 IN ULONG PrivilegeSetLength
,
1064 OUT PACCESS_MASK GrantedAccess
,
1065 OUT PNTSTATUS AccessStatus
)
1068 return STATUS_NOT_IMPLEMENTED
;
1073 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1075 IN PUNICODE_STRING ObjectTypeName
,
1076 IN PUNICODE_STRING ObjectName
,
1077 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1078 IN PSID PrincipalSelfSid
,
1079 IN ACCESS_MASK DesiredAccess
,
1080 IN AUDIT_EVENT_TYPE AuditType
,
1082 IN POBJECT_TYPE_LIST ObjectTypeList
,
1083 IN ULONG ObjectTypeLength
,
1084 IN PGENERIC_MAPPING GenericMapping
,
1085 IN BOOLEAN ObjectCreation
,
1086 OUT PACCESS_MASK GrantedAccess
,
1087 OUT PNTSTATUS AccessStatus
,
1088 OUT PBOOLEAN GenerateOnClose
)
1091 return STATUS_NOT_IMPLEMENTED
;
1096 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1097 IN PSID PrincipalSelfSid
,
1098 IN HANDLE ClientToken
,
1099 IN ACCESS_MASK DesiredAccess
,
1100 IN POBJECT_TYPE_LIST ObjectTypeList
,
1101 IN ULONG ObjectTypeLength
,
1102 IN PGENERIC_MAPPING GenericMapping
,
1103 IN PPRIVILEGE_SET PrivilegeSet
,
1104 IN ULONG PrivilegeSetLength
,
1105 OUT PACCESS_MASK GrantedAccess
,
1106 OUT PNTSTATUS AccessStatus
)
1109 return STATUS_NOT_IMPLEMENTED
;
1114 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1116 IN PUNICODE_STRING ObjectTypeName
,
1117 IN PUNICODE_STRING ObjectName
,
1118 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1119 IN PSID PrincipalSelfSid
,
1120 IN ACCESS_MASK DesiredAccess
,
1121 IN AUDIT_EVENT_TYPE AuditType
,
1123 IN POBJECT_TYPE_LIST ObjectTypeList
,
1124 IN ULONG ObjectTypeLength
,
1125 IN PGENERIC_MAPPING GenericMapping
,
1126 IN BOOLEAN ObjectCreation
,
1127 OUT PACCESS_MASK GrantedAccess
,
1128 OUT PNTSTATUS AccessStatus
,
1129 OUT PBOOLEAN GenerateOnClose
)
1132 return STATUS_NOT_IMPLEMENTED
;
1137 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName
,
1139 IN HANDLE ClientToken
,
1140 IN PUNICODE_STRING ObjectTypeName
,
1141 IN PUNICODE_STRING ObjectName
,
1142 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
1143 IN PSID PrincipalSelfSid
,
1144 IN ACCESS_MASK DesiredAccess
,
1145 IN AUDIT_EVENT_TYPE AuditType
,
1147 IN POBJECT_TYPE_LIST ObjectTypeList
,
1148 IN ULONG ObjectTypeLength
,
1149 IN PGENERIC_MAPPING GenericMapping
,
1150 IN BOOLEAN ObjectCreation
,
1151 OUT PACCESS_MASK GrantedAccess
,
1152 OUT PNTSTATUS AccessStatus
,
1153 OUT PBOOLEAN GenerateOnClose
)
1156 return STATUS_NOT_IMPLEMENTED
;