ReactOS 0.4.16-dev-250-g3ecd236
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 2214 of file accesschk.c.

2223{
2224 PAGED_CODE();
2225
2226 /* Invoke the internal function to do the job */
2228 ClientToken,
2229 NULL,
2232 PrivilegeSet,
2233 PrivilegeSetLength,
2234 NULL,
2235 0,
2236 FALSE,
2238 AccessStatus);
2239}
#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:1592
#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(), AccessCheckEmptyMappingTest(), 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 2254 of file accesschk.c.

2266{
2267 PAGED_CODE();
2268
2269 /* Invoke the internal function to do the job */
2271 ClientToken,
2272 PrincipalSelfSid,
2275 PrivilegeSet,
2276 PrivilegeSetLength,
2277 ObjectTypeList,
2278 ObjectTypeListLength,
2279 FALSE,
2281 AccessStatus);
2282}

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 2297 of file accesschk.c.

2309{
2310 PAGED_CODE();
2311
2312 /* Invoke the internal function to do the job */
2314 ClientToken,
2315 PrincipalSelfSid,
2318 PrivilegeSet,
2319 PrivilegeSetLength,
2320 ObjectTypeList,
2321 ObjectTypeListLength,
2322 TRUE,
2324 AccessStatus);
2325}
#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 1994 of file accesschk.c.

2005{
2006 BOOLEAN ret;
2007
2008 PAGED_CODE();
2009
2010 /* Check if this is kernel mode */
2011 if (AccessMode == KernelMode)
2012 {
2013 /* Check if kernel wants everything */
2015 {
2016 /* Give it */
2018 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
2020 }
2021 else
2022 {
2023 /* Give the desired and previous access */
2025 }
2026
2027 /* Success */
2029 return TRUE;
2030 }
2031
2032 /* Check if we didn't get an SD */
2033 if (!SecurityDescriptor)
2034 {
2035 /* Automatic failure */
2037 return FALSE;
2038 }
2039
2040 /* Check for invalid impersonation */
2043 {
2045 return FALSE;
2046 }
2047
2048 /* Acquire the lock if needed */
2051
2052 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
2054 {
2057
2060 FALSE))
2061 {
2064 else
2066
2068 }
2069 }
2070
2071 if (DesiredAccess == 0)
2072 {
2074 if (PreviouslyGrantedAccess == 0)
2075 {
2076 DPRINT1("Request for zero access to an object. Denying.\n");
2078 ret = FALSE;
2079 }
2080 else
2081 {
2083 ret = TRUE;
2084 }
2085 }
2086 else
2087 {
2088 /* Call the internal function */
2092 NULL,
2094 NULL,
2095 0,
2098 AccessMode,
2099 FALSE,
2100 Privileges,
2102 AccessStatus);
2103 }
2104
2105 /* Release the lock if needed */
2108
2109 return ret;
2110}
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 2138 of file accesschk.c.

