From d2eabf4e0597cdfef302b57dcba6efa9e3a61e1e Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Mon, 4 Jan 2016 21:46:02 -0800 Subject: [PATCH] dll: create.c: refactoring --- build/VStudio/winfsp_dll.vcxproj | 1 - build/VStudio/winfsp_dll.vcxproj.filters | 3 - inc/winfsp/winfsp.h | 31 +- src/dll/access.c | 213 ------------ src/dll/create.c | 411 ++++++++++++++++++----- 5 files changed, 343 insertions(+), 316 deletions(-) delete mode 100644 src/dll/access.c diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj index 3ee98e59..ab79246f 100644 --- a/build/VStudio/winfsp_dll.vcxproj +++ b/build/VStudio/winfsp_dll.vcxproj @@ -24,7 +24,6 @@ - diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters index 61513d10..a9cf81d4 100644 --- a/build/VStudio/winfsp_dll.vcxproj.filters +++ b/build/VStudio/winfsp_dll.vcxproj.filters @@ -43,9 +43,6 @@ Source - - Source - Source diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 37427431..f4e32901 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -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 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, PWSTR FileName, PDWORD PFileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize); @@ -149,6 +146,24 @@ FSP_API NTSTATUS FspFileSystemSendResponseWithStatus(FSP_FILE_SYSTEM *FileSystem /* * 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_FSCTL_TRANSACT_REQ *Request); 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_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 */ diff --git a/src/dll/access.c b/src/dll/access.c deleted file mode 100644 index dbd6474a..00000000 --- a/src/dll/access.c +++ /dev/null @@ -1,213 +0,0 @@ -/** - * @file dll/access.c - * - * @copyright 2015 Bill Zissimopoulos - */ - -#include - -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; -} diff --git a/src/dll/create.c b/src/dll/create.c index a039b7d7..8b98f8ea 100644 --- a/src/dll/create.c +++ b/src/dll/create.c @@ -6,19 +6,221 @@ #include -static inline -BOOLEAN FspIsRootDirectory(PWSTR FileName) +static GENERIC_MAPPING FspFileGenericMapping = { - for (PWSTR Pointer = FileName; *Pointer; Pointer++) - if (L'\\' != *Pointer) - return FALSE; - return TRUE; + .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 inline -NTSTATUS FspCreateCheck(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN AllowTraverseCheck, - PDWORD PGrantedAccess) +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->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; @@ -33,17 +235,73 @@ NTSTATUS FspCreateCheck(FSP_FILE_SYSTEM *FileSystem, 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, FSP_FSCTL_TRANSACT_REQ *Request) { - if (FspIsRootDirectory((PWSTR)Request->Buffer)) - return STATUS_ACCESS_DENIED; - NTSTATUS Result; DWORD GrantedAccess; 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)) return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); @@ -51,10 +309,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(Result)) return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); - memset(&FileNode->Flags, 0, sizeof FileNode->Flags); - memset(&FileNode->ShareAccess, 0, sizeof FileNode->ShareAccess); - - FspShareCheck(FileSystem, GrantedAccess, Request->Req.Create.ShareAccess, FileNode); + FspFileSystemPostCreateCheck(FileSystem, Request, GrantedAccess, FileNode); return FspFileSystemSendCreateResponse(FileSystem, Request, FILE_CREATED, FileNode, GrantedAccess); @@ -67,8 +322,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem, DWORD GrantedAccess; FSP_FILE_NODE *FileNode; - Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE, - Request->Req.Create.DesiredAccess, &GrantedAccess); + Result = FspFileSystemPreOpenCheck(FileSystem, Request, TRUE, &GrantedAccess); if (!NT_SUCCESS(Result)) return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); @@ -76,7 +330,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(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 (0 != FileSystem->Interface->Close) @@ -96,8 +350,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, FSP_FILE_NODE *FileNode; BOOLEAN Create = FALSE; - Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE, - Request->Req.Create.DesiredAccess, &GrantedAccess); + Result = FspFileSystemPreOpenCheck(FileSystem, Request, TRUE, &GrantedAccess); if (!NT_SUCCESS(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); 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) @@ -121,7 +384,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, if (FspIsRootDirectory((PWSTR)Request->Buffer)) return STATUS_ACCESS_DENIED; - Result = FspCreateCheck(FileSystem, Request, FALSE, &GrantedAccess); + Result = FspFileSystemPreCreateCheck(FileSystem, Request, FALSE, &GrantedAccess); if (!NT_SUCCESS(Result)) return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); @@ -129,16 +392,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem, 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 (0 != FileSystem->Interface->Close) - FileSystem->Interface->Close(FileSystem, Request, FileNode); - return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); + FspFileSystemPostCreateCheck(FileSystem, Request, GrantedAccess, FileNode); } return FspFileSystemSendCreateResponse(FileSystem, Request, @@ -146,31 +400,25 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(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; DWORD GrantedAccess; FSP_FILE_NODE *FileNode; + BOOLEAN Supersede = FILE_SUPERSEDE == ((Request->Req.Create.CreateOptions >> 24) & 0xff); - Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE, - Request->Req.Create.DesiredAccess | (Supersede ? DELETE : FILE_WRITE_DATA), - &GrantedAccess); + if (FspIsRootDirectory((PWSTR)Request->Buffer)) + return STATUS_ACCESS_DENIED; + + Result = FspFileSystemPreOverwriteCheck(FileSystem, Request, TRUE, &GrantedAccess); if (!NT_SUCCESS(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); if (!NT_SUCCESS(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 (0 != FileSystem->Interface->Close) @@ -193,28 +441,21 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem, static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request) { - if (FspIsRootDirectory((PWSTR)Request->Buffer)) - return STATUS_ACCESS_DENIED; - NTSTATUS Result; DWORD GrantedAccess; FSP_FILE_NODE *FileNode; BOOLEAN Create = FALSE; - Result = FspAccessCheck(FileSystem, Request, FALSE, TRUE, - Request->Req.Create.DesiredAccess | FILE_WRITE_DATA, - &GrantedAccess); + if (FspIsRootDirectory((PWSTR)Request->Buffer)) + return STATUS_ACCESS_DENIED; + + Result = FspFileSystemPreOverwriteCheck(FileSystem, Request, TRUE, &GrantedAccess); if (!NT_SUCCESS(Result)) { if (STATUS_OBJECT_NAME_NOT_FOUND != Result) return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); Create = TRUE; } - else - { - if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED)) - GrantedAccess &= ~FILE_WRITE_DATA | (Request->Req.Create.DesiredAccess & FILE_WRITE_DATA); - } if (!Create) { @@ -225,11 +466,29 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); Create = TRUE; } + else + { + Result = FspFileSystemPostOverwriteCheck(FileSystem, Request, GrantedAccess, FileNode); + if (!NT_SUCCESS(Result)) + { + if (0 != FileSystem->Interface->Close) + FileSystem->Interface->Close(FileSystem, Request, FileNode); + return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); + } + + Result = FileSystem->Interface->Overwrite(FileSystem, Request, FALSE, FileNode); + if (!NT_SUCCESS(Result)) + { + if (0 != FileSystem->Interface->Close) + FileSystem->Interface->Close(FileSystem, Request, FileNode); + return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); + } + } } if (Create) { - Result = FspCreateCheck(FileSystem, Request, FALSE, &GrantedAccess); + Result = FspFileSystemPreCreateCheck(FileSystem, Request, FALSE, &GrantedAccess); if (!NT_SUCCESS(Result)) return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); @@ -237,27 +496,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste 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 (0 != FileSystem->Interface->Close) - FileSystem->Interface->Close(FileSystem, Request, FileNode); - return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); - } - - if (!Create) - { - Result = FileSystem->Interface->Overwrite(FileSystem, Request, FALSE, FileNode); - if (!NT_SUCCESS(Result)) - { - if (0 != FileSystem->Interface->Close) - FileSystem->Interface->Close(FileSystem, Request, FileNode); - return FspFileSystemSendResponseWithStatus(FileSystem, Request, Result); - } + FspFileSystemPostCreateCheck(FileSystem, Request, GrantedAccess, FileNode); } return FspFileSystemSendCreateResponse(FileSystem, Request, @@ -267,15 +506,15 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request) { - if (FspIsRootDirectory((PWSTR)Request->Buffer)) - return STATUS_ACCESS_DENIED; - NTSTATUS Result; PWSTR Parent, Suffix; DWORD GrantedAccess; FSP_FILE_NODE *FileNode; UINT_PTR Information; + if (FspIsRootDirectory((PWSTR)Request->Buffer)) + return STATUS_ACCESS_DENIED; + Result = FspAccessCheck(FileSystem, Request, TRUE, TRUE, Request->Req.Create.DesiredAccess, &GrantedAccess); if (!NT_SUCCESS(Result)) @@ -287,7 +526,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *F if (!NT_SUCCESS(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 (0 != FileSystem->Interface->Close) @@ -326,9 +565,9 @@ FSP_API NTSTATUS FspFileSystemOpCreate(FSP_FILE_SYSTEM *FileSystem, case FILE_OPEN_IF: return FspFileSystemOpCreate_FileOpenIf(FileSystem, Request); case FILE_OVERWRITE: - return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request, FALSE); + return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request); case FILE_SUPERSEDE: - return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request, TRUE); + return FspFileSystemOpCreate_FileOverwrite(FileSystem, Request); case FILE_OVERWRITE_IF: return FspFileSystemOpCreate_FileOverwriteIf(FileSystem, Request); default: