Doing a remote read from IRP_MJ_CREATE

Hi all,

We are writing a filter driver and are having problems ( like many before by
the looks of it :wink: )
We are trying to read from file in a completion routine when we receive
IRP_MJ_CREATE requests,
so that we can identify files we need to decrypt. (we have a header on our
files)
In the completion routine for the create we queue a work item to try and do
the read from and return STATUS_MORE_PROCESSING_REQUIRED.
In the worker function we use IoBuildSynchronousFsdRequest to create an IRP
for the read and send it on.

This all works fine in almost every circumstanceā€¦ except when filtering
LanmanRedirector.
Sometimes the read fails with STATUS_ACCESS_DENIED (0xC0000022).

Helpā€¦ does anyone have any ideas? Possibly something to do with security?

We have tried SeCreateClientSecurity & SeImpersonateClient to no avail.

We have pasted the offending chunk of code below.

Thanks for any assitanceā€¦

Rob Linegar & Duncan Hume
Software Engineers
Data Encryption Systems Limited

// Running in the context of a worker thread - using ExInitializeWorkItem &
ExQueueWorkItem
void FSFil_FileCreateWorker( PFILE_CREATE_CONTEXT pContext )
{
PDEVICE_OBJECT pTargetDeviceObject;
char *pBuffer;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER ByteOffset;
LARGE_INTEGER OrigByteOffset;
PFILE_OBJECT pFileObject;

pFileObject = IoGetCurrentIrpStackLocation( pContext->pOriginalIrp
)->FileObject;

// Get the Previous filtered device object
pTargetDeviceObject =
((PFSFIL_DEVICEEXTENSION)pContext->pDeviceObject->DeviceExtension)->pPrevDev
iceObject;

// No point in continuing if there is no FileObject
if (pFileObject)
{
// Allocate memory for our Buffer
pBuffer = ExAllocatePool( NonPagedPool, 10 );
if (pBuffer)
{
ByteOffset.QuadPart = 0;
// Store the original byte offset
OrigByteOffset = pFileObject->CurrentByteOffset;

FO_ReadFile( pContext->pOriginalIrp,
pTargetDeviceObject, pFileObject, &ByteOffset, 5, pBuffer, &IoStatusBlock );

// Restore the original byte offset
pFileObject->CurrentByteOffset = OrigByteOffset;

if (NT_SUCCESS(IoStatusBlock.Status))
{
}
else
{
///FAILS
}

// Free our read buffer
ExFreePool( pBuffer );
}
}

// Complete the Create Request
IoCompleteRequest( pContext->pOriginalIrp, IO_NO_INCREMENT );

// Free the create context data
ExFreePool( pContext );
}

VOID FO_ReadFile( PIRP pIrp, PDEVICE_OBJECT pDeviceObject, PFILE_OBJECT
pFileObject, PLARGE_INTEGER Offset, ULONG Length, char * pBuffer,
PIO_STATUS_BLOCK IoStatusBlock )
{
KEVENT kEvent;
PIRP pReadIrp;
NTSTATUS ntStatus;

// Initialise an event to wait for after calling the previous driver
KeInitializeEvent( &kEvent, NotificationEvent, FALSE );

// Build an Irp for the read
pReadIrp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, pDeviceObject,
pBuffer, Length, Offset, &kEvent, IoStatusBlock );
if (pReadIrp)
{
PIO_STACK_LOCATION pReadStack = IoGetNextIrpStackLocation(
pReadIrp );

// Caching? no thank you maam!
pReadIrp->Flags = IRP_NOCACHE | IRP_READ_OPERATION;

pReadIrp->Tail.Overlay.Thread = pIrp->Tail.Overlay.Thread;
pReadIrp->RequestorMode = KernelMode;

// We need a FileObject to identify the file we are reading
pReadStack->FileObject = pFileObject;
pReadStack->DeviceObject = pDeviceObject;

// Call on to the previous driver
ntStatus = IoCallDriver( pDeviceObject, pReadIrp );
if (ntStatus == STATUS_PENDING)
{
// Wait for the Irp to complete if it is pending
KeWaitForSingleObject( &kEvent, Executive,
KernelMode, FALSE, NULL );
}
else
IoStatusBlock->Status = ntStatus;
}
else
{
IoStatusBlock->Status =
STATUS_INSUFFICIENT_RESOURCES;
IoStatusBlock->Information = 0;
}
}

// Copyright Dunk & Rob aka DES Massive

Are you being able to read at any time without using impersonation ?

In a work item you are running under a SYSTEM thread security context so you
should not be able to access remote files at all. You should impersonate
originating thread to access remote files.

How exactly are you using impersonation ? Maybe the key of the problem is
here ?

At 19:05 24/03/00 -0000, you wrote:

Hi all,

We are writing a filter driver and are having problems ( like many before by
the looks of it :wink: )
We are trying to read from file in a completion routine when we receive
IRP_MJ_CREATE requests,
so that we can identify files we need to decrypt. (we have a header on our
files)
In the completion routine for the create we queue a work item to try and do
the read from and return STATUS_MORE_PROCESSING_REQUIRED.
In the worker function we use IoBuildSynchronousFsdRequest to create an IRP
for the read and send it on.

This all works fine in almost every circumstanceā€¦ except when filtering
LanmanRedirector.
Sometimes the read fails with STATUS_ACCESS_DENIED (0xC0000022).

Helpā€¦ does anyone have any ideas? Possibly something to do with security?

We have tried SeCreateClientSecurity & SeImpersonateClient to no avail.

We have pasted the offending chunk of code below.

Thanks for any assitanceā€¦

Rob Linegar & Duncan Hume
Software Engineers
Data Encryption Systems Limited

// Running in the context of a worker thread - using ExInitializeWorkItem &
ExQueueWorkItem
void FSFil_FileCreateWorker( PFILE_CREATE_CONTEXT pContext )
{
PDEVICE_OBJECT pTargetDeviceObject;
char *pBuffer;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER ByteOffset;
LARGE_INTEGER OrigByteOffset;
PFILE_OBJECT pFileObject;

pFileObject = IoGetCurrentIrpStackLocation( pContext->pOriginalIrp
)->FileObject;

// Get the Previous filtered device object
pTargetDeviceObject =
((PFSFIL_DEVICEEXTENSION)pContext->pDeviceObject->DeviceExtension)->pPrevDev
iceObject;

// No point in continuing if there is no FileObject
if (pFileObject)
{
// Allocate memory for our Buffer
pBuffer = ExAllocatePool( NonPagedPool, 10 );
if (pBuffer)
{
ByteOffset.QuadPart = 0;
// Store the original byte offset
OrigByteOffset = pFileObject->CurrentByteOffset;

FO_ReadFile( pContext->pOriginalIrp,
pTargetDeviceObject, pFileObject, &ByteOffset, 5, pBuffer, &IoStatusBlock );

// Restore the original byte offset
pFileObject->CurrentByteOffset = OrigByteOffset;

if (NT_SUCCESS(IoStatusBlock.Status))
{
}
else
{
///FAILS
}

// Free our read buffer
ExFreePool( pBuffer );
}
}

// Complete the Create Request
IoCompleteRequest( pContext->pOriginalIrp, IO_NO_INCREMENT );

// Free the create context data
ExFreePool( pContext );
}

VOID FO_ReadFile( PIRP pIrp, PDEVICE_OBJECT pDeviceObject, PFILE_OBJECT
pFileObject, PLARGE_INTEGER Offset, ULONG Length, char * pBuffer,
PIO_STATUS_BLOCK IoStatusBlock )
{
KEVENT kEvent;
PIRP pReadIrp;
NTSTATUS ntStatus;

// Initialise an event to wait for after calling the previous driver
KeInitializeEvent( &kEvent, NotificationEvent, FALSE );

// Build an Irp for the read
pReadIrp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, pDeviceObject,
pBuffer, Length, Offset, &kEvent, IoStatusBlock );
if (pReadIrp)
{
PIO_STACK_LOCATION pReadStack = IoGetNextIrpStackLocation(
pReadIrp );

// Caching? no thank you maam!
pReadIrp->Flags = IRP_NOCACHE | IRP_READ_OPERATION;

pReadIrp->Tail.Overlay.Thread = pIrp->Tail.Overlay.Thread;
pReadIrp->RequestorMode = KernelMode;

// We need a FileObject to identify the file we are reading
pReadStack->FileObject = pFileObject;
pReadStack->DeviceObject = pDeviceObject;

// Call on to the previous driver
ntStatus = IoCallDriver( pDeviceObject, pReadIrp );
if (ntStatus == STATUS_PENDING)
{
// Wait for the Irp to complete if it is pending
KeWaitForSingleObject( &kEvent, Executive,
KernelMode, FALSE, NULL );
}
else
IoStatusBlock->Status = ntStatus;
}
else
{
IoStatusBlock->Status =
STATUS_INSUFFICIENT_RESOURCES;
IoStatusBlock->Information = 0;
}
}

// Copyright Dunk & Rob aka DES Massive


You are currently subscribed to ntfsd as: xxxxx@lander.es
To unsubscribe send a blank email to $subst(ā€˜Email.Unsubā€™)