Beispiel #1
0
    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)
Beispiel #2
0
    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
Beispiel #3
0
    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
Beispiel #4
0
    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)
Beispiel #5
0
    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)
Beispiel #6
0
    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
Beispiel #7
0
    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