Exemplo n.º 1
0
    def test_untrusted_cert(self, tctx):
        """If the certificate is not trusted, we should fail."""
        playbook = tutils.Playbook(tls.ServerTLSLayer(tctx))
        tctx.server.address = ("wrong.host.mitmproxy.org", 443)
        tctx.server.sni = "wrong.host.mitmproxy.org"

        tssl = SSLTest(server_side=True)

        # send ClientHello
        data = tutils.Placeholder(bytes)
        assert (playbook >> events.DataReceived(
            tctx.client, b"open-connection") << layer.NextLayerHook(
                tutils.Placeholder()) >> tutils.reply_next_layer(TlsEchoLayer)
                << commands.OpenConnection(tctx.server) >> tutils.reply(None)
                << tls.TlsStartHook(tutils.Placeholder()) >> reply_tls_start()
                << commands.SendData(tctx.server, data))

        # receive ServerHello, finish client handshake
        tssl.bio_write(data())
        with pytest.raises(ssl.SSLWantReadError):
            tssl.do_handshake()

        assert (playbook >> events.DataReceived(tctx.server, tssl.bio_read(
        )) << commands.Log(
            "Server TLS handshake failed. Certificate verify failed: Hostname mismatch",
            "warn"
        ) << commands.CloseConnection(tctx.server) << commands.SendData(
            tctx.client,
            b"open-connection failed: Certificate verify failed: Hostname mismatch"
        ))
        assert not tctx.server.tls_established
Exemplo n.º 2
0
    def test_simple(self, tctx):
        nl = layer.NextLayer(tctx, ask_on_start=True)
        nl.debug = "  "
        playbook = tutils.Playbook(nl, hooks=True)

        assert (
                playbook
                << layer.NextLayerHook(nl)
                >> tutils.reply()
                >> events.DataReceived(tctx.client, b"foo")
                << layer.NextLayerHook(nl)
                >> tutils.reply()
                >> events.DataReceived(tctx.client, b"bar")
                << layer.NextLayerHook(nl)
        )
        assert nl.data_client() == b"foobar"
        assert nl.data_server() == b""

        nl.layer = tutils.EchoLayer(tctx)
        assert (
                playbook
                >> tutils.reply()
                << commands.SendData(tctx.client, b"foo")
                << commands.SendData(tctx.client, b"bar")
        )
Exemplo n.º 3
0
    def test_unsupported_protocol(self, tctx: context.Context):
        """Test the scenario where the server only supports an outdated TLS version by default."""
        playbook = tutils.Playbook(tls.ServerTLSLayer(tctx))
        tctx.server.address = ("example.mitmproxy.org", 443)
        tctx.server.state = ConnectionState.OPEN
        tctx.server.sni = "example.mitmproxy.org"

        # noinspection PyTypeChecker
        tssl = SSLTest(server_side=True, max_ver=ssl.TLSVersion.TLSv1_2)

        # send ClientHello
        data = tutils.Placeholder(bytes)
        assert (
            playbook << tls.TlsStartServerHook(tutils.Placeholder()) >>
            reply_tls_start_server() << commands.SendData(tctx.server, data))

        # receive ServerHello
        tssl.bio_write(data())
        with pytest.raises(ssl.SSLError):
            tssl.do_handshake()

        # send back error
        tls_hook_data = tutils.Placeholder(TlsData)
        assert (playbook >> events.DataReceived(tctx.server, tssl.bio_read(
        )) << commands.Log(
            "Server TLS handshake failed. The remote server and mitmproxy cannot agree on a TLS version"
            " to use. You may need to adjust mitmproxy's tls_version_server_min option.",
            "warn") << tls.TlsFailedServerHook(tls_hook_data) >>
                tutils.reply() << commands.CloseConnection(tctx.server))
        assert tls_hook_data().conn.error
