Exemple #1
0
    def view_websocket_messages(self):
        flow = self.flow
        assert isinstance(flow, http.HTTPFlow)
        assert flow.websocket is not None

        if not flow.websocket.messages:
            return searchable.Searchable(
                [urwid.Text(("highlight", "No messages."))])

        viewmode = self.master.commands.call("console.flowview.mode")

        widget_lines = []
        for m in flow.websocket.messages:
            _, lines, _ = contentviews.get_message_content_view(
                viewmode, m, flow)

            for line in lines:
                if m.from_client:
                    line.insert(
                        0, ("from_client", f"{common.SYMBOL_FROM_CLIENT} "))
                else:
                    line.insert(0,
                                ("to_client", f"{common.SYMBOL_TO_CLIENT} "))

                widget_lines.append(urwid.Text(line))

        if flow.intercepted:
            markup = widget_lines[-1].get_text()[0]
            widget_lines[-1].set_text(("intercept", markup))

        widget_lines.insert(
            0, self._contentview_status_bar(viewmode.capitalize(), viewmode))

        return searchable.Searchable(widget_lines)
Exemple #2
0
    def conn_text(self, conn):
        if conn:
            txt = common.format_keyvals(
                [(h + ":", v) for (h, v) in conn.headers.items(multi=True)],
                key="header",
                val="text")
            viewmode = self.viewmode_get()
            msg, body = self.content_view(viewmode, conn)

            cols = [
                urwid.Text([
                    ("heading", msg),
                ]),
                urwid.Text([
                    " ",
                    ('heading', "["),
                    ('heading_key', "m"),
                    ('heading', (":%s]" % viewmode)),
                ],
                           align="right")
            ]
            title = urwid.AttrWrap(urwid.Columns(cols), "heading")

            txt.append(title)
            txt.extend(body)
        else:
            txt = [
                urwid.Text(""),
                urwid.Text([
                    ("highlight", "No response. Press "),
                    ("key", "e"),
                    ("highlight", " and edit any aspect to add one."),
                ])
            ]
        return searchable.Searchable(self.view, txt)
Exemple #3
0
    def view_tcp_stream(self) -> urwid.Widget:
        flow = self.flow
        assert isinstance(flow, tcp.TCPFlow)

        if not flow.messages:
            return searchable.Searchable(
                [urwid.Text(("highlight", "No messages."))])

        viewmode = self.master.commands.call("console.flowview.mode")

        # Merge adjacent TCP "messages". For detailed explanation of this code block see:
        # https://github.com/mitmproxy/mitmproxy/pull/3970/files/469bd32582f764f9a29607efa4f5b04bd87961fb#r418670880
        from_client = None
        messages = []
        for message in flow.messages:
            if message.from_client is not from_client:
                messages.append(message.content)
                from_client = message.from_client
            else:
                messages[-1] += message.content

        widget_lines = []

        from_client = flow.messages[0].from_client
        for m in messages:
            _, lines, _ = contentviews.get_tcp_content_view(viewmode, m, flow)

            for line in lines:
                if from_client:
                    line.insert(
                        0, ("from_client", f"{common.SYMBOL_FROM_CLIENT} "))
                else:
                    line.insert(0,
                                ("to_client", f"{common.SYMBOL_TO_CLIENT} "))

                widget_lines.append(urwid.Text(line))

            from_client = not from_client

        if flow.intercepted:
            markup = widget_lines[-1].get_text()[0]
            widget_lines[-1].set_text(("intercept", markup))

        widget_lines.insert(
            0, self._contentview_status_bar(viewmode.capitalize(), viewmode))

        return searchable.Searchable(widget_lines)
    def view_websocket_messages(self):
        flow = self.flow
        assert isinstance(flow, http.HTTPFlow)
        assert flow.websocket is not None

        if not flow.websocket.messages:
            return searchable.Searchable(
                [urwid.Text(("highlight", "No messages."))])

        viewmode = self.master.commands.call("console.flowview.mode")

        widget_lines = []
        for m in flow.websocket.messages:
            _, lines, _ = contentviews.get_message_content_view(
                viewmode, m, flow)

            for line in lines:
                if m.from_client:
                    line.insert(0, self.FROM_CLIENT_MARKER)
                else:
                    line.insert(0, self.TO_CLIENT_MARKER)

                widget_lines.append(urwid.Text(line))

        if flow.websocket.closed_by_client is not None:
            widget_lines.append(
                urwid.Text([
                    (self.FROM_CLIENT_MARKER if flow.websocket.closed_by_client
                     else self.TO_CLIENT_MARKER),
                    ("alert" if flow.websocket.close_code in (1000, 1001, 1005)
                     else "error",
                     f"Connection closed: {flow.websocket.close_code} {flow.websocket.close_reason}"
                     )
                ]))

        if flow.intercepted:
            markup = widget_lines[-1].get_text()[0]
            widget_lines[-1].set_text(("intercept", markup))

        widget_lines.insert(
            0, self._contentview_status_bar(viewmode.capitalize(), viewmode))

        return searchable.Searchable(widget_lines)
