mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
5.0 KiB
190 lines
5.0 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
lpcpriv.c
|
|
|
|
Abstract:
|
|
|
|
Local Inter-Process Communication priviledged procedures that implement
|
|
client impersonation.
|
|
|
|
Author:
|
|
|
|
Steve Wood (stevewo) 15-Nov-1989
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "lpcp.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,LpcpFreePortClientSecurity)
|
|
#pragma alloc_text(PAGE,NtImpersonateClientOfPort)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
NtImpersonateClientOfPort(
|
|
IN HANDLE PortHandle,
|
|
IN PPORT_MESSAGE Message
|
|
)
|
|
{
|
|
PLPCP_PORT_OBJECT PortObject;
|
|
PLPCP_PORT_OBJECT ConnectedPort;
|
|
KPROCESSOR_MODE PreviousMode;
|
|
NTSTATUS Status;
|
|
PETHREAD ClientThread;
|
|
CLIENT_ID CapturedClientId;
|
|
ULONG CapturedMessageId;
|
|
SECURITY_CLIENT_CONTEXT DynamicSecurity;
|
|
|
|
PAGED_CODE();
|
|
//
|
|
// Get previous processor mode and probe output arguments if necessary.
|
|
//
|
|
|
|
PreviousMode = KeGetPreviousMode();
|
|
if (PreviousMode != KernelMode) {
|
|
try {
|
|
ProbeForRead( Message, sizeof( PORT_MESSAGE ), sizeof( ULONG ) );
|
|
CapturedClientId = Message->ClientId;
|
|
CapturedMessageId = Message->MessageId;
|
|
}
|
|
except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
return( GetExceptionCode() );
|
|
}
|
|
}
|
|
else {
|
|
CapturedClientId = Message->ClientId;
|
|
CapturedMessageId = Message->MessageId;
|
|
}
|
|
|
|
//
|
|
// Reference the communication port object by handle. Return status if
|
|
// unsuccessful.
|
|
//
|
|
|
|
Status = LpcpReferencePortObject( PortHandle, 0,
|
|
PreviousMode, &PortObject );
|
|
if (!NT_SUCCESS( Status )) {
|
|
return( Status );
|
|
}
|
|
|
|
//
|
|
// Error if a port type is invalid.
|
|
//
|
|
|
|
if ((PortObject->Flags & PORT_TYPE) != SERVER_COMMUNICATION_PORT) {
|
|
ObDereferenceObject( PortObject );
|
|
return( STATUS_INVALID_PORT_HANDLE );
|
|
}
|
|
|
|
//
|
|
// Translate the ClientId from the connection request into a
|
|
// thread pointer. This is a referenced pointer to keep the thread
|
|
// from evaporating out from under us.
|
|
//
|
|
|
|
Status = PsLookupProcessThreadByCid( &CapturedClientId,
|
|
NULL,
|
|
&ClientThread
|
|
);
|
|
if (!NT_SUCCESS( Status )) {
|
|
ObDereferenceObject( PortObject );
|
|
return( Status );
|
|
}
|
|
|
|
//
|
|
// Acquire the mutex that gaurds the LpcReplyMessage field of
|
|
// the thread and get the pointer to the message that the thread
|
|
// is waiting for a reply to.
|
|
//
|
|
|
|
ExAcquireFastMutex( &LpcpLock );
|
|
|
|
if (PortObject->ConnectedPort == NULL) {
|
|
ExReleaseFastMutex( &LpcpLock );
|
|
ObDereferenceObject( PortObject );
|
|
ObDereferenceObject( ClientThread );
|
|
return( STATUS_PORT_DISCONNECTED );
|
|
}
|
|
ConnectedPort = PortObject->ConnectedPort;
|
|
ObReferenceObject( ConnectedPort );
|
|
|
|
//
|
|
// See if the thread is waiting for a reply to the message
|
|
// specified on this call. If not then a bogus message
|
|
// has been specified, so return failure.
|
|
//
|
|
|
|
if (ClientThread->LpcReplyMessageId != CapturedMessageId) {
|
|
ExReleaseFastMutex( &LpcpLock );
|
|
ObDereferenceObject( PortObject );
|
|
ObDereferenceObject( ClientThread );
|
|
ObDereferenceObject( ConnectedPort );
|
|
return (STATUS_REPLY_MESSAGE_MISMATCH);
|
|
}
|
|
ExReleaseFastMutex( &LpcpLock );
|
|
|
|
//
|
|
// If the client requested dynamic security tracking, then the client
|
|
// security needs to be referenced. Otherwise, (static case)
|
|
// it is already in the client's port.
|
|
//
|
|
|
|
if (ConnectedPort->Flags & PORT_DYNAMIC_SECURITY) {
|
|
|
|
//
|
|
// Impersonate the client with information from the queued message
|
|
//
|
|
|
|
Status = LpcpGetDynamicClientSecurity( ClientThread,
|
|
PortObject->ConnectedPort,
|
|
&DynamicSecurity
|
|
);
|
|
if (!NT_SUCCESS( Status )) {
|
|
ObDereferenceObject( PortObject );
|
|
ObDereferenceObject( ClientThread );
|
|
ObDereferenceObject( ConnectedPort );
|
|
return( Status );
|
|
}
|
|
|
|
SeImpersonateClient( &DynamicSecurity, NULL );
|
|
LpcpFreeDynamicClientSecurity( &DynamicSecurity );
|
|
|
|
}
|
|
else {
|
|
|
|
//
|
|
// Impersonate the client with information from the client's port
|
|
//
|
|
|
|
SeImpersonateClient( &ConnectedPort->StaticSecurity, NULL );
|
|
|
|
}
|
|
|
|
ObDereferenceObject( PortObject );
|
|
ObDereferenceObject( ClientThread );
|
|
ObDereferenceObject( ConnectedPort );
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
VOID
|
|
LpcpFreePortClientSecurity(
|
|
IN PLPCP_PORT_OBJECT Port
|
|
)
|
|
{
|
|
if ((Port->Flags & PORT_TYPE) == CLIENT_COMMUNICATION_PORT) {
|
|
if (!(Port->Flags & PORT_DYNAMIC_SECURITY)) {
|
|
if ( Port->StaticSecurity.ClientToken ) {
|
|
SeDeleteClientSecurity( &(Port)->StaticSecurity );
|
|
}
|
|
}
|
|
}
|
|
}
|