123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- /* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
- *
- * You can redistribute this program and/or modify it under the terms of
- * the GNU Lesser Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- */
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using SMBLibrary.SMB1;
- using Utilities;
- namespace SMBLibrary.Server.SMB1
- {
- public class FileSystemResponseHelper
- {
- internal static SMB1Command GetCreateDirectoryResponse(SMB1Header header, CreateDirectoryRequest request, FileSystemShare share, SMB1ConnectionState state)
- {
- string userName = state.GetConnectedUserName(header.UID);
- if (!share.HasWriteAccess(userName))
- {
- header.Status = NTStatus.STATUS_ACCESS_DENIED;
- return new ErrorResponse(CommandName.SMB_COM_CREATE_DIRECTORY);
- }
- IFileSystem fileSystem = share.FileSystem;
- try
- {
- fileSystem.CreateDirectory(request.DirectoryName);
- }
- catch (IOException)
- {
- state.LogToServer(Severity.Debug, "CreateDirectory: Cannot create '{0}'", request.DirectoryName);
- header.Status = NTStatus.STATUS_OBJECT_NAME_INVALID;
- return new ErrorResponse(CommandName.SMB_COM_CREATE_DIRECTORY);
- }
- catch (UnauthorizedAccessException)
- {
- state.LogToServer(Severity.Debug, "CreateDirectory: Cannot create '{0}', Access Denied", request.DirectoryName);
- header.Status = NTStatus.STATUS_ACCESS_DENIED;
- return new ErrorResponse(CommandName.SMB_COM_CREATE_DIRECTORY);
- }
- return new CreateDirectoryResponse();
- }
- internal static SMB1Command GetDeleteDirectoryResponse(SMB1Header header, DeleteDirectoryRequest request, FileSystemShare share, SMB1ConnectionState state)
- {
- string userName = state.GetConnectedUserName(header.UID);
- if (!share.HasWriteAccess(userName))
- {
- header.Status = NTStatus.STATUS_ACCESS_DENIED;
- return new ErrorResponse(CommandName.SMB_COM_DELETE_DIRECTORY);
- }
- IFileSystem fileSystem = share.FileSystem;
- FileSystemEntry entry = fileSystem.GetEntry(request.DirectoryName);
- if (entry == null)
- {
- header.Status = NTStatus.STATUS_NO_SUCH_FILE;
- return new ErrorResponse(CommandName.SMB_COM_DELETE_DIRECTORY);
- }
- if (!entry.IsDirectory)
- {
- header.Status = NTStatus.STATUS_OBJECT_PATH_INVALID;
- return new ErrorResponse(CommandName.SMB_COM_DELETE_DIRECTORY);
- }
- try
- {
- fileSystem.Delete(request.DirectoryName);
- return new DeleteDirectoryResponse();
- }
- catch (IOException)
- {
- state.LogToServer(Severity.Debug, "DeleteDirectory: Cannot delete '{0}'", request.DirectoryName);
- header.Status = NTStatus.STATUS_CANNOT_DELETE;
- return new ErrorResponse(CommandName.SMB_COM_DELETE_DIRECTORY);
- }
- catch (UnauthorizedAccessException)
- {
- state.LogToServer(Severity.Debug, "DeleteDirectory: Cannot delete '{0}', Access Denied", request.DirectoryName);
- header.Status = NTStatus.STATUS_ACCESS_DENIED;
- return new ErrorResponse(CommandName.SMB_COM_DELETE_DIRECTORY);
- }
- }
- internal static SMB1Command GetCheckDirectoryResponse(SMB1Header header, CheckDirectoryRequest request, FileSystemShare share)
- {
- IFileSystem fileSystem = share.FileSystem;
- FileSystemEntry entry = fileSystem.GetEntry(request.DirectoryName);
- if (entry == null || !entry.IsDirectory)
- {
- header.Status = NTStatus.STATUS_NO_SUCH_FILE;
- return new ErrorResponse(CommandName.SMB_COM_CHECK_DIRECTORY);
- }
- return new CheckDirectoryResponse();
- }
- internal static SMB1Command GetDeleteResponse(SMB1Header header, DeleteRequest request, FileSystemShare share, SMB1ConnectionState state)
- {
- string userName = state.GetConnectedUserName(header.UID);
- if (!share.HasWriteAccess(userName))
- {
- header.Status = NTStatus.STATUS_ACCESS_DENIED;
- return new ErrorResponse(CommandName.SMB_COM_DELETE);
- }
- IFileSystem fileSystem = share.FileSystem;
- FileSystemEntry entry = fileSystem.GetEntry(request.FileName);
- if (entry == null)
- {
- header.Status = NTStatus.STATUS_NO_SUCH_FILE;
- return new ErrorResponse(CommandName.SMB_COM_DELETE);
- }
- if (!entry.IsDirectory && (request.SearchAttributes & SMBFileAttributes.Directory) > 0
- || entry.IsDirectory && (request.SearchAttributes & SMBFileAttributes.Directory) == 0)
- {
- header.Status = NTStatus.STATUS_OBJECT_PATH_INVALID;
- return new ErrorResponse(CommandName.SMB_COM_DELETE);
- }
- try
- {
- fileSystem.Delete(request.FileName);
- return new DeleteResponse();
- }
- catch (IOException)
- {
- state.LogToServer(Severity.Debug, "Delete: Cannot delete '{0}'", request.FileName);
- header.Status = NTStatus.STATUS_CANNOT_DELETE;
- return new ErrorResponse(CommandName.SMB_COM_DELETE);
- }
- catch (UnauthorizedAccessException)
- {
- state.LogToServer(Severity.Debug, "DeleteDirectory: Cannot delete '{0}', Access Denied", request.FileName);
- header.Status = NTStatus.STATUS_ACCESS_DENIED;
- return new ErrorResponse(CommandName.SMB_COM_DELETE);
- }
- }
- internal static SMB1Command GetRenameResponse(SMB1Header header, RenameRequest request, FileSystemShare share, SMB1ConnectionState state)
- {
- string userName = state.GetConnectedUserName(header.UID);
- if (!share.HasWriteAccess(userName))
- {
- header.Status = NTStatus.STATUS_ACCESS_DENIED;
- return new ErrorResponse(CommandName.SMB_COM_RENAME);
- }
- IFileSystem fileSystem = share.FileSystem;
- FileSystemEntry sourceEntry = fileSystem.GetEntry(request.OldFileName);
- if (sourceEntry == null)
- {
- header.Status = NTStatus.STATUS_NO_SUCH_FILE;
- return new ErrorResponse(CommandName.SMB_COM_RENAME);
- }
- // The file must not already exist unless we just want to upcase / downcase a filename letter
- FileSystemEntry destinationEntry = fileSystem.GetEntry(request.NewFileName);
- if (destinationEntry != null &&
- !String.Equals(request.OldFileName, request.NewFileName, StringComparison.InvariantCultureIgnoreCase))
- {
- // The new file already exists.
- header.Status = NTStatus.STATUS_OBJECT_NAME_COLLISION;
- return new ErrorResponse(CommandName.SMB_COM_RENAME);
- }
- try
- {
- fileSystem.Move(request.OldFileName, request.NewFileName);
- return new RenameResponse();
- }
- catch (IOException)
- {
- state.LogToServer(Severity.Debug, "Rename: Sharing violation renaming '{0}'", request.OldFileName);
- header.Status = NTStatus.STATUS_SHARING_VIOLATION;
- return new ErrorResponse(CommandName.SMB_COM_RENAME);
- }
- catch (UnauthorizedAccessException)
- {
- state.LogToServer(Severity.Debug, "Rename: Cannot rename '{0}', Access Denied", request.OldFileName);
- header.Status = NTStatus.STATUS_ACCESS_DENIED;
- return new ErrorResponse(CommandName.SMB_COM_RENAME);
- }
- }
- internal static SMB1Command GetQueryInformationResponse(SMB1Header header, QueryInformationRequest request, FileSystemShare share)
- {
- IFileSystem fileSystem = share.FileSystem;
- FileSystemEntry entry = fileSystem.GetEntry(request.FileName);
- if (entry == null)
- {
- header.Status = NTStatus.STATUS_OBJECT_PATH_INVALID;
- return new ErrorResponse(CommandName.SMB_COM_QUERY_INFORMATION);
- }
- QueryInformationResponse response = new QueryInformationResponse();
- response.FileAttributes = InfoHelper.GetFileAttributes(entry);
- response.LastWriteTime = entry.LastWriteTime;
- response.FileSize = (uint)Math.Min(UInt32.MaxValue, entry.Size);
- return response;
- }
- internal static SMB1Command GetSetInformationResponse(SMB1Header header, SetInformationRequest request, FileSystemShare share, SMB1ConnectionState state)
- {
- string userName = state.GetConnectedUserName(header.UID);
- if (!share.HasWriteAccess(userName))
- {
- header.Status = NTStatus.STATUS_ACCESS_DENIED;
- return new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION2);
- }
- IFileSystem fileSystem = share.FileSystem;
- FileSystemEntry entry = fileSystem.GetEntry(request.FileName);
- if (entry == null)
- {
- header.Status = NTStatus.STATUS_NO_SUCH_FILE;
- return new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION);
- }
- bool? isHidden = null;
- bool? isReadOnly = null;
- bool? isArchived = null;
- if ((request.FileAttributes & SMBFileAttributes.Hidden) > 0)
- {
- isHidden = true;
- }
- if ((request.FileAttributes & SMBFileAttributes.ReadOnly) > 0)
- {
- isReadOnly = true;
- }
- if ((request.FileAttributes & SMBFileAttributes.Archive) > 0)
- {
- isArchived = true;
- }
- fileSystem.SetAttributes(request.FileName, isHidden, isReadOnly, isArchived);
- if (request.LastWriteTime != SMB1Helper.UTimeNotSpecified)
- {
- fileSystem.SetDates(request.FileName, null, request.LastWriteTime, null);
- }
- return new SetInformationResponse();
- }
- internal static SMB1Command GetSetInformation2Response(SMB1Header header, SetInformation2Request request, FileSystemShare share, SMB1ConnectionState state)
- {
- string openedFilePath = state.GetOpenedFilePath(request.FID);
- if (openedFilePath == null)
- {
- header.Status = NTStatus.STATUS_SMB_BAD_FID;
- return new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION2);
- }
- string userName = state.GetConnectedUserName(header.UID);
- if (!share.HasWriteAccess(userName))
- {
- header.Status = NTStatus.STATUS_ACCESS_DENIED;
- return new ErrorResponse(CommandName.SMB_COM_SET_INFORMATION2);
- }
- IFileSystem fileSystem = share.FileSystem;
- fileSystem.SetDates(openedFilePath, request.CreationDateTime, request.LastWriteDateTime, request.LastAccessDateTime);
- return new SetInformation2Response();
- }
- }
- }
|