internal static TransactionTransactNamedPipeResponse GetSubcommandResponse(SMBHeader header, TransactionTransactNamedPipeRequest subcommand, NamedPipeShare share, StateObject state) { string openedFilePath = state.GetOpenedFilePath(subcommand.FID); if (openedFilePath == null) { header.Status = NTStatus.STATUS_INVALID_HANDLE; return(null); } TransactionTransactNamedPipeResponse response = new TransactionTransactNamedPipeResponse(); RemoteService service = share.GetService(openedFilePath); if (service != null) { RPCPDU rpcRequest = RPCPDU.GetPDU(subcommand.WriteData); RPCPDU rpcReply = RemoteServiceHelper.GetRPCReply(rpcRequest, service); response.ReadData = rpcReply.GetBytes(); return(response); } // This code should not execute unless the request sequence is invalid header.Status = NTStatus.STATUS_INVALID_SMB; return(null); }
internal static SMBCommand GetCloseResponse(SMBHeader header, CloseRequest request, StateObject state) { string openedFilePath = state.GetOpenedFilePath(request.FID); if (openedFilePath == null) { header.Status = NTStatus.STATUS_SMB_BAD_FID; return(new ErrorResponse(CommandName.SMB_COM_CLOSE)); } state.RemoveOpenedFile(request.FID); CloseResponse response = new CloseResponse(); return(response); }
internal static SMBCommand GetSetInformation2Response(SMBHeader header, SetInformation2Request request, FileSystemShare share, StateObject 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()); }
internal static Transaction2QueryFileInformationResponse GetSubcommandResponse(SMBHeader header, Transaction2QueryFileInformationRequest subcommand, FileSystemShare share, StateObject state) { IFileSystem fileSystem = share.FileSystem; string openedFilePath = state.GetOpenedFilePath(subcommand.FID); if (openedFilePath == null) { header.Status = NTStatus.STATUS_INVALID_HANDLE; return(null); } FileSystemEntry entry = fileSystem.GetEntry(openedFilePath); if (entry == null) { header.Status = NTStatus.STATUS_NO_SUCH_FILE; return(null); } Transaction2QueryFileInformationResponse response = new Transaction2QueryFileInformationResponse(); response.QueryInfo = InfoHelper.FromFileSystemEntry(entry, subcommand.InformationLevel); return(response); }
internal static Transaction2SetFileInformationResponse GetSubcommandResponse(SMBHeader header, Transaction2SetFileInformationRequest subcommand, FileSystemShare share, StateObject state) { string openedFilePath = state.GetOpenedFilePath(subcommand.FID); if (openedFilePath == null) { header.Status = NTStatus.STATUS_INVALID_HANDLE; return(null); } Transaction2SetFileInformationResponse response = new Transaction2SetFileInformationResponse(); switch (subcommand.InformationLevel) { case SetInformationLevel.SMB_INFO_STANDARD: { return(response); } case SetInformationLevel.SMB_INFO_SET_EAS: { throw new NotImplementedException(); } case SetInformationLevel.SMB_SET_FILE_BASIC_INFO: { string userName = state.GetConnectedUserName(header.UID); if (!share.HasWriteAccess(userName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(null); } SetFileBasicInfo info = (SetFileBasicInfo)subcommand.SetInfo; bool isHidden = (info.ExtFileAttributes & ExtendedFileAttributes.Hidden) > 0; bool isReadonly = (info.ExtFileAttributes & ExtendedFileAttributes.Readonly) > 0; bool isArchived = (info.ExtFileAttributes & ExtendedFileAttributes.Archive) > 0; try { share.FileSystem.SetAttributes(openedFilePath, isHidden, isReadonly, isArchived); } catch (UnauthorizedAccessException) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(null); } DateTime?creationTime = null; DateTime?lastWriteDT = null; DateTime?lastAccessTime = null; if (info.CreationTime != SMBHelper.FileTimeNotSpecified) { creationTime = info.CreationTime; } if (info.LastWriteTime != SMBHelper.FileTimeNotSpecified) { lastWriteDT = info.LastWriteTime; } if (info.LastAccessTime != SMBHelper.FileTimeNotSpecified) { lastAccessTime = info.LastAccessTime; } try { share.FileSystem.SetDates(openedFilePath, creationTime, lastWriteDT, lastAccessTime); } catch (IOException ex) { ushort errorCode = IOExceptionHelper.GetWin32ErrorCode(ex); if (errorCode == (ushort)Win32Error.ERROR_SHARING_VIOLATION) { // Returning STATUS_SHARING_VIOLATION is undocumented but apparently valid header.Status = NTStatus.STATUS_SHARING_VIOLATION; return(null); } else { header.Status = NTStatus.STATUS_DATA_ERROR; return(null); } } catch (UnauthorizedAccessException) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(null); } return(response); } case SetInformationLevel.SMB_SET_FILE_DISPOSITION_INFO: { if (((SetFileDispositionInfo)subcommand.SetInfo).DeletePending) { // We're supposed to delete the file on close, but it's too late to report errors at this late stage string userName = state.GetConnectedUserName(header.UID); if (!share.HasWriteAccess(userName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(null); } try { share.FileSystem.Delete(openedFilePath); } catch (IOException) { header.Status = NTStatus.STATUS_FILE_LOCK_CONFLICT; return(null); } catch (UnauthorizedAccessException) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(null); } } return(response); } case SetInformationLevel.SMB_SET_FILE_ALLOCATION_INFO: { // This subcommand is used to set the file length in bytes. // Note: the input will NOT be a multiple of the cluster size / bytes per sector. ulong allocationSize = ((SetFileAllocationInfo)subcommand.SetInfo).AllocationSize; try { Stream stream = share.FileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); stream.SetLength((long)allocationSize); stream.Close(); } catch { } return(response); } case SetInformationLevel.SMB_SET_FILE_END_OF_FILE_INFO: { ulong endOfFile = ((SetFileEndOfFileInfo)subcommand.SetInfo).EndOfFile; try { Stream stream = share.FileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); stream.SetLength((long)endOfFile); stream.Close(); } catch { } return(response); } default: { throw new InvalidRequestException(); } } }