2143{
2144 PACL Dacl;
2147
2148 PAGED_CODE();
2149
2151
2152 if (SecurityDescriptor == NULL)
2153 return FALSE;
2154
2155 /* Get DACL */
2157 /* If no DACL, grant access */
2158 if (Dacl == NULL)
2159 return TRUE;
2160
2161 /* No ACE -> Deny */
2162 if (!Dacl->AceCount)
2163 return FALSE;
2164
2165 /* Can't perform the check on restricted token */
2166 if (AccessState->Flags & TOKEN_IS_RESTRICTED)
2167 return FALSE;
2168
2169 /* Browse the ACEs */
2170 for (AceIndex = 0, Ace = (PKNOWN_ACE)((ULONG_PTR)Dacl + sizeof(ACL));
2171 AceIndex < Dacl->AceCount;
2172 AceIndex++, Ace = (PKNOWN_ACE)((ULONG_PTR)Ace + Ace->Header.AceSize))
2173 {
2174 if (Ace->Header.AceFlags & INHERIT_ONLY_ACE)
2175 continue;
2176
2177 /* If access-allowed ACE */
2178 if (Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
2179 {
2180 /* Check if all accesses are granted */
2181 if (!(Ace->Mask & DesiredAccess))
2182 continue;
2183
2184 /* Check SID and grant access if matching */
2185 if (RtlEqualSid(SeWorldSid, &(Ace->SidStart)))
2186 return TRUE;
2187 }
2188 /* If access-denied ACE */
2189 else if (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
2190 {
2191 /* Here, only check if it denies any access wanted and deny if so */
2192 if (Ace->Mask & DesiredAccess)
2193 return FALSE;
2194 }
2195 }
2196
2197 /* Faulty, deny */
2198 return FALSE;
2199}
@ 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:1605
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:1879
_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 1592 of file accesschk.c.

1605{
1606 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
1607 POBJECT_TYPE_LIST_INTERNAL CapturedObjectTypeList = NULL;
1608 PSID CapturedPrincipalSelfSid = NULL;
1613 ULONG CapturedPrivilegeSetLength, RequiredPrivilegeSetLength;
1614 ULONG ResultListIndex;
1615 PTOKEN Token;
1617
1618 PAGED_CODE();
1619
1620 /* Check if this is kernel mode */
1621 if (PreviousMode == KernelMode)
1622 {
1623 /* Check if kernel wants everything */
1625 {
1626 /* Give it */
1628 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
1629 }
1630 else
1631 {
1632 /* Just give the desired access */
1634 }
1635
1636 /* Success */
1638 return STATUS_SUCCESS;
1639 }
1640
1641 /* Protect probe in SEH */
1642 _SEH2_TRY
1643 {
1644 /* Probe all pointers */
1646 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
1647 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
1648
1649 /*
1650 * Probe the access and status list based on the way
1651 * we are going to fill data in.
1652 */
1653 if (UseResultList)
1654 {
1655 /* Bail out on an empty list */
1656 if (!ObjectTypeListLength)
1657 {
1658 DPRINT1("The object type list is empty\n");
1660 }
1661
1662 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK) * ObjectTypeListLength, sizeof(ULONG));
1663 ProbeForWrite(AccessStatus, sizeof(NTSTATUS) * ObjectTypeListLength, sizeof(ULONG));
1664 }
1665 else
1666 {
1667 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
1668 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
1669 }
1670
1671 /* Capture the privilege set length and the mapping */
1672 CapturedPrivilegeSetLength = *PrivilegeSetLength;
1673 }
1675 {
1676 /* Return the exception code */
1678 }
1679 _SEH2_END;
1680
1681 /* Check for unmapped access rights */
1683 {
1684 DPRINT1("Some generic rights are not mapped\n");
1686 }
1687
1688 /* Reference the token */
1689 Status = ObReferenceObjectByHandle(ClientToken,
1693 (PVOID*)&Token,
1694 NULL);
1695 if (!NT_SUCCESS(Status))
1696 {
1697 DPRINT1("Failed to reference token (Status 0x%08lx)\n", Status);
1698 return Status;
1699 }
1700
1701 /* Check token type */
1702 if (Token->TokenType != TokenImpersonation)
1703 {
1704 DPRINT("No impersonation token\n");
1707 }
1708
1709 /* Check the impersonation level */
1710 if (Token->ImpersonationLevel < SecurityIdentification)
1711 {
1712 DPRINT1("Impersonation level < SecurityIdentification\n");
1715 }
1716
1717 /* Capture the object type list, the list is probed by the function itself */
1718 Status = SeCaptureObjectTypeList(ObjectTypeList,
1719 ObjectTypeListLength,
1721 &CapturedObjectTypeList);
1722 if (!NT_SUCCESS(Status))
1723 {
1724 DPRINT1("Failed to capture the object type list (Status 0x%08lx)\n", Status);
1726 return Status;
1727 }
1728
1729 /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
1732 NULL,
1733 Token,
1734 &Privileges,
1735 PreviousMode);
1736 if (!NT_SUCCESS(Status))
1737 {
1738 DPRINT1("SePrivilegePolicyCheck failed (Status 0x%08lx)\n", Status);
1739 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1741
1742 /*
1743 * The caller does not have the required access to do an access check.
1744 * Propagate the access and status for the whole hierarchy of the list
1745 * or just to single target object.
1746 */
1747 if (UseResultList)
1748 {
1749 for (ResultListIndex = 0; ResultListIndex < ObjectTypeListLength; ResultListIndex++)
1750 {
1751 AccessStatus[ResultListIndex] = Status;
1752 GrantedAccess[ResultListIndex] = 0;
1753 }
1754 }
1755 else
1756 {
1758 *GrantedAccess = 0;
1759 }
1760
1761 return STATUS_SUCCESS;
1762 }
1763
1764 /* Check the size of the privilege set and return the privileges */
1765 if (Privileges != NULL)
1766 {
1767 DPRINT("Privileges != NULL\n");
1768
1769 /* Calculate the required privilege set buffer size */
1770 RequiredPrivilegeSetLength = SepGetPrivilegeSetLength(Privileges);
1771
1772 /* Fail if the privilege set buffer is too small */
1773 if (CapturedPrivilegeSetLength < RequiredPrivilegeSetLength)
1774 {
1776 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1778 *PrivilegeSetLength = RequiredPrivilegeSetLength;
1780 }
1781
1782 /* Copy the privilege set to the caller */
1783 RtlCopyMemory(PrivilegeSet,
1784 Privileges,
1785 RequiredPrivilegeSetLength);
1786
1787 /* Free the local privilege set */
1789 }
1790 else
1791 {
1792 DPRINT("Privileges == NULL\n");
1793
1794 /* Fail if the privilege set buffer is too small */
1795 if (CapturedPrivilegeSetLength < sizeof(PRIVILEGE_SET))
1796 {
1797 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1799 *PrivilegeSetLength = sizeof(PRIVILEGE_SET);
1801 }
1802
1803 /* Initialize the privilege set */
1804 PrivilegeSet->PrivilegeCount = 0;
1805 PrivilegeSet->Control = 0;
1806 }
1807
1808 /* Capture the security descriptor */
1811 PagedPool,
1812 FALSE,
1813 &CapturedSecurityDescriptor);
1814 if (!NT_SUCCESS(Status))
1815 {
1816 DPRINT1("Failed to capture the Security Descriptor\n");
1817 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1819 return Status;
1820 }
1821
1822 /* Check the captured security descriptor */
1823 if (CapturedSecurityDescriptor == NULL)
1824 {
1825 DPRINT1("Security Descriptor is NULL\n");
1826 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1829 }
1830
1831 /* Check security descriptor for valid owner and group */
1832 if (SepGetOwnerFromDescriptor(CapturedSecurityDescriptor) == NULL ||
1833 SepGetGroupFromDescriptor(CapturedSecurityDescriptor) == NULL)
1834 {
1835 DPRINT1("Security Descriptor does not have a valid group or owner\n");
1836 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1838 FALSE);
1839 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1842 }
1843
1844 /* Capture the principal self SID if we have one */
1845 if (PrincipalSelfSid)
1846 {
1847 Status = SepCaptureSid(PrincipalSelfSid,
1849 PagedPool,
1850 TRUE,
1851 &CapturedPrincipalSelfSid);
1852 if (!NT_SUCCESS(Status))
1853 {
1854 DPRINT1("Failed to capture the principal self SID (Status 0x%08lx)\n", Status);
1855 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1857 FALSE);
1858 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1860 return Status;
1861 }
1862 }
1863
1864 /* Set up the subject context, and lock it */
1866
1867 /* Lock the token */
1869
1870 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
1872 {
1873 if (SepTokenIsOwner(Token, CapturedSecurityDescriptor, FALSE))
1874 {
1877 else
1879
1881 }
1882 }
1883
1884 if (DesiredAccess == 0)
1885 {
1886 /*
1887 * Propagate the access and status for the whole hierarchy
1888 * of the list or just to single target object.
1889 */
1890 if (UseResultList)
1891 {
1892 for (ResultListIndex = 0; ResultListIndex < ObjectTypeListLength; ResultListIndex++)
1893 {
1894 AccessStatus[ResultListIndex] = STATUS_SUCCESS;
1895 GrantedAccess[ResultListIndex] = PreviouslyGrantedAccess;
1896 }
1897 }
1898 else
1899 {
1902 }
1903 }
1904 else
1905 {
1906 /* Now perform the access check */
1907 SepAccessCheckWorker(CapturedSecurityDescriptor,
1908 Token,
1910 CapturedPrincipalSelfSid,
1912 CapturedObjectTypeList,
1913 ObjectTypeListLength,
1917 UseResultList,
1918 NULL,
1920 AccessStatus);
1921 }
1922
1923 /* Release subject context and unlock the token */
1926
1927 /* Release the caputed principal self SID */
1928 SepReleaseSid(CapturedPrincipalSelfSid,
1930 TRUE);
1931
1932 /* Release the captured security descriptor */
1933 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1935 FALSE);
1936
1937 /* Release the object type list */
1938 SeReleaseObjectTypeList(CapturedObjectTypeList, PreviousMode);
1939
1940 /* Dereference the token */
1942
1943 /* Check succeeded */
1944 return STATUS_SUCCESS;
1945}
static ULONG SepGetPrivilegeSetLength(_In_ PPRIVILEGE_SET PrivilegeSet)
Retrieves the length size of a set list of privileges structure.
Definition: accesschk.c:1482
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#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:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:73
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 /*
1062 * HACK: Temporary hack that checks if the caller passed an empty
1063 * generic mapping. In such cases we cannot mask out the remaining
1064 * access rights without a proper mapping so the only option we
1065 * can do is to check if the client is an administrator,
1066 * since they are powerful users.
1067 *
1068 * See CORE-18576 for information.
1069 */
1070 if (GenericMapping->GenericRead == 0 &&
1074 {
1075 if (SeTokenIsAdmin(Token))
1076 {
1077 /* Grant him access */
1078 PreviouslyGrantedAccess |= RemainingAccess;
1080 goto ReturnCommonStatus;
1081 }
1082
1083 /* It's not an admin so bail out */
1086 goto ReturnCommonStatus;
1087 }
1088
1089 /* Get the DACL */
1091 &Present,
1092 &Dacl,
1093 &Defaulted);
1094 if (!NT_SUCCESS(Status))
1095 {
1096 goto ReturnCommonStatus;
1097 }
1098
1099 /* Grant desired access if the object is unprotected */
1100 if (Present == FALSE || Dacl == NULL)
1101 {
1102 PreviouslyGrantedAccess |= RemainingAccess;
1103 if (RemainingAccess & MAXIMUM_ALLOWED)
1104 {
1105 PreviouslyGrantedAccess &= ~MAXIMUM_ALLOWED;
1107 }
1108
1110 goto ReturnCommonStatus;
1111 }
1112
1113 /* Deny access if the DACL is empty */
1114 if (Dacl->AceCount == 0)
1115 {
1116 if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0)
1117 {
1119 }
1120 else
1121 {
1122 DPRINT1("The DACL has no ACEs and the caller has no previously granted access!\n");
1125 }
1126 goto ReturnCommonStatus;
1127 }
1128
1129 /*
1130 * Determine the MAXIMUM_ALLOWED access rights according to the DACL.
1131 * Or if the caller is supplying a list of object types then determine
1132 * the rights of each object on that list.
1133 */
1134 if ((DesiredAccess & MAXIMUM_ALLOWED) || UseResultList)
1135 {
1136 /* Perform access checks against ACEs from this DACL */
1138 0,
1139 Dacl,
1140 Token,
1141 PrimaryAccessToken,
1142 FALSE,
1143 PrincipalSelfSid,
1145 ObjectTypeList,
1146 ObjectTypeListLength,
1147 UseResultList,
1148 &AccessCheckRights);
1149
1150 /*
1151 * Perform further access checks if this token
1152 * has restricted SIDs.
1153 */
1155 {
1157 0,
1158 Dacl,
1159 Token,
1160 PrimaryAccessToken,
1161 TRUE,
1162 PrincipalSelfSid,
1164 ObjectTypeList,
1165 ObjectTypeListLength,
1166 UseResultList,
1167 &AccessCheckRights);
1168 }
1169
1170 /* The caller did not provide an object type list, check access only for that object */
1171 if (!ObjectTypeList && !ObjectTypeListLength)
1172 {
1173 /* Fail if some rights have not been granted */
1174 RemainingAccess &= ~(MAXIMUM_ALLOWED | AccessCheckRights.GrantedAccessRights);
1175 if (RemainingAccess != 0)
1176 {
1177 DPRINT("Failed to grant access rights, access denied. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", RemainingAccess, DesiredAccess);
1180 goto ReturnCommonStatus;
1181 }
1182
1183 /* Set granted access right and access status */
1184 PreviouslyGrantedAccess |= AccessCheckRights.GrantedAccessRights;
1185 if (PreviouslyGrantedAccess != 0)
1186 {
1188 }
1189 else
1190 {
1191 DPRINT("Failed to grant access rights, access denied. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess);
1193 }
1194
1195 /* We are done here */
1196 goto ReturnCommonStatus;
1197 }
1198 else if (!UseResultList)
1199 {
1200 /*
1201 * We have a list but the caller wants to know if access can be granted
1202 * to an object in the list. Access will either be granted or denied
1203 * to the whole hierarchy of the list. Look for every object in the list
1204 * that has granted access rights and collect them.
1205 */
1206 for (ObjectTypeIndex = 0;
1207 ObjectTypeIndex < ObjectTypeListLength;
1208 ObjectTypeIndex++)
1209 {
1210 if (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights != 0)
1211 {
1212 GrantedRights |= ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights;
1213 }
1214 }
1215
1216 /* Now check if acccess can be granted */
1217 RemainingAccess &= ~(MAXIMUM_ALLOWED | GrantedRights);
1218 if (RemainingAccess != 0)
1219 {
1220 DPRINT("Failed to grant access rights to the whole object hierarchy list, access denied. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n",
1221 RemainingAccess, DesiredAccess);
1224 goto ReturnCommonStatus;
1225 }
1226
1227 /* Set granted access right and access status */
1228 PreviouslyGrantedAccess |= GrantedRights;
1229 if (PreviouslyGrantedAccess != 0)
1230 {
1232 }
1233 else
1234 {
1235 DPRINT("Failed to grant access rights to the whole object hierarchy list, access denied. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n",
1238 }
1239
1240 /* We are done here */
1241 goto ReturnCommonStatus;
1242 }
1243 else
1244 {
1245 /*
1246 * We have a list and the caller wants to know access for each
1247 * sub-object in the list. Report the access status and granted
1248 * rights for the object and each sub-object in the list.
1249 */
1250 for (ObjectTypeIndex = 0;
1251 ObjectTypeIndex < ObjectTypeListLength;
1252 ObjectTypeIndex++)
1253 {
1254 /* Check if we have some rights */
1255 GrantedRights = (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights | PreviouslyGrantedAccess) & MaskDesired;
1256 if (GrantedRights != 0)
1257 {
1258 /*
1259 * If we still have some remaining rights to grant the ultimate
1260 * conclusion is that the caller has no access to the object itself.
1261 */
1262 RemainingAccess = (~GrantedRights & WantedRights);
1263 if (RemainingAccess != 0)
1264 {
1265 DPRINT("Failed to grant access rights at specific object at index %lu, access denied. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n",
1266 ObjectTypeIndex, RemainingAccess, DesiredAccess);
1267 AccessStatusList[ObjectTypeIndex] = STATUS_ACCESS_DENIED;
1268 }
1269 else
1270 {
1271 AccessStatusList[ObjectTypeIndex] = STATUS_SUCCESS;
1272 }
1273 }
1274 else
1275 {
1276 /* No access is given */
1277 DPRINT("Failed to grant access rights at specific object at index %lu. No access is given\n", ObjectTypeIndex);
1278 AccessStatusList[ObjectTypeIndex] = STATUS_ACCESS_DENIED;
1279 }
1280
1281 /* Return the access rights to the caller */
1282 GrantedAccessList[ObjectTypeIndex] = GrantedRights;
1283 }
1284
1285 /*
1286 * We have built a list of access statuses for each object but
1287 * we still need to figure out the common status for the
1288 * function. The same status code will be used to check if
1289 * we should report any security debug stuff once we are done.
1290 */
1292 for (ResultListIndex = 0; ResultListIndex < ObjectTypeListLength; ResultListIndex++)
1293 {
1294 /* There is at least one sub-object of which access cannot be granted */
1295 if (AccessStatusList[ResultListIndex] == STATUS_ACCESS_DENIED)
1296 {
1297 Status = AccessStatusList[ResultListIndex];
1298 break;
1299 }
1300 }
1301
1302 /* We are done here */
1303 goto ReturnCommonStatus;
1304 }
1305 }
1306
1307 /* Grant rights according to the DACL */
1309 RemainingAccess,
1310 Dacl,
1311 Token,
1312 PrimaryAccessToken,
1313 FALSE,
1314 PrincipalSelfSid,
1316 ObjectTypeList,
1317 ObjectTypeListLength,
1318 UseResultList,
1319 &AccessCheckRights);
1320
1321 /* The caller did not provide an object type list, check access only for that object */
1322 if (!ObjectTypeList && !ObjectTypeListLength)
1323 {
1324 /* Fail if some rights have not been granted */
1325 if (AccessCheckRights.RemainingAccessRights != 0)
1326 {
1327 DPRINT("Failed to grant access rights, access denied. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", AccessCheckRights.RemainingAccessRights, DesiredAccess);
1330 goto ReturnCommonStatus;
1331 }
1332 }
1333 else
1334 {
1335 /*
1336 * We have an object type list, look for the object of which
1337 * remaining rights are all granted.
1338 */
1339 for (ObjectTypeIndex = 0;
1340 ObjectTypeIndex < ObjectTypeListLength;
1341 ObjectTypeIndex++)
1342 {
1343 if (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.RemainingAccessRights == 0)
1344 {
1345 AccessIsGranted = TRUE;
1346 break;
1347 }
1348 }
1349
1350 if (!AccessIsGranted)
1351 {
1352 DPRINT("Failed to grant access rights to the whole object hierarchy list, access denied. DesiredAccess = 0x%08lx\n", DesiredAccess);
1355 goto ReturnCommonStatus;
1356 }
1357 }
1358
1359 /*
1360 * Perform further access checks if this token
1361 * has restricted SIDs.
1362 */
1364 {
1366 RemainingAccess,
1367 Dacl,
1368 Token,
1369 PrimaryAccessToken,
1370 TRUE,
1371 PrincipalSelfSid,
1373 ObjectTypeList,
1374 ObjectTypeListLength,
1375 UseResultList,
1376 &AccessCheckRights);
1377
1378 /* The caller did not provide an object type list, check access only for that object */
1379 if (!ObjectTypeList && !ObjectTypeListLength)
1380 {
1381 /* Fail if some rights have not been granted */
1382 if (AccessCheckRights.RemainingAccessRights != 0)
1383 {
1384 DPRINT("Failed to grant access rights, access denied. RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", AccessCheckRights.RemainingAccessRights, DesiredAccess);
1387 goto ReturnCommonStatus;
1388 }
1389 }
1390 else
1391 {
1392 /*
1393 * We have an object type list, look for the object of which remaining
1394 * rights are all granted. The user may have access to the requested
1395 * object but on a restricted token case the user is only granted partial
1396 * access. If access is denied to restricted SIDs, the bottom line is that
1397 * access is denied to the user.
1398 */
1399 AccessIsGranted = FALSE;
1400 for (ObjectTypeIndex = 0;
1401 ObjectTypeIndex < ObjectTypeListLength;
1402 ObjectTypeIndex++)
1403 {
1404 if (ObjectTypeList[ObjectTypeIndex].ObjectAccessRights.RemainingAccessRights == 0)
1405 {
1406 AccessIsGranted = TRUE;
1407 break;
1408 }
1409 }
1410
1411 if (!AccessIsGranted)
1412 {
1413 DPRINT("Failed to grant access rights to the whole object hierarchy list, access denied. DesiredAccess = 0x%08lx\n", DesiredAccess);
1416 goto ReturnCommonStatus;
1417 }
1418 }
1419 }
1420
1421 /* Set granted access rights */
1423
1424 /* Fail if no rights have been granted */
1425 if (PreviouslyGrantedAccess == 0)
1426 {
1427 DPRINT("Failed to grant access rights, access denied. PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess);
1429 goto ReturnCommonStatus;
1430 }
1431
1432 /*
1433 * If we're here then we granted all the desired
1434 * access rights the caller wanted.
1435 */
1437
1438ReturnCommonStatus:
1439 if (!UseResultList)
1440 {
1441 *GrantedAccessList = PreviouslyGrantedAccess;
1442 *AccessStatusList = Status;
1443 }
1444
1445#if DBG
1446 /* Dump security debug info on access denied case */
1448 {
1451
1452 if (ObjectTypeList && (ObjectTypeListLength != 0))
1453 {
1454 SepDumpAccessAndStatusList(GrantedAccessList,
1455 AccessStatusList,
1456 UseResultList,
1457 ObjectTypeList,
1458 ObjectTypeListLength);
1459 }
1460 else
1461 {
1462 SepDumpAccessRightsStats(&AccessCheckRights);
1463 }
1464 }
1465#endif
1466
1467 return NT_SUCCESS(Status);
1468}
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 SeTokenIsAdmin(_In_ PACCESS_TOKEN Token)
Determines if a token is either an admin token or not. Such condition is checked based upon TOKEN_HAS...
Definition: token.c:2103
BOOLEAN NTAPI SeTokenIsRestricted(_In_ PACCESS_TOKEN Token)
Determines if a token is restricted or not, based upon the token flags.
Definition: token.c:2126
ACCESS_MASK RemainingAccessRights
Definition: se.h:43
ACCESS_MASK GrantedAccessRights
Definition: se.h:44
ACCESS_MASK GenericExecute
Definition: nt_native.h:567
ACCESS_MASK GenericRead
Definition: nt_native.h:565
ACCESS_MASK GenericWrite
Definition: nt_native.h:566

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:1145
#define DEFAULT_UNREACHABLE
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:326
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 1482 of file accesschk.c.

1484{
1485 if (PrivilegeSet == NULL)
1486 return 0;
1487
1488 if (PrivilegeSet->PrivilegeCount == 0)
1489 return (ULONG)(sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES));
1490
1491 return (ULONG)(sizeof(PRIVILEGE_SET) +
1492 (PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES));
1493}
struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES

Referenced by SepAccessCheck().