xref: /reactos/ntoskrnl/se/subject.c (revision 8b75dce4)
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