aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2014-03-02 19:04:56 +1300
committerAldo Cortesi <aldo@nullcube.com>2014-03-02 19:04:56 +1300
commit53334e437c6c9e7df0a6e979dbe255ab27d8e2c9 (patch)
tree88897add71d5d1c3f40b826fe31943dba73be3cd
parent0177eb899a87995d0faaed8a836904cac7f844ce (diff)
downloadmitmproxy-53334e437c6c9e7df0a6e979dbe255ab27d8e2c9.tar.gz
mitmproxy-53334e437c6c9e7df0a6e979dbe255ab27d8e2c9.tar.bz2
mitmproxy-53334e437c6c9e7df0a6e979dbe255ab27d8e2c9.zip
pathoc -S dumps information on the remote SSL certificate chain
-rw-r--r--libpathod/pathoc.py32
-rwxr-xr-xpathoc5
-rw-r--r--test/test_pathoc.py47
3 files changed, 63 insertions, 21 deletions
diff --git a/libpathod/pathoc.py b/libpathod/pathoc.py
index 31180083..995a56d8 100644
--- a/libpathod/pathoc.py
+++ b/libpathod/pathoc.py
@@ -2,6 +2,7 @@ import sys, os
from netlib import tcp, http
import netlib.utils
import language, utils
+import OpenSSL.crypto
class PathocError(Exception): pass
@@ -70,7 +71,6 @@ class Pathoc(tcp.TCPClient):
self.connection.get_peer_cert_chain()
)
-
def request(self, spec):
"""
Return an (httpversion, code, msg, headers, content) tuple.
@@ -97,7 +97,7 @@ class Pathoc(tcp.TCPClient):
print >> fp, "%s (unprintables escaped):"%header
print >> fp, netlib.utils.cleanBin(data)
- def print_request(self, spec, showreq, showresp, explain, hexdump, ignorecodes, ignoretimeout, fp=sys.stdout):
+ def print_request(self, spec, showreq, showresp, explain, showssl, hexdump, ignorecodes, ignoretimeout, fp=sys.stdout):
"""
Performs a series of requests, and prints results to the specified
file descriptor.
@@ -106,6 +106,7 @@ class Pathoc(tcp.TCPClient):
showreq: Print requests
showresp: Print responses
explain: Print request explanation
+ showssl: Print info on SSL connection
hexdump: When printing requests or responses, use hex dump output
ignorecodes: Sequence of return codes to ignore
@@ -145,6 +146,7 @@ class Pathoc(tcp.TCPClient):
if req:
if ignorecodes and resp and resp[1] in ignorecodes:
return
+
if explain:
print >> fp, ">> Spec:", r.spec()
@@ -156,4 +158,30 @@ class Pathoc(tcp.TCPClient):
else:
if resp:
self._show_summary(fp, *resp)
+
+ if self.sslinfo:
+ print >> fp, "SSL certificate chain:\n"
+ for i in self.sslinfo.certchain:
+ print >> fp, "\tSubject: ",
+ for cn in i.get_subject().get_components():
+ print >> fp, "%s=%s"%cn,
+ print >> fp
+ print >> fp, "\tIssuer: ",
+ for cn in i.get_issuer().get_components():
+ print >> fp, "%s=%s"%cn,
+ print >> fp
+ print >> fp, "\tVersion: %s"%i.get_version()
+ print >> fp, "\tValidity: %s - %s"%(i.get_notBefore(),i.get_notAfter())
+ print >> fp, "\tSerial: %s"%i.get_serial_number()
+ print >> fp, "\tAlgorithm: %s"%i.get_signature_algorithm()
+ pk = i.get_pubkey()
+ types = {
+ OpenSSL.crypto.TYPE_RSA: "RSA",
+ OpenSSL.crypto.TYPE_DSA: "DSA"
+ }
+ t = types.get(pk.type(), "Uknown")
+ print >> fp, "\tPubkey: %s bit %s"%(pk.bits(), t)
+ print >> fp
return True
+
+
diff --git a/pathoc b/pathoc
index 8f1bd479..b1045c80 100755
--- a/pathoc
+++ b/pathoc
@@ -82,6 +82,10 @@ if __name__ == "__main__":
help="Comma-separated list of response codes to ignore"
)
group.add_argument(
+ "-S", dest="showssl", action="store_true", default=False,
+ help="Show info on SSL connection"
+ )
+ group.add_argument(
"-e", dest="explain", action="store_true", default=False,
help="Explain requests"
)
@@ -153,6 +157,7 @@ if __name__ == "__main__":
showreq=args.showreq,
showresp=args.showresp,
explain=args.explain,
+ showssl=args.showssl,
hexdump=args.hexdump,
ignorecodes=codes,
ignoretimeout=args.ignoretimeout
diff --git a/test/test_pathoc.py b/test/test_pathoc.py
index 5d676d25..3eeec9f6 100644
--- a/test/test_pathoc.py
+++ b/test/test_pathoc.py
@@ -34,6 +34,28 @@ class _TestDaemon:
r = c.request("get:/api/info")
assert tuple(json.loads(r.content)["version"]) == version.IVERSION
+ def tval(self, requests, showreq=False, showresp=False, explain=False,
+ showssl=False, hexdump=False, timeout=None, ignorecodes=None,
+ ignoretimeout=None):
+ c = pathoc.Pathoc(("127.0.0.1", self.d.port), ssl=self.ssl)
+ c.connect()
+ if timeout:
+ c.settimeout(timeout)
+ s = cStringIO.StringIO()
+ for i in requests:
+ c.print_request(
+ i,
+ showreq = showreq,
+ showresp = showresp,
+ explain = explain,
+ showssl = showssl,
+ hexdump = hexdump,
+ ignorecodes = ignorecodes,
+ ignoretimeout = ignoretimeout,
+ fp = s
+ )
+ return s.getvalue()
+
class TestDaemonSSL(_TestDaemon):
ssl = True
@@ -50,6 +72,9 @@ class TestDaemonSSL(_TestDaemon):
d = json.loads(r.content)
assert d["log"][0]["request"]["sni"] == "foobar.com"
+ def test_showssl(self):
+ assert "certificate chain" in self.tval(["get:/p/200"], showssl=True)
+
def test_clientcert(self):
c = pathoc.Pathoc(
("127.0.0.1", self.d.port),
@@ -65,29 +90,13 @@ class TestDaemonSSL(_TestDaemon):
class TestDaemon(_TestDaemon):
ssl = False
- def tval(self, requests, showreq=False, showresp=False, explain=False, hexdump=False, timeout=None, ignorecodes=None, ignoretimeout=None):
- c = pathoc.Pathoc(("127.0.0.1", self.d.port))
- c.connect()
- if timeout:
- c.settimeout(timeout)
- s = cStringIO.StringIO()
- for i in requests:
- c.print_request(
- i,
- showreq = showreq,
- showresp = showresp,
- explain = explain,
- hexdump = hexdump,
- ignorecodes = ignorecodes,
- ignoretimeout = ignoretimeout,
- fp = s
- )
- return s.getvalue()
-
def test_ssl_error(self):
c = pathoc.Pathoc(("127.0.0.1", self.d.port), ssl = True)
tutils.raises("ssl handshake", c.connect)
+ def test_showssl(self):
+ assert not "certificate chain" in self.tval(["get:/p/200"], showssl=True)
+
def test_ignorecodes(self):
assert "200" in self.tval(["get:'/p/200:b@1'"])
assert "200" not in self.tval(["get:'/p/200:b@1'"], ignorecodes=[200])