NTFileSystemHelper: Added OpenFile helper method

This commit is contained in:
Tal Aloni 2017-02-02 22:53:40 +02:00
parent 2460401955
commit b24345b5ca
3 changed files with 55 additions and 60 deletions

View file

@ -256,6 +256,53 @@ namespace SMBLibrary.Server
}
}
public static NTStatus OpenFile(out Stream stream, IFileSystem fileSystem, string path, FileAccess fileAccess, ShareAccess shareAccess, bool buffered, ConnectionState state)
{
stream = null;
FileShare fileShare = NTFileSystemHelper.ToFileShare(shareAccess);
state.LogToServer(Severity.Verbose, "OpenFile: Opening '{0}', Access={1}, Share={2}, Buffered={3}", path, fileAccess, fileShare, buffered);
try
{
stream = fileSystem.OpenFile(path, FileMode.Open, fileAccess, fileShare);
}
catch (DirectoryNotFoundException)
{
state.LogToServer(Severity.Debug, "OpenFile: Cannot open '{0}'. Directory not found.", path);
return NTStatus.STATUS_NO_SUCH_FILE;
}
catch (FileNotFoundException)
{
state.LogToServer(Severity.Debug, "OpenFile: Cannot open '{0}'. File not found.", path);
return NTStatus.STATUS_NO_SUCH_FILE;
}
catch (IOException ex)
{
ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
{
state.LogToServer(Severity.Debug, "OpenFile: Cannot open '{0}'. Sharing violation.", path);
return NTStatus.STATUS_SHARING_VIOLATION;
}
else
{
state.LogToServer(Severity.Debug, "OpenFile: Cannot open '{0}'. Data Error.", path);
return NTStatus.STATUS_DATA_ERROR;
}
}
catch (UnauthorizedAccessException)
{
state.LogToServer(Severity.Debug, "OpenFile: Cannot open '{0}'. Access Denied.", path);
return NTStatus.STATUS_ACCESS_DENIED;
}
if (buffered)
{
stream = new PrefetchedStream(stream);
}
return NTStatus.STATUS_SUCCESS;
}
public static NTStatus ReadFile(out byte[] data, OpenFileObject openFile, long offset, int maxCount, ConnectionState state)
{
data = null;

View file

@ -57,9 +57,7 @@ namespace SMBLibrary.Server.SMB1
return new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX);
}
IFileSystem fileSystem = fileSystemShare.FileSystem;
FileAccess fileAccess = NTFileSystemHelper.ToFileAccess(request.DesiredAccess);
FileShare fileShare = NTFileSystemHelper.ToFileShare(request.ShareAccess);
Stream stream;
bool deleteOnClose = false;
@ -69,6 +67,7 @@ namespace SMBLibrary.Server.SMB1
}
else
{
IFileSystem fileSystem = fileSystemShare.FileSystem;
// When FILE_OPEN_REPARSE_POINT is specified, the operation should continue normally if the file is not a reparse point.
// FILE_OPEN_REPARSE_POINT is a hint that the caller does not intend to actually read the file, with the exception
// of a file copy operation (where the caller will attempt to simply copy the reparse point).
@ -76,38 +75,12 @@ namespace SMBLibrary.Server.SMB1
bool openReparsePoint = (request.CreateOptions & CreateOptions.FILE_OPEN_REPARSE_POINT) > 0;
bool disableBuffering = (request.CreateOptions & CreateOptions.FILE_NO_INTERMEDIATE_BUFFERING) > 0;
bool buffered = (request.CreateOptions & CreateOptions.FILE_SEQUENTIAL_ONLY) > 0 && !disableBuffering && !openReparsePoint;
state.LogToServer(Severity.Verbose, "NTCreate: Opening '{0}', Access={1}, Share={2}, Buffered={3}", path, fileAccess, fileShare, buffered);
try
NTStatus openStatus = NTFileSystemHelper.OpenFile(out stream, fileSystem, path, fileAccess, request.ShareAccess, buffered, state);
if (openStatus != NTStatus.STATUS_SUCCESS)
{
stream = fileSystem.OpenFile(path, FileMode.Open, fileAccess, fileShare);
}
catch (IOException ex)
{
ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
{
state.LogToServer(Severity.Debug, "NTCreate: Sharing violation opening '{0}'", path);
header.Status = NTStatus.STATUS_SHARING_VIOLATION;
header.Status = openStatus;
return new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX);
}
else
{
state.LogToServer(Severity.Debug, "NTCreate: Sharing violation opening '{0}', Data Error", path);
header.Status = NTStatus.STATUS_DATA_ERROR;
return new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX);
}
}
catch (UnauthorizedAccessException)
{
state.LogToServer(Severity.Debug, "NTCreate: Sharing violation opening '{0}', Access Denied", path);
header.Status = NTStatus.STATUS_ACCESS_DENIED;
return new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX);
}
if (buffered)
{
stream = new PrefetchedStream(stream);
}
}
ushort? fileID = session.AddOpenFile(path, stream, deleteOnClose);

