dll: create.c: refactoring

This commit is contained in:
Bill Zissimopoulos 2016-01-04 21:46:02 -08:00
parent 5eaa6b03ae
commit d2eabf4e05
5 changed files with 343 additions and 316 deletions

View File

@ -24,7 +24,6 @@
<ClInclude Include="..\..\src\dll\library.h" /> <ClInclude Include="..\..\src\dll\library.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\src\dll\access.c" />
<ClCompile Include="..\..\src\dll\cleanup.c" /> <ClCompile Include="..\..\src\dll\cleanup.c" />
<ClCompile Include="..\..\src\dll\close.c" /> <ClCompile Include="..\..\src\dll\close.c" />
<ClCompile Include="..\..\src\dll\create.c" /> <ClCompile Include="..\..\src\dll\create.c" />

View File

@ -43,9 +43,6 @@
<ClCompile Include="..\..\src\dll\create.c"> <ClCompile Include="..\..\src\dll\create.c">
<Filter>Source</Filter> <Filter>Source</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\dll\access.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="..\..\src\dll\path.c"> <ClCompile Include="..\..\src\dll\path.c">
<Filter>Source</Filter> <Filter>Source</Filter>
</ClCompile> </ClCompile>

View File

@ -50,9 +50,6 @@ typedef VOID FSP_FILE_SYSTEM_DISPATCHER(FSP_FILE_SYSTEM *, FSP_FSCTL_TRANSACT_RE
typedef NTSTATUS FSP_FILE_SYSTEM_OPERATION(FSP_FILE_SYSTEM *, FSP_FSCTL_TRANSACT_REQ *); typedef NTSTATUS FSP_FILE_SYSTEM_OPERATION(FSP_FILE_SYSTEM *, FSP_FSCTL_TRANSACT_REQ *);
typedef struct _FSP_FILE_SYSTEM_INTERFACE typedef struct _FSP_FILE_SYSTEM_INTERFACE
{ {
NTSTATUS (*AccessCheck)(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
DWORD DesiredAccess, PDWORD PGrantedAccess);
NTSTATUS (*GetSecurity)(FSP_FILE_SYSTEM *FileSystem, NTSTATUS (*GetSecurity)(FSP_FILE_SYSTEM *FileSystem,
PWSTR FileName, PDWORD PFileAttributes, PWSTR FileName, PDWORD PFileAttributes,
PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize); PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize);
@ -149,6 +146,24 @@ FSP_API NTSTATUS FspFileSystemSendResponseWithStatus(FSP_FILE_SYSTEM *FileSystem
/* /*
* File System Operations * File System Operations
*/ */
FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID);
FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
DWORD DesiredAccess, PDWORD PGrantedAccess);
FSP_API NTSTATUS FspShareCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode);
FSP_API NTSTATUS FspFileSystemPreCreateCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess);
FSP_API VOID FspFileSystemPostCreateCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode);
FSP_API NTSTATUS FspFileSystemPreOpenCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess);
FSP_API NTSTATUS FspFileSystemPostOpenCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode);
FSP_API NTSTATUS FspFileSystemPreOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess);
FSP_API NTSTATUS FspFileSystemPostOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode);
FSP_API NTSTATUS FspFileSystemOpCreate(FSP_FILE_SYSTEM *FileSystem, FSP_API NTSTATUS FspFileSystemOpCreate(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request); FSP_FSCTL_TRANSACT_REQ *Request);
FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem, FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
@ -163,16 +178,6 @@ FSP_API NTSTATUS FspFileSystemSendCloseResponse(FSP_FILE_SYSTEM *FileSystem,
FSP_API NTSTATUS FspFileSystemSendCleanupResponse(FSP_FILE_SYSTEM *FileSystem, FSP_API NTSTATUS FspFileSystemSendCleanupResponse(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request); FSP_FSCTL_TRANSACT_REQ *Request);
/*
* Access Checks
*/
FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID);
FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
DWORD DesiredAccess, PDWORD PGrantedAccess);
FSP_API NTSTATUS FspShareCheck(FSP_FILE_SYSTEM *FileSystem,
DWORD GrantedAccess, DWORD ShareAccess, FSP_FILE_NODE *FileNode);
/* /*
* Path Handling * Path Handling
*/ */

