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:
Aldo Cortesi 2012-04-03 11:10:25 +12:00
parent f526e5fa12
commit 61fab03b24
6 changed files with 113 additions and 5 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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"]

View File

@ -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):