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[out] AccessState
27 * An initialized returned parameter to an access state.
28 *
29 * @param[out] 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
SeCreateAccessStateEx(_In_ PETHREAD Thread,_In_ PEPROCESS Process,_Out_ PACCESS_STATE AccessState,_Out_ __drv_aliasesMem PAUX_ACCESS_DATA AuxData,_In_ ACCESS_MASK Access,_In_ PGENERIC_MAPPING GenericMapping)43 SeCreateAccessStateEx(
44 _In_ PETHREAD Thread,
45 _In_ PEPROCESS Process,
46 _Out_ PACCESS_STATE AccessState,
47 _Out_ __drv_aliasesMem 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->PrivilegesUsed = (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[out] AccessState
105 * An initialized returned parameter to an access state.
106 *
107 * @param[out] 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
SeCreateAccessState(_Out_ PACCESS_STATE AccessState,_Out_ __drv_aliasesMem PAUX_ACCESS_DATA AuxData,_In_ ACCESS_MASK Access,_In_ PGENERIC_MAPPING GenericMapping)121 SeCreateAccessState(
122 _Out_ PACCESS_STATE AccessState,
123 _Out_ __drv_aliasesMem 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
SeDeleteAccessState(_In_ PACCESS_STATE AccessState)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->PrivilegesUsed, 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
SeSetAccessStateGenericMapping(_In_ PACCESS_STATE AccessState,_In_ PGENERIC_MAPPING GenericMapping)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