Exemple #5
0
    def conn_text(self, conn):
        if conn:
            hdrs = []
            for k, v in conn.headers.fields:
                # This will always force an ascii representation of headers. For example, if the server sends a
                #
                #     X-Authors: Made with ❤ in Hamburg
                #
                # header, mitmproxy will display the following:
                #
                #     X-Authors: Made with \xe2\x9d\xa4 in Hamburg.
                #
                # The alternative would be to just use the header's UTF-8 representation and maybe
                # do `str.replace("\t", "\\t")` to exempt tabs from urwid's special characters escaping [1].
                # That would in some terminals allow rendering UTF-8 characters, but the mapping
                # wouldn't be bijective, i.e. a user couldn't distinguish "\\t" and "\t".
                # Also, from a security perspective, a mitmproxy user couldn't be fooled by homoglyphs.
                #
                # 1) https://github.com/mitmproxy/mitmproxy/issues/1833
                #    https://github.com/urwid/urwid/blob/6608ee2c9932d264abd1171468d833b7a4082e13/urwid/display_common.py#L35-L36,

                k = strutils.bytes_to_escaped_str(k) + ":"
                v = strutils.bytes_to_escaped_str(v)
                hdrs.append((k, v))
            txt = common.format_keyvals(hdrs, key_format="header")
            viewmode = self.master.commands.call("console.flowview.mode")
            msg, body = self.content_view(viewmode, conn)

            cols = [
                urwid.Text([
                    ("heading", msg),
                ]),
                urwid.Text([
                    " ",
                    ('heading', "["),
                    ('heading_key', "m"),
                    ('heading', (":%s]" % viewmode)),
                ],
                           align="right")
            ]
            title = urwid.AttrWrap(urwid.Columns(cols), "heading")

            txt.append(title)
            txt.extend(body)
        else:
            txt = [
                urwid.Text(""),
                urwid.Text([
                    ("highlight", "No response. Press "),
                    ("key", "e"),
                    ("highlight", " and edit any aspect to add one."),
                ])
            ]
        return searchable.Searchable(txt)
Exemple #6
0
    def conn_text(self, conn, flowtype):
        _conn = conn
        if flowtype is FlowType.Request:
            conn = conn.request
        else:
            conn = conn.response
        if conn:
            txt = common.format_keyvals(
                [(h + ":", v) for (h, v) in conn.headers.items(multi=True)],
                key="header",
                val="text")
            viewmode = self.master.commands.call("console.flowview.mode")
            msg, body = self.content_view(viewmode, _conn, flowtype)

            cols = [
                urwid.Text([
                    ("heading", msg),
                ]),
                urwid.Text([
                    " ",
                    ('heading', "["),
                    ('heading_key', "m"),
                    ('heading', (":%s]" % viewmode)),
                ],
                           align="right")
            ]
            title = urwid.AttrWrap(urwid.Columns(cols), "heading")

            txt.append(title)
            txt.extend(body)
        else:
            txt = [
                urwid.Text(""),
                urwid.Text([
                    ("highlight", "No response. Press "),
                    ("key", "e"),
                    ("highlight", " and edit any aspect to add one."),
                ])
            ]
        return searchable.Searchable(txt)
