/// <summary> /// Expect to receive a RDP_TUNNEL_CREATEREQUEST /// </summary> /// <param name="timeout"></param> /// <returns></returns> public RDP_TUNNEL_CREATEREQUEST ExpectTunnelCreateRequest(TimeSpan timeout) { if (Connected) { return(null); } DateTime endTime = DateTime.Now + timeout; RDP_TUNNEL_CREATEREQUEST createReq = null; while (DateTime.Now < endTime) { if (receiveBuffer.Count > 0) { lock (receiveBuffer) { if (receiveBuffer.Count > 0) { for (int i = 0; i < receiveBuffer.Count; i++) { if (receiveBuffer[i] is RDP_TUNNEL_CREATEREQUEST) { createReq = receiveBuffer[i] as RDP_TUNNEL_CREATEREQUEST; receiveBuffer.RemoveAt(i); return(createReq); } } } } } Thread.Sleep(waitInterval); } return(null); }
/// <summary> /// Establish a connection to server. /// </summary> /// <param name="requestId">The RequestID to be set in Tunnel Create Request PDU. </param> /// <param name="securityCooke">The SecurityCookie to be set in Tunnel Create Request PDU.</param> public bool Connect(uint requestId, byte[] securityCookie, TimeSpan timeout) { // Send a Tunnel Create Request. RDP_TUNNEL_CREATEREQUEST request = this.CreateTunnelCreateRequest(requestId, securityCookie); SendRdpemtPacket(request); // Expect a Tunnel Create Response. RDP_TUNNEL_CREATERESPONSE response = this.ExpectTunnelCreateResponse(timeout); if (null == response || response.HrResponse != HrResponse_S_OK) { return(false); } else { connected = true; return(true); } }
/// <summary> /// Expect a connection request from client. /// </summary> /// <param name="timeout">Timeout.</param> /// <param name="requestId">The requestID should be set in Tunnel Create Request.</param> /// <param name="securityCooke">The SecurityCookie should be set in Tunnel Create Request.</param> public bool ExpectConnect(TimeSpan timeout, out uint requestId, out byte[] securityCooke) { // Expect a Tunnel Create Request. RDP_TUNNEL_CREATEREQUEST createReq = this.ExpectTunnelCreateRequest(timeout); if (createReq == null) { requestId = 0; securityCooke = null; return(false); } requestId = createReq.RequestID; securityCooke = createReq.SecurityCookie; // Respond a Tunnel Create Response. RDP_TUNNEL_CREATERESPONSE createRes = this.CreateTunnelCreateResponse(HrResponse_S_OK); this.SendRdpemtPacket(createRes); connected = true; return(true); }
/// <summary> /// Create a RDP_TUNNEL_CREATEREQUEST /// </summary> /// <param name="reqestId">A 32-bit unsigned integer that contains the request ID included in the Initiate Multitransport Request PDU ([MS-RDPBCGR] section 2.2.15.1) that was sent over the main RDP connection.</param> /// <param name="securityCookie">A 16-byte element array of 8-bit unsigned integers that contains the security cookie included in the Initiate Multitransport Request PDU that was sent over the main RDP connection.</param> /// <returns>A RDP_TUNNEL_CREATEREQUEST instance.</returns> public RDP_TUNNEL_CREATEREQUEST CreateTunnelCreateRequest(uint reqestId, byte[] securityCookie) { RDP_TUNNEL_CREATEREQUEST createRes = new RDP_TUNNEL_CREATEREQUEST(); createRes.TunnelHeader = new RDP_TUNNEL_HEADER(); createRes.TunnelHeader.Action = RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_CREATEREQUEST; createRes.TunnelHeader.Flags = 0; createRes.TunnelHeader.PayloadLength = 24; createRes.TunnelHeader.HeaderLength = 4; createRes.TunnelHeader.SubHeaders = null; createRes.RequestID = reqestId; createRes.Reserved = 0; if (16 == securityCookie.Length) { createRes.SecurityCookie = new byte[securityCookie.Length]; Array.Copy(securityCookie, createRes.SecurityCookie, securityCookie.Length); return(createRes); } else { return(null); } }
/// <summary> /// Create a RDP_TUNNEL_CREATEREQUEST /// </summary> /// <param name="reqestId">A 32-bit unsigned integer that contains the request ID included in the Initiate Multitransport Request PDU ([MS-RDPBCGR] section 2.2.15.1) that was sent over the main RDP connection.</param> /// <param name="securityCookie">A 16-byte element array of 8-bit unsigned integers that contains the security cookie included in the Initiate Multitransport Request PDU that was sent over the main RDP connection.</param> /// <returns>A RDP_TUNNEL_CREATEREQUEST instance.</returns> public RDP_TUNNEL_CREATEREQUEST CreateTunnelCreateRequest(uint reqestId, byte[] securityCookie) { RDP_TUNNEL_CREATEREQUEST createRes = new RDP_TUNNEL_CREATEREQUEST(); createRes.TunnelHeader = new RDP_TUNNEL_HEADER(); createRes.TunnelHeader.Action = RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_CREATEREQUEST; createRes.TunnelHeader.Flags = 0; createRes.TunnelHeader.PayloadLength = 24; createRes.TunnelHeader.HeaderLength = 4; createRes.TunnelHeader.SubHeaders = null; createRes.RequestID = reqestId; createRes.Reserved = 0; if (16 == securityCookie.Length) { createRes.SecurityCookie = new byte[securityCookie.Length]; Array.Copy(securityCookie, createRes.SecurityCookie, securityCookie.Length); return createRes; } else { return null; } }
/// <summary> /// Call this method to decode byte array to MS-RDPEMT packets /// </summary> /// <param name="action">The action value in header</param> /// <param name="data">Data in bytes to be decoded</param> /// <returns>The decoded packet</returns> public static RdpemtBasePDU DecodeRdpemtPacket(byte[] data, ref int index) { if (data == null || data.Length - index < 4) { return null; } byte action = (byte)(0xF & data[index]); byte[] payloadLenData = new byte[2]; Array.Copy(data, index + 1, payloadLenData, 0, 2); if (!BitConverter.IsLittleEndian) { // Reverse the sequence if it is not little endian Array.Reverse(payloadLenData); } ushort payloadLength = BitConverter.ToUInt16(payloadLenData, 0); byte headerLength = data[index + 3]; int expectLen = payloadLength + headerLength; if (expectLen > data.Length) { return null; } byte[] toDecodeData = new byte[expectLen]; Array.Copy(data, index, toDecodeData, 0, expectLen); index += expectLen; RdpemtBasePDU rePdu = null; if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_CREATEREQUEST) { RDP_TUNNEL_CREATEREQUEST createReq = new RDP_TUNNEL_CREATEREQUEST(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, createReq); if (bResult) { rePdu = createReq; } } else if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_CREATERESPONSE) { RDP_TUNNEL_CREATERESPONSE createRes = new RDP_TUNNEL_CREATERESPONSE(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, createRes); if (bResult) { rePdu = createRes; } } else if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_DATA) { RDP_TUNNEL_DATA tunnelData = new RDP_TUNNEL_DATA(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, tunnelData); if (bResult) { rePdu = tunnelData; } } else { throw new NotSupportedException("Unknow action in RDP_TUNNEL_HEADER:" + action); } if (rePdu == null) { throw new NotSupportedException("Decode for RDPEMT PDU failed, Action:" + action); } return rePdu; }
/// <summary> /// Call this method to decode byte array to MS-RDPEMT packets /// </summary> /// <param name="action">The action value in header</param> /// <param name="data">Data in bytes to be decoded</param> /// <returns>The decoded packet</returns> public static RdpemtBasePDU DecodeRdpemtPacket(byte[] data, ref int index) { if (data == null || data.Length - index < 4) { return(null); } byte action = (byte)(0xF & data[index]); byte[] payloadLenData = new byte[2]; Array.Copy(data, index + 1, payloadLenData, 0, 2); if (!BitConverter.IsLittleEndian) { // Reverse the sequence if it is not little endian Array.Reverse(payloadLenData); } ushort payloadLength = BitConverter.ToUInt16(payloadLenData, 0); byte headerLength = data[index + 3]; int expectLen = payloadLength + headerLength; if (expectLen > data.Length) { return(null); } byte[] toDecodeData = new byte[expectLen]; Array.Copy(data, index, toDecodeData, 0, expectLen); index += expectLen; RdpemtBasePDU rePdu = null; if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_CREATEREQUEST) { RDP_TUNNEL_CREATEREQUEST createReq = new RDP_TUNNEL_CREATEREQUEST(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, createReq); if (bResult) { rePdu = createReq; } } else if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_CREATERESPONSE) { RDP_TUNNEL_CREATERESPONSE createRes = new RDP_TUNNEL_CREATERESPONSE(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, createRes); if (bResult) { rePdu = createRes; } } else if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_DATA) { RDP_TUNNEL_DATA tunnelData = new RDP_TUNNEL_DATA(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, tunnelData); if (bResult) { rePdu = tunnelData; } } else { throw new NotSupportedException("Unknow action in RDP_TUNNEL_HEADER:" + action); } if (rePdu == null) { throw new NotSupportedException("Decode for RDPEMT PDU failed, Action:" + action); } return(rePdu); }