windows-nt/Source/XPSP1/NT/base/ntos/ps/psimpers.c

165 lines
4.1 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
psimpers.c
Abstract:
This module implements the NtImpersonateThread() service.
Author:
Jim Kelly (JimK) 20-Apr-1991
Revision History:
--*/
#include "psp.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, NtImpersonateThread)
#endif //ALLOC_PRAGMA
NTSTATUS
NtImpersonateThread(
IN HANDLE ServerThreadHandle,
IN HANDLE ClientThreadHandle,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos
)
/*++
Routine Description:
This routine is used to cause the server thread to impersonate the client
thread. The impersonation is done according to the specified quality
of service parameters.
Arguments:
ServerThreadHandle - Is a handle to the server thread (the impersonator, or
doing the impersonation). This handle must be open for
THREAD_IMPERSONATE access.
ClientThreadHandle - Is a handle to the Client thread (the impersonatee, or
one being impersonated). This handle must be open for
THREAD_DIRECT_IMPERSONATION access.
SecurityQos - A pointer to security quality of service information
indicating what form of impersonation is to be performed.
Return Value:
STATUS_SUCCESS - Indicates the call completed successfully.
--*/
{
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PETHREAD ClientThread, ServerThread;
SECURITY_QUALITY_OF_SERVICE CapturedQos;
SECURITY_CLIENT_CONTEXT ClientSecurityContext;
//
// Get previous processor mode and probe and capture arguments if necessary
//
PreviousMode = KeGetPreviousMode();
try {
if (PreviousMode != KernelMode) {
ProbeForReadSmallStructure (SecurityQos,
sizeof (SECURITY_QUALITY_OF_SERVICE),
sizeof (ULONG));
}
CapturedQos = *SecurityQos;
} except (ExSystemExceptionFilter ()) {
return GetExceptionCode ();
}
//
// Reference the client thread, checking for appropriate access.
//
Status = ObReferenceObjectByHandle (ClientThreadHandle, // Handle
THREAD_DIRECT_IMPERSONATION, // DesiredAccess
PsThreadType, // ObjectType
PreviousMode, // AccessMode
&ClientThread, // Object
NULL); // GrantedAccess
if (!NT_SUCCESS (Status)) {
return Status;
}
//
// Reference the client thread, checking for appropriate access.
//
Status = ObReferenceObjectByHandle (ServerThreadHandle, // Handle
THREAD_IMPERSONATE, // DesiredAccess
PsThreadType, // ObjectType
PreviousMode, // AccessMode
&ServerThread, // Object
NULL); // GrantedAccess
if (!NT_SUCCESS (Status)) {
ObDereferenceObject (ClientThread);
return Status;
}
//
// Get the client's security context
//
Status = SeCreateClientSecurity (ClientThread, // ClientThread
&CapturedQos, // SecurityQos
FALSE, // ServerIsRemote
&ClientSecurityContext); // ClientContext
if (!NT_SUCCESS (Status)) {
ObDereferenceObject (ServerThread);
ObDereferenceObject (ClientThread);
return Status;
}
//
// Impersonate the client
//
Status = SeImpersonateClientEx (&ClientSecurityContext, ServerThread);
SeDeleteClientSecurity (&ClientSecurityContext);
//
// Done.
//
ObDereferenceObject (ServerThread);
ObDereferenceObject (ClientThread);
return Status ;
}