View File

@ -1,213 +0,0 @@
/**
* @file dll/access.c
*
* @copyright 2015 Bill Zissimopoulos
*/
#include <dll/library.h>
static GENERIC_MAPPING FspFileGenericMapping =
{
.GenericRead = FILE_GENERIC_READ,
.GenericWrite = FILE_GENERIC_WRITE,
.GenericExecute = FILE_GENERIC_EXECUTE,
.GenericAll = FILE_ALL_ACCESS,
};
FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID)
{
return &FspFileGenericMapping;
}
static NTSTATUS FspGetSecurity(FSP_FILE_SYSTEM *FileSystem,
PWSTR FileName, PDWORD PFileAttributes,
PSECURITY_DESCRIPTOR *PSecurityDescriptor, SIZE_T *PSecurityDescriptorSize)
{
for (;;)
{
NTSTATUS Result = FileSystem->Interface->GetSecurity(FileSystem,
FileName, PFileAttributes, *PSecurityDescriptor, PSecurityDescriptorSize);
if (STATUS_BUFFER_OVERFLOW != Result)
return Result;
MemFree(*PSecurityDescriptor);
*PSecurityDescriptor = MemAlloc(*PSecurityDescriptorSize);
if (0 == *PSecurityDescriptor)
return STATUS_INSUFFICIENT_RESOURCES;
}
}
FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
DWORD DesiredAccess, PDWORD PGrantedAccess)
{
if (0 != FileSystem->Interface->AccessCheck)
return FileSystem->Interface->AccessCheck(FileSystem,
Request, CheckParentDirectory, AllowTraverseCheck, DesiredAccess, PGrantedAccess);
if (0 == FileSystem->Interface->GetSecurity)
{
*PGrantedAccess = DesiredAccess;
return STATUS_SUCCESS;
}
NTSTATUS Result;
PWSTR Parent, Suffix;
DWORD FileAttributes;
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
SIZE_T SecurityDescriptorSize;
DWORD PrivilegeSetLength;
BOOL AccessStatus;
*PGrantedAccess = 0;
if (CheckParentDirectory)
FspPathSuffix((PWSTR)Request->Buffer, &Parent, &Suffix);
SecurityDescriptorSize = 1024;
SecurityDescriptor = MemAlloc(SecurityDescriptorSize);
if (0 == SecurityDescriptor)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
if (AllowTraverseCheck && !Request->Req.Create.HasTraversePrivilege)
{
PWSTR Path = (PWSTR)Request->Buffer, Prefix;
DWORD TraverseAccess;
for (;;)
{
FspPathPrefix(Path, &Prefix, &Path);
if (L'\0' == Path[0])
{
FspPathCombine((PWSTR)Request->Buffer, Path);
break;
}
Prefix = L'\0' == Prefix[0] ? L"\\" : (PWSTR)Request->Buffer;
Result = FspGetSecurity(FileSystem, Prefix, 0,
&SecurityDescriptor, &SecurityDescriptorSize);
FspPathCombine((PWSTR)Request->Buffer, Path);
if (!NT_SUCCESS(Result))
{
if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
Result = STATUS_OBJECT_PATH_NOT_FOUND;
goto exit;
}
if (AccessCheck(SecurityDescriptor, (HANDLE)Request->Req.Create.AccessToken, FILE_TRAVERSE,
&FspFileGenericMapping, 0, &PrivilegeSetLength, &TraverseAccess, &AccessStatus))
Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
else
Result = FspNtStatusFromWin32(GetLastError());
if (!NT_SUCCESS(Result))
goto exit;
}
}
Result = FspGetSecurity(FileSystem, (PWSTR)Request->Buffer, &FileAttributes,
&SecurityDescriptor, &SecurityDescriptorSize);
if (!NT_SUCCESS(Result))
goto exit;
if (CheckParentDirectory)
{
if (0 == (FileAttributes && FILE_ATTRIBUTE_DIRECTORY))
return STATUS_NOT_A_DIRECTORY;
}
else
{
if ((Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE) &&
0 == (FileAttributes && FILE_ATTRIBUTE_DIRECTORY))
return STATUS_NOT_A_DIRECTORY;
if ((Request->Req.Create.CreateOptions & FILE_NON_DIRECTORY_FILE) &&
0 != (FileAttributes && FILE_ATTRIBUTE_DIRECTORY))
return STATUS_NOT_A_DIRECTORY;
}
if (0 != (FileAttributes && FILE_ATTRIBUTE_READONLY))
{
if (DesiredAccess &
(FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD))
{
Result = STATUS_ACCESS_DENIED;
goto exit;
}
if (Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE)
{
Result = STATUS_CANNOT_DELETE;
goto exit;
}
}
if (AccessCheck(SecurityDescriptor, (HANDLE)Request->Req.Create.AccessToken, DesiredAccess,
&FspFileGenericMapping, 0, &PrivilegeSetLength, PGrantedAccess, &AccessStatus))
Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
else
Result = FspNtStatusFromWin32(GetLastError());
exit:
MemFree(SecurityDescriptor);
if (CheckParentDirectory)
FspPathCombine((PWSTR)Request->Buffer, Suffix);
return Result;
}
FSP_API NTSTATUS FspShareCheck(FSP_FILE_SYSTEM *FileSystem,
DWORD GrantedAccess, DWORD ShareAccess, FSP_FILE_NODE *FileNode)
{
BOOLEAN ReadAccess, WriteAccess, DeleteAccess;
BOOLEAN SharedRead, SharedWrite, SharedDelete;
ULONG OpenCount;
ReadAccess = 0 != (GrantedAccess & (FILE_READ_DATA | FILE_EXECUTE));
WriteAccess = 0 != (GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA));
DeleteAccess = 0 != (GrantedAccess & DELETE);
if (ReadAccess || WriteAccess || DeleteAccess)
{
SharedRead = 0 != (ShareAccess & FILE_SHARE_READ);
SharedWrite = 0 != (ShareAccess & FILE_SHARE_WRITE);
SharedDelete = 0 != (ShareAccess & FILE_SHARE_DELETE);
OpenCount = FileNode->ShareAccess.OpenCount;
/*
* IF ReadAccess AND there are already some exclusive readers
* OR WriteAccess AND there are already some exclusive writers
* OR DeleteAccess AND there are already some exclusive deleters
* OR exclusive read requested AND there are already some readers
* OR exclusive write requested AND there are already some writers
* OR exclusive delete requested AND there are already some deleters
*/
if (ReadAccess && (FileNode->ShareAccess.SharedRead < OpenCount))
return STATUS_SHARING_VIOLATION;
if (WriteAccess && (FileNode->ShareAccess.SharedWrite < OpenCount))
return STATUS_SHARING_VIOLATION;
if (DeleteAccess && (FileNode->ShareAccess.SharedDelete < OpenCount))
return STATUS_SHARING_VIOLATION;
if (!SharedRead && 0 != FileNode->ShareAccess.Readers)
return STATUS_SHARING_VIOLATION;
if (!SharedWrite && 0 != FileNode->ShareAccess.Writers)
return STATUS_SHARING_VIOLATION;
if (!SharedDelete && 0 != FileNode->ShareAccess.Deleters)
return STATUS_SHARING_VIOLATION;
FileNode->ShareAccess.OpenCount++;
FileNode->ShareAccess.Readers += ReadAccess;
FileNode->ShareAccess.Writers += WriteAccess;
FileNode->ShareAccess.Deleters += DeleteAccess;
FileNode->ShareAccess.SharedRead += SharedRead;
FileNode->ShareAccess.SharedWrite += SharedWrite;
FileNode->ShareAccess.SharedDelete += SharedDelete;
}
return STATUS_SUCCESS;
}

