1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Security access state functions support 5 * COPYRIGHT: Copyright Alex Ionescu <alex@relsoft.net> 6 */ 7 8 /* INCLUDES *******************************************************************/ 9 10 #include <ntoskrnl.h> 11 #define NDEBUG 12 #include <debug.h> 13 14 /* PUBLIC FUNCTIONS ***********************************************************/ 15 16 /** 17 * @brief 18 * An extended function that creates an access state. 19 * 20 * @param[in] Thread 21 * Valid thread object where subject context is to be captured. 22 * 23 * @param[in] Process 24 * Valid process object where subject context is to be captured. 25 * 26 * @param[in,out] AccessState 27 * An initialized returned parameter to an access state. 28 * 29 * @param[in] AuxData 30 * Auxiliary security data for access state. 31 * 32 * @param[in] Access 33 * Type of access mask to assign. 34 * 35 * @param[in] GenericMapping 36 * Generic mapping for the access state to assign. 37 * 38 * @return 39 * Returns STATUS_SUCCESS. 40 */ 41 NTSTATUS 42 NTAPI 43 SeCreateAccessStateEx( 44 _In_ PETHREAD Thread, 45 _In_ PEPROCESS Process, 46 _Inout_ PACCESS_STATE AccessState, 47 _In_ PAUX_ACCESS_DATA AuxData, 48 _In_ ACCESS_MASK Access, 49 _In_ PGENERIC_MAPPING GenericMapping) 50 { 51 ACCESS_MASK AccessMask = Access; 52 PTOKEN Token; 53 PAGED_CODE(); 54 55 /* Map the Generic Acess to Specific Access if we have a Mapping */ 56 if ((Access & GENERIC_ACCESS) && (GenericMapping)) 57 { 58 RtlMapGenericMask(&AccessMask, GenericMapping); 59 } 60 61 /* Initialize the Access State */ 62 RtlZeroMemory(AccessState, sizeof(ACCESS_STATE)); 63 ASSERT(AccessState->SecurityDescriptor == NULL); 64 ASSERT(AccessState->PrivilegesAllocated == FALSE); 65 66 /* Initialize and save aux data */ 67 RtlZeroMemory(AuxData, sizeof(AUX_ACCESS_DATA)); 68 AccessState->AuxData = AuxData; 69 70 /* Capture the Subject Context */ 71 SeCaptureSubjectContextEx(Thread, 72 Process, 73 &AccessState->SubjectSecurityContext); 74 75 /* Set Access State Data */ 76 AccessState->RemainingDesiredAccess = AccessMask; 77 AccessState->OriginalDesiredAccess = AccessMask; 78 ExAllocateLocallyUniqueId(&AccessState->OperationID); 79 80 /* Get the Token to use */ 81 Token = SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext); 82 83 /* Check for Travers Privilege */ 84 if (Token->TokenFlags & TOKEN_HAS_TRAVERSE_PRIVILEGE) 85 { 86 /* Preserve the Traverse Privilege */ 87 AccessState->Flags = TOKEN_HAS_TRAVERSE_PRIVILEGE; 88 } 89 90 /* Set the Auxiliary Data */ 91 AuxData->PrivilegeSet = (PPRIVILEGE_SET)((ULONG_PTR)AccessState + 92 FIELD_OFFSET(ACCESS_STATE, 93 Privileges)); 94 if (GenericMapping) AuxData->GenericMapping = *GenericMapping; 95 96 /* Return Sucess */ 97 return STATUS_SUCCESS; 98 } 99 100 /** 101 * @brief 102 * Creates an access state. 103 * 104 * @param[in,out] AccessState 105 * An initialized returned parameter to an access state. 106 * 107 * @param[in] AuxData 108 * Auxiliary security data for access state. 109 * 110 * @param[in] Access 111 * Type of access mask to assign. 112 * 113 * @param[in] GenericMapping 114 * Generic mapping for the access state to assign. 115 * 116 * @return 117 * See SeCreateAccessStateEx. 118 */ 119 NTSTATUS 120 NTAPI 121 SeCreateAccessState( 122 _Inout_ PACCESS_STATE AccessState, 123 _In_ PAUX_ACCESS_DATA AuxData, 124 _In_ ACCESS_MASK Access, 125 _In_ PGENERIC_MAPPING GenericMapping) 126 { 127 PAGED_CODE(); 128 129 /* Call the extended API */ 130 return SeCreateAccessStateEx(PsGetCurrentThread(), 131 PsGetCurrentProcess(), 132 AccessState, 133 AuxData, 134 Access, 135 GenericMapping); 136 } 137 138 /** 139 * @brief 140 * Deletes an allocated access state from the memory. 141 * 142 * @param[in] AccessState 143 * A valid access state. 144 * 145 * @return 146 * Nothing. 147 */ 148 VOID 149 NTAPI 150 SeDeleteAccessState( 151 _In_ PACCESS_STATE AccessState) 152 { 153 PAUX_ACCESS_DATA AuxData; 154 PAGED_CODE(); 155 156 /* Get the Auxiliary Data */ 157 AuxData = AccessState->AuxData; 158 159 /* Deallocate Privileges */ 160 if (AccessState->PrivilegesAllocated) 161 ExFreePoolWithTag(AuxData->PrivilegeSet, TAG_PRIVILEGE_SET); 162 163 /* Deallocate Name and Type Name */ 164 if (AccessState->ObjectName.Buffer) 165 { 166 ExFreePool(AccessState->ObjectName.Buffer); 167 } 168 169 if (AccessState->ObjectTypeName.Buffer) 170 { 171 ExFreePool(AccessState->ObjectTypeName.Buffer); 172 } 173 174 /* Release the Subject Context */ 175 SeReleaseSubjectContext(&AccessState->SubjectSecurityContext); 176 } 177 178 /** 179 * @brief 180 * Sets a new generic mapping for an allocated access state. 181 * 182 * @param[in] AccessState 183 * A valid access state. 184 * 185 * @param[in] GenericMapping 186 * New generic mapping to assign. 187 * 188 * @return 189 * Nothing. 190 */ 191 VOID 192 NTAPI 193 SeSetAccessStateGenericMapping( 194 _In_ PACCESS_STATE AccessState, 195 _In_ PGENERIC_MAPPING GenericMapping) 196 { 197 PAGED_CODE(); 198 199 /* Set the Generic Mapping */ 200 ((PAUX_ACCESS_DATA)AccessState->AuxData)->GenericMapping = *GenericMapping; 201 } 202 203 /* EOF */ 204