ReactOS 0.4.15-dev-6679-g945ee4b
accesschk.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for accesschk.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static VOID SepDenyAccessObjectTypeResultList (_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_opt_ PGUID ObjectTypeGuid)
 Denies access of a target object and the children objects in an object type list.
 
static VOID SepAllowAccessObjectTypeResultList (_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_opt_ PGUID ObjectTypeGuid)
 Allows access of a target object and the children objects in an object type list.
 
static VOID SepDenyAccessObjectTypeList (_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_opt_ PGUID ObjectTypeGuid, _Out_opt_ PBOOLEAN BreakOnDeny)
 Denies access of a target object in the object type list. This access is denied for the whole hierarchy in the list.
 
static VOID SepAllowAccessObjectTypeList (_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_ BOOLEAN RemoveRemainingRights, _In_opt_ PGUID ObjectTypeGuid)
 Allows access of a target object in the object type list. This access is allowed for the whole hierarchy in the list.
 
static VOID SepAnalyzeAcesFromDacl (_In_ ACCESS_CHECK_RIGHT_TYPE ActionType, _In_ ACCESS_MASK RemainingAccess, _In_ PACL Dacl, _In_ PACCESS_TOKEN AccessToken, _In_ PACCESS_TOKEN PrimaryAccessToken, _In_ BOOLEAN IsTokenRestricted, _In_opt_ PSID PrincipalSelfSid, _In_ PGENERIC_MAPPING GenericMapping, _In_opt_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ BOOLEAN UseResultList, _Inout_ PACCESS_CHECK_RIGHTS AccessCheckRights)
 Analyzes an access control entry that is present in a discretionary access control list (DACL) for access right masks of each entry with the purpose to judge whether the calling thread can be warranted access check to a certain object or not.
 
static BOOLEAN SepAccessCheckWorker (_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_opt_ PACCESS_TOKEN ClientAccessToken, _In_ PACCESS_TOKEN PrimaryAccessToken, _In_opt_ PSID PrincipalSelfSid, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK PreviouslyGrantedAccess, _In_ PGENERIC_MAPPING GenericMapping, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN UseResultList, _Out_opt_ PPRIVILEGE_SET *Privileges, _Out_ PACCESS_MASK GrantedAccessList, _Out_ PNTSTATUS AccessStatusList)
 Private worker function that determines whether security access rights can be givento the calling thread in order to access an object depending on the security descriptor and other security context entities, such as an owner. This function is the heart and brain of the whole access check algorithm in the kernel.
 
static ULONG SepGetPrivilegeSetLength (_In_ PPRIVILEGE_SET PrivilegeSet)
 Retrieves the length size of a set list of privileges structure.
 
static NTSTATUS SepAccessCheck (_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ HANDLE ClientToken, _In_opt_ PSID PrincipalSelfSid, _In_ ACCESS_MASK DesiredAccess, _In_ PGENERIC_MAPPING GenericMapping, _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ BOOLEAN UseResultList, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
 Internal function that performs a security check against the client who requests access on a resource object. This function is used by access check NT system calls.
 
BOOLEAN NTAPI SeAccessCheck (_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, _In_ BOOLEAN SubjectContextLocked, _In_ ACCESS_MASK DesiredAccess, _In_ ACCESS_MASK PreviouslyGrantedAccess, _Out_ PPRIVILEGE_SET *Privileges, _In_ PGENERIC_MAPPING GenericMapping, _In_ KPROCESSOR_MODE AccessMode, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
 Determines whether security access rights can be given to an object depending on the security descriptor and other security context entities, such as an owner.
 
BOOLEAN NTAPI SeFastTraverseCheck (_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ PACCESS_STATE AccessState, _In_ ACCESS_MASK DesiredAccess, _In_ KPROCESSOR_MODE AccessMode)
 Determines whether security access rights can be given to an object depending on the security descriptor. Unlike the regular access check procedure in the NT kernel, the fast traverse check is a faster way to quickly check if access can be made into an object.
 
NTSTATUS NTAPI NtAccessCheck (_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ HANDLE ClientToken, _In_ ACCESS_MASK DesiredAccess, _In_ PGENERIC_MAPPING GenericMapping, _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
 Determines whether security access can be granted to a client that requests such access on an object.
 
NTSTATUS NTAPI NtAccessCheckByType (_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_opt_ PSID PrincipalSelfSid, _In_ HANDLE ClientToken, _In_ ACCESS_MASK DesiredAccess, _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ PGENERIC_MAPPING GenericMapping, _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
 Determines whether security access can be granted to a client that requests such access on the object type list. The access is either granted or denied for the whole object hierarchy in the list.
 
NTSTATUS NTAPI NtAccessCheckByTypeResultList (_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_opt_ PSID PrincipalSelfSid, _In_ HANDLE ClientToken, _In_ ACCESS_MASK DesiredAccess, _In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ PGENERIC_MAPPING GenericMapping, _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccess, _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatus)
 Determines whether security access can be granted to a client that requests such access on the object type list. Unlike the NtAccessCheckByType variant, this function will grant or deny access to each individual object and sub-object in the list.
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file accesschk.c.

Function Documentation

◆ NtAccessCheck()

NTSTATUS NTAPI NtAccessCheck ( _In_ PSECURITY_DESCRIPTOR  SecurityDescriptor,
_In_ HANDLE  ClientToken,
_In_ ACCESS_MASK  DesiredAccess,
_In_ PGENERIC_MAPPING  GenericMapping,
_Out_writes_bytes_ *PrivilegeSetLength PPRIVILEGE_SET  PrivilegeSet,
_Inout_ PULONG  PrivilegeSetLength,
_Out_ PACCESS_MASK  GrantedAccess,
_Out_ PNTSTATUS  AccessStatus 
)

Determines whether security access can be granted to a client that requests such access on an object.

Remarks
For more documentation details about the parameters and overall function behavior, see SepAccessCheck.

Definition at line 2186 of file accesschk.c.

2195{
2196 PAGED_CODE();
2197
2198 /* Invoke the internal function to do the job */
2200 ClientToken,
2201 NULL,
2204 PrivilegeSet,
2205 PrivilegeSetLength,
2206 NULL,
2207 0,
2208 FALSE,
2210 AccessStatus);
2211}
#define PAGED_CODE()
static GENERIC_MAPPING GenericMapping
Definition: SeInheritance.c:11
static NTSTATUS SepAccessCheck(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ HANDLE ClientToken, _In_opt_ PSID PrincipalSelfSid, _In_ ACCESS_MASK DesiredAccess, _In_ PGENERIC_MAPPING GenericMapping, _Out_writes_bytes_(*PrivilegeSetLength) PPRIVILEGE_SET PrivilegeSet, _Inout_ PULONG PrivilegeSetLength, _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ BOOLEAN UseResultList, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Internal function that performs a security check against the client who requests access on a resource...
Definition: accesschk.c:1564
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:191
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK _Out_ PNTSTATUS AccessStatus
Definition: sefuncs.h:21
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:20

Referenced by AccessCheck(), and CheckTokenMembership().

◆ NtAccessCheckByType()

NTSTATUS NTAPI NtAccessCheckByType ( _In_ PSECURITY_DESCRIPTOR  SecurityDescriptor,
_In_opt_ PSID  PrincipalSelfSid,
_In_ HANDLE  ClientToken,
_In_ ACCESS_MASK  DesiredAccess,
_In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST  ObjectTypeList,
_In_ ULONG  ObjectTypeListLength,
_In_ PGENERIC_MAPPING  GenericMapping,
_Out_writes_bytes_ *PrivilegeSetLength PPRIVILEGE_SET  PrivilegeSet,
_Inout_ PULONG  PrivilegeSetLength,
_Out_ PACCESS_MASK  GrantedAccess,
_Out_ PNTSTATUS  AccessStatus 
)

Determines whether security access can be granted to a client that requests such access on the object type list. The access is either granted or denied for the whole object hierarchy in the list.

Remarks
For more documentation details about the parameters and overall function behavior, see SepAccessCheck.

Definition at line 2226 of file accesschk.c.

2238{
2239 PAGED_CODE();
2240
2241 /* Invoke the internal function to do the job */
2243 ClientToken,
2244 PrincipalSelfSid,
2247 PrivilegeSet,
2248 PrivilegeSetLength,
2249 ObjectTypeList,
2250 ObjectTypeListLength,
2251 FALSE,
2253 AccessStatus);
2254}

Referenced by AccessCheckByType(), AccessGrantedMultipleObjectsTests(), AccessGrantedNoDaclTests(), AccessGrantedTests(), DenyAccessTests(), and ParamsValidationTests().

◆ NtAccessCheckByTypeResultList()

NTSTATUS NTAPI NtAccessCheckByTypeResultList ( _In_ PSECURITY_DESCRIPTOR  SecurityDescriptor,
_In_opt_ PSID  PrincipalSelfSid,
_In_ HANDLE  ClientToken,
_In_ ACCESS_MASK  DesiredAccess,
_In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST  ObjectTypeList,
_In_ ULONG  ObjectTypeListLength,
_In_ PGENERIC_MAPPING  GenericMapping,
_Out_writes_bytes_ *PrivilegeSetLength PPRIVILEGE_SET  PrivilegeSet,
_Inout_ PULONG  PrivilegeSetLength,
_Out_writes_(ObjectTypeListLength) PACCESS_MASK  GrantedAccess,
_Out_writes_(ObjectTypeListLength) PNTSTATUS  AccessStatus 
)

Determines whether security access can be granted to a client that requests such access on the object type list. Unlike the NtAccessCheckByType variant, this function will grant or deny access to each individual object and sub-object in the list.

Remarks
For more documentation details about the parameters and overall function behavior, see SepAccessCheck.

Definition at line 2269 of file accesschk.c.

2281{
2282 PAGED_CODE();
2283
2284 /* Invoke the internal function to do the job */
2286 ClientToken,
2287 PrincipalSelfSid,
2290 PrivilegeSet,
2291 PrivilegeSetLength,
2292 ObjectTypeList,
2293 ObjectTypeListLength,
2294 TRUE,
2296 AccessStatus);
2297}
#define TRUE
Definition: types.h:120

Referenced by AccessCheckByTypeResultList(), DenyAccessTests(), GrantedAccessTests(), and ParamValidationNoObjsList().

◆ SeAccessCheck()

BOOLEAN NTAPI SeAccessCheck ( _In_ PSECURITY_DESCRIPTOR  SecurityDescriptor,
_In_ PSECURITY_SUBJECT_CONTEXT  SubjectSecurityContext,
_In_ BOOLEAN  SubjectContextLocked,
_In_ ACCESS_MASK  DesiredAccess,
_In_ ACCESS_MASK  PreviouslyGrantedAccess,
_Out_ PPRIVILEGE_SET Privileges,
_In_ PGENERIC_MAPPING  GenericMapping,
_In_ KPROCESSOR_MODE  AccessMode,
_Out_ PACCESS_MASK  GrantedAccess,
_Out_ PNTSTATUS  AccessStatus 
)

Determines whether security access rights can be given to an object depending on the security descriptor and other security context entities, such as an owner.

Parameters
[in]SecurityDescriptorSecurity descriptor of the object that is being accessed.
[in]SubjectSecurityContextThe captured subject security context.
[in]SubjectContextLockedIf set to TRUE, the caller acknowledges that the subject context has already been locked by the caller himself. If set to FALSE, the function locks the subject context.
[in]DesiredAccessAccess right bitmask that the calling thread wants to acquire.
[in]PreviouslyGrantedAccessThe access rights previously acquired in the past.
[out]PrivilegesThe returned set of privileges.
[in]GenericMappingThe generic mapping of access rights of an object type.
[in]AccessModeThe processor request level mode.
[out]GrantedAccessA list of granted access rights.
[out]AccessStatusThe returned status code specifying why access cannot be made onto an object (if said access is denied in the first place).
Returns
Returns TRUE if access onto the specific object is allowed, FALSE otherwise.

Definition at line 1966 of file accesschk.c.

1977{
1978 BOOLEAN ret;
1979
1980 PAGED_CODE();
1981
1982 /* Check if this is kernel mode */
1983 if (AccessMode == KernelMode)
1984 {
1985 /* Check if kernel wants everything */
1987 {
1988 /* Give it */
1990 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
1992 }
1993 else
1994 {
1995 /* Give the desired and previous access */
1997 }
1998
1999 /* Success */
2001 return TRUE;
2002 }
2003
2004 /* Check if we didn't get an SD */
2005 if (!SecurityDescriptor)
2006 {
2007 /* Automatic failure */
2009 return FALSE;
2010 }
2011
2012 /* Check for invalid impersonation */
2015 {
2017 return FALSE;
2018 }
2019
2020 /* Acquire the lock if needed */
2023
2024 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
2026 {
2029
2032 FALSE))
2033 {
2036 else
2038
2040 }
2041 }
2042
2043 if (DesiredAccess == 0)
2044 {
2046 if (PreviouslyGrantedAccess == 0)
2047 {
2048 DPRINT1("Request for zero access to an object. Denying.\n");
2050 ret = FALSE;
2051 }
2052 else
2053 {
2055 ret = TRUE;
2056 }
2057 }
2058 else
2059 {
2060 /* Call the internal function */
2064 NULL,
2066 NULL,
2067 0,
2070 AccessMode,
2071 FALSE,
2072 Privileges,
2074 AccessStatus);
2075 }
2076
2077 /* Release the lock if needed */
2080
2081 return ret;
2082}
unsigned char BOOLEAN
static BOOLEAN SepAccessCheckWorker(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_opt_ PACCESS_TOKEN ClientAccessToken, _In_ PACCESS_TOKEN PrimaryAccessToken, _In_opt_ PSID PrincipalSelfSid, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK PreviouslyGrantedAccess, _In_ PGENERIC_MAPPING GenericMapping, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN UseResultList, _Out_opt_ PPRIVILEGE_SET *Privileges, _Out_ PACCESS_MASK GrantedAccessList, _Out_ PNTSTATUS AccessStatusList)
Private worker function that determines whether security access rights can be givento the calling thr...
Definition: accesschk.c:942
#define DPRINT1
Definition: precomp.h:8
@ SecurityImpersonation
Definition: lsa.idl:57
#define KernelMode
Definition: asm.h:34
#define WRITE_DAC
Definition: nt_native.h:59
#define READ_CONTROL
Definition: nt_native.h:58
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
BOOLEAN NTAPI SepTokenIsOwner(_In_ PACCESS_TOKEN _Token, _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ BOOLEAN TokenLocked)
Checks if a token belongs to the main user, being the owner.
Definition: token.c:511
#define STATUS_BAD_IMPERSONATION_LEVEL
Definition: ntstatus.h:401
#define STATUS_SUCCESS
Definition: shellext.h:65
ACCESS_MASK GenericAll
Definition: nt_native.h:568
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: setypes.h:219
PACCESS_TOKEN ClientToken
Definition: setypes.h:218
PACCESS_TOKEN PrimaryToken
Definition: setypes.h:220
VOID NTAPI SeLockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Locks both the referenced primary and client access tokens of a security subject context.
Definition: subject.c:107
VOID NTAPI SeUnlockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Unlocks both the referenced primary and client access tokens of a security subject context.
Definition: subject.c:138
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
int ret
_In_ PEPROCESS _In_ KPROCESSOR_MODE AccessMode
Definition: mmfuncs.h:396
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET * Privileges
Definition: sefuncs.h:17
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN SubjectContextLocked
Definition: sefuncs.h:14
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK PreviouslyGrantedAccess
Definition: sefuncs.h:16
_In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
Definition: sefuncs.h:13