Exemple #7
0
def flowdetails(state, flow):
    text = []

    cc = flow.client_conn
    sc = flow.server_conn
    req = flow.request
    resp = flow.response

    if sc is not None:
        text.append(urwid.Text([("head", "Server Connection:")]))
        parts = [
            ["Address", repr(sc.address)],
            ["Resolved Address", repr(sc.ip_address)],
        ]

        text.extend(
            common.format_keyvals(parts, key="key", val="text", indent=4))

        c = sc.cert
        if c:
            text.append(urwid.Text([("head", "Server Certificate:")]))
            parts = [["Type", "%s, %s bits" % c.keyinfo],
                     ["SHA1 digest", c.digest("sha1")],
                     ["Valid to", str(c.notafter)],
                     ["Valid from", str(c.notbefore)],
                     ["Serial", str(c.serial)],
                     [
                         "Subject",
                         urwid.BoxAdapter(
                             urwid.ListBox(
                                 common.format_keyvals(c.subject,
                                                       key="highlight",
                                                       val="text")),
                             len(c.subject))
                     ],
                     [
                         "Issuer",
                         urwid.BoxAdapter(
                             urwid.ListBox(
                                 common.format_keyvals(c.issuer,
                                                       key="highlight",
                                                       val="text")),
                             len(c.issuer))
                     ]]

            if c.altnames:
                parts.append(
                    ["Alt names", ", ".join(str(x) for x in c.altnames)])
            text.extend(
                common.format_keyvals(parts, key="key", val="text", indent=4))

    if cc is not None:
        text.append(urwid.Text([("head", "Client Connection:")]))

        parts = [
            ["Address", repr(cc.address)],
        ]
        if cc.sni:
            parts.append(["Server Name Indication", cc.sni])

        text.extend(
            common.format_keyvals(parts, key="key", val="text", indent=4))

    parts = []

    if cc is not None and cc.timestamp_start:
        parts.append([
            "Client conn. established",
            maybe_timestamp(cc, "timestamp_start")
        ])
        if cc.ssl_established:
            parts.append([
                "Client conn. TLS handshake",
                maybe_timestamp(cc, "timestamp_ssl_setup")
            ])
    if sc is not None and sc.timestamp_start:
        parts.append(
            ["Server conn. initiated",
             maybe_timestamp(sc, "timestamp_start")])
        parts.append([
            "Server conn. TCP handshake",
            maybe_timestamp(sc, "timestamp_tcp_setup")
        ])
        if sc.ssl_established:
            parts.append([
                "Server conn. TLS handshake",
                maybe_timestamp(sc, "timestamp_ssl_setup")
            ])
    if req is not None and req.timestamp_start:
        parts.append(
            ["First request byte",
             maybe_timestamp(req, "timestamp_start")])
        parts.append(
            ["Request complete",
             maybe_timestamp(req, "timestamp_end")])
    if resp is not None and resp.timestamp_start:
        parts.append(
            ["First response byte",
             maybe_timestamp(resp, "timestamp_start")])
        parts.append(
            ["Response complete",
             maybe_timestamp(resp, "timestamp_end")])

    if parts:
        # sort operations by timestamp
        parts = sorted(parts, key=lambda p: p[1])

        text.append(urwid.Text([("head", "Timing:")]))
        text.extend(
            common.format_keyvals(parts, key="key", val="text", indent=4))
    return searchable.Searchable(state, text)
