VOID SeReleaseSubjectContext ( __inout PSECURITY_SUBJECT_CONTEXT SubjectContext ) /*++ Routine Description: This routine releases a subject security context previously captured by SeCaptureSubjectContext(). Arguments: SubjectContext - Points to a SECURITY_SUBJECT_CONTEXT data structure containing a subject's previously captured security context. Return Value: none. --*/ { PAGED_CODE(); #if DBG || TOKEN_LEAK_MONITOR if (SubjectContext->PrimaryToken) { InterlockedDecrement(&((PTOKEN)(SubjectContext->PrimaryToken))->CaptureCount); if (SubjectContext->PrimaryToken == SepTokenLeakToken) { DbgBreakPoint(); } } if (SubjectContext->ClientToken) { InterlockedDecrement(&((PTOKEN)(SubjectContext->ClientToken))->CaptureCount); if (SubjectContext->ClientToken == SepTokenLeakToken) { DbgBreakPoint(); } } #endif PsDereferencePrimaryTokenEx( PsGetCurrentProcess(), SubjectContext->PrimaryToken ); SubjectContext->PrimaryToken = NULL; PsDereferenceImpersonationToken( SubjectContext->ClientToken ); SubjectContext->ClientToken = NULL; return; }
NTSTATUS SepOpenTokenOfThread( IN HANDLE ThreadHandle, IN BOOLEAN OpenAsSelf, OUT PACCESS_TOKEN *Token, OUT PETHREAD *Thread, OUT PBOOLEAN CopyOnOpen, OUT PBOOLEAN EffectiveOnly, OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel ) /*++ Routine Description: This function does the thread specific processing of an NtOpenThreadToken() service. The service validates that the handle has appropriate access to reference the thread. If so, it goes on to increment the reference count of the token object to prevent it from going away while the rest of the NtOpenThreadToken() request is processed. NOTE: If this call completes successfully, the caller is responsible for decrementing the reference count of the target token. This must be done using PsDereferenceImpersonationToken(). Arguments: ThreadHandle - Supplies a handle to a thread object. OpenAsSelf - Is a boolean value indicating whether the access should be made using the calling thread's current security context, which may be that of a client (if impersonating), or using the caller's process-level security context. A value of FALSE indicates the caller's current context should be used un-modified. A value of TRUE indicates the request should be fulfilled using the process level security context. Token - If successful, receives a pointer to the thread's token object. CopyOnOpen - The current value of the Thread->Client->CopyOnOpen field. EffectiveOnly - The current value of the Thread->Client->EffectiveOnly field. ImpersonationLevel - The current value of the Thread->Client->ImpersonationLevel field. Return Value: STATUS_SUCCESS - Indicates the call completed successfully. STATUS_NO_TOKEN - Indicates the referenced thread is not currently impersonating a client. STATUS_CANT_OPEN_ANONYMOUS - Indicates the client requested anonymous impersonation level. An anonymous token can not be openned. status may also be any value returned by an attemp the reference the thread object for THREAD_QUERY_INFORMATION access. --*/ { NTSTATUS Status; KPROCESSOR_MODE PreviousMode; SE_IMPERSONATION_STATE DisabledImpersonationState; BOOLEAN RestoreImpersonationState = FALSE; PreviousMode = KeGetPreviousMode(); // // Disable impersonation if necessary // if (OpenAsSelf) { RestoreImpersonationState = PsDisableImpersonation( PsGetCurrentThread(), &DisabledImpersonationState ); } // // Make sure the handle grants the appropriate access to the specified // thread. // Status = ObReferenceObjectByHandle( ThreadHandle, THREAD_QUERY_INFORMATION, PsThreadType, PreviousMode, (PVOID *)Thread, NULL ); if (RestoreImpersonationState) { PsRestoreImpersonation( PsGetCurrentThread(), &DisabledImpersonationState ); } if (!NT_SUCCESS(Status)) { return Status; } // // Reference the impersonation token, if there is one // (*Token) = PsReferenceImpersonationToken( *Thread, CopyOnOpen, EffectiveOnly, ImpersonationLevel ); // // Make sure there is a token // if ((*Token) == NULL) { ObDereferenceObject( *Thread ); (*Thread) = NULL; return STATUS_NO_TOKEN; } // // Make sure the ImpersonationLevel is high enough to allow // the token to be openned. // if ((*ImpersonationLevel) <= SecurityAnonymous) { PsDereferenceImpersonationToken( (*Token) ); ObDereferenceObject( *Thread ); (*Thread) = NULL; (*Token) = NULL; return STATUS_CANT_OPEN_ANONYMOUS; } return STATUS_SUCCESS; }