Referenced by create_stream(), FatExplicitDeviceAccessGranted(), file_create(), IopParseDevice(), NpCreateClientEnd(), NpCreateExistingNamedPipe(), ObCheckCreateObjectAccess(), ObCheckObjectAccess(), ObpCheckObjectReference(), ObpCheckTraverseAccess(), open_file2(), PspCreateProcess(), PspCreateThread(), PspSetPrimaryToken(), set_link_information(), set_rename_information(), START_TEST(), and UDFCheckAccessRights().

◆ SeFastTraverseCheck()

BOOLEAN NTAPI SeFastTraverseCheck ( _In_ PSECURITY_DESCRIPTOR  SecurityDescriptor,
_In_ PACCESS_STATE  AccessState,
_In_ ACCESS_MASK  DesiredAccess,
_In_ KPROCESSOR_MODE  AccessMode 
)

Determines whether security access rights can be given to an object depending on the security descriptor. Unlike the regular access check procedure in the NT kernel, the fast traverse check is a faster way to quickly check if access can be made into an object.

Parameters
[in]SecurityDescriptorSecurity descriptor of the object that is being accessed.
[in]AccessStateAn access state to determine if the access token in the current security context of the object is an restricted token.
[in]DesiredAccessThe access right bitmask where the calling thread wants to acquire.
[in]AccessModeProcess level request mode.
Returns
Returns TRUE if access onto the specific object is allowed, FALSE otherwise.

Definition at line 2110 of file accesschk.c.

2115{
2116 PACL Dacl;
2119
2120 PAGED_CODE();
2121
2123
2124 if (SecurityDescriptor == NULL)
2125 return FALSE;
2126
2127 /* Get DACL */
2129 /* If no DACL, grant access */
2130 if (Dacl == NULL)
2131 return TRUE;
2132
2133 /* No ACE -> Deny */
2134 if (!Dacl->AceCount)
2135 return FALSE;
2136
2137 /* Can't perform the check on restricted token */
2138 if (AccessState->Flags & TOKEN_IS_RESTRICTED)
2139 return FALSE;
2140
2141 /* Browse the ACEs */
2142 for (AceIndex = 0, Ace = (PKNOWN_ACE)((ULONG_PTR)Dacl + sizeof(ACL));
2143 AceIndex < Dacl->AceCount;
2144 AceIndex++, Ace = (PKNOWN_ACE)((ULONG_PTR)Ace + Ace->Header.AceSize))
2145 {
2146 if (Ace->Header.AceFlags & INHERIT_ONLY_ACE)
2147 continue;
2148
2149 /* If access-allowed ACE */
2150 if (Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
2151 {
2152 /* Check if all accesses are granted */
2153 if (!(Ace->Mask & DesiredAccess))
2154 continue;
2155
2156 /* Check SID and grant access if matching */
2157 if (RtlEqualSid(SeWorldSid, &(Ace->SidStart)))
2158 return TRUE;
2159 }
2160 /* If access-denied ACE */
2161 else if (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
2162 {
2163 /* Here, only check if it denies any access wanted and deny if so */
2164 if (Ace->Mask & DesiredAccess)
2165 return FALSE;
2166 }
2167 }
2168
2169 /* Faulty, deny */
2170 return FALSE;
2171}
@ Ace
Definition: card.h:12
#define ASSERT(a)
Definition: mode.c:44
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL Dacl
Definition: rtlfuncs.h:1593
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)
PSID SeWorldSid
Definition: sid.c:25
FORCEINLINE PACL SepGetDaclFromDescriptor(_Inout_ PSECURITY_DESCRIPTOR _Descriptor)
Definition: se.h:129
struct _KNOWN_ACE * PKNOWN_ACE
Definition: se.h:15
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
_In_ ULONG AceIndex
Definition: rtlfuncs.h:1862
_In_opt_ PVOID _In_opt_ PUNICODE_STRING _In_ PSECURITY_DESCRIPTOR _In_ PACCESS_STATE AccessState
Definition: sefuncs.h:417
#define INHERIT_ONLY_ACE
Definition: setypes.h:749
#define ACCESS_ALLOWED_ACE_TYPE
Definition: setypes.h:717
#define ACCESS_DENIED_ACE_TYPE
Definition: setypes.h:718
#define TOKEN_IS_RESTRICTED
Definition: setypes.h:1183

Referenced by IopParseDevice(), and ObpCheckTraverseAccess().

◆ SepAccessCheck()

static NTSTATUS SepAccessCheck ( _In_ PSECURITY_DESCRIPTOR  SecurityDescriptor,
_In_ HANDLE  ClientToken,
_In_opt_ PSID  PrincipalSelfSid,
_In_ ACCESS_MASK  DesiredAccess,
_In_ PGENERIC_MAPPING  GenericMapping,
_Out_writes_bytes_ *PrivilegeSetLength PPRIVILEGE_SET  PrivilegeSet,
_Inout_ PULONG  PrivilegeSetLength,
_In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST  ObjectTypeList,
_In_ ULONG  ObjectTypeListLength,
_In_ BOOLEAN  UseResultList,
_Out_ PACCESS_MASK  GrantedAccess,
_Out_ PNTSTATUS  AccessStatus 
)
static

Internal function that performs a security check against the client who requests access on a resource object. This function is used by access check NT system calls.

Parameters
[in]SecurityDescriptorA pointer to a security descriptor that identifies the security information of an object being accessed. This function walks through this descriptor for any ACLs and respective access rights if access can be granted.
[in]ClientTokenA handle to an access token, that identifies the client of which requests access to the target object.
[in]PrincipalSelfSidA pointer to a principal self SID. This parameter can be NULL if the associated object being checked for access does not represent a principal.
[in]DesiredAccessThe access right bitmask where the client wants to acquire. This can be an OR'ed set of multiple access rights or MAXIMUM_ALLOWED to request all of possible access rights the target object allows. If only some rights were granted but not all the access is deemed as denied.
[in]GenericMappingThe generic mapping of access rights of an object type.
[out]PrivilegeSetA pointer to a set of privileges that were used to perform the access check, returned to caller. This function will return no privileges (privilege count set to 0) if no privileges were used to accomplish the access check. This parameter must not be NULL!
[in,out]PrivilegeSetLengthThe total length size of a set of privileges. This length represents the count of elements in the privilege set array.
[in]ObjectTypeListA pointer to a given object type list. If this parameter is not NULL the function will perform an access check against the main object and sub-objects of this list. If this parameter is NULL and ObjectTypeListLength is 0, the function will perform a normal access check instead.
[in]ObjectTypeListLengthThe length of the object type list array, pointed by ObjectTypeList. This length in question represents the number of elements in such array. This parameter must be 0 if no array list is provided.
[in]UseResultListIf this parameter is set to TRUE, the function will return the GrantedAccess and AccessStatus parameter as arrays of granted rights and status value for each individual object element pointed by ObjectTypeList.
[out]GrantedAccessA pointer to granted access rights, returned to the caller. If ObjectTypeList is not NULL this paramater is an array of granted access rights for the object and each individual sub-object of the list.
[out]AccessStatusA pointer to a status code, returned to the caller. This status code represents whether access is granted or denied to the client on the target object. The difference between the status code of the function is that code indicates whether the function has successfully completed the access check operation. If ObjectTypeList is not NULL, this parameter is an array of access status for the object and each individual sub-object of the list.
Returns
Returns STATUS_SUCCESS if access check has been done without problems and that the object can be accessed. STATUS_GENERIC_NOT_MAPPED is returned if no generic access right is mapped. STATUS_NO_IMPERSONATION_TOKEN is returned if the token from the handle is not an impersonation token. STATUS_BAD_IMPERSONATION_LEVEL is returned if the token cannot be impersonated because the current security impersonation level doesn't permit so. STATUS_INVALID_SECURITY_DESCR is returned if the security descriptor given to the call is not a valid one. STATUS_BUFFER_TOO_SMALL is returned if the buffer to the captured privileges has a length that is less than the required size of the set of privileges. STATUS_INVALID_PARAMETER is returned if the caller did not provide an object type list but the caller wanted to invoke an object type result list access check, or if the list is out of order or the list is invalid. A failure NTSTATUS code is returned otherwise.
Remarks
The function performs an access check against the object type list, if provided, depending on the UseResultList parameter. That is, if that parameter was set to TRUE the function will either grant or deny access to each individual sub-object and return an array of access status and granted rights for the corresponding object type list. Otherwise the function will grant or deny access to the object type list hierarchy as a whole.

Definition at line 1564 of file accesschk.c.

1577{
1578 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
1579 POBJECT_TYPE_LIST_INTERNAL CapturedObjectTypeList = NULL;
1580 PSID CapturedPrincipalSelfSid = NULL;
1585 ULONG CapturedPrivilegeSetLength, RequiredPrivilegeSetLength;
1586 ULONG ResultListIndex;
1587 PTOKEN Token;
1589
1590 PAGED_CODE();
1591
1592 /* Check if this is kernel mode */
1593 if (PreviousMode == KernelMode)
1594 {
1595 /* Check if kernel wants everything */
1597 {
1598 /* Give it */
1600 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
1601 }
1602 else
1603 {
1604 /* Just give the desired access */
1606 }
1607
1608 /* Success */
1610 return STATUS_SUCCESS;
1611 }
1612
1613 /* Protect probe in SEH */
1614 _SEH2_TRY
1615 {
1616 /* Probe all pointers */
1618 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
1619 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
1620
1621 /*
1622 * Probe the access and status list based on the way
1623 * we are going to fill data in.
1624 */
1625 if (UseResultList)
1626 {
1627 /* Bail out on an empty list */
1628 if (!ObjectTypeListLength)
1629 {
1630 DPRINT1("The object type list is empty\n");
1632 }
1633
1634 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK) * ObjectTypeListLength, sizeof(ULONG));
1635 ProbeForWrite(AccessStatus, sizeof(NTSTATUS) * ObjectTypeListLength, sizeof(ULONG));
1636 }
1637 else
1638 {
1639 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
1640 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
1641 }
1642
1643 /* Capture the privilege set length and the mapping */
1644 CapturedPrivilegeSetLength = *PrivilegeSetLength;
1645 }
1647 {
1648 /* Return the exception code */
1650 }
1651 _SEH2_END;
1652
1653 /* Check for unmapped access rights */
1655 {
1656 DPRINT1("Some generic rights are not mapped\n");
1658 }
1659
1660 /* Reference the token */
1661 Status = ObReferenceObjectByHandle(ClientToken,
1665 (PVOID*)&Token,
1666 NULL);
1667 if (!NT_SUCCESS(Status))
1668 {
1669 DPRINT1("Failed to reference token (Status 0x%08lx)\n", Status);
1670 return Status;
1671 }
1672
1673 /* Check token type */
1674 if (Token->TokenType != TokenImpersonation)
1675 {
1676 DPRINT("No impersonation token\n");
1679 }
1680
1681 /* Check the impersonation level */
1682 if (Token->ImpersonationLevel < SecurityIdentification)
1683 {
1684 DPRINT1("Impersonation level < SecurityIdentification\n");
1687 }
1688
1689 /* Capture the object type list, the list is probed by the function itself */
1690 Status = SeCaptureObjectTypeList(ObjectTypeList,
1691 ObjectTypeListLength,
1693 &CapturedObjectTypeList);
1694 if (!NT_SUCCESS(Status))
1695 {
1696 DPRINT1("Failed to capture the object type list (Status 0x%08lx)\n", Status);
1698 return Status;
1699 }
1700
1701 /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
1704 NULL,
1705 Token,
1706 &Privileges,
1707 PreviousMode);
1708 if (!NT_SUCCESS(Status))
1709 {
1710 DPRINT1("SePrivilegePolicyCheck failed (Status 0x%08lx)\n", Status);
1711 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1713
1714 /*
1715 * The caller does not have the required access to do an access check.
1716 * Propagate the access and status for the whole hierarchy of the list
1717 * or just to single target object.
1718 */
1719 if (UseResultList)
1720 {
1721 for (ResultListIndex = 0; ResultListIndex < ObjectTypeListLength; ResultListIndex++)
1722 {
1723 AccessStatus[ResultListIndex] = Status;
1724 GrantedAccess[ResultListIndex] = 0;
1725 }
1726 }
1727 else
1728 {
1730 *GrantedAccess = 0;
1731 }
1732
1733 return STATUS_SUCCESS;
1734 }
1735
1736 /* Check the size of the privilege set and return the privileges */
1737 if (Privileges != NULL)
1738 {
1739 DPRINT("Privileges != NULL\n");
1740
1741 /* Calculate the required privilege set buffer size */
1742 RequiredPrivilegeSetLength = SepGetPrivilegeSetLength(Privileges);
1743
1744 /* Fail if the privilege set buffer is too small */
1745 if (CapturedPrivilegeSetLength < RequiredPrivilegeSetLength)
1746 {
1748 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1750 *PrivilegeSetLength = RequiredPrivilegeSetLength;
1752 }
1753
1754 /* Copy the privilege set to the caller */
1755 RtlCopyMemory(PrivilegeSet,
1756 Privileges,
1757 RequiredPrivilegeSetLength);
1758
1759 /* Free the local privilege set */
1761 }
1762 else
1763 {
1764 DPRINT("Privileges == NULL\n");
1765
1766 /* Fail if the privilege set buffer is too small */
1767 if (CapturedPrivilegeSetLength < sizeof(PRIVILEGE_SET))
1768 {
1769 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1771 *PrivilegeSetLength = sizeof(PRIVILEGE_SET);
1773 }
1774
1775 /* Initialize the privilege set */
1776 PrivilegeSet->PrivilegeCount = 0;
1777 PrivilegeSet->Control = 0;
1778 }
1779
1780 /* Capture the security descriptor */
1783 PagedPool,
1784 FALSE,
1785 &CapturedSecurityDescriptor);
1786 if (!NT_SUCCESS(Status))
1787 {
1788 DPRINT1("Failed to capture the Security Descriptor\n");
1789 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1791 return Status;
1792 }
1793
1794 /* Check the captured security descriptor */
1795 if (CapturedSecurityDescriptor == NULL)
1796 {
1797 DPRINT1("Security Descriptor is NULL\n");
1798 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1801 }
1802
1803 /* Check security descriptor for valid owner and group */
1804 if (SepGetOwnerFromDescriptor(CapturedSecurityDescriptor) == NULL ||
1805 SepGetGroupFromDescriptor(CapturedSecurityDescriptor) == NULL)
1806 {
1807 DPRINT1("Security Descriptor does not have a valid group or owner\n");
1808 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1810 FALSE);
1811 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1814 }
1815
1816 /* Capture the principal self SID if we have one */
1817 if (PrincipalSelfSid)
1818 {
1819 Status = SepCaptureSid(PrincipalSelfSid,
1821 PagedPool,
1822 TRUE,
1823 &CapturedPrincipalSelfSid);
1824 if (!NT_SUCCESS(Status))
1825 {
1826 DPRINT1("Failed to capture the principal self SID (Status 0x%08lx)\n", Status);
1827 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1829 FALSE);
1830 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1832 return Status;
1833 }
1834 }
1835
1836 /* Set up the subject context, and lock it */
1838
1839 /* Lock the token */
1841
1842 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
1844 {
1845 if (SepTokenIsOwner(Token, CapturedSecurityDescriptor, FALSE))
1846 {
1849 else
1851
1853 }
1854 }
1855
1856 if (DesiredAccess == 0)
1857 {
1858 /*
1859 * Propagate the access and status for the whole hierarchy
1860 * of the list or just to single target object.
1861 */
1862 if (UseResultList)
1863 {
1864 for (ResultListIndex = 0; ResultListIndex < ObjectTypeListLength; ResultListIndex++)
1865 {
1866 AccessStatus[ResultListIndex] = STATUS_SUCCESS;
1867 GrantedAccess[ResultListIndex] = PreviouslyGrantedAccess;
1868 }
1869 }
1870 else
1871 {
1874 }
1875 }
1876 else
1877 {
1878 /* Now perform the access check */
1879 SepAccessCheckWorker(CapturedSecurityDescriptor,
1880 Token,
1882 CapturedPrincipalSelfSid,
1884 CapturedObjectTypeList,
1885 ObjectTypeListLength,
1889 UseResultList,
1890 NULL,
1892 AccessStatus);
1893 }
1894
1895 /* Release subject context and unlock the token */
1898
1899 /* Release the caputed principal self SID */
1900 SepReleaseSid(CapturedPrincipalSelfSid,
1902 TRUE);
1903
1904 /* Release the captured security descriptor */
1905 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1907 FALSE);
1908
1909 /* Release the object type list */
1910 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1911
1912 /* Dereference the token */
1914
1915 /* Check succeeded */
1916 return STATUS_SUCCESS;
1917}
static ULONG SepGetPrivilegeSetLength(_In_ PPRIVILEGE_SET PrivilegeSet)
Retrieves the length size of a set list of privileges structure.
Definition: accesschk.c:1454
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define GENERIC_READ
Definition: compat.h:135
#define PagedPool
Definition: env_spec_w32.h:308
#define ExGetPreviousMode
Definition: ex.h:140
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
@ SecurityIdentification
Definition: lsa.idl:56
@ TokenImpersonation
Definition: imports.h:274
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define GENERIC_ALL
Definition: nt_native.h:92
#define GENERIC_WRITE
Definition: nt_native.h:90
#define GENERIC_EXECUTE
Definition: nt_native.h:91
VOID NTAPI SepReleaseSid(_In_ PSID CapturedSid, _In_ KPROCESSOR_MODE AccessMode, _In_ BOOLEAN CaptureIfKernel)
Releases a captured SID.
Definition: sid.c:400
NTSTATUS NTAPI SepCaptureSid(_In_ PSID InputSid, _In_ KPROCESSOR_MODE AccessMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSID *CapturedSid)
Captures a SID.
Definition: sid.c:314
VOID SeReleaseObjectTypeList(_In_ _Post_invalid_ POBJECT_TYPE_LIST_INTERNAL CapturedObjectTypeList, _In_ KPROCESSOR_MODE PreviousMode)
Releases a buffer list of object types.
Definition: objtype.c:378
NTSTATUS SeCaptureObjectTypeList(_In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ KPROCESSOR_MODE PreviousMode, _Out_ POBJECT_TYPE_LIST_INTERNAL *CapturedObjectTypeList)
Captures a list of object types and converts it to an internal form for use by the kernel....
Definition: objtype.c:282
FORCEINLINE PSID SepGetOwnerFromDescriptor(_Inout_ PSECURITY_DESCRIPTOR _Descriptor)
Definition: se.h:109
#define SepAcquireTokenLockShared(Token)
Definition: se.h:290
NTSTATUS NTAPI SePrivilegePolicyCheck(_Inout_ PACCESS_MASK DesiredAccess, _Inout_ PACCESS_MASK GrantedAccess, _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, _In_ PTOKEN Token, _Out_opt_ PPRIVILEGE_SET *OutPrivilegeSet, _In_ KPROCESSOR_MODE PreviousMode)
Checks the security policy and returns a set of privileges based upon the said security policy contex...
Definition: priv.c:244
FORCEINLINE PSID SepGetGroupFromDescriptor(_Inout_ PSECURITY_DESCRIPTOR _Descriptor)
Definition: se.h:89
#define SepReleaseTokenLock(Token)
Definition: se.h:296
VOID NTAPI SeFreePrivileges(_In_ PPRIVILEGE_SET Privileges)
Frees a set of privileges.
Definition: priv.c:669
NTSTATUS NTAPI SeCaptureSecurityDescriptor(_In_ PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor, _In_ KPROCESSOR_MODE CurrentMode, _In_ POOL_TYPE PoolType, _In_ BOOLEAN CaptureIfKernel, _Out_ PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor)
Captures a security descriptor.
Definition: sd.c:386
NTSTATUS NTAPI SeReleaseSecurityDescriptor(_In_ PSECURITY_DESCRIPTOR CapturedSecurityDescriptor, _In_ KPROCESSOR_MODE CurrentMode, _In_ BOOLEAN CaptureIfKernelMode)
Releases a captured security descriptor buffer.
Definition: sd.c:760
POBJECT_TYPE SeTokenObjectType
Definition: token.c:17
#define STATUS_NO_IMPERSONATION_TOKEN
Definition: ntstatus.h:328
#define STATUS_INVALID_SECURITY_DESCR
Definition: ntstatus.h:357
#define STATUS_GENERIC_NOT_MAPPED
Definition: ntstatus.h:466
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:71
VOID NTAPI SeReleaseSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Releases both the primary and client tokens of a security subject context.
Definition: subject.c:171
VOID NTAPI SeCaptureSubjectContext(_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Captures the security subject context of the calling thread and calling process.
Definition: subject.c:85
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define TOKEN_QUERY
Definition: setypes.h:928
struct _PRIVILEGE_SET PRIVILEGE_SET

Referenced by NtAccessCheck(), NtAccessCheckByType(), and NtAccessCheckByTypeResultList().

◆ SepAccessCheckWorker()

static BOOLEAN SepAccessCheckWorker ( _In_ PSECURITY_DESCRIPTOR  SecurityDescriptor,
_In_opt_ PACCESS_TOKEN  ClientAccessToken,
_In_ PACCESS_TOKEN  PrimaryAccessToken,
_In_opt_ PSID  PrincipalSelfSid,
_In_ ACCESS_MASK  DesiredAccess,
_In_opt_ POBJECT_TYPE_LIST_INTERNAL  ObjectTypeList,
_In_ ULONG  ObjectTypeListLength,
_In_ ACCESS_MASK  PreviouslyGrantedAccess,
_In_ PGENERIC_MAPPING  GenericMapping,
_In_ KPROCESSOR_MODE  AccessMode,
_In_ BOOLEAN  UseResultList,
_Out_opt_ PPRIVILEGE_SET Privileges,
_Out_ PACCESS_MASK  GrantedAccessList,
_Out_ PNTSTATUS  AccessStatusList 
)
static

Private worker function that determines whether security access rights can be givento the calling thread in order to access an object depending on the security descriptor and other security context entities, such as an owner. This function is the heart and brain of the whole access check algorithm in the kernel.

Parameters
[in]ClientAccessTokenA pointer to a client (thread) access token that requests access rights of an object or subset of multiple objects.
[in]PrimaryAccessTokenA pointer to a primary access token that describes the primary security context of the main calling process.
[in]PrincipalSelfSidA pointer to a security identifier that represents a security principal, that is, a user object associated with its security descriptor.
[in]DesiredAccessThe access rights desired by the calling thread to acquire in order to access an object.
[in]ObjectTypeListAn array list of object types to be checked against for access. The function will act accordingly in this case by checking each sub-object of an object of primary level and such. If this parameter is NULL, the function will perform a normal access check against the target object itself.
[in]ObjectTypeListLengthThe length of a object type list. Such length represents the number of elements in this list.
[in]PreviouslyGrantedAccessThe access rights previously acquired in the past. If this parameter is 0, it is deemed that the calling thread hasn't acquired any rights. Access checks are more tighten in this case.
[in]GenericMappingA pointer to a generic mapping of access rights of the target object.
[in]AccessModeThe processor request level mode.
[in]UseResultListIf set to TRUE, the function will return a list of granted access rights of each sub-object as well as status code for each. If this parameter is set to FALSE, then the function will just return only the granted access rights and status code for single object that's been target for access checks.
[out]PrivilegesA pointer to a definite set of privileges that have been audited whilst doing access check procedures. Such set of privileges are optionally returned to the caller. This can be set to NULL if the caller doesn't want to obtain a set of privileges.
[out]GrantedAccessListA list of granted access rights returned to the caller. This list can comprehend multiple elements which represent the sub-objects that have been checked or a single element which is the target object itself.
[out]AccessStatusListA list of access status codes returned to the caller. This list can comprehend multiple elements which represent the sub-objects that have been checked or a single element which is the target object itself.
Returns
Returns TRUE if access onto the specific object is allowed, FALSE otherwise.

Definition at line 942 of file accesschk.c.

957{
958 ACCESS_MASK RemainingAccess;
959 ACCESS_MASK WantedRights;
960 ACCESS_MASK MaskDesired;
961 ACCESS_MASK GrantedRights = 0;
962 ULONG ResultListIndex;
963 ULONG ObjectTypeIndex;
964 PACL Dacl;
965 BOOLEAN Present;
966 BOOLEAN Defaulted;
968 BOOLEAN AccessIsGranted = FALSE;
970 ACCESS_CHECK_RIGHTS AccessCheckRights = {0};
971
972 PAGED_CODE();
973
974 /* A security descriptor must be expected for access checks */
976
977 /* Check for no access desired */
978 if (!DesiredAccess)
979 {
980 /* Check if we had no previous access */
982 {
983 /* Then there's nothing to give */
984 DPRINT1("The caller has no previously granted access gained!\n");
986 goto ReturnCommonStatus;
987 }
988
989 /* Return the previous access only */
991 *Privileges = NULL;
992 goto ReturnCommonStatus;
993 }
994
995 /* Map given accesses */
999
1000 /* Initialize remaining access rights */
1001 RemainingAccess = DesiredAccess;
1002
1003 /*
1004 * Initialize the required rights if the caller wants to know access
1005 * for the object and each sub-object in the list.
1006 */
1007 if (UseResultList)
1008 {
1010 {
1012 MaskDesired = ~MAXIMUM_ALLOWED;
1013 }
1014 else
1015 {
1016 WantedRights = MaskDesired = DesiredAccess | PreviouslyGrantedAccess;
1017 }
1018 }
1019
1020 /*
1021 * Obtain the token provided by the caller. Client (or also
1022 * called impersonation or thread) token takes precedence over
1023 * the primary token which is the token associated with the security
1024 * context of the main calling process. This is because it is the
1025 * client itself that requests access of an object or subset of
1026 * multiple objects. Otherwise obtain the security context of the
1027 * main process (the actual primary token).
1028 */
1029 Token = ClientAccessToken ? ClientAccessToken : PrimaryAccessToken;
1030
1031 /*
1032 * We should at least expect a primary token
1033 * to be present if client token is not
1034 * available.
1035 */
1036 ASSERT(Token);
1037
1038 /*
1039 * Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access.
1040 * Write down a set of privileges that have been checked
1041 * if the caller wants it.
1042 */
1043 Status = SePrivilegePolicyCheck(&RemainingAccess,
1045 NULL,
1046 Token,
1047 Privileges,
1048 AccessMode);
1049 if (!NT_SUCCESS(Status))
1050 {
1051 goto ReturnCommonStatus;
1052 }
1053
1054 /* Succeed if there are no more rights to grant */
1055 if (RemainingAccess == 0)
1056 {
1058 goto ReturnCommonStatus;
1059 }
1060
1061 /* Get the DACL */
1063 &Present,
1064 &Dacl,
1065 &Defaulted);
1066 if (!NT_SUCCESS(Status))
1067 {
1068 goto ReturnCommonStatus;
1069 }
1070
1071 /* Grant desired access if the object is unprotected */
1072 if (Present == FALSE || Dacl == NULL)
1073 {
1074 PreviouslyGrantedAccess |= RemainingAccess;
1075 if (RemainingAccess & MAXIMUM_ALLOWED)
1076 {
1077 PreviouslyGrantedAccess &= ~MAXIMUM_ALLOWED;
1079 }
1080
1082 goto ReturnCommonStatus;
1083 }
1084
1085 /* Deny access if the DACL is empty */
1086 if (Dacl->AceCount == 0)
1087 {
1088 if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0)
1089 {
1091 }
1092 else
1093 {
1094 DPRINT1("The DACL has no ACEs and the caller has no previously granted access!\n");
1097 }
1098 goto ReturnCommonStatus;
1099 }
1100
1101 /*
1102 * Determine the MAXIMUM_ALLOWED access rights according to the DACL.
1103 * Or if the caller is supplying a list of object types then determine
1104 * the rights of each object on that list.
1105 */
1106 if ((DesiredAccess & MAXIMUM_ALLOWED) || UseResultList)
1107 {
1108 /* Perform access checks against ACEs from this DACL */
1110 0,
1111 Dacl,
1112 Token,
1113 PrimaryAccessToken,
1114 FALSE,
1115 PrincipalSelfSid,
1117 ObjectTypeList,
1118 ObjectTypeListLength,
1119 UseResultList,
1120 &AccessCheckRights);
1121
1122 /*
1123 * Perform further access checks if this token
1124 * has restricted SIDs.
1125 */
1127 {
1129 0,
1130 Dacl,
1131 Token,
1132 PrimaryAccessToken,
1133 TRUE,
1134 PrincipalSelfSid,
1136 ObjectTypeList,
1137 ObjectTypeListLength,
1138 UseResultList,
1139 &AccessCheckRights);
1140 }
1141
1142 /* The caller did not provide an object type list, check access only for that object */
1143 if (!ObjectTypeList && !ObjectTypeListLength)
1144 {
1145 /* Fail if some rights have not been granted */
1146 RemainingAccess &= ~(MAXIMUM_ALLOWED | AccessCheckRights.GrantedAccessRights);
1147 if (RemainingAccess != 0)
1148 {
1149 DPRINT1("Failed to grant access rights. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", RemainingAccess, DesiredAccess);
1152 goto ReturnCommonStatus;
1153 }
1154
1155 /* Set granted access right and access status */
1156 PreviouslyGrantedAccess |= AccessCheckRights.GrantedAccessRights;
1157 if (PreviouslyGrantedAccess != 0)
1158 {
1160 }
1161 else
1162 {
1163 DPRINT1("Failed to grant access rights. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess);
1165 }
1166
1167 /* We are done here */
1168 goto ReturnCommonStatus;
1169 }
1170 else if (!UseResultList)
1171 {
1172 /*
1173 * We have a list but the caller wants to know if access can be granted
1174 * to an object in the list. Access will either be granted or denied
1175 * to the whole hierarchy of the list. Look for every object in the list
1176 * that has granted access rights and collect them.
1177 */
1178 for (ObjectTypeIndex = 0;
1179 ObjectTypeIndex < ObjectTypeListLength;
1180 ObjectTypeIndex++)
1181 {
1182 if (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights != 0)
1183 {
1184 GrantedRights |= ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights;
1185 }
1186 }
1187
1188 /* Now check if acccess can be granted */
1189 RemainingAccess &= ~(MAXIMUM_ALLOWED | GrantedRights);
1190 if (RemainingAccess != 0)
1191 {
1192 DPRINT1("Failed to grant access rights to the whole object hierarchy list. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n",
1193 RemainingAccess, DesiredAccess);
1196 goto ReturnCommonStatus;
1197 }
1198
1199 /* Set granted access right and access status */
1200 PreviouslyGrantedAccess |= GrantedRights;
1201 if (PreviouslyGrantedAccess != 0)
1202 {
1204 }
1205 else
1206 {
1207 DPRINT1("Failed to grant access rights to the whole object hierarchy list. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n",
1210 }
1211
1212 /* We are done here */
1213 goto ReturnCommonStatus;
1214 }
1215 else
1216 {
1217 /*
1218 * We have a list and the caller wants to know access for each
1219 * sub-object in the list. Report the access status and granted
1220 * rights for the object and each sub-object in the list.
1221 */
1222 for (ObjectTypeIndex = 0;
1223 ObjectTypeIndex < ObjectTypeListLength;
1224 ObjectTypeIndex++)
1225 {
1226 /* Check if we have some rights */
1227 GrantedRights = (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights | PreviouslyGrantedAccess) & MaskDesired;
1228 if (GrantedRights != 0)
1229 {
1230 /*
1231 * If we still have some remaining rights to grant the ultimate
1232 * conclusion is that the caller has no access to the object itself.
1233 */
1234 RemainingAccess = (~GrantedRights & WantedRights);
1235 if (RemainingAccess != 0)
1236 {
1237 DPRINT1("Failed to grant access rights at specific object at index %lu. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n",
1238 ObjectTypeIndex, RemainingAccess, DesiredAccess);
1239 AccessStatusList[ObjectTypeIndex] = STATUS_ACCESS_DENIED;
1240 }
1241 else
1242 {
1243 AccessStatusList[ObjectTypeIndex] = STATUS_SUCCESS;
1244 }
1245 }
1246 else
1247 {
1248 /* No access is given */
1249 DPRINT1("Failed to grant access rights at specific object at index %lu. No access is given\n", ObjectTypeIndex);
1250 AccessStatusList[ObjectTypeIndex] = STATUS_ACCESS_DENIED;
1251 }
1252
1253 /* Return the access rights to the caller */
1254 GrantedAccessList[ObjectTypeIndex] = GrantedRights;
1255 }
1256
1257 /*
1258 * We have built a list of access statuses for each object but
1259 * we still need to figure out the common status for the
1260 * function. The same status code will be used to check if
1261 * we should report any security debug stuff once we are done.
1262 */
1264 for (ResultListIndex = 0; ResultListIndex < ObjectTypeListLength; ResultListIndex++)
1265 {
1266 /* There is at least one sub-object of which access cannot be granted */
1267 if (AccessStatusList[ResultListIndex] == STATUS_ACCESS_DENIED)
1268 {
1269 Status = AccessStatusList[ResultListIndex];
1270 break;
1271 }
1272 }
1273
1274 /* We are done here */
1275 goto ReturnCommonStatus;
1276 }
1277 }
1278
1279 /* Grant rights according to the DACL */
1281 RemainingAccess,
1282 Dacl,
1283 Token,
1284 PrimaryAccessToken,
1285 FALSE,
1286 PrincipalSelfSid,
1288 ObjectTypeList,
1289 ObjectTypeListLength,
1290 UseResultList,
1291 &AccessCheckRights);
1292
1293 /* The caller did not provide an object type list, check access only for that object */
1294 if (!ObjectTypeList && !ObjectTypeListLength)
1295 {
1296 /* Fail if some rights have not been granted */
1297 if (AccessCheckRights.RemainingAccessRights != 0)
1298 {
1299 DPRINT1("Failed to grant access rights. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", AccessCheckRights.RemainingAccessRights, DesiredAccess);
1302 goto ReturnCommonStatus;
1303 }
1304 }
1305 else
1306 {
1307 /*
1308 * We have an object type list, look for the object of which
1309 * remaining rights are all granted.
1310 */
1311 for (ObjectTypeIndex = 0;
1312 ObjectTypeIndex < ObjectTypeListLength;
1313 ObjectTypeIndex++)
1314 {
1315 if (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.RemainingAccessRights == 0)
1316 {
1317 AccessIsGranted = TRUE;
1318 break;
1319 }
1320 }
1321
1322 if (!AccessIsGranted)
1323 {
1324 DPRINT1("Failed to grant access rights to the whole object hierarchy list. DesiredAccess = 0x%08lx\n", DesiredAccess);
1327 goto ReturnCommonStatus;
1328 }
1329 }
1330
1331 /*
1332 * Perform further access checks if this token
1333 * has restricted SIDs.
1334 */
1336 {
1338 RemainingAccess,
1339 Dacl,
1340 Token,
1341 PrimaryAccessToken,
1342 TRUE,
1343 PrincipalSelfSid,
1345 ObjectTypeList,
1346 ObjectTypeListLength,
1347 UseResultList,
1348 &AccessCheckRights);
1349
1350 /* The caller did not provide an object type list, check access only for that object */
1351 if (!ObjectTypeList && !ObjectTypeListLength)
1352 {
1353 /* Fail if some rights have not been granted */
1354 if (AccessCheckRights.RemainingAccessRights != 0)
1355 {
1356 DPRINT1("Failed to grant access rights. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", AccessCheckRights.RemainingAccessRights, DesiredAccess);
1359 goto ReturnCommonStatus;
1360 }
1361 }
1362 else
1363 {
1364 /*
1365 * We have an object type list, look for the object of which remaining
1366 * rights are all granted. The user may have access to the requested
1367 * object but on a restricted token case the user is only granted partial
1368 * access. If access is denied to restricted SIDs, the bottom line is that
1369 * access is denied to the user.
1370 */
1371 AccessIsGranted = FALSE;
1372 for (ObjectTypeIndex = 0;
1373 ObjectTypeIndex < ObjectTypeListLength;
1374 ObjectTypeIndex++)
1375 {
1376 if (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.RemainingAccessRights == 0)
1377 {
1378 AccessIsGranted = TRUE;
1379 break;
1380 }
1381 }
1382
1383 if (!AccessIsGranted)
1384 {
1385 DPRINT1("Failed to grant access rights to the whole object hierarchy list. DesiredAccess = 0x%08lx\n", DesiredAccess);
1388 goto ReturnCommonStatus;
1389 }
1390 }
1391 }
1392
1393 /* Set granted access rights */
1395
1396 /* Fail if no rights have been granted */
1397 if (PreviouslyGrantedAccess == 0)
1398 {
1399 DPRINT1("Failed to grant access rights. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess);
1401 goto ReturnCommonStatus;
1402 }
1403
1404 /*
1405 * If we're here then we granted all the desired
1406 * access rights the caller wanted.
1407 */
1409
1410ReturnCommonStatus:
1411 if (!UseResultList)
1412 {
1413 *GrantedAccessList = PreviouslyGrantedAccess;
1414 *AccessStatusList = Status;
1415 }
1416
1417#if DBG
1418 /* Dump security debug info on access denied case */
1420 {
1423
1424 if (ObjectTypeList && (ObjectTypeListLength != 0))
1425 {
1426 SepDumpAccessAndStatusList(GrantedAccessList,
1427 AccessStatusList,
1428 UseResultList,
1429 ObjectTypeList,
1430 ObjectTypeListLength);
1431 }
1432 else
1433 {
1434 SepDumpAccessRightsStats(&AccessCheckRights);
1435 }
1436 }
1437#endif
1438
1439 return NT_SUCCESS(Status);
1440}
static VOID SepAnalyzeAcesFromDacl(_In_ ACCESS_CHECK_RIGHT_TYPE ActionType, _In_ ACCESS_MASK RemainingAccess, _In_ PACL Dacl, _In_ PACCESS_TOKEN AccessToken, _In_ PACCESS_TOKEN PrimaryAccessToken, _In_ BOOLEAN IsTokenRestricted, _In_opt_ PSID PrincipalSelfSid, _In_ PGENERIC_MAPPING GenericMapping, _In_opt_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ BOOLEAN UseResultList, _Inout_ PACCESS_CHECK_RIGHTS AccessCheckRights)
Analyzes an access control entry that is present in a discretionary access control list (DACL) for ac...
Definition: accesschk.c:460
NTSYSAPI VOID NTAPI RtlMapGenericMask(PACCESS_MASK AccessMask, PGENERIC_MAPPING GenericMapping)
NTSYSAPI NTSTATUS NTAPI RtlGetDaclSecurityDescriptor(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _Out_ PBOOLEAN DaclPresent, _Out_ PACL *Dacl, _Out_ PBOOLEAN DaclDefaulted)
@ AccessCheckMaximum
Definition: se.h:60
@ AccessCheckRegular
Definition: se.h:61
VOID SepDumpTokenDebugInfo(_In_opt_ PTOKEN Token)
Dumps debug information of an access token to the debugger.
Definition: debug.c:280
VOID SepDumpAccessAndStatusList(_In_ PACCESS_MASK GrantedAccessList, _In_ PNTSTATUS AccessStatusList, _In_ BOOLEAN IsResultList, _In_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength)
Dumps access and status values of each object type in the result list.
Definition: debug.c:353
VOID SepDumpAccessRightsStats(_In_ PACCESS_CHECK_RIGHTS AccessRights)
Dumps security access rights to the debugger.
Definition: debug.c:325
VOID SepDumpSdDebugInfo(_In_opt_ PISECURITY_DESCRIPTOR SecurityDescriptor)
Dumps debug information of a security descriptor to the debugger.
Definition: debug.c:217
BOOLEAN NTAPI SeTokenIsRestricted(_In_ PACCESS_TOKEN Token)
Determines if a token is restricted or not, based upon the token flags.
Definition: token.c:2124
ACCESS_MASK RemainingAccessRights
Definition: se.h:43
ACCESS_MASK GrantedAccessRights
Definition: se.h:44

Referenced by SeAccessCheck(), and SepAccessCheck().

◆ SepAllowAccessObjectTypeList()

static VOID SepAllowAccessObjectTypeList ( _Inout_ POBJECT_TYPE_LIST_INTERNAL  ObjectTypeList,
_In_ ULONG  ObjectTypeListLength,
_In_ ACCESS_MASK  AccessMask,
_In_ BOOLEAN  RemoveRemainingRights,
_In_opt_ PGUID  ObjectTypeGuid 
)
static

Allows access of a target object in the object type list. This access is allowed for the whole hierarchy in the list.

Parameters
[in,out]ObjectTypeListA pointer to an object type list where access is to be allowed for the target object. This operation applies for the entire hierarchy of the object type list.
[in]ObjectTypeListLengthThe length of the object type list. This length represents the number of object elements in the list.
[in]AccessMaskThe access mask right that is to be allowed for the object.
[in]RemoveRemainingRightsIf set to TRUE, the function will remove the remaining rights of a target object. It will also grant access of the said object. Otherwise if set to FALSE, the function will only grant access.
[in]ObjectTypeGuidA pointer to a object type GUID, that identifies the object. This GUID is used to search for the target object in the list. If this parameter is set to NULL, the function will allow access to the object itself in the list (aka the root).

