Windows NT 4.0 source code leak
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

/*++
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 );
}
}
}
}