STATUS_ACCESS_DENIED on FltCreateFileEx for mapped/network drive

InitializeObjectAttributes( &objectAttributes,
&redirName,
OBJ_KERNEL_HANDLE,
NULL,
NULL );

status = FltCreateFileEx(
MyFltData.Filter,
NULL,
&handle,
NULL,
Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess,
&objectAttributes,
&ioStatus,
(PLARGE_INTEGER) NULL,
Data->Iopb->Parameters.Create.FileAttributes,
Data->Iopb->Parameters.Create.ShareAccess,
FILE_OPEN,
Data->Iopb->Parameters.Create.Options & 0x00ffffff,
Data->Iopb->Parameters.Create.EaBuffer,
Data->Iopb->Parameters.Create.EaLength,
0);

Sorry I inadvertantly posted this message before I had posted any useful information. Please ignore. I’ll post a follow up with the correct question/info.

In my post Create handler in certain situations after a successful Create operation on a volume I am monitoring, I am then calling FltCreateFileEx on a separate volume to obtain a file handle I use later. This seems to work fine on local drives (i.e. \Device\HarddiskXXX) but in the case of mapped network drives (i.e. \Device\LanmanRedirector.…) I am always getting STATUS_ACCESS_DENIED.

I’ve tried various styles of filename but always with the same result.

For the working case of local drives/volumes I’m using names similar to the following:

RtlInitUnicodeString( &FltData.MirrorRoot, L"\Device\HarddiskVolume1\MIRROR" );

RtlInitUnicodeString( &FltData.SecondaryRoot, L"\Device\Harddisk1\DP(1)0-0+5\MIRROR" );

For mapped drives I’ve tried the following:

RtlInitUnicodeString( &FltData.MirrorRoot, L"\Device\LanmanRedirector\machine\share\MIRROR" );

RtlInitUnicodeString( &FltData.MirrorRoot,
L"\Device\LanmanRedirector\;Z:000000000000bf08\machine\share\MIRROR" );

Also tried the above 2 with an addition "" tacked onto the end but I’m always getting STATUS_ACCESS_DENIED.

I’m probably just forgetting something really basic but at the moment I’m stuck. Any suggestions are greatly appreciated. I’ve done a search of the archives but couldn’t find anything obvious.

Thanks. Source code below…

InitializeObjectAttributes( &objectAttributes,
&mirrorFileName,
OBJ_KERNEL_HANDLE,
NULL,
NULL );

status = FltCreateFileEx(FltData.Filter,
NULL,
&shContext->mirrorHandle,
NULL,
Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess,
&objectAttributes,
&ioStatus,
(PLARGE_INTEGER) NULL,
Data->Iopb->Parameters.Create.FileAttributes,
Data->Iopb->Parameters.Create.ShareAccess,
(Data->Iopb->Parameters.Create.Options & 0xff000000) >> 24,
Data->Iopb->Parameters.Create.Options & 0x00ffffff,
Data->Iopb->Parameters.Create.EaBuffer,
Data->Iopb->Parameters.Create.EaLength,
0);

Does the user in which the context of the FltCreateFile command will run
have permission to create files on the mapped drive?
For example the local admin account on the client machine…

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@yahoo.com
Sent: 20 February 2008 16:27
To: Windows File Systems Devs Interest List
Subject: [ntfsd] STATUS_ACCESS_DENIED on FltCreateFileEx for
mapped/network drive

*** WARNING ***

This mail has originated outside your organization, either from an
external partner or the Global Internet.
Keep this in mind if you answer this message.

In my post Create handler in certain situations after a successful
Create operation on a volume I am monitoring, I am then calling
FltCreateFileEx on a separate volume to obtain a file handle I use
later. This seems to work fine on local drives (i.e.
\Device\HarddiskXXX) but in the case of mapped network drives (i.e.
\Device\LanmanRedirector.…) I am always getting STATUS_ACCESS_DENIED.

I’ve tried various styles of filename but always with the same result.

For the working case of local drives/volumes I’m using names similar to
the following:

RtlInitUnicodeString( &FltData.MirrorRoot,
L"\Device\HarddiskVolume1\MIRROR" );

RtlInitUnicodeString( &FltData.SecondaryRoot,
L"\Device\Harddisk1\DP(1)0-0+5\MIRROR" );

For mapped drives I’ve tried the following:

RtlInitUnicodeString( &FltData.MirrorRoot,
L"\Device\LanmanRedirector\machine\share\MIRROR" );