Definition at line 324 of file accesschk.c.

330{
331 ULONG ReturnedObjectIndex;
332
333 PAGED_CODE();
334
335 DPRINT("Access rights 0x%08lx\n", AccessMask);
336
337 /*
338 * If no object type was supplied then remove the remaining rights
339 * of the object itself, the root. Track down that right to the
340 * granted rights as well.
341 */
342 if (!ObjectTypeGuid)
343 {
344 if (RemoveRemainingRights)
345 {
346 ObjectTypeList[0].ObjectAccessRights.RemainingAccessRights &= ~AccessMask;
347 DPRINT("Remaining rights of root object 0x%08lx\n", ObjectTypeList[0].ObjectAccessRights.RemainingAccessRights);
348 }
349
350 ObjectTypeList[0].ObjectAccessRights.GrantedAccessRights |=
351 (AccessMask & ~ObjectTypeList[0].ObjectAccessRights.DeniedAccessRights);
352 DPRINT("Granted rights of root object 0x%08lx\n", ObjectTypeList[0].ObjectAccessRights.GrantedAccessRights);
353 return;
354 }
355
356 /*
357 * Grant access to the object if it exists by removing the remaining
358 * rights. Unlike the NtAccessCheckByTypeResultList variant we do not
359 * care about the children of the target object beccause NtAccessCheckByType
360 * will either grant or deny access to the entire hierarchy of the list.
361 */
362 if (SepObjectTypeGuidInList(ObjectTypeList,
363 ObjectTypeListLength,
364 ObjectTypeGuid,
365 &ReturnedObjectIndex))
366 {
367 /* Remove the remaining rights of that object */
368 if (RemoveRemainingRights)
369 {
370 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.RemainingAccessRights &= ~AccessMask;
371 DPRINT("Remaining rights of object 0x%08lx at index %lu\n",
372 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.RemainingAccessRights, ReturnedObjectIndex);
373 }
374
375 /* And track it down to the granted access rights */
376 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights |=
377 (AccessMask & ~ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights);
378 DPRINT("Granted rights of object 0x%08lx at index %lu\n",
379 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights, ReturnedObjectIndex);
380 }
381}
_In_ ACCESS_MASK AccessMask
Definition: exfuncs.h:186
BOOLEAN SepObjectTypeGuidInList(_In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ PGUID ObjectTypeGuid, _Out_ PULONG ObjectIndex)
Searches for an object type GUID if it exists on an object type list.
Definition: objtype.c:223

