diff --git a/SMBLibrary/Server/Helpers/NTFileSystemHelper.cs b/SMBLibrary/Server/Helpers/NTFileSystemHelper.cs index 3f7517c..3cc2a35 100644 --- a/SMBLibrary/Server/Helpers/NTFileSystemHelper.cs +++ b/SMBLibrary/Server/Helpers/NTFileSystemHelper.cs @@ -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; diff --git a/SMBLibrary/Server/SMB1/NTCreateHelper.cs b/SMBLibrary/Server/SMB1/NTCreateHelper.cs index 5036546..0c3606a 100644 --- a/SMBLibrary/Server/SMB1/NTCreateHelper.cs +++ b/SMBLibrary/Server/SMB1/NTCreateHelper.cs @@ -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; - 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; + header.Status = openStatus; return new ErrorResponse(CommandName.SMB_COM_NT_CREATE_ANDX); } - - if (buffered) - { - stream = new PrefetchedStream(stream); - } } ushort? fileID = session.AddOpenFile(path, stream, deleteOnClose); diff --git a/SMBLibrary/Server/SMB2/CreateHelper.cs b/SMBLibrary/Server/SMB2/CreateHelper.cs index eb16ab1..33df8ab 100644 --- a/SMBLibrary/Server/SMB2/CreateHelper.cs +++ b/SMBLibrary/Server/SMB2/CreateHelper.cs @@ -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); } }