Exemplo n.º 4
0
    def test_not_connected(self, tctx: context.Context):
        """Test that we don't do anything if no server connection exists."""
        layer = tls.ServerTLSLayer(tctx)
        layer.child_layer = TlsEchoLayer(tctx)

        assert (tutils.Playbook(layer) >> events.DataReceived(
            tctx.client, b"Hello World") << commands.SendData(
                tctx.client, b"hello world"))
Exemplo n.º 5
0
    def test_continue(self, tctx: Context):
        class TLayer(layer.Layer):
            def _handle_event(
                    self, event: events.Event) -> layer.CommandGenerator[None]:
                yield commands.OpenConnection(self.context.server)
                yield commands.OpenConnection(self.context.server)

        assert (tutils.Playbook(TLayer(tctx)) << commands.OpenConnection(
            tctx.server) >> tutils.reply(None) << commands.OpenConnection(
                tctx.server) >> tutils.reply(None))
Exemplo n.º 6
0
    def test_func_references(self, tctx: Context):
        nl = layer.NextLayer(tctx)
        playbook = tutils.Playbook(nl)

        assert (playbook >> events.DataReceived(tctx.client, b"foo") <<
                layer.NextLayerHook(nl))
        nl.layer = tutils.EchoLayer(tctx)
        handle = nl.handle_event
        assert (playbook >> tutils.reply() << commands.SendData(
            tctx.client, b"foo"))
        sd, = handle(events.DataReceived(tctx.client, b"bar"))
        assert isinstance(sd, commands.SendData)
Exemplo n.º 7
0
    def test_simple(self, tctx):
        playbook = tutils.Playbook(tls.ServerTLSLayer(tctx))
        tctx.server.state = ConnectionState.OPEN
        tctx.server.address = ("example.mitmproxy.org", 443)
        tctx.server.sni = b"example.mitmproxy.org"

        tssl = SSLTest(server_side=True)

        # send ClientHello
        data = tutils.Placeholder(bytes)
        assert (
                playbook
                << tls.TlsStartHook(tutils.Placeholder())
                >> reply_tls_start()
                << commands.SendData(tctx.server, data)
        )

        # receive ServerHello, finish client handshake
        tssl.bio_write(data())
        with pytest.raises(ssl.SSLWantReadError):
            tssl.do_handshake()
        interact(playbook, tctx.server, tssl)

        # finish server handshake
        tssl.do_handshake()
        assert (
                playbook
                >> events.DataReceived(tctx.server, tssl.bio_read())
                << None
        )

        assert tctx.server.tls_established

        # Echo
        assert (
                playbook
                >> events.DataReceived(tctx.client, b"foo")
                << layer.NextLayerHook(tutils.Placeholder())
                >> tutils.reply_next_layer(TlsEchoLayer)
                << commands.SendData(tctx.client, b"foo")
        )
        _test_echo(playbook, tssl, tctx.server)

        with pytest.raises(ssl.SSLWantReadError):
            tssl.obj.unwrap()
        assert (
                playbook
                >> events.DataReceived(tctx.server, tssl.bio_read())
                << commands.CloseConnection(tctx.server)
                >> events.ConnectionClosed(tctx.server)
                << None
        )
Exemplo n.º 8
0
 def test_receive_close(self, tctx: Context, layer_found: bool):
     """Test that we abort a client connection which has disconnected without any layer being found."""
     nl = layer.NextLayer(tctx)
     playbook = tutils.Playbook(nl)
     assert (
         playbook >> events.DataReceived(tctx.client, b"foo") <<
         layer.NextLayerHook(nl) >> events.ConnectionClosed(tctx.client))
     if layer_found:
         nl.layer = tutils.RecordLayer(tctx)
         assert (playbook >> tutils.reply(to=-2))
         assert isinstance(nl.layer.event_log[-1], events.ConnectionClosed)
     else:
         assert (playbook >> tutils.reply(to=-2) <<
                 commands.CloseConnection(tctx.client))
Exemplo n.º 9
0
    def test_remote_speaks_no_tls(self, tctx):
        playbook = tutils.Playbook(tls.ServerTLSLayer(tctx))
        tctx.server.state = ConnectionState.OPEN
        tctx.server.sni = "example.mitmproxy.org"

        # send ClientHello, receive random garbage back
        data = tutils.Placeholder(bytes)
        assert (playbook << tls.TlsStartHook(tutils.Placeholder(
        )) >> reply_tls_start(
        ) << commands.SendData(tctx.server, data) >> events.DataReceived(
            tctx.server, b"HTTP/1.1 404 Not Found\r\n"
        ) << commands.Log(
            "Server TLS handshake failed. The remote server does not speak TLS.",
            "warn") << commands.CloseConnection(tctx.server))
Exemplo n.º 10
0
    def test_late_hook_reply(self, tctx: Context):
        """
        Properly handle case where we receive an additional event while we are waiting for
        a reply from the proxy core.
        """
        nl = layer.NextLayer(tctx)
        playbook = tutils.Playbook(nl)

        assert (playbook >> events.DataReceived(tctx.client, b"foo") <<
                layer.NextLayerHook(nl) >> events.DataReceived(
                    tctx.client, b"bar"))
        assert nl.data_client() == b"foo"  # "bar" is paused.
        nl.layer = tutils.EchoLayer(tctx)

        assert (playbook >> tutils.reply(to=-2) << commands.SendData(
            tctx.client, b"foo") << commands.SendData(tctx.client, b"bar"))
Exemplo n.º 11
0
    def test_debug_messages(self, tctx: Context):
        tctx.server.id = "serverid"

        class TLayer(layer.Layer):
            debug = " "

            def _handle_event(
                    self, event: events.Event) -> layer.CommandGenerator[None]:
                yield from self.state(event)

            def state_foo(self,
                          event: events.Event) -> layer.CommandGenerator[None]:
                assert isinstance(event, events.Start)
                yield commands.OpenConnection(self.context.server)
                self.state = self.state_bar

            state = state_foo

            def state_bar(self,
                          event: events.Event) -> layer.CommandGenerator[None]:
                assert isinstance(event, events.DataReceived)
                yield commands.Log("baz", "info")

        tlayer = TLayer(tctx)
        assert (tutils.Playbook(tlayer, hooks=True, logs=True) << commands.Log(
            " >> Start({})", "debug"
        ) << commands.Log(
            " << OpenConnection({'connection': Server({'id': '…rverid', 'address': None, "
            "'state': <ConnectionState.CLOSED: 0>})})", "debug"
        ) << commands.OpenConnection(tctx.server) >> events.DataReceived(
            tctx.client, b"foo"
        ) << commands.Log(
            " >! DataReceived(client, b'foo')", "debug"
        ) >> tutils.reply(
            None, to=-3
        ) << commands.Log(
            " >> Reply(OpenConnection({'connection': Server("
            "{'id': '…rverid', 'address': None, 'state': <ConnectionState.OPEN: 3>, "
            "'timestamp_start': 1624544785})}),None)", "debug") <<
                commands.Log(" !> DataReceived(client, b'foo')",
                             "debug") << commands.Log("baz", "info"))
        assert repr(tlayer) == "TLayer(state: bar)"
Exemplo n.º 12
0
def make_client_tls_layer(
        tctx: context.Context, **kwargs
) -> typing.Tuple[tutils.Playbook, tls.ClientTLSLayer, SSLTest]:
    # This is a bit contrived as the client layer expects a server layer as parent.
    # We also set child layers manually to avoid NextLayer noise.
    server_layer = tls.ServerTLSLayer(tctx)
    client_layer = tls.ClientTLSLayer(tctx)
    server_layer.child_layer = client_layer
    client_layer.child_layer = TlsEchoLayer(tctx)
    playbook = tutils.Playbook(server_layer)

    # Add some server config, this is needed anyways.
    tctx.server.address = ("example.mitmproxy.org", 443)
    tctx.server.sni = "example.mitmproxy.org"

    tssl_client = SSLTest(**kwargs)
    # Start handshake.
    with pytest.raises(ssl.SSLWantReadError):
        tssl_client.do_handshake()

    return playbook, client_layer, tssl_client