View File

@ -6,19 +6,221 @@
#include <dll/library.h> #include <dll/library.h>
static inline static GENERIC_MAPPING FspFileGenericMapping =
BOOLEAN FspIsRootDirectory(PWSTR FileName)
{ {
for (PWSTR Pointer = FileName; *Pointer; Pointer++) .GenericRead = FILE_GENERIC_READ,
if (L'\\' != *Pointer) .GenericWrite = FILE_GENERIC_WRITE,
return FALSE; .GenericExecute = FILE_GENERIC_EXECUTE,
return TRUE; .GenericAll = FILE_ALL_ACCESS,
};
FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID)
{
return &FspFileGenericMapping;
} }
static inline static NTSTATUS FspGetSecurity(FSP_FILE_SYSTEM *FileSystem,
NTSTATUS FspCreateCheck(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, PDWORD PFileAttributes,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PSECURITY_DESCRIPTOR *PSecurityDescriptor, SIZE_T *PSecurityDescriptorSize)
PDWORD PGrantedAccess) {
for (;;)
{
NTSTATUS Result = FileSystem->Interface->GetSecurity(FileSystem,
FileName, PFileAttributes, *PSecurityDescriptor, PSecurityDescriptorSize);
if (STATUS_BUFFER_OVERFLOW != Result)
return Result;
MemFree(*PSecurityDescriptor);
*PSecurityDescriptor = MemAlloc(*PSecurityDescriptorSize);
if (0 == *PSecurityDescriptor)
return STATUS_INSUFFICIENT_RESOURCES;
}
}
FSP_API NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
DWORD DesiredAccess, PDWORD PGrantedAccess)
{
if (0 == FileSystem->Interface->GetSecurity)
{
*PGrantedAccess = DesiredAccess;
return STATUS_SUCCESS;
}
NTSTATUS Result;
PWSTR Parent, Suffix, Prefix, Remain;
DWORD FileAttributes;
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
SIZE_T SecurityDescriptorSize;
DWORD PrivilegeSetLength;
DWORD TraverseAccess;
BOOL AccessStatus;
*PGrantedAccess = 0;
if (CheckParentDirectory)
FspPathSuffix((PWSTR)Request->Buffer, &Parent, &Suffix);
SecurityDescriptorSize = 1024;
SecurityDescriptor = MemAlloc(SecurityDescriptorSize);
if (0 == SecurityDescriptor)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
if (AllowTraverseCheck && !Request->Req.Create.HasTraversePrivilege)
{
Remain = (PWSTR)Request->Buffer;
for (;;)
{
FspPathPrefix(Remain, &Prefix, &Remain);
if (L'\0' == Remain[0])
{
FspPathCombine((PWSTR)Request->Buffer, Remain);
break;
}
Prefix = L'\0' == Prefix[0] ? L"\\" : (PWSTR)Request->Buffer;
Result = FspGetSecurity(FileSystem, Prefix, 0,
&SecurityDescriptor, &SecurityDescriptorSize);
FspPathCombine((PWSTR)Request->Buffer, Remain);
if (!NT_SUCCESS(Result))
{
if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
Result = STATUS_OBJECT_PATH_NOT_FOUND;
goto exit;
}
if (AccessCheck(SecurityDescriptor, (HANDLE)Request->Req.Create.AccessToken, FILE_TRAVERSE,
&FspFileGenericMapping, 0, &PrivilegeSetLength, &TraverseAccess, &AccessStatus))
Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
else
Result = FspNtStatusFromWin32(GetLastError());
if (!NT_SUCCESS(Result))
goto exit;
}
}
Result = FspGetSecurity(FileSystem, (PWSTR)Request->Buffer, &FileAttributes,
&SecurityDescriptor, &SecurityDescriptorSize);
if (!NT_SUCCESS(Result))
goto exit;
if (AccessCheck(SecurityDescriptor, (HANDLE)Request->Req.Create.AccessToken, DesiredAccess,
&FspFileGenericMapping, 0, &PrivilegeSetLength, PGrantedAccess, &AccessStatus))
Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
else
Result = FspNtStatusFromWin32(GetLastError());
if (!NT_SUCCESS(Result))
goto exit;
if (CheckParentDirectory)
{
if (0 == (FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
Result = STATUS_NOT_A_DIRECTORY;
goto exit;
}
}
else
{
if ((Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE) &&
0 == (FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
Result = STATUS_NOT_A_DIRECTORY;
goto exit;
}
if ((Request->Req.Create.CreateOptions & FILE_NON_DIRECTORY_FILE) &&
0 != (FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
Result = STATUS_FILE_IS_A_DIRECTORY;
goto exit;
}
}
if (0 != (FileAttributes & FILE_ATTRIBUTE_READONLY))
{
if (DesiredAccess &
(FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD))
{
Result = STATUS_ACCESS_DENIED;
goto exit;
}
if (Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE)
{
Result = STATUS_CANNOT_DELETE;
goto exit;
}
}
exit:
MemFree(SecurityDescriptor);
if (CheckParentDirectory)
FspPathCombine((PWSTR)Request->Buffer, Suffix);
return Result;
}
FSP_API NTSTATUS FspShareCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode)
{
DWORD ShareAccess = Request->Req.Create.ShareAccess;
BOOLEAN ReadAccess, WriteAccess, DeleteAccess;
BOOLEAN SharedRead, SharedWrite, SharedDelete;
ULONG OpenCount;
ReadAccess = 0 != (GrantedAccess & (FILE_READ_DATA | FILE_EXECUTE));
WriteAccess = 0 != (GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA));
DeleteAccess = 0 != (GrantedAccess & DELETE);
if (ReadAccess || WriteAccess || DeleteAccess)
{
SharedRead = 0 != (ShareAccess & FILE_SHARE_READ);
SharedWrite = 0 != (ShareAccess & FILE_SHARE_WRITE);
SharedDelete = 0 != (ShareAccess & FILE_SHARE_DELETE);
OpenCount = FileNode->ShareAccess.OpenCount;
/*
* IF ReadAccess AND there are already some exclusive readers
* OR WriteAccess AND there are already some exclusive writers
* OR DeleteAccess AND there are already some exclusive deleters
* OR exclusive read requested AND there are already some readers
* OR exclusive write requested AND there are already some writers
* OR exclusive delete requested AND there are already some deleters
*/
if (ReadAccess && (FileNode->ShareAccess.SharedRead < OpenCount))
return STATUS_SHARING_VIOLATION;
if (WriteAccess && (FileNode->ShareAccess.SharedWrite < OpenCount))
return STATUS_SHARING_VIOLATION;
if (DeleteAccess && (FileNode->ShareAccess.SharedDelete < OpenCount))
return STATUS_SHARING_VIOLATION;
if (!SharedRead && 0 != FileNode->ShareAccess.Readers)
return STATUS_SHARING_VIOLATION;
if (!SharedWrite && 0 != FileNode->ShareAccess.Writers)
return STATUS_SHARING_VIOLATION;
if (!SharedDelete && 0 != FileNode->ShareAccess.Deleters)
return STATUS_SHARING_VIOLATION;
FileNode->ShareAccess.OpenCount++;
FileNode->ShareAccess.Readers += ReadAccess;
FileNode->ShareAccess.Writers += WriteAccess;
FileNode->ShareAccess.Deleters += DeleteAccess;
FileNode->ShareAccess.SharedRead += SharedRead;
FileNode->ShareAccess.SharedWrite += SharedWrite;
FileNode->ShareAccess.SharedDelete += SharedDelete;
}
return STATUS_SUCCESS;
}
FSP_API NTSTATUS FspFileSystemPreCreateCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess)
{ {
NTSTATUS Result; NTSTATUS Result;
@ -33,17 +235,73 @@ NTSTATUS FspCreateCheck(FSP_FILE_SYSTEM *FileSystem,
return Result; return Result;
} }
FSP_API VOID FspFileSystemPostCreateCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode)
{
memset(&FileNode->Flags, 0, sizeof FileNode->Flags);
memset(&FileNode->ShareAccess, 0, sizeof FileNode->ShareAccess);
FspShareCheck(FileSystem, Request, GrantedAccess, FileNode);
}
FSP_API NTSTATUS FspFileSystemPreOpenCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess)
{
return FspAccessCheck(FileSystem, Request, FALSE, AllowTraverseCheck,
Request->Req.Create.DesiredAccess, PGrantedAccess);
}
FSP_API NTSTATUS FspFileSystemPostOpenCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode)
{
return FspShareCheck(FileSystem, Request, GrantedAccess, FileNode);
}
FSP_API NTSTATUS FspFileSystemPreOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, PDWORD PGrantedAccess)
{
NTSTATUS Result;
BOOLEAN Supersede = FILE_SUPERSEDE == ((Request->Req.Create.CreateOptions >> 24) & 0xff);
Result = FspAccessCheck(FileSystem, Request, FALSE, AllowTraverseCheck,
Request->Req.Create.DesiredAccess | (Supersede ? DELETE : FILE_WRITE_DATA),
PGrantedAccess);
if (NT_SUCCESS(Result))
{
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
*PGrantedAccess &= Supersede ?
(~DELETE | (Request->Req.Create.DesiredAccess & DELETE)) :
(~FILE_WRITE_DATA | (Request->Req.Create.DesiredAccess & FILE_WRITE_DATA));
}
return Result;
}
FSP_API NTSTATUS FspFileSystemPostOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, DWORD GrantedAccess, FSP_FILE_NODE *FileNode)
{
return FspShareCheck(FileSystem, Request, GrantedAccess, FileNode);
}
static BOOLEAN FspIsRootDirectory(PWSTR FileName)
{
for (PWSTR Pointer = FileName; *Pointer; Pointer++)
if (L'\\' != *Pointer)
return FALSE;
return TRUE;
}
static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem, static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request) FSP_FSCTL_TRANSACT_REQ *Request)
{ {
if (FspIsRootDirectory((PWSTR)Request->Buffer))
return STATUS_ACCESS_DENIED;
NTSTATUS Result; NTSTATUS Result;
DWORD GrantedAccess; DWORD GrantedAccess;
FSP_FILE_NODE *FileNode; FSP_FILE_NODE *FileNode;
Result = FspCreateCheck(FileSystem, Request, TRUE, &GrantedAccess); if (FspIsRootDirectory((PWSTR)Request->Buffer))
return STATUS_ACCESS_DENIED;
Result = FspFileSystemPreCreateCheck(FileSystem, Request, TRUE, &GrantedAccess);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
@ -51,10 +309,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
memset(&FileNode->Flags, 0, sizeof FileNode->Flags); FspFileSystemPostCreateCheck(FileSystem, Request, GrantedAccess, FileNode);
memset(&FileNode->ShareAccess, 0, sizeof FileNode->ShareAccess);
FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode);
return FspFileSystemSendCreateResponse(FileSystem, Request, return FspFileSystemSendCreateResponse(FileSystem, Request,
FILE_CREATED, FileNode, GrantedAccess); FILE_CREATED, FileNode, GrantedAccess);
@ -67,8 +322,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem,
DWORD GrantedAccess; DWORD GrantedAccess;
FSP_FILE_NODE *FileNode; FSP_FILE_NODE *FileNode;
Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE, Result = FspFileSystemPreOpenCheck(FileSystem, Request, TRUE, &GrantedAccess);
Request->Req.Create.DesiredAccess, &GrantedAccess);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
@ -76,7 +330,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Result = FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode); Result = FspFileSystemPostOpenCheck(FileSystem, Request, GrantedAccess, FileNode);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
if (0 != FileSystem->Interface->Close) if (0 != FileSystem->Interface->Close)
@ -96,8 +350,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
FSP_FILE_NODE *FileNode; FSP_FILE_NODE *FileNode;
BOOLEAN Create = FALSE; BOOLEAN Create = FALSE;
Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE, Result = FspFileSystemPreOpenCheck(FileSystem, Request, TRUE, &GrantedAccess);
Request->Req.Create.DesiredAccess, &GrantedAccess);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
if (STATUS_OBJECT_NAME_NOT_FOUND != Result) if (STATUS_OBJECT_NAME_NOT_FOUND != Result)
@ -114,6 +367,16 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Create = TRUE; Create = TRUE;
} }
else
{
Result = FspFileSystemPostOpenCheck(FileSystem, Request, GrantedAccess, FileNode);
if (!NT_SUCCESS(Result))
{
if (0 != FileSystem->Interface->Close)
FileSystem->Interface->Close(FileSystem, Request, FileNode);
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
}
}
} }
if (Create) if (Create)
@ -121,7 +384,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
if (FspIsRootDirectory((PWSTR)Request->Buffer)) if (FspIsRootDirectory((PWSTR)Request->Buffer))
return STATUS_ACCESS_DENIED; return STATUS_ACCESS_DENIED;
Result = FspCreateCheck(FileSystem, Request, FALSE, &GrantedAccess); Result = FspFileSystemPreCreateCheck(FileSystem, Request, FALSE, &GrantedAccess);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
@ -129,16 +392,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
memset(&FileNode->Flags, 0, sizeof FileNode->Flags); FspFileSystemPostCreateCheck(FileSystem, Request, GrantedAccess, FileNode);
memset(&FileNode->ShareAccess, 0, sizeof FileNode->ShareAccess);
}
Result = FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode);
if (!NT_SUCCESS(Result))
{
if (0 != FileSystem->Interface->Close)
FileSystem->Interface->Close(FileSystem, Request, FileNode);
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
} }
return FspFileSystemSendCreateResponse(FileSystem, Request, return FspFileSystemSendCreateResponse(FileSystem, Request,
@ -146,31 +400,25 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
} }
static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem, static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN Supersede) FSP_FSCTL_TRANSACT_REQ *Request)
{ {
if (FspIsRootDirectory((PWSTR)Request->Buffer))
return STATUS_ACCESS_DENIED;
NTSTATUS Result; NTSTATUS Result;
DWORD GrantedAccess; DWORD GrantedAccess;
FSP_FILE_NODE *FileNode; FSP_FILE_NODE *FileNode;
BOOLEAN Supersede = FILE_SUPERSEDE == ((Request->Req.Create.CreateOptions >> 24) & 0xff);
Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE, if (FspIsRootDirectory((PWSTR)Request->Buffer))
Request->Req.Create.DesiredAccess | (Supersede ? DELETE : FILE_WRITE_DATA), return STATUS_ACCESS_DENIED;
&GrantedAccess);
Result = FspFileSystemPreOverwriteCheck(FileSystem, Request, TRUE, &GrantedAccess);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
GrantedAccess &= Supersede ?
(~DELETE | (Request->Req.Create.DesiredAccess & DELETE)) :
(~FILE_WRITE_DATA | (Request->Req.Create.DesiredAccess & FILE_WRITE_DATA));
Result = FileSystem->Interface->Open(FileSystem, Request, &FileNode); Result = FileSystem->Interface->Open(FileSystem, Request, &FileNode);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Result = FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode); Result = FspFileSystemPostOverwriteCheck(FileSystem, Request, GrantedAccess, FileNode);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
if (0 != FileSystem->Interface->Close) if (0 != FileSystem->Interface->Close)
@ -193,28 +441,21 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem,
static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSystem, static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request) FSP_FSCTL_TRANSACT_REQ *Request)
{ {
if (FspIsRootDirectory((PWSTR)Request->Buffer))
return STATUS_ACCESS_DENIED;
NTSTATUS Result; NTSTATUS Result;
DWORD GrantedAccess; DWORD GrantedAccess;
FSP_FILE_NODE *FileNode; FSP_FILE_NODE *FileNode;
BOOLEAN Create = FALSE; BOOLEAN Create = FALSE;
Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE, if (FspIsRootDirectory((PWSTR)Request->Buffer))
Request->Req.Create.DesiredAccess | FILE_WRITE_DATA, return STATUS_ACCESS_DENIED;
&GrantedAccess);
Result = FspFileSystemPreOverwriteCheck(FileSystem, Request, TRUE, &GrantedAccess);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
if (STATUS_OBJECT_NAME_NOT_FOUND != Result) if (STATUS_OBJECT_NAME_NOT_FOUND != Result)
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Create = TRUE; Create = TRUE;
} }
else
{
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
GrantedAccess &= ~FILE_WRITE_DATA | (Request->Req.Create.DesiredAccess & FILE_WRITE_DATA);
}
if (!Create) if (!Create)
{ {
@ -225,23 +466,9 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Create = TRUE; Create = TRUE;
} }
} else
if (Create)
{ {
Result = FspCreateCheck(FileSystem, Request, FALSE, &GrantedAccess); Result = FspFileSystemPostOverwriteCheck(FileSystem, Request, GrantedAccess, FileNode);
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Result = FileSystem->Interface->Create(FileSystem, Request, &FileNode);
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
memset(&FileNode->Flags, 0, sizeof FileNode->Flags);
memset(&FileNode->ShareAccess, 0, sizeof FileNode->ShareAccess);
}
Result = FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
if (0 != FileSystem->Interface->Close) if (0 != FileSystem->Interface->Close)
@ -249,8 +476,6 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
} }
if (!Create)
{
Result = FileSystem->Interface->Overwrite(FileSystem, Request, FALSE, FileNode); Result = FileSystem->Interface->Overwrite(FileSystem, Request, FALSE, FileNode);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
@ -259,6 +484,20 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
} }
} }
}
if (Create)
{
Result = FspFileSystemPreCreateCheck(FileSystem, Request, FALSE, &GrantedAccess);
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Result = FileSystem->Interface->Create(FileSystem, Request, &FileNode);
if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
FspFileSystemPostCreateCheck(FileSystem, Request, GrantedAccess, FileNode);
}
return FspFileSystemSendCreateResponse(FileSystem, Request, return FspFileSystemSendCreateResponse(FileSystem, Request,
Create ? FILE_CREATED : FILE_OVERWRITTEN, FileNode, GrantedAccess); Create ? FILE_CREATED : FILE_OVERWRITTEN, FileNode, GrantedAccess);
@ -267,15 +506,15 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *FileSystem, static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request) FSP_FSCTL_TRANSACT_REQ *Request)
{ {
if (FspIsRootDirectory((PWSTR)Request->Buffer))
return STATUS_ACCESS_DENIED;
NTSTATUS Result; NTSTATUS Result;
PWSTR Parent, Suffix; PWSTR Parent, Suffix;
DWORD GrantedAccess; DWORD GrantedAccess;
FSP_FILE_NODE *FileNode; FSP_FILE_NODE *FileNode;
UINT_PTR Information; UINT_PTR Information;
if (FspIsRootDirectory((PWSTR)Request->Buffer))
return STATUS_ACCESS_DENIED;
Result = FspAccessCheck(FileSystem, Request, TRUE, TRUE, Result = FspAccessCheck(FileSystem, Request, TRUE, TRUE,
Request->Req.Create.DesiredAccess, &GrantedAccess); Request->Req.Create.DesiredAccess, &GrantedAccess);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
@ -287,7 +526,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *F
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result);
Result = FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode); Result = FspFileSystemPostOpenCheck(FileSystem, Request, GrantedAccess, FileNode);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
if (0 != FileSystem->Interface->Close) if (0 != FileSystem->Interface->Close)
@ -326,9 +565,9 @@ FSP_API NTSTATUS FspFileSystemOpCreate(FSP_FILE_SYSTEM *FileSystem,
case FILE_OPEN_IF: case FILE_OPEN_IF:
return FspFileSystemOpCreate_FileOpenIf(FileSystem, Request); return FspFileSystemOpCreate_FileOpenIf(FileSystem, Request);
case FILE_OVERWRITE: case FILE_OVERWRITE:
return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request, FALSE); return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request);
case FILE_SUPERSEDE: case FILE_SUPERSEDE:
return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request, TRUE); return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request);
case FILE_OVERWRITE_IF: case FILE_OVERWRITE_IF:
return FspFileSystemOpCreate_FileOverwriteIf(FileSystem, Request); return FspFileSystemOpCreate_FileOverwriteIf(FileSystem, Request);
default: default: