1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Security subject context support routines
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 /* GLOBALS ********************************************************************/
15
16 ERESOURCE SepSubjectContextLock;
17
18 /* PUBLIC FUNCTIONS ***********************************************************/
19
20 /**
21 * @brief
22 * An extended function that captures the security subject context based upon
23 * the specified thread and process.
24 *
25 * @param[in] Thread
26 * A thread where the calling thread's token is to be referenced for
27 * the security context.
28 *
29 * @param[in] Process
30 * A process where the main process' token is to be referenced for
31 * the security context.
32 *
33 * @param[out] SubjectContext
34 * The returned security subject context.
35 *
36 * @return
37 * Nothing.
38 */
39 VOID
40 NTAPI
SeCaptureSubjectContextEx(_In_ PETHREAD Thread,_In_ PEPROCESS Process,_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)41 SeCaptureSubjectContextEx(
42 _In_ PETHREAD Thread,
43 _In_ PEPROCESS Process,
44 _Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
45 {
46 BOOLEAN CopyOnOpen, EffectiveOnly;
47
48 PAGED_CODE();
49
50 /* Save the unique ID */
51 SubjectContext->ProcessAuditId = Process->UniqueProcessId;
52
53 /* Check if we have a thread */
54 if (!Thread)
55 {
56 /* We don't, so no token */
57 SubjectContext->ClientToken = NULL;
58 }
59 else
60 {
61 /* Get the impersonation token */
62 SubjectContext->ClientToken = PsReferenceImpersonationToken(Thread,
63 &CopyOnOpen,
64 &EffectiveOnly,
65 &SubjectContext->ImpersonationLevel);
66 }
67
68 /* Get the primary token */
69 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Process);
70 }
71
72 /**
73 * @brief
74 * Captures the security subject context of the calling thread and calling
75 * process.
76 *
77 * @param[out] SubjectContext
78 * The returned security subject context.
79 *
80 * @return
81 * Nothing.
82 */
83 VOID
84 NTAPI
SeCaptureSubjectContext(_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)85 SeCaptureSubjectContext(
86 _Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
87 {
88 /* Call the extended API */
89 SeCaptureSubjectContextEx(PsGetCurrentThread(),
90 PsGetCurrentProcess(),
91 SubjectContext);
92 }
93
94 /**
95 * @brief
96 * Locks both the referenced primary and client access tokens of a
97 * security subject context.
98 *
99 * @param[in] SubjectContext
100 * A valid security context with both referenced tokens.
101 *
102 * @return
103 * Nothing.
104 */
105 VOID
106 NTAPI
SeLockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)107 SeLockSubjectContext(
108 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
109 {
110 PTOKEN PrimaryToken, ClientToken;
111 PAGED_CODE();
112
113 /* Read both tokens */
114 PrimaryToken = SubjectContext->PrimaryToken;
115 ClientToken = SubjectContext->ClientToken;
116
117 /* Always lock the primary */
118 SepAcquireTokenLockShared(PrimaryToken);
119
120 /* Lock the impersonation one if it's there */
121 if (!ClientToken) return;
122 SepAcquireTokenLockShared(ClientToken);
123 }
124
125 /**
126 * @brief
127 * Unlocks both the referenced primary and client access tokens of a
128 * security subject context.
129 *
130 * @param[in] SubjectContext
131 * A valid security context with both referenced tokens.
132 *
133 * @return
134 * Nothing.
135 */
136 VOID
137 NTAPI
SeUnlockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)138 SeUnlockSubjectContext(
139 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
140 {
141 PTOKEN PrimaryToken, ClientToken;
142 PAGED_CODE();
143
144 /* Read both tokens */
145 PrimaryToken = SubjectContext->PrimaryToken;
146 ClientToken = SubjectContext->ClientToken;
147
148 /* Unlock the impersonation one if it's there */
149 if (ClientToken)
150 {
151 SepReleaseTokenLock(ClientToken);
152 }
153
154 /* Always unlock the primary one */
155 SepReleaseTokenLock(PrimaryToken);
156 }
157
158 /**
159 * @brief
160 * Releases both the primary and client tokens of a security
161 * subject context.
162 *
163 * @param[in] SubjectContext
164 * The captured security context.
165 *
166 * @return
167 * Nothing.
168 */
169 VOID
170 NTAPI
SeReleaseSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)171 SeReleaseSubjectContext(
172 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
173 {
174 PAGED_CODE();
175
176 /* Drop reference on the primary */
177 ObFastDereferenceObject(&PsGetCurrentProcess()->Token, SubjectContext->PrimaryToken);
178 SubjectContext->PrimaryToken = NULL;
179
180 /* Drop reference on the impersonation, if there was one */
181 PsDereferenceImpersonationToken(SubjectContext->ClientToken);
182 SubjectContext->ClientToken = NULL;
183 }
184
185 /* EOF */
186