/// <summary> /// Send a Tunnel Data PDU with RDP_NETCHAR_RESULT in its subheader /// </summary> /// <param name="requestedProtocol"></param> /// <param name="sequenceNumber"></param> private void SendTunnelDataPdu_NetcharResult(Multitransport_Protocol_value requestedProtocol, ushort sequenceNumber) { autoDetectedBaseRTT = (uint)(rttDataStore.responseTime - rttDataStore.requestTime).Milliseconds; autoDetectedAverageRTT = (uint)(rttDataStore.responseTime - rttDataStore.requestTime).Milliseconds; if (bwDataStore.timeDelta != 0) { autoDetectedBandwidth = (bwDataStore.byteCount * 8) / bwDataStore.timeDelta; } RdpemtServer rdpemtServer = rdpemtServerR; if (requestedProtocol == Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECL) { rdpemtServer = rdpemtServerL; } RDP_NETCHAR_RESULT netResult = RdpbcgrUtility.GenerateNetworkCharacteristicsResult(AUTO_DETECT_REQUEST_TYPE.RDP_NETCHAR_RESULT_BASERTT_BANDWIDTH_AVERAGERTT, sequenceNumber, autoDetectedBaseRTT, autoDetectedBandwidth, autoDetectedAverageRTT); byte[] reqData = rdpbcgrServer.EncodeNetworkDetectionRequest(netResult, true); List <byte[]> subHdDataList = new List <byte[]>(); subHdDataList.Add(reqData); RDP_TUNNEL_DATA tunnelData = rdpemtServer.CreateTunnelDataPdu(null, subHdDataList); rdpemtServer.SendRdpemtPacket(tunnelData); }
public void S2_DataTransfer_SecurityChannelCreation_ReliableConnection() { CheckSecurityProtocolForMultitransport(); Site.Log.Add(LogEntryKind.Debug, "Establishing RDP connection ..."); StartRDPConnection(); this.TestSite.Log.Add(LogEntryKind.Comment, "Create a reliable UDP connection."); this.EstablishUDPConnection(TransportMode.Reliable, waitTime, true, true); // Set the autoHandle to true, then can be used for create security channel. this.TestSite.Log.Add(LogEntryKind.Comment, "Start TLS handshake."); String certFile; PtfPropUtility.GetPtfPropertyValue(Site, "CertificatePath", out certFile); String certPwd; PtfPropUtility.GetPtfPropertyValue(Site, "CertificatePassword", out certPwd); X509Certificate2 cert = new X509Certificate2(certFile, certPwd); rdpemtServerR = new RdpemtServer(rdpeudpSocketR, cert, false); this.TestSite.Log.Add(LogEntryKind.Comment, "Wait for a RDP_TUNNEL_CREATEREQUEST message from client after security channel creation"); RDP_TUNNEL_CREATEREQUEST createReq = rdpemtServerR.ExpectTunnelCreateRequest(waitTime); Site.Assert.IsNotNull(createReq, "Client should send a RDP_TUNNEL_CREATEREQUEST message after security channel creation."); }
/// <summary> /// Send an invalid UDP source Packet. /// </summary> /// <param name="udpTransportMode"></param> /// <param name="invalidType"></param> private void SendInvalidUdpSourcePacket(TransportMode udpTransportMode, SourcePacket_InvalidType invalidType) { RdpeudpSocket rdpeudpSocket = rdpeudpSocketR; RdpemtServer rdpemtServer = rdpemtServerR; if (udpTransportMode == TransportMode.Lossy) { rdpeudpSocket = rdpeudpSocketL; rdpemtServer = rdpemtServerL; } if (invalidType == SourcePacket_InvalidType.LargerSourcePayload) { // Change UpStreamMtu of RDPEUDP Socket, so that large data can be sent ushort upstreamMtu = rdpeudpSocket.UUpStreamMtu; rdpeudpSocket.UUpStreamMtu = 2000; byte[] data = new byte[1600]; RDP_TUNNEL_DATA tunnelData = rdpemtServer.CreateTunnelDataPdu(data, null); rdpemtServer.SendRdpemtPacket(tunnelData); // Change UpStreamMtu to correct value rdpeudpSocket.UUpStreamMtu = upstreamMtu; } }
/// <summary> /// Establish a MultiTransport Connection /// </summary> private void EstablishTransportConnection() { // Send the Server Initial multitransport byte[] securityCookie = new byte[16]; Random rnd = new Random(); rnd.NextBytes(securityCookie); Server_Initiate_Multitransport_Request_PDU requestPDU = rdpbcgrServer.CreateServerInitiateMultitransportRequestPDU(serverSessionContext, ++multitransportId, transportProtocol, securityCookie); rdpbcgrServer.SendPdu(serverSessionContext, requestPDU); //Create RDP-UDP Connection CreateRdpeudpServer(this.serverSessionContext); TransportMode transMode = TransportMode.Reliable; if (transportProtocol == Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECL) { transMode = TransportMode.Lossy; } rdpeudpSocket = rdpeudpServer.Accept(((IPEndPoint)serverSessionContext.Identity).Address, transMode, timeout); if (rdpeudpSocket == null) { if (rdpeudpServer != null && rdpeudpServer.Running) { rdpeudpServer.Dispose(); } throw new NotSupportedException("RDPEMT Server create rdpedupSocket failed."); } rdpemtServer = new RdpemtServer(rdpeudpSocket, rdpbcgrServer.AuthCertificate, true); rdpemtServer.Received += ReceivedBytes; uint receivedRequestId; byte[] receivedCookie; if (!rdpemtServer.ExpectConnect(timeout, out receivedRequestId, out receivedCookie)) { throw new ProtocolViolationException("RDPEMT Server Expect Connection failed"); } if (receivedRequestId != multitransportId || receivedCookie == null || receivedCookie.Length != 16) { throw new ProtocolViolationException("RDPEMT Server received a connection with un-expected request id or Cookie is null (or cookie's length is not 16)!"); } for (int i = 0; i < receivedCookie.Length; i++) { if (receivedCookie[i] != securityCookie[i]) { throw new ProtocolViolationException("RDPEMT Server received a connection with un-correct cookie!"); } } }
/// <summary> /// Get a valid RDPEUDP packet and send it. /// </summary> /// <param name="udpTransportMode">Transport mode: reliable or lossy.</param> private void SendNextValidUdpPacket(TransportMode udpTransportMode, byte[] data = null) { RdpemtServer rdpemtServer = rdpemtServerR; if (udpTransportMode == TransportMode.Lossy) { rdpemtServer = rdpemtServerL; } if (data == null) data = new byte[1000]; RDP_TUNNEL_DATA tunnelData = rdpemtServer.CreateTunnelDataPdu(data, null); rdpemtServer.SendRdpemtPacket(tunnelData); }
/// <summary> /// Send some random tunnel data /// </summary> /// <param name="requestedProtocol">Which tunnel to be used, reliable or lossy</param> public void SendRandomTunnelData(TransportMode udpTransportMode) { RdpemtServer rdpemtServer = rdpemtServerR; if (udpTransportMode == TransportMode.Lossy) { rdpemtServer = rdpemtServerL; } Random rnd = new Random(); for (int i = 0; i < 3; i++) { int len = rnd.Next(100, 500); byte[] randomData = new byte[len]; rnd.NextBytes(randomData); rdpemtServer.Send(randomData); } }
/// <summary> /// Get the next valid rdpeudp packet. /// </summary> /// <param name="udpTransportMode">Transport mode: reliable or Lossy.</param> /// <returns>The next valid rdpeudp packet.</returns> private RdpeudpPacket GetNextValidUdpPacket(TransportMode udpTransportMode, byte[] data = null) { /*This function is used to get a valid rdpeudp packet. * Using rdpeudpSocket.LossPacket flag to control whether the socket send the packet. * First set rdpeudpSocket.LossPacket to true and send a tunnal Data, the socket will store the next packet(RDPEUDP socket which contains the encrypted tunnel data) and doesn't send it. * Then get the stored packet and return it. */ RdpemtServer rdpemtServer = rdpemtServerR; RdpeudpSocket rdpeudpSocket = rdpeudpSocketR; if (udpTransportMode == TransportMode.Lossy) { rdpemtServer = rdpemtServerL; rdpeudpSocket = rdpeudpSocketL; } if (data == null) { data = new byte[1000]; } RDP_TUNNEL_DATA tunnelData = rdpemtServer.CreateTunnelDataPdu(data, null); byte[] unEncryptData = PduMarshaler.Marshal(tunnelData); byte[] encryptData = null; if (udpTransportMode == TransportMode.Reliable) { RdpeudpTLSChannel secChannel = rdpemtServer.SecureChannel as RdpeudpTLSChannel; encryptData = secChannel.Encrypt(unEncryptData); } else { RdpeudpDTLSChannel secChannel = rdpemtServer.SecureChannel as RdpeudpDTLSChannel; List <byte[]> encryptDataList = secChannel.Encrypt(unEncryptData); if (encryptDataList != null && encryptDataList.Count > 0) { encryptData = encryptDataList[0]; } } RdpeudpPacket packet = rdpeudpSocket.CreateSourcePacket(encryptData); return(packet); }
/// <summary> /// Used to establish a RDPEMT connection /// </summary> /// <param name="udpTransportMode">Transport Mode: Reliable or Lossy</param> /// <param name="timeout">wait time</param> private void EstablishRdpemtConnection(TransportMode udpTransportMode, TimeSpan timeout, bool verifyPacket = false) { RdpeudpSocket rdpeudpSocket = rdpeudpSocketR; if (udpTransportMode == TransportMode.Lossy) { rdpeudpSocket = rdpeudpSocketL; } String certFile; PtfPropUtility.GetPtfPropertyValue(Site, "CertificatePath", out certFile); String certPwd; PtfPropUtility.GetPtfPropertyValue(Site, "CertificatePassword", out certPwd); X509Certificate2 cert = new X509Certificate2(certFile, certPwd); RdpemtServer rdpemtServer = new RdpemtServer(rdpeudpSocket, cert, false); uint receivedRequestId; byte[] receivedSecurityCookie; if (!rdpemtServer.ExpectConnect(waitTime, out receivedRequestId, out receivedSecurityCookie)) { Site.Assert.Fail("RDPEMT tunnel creation failed"); } if (verifyPacket) { VerifyTunnelCreateRequestPacket(receivedRequestId, receivedSecurityCookie); } if (udpTransportMode == TransportMode.Reliable) { rdpemtServerR = rdpemtServer; } else { rdpemtServerL = rdpemtServer; } }
/// <summary> /// Send a Tunnel Data PDU with RDP_BW_STOP in its subheader /// </summary> /// <param name="requestedProtocol"></param> /// <param name="sequenceNumber"></param> private void SendTunnelDataPdu_BWStop(Multitransport_Protocol_value requestedProtocol, ushort sequenceNumber) { AUTO_DETECT_REQUEST_TYPE requestType = AUTO_DETECT_REQUEST_TYPE.RDP_BW_STOP_AFTER_CONNECTTIME_OR_RELIABLEUDP; RdpemtServer rdpemtServer = rdpemtServerR; if (requestedProtocol == Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECL) { requestType = AUTO_DETECT_REQUEST_TYPE.RDP_BW_STOP_AFTER_CONNECTTIME_OR_LOSSYUDP; rdpemtServer = rdpemtServerL; } RDP_BW_STOP bwStop = RdpbcgrUtility.GenerateBandwidthMeasureStop(requestType, sequenceNumber); byte[] reqData = rdpbcgrServer.EncodeNetworkDetectionRequest(bwStop, true); List <byte[]> subHdDataList = new List <byte[]>(); subHdDataList.Add(reqData); RDP_TUNNEL_DATA tunnelData = rdpemtServer.CreateTunnelDataPdu(null, subHdDataList); rdpemtServer.SendRdpemtPacket(tunnelData); }
/// <summary> /// Send a Tunnel Data PDU with RTT Measure Request in its subheader /// </summary> /// <param name="udpTransportMode">Transport Mode: Reliable or Lossy</param> private void SendTunnelDataPdu_RTTMeasureRequest(Multitransport_Protocol_value requestedProtocol, ushort sequenceNumber) { AUTO_DETECT_REQUEST_TYPE requestType = AUTO_DETECT_REQUEST_TYPE.RDP_RTT_REQUEST_AFTER_CONNECTTIME; RdpemtServer rdpemtServer = rdpemtServerR; if (requestedProtocol == Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECL) { rdpemtServer = rdpemtServerL; } RDP_RTT_REQUEST RTTRequest = RdpbcgrUtility.GenerateRTTMeasureRequest(requestType, sequenceNumber); byte[] reqData = rdpbcgrServer.EncodeNetworkDetectionRequest(RTTRequest, true); List <byte[]> subHdDataList = new List <byte[]>(); subHdDataList.Add(reqData); RDP_TUNNEL_DATA tunnelData = rdpemtServer.CreateTunnelDataPdu(null, subHdDataList); rttDataStore.requestTime = DateTime.Now; rdpemtServer.SendRdpemtPacket(tunnelData); }
/// <summary> /// Used to establish a RDPEMT connection. /// </summary> /// <param name="udpTransportMode">Transport Mode: Reliable or Lossy.</param> /// <param name="timeout">Wait time.</param> private void EstablishRdpemtConnection(TransportMode udpTransportMode, TimeSpan timeout) { RdpeudpServerSocket rdpeudpSocket = rdpeudpSocketR; if (udpTransportMode == TransportMode.Lossy) { rdpeudpSocket = rdpeudpSocketL; } if (!rdpeudpSocket.AutoHandle) { rdpeudpSocket.AutoHandle = true; } String certFile = this.Site.Properties["CertificatePath"]; String certPwd = this.Site.Properties["CertificatePassword"]; X509Certificate2 cert = new X509Certificate2(certFile, certPwd); RdpemtServer rdpemtServer = new RdpemtServer(rdpeudpSocket, cert); uint receivedRequestId; byte[] receivedSecurityCookie; if (!rdpemtServer.ExpectConnect(waitTime, out receivedRequestId, out receivedSecurityCookie)) { Site.Assert.Fail("RDPEMT tunnel creation failed"); } rdpeudpSocket.AutoHandle = false; if (udpTransportMode == TransportMode.Reliable) { rdpemtServerR = rdpemtServer; } else { rdpemtServerL = rdpemtServer; } }
public void S2_DataTransfer_SecurityChannelCreation_LossyConnection() { Site.Log.Add(LogEntryKind.Debug, "Establishing RDP connection ..."); StartRDPConnection(); this.TestSite.Log.Add(LogEntryKind.Comment, "Create a Lossy UDP connection."); this.EstablishUDPConnection(TransportMode.Lossy, waitTime, true); // Set the autoHandle to true, then can be used for create security channel. this.TestSite.Log.Add(LogEntryKind.Comment, "Start DTLS handshake."); this.rdpeudpSocketL.AutoHandle = true; String certFile = this.Site.Properties["CertificatePath"]; String certPwd = this.Site.Properties["CertificatePassword"]; X509Certificate2 cert = new X509Certificate2(certFile, certPwd); rdpemtServerL = new RdpemtServer(rdpeudpSocketL, cert, false); this.TestSite.Log.Add(LogEntryKind.Comment, "Wait for a RDP_TUNNEL_CREATEREQUEST message from client after security channel creation"); RDP_TUNNEL_CREATEREQUEST createReq = rdpemtServerL.ExpectTunnelCreateRequest(waitTime); Site.Assert.IsNotNull(createReq, "Client should send a RDP_TUNNEL_CREATEREQUEST message after security channel creation."); }
/// <summary> /// Wait for a Tunnel Data PDU with RDP_BW_RESULTS and check its sequenceNumber. /// </summary> /// <param name="requestedProtocol">Which tunnel to be used, reliable or lossy</param> /// <param name="sequenceNumber"></param> /// <param name="timeout"></param> private void WaitForAndCheckTunnelDataPdu_BWResult(Multitransport_Protocol_value requestedProtocol, ushort sequenceNumber, TimeSpan timeout, bool NegiveLossy = false) { bool isReceived = false; TimeSpan leftTime = timeout; DateTime expiratedTime = DateTime.Now + timeout; RDP_BW_RESULTS bwResult = null; RdpemtServer rdpemtServer = rdpemtServerR; if (requestedProtocol == Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECL) { rdpemtServer = rdpemtServerL; } while (!isReceived && leftTime.CompareTo(new TimeSpan(0)) > 0) { try { RDP_TUNNEL_DATA tunnelData = rdpemtServer.ExpectTunnelData(leftTime); if (tunnelData != null) { RDP_TUNNEL_SUBHEADER[] SubHeaders = tunnelData.TunnelHeader.SubHeaders; if (SubHeaders != null) { foreach (RDP_TUNNEL_SUBHEADER subHeader in SubHeaders) { if (subHeader.SubHeaderType == RDP_TUNNEL_SUBHEADER_TYPE_Values.TYPE_ID_AUTODETECT_RESPONSE) { NETWORK_DETECTION_RESPONSE detectRsp = rdpbcgrServer.ParseNetworkDetectionResponse(subHeader.SubHeaderData, true); { if (detectRsp.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_BW_RESULTS_AFTER_CONNECT) { bwResult = (RDP_BW_RESULTS)detectRsp; isReceived = true; bwDataStore.byteCount = bwResult.byteCount; bwDataStore.timeDelta = bwResult.timeDelta; Site.Log.Add(LogEntryKind.Comment, "ByteCount: {0} Bytes\tTimeDelta: {1} Milliseconds", bwDataStore.byteCount, bwDataStore.timeDelta); } } } } } } } catch (TimeoutException) { if (NegiveLossy) { Site.Log.Add(LogEntryKind.Comment, "If the sequenceNumber of RDP_BW_STOP is different from that in RDP_BW_START, Client should not send RDP_BW_RESULTS"); } else { Site.Assert.Fail("Timeout when expecting a Tunnel Data PDU with RDP_BW_RESULTS"); } } catch (InvalidOperationException ex) { //break; Site.Log.Add(LogEntryKind.Warning, "Exception thrown out when receiving client PDUs {0}.", ex.Message); } finally { System.Threading.Thread.Sleep(100);//Wait some time for next packet. leftTime = expiratedTime - DateTime.Now; } } if (isReceived) { VerifyTunnelDataPdu_BWResult(bwResult, sequenceNumber); if (NegiveLossy) { Site.Assert.Fail("If the sequenceNumber of RDP_BW_STOP is different from that in RDP_BW_START, Client should not send RDP_BW_RESULTS"); } } else { if (NegiveLossy) { Site.Log.Add(LogEntryKind.Comment, "If the sequenceNumber of RDP_BW_STOP is different from that in RDP_BW_START, Client should not send RDP_BW_RESULTS"); } else { Site.Assert.Fail("Timeout when expecting a Tunnel Data PDU with RDP_BW_RESULTS"); } } }
/// <summary> /// Wait for a Tunnel Data PDU with RDP_RTT_RESPONSE and check its sequenceNumber. /// </summary> /// <param name="requestedProtocol">Which tunnel to be used, reliable or lossy</param> /// <param name="sequenceNumber"></param> /// <param name="timeout"></param> private void WaitForAndCheckTunnelDataPdu_RTTResponse(Multitransport_Protocol_value requestedProtocol, ushort sequenceNumber, TimeSpan timeout) { bool isReceived = false; TimeSpan leftTime = timeout; DateTime expiratedTime = DateTime.Now + timeout; RDP_RTT_RESPONSE rttResponse = null; RdpemtServer rdpemtServer = rdpemtServerR; if (requestedProtocol == Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECL) { rdpemtServer = rdpemtServerL; } while (!isReceived && leftTime.CompareTo(new TimeSpan(0)) > 0) { try { RDP_TUNNEL_DATA tunnelData = rdpemtServer.ExpectTunnelData(leftTime); if (tunnelData != null) { RDP_TUNNEL_SUBHEADER[] SubHeaders = tunnelData.TunnelHeader.SubHeaders; if (SubHeaders != null) { foreach (RDP_TUNNEL_SUBHEADER subHeader in SubHeaders) { if (subHeader.SubHeaderType == RDP_TUNNEL_SUBHEADER_TYPE_Values.TYPE_ID_AUTODETECT_RESPONSE) { NETWORK_DETECTION_RESPONSE detectRsp = rdpbcgrServer.ParseNetworkDetectionResponse(subHeader.SubHeaderData, true); { if (detectRsp.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_RTT_RESPONSE) { rttResponse = (RDP_RTT_RESPONSE)detectRsp; isReceived = true; rttDataStore.responseTime = DateTime.Now; Site.Log.Add(LogEntryKind.Comment, "RequestTime: {0}\tResponseTime: {1}", rttDataStore.responseTime.Ticks, rttDataStore.responseTime.Ticks); } } } } } } } catch (TimeoutException) { Site.Assert.Fail("Timeout when expecting a Tunnel Data PDU with RDP_RTT_RESULTS"); } catch (InvalidOperationException ex) { //break; Site.Log.Add(LogEntryKind.Warning, "Exception thrown out when receiving client PDUs {0}.", ex.Message); } finally { System.Threading.Thread.Sleep(100);//Wait some time for next packet. leftTime = expiratedTime - DateTime.Now; } } if (isReceived) { VerifyTunnelDataPdu_RTTResponse(rttResponse, sequenceNumber); } else { Site.Assert.Fail("Timeout when expecting a Tunnel Data PDU with RDP_RTT_RESULTS"); } }
/// <summary> /// Used to establish a RDPEMT connection. /// </summary> /// <param name="udpTransportMode">Transport Mode: Reliable or Lossy.</param> /// <param name="timeout">Wait time.</param> /// <returns>true,false.</returns> private bool EstablishRdpemtConnection(TransportMode udpTransportMode, TimeSpan timeout) { bool pass = true; RdpeudpServerSocket rdpeudpSocket = rdpeudpSocketR; if (udpTransportMode == TransportMode.Lossy) { rdpeudpSocket = rdpeudpSocketL; } if (!rdpeudpSocket.AutoHandle) { rdpeudpSocket.AutoHandle = true; } String certFile; PtfPropUtility.GetPtfPropertyValue(Site, "CertificatePath", out certFile); String certPwd; PtfPropUtility.GetPtfPropertyValue(Site, "CertificatePassword", out certPwd); X509Certificate2 cert = new X509Certificate2(certFile, certPwd); RdpemtServer rdpemtServer = new RdpemtServer(rdpeudpSocket, cert); uint receivedRequestId; byte[] receivedSecurityCookie; if (!rdpemtServer.ExpectConnect(waitTime, out receivedRequestId, out receivedSecurityCookie)) { pass = false; } rdpeudpSocket.AutoHandle = false; if (udpTransportMode == TransportMode.Reliable) { rdpemtServerR = rdpemtServer; } else { rdpemtServerL = rdpemtServer; } if (!pass) { this.TestSite.Log.Add(LogEntryKind.Comment, "Create a {0} RDPEMT connection failed, stop rdpeudpServer and close socket connection and retry.", udpTransportMode); rdpeudpServer.Stop(); rdpeudpServer = null; if (udpTransportMode == TransportMode.Reliable) { rdpeudpSocketR.Close(); rdpeudpSocketR = null; } else { rdpeudpSocketL.Close(); rdpeudpSocketL = null; } } return(pass); }