/// <summary> /// Constructor /// </summary> /// <param name="socket"></param> /// <param name="targetHost"></param> /// <param name="autoHandle"></param> public RdpemtClient(RdpeudpSocket socket, string targetHost, bool autoHandle = true) : base(autoHandle) { if (!socket.AutoHandle) { throw new NotSupportedException("To Create RDPEMT Server, RDPEUDP Socket must be auto handle."); } if (socket.TransMode == TransportMode.Reliable) { RdpeudpTLSChannel secChannel = new RdpeudpTLSChannel(socket); secChannel.Received += ReceiveBytes; secChannel.AuthenticateAsClient(targetHost); this.secureChannel = secChannel; } else { RdpeudpDTLSChannel secChannel = new RdpeudpDTLSChannel(socket); secChannel.Received += ReceiveBytes; secChannel.AuthenticateAsClient(targetHost); this.secureChannel = secChannel; } bandwidthMeasureStartTime = DateTime.Now; bandwidthMeasurePayloadByteCount = 0; detectBandwidth = false; }
/// <summary> /// Constructor /// </summary> /// <param name="eudpSocket">RDPEUDP Socket, which is transport</param> public RdpeudpDTLSChannel(RdpeudpSocket eudpSocket) { if (eudpSocket == null || eudpSocket.TransMode == TransportMode.Reliable) { throw new NotSupportedException("RdpeudpSocket is null or it is a socket for reliable RDPEUDP connection."); } this.rdpeudpSocket = eudpSocket; this.rdpeudpSocket.Received += ReceiveBytes; isAuthenticated = false; rdpeudpSocket.Disconnected += RdpeudpSocket_Disconnected; receivedBuffer = new List <byte[]>(); toSendBuffer = new List <byte[]>(); if (eudpSocket.AutoHandle) { // Check whether there is packets in unprocessed packet buffer RdpeudpPacket packet = eudpSocket.ExpectPacket(shortWaitTime); if (packet != null) { eudpSocket.ReceivePacket(packet); } } }
/// <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> /// Constructor /// </summary> /// <param name="socket"></param> /// <param name="targetHost"></param> /// <param name="autoHandle"></param> /// <param name="selectedSslProtocols">The selected SSL protocols.</param> public RdpemtClient(RdpeudpSocket socket, string targetHost, bool autoHandle = true, SslProtocols selectedSslProtocols = SslProtocols.Tls) : base(autoHandle) { if (!socket.AutoHandle) { throw new NotSupportedException("To Create RDPEMT Server, RDPEUDP Socket must be auto handle."); } if (socket.TransMode == TransportMode.Reliable) { RdpeudpTLSChannel secChannel = new RdpeudpTLSChannel(socket); secChannel.Received += ReceiveBytes; secChannel.AuthenticateAsClient(targetHost, selectedSslProtocols); this.secureChannel = secChannel; } else { RdpeudpDTLSChannel secChannel = new RdpeudpDTLSChannel(socket); secChannel.Received += ReceiveBytes; secChannel.AuthenticateAsClient(targetHost); this.secureChannel = secChannel; } Initialize(); }
/// <summary> /// Expect for a Source Packet. /// </summary> /// <param name="udpTransportMode">Transport mode: reliable or lossy.</param> /// <param name="timeout">Wait time</param> /// <returns></returns> private RdpeudpPacket WaitForSourcePacket(TransportMode udpTransportMode, TimeSpan timeout, uint sequnceNumber = 0) { RdpeudpSocket rdpeudpSocket = rdpeudpSocketR; if (udpTransportMode == TransportMode.Lossy) { rdpeudpSocket = rdpeudpSocketL; } DateTime endTime = DateTime.Now + timeout; while (DateTime.Now < endTime) { RdpeudpPacket packet = rdpeudpSocket.ExpectPacket(endTime - DateTime.Now); if (packet != null && packet.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_DATA)) { if (sequnceNumber == 0 || packet.sourceHeader.Value.snSourceStart == sequnceNumber) { return(packet); } } } return(null); }
/// <summary> /// Send a udp packet. /// </summary> /// <param name="udpTransportMode">Transport mode: reliable or lossy.</param> /// <param name="packet">The packet to send.</param> private void SendPacket(TransportMode udpTransportMode, RdpeudpPacket packet) { RdpeudpSocket rdpeudpSocket = rdpeudpSocketR; if (udpTransportMode == TransportMode.Lossy) { rdpeudpSocket = rdpeudpSocketL; } rdpeudpSocket.SendPacket(packet); }
/// <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 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> /// Establish a UDP connection /// </summary> /// <param name="udpTransportMode">Transport mode: Reliable or Lossy</param> /// <param name="timeout">wait time</param> /// <returns>The accepted socket</returns> private void EstablishUDPConnection(TransportMode udpTransportMode, TimeSpan timeout) { //Start UDP listening if (rdpeudpServer == null) { rdpeudpServer = new RdpeudpServer((IPEndPoint)this.rdpbcgrAdapter.SessionContext.LocalIdentity, true); rdpeudpServer.UnhandledExceptionReceived += (ex) => { Site.Log.Add(LogEntryKind.Debug, $"Unhandled exception from RdpeudpServer: {ex}"); }; } if (!rdpeudpServer.Running) { rdpeudpServer.Start(); } //Send a Server Initiate Multitransport Request PDU byte[] securityCookie = new byte[16]; Random rnd = new Random(); rnd.NextBytes(securityCookie); Multitransport_Protocol_value requestedProtocol = Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECR; if (udpTransportMode == TransportMode.Lossy) { requestedProtocol = Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECL; } this.rdpbcgrAdapter.SendServerInitiateMultitransportRequestPDU(++this.multitransportRequestId, requestedProtocol, securityCookie); this.requestIdList.Add(this.multitransportRequestId); this.securityCookieList.Add(securityCookie); //create a UDP socket RdpeudpSocket rdpudpSocket = rdpeudpServer.Accept(((IPEndPoint)this.rdpbcgrAdapter.SessionContext.Identity).Address, udpTransportMode, timeout); if (udpTransportMode == TransportMode.Reliable) { this.rdpeudpSocketR = rdpudpSocket; } else { this.rdpeudpSocketL = rdpudpSocket; } }
/// <summary> /// Wait for an ACK packet which meets certain conditions. /// </summary> /// <param name="udpTransportMode">Transport mode: reliable or lossy.</param> /// <param name="timeout">Wait time.</param> /// <param name="expectAckVectors">Expected ack vectors.</param> /// <param name="hasFlag">Flags, which the ACK packet must contain.</param> /// <param name="notHasFlag">Flags, which the ACK packet must no contain.</param> /// <returns></returns> private RdpeudpPacket WaitForACKPacket(TransportMode udpTransportMode, TimeSpan timeout, AckVector[] expectAckVectors = null, RDPUDP_FLAG hasFlag = 0, RDPUDP_FLAG notHasFlag = 0) { RdpeudpSocket rdpeudpSocket = rdpeudpSocketR; if (udpTransportMode == TransportMode.Lossy) { rdpeudpSocket = rdpeudpSocketL; } DateTime endTime = DateTime.Now + timeout; while (DateTime.Now < endTime) { RdpeudpPacket ackPacket = rdpeudpSocket.ExpectACKPacket(endTime - DateTime.Now); if (ackPacket != null) { if (expectAckVectors != null) { if (!(ackPacket.ackVectorHeader.HasValue && CompareAckVectors(ackPacket.ackVectorHeader.Value.AckVectorElement, expectAckVectors))) { continue; } } if (hasFlag != 0) { if ((ackPacket.fecHeader.uFlags & hasFlag) != hasFlag) { continue; } } if (notHasFlag != 0) { if ((ackPacket.fecHeader.uFlags & notHasFlag) != 0) { continue; } } return(ackPacket); } } return(null); }
/// <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> /// Constructor /// </summary> /// <param name="eudpSocket">A RdpeudpSocket used for transport</param> public RdpeudpTLSChannel(RdpeudpSocket eudpSocket) { if (eudpSocket == null || eudpSocket.TransMode == TransportMode.Lossy) { throw new NotSupportedException("RdpeudpSocket is null or it is a socket for Lossy RDPEUDP connection."); } this.rdpeudpSocket = eudpSocket; this.rdpeudpSocket.Received += ReceiveBytes; innerStream = new SSLInnerStream(); isAuthenticated = false; if (eudpSocket.AutoHandle) { // Check whether there is packets in unprocessed packet buffer RdpeudpPacket packet = eudpSocket.ExpectPacket(shortWaitTime); if (packet != null) { eudpSocket.ReceivePacket(packet); } } }
/// <summary> /// Constructor /// </summary> /// <param name="socket"></param> /// <param name="cert"></param> /// <param name="autoHandle"></param> public RdpemtServer(RdpeudpSocket socket, X509Certificate2 cert, bool autoHandle = true) : base(autoHandle) { if (!socket.AutoHandle) { throw new NotSupportedException("To Create RDPEMT Server, RDPEUDP Socket must be auto handle."); } if (socket.TransMode == TransportMode.Reliable) { RdpeudpTLSChannel secChannel = new RdpeudpTLSChannel(socket); secChannel.Received += ReceiveBytes; secChannel.AuthenticateAsServer(cert); this.secureChannel = secChannel; } else { RdpeudpDTLSChannel secChannel = new RdpeudpDTLSChannel(socket); secChannel.Received += ReceiveBytes; secChannel.AuthenticateAsServer(cert); this.secureChannel = secChannel; } }