Referenced by SepAnalyzeAcesFromDacl().

◆ SepAllowAccessObjectTypeResultList()

static VOID SepAllowAccessObjectTypeResultList ( _Inout_ POBJECT_TYPE_LIST_INTERNAL  ObjectTypeList,
_In_ ULONG  ObjectTypeListLength,
_In_ ACCESS_MASK  AccessMask,
_In_opt_ PGUID  ObjectTypeGuid 
)
static

Allows access of a target object and the children objects in an object type list.

Parameters
[in,out]ObjectTypeListA pointer to an object type list where access is to be allowed for the target object and its children in the hierarchy list.
[in]ObjectTypeListLengthThe length of the object type list. This length represents the number of object elements in the list.
[in]AccessMaskThe access mask right that is to be allowed for the object.
[in]ObjectTypeGuidA pointer to a object type GUID, that identifies the object. This GUID is used to search for the target object in the list. If this parameter is set to NULL, the function will allow access starting from the object itself in the list (aka the root).

Definition at line 135 of file accesschk.c.

140{
141 ULONG ObjectTypeIndex;
142 ULONG ReturnedObjectIndex;
144
145 PAGED_CODE();
146
147 DPRINT("Access rights 0x%08lx\n", AccessMask);
148
149 /*
150 * Begin updating the access rights from the root object
151 * (see comment in SepDenyAccessObjectTypeListMaximum).
152 */
153 if (!ObjectTypeGuid)
154 {
155 DPRINT("No object type provided, updating access rights from root\n");
156 ReturnedObjectIndex = 0;
157 goto LoopAndUpdateRightsObjects;
158 }
159
160 /* Check if that object exists in the list */
161 if (SepObjectTypeGuidInList(ObjectTypeList,
162 ObjectTypeListLength,
163 ObjectTypeGuid,
164 &ReturnedObjectIndex))
165 {
166LoopAndUpdateRightsObjects:
167 /* Update the access rights of the target object */
168 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights |=
169 (AccessMask & ~ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights);
170 DPRINT("Granted rights 0x%08lx of target object at index %lu\n",
171 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights, ReturnedObjectIndex);
172
173 /* And update the children of the target object */
174 for (ObjectTypeIndex = ReturnedObjectIndex + 1;
175 ObjectTypeIndex < ObjectTypeListLength;
176 ObjectTypeIndex++)
177 {
178 /*
179 * Stop looking for children objects if we hit an object that has
180 * the same level as the target object or less.
181 */
182 Level = ObjectTypeList[ObjectTypeIndex].Level;
183 if (Level <= ObjectTypeList[ReturnedObjectIndex].Level)
184 {
185 break;
186 }
187
188 /* Update the access right of the child */
189 ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights |=
190 (AccessMask & ~ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.DeniedAccessRights);
191 DPRINT("Granted rights 0x%08lx of child object at index %lu\n",
192 ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights, ObjectTypeIndex);
193 }
194 }
195}
unsigned short USHORT
Definition: pedump.c:61
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56

Referenced by SepAnalyzeAcesFromDacl().

◆ SepAnalyzeAcesFromDacl()

static VOID SepAnalyzeAcesFromDacl ( _In_ ACCESS_CHECK_RIGHT_TYPE  ActionType,
_In_ ACCESS_MASK  RemainingAccess,
_In_ PACL  Dacl,
_In_ PACCESS_TOKEN  AccessToken,
_In_ PACCESS_TOKEN  PrimaryAccessToken,
_In_ BOOLEAN  IsTokenRestricted,
_In_opt_ PSID  PrincipalSelfSid,
_In_ PGENERIC_MAPPING  GenericMapping,
_In_opt_ POBJECT_TYPE_LIST_INTERNAL  ObjectTypeList,
_In_ ULONG  ObjectTypeListLength,
_In_ BOOLEAN  UseResultList,
_Inout_ PACCESS_CHECK_RIGHTS  AccessCheckRights 
)
static

Analyzes an access control entry that is present in a discretionary access control list (DACL) for access right masks of each entry with the purpose to judge whether the calling thread can be warranted access check to a certain object or not.

Parameters
[in]ActionTypeThe type of analysis to be done against an access entry. This type influences how access rights are gathered. This can either be AccessCheckMaximum which means the algorithm will perform analysis against ACEs on behalf of the requestor that gave us the acknowledgement that he desires MAXIMUM_ALLOWED access right or AccessCheckRegular if the requestor wants a subset of access rights.
[in]RemainingAccessThe remaining access rights that have yet to be granted to the calling thread whomst requests access to a certain object. This parameter mustn't be 0 as the remaining rights are left to be addressed. This is the case if we have to address the remaining rights on a regular subset basis (the requestor didn't ask for MAXIMUM_ALLOWED). Otherwise this parameter can be 0.
[in]DaclThe discretionary access control list to be given to this function. This DACL must have at least one ACE currently present in the list.
[in]AccessTokenA pointer to an access token, where an equality comparison check is performed if the security identifier (SID) from a ACE of a certain object is present in this token. This token represents the effective (calling thread) token of the caller.
[in]PrimaryAccessTokenA pointer to an access token, represented as an access token associated with the primary calling process. This token describes the primary security context of the main process.
[in]IsTokenRestrictedIf this parameter is set to TRUE, the function considers the token pointed by AccessToken parameter argument as restricted. That is, the token has restricted SIDs therefore the function will act accordingly against that token by checking for restricted SIDs only when doing an equaility comparison check between the two identifiers.
[in]PrincipalSelfSidA pointer to a security identifier that represents a principal. A principal identifies a user object which is associated with its own security descriptor.
[in]GenericMappingA pointer to a generic mapping that is associated with the object in question being checked for access. If certain set of desired access rights have a generic access right, this parameter is needed to map generic rights.
[in]ObjectTypeListA pointer to a list array of object types. If such array is provided to the function, the algorithm will perform a different approach by doing analysis against ACEs each sub-object of an object of primary level (level 0) or sub-objects of a sub-object of an object. If this parameter is NULL, the function will normally analyze the ACEs of a DACL of the target object itself.
[in]ObjectTypeListLengthThe length of the object type list array, pointed by ObjectTypeList. This length in question represents the number of elements in such array. This parameter must be 0 if no array list is provided.
[in]UseResultListThis parameter is to used to determine how to perform an object type access check. If set to TRUE, the function will either grant or deny access to the object and sub-objects in the hierarchy list. If set to FALSE, the function will either grant or deny access to the target that will affect the entire hierarchy of the list. This parameter is used if the access action type is AccessCheckMaximum.
[in,out]AccessCheckRightsA pointer to a structure that contains the access check rights. This function fills up this structure with remaining, granted and denied rights to the caller for access check. Henceforth, this parameter must not be NULL!

Definition at line 460 of file accesschk.c.

