def parse(self, data: bytes) -> NegotiationResponsePDU: """ Parse a negotiation response. :param data: the response data. """ stream = BytesIO(data) if len(data) == 8: type = Uint8.unpack(stream) flags = Uint8.unpack(stream) length = Uint16LE.unpack(stream) selectedProtocols = Uint32LE.unpack(stream) return NegotiationResponsePDU(type, flags, selectedProtocols) else: return NegotiationResponsePDU(None, None, None)
def onConnectionConfirm(self, pdu: X224ConnectionConfirmPDU): """ Execute a startTLS if the SSL protocol was selected. :param _: the connection confirm PDU """ # X224 Response protocols = NegotiationProtocols.SSL if self.originalRequest.tlsSupported else NegotiationProtocols.NONE parser = NegotiationResponseParser() response = parser.parse(pdu.payload) if isinstance(response, NegotiationFailurePDU): self.log.info( "The server failed the negotiation. Error: %(error)s", { "error": NegotiationFailureCode.getMessage(response.failureCode) }) payload = pdu.payload else: payload = parser.write( NegotiationResponsePDU(NegotiationType.TYPE_RDP_NEG_RSP, 0x00, protocols)) self.client.sendConnectionConfirm(payload, source=0x1234) if self.originalRequest.tlsSupported: self.startTLSCallback() self.state.useTLS = True
def onConnectionConfirm(self, pdu: X224ConnectionConfirmPDU): """ Execute a startTLS if the SSL protocol was selected. :param _: the connection confirm PDU """ # FIXME: In case the server picks anything other than what we support, PyRDP is # likely going to be unable to complete the handshake with the server. # This should not happen since we are intercepting and spoofing the NEG_REQ, # though. # protocols = NegotiationProtocols.SSL if self.originalRequest.tlsSupported else NegotiationProtocols.NONE parser = NegotiationResponseParser() response = parser.parse(pdu.payload) if isinstance(response, NegotiationFailurePDU): self.log.info( "The server failed the negotiation. Error: %(error)s", { "error": NegotiationFailureCode.getMessage(response.failureCode) }) payload = pdu.payload else: payload = parser.write( NegotiationResponsePDU(NegotiationType.TYPE_RDP_NEG_RSP, 0x00, response.selectedProtocols)) self.client.sendConnectionConfirm(payload, source=0x1234) # FIXME: This should be done based on what authentication method the server selected, not on what # the client supports. if self.originalRequest.tlsSupported: self.startTLSCallback() self.state.useTLS = True
def onConnectionConfirm(self, pdu: X224ConnectionConfirmPDU): """ Execute a startTLS if the SSL protocol was selected. :param pdu: the connection confirm PDU """ # FIXME: In case the server picks anything other than what we support, PyRDP is # likely going to be unable to complete the handshake with the server. # This should not happen since we are intercepting and spoofing the NEG_REQ, # though. # protocols = NegotiationProtocols.SSL if self.originalRequest.tlsSupported else NegotiationProtocols.NONE parser = NegotiationResponseParser() response = parser.parse(pdu.payload) if isinstance(response, NegotiationFailurePDU): if response.failureCode == NegotiationFailureCode.HYBRID_REQUIRED_BY_SERVER and self.state.canRedirect( ): self.log.info( "The server forces the use of NLA. Using redirection host: %(redirectionHost)s:%(redirectionPort)d", { "redirectionHost": self.state.config.redirectionHost, "redirectionPort": self.state.config.redirectionPort }) # Disconnect from current server self.disconnector() # Use redirection host and replay sequence starting from the connection request self.state.useRedirectionHost() self.onConnectionRequest(self.originalConnectionRequest) return else: self.log.info( "The server failed the negotiation. Error: %(error)s", { "error": NegotiationFailureCode.getMessage(response.failureCode) }) payload = pdu.payload else: payload = parser.write( NegotiationResponsePDU(NegotiationType.TYPE_RDP_NEG_RSP, 0x00, response.selectedProtocols)) # FIXME: This should be done based on what authentication method the server selected, not on what # the client supports. if self.originalNegotiationRequest.tlsSupported: # If a TLS tunnel is requested, then we establish the server-side tunnel before # replying to the client, so that we can clone the certificate if needed. self.startTLSCallback(lambda: self.client.sendConnectionConfirm( payload, source=0x1234)) self.state.useTLS = True else: self.client.sendConnectionConfirm(payload, source=0x1234)
def parse( self, data: bytes ) -> Union[NegotiationResponsePDU, NegotiationFailurePDU]: """ Parse a negotiation response. :param data: the response data. """ stream = BytesIO(data) if len(data) == 8: type = Uint8.unpack(stream) flags = Uint8.unpack(stream) length = Uint16LE.unpack(stream) if type == NegotiationType.TYPE_RDP_NEG_FAILURE: failureCode = Uint32LE.unpack(stream) return NegotiationFailurePDU(type, flags, failureCode) else: selectedProtocols = Uint32LE.unpack(stream) return NegotiationResponsePDU(type, flags, selectedProtocols) else: return NegotiationResponsePDU(None, None, None)
def onConnectionConfirm(self, _): # X224 Response protocols = NegotiationProtocols.SSL if self.originalNegotiationPDU.tlsSupported else NegotiationProtocols.NONE parser = NegotiationResponseParser() payload = parser.write( NegotiationResponsePDU(NegotiationType.TYPE_RDP_NEG_RSP, 0x00, protocols)) self.x224.sendConnectionConfirm(payload, source=0x1234) if self.originalNegotiationPDU.tlsSupported: self.tcp.startTLS( ServerTLSContext(privateKeyFileName=self.privateKeyFileName, certificateFileName=self.certificateFileName)) self.useTLS = True
def onConnectionConfirm(self, _: X224ConnectionConfirmPDU): """ Execute a startTLS if the SSL protocol was selected. :param _: the connection confirm PDU """ # X224 Response protocols = NegotiationProtocols.SSL if self.originalRequest.tlsSupported else NegotiationProtocols.NONE parser = NegotiationResponseParser() payload = parser.write( NegotiationResponsePDU(NegotiationType.TYPE_RDP_NEG_RSP, 0x00, protocols)) self.client.sendConnectionConfirm(payload, source=0x1234) if self.originalRequest.tlsSupported: self.startTLSCallback() self.state.useTLS = True