170 lines
3.9 KiB
C
170 lines
3.9 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
|
||
//
|
||
|
||
SeImpersonateClient( &ClientSecurityContext, ServerThread );
|
||
SeDeleteClientSecurity( &ClientSecurityContext );
|
||
|
||
//
|
||
// Done.
|
||
//
|
||
|
||
|
||
ObDereferenceObject( ServerThread );
|
||
ObDereferenceObject( ClientThread );
|
||
return STATUS_SUCCESS;
|
||
}
|