473{
475 PACE CurrentAce;
477 ULONG ObjectTypeIndex;
478 PSID Sid;
479 PGUID ObjectTypeGuid;
480 ACCESS_MASK Access;
481 BOOLEAN BreakOnDeny;
482
483 PAGED_CODE();
484
485 /* These parameters are really needed */
486 ASSERT(Dacl);
487 ASSERT(AccessToken);
488
489 /* TODO: To be removed once we support compound ACEs handling in Se */
490 DBG_UNREFERENCED_PARAMETER(PrimaryAccessToken);
491
492 /* Determine how we should analyze the ACEs */
493 switch (ActionType)
494 {
495 /*
496 * We got the acknowledgement the calling thread desires
497 * maximum rights (as according to MAXIMUM_ALLOWED access
498 * mask). Analyze the ACE of the given DACL.
499 */
501 {
502 /* Loop over the DACL to retrieve ACEs */
503 for (AceIndex = 0; AceIndex < Dacl->AceCount; AceIndex++)
504 {
505 /* Obtain a ACE now */
506 Status = RtlGetAce(Dacl, AceIndex, (PVOID*)&CurrentAce);
507
508 /* Getting this ACE is important, otherwise something is seriously wrong */
510
511 /*
512 * Now it's time to analyze it based upon the
513 * type of this ACE we're being given.
514 */
515 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
516 {
517 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
518 {
519 /* Get the SID from this ACE */
520 Sid = SepGetSidFromAce(CurrentAce);
521 ASSERT(Sid);
522
523 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, TRUE, IsTokenRestricted))
524 {
525 /* Get this access right from the ACE */
526 Access = CurrentAce->AccessMask;
527
528 /* Map this access right if it has a generic mask right */
529 if ((Access & GENERIC_ACCESS) && GenericMapping)
530 {
532 }
533
534 /* Deny access rights that have not been granted yet */
535 AccessCheckRights->DeniedAccessRights |= (Access & ~AccessCheckRights->GrantedAccessRights);
536 DPRINT("DeniedAccessRights 0x%08lx\n", AccessCheckRights->DeniedAccessRights);
537 }
538 }
539 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
540 {
541 /* Get the SID from this ACE */
542 Sid = SepGetSidFromAce(CurrentAce);
543 ASSERT(Sid);
544
545 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, FALSE, IsTokenRestricted))
546 {
547 /* Get this access right from the ACE */
548 Access = CurrentAce->AccessMask;
549
550 /* Map this access right if it has a generic mask right */
551 if ((Access & GENERIC_ACCESS) && GenericMapping)
552 {
554 }
555
556 /* Grant access rights that have not been denied yet */
557 AccessCheckRights->GrantedAccessRights |= (Access & ~AccessCheckRights->DeniedAccessRights);
558 DPRINT("GrantedAccessRights 0x%08lx\n", AccessCheckRights->GrantedAccessRights);
559 }
560 }
561 else if (CurrentAce->Header.AceType == ACCESS_DENIED_OBJECT_ACE_TYPE)
562 {
563 /* Get the SID and object type from this ACE */
564 Sid = SepGetSidFromAce(CurrentAce);
565 ObjectTypeGuid = SepGetObjectTypeGuidFromAce(CurrentAce, TRUE);
566 ASSERT(Sid);
567
568 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, TRUE, IsTokenRestricted))
569 {
570 /* Get this access right from the ACE */
571 Access = CurrentAce->AccessMask;
572
573 /* Map this access right if it has a generic mask right */
574 if ((Access & GENERIC_ACCESS) && GenericMapping)
575 {
577 }
578
579 /* If no list was passed treat this is as ACCESS_DENIED_ACE_TYPE */
580 if (!ObjectTypeList && !ObjectTypeListLength)
581 {
582 AccessCheckRights->DeniedAccessRights |= (Access & ~AccessCheckRights->GrantedAccessRights);
583 DPRINT("DeniedAccessRights 0x%08lx\n", AccessCheckRights->DeniedAccessRights);
584 }
585 else if (!UseResultList)
586 {
587 /*
588 * We have an object type list but the caller wants to deny access
589 * to the entire hierarchy list. Evaluate the rights of the object
590 * for the whole list. Ignore what the function tells us if we have
591 * to break on deny or not because we only want to keep track of
592 * denied rights.
593 */
594 SepDenyAccessObjectTypeList(ObjectTypeList,
595 ObjectTypeListLength,
596 Access,
597 ObjectTypeGuid,
598 NULL);
599 }
600 else
601 {
602 /* Otherwise evaluate the access rights for each sub-object */
604 ObjectTypeListLength,
605 Access,
606 ObjectTypeGuid);
607 }
608 }
609 }
610 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE)
611 {
612 /* Get the SID and object type from this ACE */
613 Sid = SepGetSidFromAce(CurrentAce);
614 ObjectTypeGuid = SepGetObjectTypeGuidFromAce(CurrentAce, FALSE);
615 ASSERT(Sid);
616
617 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, FALSE, IsTokenRestricted))
618 {
619 /* Get this access right from the ACE */
620 Access = CurrentAce->AccessMask;
621
622 /* Map this access right if it has a generic mask right */
623 if ((Access & GENERIC_ACCESS) && GenericMapping)
624 {
626 }
627
628 /* If no list was passed treat this is as ACCESS_ALLOWED_ACE_TYPE */
629 if (!ObjectTypeList && !ObjectTypeListLength)
630 {
631 AccessCheckRights->GrantedAccessRights |= (Access & ~AccessCheckRights->DeniedAccessRights);
632 DPRINT("GrantedAccessRights 0x%08lx\n", AccessCheckRights->GrantedAccessRights);
633 }
634 else if (!UseResultList)
635 {
636 /*
637 * We have an object type list but the caller wants to allow access
638 * to the entire hierarchy list. Evaluate the rights of the object
639 * for the whole list.
640 */
641 SepAllowAccessObjectTypeList(ObjectTypeList,
642 ObjectTypeListLength,
643 Access,
644 FALSE,
645 ObjectTypeGuid);
646 }
647 else
648 {
649 /* Otherwise evaluate the access rights for each sub-object */
651 ObjectTypeListLength,
652 Access,
653 ObjectTypeGuid);
654 }
655 }
656 }
657 else
658 {
659 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
660 }
661 }
662 }
663
664 /* We're done here */
665 break;
666 }
667
668 /*
669 * We got the acknowledgement the calling thread desires
670 * only a subset of rights therefore we have to act a little
671 * different here.
672 */
674 {
675 /* Cache the remaining access rights to be addressed */
676 ASSERT(RemainingAccess != 0);
677 AccessCheckRights->RemainingAccessRights = RemainingAccess;
678
679 /* Fill the remaining rights of each object in the list if we have one */
680 if (ObjectTypeList && (ObjectTypeListLength != 0))
681 {
682 for (ObjectTypeIndex = 0;
683 ObjectTypeIndex < ObjectTypeListLength;
684 ObjectTypeIndex++)
685 {
686 ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.RemainingAccessRights = RemainingAccess;
687 }
688 }
689
690 /* Loop over the DACL to retrieve ACEs */
691 for (AceIndex = 0; AceIndex < Dacl->AceCount; AceIndex++)
692 {
693 /* Obtain a ACE now */
694 Status = RtlGetAce(Dacl, AceIndex, (PVOID*)&CurrentAce);
695
696 /* Getting this ACE is important, otherwise something is seriously wrong */
698
699 /*
700 * Now it's time to analyze it based upon the
701 * type of this ACE we're being given.
702 */
703 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
704 {
705 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
706 {
707 /* Get the SID from this ACE */
708 Sid = SepGetSidFromAce(CurrentAce);
709 ASSERT(Sid);
710
711 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, TRUE, IsTokenRestricted))
712 {
713 /* Get this access right from the ACE */
714 Access = CurrentAce->AccessMask;
715
716 /* Map this access right if it has a generic mask right */
717 if ((Access & GENERIC_ACCESS) && GenericMapping)
718 {
720 }
721
722 /*
723 * The caller requests a right that cannot be
724 * granted. Access is implicitly denied for
725 * the calling thread. Track this access right.
726 */
727 if (AccessCheckRights->RemainingAccessRights & Access)
728 {
729 DPRINT("Refuted access 0x%08lx\n", Access);
730 AccessCheckRights->DeniedAccessRights |= Access;
731 break;
732 }
733 }
734 }
735 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
736 {
737 /* Get the SID from this ACE */
738 Sid = SepGetSidFromAce(CurrentAce);
739 ASSERT(Sid);
740
741 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, FALSE, IsTokenRestricted))
742 {
743 /* Get this access right from the ACE */
744 Access = CurrentAce->AccessMask;
745
746 /* Map this access right if it has a generic mask right */
747 if ((Access & GENERIC_ACCESS) && GenericMapping)
748 {
750 }
751
752 /* Remove the remaining rights */
753 DPRINT("RemainingAccessRights 0x%08lx Access 0x%08lx\n", AccessCheckRights->RemainingAccessRights, Access);
754 AccessCheckRights->RemainingAccessRights &= ~Access;
755 DPRINT("RemainingAccessRights 0x%08lx\n", AccessCheckRights->RemainingAccessRights);
756
757 /* Track the granted access right */
758 AccessCheckRights->GrantedAccessRights |= Access;
759 }
760 }
761 else if (CurrentAce->Header.AceType == ACCESS_DENIED_OBJECT_ACE_TYPE)
762 {
763 /* Get the SID and object type from this ACE */
764 Sid = SepGetSidFromAce(CurrentAce);
765 ObjectTypeGuid = SepGetObjectTypeGuidFromAce(CurrentAce, TRUE);
766 ASSERT(Sid);
767
768 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, TRUE, IsTokenRestricted))
769 {
770 /* Get this access right from the ACE */
771 Access = CurrentAce->AccessMask;
772
773 /* Map this access right if it has a generic mask right */
774 if ((Access & GENERIC_ACCESS) && GenericMapping)
775 {
777 }
778
779 /* If no list was passed treat this is as ACCESS_DENIED_ACE_TYPE */
780 if (!ObjectTypeList && !ObjectTypeListLength)
781 {
782 if (AccessCheckRights->RemainingAccessRights & Access)
783 {
784 DPRINT("Refuted access 0x%08lx\n", Access);
785 AccessCheckRights->DeniedAccessRights |= Access;
786 break;
787 }
788 }
789 else
790 {
791 /*
792 * Otherwise evaluate the rights of the object for the entire list.
793 * The function will signal us if the caller requested a right that is
794 * denied by the ACE of an object in the list.
795 */
796 SepDenyAccessObjectTypeList(ObjectTypeList,
797 ObjectTypeListLength,
798 Access,
799 ObjectTypeGuid,
800 &BreakOnDeny);
801
802 /* We are acknowledged the caller requested a denied right */
803 if (BreakOnDeny)
804 {
805 DPRINT("Refuted access 0x%08lx\n", Access);
806 break;
807 }
808 }
809 }
810 }
811 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE)
812 {
813 /* Get the SID and object type from this ACE */
814 Sid = SepGetSidFromAce(CurrentAce);
815 ObjectTypeGuid = SepGetObjectTypeGuidFromAce(CurrentAce, FALSE);
816 ASSERT(Sid);
817
818 if (SepSidInTokenEx(AccessToken, PrincipalSelfSid, Sid, FALSE, IsTokenRestricted))
819 {
820 /* Get this access right from the ACE */
821 Access = CurrentAce->AccessMask;
822
823 /* Map this access right if it has a generic mask right */
824 if ((Access & GENERIC_ACCESS) && GenericMapping)
825 {
827 }
828
829 /* If no list was passed treat this is as ACCESS_ALLOWED_ACE_TYPE */
830 if (!ObjectTypeList && !ObjectTypeListLength)
831 {
832 /* Remove the remaining rights */
833 DPRINT("RemainingAccessRights 0x%08lx Access 0x%08lx\n", AccessCheckRights->RemainingAccessRights, Access);
834 AccessCheckRights->RemainingAccessRights &= ~Access;
835 DPRINT("RemainingAccessRights 0x%08lx\n", AccessCheckRights->RemainingAccessRights);
836
837 /* Track the granted access right */
838 AccessCheckRights->GrantedAccessRights |= Access;
839 }
840 else
841 {
842 /* Otherwise evaluate the rights of the object for the entire list */
843 SepAllowAccessObjectTypeList(ObjectTypeList,
844 ObjectTypeListLength,
845 Access,
846 TRUE,
847 ObjectTypeGuid);
848 }
849 }
850 }
851 else
852 {
853 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
854 }
855 }
856 }
857
858 /* We're done here */
859 break;
860 }
861
862 /* We shouldn't reach here */
864 }
865}
static VOID SepDenyAccessObjectTypeList(_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_opt_ PGUID ObjectTypeGuid, _Out_opt_ PBOOLEAN BreakOnDeny)
Denies access of a target object in the object type list. This access is denied for the whole hierarc...
Definition: accesschk.c:228
static VOID SepDenyAccessObjectTypeResultList(_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_opt_ PGUID ObjectTypeGuid)
Denies access of a target object and the children objects in an object type list.
Definition: accesschk.c:43
static VOID SepAllowAccessObjectTypeList(_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_ BOOLEAN RemoveRemainingRights, _In_opt_ PGUID ObjectTypeGuid)
Allows access of a target object in the object type list. This access is allowed for the whole hierar...
Definition: accesschk.c:324
static VOID SepAllowAccessObjectTypeResultList(_Inout_ POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ ACCESS_MASK AccessMask, _In_opt_ PGUID ObjectTypeGuid)
Allows access of a target object and the children objects in an object type list.
Definition: accesschk.c:135
#define GENERIC_ACCESS
Definition: security.c:35
BOOL WINAPI IsTokenRestricted(HANDLE TokenHandle)
Definition: token.c:207
NTSYSAPI NTSTATUS NTAPI RtlGetAce(PACL Acl, ULONG AceIndex, PVOID *Ace)
_In_ ULONG _In_ ACCESS_MASK _In_ PSID Sid
Definition: rtlfuncs.h:1133
#define DEFAULT_UNREACHABLE
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:318
PGUID SepGetObjectTypeGuidFromAce(_In_ PACE Ace, _In_ BOOLEAN IsAceDenied)
Captures an object type GUID from an object access control entry (ACE).
Definition: objtype.c:180
PSID NTAPI SepGetSidFromAce(_In_ PACE Ace)
Captures a security identifier from a given access control entry. This identifier is valid for the wh...
Definition: sid.c:572
BOOLEAN NTAPI SepSidInTokenEx(_In_ PACCESS_TOKEN _Token, _In_ PSID PrincipalSelfSid, _In_ PSID _Sid, _In_ BOOLEAN Deny, _In_ BOOLEAN Restricted)
Checks if a SID is present in a token.
Definition: sid.c:443
UCHAR AceFlags
Definition: ms-dtyp.idl:211
UCHAR AceType
Definition: ms-dtyp.idl:210
Definition: rtltypes.h:993
ACE_HEADER Header
Definition: rtltypes.h:994
ACCESS_MASK AccessMask
Definition: rtltypes.h:995
#define ACCESS_DENIED_OBJECT_ACE_TYPE
Definition: setypes.h:726
#define ACCESS_ALLOWED_OBJECT_ACE_TYPE
Definition: setypes.h:725

