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 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 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 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 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 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