mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-23 00:01:36 +00:00
Add a details page, available from a flow view with the 'X' shortcut
At the moment, this shows the upstream SSL certificate details. More fine-grained detail that doesn't fit in the flow view itself will be added.
This commit is contained in:
parent
f526e5fa12
commit
61fab03b24
@ -151,6 +151,10 @@ class SSLCert:
|
|||||||
def digest(self, name):
|
def digest(self, name):
|
||||||
return self.cert.digest(name)
|
return self.cert.digest(name)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def issuer(self):
|
||||||
|
return self.cert.get_issuer().get_components()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def notbefore(self):
|
def notbefore(self):
|
||||||
return self.cert.get_notBefore()
|
return self.cert.get_notBefore()
|
||||||
@ -186,7 +190,7 @@ class SSLCert:
|
|||||||
@property
|
@property
|
||||||
def cn(self):
|
def cn(self):
|
||||||
cn = None
|
cn = None
|
||||||
for i in self.cert.get_subject().get_components():
|
for i in self.subject:
|
||||||
if i[0] == "CN":
|
if i[0] == "CN":
|
||||||
cn = i[1]
|
cn = i[1]
|
||||||
return cn
|
return cn
|
||||||
@ -199,7 +203,7 @@ class SSLCert:
|
|||||||
if ext.get_short_name() == "subjectAltName":
|
if ext.get_short_name() == "subjectAltName":
|
||||||
dec = decode(ext.get_data(), asn1Spec=_GeneralNames())
|
dec = decode(ext.get_data(), asn1Spec=_GeneralNames())
|
||||||
for i in dec[0]:
|
for i in dec[0]:
|
||||||
altnames.append(i[0])
|
altnames.append(i[0].asOctets())
|
||||||
return altnames
|
return altnames
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import mailcap, mimetypes, tempfile, os, subprocess, glob, time, shlex
|
|||||||
import os.path, sys, weakref
|
import os.path, sys, weakref
|
||||||
import urwid
|
import urwid
|
||||||
from .. import controller, utils, flow
|
from .. import controller, utils, flow
|
||||||
import flowlist, flowview, help, common, grideditor, palettes, contentview
|
import flowlist, flowview, help, common, grideditor, palettes, contentview, flowdetailview
|
||||||
|
|
||||||
EVENTLOG_SIZE = 500
|
EVENTLOG_SIZE = 500
|
||||||
|
|
||||||
@ -547,6 +547,13 @@ class ConsoleMaster(flow.FlowMaster):
|
|||||||
self.header = None
|
self.header = None
|
||||||
self.make_view()
|
self.make_view()
|
||||||
|
|
||||||
|
def view_flowdetails(self, flow):
|
||||||
|
h = flowdetailview.FlowDetailsView(self, flow, (self.statusbar, self.body, self.header))
|
||||||
|
self.statusbar = StatusBar(self, flowdetailview.footer)
|
||||||
|
self.body = h
|
||||||
|
self.header = None
|
||||||
|
self.make_view()
|
||||||
|
|
||||||
def view_grideditor(self, ge):
|
def view_grideditor(self, ge):
|
||||||
self.body = ge
|
self.body = ge
|
||||||
self.header = None
|
self.header = None
|
||||||
|
@ -61,8 +61,8 @@ def format_keyvals(lst, key="key", val="text", indent=0):
|
|||||||
maxk,
|
maxk,
|
||||||
urwid.Text([(key, kv[0] or "")])
|
urwid.Text([(key, kv[0] or "")])
|
||||||
),
|
),
|
||||||
urwid.Text([(val, kv[1])])
|
kv[1] if isinstance(kv[1], urwid.Widget) else urwid.Text([(val, kv[1])])
|
||||||
])
|
])
|
||||||
ret.append(urwid.Columns(cols, dividechars = 2))
|
ret.append(urwid.Columns(cols, dividechars = 2))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
93
libmproxy/console/flowdetailview.py
Normal file
93
libmproxy/console/flowdetailview.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# Copyright (C) 2012 Aldo Cortesi
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import urwid
|
||||||
|
import common
|
||||||
|
from .. import filt, version
|
||||||
|
|
||||||
|
footer = [
|
||||||
|
('heading_key', "q"), ":back ",
|
||||||
|
]
|
||||||
|
|
||||||
|
class FlowDetailsView(urwid.ListBox):
|
||||||
|
def __init__(self, master, flow, state):
|
||||||
|
self.master, self.flow, self.state = master, flow, state
|
||||||
|
urwid.ListBox.__init__(
|
||||||
|
self,
|
||||||
|
self.flowtext()
|
||||||
|
)
|
||||||
|
|
||||||
|
def keypress(self, size, key):
|
||||||
|
key = common.shortcuts(key)
|
||||||
|
if key == "q":
|
||||||
|
self.master.statusbar = self.state[0]
|
||||||
|
self.master.body = self.state[1]
|
||||||
|
self.master.header = self.state[2]
|
||||||
|
self.master.make_view()
|
||||||
|
return None
|
||||||
|
elif key == "?":
|
||||||
|
key = None
|
||||||
|
return urwid.ListBox.keypress(self, size, key)
|
||||||
|
|
||||||
|
def flowtext(self):
|
||||||
|
text = []
|
||||||
|
|
||||||
|
title = urwid.Text("Flow details")
|
||||||
|
title = urwid.Padding(title, align="left", width=("relative", 100))
|
||||||
|
title = urwid.AttrWrap(title, "heading")
|
||||||
|
text.append(title)
|
||||||
|
|
||||||
|
if self.flow.response:
|
||||||
|
c = self.flow.response.get_cert()
|
||||||
|
if c:
|
||||||
|
text.append(urwid.Text([("head", "Server Certificate:")]))
|
||||||
|
parts = [
|
||||||
|
["Type", "%s, %s bits"%c.keyinfo],
|
||||||
|
["Valid to", c.notafter],
|
||||||
|
["Valid from", c.notbefore],
|
||||||
|
["Serial", str(c.serial)],
|
||||||
|
]
|
||||||
|
|
||||||
|
parts.append(
|
||||||
|
[
|
||||||
|
"Subject",
|
||||||
|
urwid.BoxAdapter(
|
||||||
|
urwid.ListBox(common.format_keyvals(c.subject, key="highlight", val="text")),
|
||||||
|
len(c.subject)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
parts.append(
|
||||||
|
[
|
||||||
|
"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(c.altnames)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
text.extend(common.format_keyvals(parts, key="key", val="text", indent=4))
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
@ -67,6 +67,7 @@ def _mkhelp():
|
|||||||
("v", "view body in external viewer"),
|
("v", "view body in external viewer"),
|
||||||
("w", "save all flows matching current limit"),
|
("w", "save all flows matching current limit"),
|
||||||
("W", "save this flow"),
|
("W", "save this flow"),
|
||||||
|
("X", "view flow details"),
|
||||||
("z", "encode/decode a request/response"),
|
("z", "encode/decode a request/response"),
|
||||||
("tab", "toggle request/response view"),
|
("tab", "toggle request/response view"),
|
||||||
("space", "next flow"),
|
("space", "next flow"),
|
||||||
@ -497,6 +498,8 @@ class FlowView(common.WWrap):
|
|||||||
"Send flow to script: ", self.state.last_script,
|
"Send flow to script: ", self.state.last_script,
|
||||||
self.master.run_script_once, self.flow
|
self.master.run_script_once, self.flow
|
||||||
)
|
)
|
||||||
|
elif key == "X":
|
||||||
|
self.master.view_flowdetails(self.flow)
|
||||||
elif key == "z":
|
elif key == "z":
|
||||||
if conn:
|
if conn:
|
||||||
e = conn.headers["content-encoding"] or ["identity"]
|
e = conn.headers["content-encoding"] or ["identity"]
|
||||||
|
@ -64,6 +64,7 @@ class uSSLCert(libpry.AutoTree):
|
|||||||
assert c.subject
|
assert c.subject
|
||||||
assert c.keyinfo == ("RSA", 2048)
|
assert c.keyinfo == ("RSA", 2048)
|
||||||
assert c.serial
|
assert c.serial
|
||||||
|
assert c.issuer
|
||||||
c.has_expired
|
c.has_expired
|
||||||
|
|
||||||
def test_der(self):
|
def test_der(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user