/// <summary> /// to new a Smb response packet in type of the Command in SmbHeader. /// </summary> /// <param name="request">the request of the response.</param> /// <param name="smbHeader">the SMB header of the packet.</param> /// <param name="channel">the channel started with SmbParameters.</param> /// <returns> /// the new response packet. /// the null means that the utility don't know how to create the response. /// </returns> protected virtual SmbPacket CreateSmbResponsePacket( SmbPacket request, SmbHeader smbHeader, Channel channel) { return(CifsMessageUtils.CreateSmbResponsePacket(request, smbHeader, channel)); }
/// <summary> /// Build a Smb2Packet from a byte array /// </summary> /// <param name="data">The byte array</param> /// <param name="consumedLen">The consumed data length</param> /// <param name="expectedLen">The expected data length</param> internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen) { consumedLen = 0; this.Header = TypeMarshal.ToStruct <SmbHeader>(data, ref consumedLen); this.PayLoad = TypeMarshal.ToStruct <SmbNegotiateRequest>(data, ref consumedLen); expectedLen = 0; }
/// <summary> /// Build a Smb2Packet from a byte array /// </summary> /// <param name="data">The byte array</param> /// <param name="consumedLen">The consumed data length</param> /// <param name="expectedLen">The expected data length</param> internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen) { consumedLen = 0; this.Header = TypeMarshal.ToStruct<SmbHeader>(data, ref consumedLen); this.PayLoad = TypeMarshal.ToStruct<SmbNegotiateRequest>(data, ref consumedLen); expectedLen = 0; }
/// <summary> /// Update the andx packet header and all the its following batched packet's headers. /// </summary> public void UpdateHeader() { SmbHeader smbHeader = this.SmbHeader; SmbPacket nextPacket = this.AndxPacket; //update this header while (nextPacket != null) { smbHeader.Flags |= nextPacket.SmbHeader.Flags; smbHeader.Flags2 |= nextPacket.SmbHeader.Flags2; if (smbHeader.Status == 0) { smbHeader.Status = nextPacket.SmbHeader.Status; } if (nextPacket.SmbHeader.Uid != 0) { smbHeader.Uid = nextPacket.SmbHeader.Uid; } if (nextPacket.SmbHeader.Tid != 0) { smbHeader.Tid = nextPacket.SmbHeader.Tid; } nextPacket = nextPacket as SmbBatchedResponsePacket; if (nextPacket != null) { nextPacket = (nextPacket as SmbBatchedResponsePacket).AndxPacket; } } this.SmbHeader = smbHeader; //update andx packet header nextPacket = this.AndxPacket; while (nextPacket != null) { smbHeader = nextPacket.SmbHeader; smbHeader.Flags = this.SmbHeader.Flags; smbHeader.Flags2 = this.SmbHeader.Flags2; smbHeader.Uid = this.SmbHeader.Uid; smbHeader.Tid = this.SmbHeader.Tid; nextPacket.SmbHeader = smbHeader; nextPacket = nextPacket as SmbBatchedResponsePacket; if (nextPacket != null) { nextPacket = (nextPacket as SmbBatchedResponsePacket).AndxPacket; } } }
/// <summary> /// server response an error packet /// </summary> /// <param name="connection">the connection between server and client</param> /// <param name="status">error code</param> /// <param name="requestPacket">the request packet to send the error response</param> public override void SendErrorResponse( IFileServiceServerConnection connection, uint status, SmbFamilyPacket requestPacket) { CifsServerPerConnection cifsConnection = connection as CifsServerPerConnection; SmbPacket response = this.cifsServer.CreateDefaultResponse(cifsConnection, requestPacket as SmbPacket); SmbHeader smbHeader = response.SmbHeader; smbHeader.Status = status; response.SmbHeader = smbHeader; this.cifsServer.SendPacket(response, cifsConnection); }
/// <summary> /// to new a Smb request packet in type of the Command in SmbHeader. /// </summary> /// <param name="messageBytes">bytes contains packet</param> /// <returns> /// the new request packet. /// the null means that the utility don't know how to create the request. /// </returns> protected virtual SmbPacket CreateSmbRequestPacket(byte[] messageBytes) { SmbPacket smbRequest = null; using (MemoryStream stream = new MemoryStream(messageBytes, true)) { using (Channel channel = new Channel(null, stream)) { //read smb header and new SmbPacket if (messageBytes.Length >= CifsMessageUtils.PACKET_MINIMUM_LENGTH) { SmbHeader smbHeader = channel.Read <SmbHeader>(); smbRequest = CifsMessageUtils.CreateSmbRequestPacket(smbHeader, channel); } } } return(smbRequest); }
/// <summary> /// to new a Smb request packet in type of the Command in SmbHeader. /// </summary> /// <param name="messageBytes">bytes contains packet</param> /// <returns> /// the new request packet. /// the null means that the utility don't know how to create the request. /// </returns> protected override SmbPacket CreateSmbRequestPacket(byte[] messageBytes) { SmbPacket smbRequest = null; using (MemoryStream stream = new MemoryStream(messageBytes, true)) { using (Channel channel = new Channel(null, stream)) { // read smb header and new SmbPacket: if (channel.Stream.Position < channel.Stream.Length && messageBytes.Length >= CifsMessageUtils.GetSize <SmbHeader>(new SmbHeader())) { SmbHeader smbHeader = channel.Read <SmbHeader>(); smbRequest = FindTheTargetPacket(smbHeader, channel); } } } return(smbRequest); }
/// <summary> /// to read the andx packet from the channel /// </summary> /// <param name="channel">the channel started with the SmbParameters of the andx.</param> /// <returns>the size in bytes of the SmbParameters, SmbData and andx if existed of the andx.</returns> internal int ReadAndxFromChannel(Channel channel) { int consumedLen = 0; if (this.AndxCommand != SmbCommand.SMB_COM_NO_ANDX_COMMAND) { SmbHeader andxHeader = this.SmbHeader; andxHeader.Protocol = CifsMessageUtils.SMB_PROTOCOL_ANDXPACKET; andxHeader.Command = this.AndxCommand; this.andxPacket = CifsMessageUtils.CreateSmbRequestPacket(andxHeader, channel); this.andxPacket.SmbHeader = andxHeader; consumedLen += this.andxPacket.ReadParametersFromChannel(channel); consumedLen += this.andxPacket.ReadDataFromChannel(channel); SmbBatchedRequestPacket batchedRequest = this.andxPacket as SmbBatchedRequestPacket; if (batchedRequest != null) { consumedLen += batchedRequest.ReadAndxFromChannel(channel); } } return(consumedLen); }
/// <summary> /// decode packet from bytes /// </summary> /// <param name="messageBytes">bytes contains packet</param> /// <param name="consumedLength">the bytes length which are consumed when decode.</param> /// <returns>the decoded packet from the bytes array. if failed, return null.</returns> protected SmbPacket DecodeSmbRequestFromBytes( byte[] messageBytes, out int consumedLength) { consumedLength = 0; SmbPacket smbRequest = null; using (MemoryStream memoryStream = new MemoryStream(messageBytes, false)) { using (Channel channel = new Channel(null, memoryStream)) { smbRequest = CreateSmbRequestPacket(messageBytes); if (smbRequest == null) { return(null); } // decode smb header SmbHeader smbHeader = channel.Read <SmbHeader>(); consumedLength += smbRequest.HeaderSize; // set packet header smbRequest.SmbHeader = smbHeader; // read SmbParameters: consumedLength += smbRequest.ReadParametersFromChannel(channel); // read SmbData: consumedLength += smbRequest.ReadDataFromChannel(channel); // read andx: SmbBatchedRequestPacket smbBatchedRequest = smbRequest as SmbBatchedRequestPacket; if (smbBatchedRequest != null) { consumedLength += DecodeBatchedRequest(channel, smbBatchedRequest); } } } return(smbRequest); }
/// <summary> /// decode the batched request packet /// </summary> /// <param name="channel">the channel of bytes to read</param> /// <param name="request">the request of the response.</param> /// <param name="smbBatchedResponse">the batched response</param> /// <returns>the consumed length of batched response packet</returns> protected override int DecodeBatchedRequest( Channel channel, SmbPacket request, SmbBatchedResponsePacket smbBatchedResponse) { int result = base.DecodeBatchedRequest(channel, request, smbBatchedResponse); for (SmbBatchedResponsePacket currentPacket = smbBatchedResponse; currentPacket != null && currentPacket.AndxPacket != null; currentPacket = currentPacket.AndxPacket as SmbBatchedResponsePacket) { SmbPacket andxPacket = currentPacket.AndxPacket; // create the smb packet object smbParameters = ObjectUtility.GetFieldValue(currentPacket, "smbParameters"); if (smbParameters != null) { SmbHeader smbHeader = smbBatchedResponse.SmbHeader; smbHeader.Command = (SmbCommand)ObjectUtility.GetFieldValue(smbParameters, "AndXCommand"); andxPacket = CreateSmbResponsePacket(null, smbHeader, null); } // convert from cifs packet to smb packet if (andxPacket != null) { Type smbPacketType = andxPacket.GetType(); andxPacket = ObjectUtility.CreateInstance( smbPacketType.Module.FullyQualifiedName, smbPacketType.FullName, new object[] { currentPacket.AndxPacket }) as SmbPacket; } currentPacket.AndxPacket = andxPacket; } return(result); }
private bool SmbUpdateContextWithResponsePacket(SmbClientConnection connection, SmbPacket response) { if (response == null) { return false; } int connectionId = connection.ConnectionId; SmbHeader smbHeader = response.SmbHeader; // only process the response packet. if (response.PacketType != SmbPacketType.BatchedResponse && response.PacketType != SmbPacketType.SingleResponse) { return false; } // packet status SmbStatus packetStatus = (SmbStatus)smbHeader.Status; // filter error packet if (packetStatus != SmbStatus.STATUS_SUCCESS && packetStatus != SmbStatus.STATUS_MORE_PROCESSING_REQUIRED && packetStatus != SmbStatus.STATUS_BUFFER_OVERFLOW) { return false; } // process each special command switch (smbHeader.Command) { #region Negotiate Response case SmbCommand.SMB_COM_NEGOTIATE: // implicit ntlm, decode using cifs sdk. if (!smbClient.Capability.IsSupportsExtendedSecurity) { return false; } // down cast to negotiate response packet. SmbNegotiateResponsePacket negotiate = response as SmbNegotiateResponsePacket; // set negotiate flag connection.NegotiateSent = true; #region update security mode SecurityModes securityModes = negotiate.SmbParameters.SecurityMode; if (SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_ENABLED == (securityModes & SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) { connection.ServerSigningState = SignState.ENABLED; } else if (SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED == (securityModes & SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)) { connection.ServerSigningState = SignState.REQUIRED; } else { connection.ServerSigningState = SignState.DISABLED; } if (SecurityModes.NEGOTIATE_USER_SECURITY == (securityModes & SecurityModes.NEGOTIATE_USER_SECURITY)) { connection.UsesSharePasswords = false; } else { connection.UsesSharePasswords = true; } if (SecurityModes.NEGOTIATE_ENCRYPT_PASSWORDS == (securityModes & SecurityModes.NEGOTIATE_ENCRYPT_PASSWORDS)) { connection.IsClientEncryptPasswords = true; } else { connection.IsClientEncryptPasswords = false; } // update IsSignActive using the combination of the client's // MessageSigningPolicy and the connection's ServerSigningState smbClient.Context.UpdateSigningActive(connection); #endregion #region update server capabilities connection.ServerCapabilities = (Capabilities)negotiate.SmbParameters.Capabilities; if (Capabilities.CAP_INFOLEVEL_PASSTHRU == (connection.ServerCapabilities & Capabilities.CAP_INFOLEVEL_PASSTHRU)) { smbClient.Capability.IsUsePassThrough = true; } #endregion #region update maxbuffersize connection.MaxBufferSize = negotiate.SmbParameters.MaxBufferSize; #endregion this.AddOrUpdateConnection(connection); break; #endregion #region Session Setup Response case SmbCommand.SMB_COM_SESSION_SETUP_ANDX: // implicit ntlm, decode using cifs sdk. if (!smbClient.Capability.IsSupportsExtendedSecurity) { return false; } // the session to operation on. SmbClientSession session = null; // down-case the packet SmbSessionSetupAndxResponsePacket packet = response as SmbSessionSetupAndxResponsePacket; // if session exists, use it. if (this.GetSession(connectionId, smbHeader.Uid) != null) { session = new SmbClientSession(this.GetSession(connectionId, smbHeader.Uid)); } else { session = new SmbClientSession(); } // if success, update context and session key. if (packetStatus == SmbStatus.STATUS_SUCCESS) { // if spng, the SessionKey is null and the SecurityBlob from server contains data // in this situation, need to initialize the SecurityBlob of server to generate the SessionKey if (connection.GssApi.SessionKey == null && packet.SecurityBlob != null && packet.SecurityBlob.Length > 0) { connection.GssApi.Initialize(packet.SecurityBlob); } // get session key and store in the context session.SessionKey = connection.GssApi.SessionKey; // reset the gss api of connection connection.GssApi = null; // reset the securityblob when success packet.SecurityBlob = null; } // update the security blob from server connection.SecurityBlob = packet.SecurityBlob; this.AddOrUpdateConnection(connection); // update session session.SessionUid = smbHeader.Uid; session.ConnectionId = connectionId; this.AddOrUpdateSession(session); break; #endregion default: return false; } return true; }
/// <summary> /// create the nt transaction packet /// </summary> /// <param name="request">the request packet</param> /// <param name="smbHeader">the smb header of response packet</param> /// <param name="channel">the channel contains the packet bytes</param> /// <returns>the response packet</returns> private SmbPacket CreateNtTransactionResponsePacket(SmbPacket request, SmbHeader smbHeader, Channel channel) { SmbPacket smbPacket = null; if (smbHeader.Status == 0 && channel.Peek <byte>(0) == 0 && channel.Peek <ushort>(1) == 0) { return(smbPacket); } SmbNtTransactRequestPacket ntTransactRequest = request as SmbNtTransactRequestPacket; if (ntTransactRequest == null) { return(smbPacket); } // find regular packet switch ((uint)ntTransactRequest.SmbParameters.Function) { case (uint)NtTransSubCommand.NT_TRANSACT_RENAME: smbPacket = new SmbNtTransRenameResponsePacket(); break; case (uint)NtTransSubCommand.NT_TRANSACT_CREATE: smbPacket = new SmbNtTransactCreateResponsePacket(); break; case (uint)NtTransSubCommand.NT_TRANSACT_IOCTL: NT_TRANSACT_IOCTL_SETUP setup = CifsMessageUtils.ToStuct <NT_TRANSACT_IOCTL_SETUP>( CifsMessageUtils.ToBytesArray <ushort>(ntTransactRequest.SmbParameters.Setup)); switch ((NtTransFunctionCode)setup.FunctionCode) { case NtTransFunctionCode.FSCTL_SRV_ENUMERATE_SNAPSHOTS: smbPacket = new SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket(); break; case NtTransFunctionCode.FSCTL_SRV_REQUEST_RESUME_KEY: smbPacket = new SmbNtTransFsctlSrvRequestResumeKeyResponsePacket(); break; case NtTransFunctionCode.FSCTL_SRV_COPYCHUNK: smbPacket = new SmbNtTransFsctlSrvCopyChunkResponsePacket(); break; default: smbPacket = new SmbNtTransactIoctlResponsePacket(); break; } break; case (uint)SmbNtTransSubCommand.NT_TRANSACT_QUERY_QUOTA: smbPacket = new SmbNtTransQueryQuotaResponsePacket(); break; case (uint)SmbNtTransSubCommand.NT_TRANSACT_SET_QUOTA: smbPacket = new SmbNtTransSetQuotaResponsePacket(); break; default: break; } return(smbPacket); }
private SmbPacket CreateTransaction2ResponsePacket(SmbPacket request, SmbHeader smbHeader, Channel channel) { SmbPacket smbPacket = null; if (smbHeader.Status == 0 && channel.Peek <byte>(0) == 0 && channel.Peek <ushort>(1) == 0) { return(smbPacket); } SmbTransaction2RequestPacket transaction2Request = request as SmbTransaction2RequestPacket; if (transaction2Request == null) { return(smbPacket); } // if no setup command. break if (transaction2Request.SmbParameters.SetupCount == 0) { return(smbPacket); } // decode packet using the setup command switch ((Trans2SubCommand)transaction2Request.SmbParameters.Setup[0]) { case Trans2SubCommand.TRANS2_QUERY_FILE_INFORMATION: SmbTrans2QueryFileInformationRequestPacket queryFileRequest = transaction2Request as SmbTrans2QueryFileInformationRequestPacket; if (queryFileRequest != null) { smbPacket = new SmbTrans2QueryFileInformationResponsePacket( queryFileRequest.Trans2Parameters.InformationLevel); } break; case Trans2SubCommand.TRANS2_QUERY_PATH_INFORMATION: SmbTrans2QueryPathInformationRequestPacket queryPathRequest = transaction2Request as SmbTrans2QueryPathInformationRequestPacket; if (queryPathRequest != null) { smbPacket = new SmbTrans2QueryPathInformationResponsePacket( queryPathRequest.Trans2Parameters.InformationLevel); } break; case Trans2SubCommand.TRANS2_SET_FILE_INFORMATION: smbPacket = new SmbTrans2SetFileInformationResponsePacket(); break; case Trans2SubCommand.TRANS2_SET_PATH_INFORMATION: smbPacket = new SmbTrans2SetPathInformationResponsePacket(); break; case Trans2SubCommand.TRANS2_QUERY_FS_INFORMATION: SmbTrans2QueryFsInformationRequestPacket queryFsRequest = transaction2Request as SmbTrans2QueryFsInformationRequestPacket; if (queryFsRequest != null) { smbPacket = new SmbTrans2QueryFsInformationResponsePacket( queryFsRequest.Trans2Parameters.InformationLevel); } break; case Trans2SubCommand.TRANS2_SET_FS_INFORMATION: smbPacket = new SmbTrans2SetFsInformationResponsePacket(); break; case Trans2SubCommand.TRANS2_FIND_FIRST2: SmbTrans2FindFirst2RequestPacket first2Request = transaction2Request as SmbTrans2FindFirst2RequestPacket; if (first2Request != null) { smbPacket = new SmbTrans2FindFirst2ResponsePacket(first2Request.Trans2Parameters.InformationLevel, (first2Request.Trans2Parameters.Flags & Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS) == Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS); } break; case Trans2SubCommand.TRANS2_FIND_NEXT2: SmbTrans2FindNext2RequestPacket next2Request = transaction2Request as SmbTrans2FindNext2RequestPacket; if (next2Request != null) { smbPacket = new SmbTrans2FindNext2ResponsePacket(next2Request.Trans2Parameters.InformationLevel, (next2Request.Trans2Parameters.Flags & Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS) == Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS); } break; case Trans2SubCommand.TRANS2_GET_DFS_REFERRAL: smbPacket = new SmbTrans2GetDfsReferralResponsePacket(); break; default: break; } return(smbPacket); }
/// <summary> /// createt the transactions packet /// </summary> /// <param name="request">the request packet</param> /// <param name="smbHeader">the smb header of response packet</param> /// <param name="channel">the channel contains the packet bytes</param> /// <returns>the response packet</returns> private SmbPacket CreateTransactionResponsePacket(SmbPacket request, SmbHeader smbHeader, Channel channel) { SmbPacket smbPacket = null; if (smbHeader.Status == 0 && channel.Peek <byte>(0) == 0 && channel.Peek <ushort>(1) == 0) { return(smbPacket); } SmbTransactionRequestPacket transactionRequest = request as SmbTransactionRequestPacket; if (transactionRequest == null) { return(smbPacket); } switch (smbClient.Capability.TransactionSubCommand) { case TransSubCommandExtended.TRANS_EXT_MAILSLOT_WRITE: smbPacket = new SmbTransMailslotWriteResponsePacket(); break; case TransSubCommandExtended.TRANS_EXT_RAP: smbPacket = new SmbTransRapResponsePacket(); break; default: break; } // the packet is find if (smbPacket != null) { return(smbPacket); } // if no setup command. break if (transactionRequest.SmbParameters.SetupCount == 0) { return(smbPacket); } // decode packet using the setup command switch ((TransSubCommand)transactionRequest.SmbParameters.Setup[0]) { case TransSubCommand.TRANS_SET_NMPIPE_STATE: smbPacket = new SmbTransSetNmpipeStateResponsePacket(); break; case TransSubCommand.TRANS_QUERY_NMPIPE_STATE: smbPacket = new SmbTransQueryNmpipeStateResponsePacket(); break; case TransSubCommand.TRANS_RAW_READ_NMPIPE: smbPacket = new SmbTransRawReadNmpipeResponsePacket(); break; case TransSubCommand.TRANS_QUERY_NMPIPE_INFO: smbPacket = new SmbTransQueryNmpipeInfoResponsePacket(); break; case TransSubCommand.TRANS_PEEK_NMPIPE: smbPacket = new SmbTransPeekNmpipeResponsePacket(); break; case TransSubCommand.TRANS_TRANSACT_NMPIPE: smbPacket = new SmbTransTransactNmpipeResponsePacket(); break; case TransSubCommand.TRANS_READ_NMPIPE: smbPacket = new SmbTransReadNmpipeResponsePacket(); break; case TransSubCommand.TRANS_WRITE_NMPIPE: smbPacket = new SmbTransWriteNmpipeResponsePacket(); break; case TransSubCommand.TRANS_WAIT_NMPIPE: smbPacket = new SmbTransWaitNmpipeResponsePacket(); break; case TransSubCommand.TRANS_CALL_NMPIPE: smbPacket = new SmbTransCallNmpipeResponsePacket(); break; default: break; } return(smbPacket); }
protected override SmbPacket CreateSmbResponsePacket( SmbPacket request, SmbHeader smbHeader, Channel channel) { SmbPacket smbPacket = null; // error packet SmbStatus packetStatus = (SmbStatus)smbHeader.Status; // error packet if (packetStatus != SmbStatus.STATUS_SUCCESS && packetStatus != SmbStatus.STATUS_MORE_PROCESSING_REQUIRED && packetStatus != SmbStatus.STATUS_BUFFER_OVERFLOW) { smbPacket = new SmbErrorResponsePacket(); smbPacket.SmbHeader = smbHeader; return(smbPacket); } // success packet switch (smbHeader.Command) { case SmbCommand.SMB_COM_NEGOTIATE: if (smbClient.Capability.IsSupportsExtendedSecurity) { smbPacket = new SmbNegotiateResponsePacket(); } else { smbPacket = new SmbNegotiateImplicitNtlmResponsePacket(); } break; case SmbCommand.SMB_COM_SESSION_SETUP_ANDX: if (smbClient.Capability.IsSupportsExtendedSecurity) { smbPacket = new SmbSessionSetupAndxResponsePacket(); } else { smbPacket = new SmbSessionSetupImplicitNtlmAndxResponsePacket(); } break; case SmbCommand.SMB_COM_TREE_CONNECT_ANDX: smbPacket = new SmbTreeConnectAndxResponsePacket(); break; case SmbCommand.SMB_COM_TREE_DISCONNECT: smbPacket = new SmbTreeDisconnectResponsePacket(); break; case SmbCommand.SMB_COM_LOGOFF_ANDX: smbPacket = new SmbLogoffAndxResponsePacket(); break; case SmbCommand.SMB_COM_NT_CREATE_ANDX: smbPacket = new SmbNtCreateAndxResponsePacket(); break; case SmbCommand.SMB_COM_CLOSE: smbPacket = new SmbCloseResponsePacket(); break; case SmbCommand.SMB_COM_OPEN_ANDX: smbPacket = new SmbOpenAndxResponsePacket(); break; case SmbCommand.SMB_COM_WRITE_ANDX: smbPacket = new SmbWriteAndxResponsePacket(); break; case SmbCommand.SMB_COM_READ_ANDX: smbPacket = new SmbReadAndxResponsePacket(); break; case SmbCommand.SMB_COM_TRANSACTION: smbPacket = this.CreateTransactionResponsePacket(request, smbHeader, channel); break; case SmbCommand.SMB_COM_TRANSACTION2: smbPacket = this.CreateTransaction2ResponsePacket(request, smbHeader, channel); break; case SmbCommand.SMB_COM_NT_TRANSACT: smbPacket = this.CreateNtTransactionResponsePacket(request, smbHeader, channel); break; default: break; } if (smbPacket != null) { smbPacket.SmbHeader = smbHeader; return(smbPacket); } return(base.CreateSmbResponsePacket(request, smbHeader, channel)); }
/// <summary> /// decode packet from bytes /// </summary> /// <param name="connectId">the connection identity.</param> /// <param name="messageBytes">bytes contains packet</param> /// <param name="consumedLength">the bytes length which are consumed when decode.</param> /// <returns>the decoded packet from the bytes array. if failed, return null.</returns> protected SmbPacket DecodeSmbResponseFromBytes( int connectId, byte[] messageBytes, out int consumedLength) { consumedLength = 0; SmbPacket smbRequest = null; SmbPacket smbResponse = null; using (MemoryStream memoryStream = new MemoryStream(messageBytes, true)) { using (Channel channel = new Channel(null, memoryStream)) { // read raw response: Collection <SmbPacket> outstandingRequests = this.clientContext.GetOutstandingRequests(connectId); if (outstandingRequests != null && outstandingRequests.Count > 0) { SmbReadRawRequestPacket readRawRequest = outstandingRequests[0] as SmbReadRawRequestPacket; if (readRawRequest != null) { SmbReadRawResponsePacket readRawResponse = this.CreateSmbResponsePacket( readRawRequest, readRawRequest.SmbHeader, channel) as SmbReadRawResponsePacket; if (readRawResponse != null) { byte[] rawData = new byte[messageBytes.Length]; Array.Copy(messageBytes, rawData, rawData.Length); readRawResponse.RawData = rawData; consumedLength = rawData.Length; return(readRawResponse); } else { // discard the none-parsable data silently: consumedLength = messageBytes.Length; return(null); } } else { // No SmbReadRawResponsePacket sent, so the response should not be SmbReadRawResponsePacket. // and do nothing here. } } // read smb header and new SmbPacket: if (channel.Stream.Position < channel.Stream.Length && messageBytes.Length >= CifsMessageUtils.GetSize <SmbHeader>(new SmbHeader())) { SmbHeader smbHeader = channel.Read <SmbHeader>(); smbRequest = this.clientContext.GetOutstandingRequest(connectId, smbHeader.Mid); smbResponse = this.CreateSmbResponsePacket(smbRequest, smbHeader, channel); consumedLength += smbResponse.HeaderSize; } else { // The data in the channel is less than the size of SmbHeader. consume nothing and return null: consumedLength = 0; return(null); } // read SmbParameters: consumedLength += smbResponse.ReadParametersFromChannel(channel); // read SmbData: consumedLength += smbResponse.ReadDataFromChannel(channel); // read andx: SmbBatchedResponsePacket smbBatchedResponse = smbResponse as SmbBatchedResponsePacket; if (smbRequest != null && smbBatchedResponse != null) { consumedLength += DecodeBatchedRequest(channel, smbRequest, smbBatchedResponse); } // handle the difference of protocol implementation: SmbWriteAndCloseResponsePacket writeAndCloseResponse = smbResponse as SmbWriteAndCloseResponsePacket; if (writeAndCloseResponse != null) { if (this.clientConfig.IsWriteAndCloseResponseExtraPadding) { // Windows NT Server appends three NULL bytes to this message, following the ByteCount field. // These three bytes are not message data and can safely be discarded. const int PaddingLength = 3; writeAndCloseResponse.PaddingBytes = channel.ReadBytes(PaddingLength); consumedLength += PaddingLength; } } } } return(smbResponse); }
/// <summary> /// find the target packet. /// </summary> /// <param name="smbHeader">the header of smb packet</param> /// <param name="channel">the channel to access bytes</param> /// <returns>the target packet</returns> private static SmbPacket FindTheTargetPacket(SmbHeader smbHeader, Channel channel) { SmbPacket smbPacket = null; switch (smbHeader.Command) { case SmbCommand.SMB_COM_NEGOTIATE: smbPacket = new SmbNegotiateRequestPacket(); break; case SmbCommand.SMB_COM_SESSION_SETUP_ANDX: SmbHeader_Flags2_Values flags2 = (SmbHeader_Flags2_Values)smbHeader.Flags2; if ((flags2 & SmbHeader_Flags2_Values.SMB_FLAGS2_EXTENDED_SECURITY) == SmbHeader_Flags2_Values.SMB_FLAGS2_EXTENDED_SECURITY) { smbPacket = new Smb.SmbSessionSetupAndxRequestPacket(); } else { smbPacket = new Cifs.SmbSessionSetupAndxRequestPacket(); } break; case SmbCommand.SMB_COM_TREE_CONNECT_ANDX: smbPacket = new SmbTreeConnectAndxRequestPacket(); break; case SmbCommand.SMB_COM_NT_CREATE_ANDX: smbPacket = new SmbNtCreateAndxRequestPacket(); break; case SmbCommand.SMB_COM_OPEN_ANDX: smbPacket = new SmbOpenAndxRequestPacket(); break; case SmbCommand.SMB_COM_WRITE_ANDX: smbPacket = new SmbWriteAndxRequestPacket(); break; case SmbCommand.SMB_COM_READ_ANDX: smbPacket = new SmbReadAndxRequestPacket(); break; case SmbCommand.SMB_COM_CLOSE: smbPacket = new SmbCloseRequestPacket(); break; case SmbCommand.SMB_COM_TREE_DISCONNECT: smbPacket = new SmbTreeDisconnectRequestPacket(); break; case SmbCommand.SMB_COM_LOGOFF_ANDX: smbPacket = new SmbLogoffAndxRequestPacket(); break; case SmbCommand.SMB_COM_TRANSACTION: SMB_COM_TRANSACTION_Request_SMB_Parameters transaction = channel.Read <SMB_COM_TRANSACTION_Request_SMB_Parameters>(); if (transaction.SetupCount == 0) { smbPacket = new SmbTransRapRequestPacket(); } else { smbPacket = FindTheTransactionPacket( transaction.SetupCount, (TransSubCommand)transaction.Setup[0]); } break; case SmbCommand.SMB_COM_TRANSACTION2: SMB_COM_TRANSACTION2_Request_SMB_Parameters transaction2 = channel.Read <SMB_COM_TRANSACTION2_Request_SMB_Parameters>(); smbPacket = FindTheTrans2Packet((Trans2SubCommand)transaction2.Subcommand); break; case SmbCommand.SMB_COM_NT_TRANSACT: SMB_COM_NT_TRANSACT_Request_SMB_Parameters ntTransactoin = channel.Read <SMB_COM_NT_TRANSACT_Request_SMB_Parameters>(); smbPacket = FindTheNtTransPacket(ntTransactoin.Function, CifsMessageUtils.ToBytesArray <ushort>(ntTransactoin.Setup)); break; default: break; } return(smbPacket); }
/// <summary> /// update the context with response packet /// </summary> /// <param name="connection">the connection of endpoint</param> /// <param name="packet">the packet to update the context</param> private void ResponsePacketUpdateRoleContext(SmbServerConnection connection, SmbPacket packet) { SmbHeader smbHeader = packet.SmbHeader; SmbPacket requestPacket = connection.GetRequestPacket(smbHeader.Mid); if (requestPacket == null) { return; } switch (smbHeader.Command) { case SmbCommand.SMB_COM_SESSION_SETUP_ANDX: if (smbHeader.Uid == 0) { break; } else { SmbServerSession session = new SmbServerSession(); session.Uid = smbHeader.Uid; session.AuthenticationState = SessionState.Complete; session.Connection = connection; session.SessionKey = connection.GssApi.SessionKey; connection.AddSession(session); } break; case SmbCommand.SMB_COM_LOGOFF_ANDX: if (requestPacket.SmbHeader.Uid == 0) { break; } else { connection.RemoveSession(connection.GetSession(requestPacket.SmbHeader.Uid)); } break; case SmbCommand.SMB_COM_TREE_CONNECT_ANDX: { SmbTreeConnectAndxRequestPacket request = requestPacket as SmbTreeConnectAndxRequestPacket; SmbServerTreeConnect treeconnect = new SmbServerTreeConnect(); treeconnect.TreeId = smbHeader.Tid; treeconnect.Session = connection.GetSession(smbHeader.Uid); if (treeconnect.Session == null) { break; } if ((request.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) != 0) { treeconnect.Path = Encoding.Unicode.GetString(request.SmbData.Path); } else { treeconnect.Path = Encoding.ASCII.GetString(request.SmbData.Path); } treeconnect.Path = treeconnect.Path.TrimEnd('\0'); treeconnect.Session.AddTreeConnect(treeconnect); } break; case SmbCommand.SMB_COM_TREE_DISCONNECT: if (requestPacket.SmbHeader.Uid != 0) { SmbServerSession session = connection.GetSession(requestPacket.SmbHeader.Uid); if (session == null) { break; } session.RemoveTreeConnect(session.GetTreeConnect(requestPacket.SmbHeader.Tid)); } break; case SmbCommand.SMB_COM_NT_CREATE_ANDX: { SmbNtCreateAndxResponsePacket response = packet as SmbNtCreateAndxResponsePacket; SmbNtCreateAndxRequestPacket request = requestPacket as SmbNtCreateAndxRequestPacket; SmbServerOpen open = new SmbServerOpen(); open.SmbFid = response.SmbParameters.FID; open.PathName = SmbMessageUtils.GetString(request.SmbData.FileName, SmbFlags2.SMB_FLAGS2_UNICODE == (request.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE)); open.PathName = open.PathName.TrimEnd('\0'); open.Session = connection.GetSession(smbHeader.Uid); open.TreeConnect = connection.GetTreeConnect(smbHeader.Tid); if (open.TreeConnect == null) { break; } open.TreeConnect.AddOpen(open); } break; case SmbCommand.SMB_COM_OPEN_ANDX: { SmbOpenAndxResponsePacket response = packet as SmbOpenAndxResponsePacket; SmbOpenAndxRequestPacket request = requestPacket as SmbOpenAndxRequestPacket; SmbServerOpen open = new SmbServerOpen(); open.SmbFid = response.SmbParameters.FID; open.PathName = SmbMessageUtils.GetString(request.SmbData.FileName, SmbFlags2.SMB_FLAGS2_UNICODE == (request.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE)); open.Session = connection.GetSession(smbHeader.Uid); open.TreeConnect = connection.GetTreeConnect(smbHeader.Tid); if (open.TreeConnect == null) { break; } open.TreeConnect.AddOpen(open); } break; case SmbCommand.SMB_COM_CLOSE: { SmbCloseRequestPacket closeRequest = requestPacket as SmbCloseRequestPacket; SmbServerTreeConnect treeconnect = connection.GetTreeConnect(requestPacket.SmbHeader.Tid); if (treeconnect == null) { break; } treeconnect.RemoveOpen(treeconnect.GetOpen(closeRequest.SmbParameters.FID)); } break; default: break; } connection.RemoveRequestPacket(packet); }