mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
sys,dll: properly implement stream create check
This commit is contained in:
parent
4dc1828e1f
commit
4084448bd5
@ -218,7 +218,8 @@ typedef struct
|
|||||||
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
|
UINT32 HasTraversePrivilege:1; /* requestor has TOKEN_HAS_TRAVERSE_PRIVILEGE */
|
||||||
UINT32 OpenTargetDirectory:1; /* open target dir and report FILE_{EXISTS,DOES_NOT_EXIST} */
|
UINT32 OpenTargetDirectory:1; /* open target dir and report FILE_{EXISTS,DOES_NOT_EXIST} */
|
||||||
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
||||||
UINT32 NamedStream:1; /* request targets named stream; FileName has colon */
|
UINT32 ReservedFlags:28;
|
||||||
|
UINT16 NamedStream; /* request targets named stream; colon offset in FileName */
|
||||||
} Create;
|
} Create;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -1207,7 +1207,7 @@ FSP_API BOOLEAN FspFileSystemAddStreamInfo(FSP_FSCTL_STREAM_INFO *StreamInfo,
|
|||||||
FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID);
|
FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID);
|
||||||
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
|
BOOLEAN CheckParentOrMain, BOOLEAN AllowTraverseCheck,
|
||||||
UINT32 DesiredAccess, PUINT32 PGrantedAccess/* or ReparsePointIndex */,
|
UINT32 DesiredAccess, PUINT32 PGrantedAccess/* or ReparsePointIndex */,
|
||||||
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
||||||
FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
|
||||||
@ -1223,11 +1223,11 @@ FSP_API VOID FspDeleteSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor
|
|||||||
static inline
|
static inline
|
||||||
NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
|
BOOLEAN CheckParentOrMain, BOOLEAN AllowTraverseCheck,
|
||||||
UINT32 DesiredAccess, PUINT32 PGrantedAccess)
|
UINT32 DesiredAccess, PUINT32 PGrantedAccess)
|
||||||
{
|
{
|
||||||
return FspAccessCheckEx(FileSystem, Request,
|
return FspAccessCheckEx(FileSystem, Request,
|
||||||
CheckParentDirectory, AllowTraverseCheck,
|
CheckParentOrMain, AllowTraverseCheck,
|
||||||
DesiredAccess, PGrantedAccess,
|
DesiredAccess, PGrantedAccess,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
@ -140,24 +140,57 @@ NTSTATUS FspFileSystemCreateCheck(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
UINT32 GrantedAccess;
|
UINT32 GrantedAccess;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CreateCheck consists of checking the parent directory for the
|
* CreateCheck does different checks depending on whether we are
|
||||||
* FILE_ADD_SUBDIRECTORY or FILE_ADD_FILE rights (depending on whether
|
* creating a new file/directory or a new stream.
|
||||||
* we are creating a file or directory).
|
|
||||||
*
|
*
|
||||||
* If the access check succeeds and MAXIMUM_ALLOWED has been requested
|
* - CreateCheck for a new file consists of checking the parent directory
|
||||||
* then we go ahead and grant all access to the creator.
|
* for the FILE_ADD_SUBDIRECTORY or FILE_ADD_FILE rights (depending on
|
||||||
|
* whether we are creating a file or directory).
|
||||||
|
*
|
||||||
|
* If the access check succeeds and MAXIMUM_ALLOWED has been requested
|
||||||
|
* then we go ahead and grant all access to the creator.
|
||||||
|
*
|
||||||
|
* - CreateCheck for a new stream consists of checking the main file for
|
||||||
|
* FILE_WRITE_DATA access, unless FILE_DELETE_ON_CLOSE is requested in
|
||||||
|
* which case we also check for DELETE access.
|
||||||
|
*
|
||||||
|
* If the access check succeeds and MAXIMUM_ALLOWED was not requested
|
||||||
|
* then we reset the DELETE and FILE_WRITE_DATA accesses based on whether
|
||||||
|
* they were actually requested in DesiredAccess.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck,
|
if (!Request->Req.Create.NamedStream)
|
||||||
(Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE) ?
|
|
||||||
FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE,
|
|
||||||
&GrantedAccess, PSecurityDescriptor);
|
|
||||||
if (STATUS_REPARSE == Result)
|
|
||||||
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, GrantedAccess);
|
|
||||||
else if (NT_SUCCESS(Result))
|
|
||||||
{
|
{
|
||||||
*PGrantedAccess = (MAXIMUM_ALLOWED & Request->Req.Create.DesiredAccess) ?
|
Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck,
|
||||||
FspGetFileGenericMapping()->GenericAll : Request->Req.Create.DesiredAccess;
|
(Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE) ?
|
||||||
|
FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE,
|
||||||
|
&GrantedAccess, PSecurityDescriptor);
|
||||||
|
if (STATUS_REPARSE == Result)
|
||||||
|
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, GrantedAccess);
|
||||||
|
else if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
*PGrantedAccess = (MAXIMUM_ALLOWED & Request->Req.Create.DesiredAccess) ?
|
||||||
|
FspGetFileGenericMapping()->GenericAll : Request->Req.Create.DesiredAccess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*PSecurityDescriptor = 0;
|
||||||
|
|
||||||
|
Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck,
|
||||||
|
Request->Req.Create.DesiredAccess |
|
||||||
|
FILE_WRITE_DATA |
|
||||||
|
((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0),
|
||||||
|
&GrantedAccess, 0);
|
||||||
|
if (STATUS_REPARSE == Result)
|
||||||
|
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, GrantedAccess);
|
||||||
|
else if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
*PGrantedAccess = GrantedAccess;
|
||||||
|
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
|
||||||
|
*PGrantedAccess &= ~(DELETE | FILE_WRITE_DATA) |
|
||||||
|
(Request->Req.Create.DesiredAccess & (DELETE | FILE_WRITE_DATA));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -63,10 +63,21 @@ static inline ULONG FspPathSuffixIndex(PWSTR FileName)
|
|||||||
|
|
||||||
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
|
BOOLEAN CheckParentOrMain, BOOLEAN AllowTraverseCheck,
|
||||||
UINT32 DesiredAccess, PUINT32 PGrantedAccess,
|
UINT32 DesiredAccess, PUINT32 PGrantedAccess,
|
||||||
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor)
|
||||||
{
|
{
|
||||||
|
BOOLEAN CheckParentDirectory, CheckMainFile;
|
||||||
|
|
||||||
|
CheckParentDirectory = CheckMainFile = FALSE;
|
||||||
|
if (CheckParentOrMain)
|
||||||
|
{
|
||||||
|
if (!Request->Req.Create.NamedStream)
|
||||||
|
CheckParentDirectory = TRUE;
|
||||||
|
else
|
||||||
|
CheckMainFile = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
*PGrantedAccess = 0;
|
*PGrantedAccess = 0;
|
||||||
if (0 != PSecurityDescriptor)
|
if (0 != PSecurityDescriptor)
|
||||||
*PSecurityDescriptor = 0;
|
*PSecurityDescriptor = 0;
|
||||||
@ -100,6 +111,11 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
if (CheckParentDirectory)
|
if (CheckParentDirectory)
|
||||||
FspPathSuffix((PWSTR)Request->Buffer, &FileName, &Suffix, Root);
|
FspPathSuffix((PWSTR)Request->Buffer, &FileName, &Suffix, Root);
|
||||||
|
else if (CheckMainFile)
|
||||||
|
{
|
||||||
|
((PWSTR)Request->Buffer)[Request->Req.Create.NamedStream / sizeof(WCHAR)] = L'\0';
|
||||||
|
FileName = (PWSTR)Request->Buffer;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
FileName = (PWSTR)Request->Buffer;
|
FileName = (PWSTR)Request->Buffer;
|
||||||
|
|
||||||
@ -269,6 +285,20 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (CheckMainFile)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We check to see if this is a reparse point and FILE_OPEN_REPARSE_POINT
|
||||||
|
* was not specified, in which case we return STATUS_REPARSE.
|
||||||
|
*/
|
||||||
|
if (0 != (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
||||||
|
0 == (Request->Req.Create.CreateOptions & FILE_OPEN_REPARSE_POINT))
|
||||||
|
{
|
||||||
|
FileAttributes = FspPathSuffixIndex(FileName);
|
||||||
|
Result = STATUS_REPARSE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -344,6 +374,8 @@ exit:
|
|||||||
if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
|
if (STATUS_OBJECT_NAME_NOT_FOUND == Result)
|
||||||
Result = STATUS_OBJECT_PATH_NOT_FOUND;
|
Result = STATUS_OBJECT_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
else if (CheckMainFile)
|
||||||
|
((PWSTR)Request->Buffer)[Request->Req.Create.NamedStream / sizeof(WCHAR)] = L':';
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -477,7 +477,11 @@ static NTSTATUS FspFsvolCreateNoLock(
|
|||||||
Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
|
Request->Req.Create.HasTraversePrivilege = HasTraversePrivilege;
|
||||||
Request->Req.Create.OpenTargetDirectory = BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY);
|
Request->Req.Create.OpenTargetDirectory = BooleanFlagOn(Flags, SL_OPEN_TARGET_DIRECTORY);
|
||||||
Request->Req.Create.CaseSensitive = CaseSensitiveRequested;
|
Request->Req.Create.CaseSensitive = CaseSensitiveRequested;
|
||||||
Request->Req.Create.NamedStream = 0 != StreamPart.Length;
|
Request->Req.Create.NamedStream = MainFileName.Length;
|
||||||
|
|
||||||
|
ASSERT(
|
||||||
|
0 == StreamPart.Length && 0 == MainFileName.Length ||
|
||||||
|
0 != StreamPart.Length && 0 != MainFileName.Length);
|
||||||
|
|
||||||
/* copy the security descriptor (if any) into the request */
|
/* copy the security descriptor (if any) into the request */
|
||||||
if (0 != SecurityDescriptorSize)
|
if (0 != SecurityDescriptorSize)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user