RtlInitUnicodeString( &FltData.MirrorRoot,
L"\Device\LanmanRedirector\;Z:000000000000bf08\machine\share\MIRRO
R" );

Also tried the above 2 with an addition "" tacked onto the end but I’m
always getting STATUS_ACCESS_DENIED.

I’m probably just forgetting something really basic but at the moment
I’m stuck. Any suggestions are greatly appreciated. I’ve done a search
of the archives but couldn’t find anything obvious.

Thanks. Source code below…

InitializeObjectAttributes( &objectAttributes,
&mirrorFileName,
OBJ_KERNEL_HANDLE,
NULL,
NULL );

status = FltCreateFileEx(FltData.Filter,
NULL,
&shContext->mirrorHandle,
NULL,
Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess,
&objectAttributes,
&ioStatus,
(PLARGE_INTEGER) NULL,
Data->Iopb->Parameters.Create.FileAttributes,
Data->Iopb->Parameters.Create.ShareAccess,
(Data->Iopb->Parameters.Create.Options & 0xff000000) >> 24,
Data->Iopb->Parameters.Create.Options & 0x00ffffff,
Data->Iopb->Parameters.Create.EaBuffer,
Data->Iopb->Parameters.Create.EaLength,
0);


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars (including our new
fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@baesystems.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************

Some notes on my configuration:

MachineA is a remote server providing share “SHARED” containing subdirectory named “MIRROR”. Currently ALL access is granted to Everyone for this share.

MachineB is the machine on which my filter driver is running. It has a Z: drive mapped to \MachineA\SHARED using Adminstrator user.

Besides being a client to MachineA, MachineB is also a server providing a share named “PRIMARY” (i.e. \MachineB\PRIMARY) that also grants All access to Everyone.

All I/O that we are interested in comes from remote users (Administrator in this case) that have a mapped drive to \MachineB\PRIMARY. So when we see a remote user do Create on PRIMARY on MachineB in post Create I then try to do the FltCreateFileEx using equivalent input parameters to \MachineA\SHARED\MIRROR using the filename(s) that I mentioned originally (i.e. \Device\LanmanRedirector…).

So I would think the user context in which the FltCreateFileEx is running would be the local Administrator since this the user account used by the remote machine that mapped the drive to \MachineB\PRIMARY. Currently the Administrator accounts on both MachineA and MachineB have the same passwords.

Probably providing way to much detail but I didn’t want to miss anything that might shed some light.

Thanks for your help.

Calls to FSD from SRV are executed in impersonation context, where you have
PrimaryToken as LocalSystem and ClientToken as (your case) Administrator.

Probably FltCreateFileEx loses this impersonation and remains with
PrimaryToken only, which means it tries to access SMB from LocalSystem, and
this is not supported even for Everyone-accessible shares, since LocalSystem
cannot run the SMB logon sequence (maybe allowing Guest on the file server will
help, but this seems to be an overkill).


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntfsd…
> Some notes on my configuration:
>
> MachineA is a remote server providing share “SHARED” containing subdirectory
named “MIRROR”. Currently ALL access is granted to Everyone for this share.
>
> MachineB is the machine on which my filter driver is running. It has a Z:
drive mapped to \MachineA\SHARED using Adminstrator user.
>
> Besides being a client to MachineA, MachineB is also a server providing a
share named “PRIMARY” (i.e. \MachineB\PRIMARY) that also grants All access to
Everyone.
>
> All I/O that we are interested in comes from remote users (Administrator in
this case) that have a mapped drive to \MachineB\PRIMARY. So when we see a
remote user do Create on PRIMARY on MachineB in post Create I then try to do
the FltCreateFileEx using equivalent input parameters to
\MachineA\SHARED\MIRROR using the filename(s) that I mentioned originally
(i.e. \Device\LanmanRedirector…).
>
> So I would think the user context in which the FltCreateFileEx is running
would be the local Administrator since this the user account used by the remote
machine that mapped the drive to \MachineB\PRIMARY. Currently the
Administrator accounts on both MachineA and MachineB have the same passwords.
>
> Probably providing way to much detail but I didn’t want to miss anything that
might shed some light.
>
> Thanks for your help.
>
>
>

Thanks Maxim for the information.

So what is the best way to do this or is there not a good way to redirect local I/O that came from a remote user to a network/lanmanredirector volume such that the ClientToken is used instead of the PrimaryToken?

Should I expect ZwCreateFile to handle this situation any differently than FltCreateFileEx?

Try IoCreateFile, there is much hope SRV itself uses it.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntfsd…
> Thanks Maxim for the information.
>
> So what is the best way to do this or is there not a good way to redirect
local I/O that came from a remote user to a network/lanmanredirector volume
such that the ClientToken is used instead of the PrimaryToken?
>
> Should I expect ZwCreateFile to handle this situation any differently than
FltCreateFileEx?
>
>
>

Thanks for the suggestion Maxim. Unfortunately I get the same error (STATUS_ACCESS_DENIED) using IoCreateFile. I’ll keep tinkering around and if I find anything that works I’ll post an update. Any other suggestions are greatly appreciated.

It seems that you must explicitly impersonate before you call FltCreateFileEx, because I think the client token is only in IRP but it is not set up in current thread for you. Use !token command to verify how are tokens setup for current thread. For impersonation you should use SecurityContext->AccessState->SubjectSecurityContext and following API:
SeCreateClientSecurityFromSubjectContext(), SeImpersonateClientEx(), SeDeleteClientSecurity().
For reverting of impersonation use SeImpersonateClientEx(NULL).
Also I think you need the client allows you SecurityDelegation impersonation level, but I don’t know how to say to SMB redirector which level it should use for creation of token. You can try to create your own SecurityQualityOfService (not from IRP SP) with SecurityDelegation impersonation level and you will see if all APIs will succeed. Here is how it should be initialized

void InitSecurityQualityOfService(PSECURITY_QUALITY_OF_SERVICE ClientSecurityQos)
{
ClientSecurityQos->Length = sizeof(ClientSecurityQos);
ClientSecurityQos->ImpersonationLevel = SecurityDelegation;
ClientSecurityQos->ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
ClientSecurityQos->EffectiveOnly = FALSE;
}

Good luck
-bg

Thanks for the suggestion Bronislav. I will experiment with this and see if I can find a workable solution.

> Also I think you need the client allows you SecurityDelegation impersonation
level,

This works with Kerberos only, i.e. between machines from the same Active
Directory forest.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com