/// <summary> /// to decode stack packet from the received message bytes. /// </summary> /// <param name = "endPoint">the endpoint from which the message bytes are received. </param> /// <param name = "messageBytes">the received message bytes to be decoded. </param> /// <param name = "consumedLength">the length of message bytes consumed by decoder. </param> /// <param name = "expectedLength">the length of message bytes the decoder expects to receive. </param> /// <returns>the stack packets decoded from the received message bytes. </returns> public StackPacket[] DecodePacketCallback( object endPoint, byte[] messageBytes, out int consumedLength, out int expectedLength) { // initialize the default values consumedLength = 0; expectedLength = 0; SmbPacket[] packets = new SmbPacket[0]; SmbPacket request = this.DecodeSmbRequestFromBytes(messageBytes, out consumedLength); // Use the decoded packet to UpdateRoleContext if it is not null and ContextUpdate is enabled: if (request != null) { if (this.serverContext.IsContextUpdateEnabled) { this.serverContext.UpdateRoleContext(this.serverContext.ConnectionTable[endPoint], request); } packets = new SmbPacket[] { request }; } expectedLength = 0; return packets; }
/// <summary> /// Deep copy constructor. /// </summary> /// <exception cref="System.ArgumentNullException">the smbPacket is null.</exception> protected SmbPacket(SmbPacket smbPacket) : base() { if (smbPacket == null) { throw new ArgumentNullException("smbPacket", "the copy constructor of smbpacket can not accept null smbPacket."); } lock (smbPacket) { this.isSignatureCorrect = smbPacket.isSignatureCorrect; this.transportHeader = new TransportHeader(); this.transportHeader.Zero = smbPacket.transportHeader.Zero; this.transportHeader.StreamProtocolLength = new byte[3]; this.transportHeader.StreamProtocolLength = smbPacket.transportHeader.StreamProtocolLength; this.SmbHeader = new SmbHeader(); this.smbHeader.Protocol = smbPacket.smbHeader.Protocol; this.smbHeader.Command = smbPacket.smbHeader.Command; this.smbHeader.Status = smbPacket.smbHeader.Status; this.smbHeader.Flags = smbPacket.smbHeader.Flags; this.smbHeader.Flags2 = smbPacket.smbHeader.Flags2; this.smbHeader.PidHigh = smbPacket.smbHeader.PidHigh; this.smbHeader.SecurityFeatures = smbPacket.smbHeader.SecurityFeatures; this.smbHeader.Reserved = smbPacket.smbHeader.Reserved; this.smbHeader.Tid = smbPacket.smbHeader.Tid; this.smbHeader.PidLow = smbPacket.smbHeader.PidLow; this.smbHeader.Uid = smbPacket.smbHeader.Uid; this.smbHeader.Mid = smbPacket.smbHeader.Mid; this.SmbParametersBlock = new SmbParameters(); this.smbParametersBlock.WordCount = smbPacket.smbParametersBlock.WordCount; if (smbPacket.smbParametersBlock.Words != null) { this.smbParametersBlock.Words = new ushort[smbPacket.smbParametersBlock.Words.Length]; Array.Copy(smbPacket.smbParametersBlock.Words, this.smbParametersBlock.Words, smbPacket.smbParametersBlock.Words.Length); } else { this.smbParametersBlock.Words = new ushort[0]; } this.SmbDataBlock = new SmbData(); this.smbDataBlock.ByteCount = smbPacket.smbDataBlock.ByteCount; if (smbPacket.smbDataBlock.Bytes != null) { this.smbDataBlock.Bytes = new byte[smbPacket.smbDataBlock.Bytes.Length]; Array.Copy(smbPacket.smbDataBlock.Bytes, this.smbDataBlock.Bytes, smbPacket.smbDataBlock.Bytes.Length); } else { this.smbDataBlock.Bytes = new byte[0]; } } }
/// <summary> /// Deep copy constructor. /// </summary> protected SmbBatchedRequestPacket(SmbBatchedRequestPacket packet) : base(packet) { lock (packet) { if (packet.andxPacket != null) { this.andxPacket = packet.AndxPacket.Clone() as SmbPacket; } } }
/// <summary> /// this function will be invoked every time a packet is sent or received. all logics about /// Client' states will be implemented here. /// response packet update the context, do regular transaction. /// </summary> /// <param name="connection">the connection object.</param> /// <param name="packet">the sent or received packet in stack transport.</param> protected virtual void ResponsePacketUpdateRoleContextRegular(Connection connection, SmbPacket packet) { int connectionId = connection.ConnectionId; #region RemoveOutstandingRequest if (packet.SmbHeader.Status != 0 ||!(packet is SmbTransactionInterimResponsePacket || packet is SmbTransaction2InterimResponsePacket || packet is SmbNtTransactInterimResponsePacket || packet is SmbWriteRawInterimResponsePacket)) { this.RemoveOutstandingRequest(connectionId, (ulong)packet.SmbHeader.Mid); } #endregion #region RemoveSequenceNumber this.RemoveSequenceNumber(connectionId, packet); #endregion }
/// <summary> /// remove the sequence number. /// </summary> /// <param name="response">the last response packet.</param> /// <exception cref="System.InvalidOperationException">the msg should be response.</exception> public void RemoveSequenceNumber(SmbPacket response) { this.serverSendSequenceNumbers.Remove(response.SmbHeader.Mid); }
protected virtual void ResponsePacketUpdateRoleContext( CifsClientPerConnection connection, SmbPacket request, SmbPacket response) { int connectionId = connection.ConnectionId; if (request ==null | response == null) { return; } #region To update Connection/Session/Tree/Open with response // Update context with success response: if (response.SmbHeader.Status == 0) { CifsClientPerSession session = new CifsClientPerSession(); CifsClientPerTreeConnect tree = new CifsClientPerTreeConnect(); CifsClientPerOpenFile openFile = new CifsClientPerOpenFile(); CifsClientPerOpenSearch openSearch = new CifsClientPerOpenSearch(); switch (response.SmbHeader.Command) { #region connection case SmbCommand.SMB_COM_NEGOTIATE: #region SMB_COM_NEGOTIATE SmbNegotiateRequestPacket negotiateRequest = request as SmbNegotiateRequestPacket; SmbNegotiateResponsePacket negotiateResponse = response as SmbNegotiateResponsePacket; if (negotiateRequest == null || negotiateResponse == null) { break; } // base class Connection: connection.NegotiateReceived = true; // common ADM: int dialectIndex = (int)(negotiateResponse.SmbParameters.DialectIndex); byte[] dialectBytes = negotiateRequest.SmbData.Dialects; int startIndex = 0; for (int i = 0; i < dialectIndex; i++) { startIndex = Array.IndexOf<byte>(dialectBytes, 0, startIndex, dialectBytes.Length - startIndex) + 1; } connection.SelectedDialect = CifsMessageUtils.ToSmbString(dialectBytes, startIndex, true); // client ADM: connection.ShareLevelAccessControl = ((negotiateResponse.SmbParameters.SecurityMode & SecurityModes.NEGOTIATE_ENCRYPT_PASSWORDS) == SecurityModes.NONE); connection.ServerChallengeResponse = ((negotiateResponse.SmbParameters.SecurityMode & SecurityModes.NEGOTIATE_ENCRYPT_PASSWORDS) == SecurityModes.NEGOTIATE_ENCRYPT_PASSWORDS); if (connection.ServerChallengeResponse && ((negotiateResponse.SmbParameters.SecurityMode & SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_ENABLED) == SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) { connection.ServerSigningState = SignStateValue.ENABLED; } if (connection.ServerSigningState == SignStateValue.ENABLED && ((negotiateResponse.SmbParameters.SecurityMode & SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) == SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)) { connection.ServerSigningState = SignStateValue.REQUIRED; } connection.ServerCapabilities = negotiateResponse.SmbParameters.Capabilities; connection.MaxBufferSize = negotiateResponse.SmbParameters.MaxBufferSize; // negotiate response: connection.SecurityMode = negotiateResponse.SmbParameters.SecurityMode; connection.MaxMpxCount = negotiateResponse.SmbParameters.MaxMpxCount; connection.MaxNumberVcs = negotiateResponse.SmbParameters.MaxNumberVcs; connection.MaxRawSize = negotiateResponse.SmbParameters.MaxRawSize; connection.SessionKey = negotiateResponse.SmbParameters.SessionKey; connection.SystemTime = negotiateResponse.SmbParameters.SystemTime.Time; connection.ServerTimeZone = negotiateResponse.SmbParameters.ServerTimeZone; if (negotiateResponse.SmbData.Challenge != null && negotiateResponse.SmbData.Challenge.Length >= 8) { connection.Challenge = BitConverter.ToUInt64(negotiateResponse.SmbData.Challenge, 0); } if (negotiateResponse.SmbData.DomainName != null) { connection.DomainName = new byte[negotiateResponse.SmbData.DomainName.Length]; Array.Copy(negotiateResponse.SmbData.DomainName, connection.DomainName, negotiateResponse.SmbData.DomainName.Length); } // stack sdk design: connection.ConnectionState = StackTransportState.ConnectionEstablished; // update: this.AddOrUpdateConnection(connection); #endregion break; #endregion #region session case SmbCommand.SMB_COM_SESSION_SETUP_ANDX: #region SMB_COM_SESSION_SETUP_ANDX SmbSessionSetupAndxRequestPacket sessionSetupRequest = request as SmbSessionSetupAndxRequestPacket; SmbSessionSetupAndxResponsePacket sessionSetupResponse = response as SmbSessionSetupAndxResponsePacket; if (sessionSetupRequest == null || sessionSetupResponse == null) { break; } session.ConnectionId = connectionId; session.SessionId = (ulong)sessionSetupResponse.SmbHeader.Uid; // in request: session.SessionKey = sessionSetupRequest.ImplicitNtlmSessionKey; session.MaxBufferSize = sessionSetupRequest.SmbParameters.MaxBufferSize; session.MaxMpxCount = sessionSetupRequest.SmbParameters.MaxMpxCount; session.VcNumber = sessionSetupRequest.SmbParameters.VcNumber; session.SessionKeyOfNegotiated = sessionSetupRequest.SmbParameters.SessionKey; session.Capabilities = sessionSetupRequest.SmbParameters.Capabilities; if ((sessionSetupRequest.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE) { session.UserAccount = new CifsUserAccount( Encoding.Unicode.GetString(sessionSetupRequest.SmbData.PrimaryDomain), Encoding.Unicode.GetString(sessionSetupRequest.SmbData.AccountName), Encoding.Unicode.GetString(sessionSetupRequest.SmbData.OEMPassword)); session.ClientNativeOs = Encoding.Unicode.GetString(sessionSetupRequest.SmbData.NativeOS); session.ClientNativeLanMan = Encoding.Unicode.GetString(sessionSetupRequest.SmbData.NativeLanMan); } else { session.UserAccount = new CifsUserAccount( Encoding.ASCII.GetString(sessionSetupRequest.SmbData.PrimaryDomain), Encoding.ASCII.GetString(sessionSetupRequest.SmbData.AccountName), Encoding.ASCII.GetString(sessionSetupRequest.SmbData.OEMPassword)); session.ClientNativeOs = Encoding.ASCII.GetString(sessionSetupRequest.SmbData.NativeOS); session.ClientNativeLanMan = Encoding.ASCII.GetString(sessionSetupRequest.SmbData.NativeLanMan); } // in response: session.Action = sessionSetupResponse.SmbParameters.Action; if ((sessionSetupResponse.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE) { session.ServerNativeOs = Encoding.Unicode.GetString(sessionSetupResponse.SmbData.NativeOS); session.ServerNativeLanMan = Encoding.Unicode.GetString(sessionSetupResponse.SmbData.NativeLanMan); session.ServerPrimaryDomain = Encoding.Unicode.GetString(sessionSetupResponse.SmbData.PrimaryDomain); } else { session.ServerNativeOs = Encoding.ASCII.GetString(sessionSetupResponse.SmbData.NativeOS); session.ServerNativeLanMan = Encoding.ASCII.GetString(sessionSetupResponse.SmbData.NativeLanMan); session.ServerPrimaryDomain = Encoding.ASCII.GetString(sessionSetupResponse.SmbData.PrimaryDomain); } if (connection.ShareLevelAccessControl == false) { connection.IsSigningActive = true; connection.ConnectionSigningSessionKey = sessionSetupRequest.ImplicitNtlmSessionKey; connection.ConnectionSigningChallengeResponse = sessionSetupRequest.SmbData.UnicodePassword; AddOrUpdateConnection(connection); } // update: this.AddOrUpdateSession(session); #endregion break; case SmbCommand.SMB_COM_LOGOFF_ANDX: #region SMB_COM_LOGOFF_ANDX SmbLogoffAndxResponsePacket logoffResponse = response as SmbLogoffAndxResponsePacket; if (logoffResponse == null) { break; } this.RemoveSession(connectionId, (ulong)logoffResponse.SmbHeader.Uid); #endregion break; #endregion #region treeconnect case SmbCommand.SMB_COM_TREE_CONNECT: #region SMB_COM_TREE_CONNECT SmbTreeConnectRequestPacket treeConnectRequest = request as SmbTreeConnectRequestPacket; SmbTreeConnectResponsePacket treeConnectResponse = response as SmbTreeConnectResponsePacket; if (treeConnectRequest == null || treeConnectResponse == null) { break; } tree.ConnectionId = connectionId; tree.SessionId = (ulong)treeConnectResponse.SmbHeader.Uid; tree.TreeId = (ulong)treeConnectResponse.SmbHeader.Tid; tree.ShareName = CifsMessageUtils.ToSmbString(treeConnectRequest.SmbData.Path, 0, false); int index = tree.ShareName.LastIndexOf(@"\"); if (index > 0) { tree.Share = tree.ShareName.Substring(index + 1); } else { tree.Share = tree.ShareName; } this.AddOrUpdateTreeConnect(tree); #endregion break; case SmbCommand.SMB_COM_TREE_CONNECT_ANDX: #region SMB_COM_TREE_CONNECT_ANDX SmbTreeConnectAndxRequestPacket treeConnectAndxRequest = request as SmbTreeConnectAndxRequestPacket; SmbTreeConnectAndxResponsePacket treeConnectAndxResponse = response as SmbTreeConnectAndxResponsePacket; if (treeConnectAndxRequest == null || treeConnectAndxResponse == null) { break; } tree.ConnectionId = connectionId; tree.SessionId = (ulong)treeConnectAndxResponse.SmbHeader.Uid; tree.TreeId = (ulong)treeConnectAndxResponse.SmbHeader.Tid; if ((treeConnectAndxRequest.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE) { tree.ShareName = Encoding.Unicode.GetString(treeConnectAndxRequest.SmbData.Path); } else { tree.ShareName = Encoding.ASCII.GetString(treeConnectAndxRequest.SmbData.Path); } int IndexOfShare = tree.ShareName.LastIndexOf(@"\"); if (IndexOfShare > 0) { tree.Share = tree.ShareName.Substring(IndexOfShare + 1); } else { tree.Share = tree.ShareName; } this.AddOrUpdateTreeConnect(tree); #endregion break; case SmbCommand.SMB_COM_TREE_DISCONNECT: #region SMB_COM_TREE_DISCONNECT SmbTreeDisconnectResponsePacket treeDisconnectResponse = response as SmbTreeDisconnectResponsePacket; if (treeDisconnectResponse == null) { break; } this.RemoveTreeConnect(connectionId, (ulong)treeDisconnectResponse.SmbHeader.Uid, (ulong)treeDisconnectResponse.SmbHeader.Tid); #endregion break; #endregion #region openfile case SmbCommand.SMB_COM_OPEN: #region SMB_COM_OPEN SmbOpenRequestPacket openRequest = request as SmbOpenRequestPacket; SmbOpenResponsePacket openResponse = response as SmbOpenResponsePacket; if (openRequest == null || openResponse == null) { break; } openFile.ConnectionId = connectionId; openFile.SessionId = (ulong)openResponse.SmbHeader.Uid; openFile.TreeConnectId = (ulong)openResponse.SmbHeader.Tid; openFile.FileHandle = openResponse.SmbParameters.FID; openFile.FileName = CifsMessageUtils.ToSmbString(openRequest.SmbData.FileName, 0, false); this.AddOrUpdateOpenFile(openFile); #endregion break; case SmbCommand.SMB_COM_CREATE: #region SMB_COM_CREATE SmbCreateRequestPacket createRequest = request as SmbCreateRequestPacket; SmbCreateResponsePacket createResponse = response as SmbCreateResponsePacket; if (createRequest == null || createResponse == null) { break; } openFile.ConnectionId = connectionId; openFile.SessionId = (ulong)createResponse.SmbHeader.Uid; openFile.TreeConnectId = (ulong)createResponse.SmbHeader.Tid; openFile.FileHandle = createResponse.SmbParameters.FID; openFile.FileName = CifsMessageUtils.ToSmbString(createRequest.SmbData.FileName, 0, false); this.AddOrUpdateOpenFile(openFile); #endregion break; case SmbCommand.SMB_COM_CREATE_TEMPORARY: #region SMB_COM_CREATE_TEMPORARY SmbCreateTemporaryRequestPacket createTemporaryRequest = request as SmbCreateTemporaryRequestPacket; SmbCreateTemporaryResponsePacket createTemporaryResponse = response as SmbCreateTemporaryResponsePacket; if (createTemporaryRequest == null || createTemporaryResponse == null) { break; } openFile.ConnectionId = connectionId; openFile.SessionId = (ulong)createTemporaryResponse.SmbHeader.Uid; openFile.TreeConnectId = (ulong)createTemporaryResponse.SmbHeader.Tid; openFile.FileHandle = createTemporaryResponse.SmbParameters.FID; openFile.FileName = CifsMessageUtils.ToSmbString( createTemporaryResponse.SmbData.TemporaryFileName, 0, false); this.AddOrUpdateOpenFile(openFile); #endregion break; case SmbCommand.SMB_COM_CREATE_NEW: #region SMB_COM_CREATE_NEW SmbCreateNewRequestPacket createNewRequest = request as SmbCreateNewRequestPacket; SmbCreateNewResponsePacket createNewResponse = response as SmbCreateNewResponsePacket; if (createNewRequest == null || createNewResponse == null) { break; } openFile.ConnectionId = connectionId; openFile.SessionId = (ulong)createNewResponse.SmbHeader.Uid; openFile.TreeConnectId = (ulong)createNewResponse.SmbHeader.Tid; openFile.FileHandle = createNewResponse.SmbParameters.FID; openFile.FileName = CifsMessageUtils.ToSmbString(createNewRequest.SmbData.FileName, 0, false); this.AddOrUpdateOpenFile(openFile); #endregion break; case SmbCommand.SMB_COM_OPEN_ANDX: #region SMB_COM_OPEN_ANDX SmbOpenAndxRequestPacket openAndxRequest = request as SmbOpenAndxRequestPacket; SmbOpenAndxResponsePacket openAndxResponse = response as SmbOpenAndxResponsePacket; if (openAndxRequest == null || openAndxResponse == null) { break; } openFile.ConnectionId = connectionId; openFile.SessionId = (ulong)openAndxResponse.SmbHeader.Uid; openFile.TreeConnectId = (ulong)openAndxResponse.SmbHeader.Tid; openFile.FileHandle = openAndxResponse.SmbParameters.FID; if ((openAndxRequest.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE) { openFile.FileName = Encoding.Unicode.GetString(openAndxRequest.SmbData.FileName); } else { openFile.FileName = Encoding.ASCII.GetString(openAndxRequest.SmbData.FileName); } this.AddOrUpdateOpenFile(openFile); #endregion //save FID for chained response like: //treeConnect->openAndx->readAndx->close //when "close", FID is need to close the open opened in openAndx. if (openAndxResponse.AndxPacket != null) { //borrow smbHeader.Protocol to save FID for later process. //smbHeader.Protocol also use a flag to differentiate a single packet from a //batched andx packet. //FID is ushort, impossible to impact smbHeader.Protocol's usage as //a real packet header 0x424D53FF(0xFF, 'S', 'M', 'B') SmbHeader andxHeader = openAndxResponse.AndxPacket.SmbHeader; andxHeader.Protocol = openAndxResponse.SmbParameters.FID; openAndxResponse.AndxPacket.SmbHeader = andxHeader; } break; case SmbCommand.SMB_COM_NT_CREATE_ANDX: #region SMB_COM_NT_CREATE_ANDX SmbNtCreateAndxRequestPacket ntCreateAndxRequest = request as SmbNtCreateAndxRequestPacket; SmbNtCreateAndxResponsePacket ntCreateAndxResponse = response as SmbNtCreateAndxResponsePacket; if (ntCreateAndxRequest == null || ntCreateAndxResponse == null) { break; } openFile.ConnectionId = connectionId; openFile.SessionId = (ulong)ntCreateAndxResponse.SmbHeader.Uid; openFile.TreeConnectId = (ulong)ntCreateAndxResponse.SmbHeader.Tid; openFile.FileHandle = ntCreateAndxResponse.SmbParameters.FID; if ((ntCreateAndxRequest.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE) { openFile.FileName = Encoding.Unicode.GetString(ntCreateAndxRequest.SmbData.FileName); } else { openFile.FileName = Encoding.ASCII.GetString(ntCreateAndxRequest.SmbData.FileName); } this.AddOrUpdateOpenFile(openFile); #endregion break; case SmbCommand.SMB_COM_OPEN_PRINT_FILE: #region SMB_COM_OPEN_PRINT_FILE SmbOpenPrintFileRequestPacket openPrintFileRequest = request as SmbOpenPrintFileRequestPacket; SmbOpenPrintFileResponsePacket openPrintFileResponse = response as SmbOpenPrintFileResponsePacket; if (openPrintFileRequest == null || openPrintFileResponse == null) { break; } openFile.ConnectionId = connectionId; openFile.SessionId = (ulong)openPrintFileResponse.SmbHeader.Uid; openFile.TreeConnectId = (ulong)openPrintFileResponse.SmbHeader.Tid; openFile.FileHandle = openPrintFileResponse.SmbParameters.FID; openFile.FileName = CifsMessageUtils.ToSmbString( openPrintFileRequest.SmbData.Identifier, 0, false); this.AddOrUpdateOpenFile(openFile); #endregion break; case SmbCommand.SMB_COM_TRANSACTION2: #region Trans2Open2 SmbTrans2Open2RequestPacket trans2Open2Request = request as SmbTrans2Open2RequestPacket; SmbTrans2Open2FinalResponsePacket trans2Open2Response = response as SmbTrans2Open2FinalResponsePacket; if (trans2Open2Request != null && trans2Open2Response != null) { openFile.ConnectionId = connectionId; openFile.SessionId = (ulong)trans2Open2Response.SmbHeader.Uid; openFile.TreeConnectId = (ulong)trans2Open2Response.SmbHeader.Tid; openFile.FileHandle = trans2Open2Response.Trans2Parameters.Fid; if ((trans2Open2Request.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE) { openFile.FileName = Encoding.Unicode.GetString( trans2Open2Request.Trans2Parameters.FileName); } else { openFile.FileName = Encoding.ASCII.GetString( trans2Open2Request.Trans2Parameters.FileName); } this.AddOrUpdateOpenFile(openFile); break; } #endregion #region Trans2FindFirst2 SmbTrans2FindFirst2RequestPacket trans2FindFirst2Request = request as SmbTrans2FindFirst2RequestPacket; SmbTrans2FindFirst2FinalResponsePacket trans2FindFirst2Response = response as SmbTrans2FindFirst2FinalResponsePacket; if (trans2FindFirst2Request != null && trans2FindFirst2Response != null) { openSearch.ConnectionId = connectionId; openSearch.SessionId = (ulong)trans2FindFirst2Response.SmbHeader.Uid; openSearch.TreeConnectId = (ulong)trans2FindFirst2Response.SmbHeader.Tid; openSearch.SearchID = trans2FindFirst2Response.Trans2Parameters.SID; if ((trans2FindFirst2Request.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE) { openSearch.SearchName = Encoding.Unicode.GetString( trans2FindFirst2Request.Trans2Parameters.FileName); } else { openSearch.SearchName = Encoding.ASCII.GetString( trans2FindFirst2Request.Trans2Parameters.FileName); } this.AddOrUpdateOpenSearch(openSearch); break; } #endregion break; case SmbCommand.SMB_COM_WRITE_AND_CLOSE: #region SMB_COM_WRITE_AND_CLOSE SmbWriteAndCloseRequestPacket writeAndCloseRequest = request as SmbWriteAndCloseRequestPacket; if (writeAndCloseRequest == null) { break; } this.RemoveOpenFile(connectionId, (ulong)response.SmbHeader.Uid, (ulong)response.SmbHeader.Tid, writeAndCloseRequest.SmbParameters.FID); #endregion break; case SmbCommand.SMB_COM_CLOSE: #region SMB_COM_CLOSE // Get FID from CLOSE request. // If fail, then get FID from the Batched Request. // If still fail, then Get FID from the Batched Response. ushort closeFId = 0; SmbCloseRequestPacket closeRequest = request as SmbCloseRequestPacket; if (closeRequest != null) { //Neither SMB_PROTOCOL_IDENTIFIER, or SMB_PROTOCOL_ANDXPACKET, then must be a FID if (response.SmbHeader.Protocol != CifsMessageUtils.SMB_PROTOCOL_IDENTIFIER && response.SmbHeader.Protocol != CifsMessageUtils.SMB_PROTOCOL_ANDXPACKET) { closeFId = (ushort)response.SmbHeader.Protocol; } else { closeFId = closeRequest.SmbParameters.FID; } this.RemoveOpenFile(connectionId, (ulong)response.SmbHeader.Uid, (ulong)response.SmbHeader.Tid, closeFId); } #endregion break; #endregion #region opensearch case SmbCommand.SMB_COM_FIND_CLOSE2: #region SMB_COM_FIND_CLOSE2 SmbFindClose2RequestPacket findClose2Request = request as SmbFindClose2RequestPacket; if (findClose2Request == null) { break; } this.RemoveOpenSearch(connectionId, (ulong)response.SmbHeader.Uid, (ulong)response.SmbHeader.Tid, findClose2Request.SmbParameters.SearchHandle); #endregion break; #endregion default: // No Connection/Session/Tree/Open will be updated if other types of response. break; } SmbBatchedRequestPacket smbBatchedRequest = request as SmbBatchedRequestPacket; SmbBatchedResponsePacket smbBatchedResponse = response as SmbBatchedResponsePacket; if (smbBatchedRequest != null && smbBatchedResponse != null) { //pass the FID stored in the andxHeader.Protocol into response.AndxPacket if (smbBatchedRequest.AndxPacket != null && smbBatchedResponse.AndxPacket != null && response.SmbHeader.Protocol != CifsMessageUtils.SMB_PROTOCOL_ANDXPACKET && response.SmbHeader.Protocol != CifsMessageUtils.SMB_PROTOCOL_IDENTIFIER) { SmbHeader andxHeader = smbBatchedResponse.AndxPacket.SmbHeader; andxHeader.Protocol = smbBatchedResponse.SmbHeader.Protocol; smbBatchedResponse.AndxPacket.SmbHeader = andxHeader; } this.ResponsePacketUpdateRoleContext(connection, smbBatchedRequest.AndxPacket, smbBatchedResponse.AndxPacket); } } #endregion }
/// <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> /// to decode stack packet from the received message bytes. /// the message bytes contains data without transport information /// </summary> /// <param name = "connection">the connection from which the message bytes are received. </param> /// <param name = "packetBytesWithoutTransport">the received message bytes to be decoded. </param> /// <param name = "consumedLength">the length of message bytes consumed by decoder. </param> /// <param name = "expectedLength">the length of message bytes the decoder expects to receive. </param> /// <returns>the stack packets decoded from the received message bytes. </returns> /// <exception cref="InvalidOperationException"> /// thrown when packet security signature is invalid. /// </exception> private SmbPacket[] DecodePacketFromBytesWithoutTransport( SmbServerConnection connection, byte[] packetBytesWithoutTransport, out int consumedLength, out int expectedLength) { expectedLength = 0; consumedLength = 0; SmbPacket[] packets = new SmbPacket[0]; int packetConsumedLength = 0; int packetExpectedLength = 0; // decode packets using cifs decorder. SmbPacket request = this.DecodeSmbRequestFromBytes( packetBytesWithoutTransport, out packetConsumedLength); // valid the signature if (request != null && request.SmbHeader.SecurityFeatures != 0 && connection.GssApi != null && connection.GssApi.SessionKey != null) { byte[] bytesToValid = ArrayUtility.SubArray(packetBytesWithoutTransport, 0); // the signature offset is 14. byte[] zeroSignature = new byte[sizeof(ulong)]; Array.Copy(zeroSignature, 0, bytesToValid, 14, zeroSignature.Length); // the signature offset is 14. zeroSignature = BitConverter.GetBytes((ulong)connection.ServerNextReceiveSequenceNumber); Array.Copy(zeroSignature, 0, bytesToValid, 14, zeroSignature.Length); byte[] signature = CifsMessageUtils.CreateSignature(bytesToValid, connection.GssApi.SessionKey); if (request.SmbHeader.SecurityFeatures != BitConverter.ToUInt64(signature, 0)) { throw new InvalidOperationException("packet security signature is invalid"); } } // Use the decoded packet to UpdateRoleContext if it is not null and ContextUpdate is enabled: if (request != null) { if (this.context.IsUpdateContext) { this.context.UpdateRoleContext(connection, request); } packets = new SmbPacket[] { request }; } // update the length after decode packet. consumedLength += packetConsumedLength; expectedLength += packetExpectedLength; return packets; }
/// <summary> /// update the sequence number of a connection. /// </summary> /// <param name="connectionId">the connection identity.</param> /// <param name="msg">the last request packet.</param> private void UpdateSequenceNumber(int connectionId, SmbPacket msg) { lock (this.contextCollection) { for (int i = this.contextCollection.ConnectionList.Count - 1; i >= 0; i--) { if (this.contextCollection.ConnectionList[i].ConnectionId == connectionId) { (this.contextCollection.ConnectionList[i] as CifsClientPerConnection).UpdateSequenceNumber(msg); return; } } } }
/// <summary> /// add request packet to the request list /// </summary> /// <param name="request">the request packet</param> internal void AddRequestPacket(SmbPacket request) { lock (this.requestList) { this.requestList[request.SmbHeader.Mid] = request; } }
/// <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; }
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 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; }
/// <summary> /// add a request into the table of OutstandingRequests. /// </summary> /// <param name="packet">the Outstanding Request.</param> /// <returns>false:the packet is not REQUEST or it is Cancel packet or the MessageId already exists in the table. /// otherwise true.</returns> internal bool AddOutstandingRequest(SmbPacket packet) { ulong mid = (ulong)(packet.SmbHeader.Mid); lock (this.RequestList) { if (this.RequestList.ContainsKey(mid)) { return false; } else { this.RequestList.Add(mid, packet); return true; } } }
/// <summary> /// update the sequence number. /// </summary> /// <param name="msg">the last request packet.</param> /// <exception cref="System.InvalidOperationException">the msg should be request.</exception> public void UpdateSequenceNumber(SmbPacket msg) { // only request can be used to UpdateSequenceNumber: if (msg.PacketType != SmbPacketType.SingleRequest && msg.PacketType != SmbPacketType.BatchedRequest) { throw new InvalidOperationException("the packet used to UpdateSequenceNumber should be request."); } // if the message is not signed, return. if (!msg.IsSignRequired) { return; } // update client sequence number if (msg.SmbHeader.Command == SmbCommand.SMB_COM_NT_CANCEL) { this.ClientNextSendSequenceNumber++; } else { this.clientResponseSequenceNumberList[msg.SmbHeader.Mid] = this.ClientNextSendSequenceNumber + 1; this.ClientNextSendSequenceNumber += 2; } }
/// <summary> /// remove the sequence number. /// </summary> /// <param name="msg">the last response packet.</param> /// <exception cref="System.InvalidOperationException">the msg should be response.</exception> public void RemoveSequenceNumber(SmbPacket msg) { // only response can be used to RemoveSequenceNumber: if (msg.PacketType != SmbPacketType.SingleResponse && msg.PacketType != SmbPacketType.BatchedResponse) { throw new InvalidOperationException("the packet used to RemoveSequenceNumber should be response."); } if (this.ClientResponseSequenceNumberList.ContainsKey(msg.SmbHeader.Mid)) { this.ClientResponseSequenceNumberList.Remove(msg.SmbHeader.Mid); } }
protected virtual void UpdateRoleContext(CifsClientPerConnection connection, SmbPacket packet) { // request packet: if ((packet.PacketType == SmbPacketType.BatchedRequest || packet.PacketType == SmbPacketType.SingleRequest) // Skip over the OpLock Break Notification request sent from server. && packet.SmbHeader.Protocol != CifsMessageUtils.SMB_PROTOCOL_IDENTIFIER_ASYNC && packet.SmbHeader.Mid != CifsMessageUtils.INVALID_MID) { RequestPacketUpdateRoleContext(connection, packet, false); } // response packet: else if (packet.PacketType == SmbPacketType.BatchedResponse || packet.PacketType == SmbPacketType.SingleResponse) { SmbPacket request = this.GetOutstandingRequest(connection.ConnectionId, (ulong)packet.SmbHeader.Mid); ResponsePacketUpdateRoleContext(connection, request, packet); if (connection.IsSigningActive && packet.IsSignRequired) { packet.IsSignatureCorrect = CifsMessageUtils.VerifySignature( packet, connection.ConnectionSigningSessionKey, (uint)connection.ClientResponseSequenceNumberList[packet.SmbHeader.Mid], connection.ConnectionSigningChallengeResponse); } ResponsePacketUpdateRoleContextRegular(connection, packet); } else { // Do nothing if neither request nor response. // No exception is thrown here because UpdateRoleContext is not responsible for checking the // invalidation of the packet. } }
/// <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; }
/// <summary> /// add a request into the table of OutstandingRequests. /// </summary> /// <param name="connectionId">the connection identity.</param> /// <param name="packet">the Outstanding Request.</param> public void AddOutstandingRequest(int connectionId, SmbPacket packet) { if (packet == null) { return; } lock (this.contextCollection) { for (int i = this.contextCollection.ConnectionList.Count - 1; i >= 0; i--) { if (this.contextCollection.ConnectionList[i].ConnectionId == connectionId) { (this.contextCollection.ConnectionList[i] as CifsClientPerConnection).AddOutstandingRequest(packet); return; } } } }
/// <summary> /// this function will be invoked every time a packet is sent or received. all logics about /// Client' states will be implemented here. /// </summary> /// <param name="connection">the connection object.</param> /// <param name="packet">the sent or received packet in stack transport.</param> protected override void UpdateRoleContext(CifsClientPerConnection connection, SmbPacket packet) { // Do nothing if no connection is found or the packet is not SmbPacket: if (connection == null || packet == null) { return; } // request packet: if (packet.PacketType == SmbPacketType.BatchedRequest || packet.PacketType == SmbPacketType.SingleRequest) { RequestPacketUpdateRoleContext(connection, packet, false); } // response packet: else if (packet.PacketType == SmbPacketType.BatchedResponse || packet.PacketType == SmbPacketType.SingleResponse) { if (!this.SmbUpdateContextWithResponsePacket(connection as SmbClientConnection, packet)) { SmbPacket request = this.GetOutstandingRequest(connection.ConnectionId, (ulong)packet.SmbHeader.Mid); ResponsePacketUpdateRoleContext(connection, request, packet); } ResponsePacketUpdateRoleContextRegular(connection, packet); } else { // Do nothing if neither request nor response. // No exception is thrown here because UpdateRoleContext is not responsible for checking the // invalidation of the packet. } }
/// <summary> /// Send packet to a specific connected client /// </summary> /// <param name="connection">connection to remote client</param> /// <param name="packet">the smb packet</param> /// <exception cref="ArgumentNullException">smbPacket</exception> /// <exception cref="ArgumentNullException">endpoint</exception> /// <exception cref="InvalidOperationException"> /// The transport is null for not started. Please invoke Start() first /// </exception> public virtual void SendPacket(SmbPacket packet, SmbServerConnection connection) { if (packet == null) { throw new ArgumentNullException("packet"); } if (connection == null) { throw new ArgumentNullException("connection"); } if (this.transport == null) { throw new InvalidOperationException( "The transport is null for not started. Please invoke Start() first."); } SmbPacket smbPacket = packet as SmbPacket; if (smbPacket != null && this.context.IsUpdateContext) { this.context.UpdateRoleContext(connection, smbPacket); } switch(this.transportType) { case TransportType.TCP: // send packet through the direct tcp this.transport.SendPacket(connection.Identity, new SmbDirectTcpPacket(packet)); break; case TransportType.NetBIOS: // send packet through netbios over Tcp this.transport.SendPacket(connection.Identity, smbPacket); break; default: break; } }
/// <summary> /// Send raw frame, which has been customized by upper layer modules. /// </summary> /// <param name = "smbPacket">SmbPacket is the base class of all the SM2 packets. </param> /// <exception cref="ArgumentNullException">smbPacket</exception> /// <exception cref="InvalidOperationException"> /// The transport is null for not connected to server. Please invoke Connect() first. /// </exception> public virtual void SendPacket(SmbPacket smbPacket) { if (smbPacket == null) { throw new ArgumentNullException("smbPacket"); } if (this.transport == null) { throw new InvalidOperationException( "The transport is null for not connected to server. Please invoke Connect() first."); } if (this.cifsClient.IsContextUpdateEnabled) { this.cifsClient.Context.UpdateRoleContext(this.ConnectionId, smbPacket); } switch (this.capability.TransportType) { case TransportType.TCP: // send packet through the direct tcp this.transport.SendPacket(new SmbDirectTcpPacket(smbPacket)); break; case TransportType.NetBIOS: // send packet through netbios over Tcp this.transport.SendPacket(smbPacket); break; default: break; } }
/// <summary> /// remove the request packet according to the response packet /// </summary> /// <param name="response">the response packet</param> internal void RemoveRequestPacket(SmbPacket response) { lock (this.requestList) { if (this.requestList.ContainsKey(response.SmbHeader.Mid)) { this.requestList.Remove(response.SmbHeader.Mid); } } }
/// <summary> /// update the context with request packet /// </summary> /// <param name="connection">the connection of endpoint</param> /// <param name="packet">the packet to update the context</param> private void RequestPacketUpdateRoleContext(SmbServerConnection connection, SmbPacket packet) { connection.AddRequestPacket(packet); // update the message id connection.MessageId = packet.SmbHeader.Mid; // update the process id connection.ProcessId = (uint)(packet.SmbHeader.PidHigh << 16); connection.ProcessId += packet.SmbHeader.PidLow; // update the message sign sequence number if (packet.SmbHeader.SecurityFeatures != 0 && connection.GssApi != null && connection.GssApi.SessionKey != null) { if (packet.SmbHeader.Command == SmbCommand.SMB_COM_NT_CANCEL) { connection.ServerNextReceiveSequenceNumber++; } else { ServerSendSequenceNumberKey key = new ServerSendSequenceNumberKey(); key.PidHigh = packet.SmbHeader.PidHigh; key.PidLow = packet.SmbHeader.PidLow; key.Mid = packet.SmbHeader.Mid; connection.ServerSendSequenceNumber[key] = connection.ServerNextReceiveSequenceNumber + 1; connection.ServerNextReceiveSequenceNumber += 2; } } // process each special command switch (packet.SmbHeader.Command) { case SmbCommand.SMB_COM_NEGOTIATE: SmbNegotiateRequestPacket request = packet as SmbNegotiateRequestPacket; byte[] dialects = request.SmbData.Dialects; List<string> negotiateDialects = new List<string>(); for (int i = 0; i < dialects.Length; i++) { if (dialects[i] == 0x02) { continue; } string dialect = ""; for (; i < dialects.Length && dialects[i] != 0x00; i++) { dialect += (char)dialects[i]; } negotiateDialects.Add(dialect); } connection.NegotiatedDialects = negotiateDialects.ToArray(); break; case SmbCommand.SMB_COM_TREE_CONNECT_ANDX: // down-case the packet Cifs.SmbTreeConnectAndxRequestPacket treeconnect = packet as Cifs.SmbTreeConnectAndxRequestPacket; // get the specified session. SmbServerSession treeconnectSession = connection.GetSession((ushort)treeconnect.SmbHeader.Uid); if (treeconnectSession == null) { return; } // Calculate the one-way hash byte[] sessionKey = FileServiceUtils.ProtectSessionKey(treeconnectSession.SessionKey); // update the session key state. treeconnectSession.SessionKeyState = SessionKeyStateValue.Available; // if server does not support SMB_EXTENDED_SIGNATURES, return. if (SmbClientTreeConnect.TreeConnectAndxExtendedSignatures != (treeconnect.SmbParameters.Flags & SmbClientTreeConnect.TreeConnectAndxExtendedSignatures)) { return; } treeconnectSession.SessionKey = sessionKey; break; default: return; } return; }
/// <summary> /// to decode stack packet from the received message bytes. /// the message bytes contains data without transport information /// </summary> /// <param name = "endpoint">the endpoint from which the message bytes are received. </param> /// <param name = "packetBytesWithoutTransport">the received message bytes to be decoded. </param> /// <param name = "consumedLength">the length of message bytes consumed by decoder. </param> /// <param name = "expectedLength">the length of message bytes the decoder expects to receive. </param> /// <returns>the stack packets decoded from the received message bytes. </returns> private SmbPacket[] DecodePacketFromBytesWithoutTransport( int endpoint, byte[] packetBytesWithoutTransport, out int consumedLength, out int expectedLength) { expectedLength = 0; consumedLength = 0; SmbPacket[] packets = new SmbPacket[0]; int packetConsumedLength = 0; int packetExpectedLength = 0; // decode packets using cifs decorder. SmbPacket response = this.DecodeSmbResponseFromBytes( (int)endpoint, packetBytesWithoutTransport, out packetConsumedLength); // Use the decoded packet to UpdateRoleContext if it is not null and ContextUpdate is enabled: if (response != null) { if (this.IsContextUpdateEnabled) { this.clientContext.UpdateRoleContext((int)endpoint, response); } packets = new SmbPacket[] { response }; } // update the length after decode packet. consumedLength += packetConsumedLength; expectedLength += packetExpectedLength; return packets; }
/// <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); }
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.IsUsePathThrough = 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> /// Expect a request. If user is not interested in the packet, please call DefaultSendResponse(). /// </summary> /// <param name="timeout">timeout</param> /// <param name="connection">the connection between server and client</param> /// <param name="session">the session between server and client</param> /// <param name="treeConnect">the tree connect between server and client</param> /// <param name="open">the file open between server and client</param> /// <param name="requestPacket">the request</param> public override void ExpectRequest( TimeSpan timeout, out IFileServiceServerConnection connection, out IFileServiceServerSession session, out IFileServiceServerTreeConnect treeConnect, out IFileServiceServerOpen open, out SmbFamilyPacket requestPacket) { CifsServerPerConnection cifsConnection; SmbPacket request = this.cifsServer.ExpectPacket(timeout, out cifsConnection); connection = cifsConnection; requestPacket = request; session = null; treeConnect = null; open = null; if (request != null) { session = cifsConnection.GetSession(request.SmbHeader.Uid); if (session != null) { treeConnect = (session as CifsServerPerSession).GetTreeConnect(request.SmbHeader.Tid); if (treeConnect != null) { ushort fid = 0; SmbTransactionRequestPacket transactionRequest = request as SmbTransactionRequestPacket; SmbNtTransactIoctlRequestPacket ioctlRequest = request as SmbNtTransactIoctlRequestPacket; SmbNtTransactNotifyChangeRequestPacket notifyChange = request as SmbNtTransactNotifyChangeRequestPacket; if (transactionRequest != null) { //SubCommand(2bytes), FID(2bytes) fid = transactionRequest.SmbParameters.Setup[1]; } else if (ioctlRequest != null) { //FunctionCode(4bytes), FID(2bytes), IsFctl(1bytes), IsFlags(1bytes) fid = ioctlRequest.SmbParameters.Setup[2]; } else if (notifyChange != null) { //CompletionFilter(4bytes), FID(2bytes), WatchTree(1bytes), Reserved(1bytes) fid = notifyChange.SmbParameters.Setup[2]; } else { Type packetType = request.GetType(); PropertyInfo pi = packetType.GetProperty( "Trans2Parameters", BindingFlags.Instance | BindingFlags.Public); if (pi == null) { pi = packetType.GetProperty( "NtTransParameters", BindingFlags.Instance | BindingFlags.Public); } if (pi == null) { pi = packetType.GetProperty( "SmbParameters", BindingFlags.Instance | BindingFlags.Public); } if (pi != null) { object smbParameters = pi.GetValue(request, null); FieldInfo fi = smbParameters.GetType().GetField( "FID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase); if (fi != null) { fid = (ushort)fi.GetValue(smbParameters); } } } if (fid > 0) { open = (treeConnect as CifsServerPerTreeConnect).GetOpen(fid); } } } } }
/// <summary> /// update the context of smb server /// </summary> /// <param name="connection">the connection of the client</param> /// <param name="packet">the packet to update the context</param> internal void UpdateRoleContext(SmbServerConnection connection, SmbPacket packet) { if (connection == null) { return; } // packet status SmbStatus packetStatus = (SmbStatus)packet.SmbHeader.Status; // filter error packet if (packetStatus != SmbStatus.STATUS_SUCCESS && packetStatus != SmbStatus.STATUS_MORE_PROCESSING_REQUIRED && packetStatus != SmbStatus.STATUS_BUFFER_OVERFLOW) { return; } // process the response packet. if (packet.PacketType == SmbPacketType.BatchedResponse || packet.PacketType == SmbPacketType.SingleResponse) { ResponsePacketUpdateRoleContext(connection, packet); return; } // process the request packet. if (packet.PacketType == SmbPacketType.BatchedRequest || packet.PacketType == SmbPacketType.SingleRequest) { RequestPacketUpdateRoleContext(connection, packet); return; } }
/// <summary> /// the transport /// </summary> /// <param name = "packet">the packet to send through TCP </param> public SmbDirectTcpPacket(SmbPacket packet) { this.packet = packet; }
/// <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); }
/// <summary> /// this function will be invoked every time a packet is sent or received. all logics about /// Client' states will be implemented here. /// request packet update the context /// </summary> /// <param name="connection">the connection object.</param> /// <param name="packet">the sent or received packet in stack transport.</param> /// <param name="isAndxPacket">the packet is andx packet or not.</param> protected virtual void RequestPacketUpdateRoleContext(CifsClientPerConnection connection, SmbPacket packet, bool isAndxPacket) { int connectionId = connection.ConnectionId; if (packet == null) { return; } #region To update Connection/Session/Tree/Open with request switch (packet.SmbHeader.Command) { case SmbCommand.SMB_COM_NEGOTIATE: connection.NegotiateSent = true; this.AddOrUpdateConnection(connection); break; default: // No Connection/Session/Tree/Open will be updated for other requests. break; } #endregion #region AddOutstandingRequest if (!isAndxPacket && packet.SmbHeader.Command != SmbCommand.SMB_COM_TRANSACTION_SECONDARY && packet.SmbHeader.Command != SmbCommand.SMB_COM_TRANSACTION2_SECONDARY && packet.SmbHeader.Command != SmbCommand.SMB_COM_NT_TRANSACT_SECONDARY && packet.SmbHeader.Command != SmbCommand.SMB_COM_NT_CANCEL) { this.AddOutstandingRequest(connectionId, packet); } else { // do nothing for requests of Andx, SECONDARY and CANCEL. } #endregion #region UpdateSequenceNumber if (!isAndxPacket) { this.UpdateSequenceNumber(connectionId, packet); } SmbBatchedRequestPacket batchedPacket = packet as SmbBatchedRequestPacket; if (batchedPacket != null) { RequestPacketUpdateRoleContext(connection, batchedPacket.AndxPacket, true); } #endregion }