aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2012-04-03 11:10:25 +1200
committerAldo Cortesi <aldo@nullcube.com>2012-04-03 11:10:25 +1200
commit61fab03b24bdb53d203eb7fb68ba891874d11114 (patch)
tree17c45c32905802d9da9ac6bb81c3239a8b5c264d
parentf526e5fa125339e8f3a16c1590c1607f45862b47 (diff)
downloadmitmproxy-61fab03b24bdb53d203eb7fb68ba891874d11114.tar.gz
mitmproxy-61fab03b24bdb53d203eb7fb68ba891874d11114.tar.bz2
mitmproxy-61fab03b24bdb53d203eb7fb68ba891874d11114.zip
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.
-rw-r--r--libmproxy/certutils.py8
-rw-r--r--libmproxy/console/__init__.py9
-rw-r--r--libmproxy/console/common.py4
-rw-r--r--libmproxy/console/flowdetailview.py93
-rw-r--r--libmproxy/console/flowview.py3
-rw-r--r--test/test_certutils.py1
6 files changed, 113 insertions, 5 deletions
diff --git a/libmproxy/certutils.py b/libmproxy/certutils.py
index 5fbc9840..f393648d 100644
--- a/libmproxy/certutils.py
+++ b/libmproxy/certutils.py
@@ -152,6 +152,10 @@ class SSLCert:
return self.cert.digest(name)
@property
+ def issuer(self):
+ return self.cert.get_issuer().get_components()
+
+ @property
def notbefore(self):
return self.cert.get_notBefore()
@@ -186,7 +190,7 @@ class SSLCert:
@property
def cn(self):
cn = None
- for i in self.cert.get_subject().get_components():
+ for i in self.subject:
if i[0] == "CN":
cn = i[1]
return cn
@@ -199,7 +203,7 @@ class SSLCert:
if ext.get_short_name() == "subjectAltName":
dec = decode(ext.get_data(), asn1Spec=_GeneralNames())
for i in dec[0]:
- altnames.append(i[0])
+ altnames.append(i[0].asOctets())
return altnames
diff --git a/libmproxy/console/__init__.py b/libmproxy/console/__init__.py
index a0a743b5..a6355160 100644
--- a/libmproxy/console/__init__.py
+++ b/libmproxy/console/__init__.py
@@ -17,7 +17,7 @@ import mailcap, mimetypes, tempfile, os, subprocess, glob, time, shlex
import os.path, sys, weakref
import urwid
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
@@ -547,6 +547,13 @@ class ConsoleMaster(flow.FlowMaster):
self.header = None
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):
self.body = ge
self.header = None
diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py
index d172209e..2d4c98ea 100644
--- a/libmproxy/console/common.py
+++ b/libmproxy/console/common.py
@@ -61,8 +61,8 @@ def format_keyvals(lst, key="key", val="text", indent=0):
maxk,
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))
return ret
diff --git a/libmproxy/console/flowdetailview.py b/libmproxy/console/flowdetailview.py
new file mode 100644
index 00000000..7391347e
--- /dev/null
+++ b/libmproxy/console/flowdetailview.py
@@ -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
+
+
diff --git a/libmproxy/console/flowview.py b/libmproxy/console/flowview.py
index 2d4b71af..1ec410ed 100644
--- a/libmproxy/console/flowview.py
+++ b/libmproxy/console/flowview.py
@@ -67,6 +67,7 @@ def _mkhelp():
("v", "view body in external viewer"),
("w", "save all flows matching current limit"),
("W", "save this flow"),
+ ("X", "view flow details"),
("z", "encode/decode a request/response"),
("tab", "toggle request/response view"),
("space", "next flow"),
@@ -497,6 +498,8 @@ class FlowView(common.WWrap):
"Send flow to script: ", self.state.last_script,
self.master.run_script_once, self.flow
)
+ elif key == "X":
+ self.master.view_flowdetails(self.flow)
elif key == "z":
if conn:
e = conn.headers["content-encoding"] or ["identity"]
diff --git a/test/test_certutils.py b/test/test_certutils.py
index e27088e7..9b89599a 100644
--- a/test/test_certutils.py
+++ b/test/test_certutils.py
@@ -64,6 +64,7 @@ class uSSLCert(libpry.AutoTree):
assert c.subject
assert c.keyinfo == ("RSA", 2048)
assert c.serial
+ assert c.issuer
c.has_expired
def test_der(self):