示例#1
0
    def test_client_only(self, tctx: context.Context):
        """Test TLS with client only"""
        playbook, client_layer, tssl_client = make_client_tls_layer(tctx)
        client_layer.debug = "  "
        assert not tctx.client.tls_established

        # Send ClientHello, receive ServerHello
        data = tutils.Placeholder(bytes)
        assert (playbook >> events.DataReceived(
            tctx.client, tssl_client.bio_read()) << tls.TlsClienthelloHook(
                tutils.Placeholder()) >> tutils.reply() << tls.TlsStartHook(
                    tutils.Placeholder()) >> reply_tls_start() <<
                commands.SendData(tctx.client, data))
        tssl_client.bio_write(data())
        tssl_client.do_handshake()
        # Finish Handshake
        interact(playbook, tctx.client, tssl_client)

        assert tssl_client.obj.getpeercert(True)
        assert tctx.client.tls_established

        # Echo
        _test_echo(playbook, tssl_client, tctx.client)
        other_server = Server(None)
        assert (playbook >> events.DataReceived(other_server, b"Plaintext") <<
                commands.SendData(other_server, b"plaintext"))
示例#2
0
    def test_mitmproxy_ca_is_untrusted(self, tctx: context.Context):
        """Test the scenario where the client doesn't trust the mitmproxy CA."""
        playbook, client_layer, tssl_client = make_client_tls_layer(tctx, sni=b"wrong.host.mitmproxy.org")
        playbook.logs = True

        data = tutils.Placeholder(bytes)
        assert (
                playbook
                >> events.DataReceived(tctx.client, tssl_client.bio_read())
                << tls.TlsClienthelloHook(tutils.Placeholder())
                >> tutils.reply()
                << tls.TlsStartHook(tutils.Placeholder())
                >> reply_tls_start()
                << commands.SendData(tctx.client, data)
        )
        tssl_client.bio_write(data())
        with pytest.raises(ssl.SSLCertVerificationError):
            tssl_client.do_handshake()
        # Finish Handshake
        assert (
                playbook
                >> events.DataReceived(tctx.client, tssl_client.bio_read())
                << commands.Log("Client TLS handshake failed. The client does not trust the proxy's certificate "
                                "for wrong.host.mitmproxy.org (sslv3 alert bad certificate)", "warn")
                << commands.CloseConnection(tctx.client)
                >> events.ConnectionClosed(tctx.client)
        )
        assert not tctx.client.tls_established
示例#3
0
    def test_server_required(self, tctx):
        """
        Test the scenario where a server connection is required (for example, because of an unknown ALPN)
        to establish TLS with the client.
        """
        tssl_server = SSLTest(server_side=True, alpn=["quux"])
        playbook, client_layer, tssl_client = make_client_tls_layer(tctx, alpn=["quux"])

        # We should now get instructed to open a server connection.
        data = tutils.Placeholder(bytes)

        def require_server_conn(client_hello: tls.ClientHelloData) -> None:
            client_hello.establish_server_tls_first = True

        assert (
                playbook
                >> events.DataReceived(tctx.client, tssl_client.bio_read())
                << tls.TlsClienthelloHook(tutils.Placeholder())
                >> tutils.reply(side_effect=require_server_conn)
                << commands.OpenConnection(tctx.server)
                >> tutils.reply(None)
                << tls.TlsStartHook(tutils.Placeholder())
                >> reply_tls_start(alpn=b"quux")
                << commands.SendData(tctx.server, data)
        )

        # Establish TLS with the server...
        tssl_server.bio_write(data())
        with pytest.raises(ssl.SSLWantReadError):
            tssl_server.do_handshake()

        data = tutils.Placeholder(bytes)
        assert (
                playbook
                >> events.DataReceived(tctx.server, tssl_server.bio_read())
                << commands.SendData(tctx.server, data)
                << tls.TlsStartHook(tutils.Placeholder())
        )
        tssl_server.bio_write(data())
        assert tctx.server.tls_established
        # Server TLS is established, we can now reply to the client handshake...

        data = tutils.Placeholder(bytes)
        assert (
                playbook
                >> reply_tls_start(alpn=b"quux")
                << commands.SendData(tctx.client, data)
        )
        tssl_client.bio_write(data())
        tssl_client.do_handshake()
        interact(playbook, tctx.client, tssl_client)

        # Both handshakes completed!
        assert tctx.client.tls_established
        assert tctx.server.tls_established
        assert tctx.server.sni == tctx.client.sni
        assert tctx.client.alpn == b"quux"
        assert tctx.server.alpn == b"quux"
        _test_echo(playbook, tssl_server, tctx.server)
        _test_echo(playbook, tssl_client, tctx.client)
示例#4
0
    def test_immediate_disconnect(self, tctx: context.Context, close_at):
        """Test the scenario where the client is disconnecting during the handshake.
        This may happen because they are not interested in the connection anymore, or because they do not like
        the proxy certificate."""
        playbook, client_layer, tssl_client = make_client_tls_layer(
            tctx, sni=b"wrong.host.mitmproxy.org")
        playbook.logs = True

        playbook >> events.DataReceived(tctx.client, tssl_client.bio_read())
        playbook << tls.TlsClienthelloHook(tutils.Placeholder())

        if close_at == "tls_clienthello":
            assert (playbook >> events.ConnectionClosed(
                tctx.client) >> tutils.reply(to=-2) << tls.TlsStartClientHook(
                    tutils.Placeholder()) >> reply_tls_start_client() <<
                    commands.CloseConnection(tctx.client))
            return

        playbook >> tutils.reply()
        playbook << tls.TlsStartClientHook(tutils.Placeholder())

        if close_at == "tls_start_client":
            assert (playbook >> events.ConnectionClosed(tctx.client) >>
                    reply_tls_start_client(to=-2) << commands.CloseConnection(
                        tctx.client))
            return

        assert (playbook >> reply_tls_start_client() << commands.SendData(
            tctx.client, tutils.Placeholder()
        ) >> events.ConnectionClosed(tctx.client) << commands.Log(
            "Client TLS handshake failed. The client disconnected during the handshake. "
            "If this happens consistently for wrong.host.mitmproxy.org, this may indicate that the "
            "client does not trust the proxy's certificate.", "info") <<
                commands.CloseConnection(tctx.client))
示例#5
0
    def test_passthrough_from_clienthello(self, tctx, server_state):
        """
        Test the scenario where the connection is moved to passthrough mode in the tls_clienthello hook.
        """
        if server_state == "open":
            tctx.server.timestamp_start = time.time()
            tctx.server.state = ConnectionState.OPEN

        playbook, client_layer, tssl_client = make_client_tls_layer(
            tctx, alpn=["quux"])

        def make_passthrough(client_hello: ClientHelloData) -> None:
            client_hello.ignore_connection = True

        client_hello = tssl_client.bio_read()
        (playbook >> events.DataReceived(tctx.client, client_hello) <<
         tls.TlsClienthelloHook(tutils.Placeholder()) >>
         tutils.reply(side_effect=make_passthrough))
        if server_state == "closed":
            (playbook << commands.OpenConnection(tctx.server) >>
             tutils.reply(None))
        assert (playbook << commands.SendData(
            tctx.server, client_hello)  # passed through unmodified
                >> events.DataReceived(
                    tctx.server,
                    b"ServerHello")  # and the same for the serverhello.
                << commands.SendData(tctx.client, b"ServerHello"))
示例#6
0
    def test_unsupported_protocol(self, tctx: context.Context):
        """Test the scenario where the client only supports an outdated TLS version by default."""
        playbook, client_layer, tssl_client = make_client_tls_layer(
            tctx, max_ver=ssl.TLSVersion.TLSv1_2)
        playbook.logs = True

        assert (playbook >> events.DataReceived(
            tctx.client, tssl_client.bio_read()
        ) << tls.TlsClienthelloHook(tutils.Placeholder(
        )) >> tutils.reply() << tls.TlsStartClientHook(tutils.Placeholder(
        )) >> reply_tls_start_client() << commands.Log(
            "Client TLS handshake failed. Client and mitmproxy cannot agree on a TLS version to "
            "use. You may need to adjust mitmproxy's tls_version_client_min option.",
            "warn") << commands.CloseConnection(tctx.client))
示例#7
0
    def test_mitmproxy_ca_is_untrusted_immediate_disconnect(
            self, tctx: context.Context):
        """Test the scenario where the client doesn't trust the mitmproxy CA."""
        playbook, client_layer, tssl_client = make_client_tls_layer(
            tctx, sni=b"wrong.host.mitmproxy.org")

        assert (
            playbook >> events.DataReceived(
                tctx.client, tssl_client.bio_read()) << tls.TlsClienthelloHook(
                    tutils.Placeholder()) >> tutils.reply() <<
            tls.TlsStartHook(tutils.Placeholder()) >> reply_tls_start() <<
            commands.SendData(tctx.client, tutils.Placeholder()) >>
            events.ConnectionClosed(tctx.client) << commands.Log(
                "Client TLS handshake failed. The client may not trust the proxy's certificate "
                "for wrong.host.mitmproxy.org (connection closed)",
                "warn") << commands.CloseConnection(tctx.client))