xref: /reactos/ntoskrnl/se/access.c (revision 9cfd8dd9)
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