def flowdetails(state, flow: mitmproxy.flow.Flow):
    text = []

    sc = flow.server_conn
    cc = flow.client_conn
    req: typing.Optional[http.Request]
    resp: typing.Optional[http.Response]
    if isinstance(flow, http.HTTPFlow):
        req = flow.request
        resp = flow.response
    else:
        req = None
        resp = None
    metadata = flow.metadata

    if metadata is not None and len(metadata) > 0:
        parts = [(str(k), repr(v)) for k, v in metadata.items()]
        text.append(urwid.Text([("head", "Metadata:")]))
        text.extend(common.format_keyvals(parts, indent=4))

    if sc is not None and sc.peername:
        text.append(urwid.Text([("head", "Server Connection:")]))
        parts = [
            ("Address", human.format_address(sc.address)),
        ]
        if sc.peername:
            parts.append(("Resolved Address", human.format_address(sc.peername)))
        if resp:
            parts.append(("HTTP Version", resp.http_version))
        if sc.alpn:
            parts.append(("ALPN", strutils.bytes_to_escaped_str(sc.alpn)))

        text.extend(
            common.format_keyvals(parts, indent=4)
        )

        if sc.certificate_list:
            c = sc.certificate_list[0]
            text.append(urwid.Text([("head", "Server Certificate:")]))
            parts = [
                ("Type", "%s, %s bits" % c.keyinfo),
                ("SHA256 digest", c.fingerprint().hex()),
                ("Valid to", str(c.notafter)),
                ("Valid from", str(c.notbefore)),
                ("Serial", str(c.serial)),
                ("Subject", urwid.Pile(common.format_keyvals(c.subject, key_format="highlight"))),
                ("Issuer", urwid.Pile(common.format_keyvals(c.issuer, key_format="highlight")))
            ]

            if c.altnames:
                parts.append(("Alt names", ", ".join(c.altnames)))
            text.extend(
                common.format_keyvals(parts, indent=4)
            )

    if cc is not None:
        text.append(urwid.Text([("head", "Client Connection:")]))

        parts = [
            ("Address", human.format_address(cc.peername)),
        ]
        if req:
            parts.append(("HTTP Version", req.http_version))
        if cc.tls_version:
            parts.append(("TLS Version", cc.tls_version))
        if cc.sni:
            parts.append(("Server Name Indication", cc.sni))
        if cc.cipher:
            parts.append(("Cipher Name", cc.cipher))
        if cc.alpn:
            parts.append(("ALPN", strutils.bytes_to_escaped_str(cc.alpn)))

        text.extend(
            common.format_keyvals(parts, indent=4)
        )

    parts = []

    if cc is not None and cc.timestamp_start:
        parts.append(
            (
                "Client conn. established",
                maybe_timestamp(cc, "timestamp_start")
            )
        )
        if cc.tls_established:
            parts.append(
                (
                    "Client conn. TLS handshake",
                    maybe_timestamp(cc, "timestamp_tls_setup")
                )
            )
        parts.append(
            (
                "Client conn. closed",
                maybe_timestamp(cc, "timestamp_end")
            )
        )

    if sc is not None and sc.timestamp_start:
        parts.append(
            (
                "Server conn. initiated",
                maybe_timestamp(sc, "timestamp_start")
            )
        )
        parts.append(
            (
                "Server conn. TCP handshake",
                maybe_timestamp(sc, "timestamp_tcp_setup")
            )
        )
        if sc.tls_established:
            parts.append(
                (
                    "Server conn. TLS handshake",
                    maybe_timestamp(sc, "timestamp_tls_setup")
                )
            )
        parts.append(
            (
                "Server conn. closed",
                maybe_timestamp(sc, "timestamp_end")
            )
        )

    if req is not None and req.timestamp_start:
        parts.append(
            (
                "First request byte",
                maybe_timestamp(req, "timestamp_start")
            )
        )
        parts.append(
            (
                "Request complete",
                maybe_timestamp(req, "timestamp_end")
            )
        )

    if resp is not None and resp.timestamp_start:
        parts.append(
            (
                "First response byte",
                maybe_timestamp(resp, "timestamp_start")
            )
        )
        parts.append(
            (
                "Response complete",
                maybe_timestamp(resp, "timestamp_end")
            )
        )

    if parts:
        # sort operations by timestamp
        parts = sorted(parts, key=lambda p: p[1])

        text.append(urwid.Text([("head", "Timing:")]))
        text.extend(common.format_keyvals(parts, indent=4))

    return searchable.Searchable(text)
