Windows2000/private/ntos/ps/psimpers.c
2020-09-30 17:12:32 +02:00

172 lines
3.8 KiB
C

/*++
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"
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();
if (PreviousMode != KernelMode) {
try {
ProbeForRead( SecurityQos,
sizeof( SECURITY_QUALITY_OF_SERVICE ),
sizeof( ULONG )
);
CapturedQos = (*SecurityQos);
} except( EXCEPTION_EXECUTE_HANDLER ) {
return( GetExceptionCode() );
}
} else {
CapturedQos = *SecurityQos;
}
// Reference the client thread, checking for appropriate access.
Status = ObReferenceObjectByHandle(
ClientThreadHandle, // Handle
THREAD_DIRECT_IMPERSONATION, // DesiredAccess
PsThreadType, // ObjectType
PreviousMode, // AccessMode
(PVOID *)&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
(PVOID *)&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 ;
}