internal static Transaction2FindNext2Response GetSubcommandResponse(SMBHeader header, Transaction2FindNext2Request subcommand, FileSystemShare share, StateObject state) { Transaction2FindNext2Response response = new Transaction2FindNext2Response(); if (!state.OpenSearches.ContainsKey(subcommand.SID)) { header.Status = NTStatus.STATUS_INVALID_HANDLE; return(null); } bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0; List <FileSystemEntry> entries = state.OpenSearches[subcommand.SID]; for (int index = 0; index < entries.Count; index++) { FindInformationEntry infoEntry = InfoHelper.FromFileSystemEntry(entries[index], subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys); response.FindInfoList.Add(infoEntry); if (response.FindInfoList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID)) { response.FindInfoList.RemoveAt(response.FindInfoList.Count - 1); break; } } int returnCount = response.FindInfoList.Count; entries.RemoveRange(0, returnCount); state.OpenSearches[subcommand.SID] = entries; response.SearchCount = (ushort)returnCount; response.EndOfSearch = (returnCount == entries.Count) && (entries.Count <= subcommand.SearchCount); return(response); }
internal static SMBCommand GetCreateDirectoryResponse(SMBHeader header, CreateDirectoryRequest request, FileSystemShare share, StateObject 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) { header.Status = NTStatus.STATUS_OBJECT_NAME_INVALID; return(new ErrorResponse(CommandName.SMB_COM_CREATE_DIRECTORY)); } catch (UnauthorizedAccessException) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(new ErrorResponse(CommandName.SMB_COM_CREATE_DIRECTORY)); } return(new CreateDirectoryResponse()); }
internal static Transaction2QueryFSInformationResponse GetSubcommandResponse(SMBHeader header, Transaction2QueryFSInformationRequest subcommand, FileSystemShare share) { Transaction2QueryFSInformationResponse response = new Transaction2QueryFSInformationResponse(); response.QueryFSInfo = InfoHelper.GetFSInformation(subcommand.InformationLevel, share.FileSystem); return(response); }
/// <summary> /// There are no secondary response messages. /// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request. /// The server MUST respond to the transaction request as a whole. /// </summary> internal static SMBCommand GetTransactionResponse(SMBHeader header, TransactionSecondaryRequest request, object share, StateObject state, List <SMBCommand> sendQueue) { ProcessStateObject processState = state.GetProcessState(header.PID); if (processState == null) { throw new InvalidRequestException(); } ByteWriter.WriteBytes(processState.TransactionParameters, request.ParameterDisplacement, request.TransParameters); ByteWriter.WriteBytes(processState.TransactionData, request.DataDisplacement, request.TransData); processState.TransactionParametersReceived += request.TransParameters.Length; processState.TransactionDataReceived += request.TransData.Length; if (processState.TransactionParametersReceived < processState.TransactionParameters.Length || processState.TransactionDataReceived < processState.TransactionData.Length) { return(null); } else { // We have a complete command if (request is Transaction2SecondaryRequest) { return(GetCompleteTransaction2Response(header, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state, sendQueue)); } else { return(GetCompleteTransactionResponse(header, processState.TransactionSetup, processState.TransactionParameters, processState.TransactionData, share, state, sendQueue)); } } }
/// <summary> /// There are no interim response messages. /// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request. /// The server MUST respond to the transaction request as a whole. /// </summary> internal static SMBCommand GetTransactionResponse(SMBHeader header, TransactionRequest request, object share, StateObject state, List <SMBCommand> sendQueue) { ProcessStateObject processState = state.ObtainProcessState(header.PID); processState.MaxDataCount = request.MaxDataCount; if (request.TransParameters.Length < request.TotalParameterCount || request.TransData.Length < request.TotalDataCount) { // A secondary transaction request is pending processState.TransactionSetup = request.Setup; processState.TransactionParameters = new byte[request.TotalParameterCount]; processState.TransactionData = new byte[request.TotalDataCount]; ByteWriter.WriteBytes(processState.TransactionParameters, 0, request.TransParameters); ByteWriter.WriteBytes(processState.TransactionData, 0, request.TransData); processState.TransactionParametersReceived += request.TransParameters.Length; processState.TransactionDataReceived += request.TransData.Length; return(null); } else { // We have a complete command if (request is Transaction2Request) { return(GetCompleteTransaction2Response(header, request.Setup, request.TransParameters, request.TransData, share, state, sendQueue)); } else { return(GetCompleteTransactionResponse(header, request.Setup, request.TransParameters, request.TransData, share, state, sendQueue)); } } }
internal static NegotiateResponseNTLM GetNegotiateResponse(SMBHeader header, NegotiateRequest request, byte[] serverChallenge) { NegotiateResponseNTLM response = new NegotiateResponseNTLM(); response.DialectIndex = (ushort)request.Dialects.IndexOf(SMBServer.NTLanManagerDialect); response.SecurityMode = SecurityMode.UserSecurityMode | SecurityMode.EncryptPasswords; response.MaxMpxCount = 50; response.MaxNumberVcs = 1; response.MaxBufferSize = 16644; response.MaxRawSize = 65536; response.Capabilities = ServerCapabilities.Unicode | ServerCapabilities.LargeFiles | ServerCapabilities.NTSMB | ServerCapabilities.NTStatusCode | ServerCapabilities.NTFind | ServerCapabilities.LargeRead | ServerCapabilities.LargeWrite; response.SystemTime = DateTime.UtcNow; response.ServerTimeZone = (short)-TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).TotalMinutes; response.Challenge = serverChallenge; response.DomainName = String.Empty; response.ServerName = String.Empty; return(response); }
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); }
public static byte[] PerformRead(SMBHeader header, object share, ushort FID, ulong offset, uint maxCount, StateObject state) { if (offset > Int64.MaxValue || maxCount > Int32.MaxValue) { throw new NotImplementedException("Underlying filesystem does not support unsigned offset / read count"); } return(PerformRead(header, share, FID, (long)offset, (int)maxCount, state)); }
internal static SMBCommand GetFindClose2Request(SMBHeader header, FindClose2Request request, StateObject state) { if (state.OpenSearches.ContainsKey(request.SearchHandle)) { state.OpenSearches.Remove(request.SearchHandle); } return(new FindClose2Response()); }
internal static SMBCommand GetTreeDisconnectResponse(SMBHeader header, TreeDisconnectRequest request, StateObject state) { if (!state.IsTreeConnected(header.TID)) { header.Status = NTStatus.STATUS_SMB_BAD_TID; return(new ErrorResponse(CommandName.SMB_COM_TREE_DISCONNECT)); } state.RemoveConnectedTree(header.TID); return(new TreeDisconnectResponse()); }
internal static SMBCommand GetCheckDirectoryResponse(SMBHeader 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 SMBCommand GetSessionSetupResponseExtended(SMBHeader header, SessionSetupAndXRequestExtended request, StateObject state) { SessionSetupAndXResponseExtended response = new SessionSetupAndXResponseExtended(); //see commit dd68473e2086bad4c57d39bb33d7c1a87d037144. Bunch of authentication stuff was removed response.Action = SessionSetupAction.SetupGuest; header.UID = state.AddConnectedUser("Guest"); response.NativeOS = String.Empty; // "Windows Server 2003 3790 Service Pack 2" response.NativeLanMan = String.Empty; // "Windows Server 2003 5.2" return(response); }
//////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////// public void NegotiateSMB() { SMBHeader smbHeader = new SMBHeader(); smbHeader.SetCommand(new Byte[] { 0x72 }); smbHeader.SetFlags(new Byte[] { 0x18 }); smbHeader.SetFlags2(new Byte[] { 0x01, 0x48 }); smbHeader.SetProcessID(processId.Take(2).ToArray()); smbHeader.SetUserID(new Byte[] { 0x00, 0x00 }); Byte[] bHeader = smbHeader.GetHeader(); SMBNegotiateProtocolRequest protocols = new SMBNegotiateProtocolRequest(); Byte[] bData = protocols.GetProtocols(); NetBIOSSessionService sessionService = new NetBIOSSessionService(); sessionService.SetHeaderLength(bHeader.Length); sessionService.SetDataLength(bData.Length); Byte[] bSessionService = sessionService.GetNetBIOSSessionService(); Byte[] send = Combine.combine(bSessionService, bHeader); send = Combine.combine(send, bData); streamSocket.Write(send, 0, send.Length); streamSocket.Flush(); Byte[] recieve = new Byte[81920]; streamSocket.Read(recieve, 0, recieve.Length); Byte[] response = recieve.Skip(5).Take(4).ToArray(); if (response == new Byte[] { 0xff, 0x53, 0x4d, 0x42 }) { Console.WriteLine("[-] SMB1 is not supported"); return; } version = "SMB2"; Byte[] keyLength = { 0x00, 0x00 }; if (recieve.Skip(70).Take(1).ToArray().SequenceEqual(new Byte[] { 0x03 })) { Console.WriteLine("[*] SMB Signing Required"); signing = true; flags = new Byte[] { 0x15, 0x82, 0x08, 0xa0 }; } else { signing = false; flags = new Byte[] { 0x05, 0x80, 0x08, 0xa0 }; } }
internal static SMBCommand GetWriteResponse(SMBHeader header, WriteRequest request, object share, StateObject state) { ushort bytesWritten = (ushort)PerformWrite(header, share, request.FID, request.WriteOffsetInBytes, request.Data, state); if (header.Status != NTStatus.STATUS_SUCCESS) { return(new ErrorResponse(CommandName.SMB_COM_WRITE_ANDX)); } WriteResponse response = new WriteResponse(); response.CountOfBytesWritten = bytesWritten; return(response); }
internal static SMBCommand GetReadResponse(SMBHeader header, ReadRequest request, object share, StateObject state) { byte[] data = PerformRead(header, share, request.FID, request.ReadOffsetInBytes, request.CountOfBytesToRead, state); if (header.Status != NTStatus.STATUS_SUCCESS) { return(new ErrorResponse(CommandName.SMB_COM_READ)); } ReadResponse response = new ReadResponse(); response.Bytes = data; response.CountOfBytesReturned = (ushort)data.Length; return(response); }
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 GetTreeConnectResponse(SMBHeader header, TreeConnectAndXRequest request, StateObject state, ShareCollection shares) { bool isExtended = (request.Flags & TreeConnectFlags.ExtendedResponse) > 0; string relativePath = ServerPathUtils.GetRelativeServerPath(request.Path); if (String.Equals(relativePath, "\\IPC$", StringComparison.InvariantCultureIgnoreCase)) { header.TID = state.AddConnectedTree(relativePath); if (isExtended) { return(CreateTreeConnectResponseExtended(ServiceName.NamedPipe)); } else { return(CreateTreeConnectResponse(ServiceName.NamedPipe)); } } else { FileSystemShare share = shares.GetShareFromRelativePath(relativePath); if (share == null) { header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND; return(new ErrorResponse(CommandName.SMB_COM_TREE_CONNECT_ANDX)); } else { string userName = state.GetConnectedUserName(header.UID); if (!share.HasReadAccess(userName)) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(new ErrorResponse(CommandName.SMB_COM_TREE_CONNECT_ANDX)); } else { header.TID = state.AddConnectedTree(relativePath); if (isExtended) { return(CreateTreeConnectResponseExtended(ServiceName.DiskShare)); } else { return(CreateTreeConnectResponse(ServiceName.DiskShare)); } } } } }
internal static SMBCommand GetRenameResponse(SMBHeader header, RenameRequest request, FileSystemShare share, StateObject 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) { header.Status = NTStatus.STATUS_SHARING_VIOLATION; return(new ErrorResponse(CommandName.SMB_COM_RENAME)); } catch (UnauthorizedAccessException) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(new ErrorResponse(CommandName.SMB_COM_RENAME)); } }
internal static SMBCommand GetSetInformationResponse(SMBHeader header, SetInformationRequest request, FileSystemShare share, StateObject 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 & SMBLibrary.SMB1.FileAttributes.Hidden) > 0) { isHidden = true; } if ((request.FileAttributes & SMBLibrary.SMB1.FileAttributes.ReadOnly) > 0) { isReadOnly = true; } if ((request.FileAttributes & SMBLibrary.SMB1.FileAttributes.Archive) > 0) { isArchived = true; } fileSystem.SetAttributes(request.FileName, isHidden, isReadOnly, isArchived); if (request.LastWriteTime != SMBHelper.UTimeNotSpecified) { fileSystem.SetDates(request.FileName, null, request.LastWriteTime, null); } return(new SetInformationResponse()); }
internal static SMBCommand GetCompleteNTTransactResponse(SMBHeader header, NTTransactSubcommandName subcommandName, byte[] requestSetup, byte[] requestParameters, byte[] requestData, object share, StateObject state, List <SMBCommand> sendQueue) { NTTransactSubcommand subcommand = NTTransactSubcommand.GetSubcommandRequest(subcommandName, requestSetup, requestParameters, requestData, header.UnicodeFlag); NTTransactSubcommand subcommandResponse = null; if (subcommand is NTTransactCreateRequest) { header.Status = NTStatus.STATUS_NOT_IMPLEMENTED; } else if (subcommand is NTTransactIOCTLRequest) { subcommandResponse = GetSubcommandResponse(header, (NTTransactIOCTLRequest)subcommand); } else if (subcommand is NTTransactSetSecurityDescriptor) { header.Status = NTStatus.STATUS_NOT_IMPLEMENTED; } else if (subcommand is NTTransactNotifyChangeRequest) { header.Status = NTStatus.STATUS_NOT_IMPLEMENTED; } else if (subcommand is NTTransactQuerySecurityDescriptorRequest) { header.Status = NTStatus.STATUS_NOT_IMPLEMENTED; } else { header.Status = NTStatus.STATUS_SMB_BAD_COMMAND; } if (header.Status != NTStatus.STATUS_SUCCESS) { return(new ErrorResponse(CommandName.SMB_COM_NT_TRANSACT)); } byte[] responseSetup = subcommandResponse.GetSetup(); byte[] responseParameters = subcommandResponse.GetParameters(header.UnicodeFlag); byte[] responseData = subcommandResponse.GetData(); NTTransactResponse response = new NTTransactResponse(); PrepareResponse(response, responseSetup, responseParameters, responseData, state.MaxBufferSize, sendQueue); return(response); }
internal static SMBCommand GetWriteResponse(SMBHeader header, WriteAndXRequest request, object share, StateObject state) { uint bytesWritten = PerformWrite(header, share, request.FID, request.Offset, request.Data, state); if (header.Status != NTStatus.STATUS_SUCCESS) { return(new ErrorResponse(CommandName.SMB_COM_WRITE_ANDX)); } WriteAndXResponse response = new WriteAndXResponse(); response.Count = bytesWritten; if (share is FileSystemShare) { // If the client wrote to a disk file, this field MUST be set to 0xFFFF. response.Available = 0xFFFF; } return(response); }
internal static SMBCommand GetQueryInformationResponse(SMBHeader 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 SMBCommand GetDeleteResponse(SMBHeader header, DeleteRequest request, FileSystemShare share, StateObject 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 & SMBLibrary.SMB1.FileAttributes.Directory) > 0 || entry.IsDirectory && (request.SearchAttributes & SMBLibrary.SMB1.FileAttributes.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) { header.Status = NTStatus.STATUS_CANNOT_DELETE; return(new ErrorResponse(CommandName.SMB_COM_DELETE)); } catch (UnauthorizedAccessException) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(new ErrorResponse(CommandName.SMB_COM_DELETE)); } }
private static NTTransactIOCTLResponse GetSubcommandResponse(SMBHeader header, NTTransactIOCTLRequest subcommand) { const uint FSCTL_CREATE_OR_GET_OBJECT_ID = 0x900C0; NTTransactIOCTLResponse response = new NTTransactIOCTLResponse(); if (subcommand.IsFsctl) { if (subcommand.FunctionCode == FSCTL_CREATE_OR_GET_OBJECT_ID) { ObjectIDBufferType1 objectID = new ObjectIDBufferType1(); objectID.ObjectId = Guid.NewGuid(); response.Data = objectID.GetBytes(); return(response); } } header.Status = NTStatus.STATUS_NOT_IMPLEMENTED; return(null); }
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()); }
private static SMBHeader DataToSmbHeader(byte[] data, int receivedBytes, bool allowSuccessfulStatusOnly) { SMBHeader sMBHeader = default(SMBHeader); int num = 4; int num2 = Marshal.SizeOf((object)sMBHeader); int num3 = num2 + num; if (receivedBytes < num3) { throw new Exception("Bytes received = " + receivedBytes + " while required size = " + num3); } IntPtr intPtr = Marshal.AllocHGlobal(num2); Marshal.Copy(data, num, intPtr, num2); sMBHeader = (SMBHeader)Marshal.PtrToStructure(intPtr, typeof(SMBHeader)); Marshal.FreeHGlobal(intPtr); if (allowSuccessfulStatusOnly && !isSuccessfullSMB(sMBHeader)) { throw new Exception(SmbStatusToMessage(sMBHeader)); } return(sMBHeader); }
/// <summary> /// The client MUST send as many secondary requests as are needed to complete the transfer of the transaction request. /// </summary> internal static SMBCommand GetNTTransactResponse(SMBHeader header, NTTransactRequest request, object share, StateObject state, List <SMBCommand> sendQueue) { if (request.TransParameters.Length < request.TotalParameterCount || request.TransData.Length < request.TotalDataCount) { ProcessStateObject processState = state.ObtainProcessState(header.PID); // A secondary transaction request is pending processState.SubcommandID = (ushort)request.Function; processState.TransactionSetup = request.Setup; processState.TransactionParameters = new byte[request.TotalParameterCount]; processState.TransactionData = new byte[request.TotalDataCount]; ByteWriter.WriteBytes(processState.TransactionParameters, 0, request.TransParameters); ByteWriter.WriteBytes(processState.TransactionData, 0, request.TransData); processState.TransactionParametersReceived += request.TransParameters.Length; processState.TransactionDataReceived += request.TransData.Length; return(new NTTransactInterimResponse()); } else { // We have a complete command return(GetCompleteNTTransactResponse(header, request.Function, request.Setup, request.TransParameters, request.TransData, share, state, sendQueue)); } }
internal static SMBCommand GetSessionSetupResponse(SMBHeader header, SessionSetupAndXRequest request, StateObject state) { SessionSetupAndXResponse response = new SessionSetupAndXResponse(); // The PrimaryDomain field in the request is used to determine with domain controller should authenticate the user credentials, // However, the domain controller itself does not use this field. // See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378749%28v=vs.85%29.aspx response.Action = SessionSetupAction.SetupGuest; response.PrimaryDomain = request.PrimaryDomain; header.UID = state.AddConnectedUser("Guest"); if ((request.Capabilities & ServerCapabilities.LargeRead) > 0) { state.LargeRead = true; } if ((request.Capabilities & ServerCapabilities.LargeWrite) > 0) { state.LargeWrite = true; } response.NativeOS = String.Empty; // "Windows Server 2003 3790 Service Pack 2" response.NativeLanMan = String.Empty; // "Windows Server 2003 5.2" return(response); }
internal static SMBCommand GetReadResponse(SMBHeader header, ReadAndXRequest request, object share, StateObject state) { uint maxCount = request.MaxCount; if ((share is FileSystemShare) && state.LargeRead) { maxCount = request.MaxCountLarge; } byte[] data = PerformRead(header, share, request.FID, request.Offset, maxCount, state); if (header.Status != NTStatus.STATUS_SUCCESS) { return(new ErrorResponse(CommandName.SMB_COM_READ_ANDX)); } ReadAndXResponse response = new ReadAndXResponse(); if (share is FileSystemShare) { // If the client reads from a disk file, this field MUST be set to -1 (0xFFFF) response.Available = 0xFFFF; } response.Data = data; return(response); }
public static byte[] PerformRead(SMBHeader header, object share, ushort FID, long offset, int maxCount, StateObject state) { OpenedFileObject openedFile = state.GetOpenedFileObject(FID); if (openedFile == null) { header.Status = NTStatus.STATUS_INVALID_HANDLE; return(null); } string openedFilePath = openedFile.Path; if (share is NamedPipeShare) { return(state.RetrieveNamedPipeReply(FID)); } else // FileSystemShare { FileSystemShare fileSystemShare = (FileSystemShare)share; IFileSystem fileSystem = fileSystemShare.FileSystem; if (openedFile.IsSequentialAccess) { bool isInCache = (offset >= openedFile.CacheOffset) && (offset + maxCount <= openedFile.CacheOffset + openedFile.Cache.Length); if (!isInCache) { int bytesRead; try { Stream stream = fileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); stream.Seek(offset, SeekOrigin.Begin); openedFile.CacheOffset = offset; openedFile.Cache = new byte[OpenedFileObject.CacheSize]; bytesRead = stream.Read(openedFile.Cache, 0, OpenedFileObject.CacheSize); stream.Close(); } 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); } if (bytesRead < OpenedFileObject.CacheSize) { // EOF, we must trim the response data array byte[] buffer = new byte[bytesRead]; Array.Copy(openedFile.Cache, 0, buffer, 0, bytesRead); openedFile.Cache = buffer; } } int offsetInCache = (int)(offset - openedFile.CacheOffset); int bytesRemained = openedFile.Cache.Length - offsetInCache; int dataLength = Math.Min(maxCount, bytesRemained); byte[] data = new byte[dataLength]; Array.Copy(openedFile.Cache, offsetInCache, data, 0, dataLength); return(data); } else { int bytesRead; byte[] data; try { Stream stream = fileSystem.OpenFile(openedFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); stream.Seek(offset, SeekOrigin.Begin); data = new byte[maxCount]; bytesRead = stream.Read(data, 0, maxCount); stream.Close(); } 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 (ArgumentOutOfRangeException) { header.Status = NTStatus.STATUS_DATA_ERROR; return(null); } catch (UnauthorizedAccessException) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(null); } if (bytesRead < maxCount) { // EOF, we must trim the response data array byte[] buffer = new byte[bytesRead]; Array.Copy(data, 0, buffer, 0, bytesRead); data = buffer; } return(data); } } }