Referenced by SepAccessCheckWorker().

◆ SepDenyAccessObjectTypeList()

static VOID SepDenyAccessObjectTypeList ( _Inout_ POBJECT_TYPE_LIST_INTERNAL  ObjectTypeList,
_In_ ULONG  ObjectTypeListLength,
_In_ ACCESS_MASK  AccessMask,
_In_opt_ PGUID  ObjectTypeGuid,
_Out_opt_ PBOOLEAN  BreakOnDeny 
)
static

Denies access of a target object in the object type list. This access is denied for the whole hierarchy in the list.

Parameters
[in,out]ObjectTypeListA pointer to an object type list where access is to be denied for the target object. This operation applies for the entire hierarchy of the object type list.
[in]ObjectTypeListLengthThe length of the object type list. This length represents the number of object elements in the list.
[in]AccessMaskThe access mask right that is to be denied for the object.
[in]ObjectTypeGuidA pointer to a object type GUID, that identifies the object. This GUID is used to search for the target object in the list. If this parameter is set to NULL, the function will deny access to the object itself in the list (aka the root).
[out]BreakOnDenyA pointer returned boolean value to the caller. The function will return TRUE if the requested remaining right is denied by the ACE, otherwise it returns FALSE.

Definition at line 228 of file accesschk.c.

234{
235 ULONG ReturnedObjectIndex;
236 BOOLEAN MustBreak;
237
238 PAGED_CODE();
239
240 DPRINT("Access rights 0x%08lx\n", AccessMask);
241
242 /* Assume we do not want to break at first */
243 MustBreak = FALSE;
244
245 /*
246 * If no object type was supplied then tell the caller it has to break on
247 * searching for other ACEs if the requested remaining access right is
248 * denied by the deny ACE itself. Track down that denied right too.
249 */
250 if (!ObjectTypeGuid)
251 {
252 if (ObjectTypeList[0].ObjectAccessRights.RemainingAccessRights & AccessMask)
253 {
254 DPRINT("Root object requests remaining access right that is denied 0x%08lx\n", AccessMask);
255 MustBreak = TRUE;
256 }
257
258 ObjectTypeList[0].ObjectAccessRights.DeniedAccessRights |=
259 (AccessMask & ~ObjectTypeList[0].ObjectAccessRights.GrantedAccessRights);
260 DPRINT("Denied rights of root object 0x%08lx\n", ObjectTypeList[0].ObjectAccessRights.DeniedAccessRights);
261 goto Quit;
262 }
263
264 /*
265 * If the object exists tell the caller it has to break down if the requested
266 * remaining access right is denied by the ACE. Track down the denied right too.
267 */
268 if (SepObjectTypeGuidInList(ObjectTypeList,
269 ObjectTypeListLength,
270 ObjectTypeGuid,
271 &ReturnedObjectIndex))
272 {
273 if (ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.RemainingAccessRights & AccessMask)
274 {
275 DPRINT("Object at index %lu requests remaining access right that is denied 0x%08lx\n", ReturnedObjectIndex, AccessMask);
276 MustBreak = TRUE;
277 }
278
279 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights |=
280 (AccessMask & ~ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights);
281 DPRINT("Denied rights 0x%08lx of object at index %lu\n",
282 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights, ReturnedObjectIndex);
283 }
284
285Quit:
286 /* Signal the caller he has to break if he wants to */
287 if (BreakOnDeny)
288 {
289 *BreakOnDeny = MustBreak;
290 }
291}

Referenced by SepAnalyzeAcesFromDacl().

◆ SepDenyAccessObjectTypeResultList()

static VOID SepDenyAccessObjectTypeResultList ( _Inout_ POBJECT_TYPE_LIST_INTERNAL  ObjectTypeList,
_In_ ULONG  ObjectTypeListLength,
_In_ ACCESS_MASK  AccessMask,
_In_opt_ PGUID  ObjectTypeGuid 
)
static

Denies access of a target object and the children objects in an object type list.

Parameters
[in,out]ObjectTypeListA pointer to an object type list where access is to be denied for the target object and its children in the hierarchy list.
[in]ObjectTypeListLengthThe length of the object type list. This length represents the number of object elements in the list.
[in]AccessMaskThe access mask right that is to be denied for the object.
[in]ObjectTypeGuidA pointer to a object type GUID, that identifies the object. This GUID is used to search for the target object in the list. If this parameter is set to NULL, the function will deny access starting from the object itself in the list (aka the root).

Definition at line 43 of file accesschk.c.

48{
49 ULONG ObjectTypeIndex;
50 ULONG ReturnedObjectIndex;
52
53 PAGED_CODE();
54
55 DPRINT("Access rights 0x%08lx\n", AccessMask);
56
57 /*
58 * The object type of interest is the one that was supplied
59 * by the creator who made the ACE. If the object type was
60 * not supplied then we have no clear indication from where
61 * shall we start updating the access rights of objects on
62 * this list, so we have to begin from the root (aka the
63 * object itself).
64 */
65 if (!ObjectTypeGuid)
66 {
67 DPRINT("No object type provided, updating access rights from root\n");
68 ReturnedObjectIndex = 0;
69 goto LoopAndUpdateRightsObjects;
70 }
71
72 /* Check if that object exists in the list */
73 if (SepObjectTypeGuidInList(ObjectTypeList,
74 ObjectTypeListLength,
75 ObjectTypeGuid,
76 &ReturnedObjectIndex))
77 {
78LoopAndUpdateRightsObjects:
79 /* Update the access rights of the target object */
80 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights |=
81 (AccessMask & ~ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.GrantedAccessRights);
82 DPRINT("Denied rights 0x%08lx of target object at index %lu\n",
83 ObjectTypeList[ReturnedObjectIndex].ObjectAccessRights.DeniedAccessRights, ReturnedObjectIndex);
84
85 /* And update the children of the target object */
86 for (ObjectTypeIndex = ReturnedObjectIndex + 1;
87 ObjectTypeIndex < ObjectTypeListLength;
88 ObjectTypeIndex++)
89 {
90 /*
91 * Stop looking for children objects if we hit an object that has
92 * the same level as the target object or less.
93 */
94 Level = ObjectTypeList[ObjectTypeIndex].Level;
95 if (Level <= ObjectTypeList[ReturnedObjectIndex].Level)
96 {
97 DPRINT("We looked for all children objects, stop looking\n");
98 break;
99 }
100
101 /* Update the access right of the child */
102 ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.DeniedAccessRights |=
103 (AccessMask & ~ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights);
104 DPRINT("Denied rights 0x%08lx of child object at index %lu\n",
105 ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.DeniedAccessRights, ObjectTypeIndex);
106 }
107 }
108}

Referenced by SepAnalyzeAcesFromDacl().

◆ SepGetPrivilegeSetLength()

static ULONG SepGetPrivilegeSetLength ( _In_ PPRIVILEGE_SET  PrivilegeSet)
static

Retrieves the length size of a set list of privileges structure.

Parameters
[in]PrivilegeSetA valid set of privileges.
Returns
Returns the total length of a set of privileges.

Definition at line 1454 of file accesschk.c.

1456{
1457 if (PrivilegeSet == NULL)
1458 return 0;
1459
1460 if (PrivilegeSet->PrivilegeCount == 0)
1461 return (ULONG)(sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES));
1462
1463 return (ULONG)(sizeof(PRIVILEGE_SET) +
1464 (PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES));
1465}
struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES

Referenced by SepAccessCheck().