View file

@ -50,9 +50,7 @@ namespace SMBLibrary.Server.SMB2
return new ErrorResponse(request.CommandName, createStatus);
}
IFileSystem fileSystem = fileSystemShare.FileSystem;
FileAccess fileAccess = NTFileSystemHelper.ToFileAccess(request.DesiredAccess.File);
FileShare fileShare = NTFileSystemHelper.ToFileShare(request.ShareAccess);
Stream stream;
bool deleteOnClose = false;
@ -62,6 +60,7 @@ namespace SMBLibrary.Server.SMB2
}
else
{
IFileSystem fileSystem = fileSystemShare.FileSystem;
// When FILE_OPEN_REPARSE_POINT is specified, the operation should continue normally if the file is not a reparse point.
// FILE_OPEN_REPARSE_POINT is a hint that the caller does not intend to actually read the file, with the exception
// of a file copy operation (where the caller will attempt to simply copy the reparse point).
@ -69,34 +68,10 @@ namespace SMBLibrary.Server.SMB2
bool openReparsePoint = (request.CreateOptions & CreateOptions.FILE_OPEN_REPARSE_POINT) > 0;
bool disableBuffering = (request.CreateOptions & CreateOptions.FILE_NO_INTERMEDIATE_BUFFERING) > 0;
bool buffered = (request.CreateOptions & CreateOptions.FILE_SEQUENTIAL_ONLY) > 0 && !disableBuffering && !openReparsePoint;
state.LogToServer(Severity.Verbose, "Create: Opening '{0}', Access={1}, Share={2}, Buffered={3}", path, fileAccess, fileShare, buffered);
try
NTStatus openStatus = NTFileSystemHelper.OpenFile(out stream, fileSystem, path, fileAccess, request.ShareAccess, buffered, state);
if (openStatus != NTStatus.STATUS_SUCCESS)
{
stream = fileSystem.OpenFile(path, FileMode.Open, fileAccess, fileShare);
}
catch (IOException ex)
{
ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex);
if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION)
{
state.LogToServer(Severity.Debug, "NTCreate: Sharing violation opening '{0}'", path);
return new ErrorResponse(request.CommandName, NTStatus.STATUS_SHARING_VIOLATION);
}
else
{
state.LogToServer(Severity.Debug, "NTCreate: Sharing violation opening '{0}', Data Error", path);
return new ErrorResponse(request.CommandName, NTStatus.STATUS_DATA_ERROR);
}
}
catch (UnauthorizedAccessException)
{
state.LogToServer(Severity.Debug, "NTCreate: Sharing violation opening '{0}', Access Denied", path);
return new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED);
}
if (buffered)
{
stream = new PrefetchedStream(stream);
return new ErrorResponse(request.CommandName, openStatus);
}
}