def flowdetails(state, flow: http.HTTPFlow):
    text = []

    sc = flow.server_conn
    cc = flow.client_conn
    req = flow.request
    resp = flow.response
    metadata = flow.metadata

    if metadata is not None and len(metadata) > 0:
        parts = [[str(k), repr(v)] for k, v in metadata.items()]
        text.append(urwid.Text([("head", "Metadata:")]))
        text.extend(
            common.format_keyvals(parts, key="key", val="text", indent=4))

    if sc is not None and sc.ip_address:
        text.append(urwid.Text([("head", "Server Connection:")]))
        parts = [
            ["Address", human.format_address(sc.address)],
        ]
        if sc.ip_address:
            parts.append(
                ["Resolved Address",
                 human.format_address(sc.ip_address)])
        if resp:
            parts.append(["HTTP Version", resp.http_version])
        if sc.alpn_proto_negotiated:
            parts.append(["ALPN", sc.alpn_proto_negotiated])

        text.extend(
            common.format_keyvals(parts, key="key", val="text", indent=4))

        c = sc.cert
        if c:
            text.append(urwid.Text([("head", "Server Certificate:")]))
            parts = [["Type", "%s, %s bits" % c.keyinfo],
                     ["SHA1 digest", c.digest("sha1")],
                     ["Valid to", str(c.notafter)],
                     ["Valid from", str(c.notbefore)],
                     ["Serial", str(c.serial)],
                     [
                         "Subject",
                         urwid.BoxAdapter(
                             urwid.ListBox(
                                 common.format_keyvals(c.subject,
                                                       key="highlight",
                                                       val="text")),
                             len(c.subject))
                     ],
                     [
                         "Issuer",
                         urwid.BoxAdapter(
                             urwid.ListBox(
                                 common.format_keyvals(c.issuer,
                                                       key="highlight",
                                                       val="text")),
                             len(c.issuer))
                     ]]

            if c.altnames:
                parts.append([
                    "Alt names", ", ".join(
                        strutils.bytes_to_escaped_str(x) for x in c.altnames)
                ])
            text.extend(
                common.format_keyvals(parts, key="key", val="text", indent=4))

    if cc is not None:
        text.append(urwid.Text([("head", "Client Connection:")]))

        parts = [
            ["Address", "{}:{}".format(cc.address[0], cc.address[1])],
        ]
        if req:
            parts.append(["HTTP Version", req.http_version])
        if cc.tls_version:
            parts.append(["TLS Version", cc.tls_version])
        if cc.sni:
            parts.append(["Server Name Indication", cc.sni])
        if cc.cipher_name:
            parts.append(["Cipher Name", cc.cipher_name])
        if cc.alpn_proto_negotiated:
            parts.append(["ALPN", cc.alpn_proto_negotiated])

        text.extend(
            common.format_keyvals(parts, key="key", val="text", indent=4))

    parts = []

    if cc is not None and cc.timestamp_start:
        parts.append([
            "Client conn. established",
            maybe_timestamp(cc, "timestamp_start")
        ])
        if cc.ssl_established:
            parts.append([
                "Client conn. TLS handshake",
                maybe_timestamp(cc, "timestamp_ssl_setup")
            ])

    if sc is not None and sc.timestamp_start:
        parts.append(
            ["Server conn. initiated",
             maybe_timestamp(sc, "timestamp_start")])
        parts.append([
            "Server conn. TCP handshake",
            maybe_timestamp(sc, "timestamp_tcp_setup")
        ])
        if sc.ssl_established:
            parts.append([
                "Server conn. TLS handshake",
                maybe_timestamp(sc, "timestamp_ssl_setup")
            ])

    if req is not None and req.timestamp_start:
        parts.append(
            ["First request byte",
             maybe_timestamp(req, "timestamp_start")])
        parts.append(
            ["Request complete",
             maybe_timestamp(req, "timestamp_end")])

    if resp is not None and resp.timestamp_start:
        parts.append(
            ["First response byte",
             maybe_timestamp(resp, "timestamp_start")])
        parts.append(
            ["Response complete",
             maybe_timestamp(resp, "timestamp_end")])

    if parts:
        # sort operations by timestamp
        parts = sorted(parts, key=lambda p: p[1])

        text.append(urwid.Text([("head", "Timing:")]))
        text.extend(
            common.format_keyvals(parts, key="key", val="text", indent=4))

    return searchable.Searchable(text)