aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorikoz <john@kozyrakis.gr>2016-03-02 15:23:33 +0000
committerikoz <john@kozyrakis.gr>2016-03-08 18:13:36 +0000
commit0169271bf993aa16b4d5627eda8523552661d7ef (patch)
treefa176d5c0f94b4b380364f1cf493b06b4ea1f7de
parentea3742c3938248c273be159d15ac49b4d2884ed8 (diff)
downloadmitmproxy-0169271bf993aa16b4d5627eda8523552661d7ef.tar.gz
mitmproxy-0169271bf993aa16b4d5627eda8523552661d7ef.tar.bz2
mitmproxy-0169271bf993aa16b4d5627eda8523552661d7ef.zip
New option: Add server certs to client chain
If enabled, append all server certificates to the certificate chain served to the client, as extras. Can be used to bypass certain certificate pinning impementations.
-rw-r--r--mitmproxy/cmdline.py6
-rw-r--r--mitmproxy/protocol/tls.py6
-rw-r--r--mitmproxy/proxy/config.py5
-rw-r--r--netlib/tcp.py10
4 files changed, 26 insertions, 1 deletions
diff --git a/mitmproxy/cmdline.py b/mitmproxy/cmdline.py
index b1b860f8..a04a36ba 100644
--- a/mitmproxy/cmdline.py
+++ b/mitmproxy/cmdline.py
@@ -435,6 +435,12 @@ def proxy_ssl_options(parser):
help="Don't connect to upstream server to look up certificate details."
)
group.add_argument(
+ "--add-server-certs-to-client-chain", default=False,
+ action="store_true", dest="add_server_certs_to_client_chain",
+ help="Add all the certificates of the server to the certificate chain "
+ "that will be served to the client, as extras."
+ )
+ group.add_argument(
"--verify-upstream-cert", default=False,
action="store_true", dest="ssl_verify_upstream_cert",
help="Verify upstream server SSL/TLS certificates and fail if invalid "
diff --git a/mitmproxy/protocol/tls.py b/mitmproxy/protocol/tls.py
index 6913396d..22ee8ff9 100644
--- a/mitmproxy/protocol/tls.py
+++ b/mitmproxy/protocol/tls.py
@@ -432,6 +432,11 @@ class TlsLayer(Layer):
self.log("Establish TLS with client", "debug")
cert, key, chain_file = self._find_cert()
+ if self.config.add_server_certs_to_client_chain:
+ extra_certs = self.server_conn.server_certs
+ else:
+ extra_certs = None
+
try:
self.client_conn.convert_to_ssl(
cert, key,
@@ -441,6 +446,7 @@ class TlsLayer(Layer):
dhparams=self.config.certstore.dhparams,
chain_file=chain_file,
alpn_select_callback=self.__alpn_select_callback,
+ extra_chain_certs = extra_certs,
)
# Some TLS clients will not fail the handshake,
# but will immediately throw an "unexpected eof" error on the first read.
diff --git a/mitmproxy/proxy/config.py b/mitmproxy/proxy/config.py
index 149d4710..9932ec8c 100644
--- a/mitmproxy/proxy/config.py
+++ b/mitmproxy/proxy/config.py
@@ -67,6 +67,7 @@ class ProxyConfig:
ssl_verify_upstream_cert=False,
ssl_verify_upstream_trusted_cadir=None,
ssl_verify_upstream_trusted_ca=None,
+ add_server_certs_to_client_chain=False,
):
self.host = host
self.port = port
@@ -107,6 +108,7 @@ class ProxyConfig:
self.openssl_verification_mode_server = SSL.VERIFY_NONE
self.openssl_trusted_cadir_server = ssl_verify_upstream_trusted_cadir
self.openssl_trusted_ca_server = ssl_verify_upstream_trusted_ca
+ self.add_server_certs_to_client_chain = add_server_certs_to_client_chain
def process_proxy_options(parser, options):
@@ -206,5 +208,6 @@ def process_proxy_options(parser, options):
ssl_version_server=options.ssl_version_server,
ssl_verify_upstream_cert=options.ssl_verify_upstream_cert,
ssl_verify_upstream_trusted_cadir=options.ssl_verify_upstream_trusted_cadir,
- ssl_verify_upstream_trusted_ca=options.ssl_verify_upstream_trusted_ca
+ ssl_verify_upstream_trusted_ca=options.ssl_verify_upstream_trusted_ca,
+ add_server_certs_to_client_chain=options.add_server_certs_to_client_chain,
)
diff --git a/netlib/tcp.py b/netlib/tcp.py
index 6423888a..68a71270 100644
--- a/netlib/tcp.py
+++ b/netlib/tcp.py
@@ -584,6 +584,7 @@ class TCPClient(_Connection):
self.address = address
self.source_address = source_address
self.cert = None
+ self.server_certs = []
self.ssl_verification_error = None
self.sni = None
@@ -668,6 +669,10 @@ class TCPClient(_Connection):
self.cert = certutils.SSLCert(self.connection.get_peer_certificate())
+ # Keep all server certificates in a list
+ for i in self.connection.get_peer_cert_chain():
+ self.server_certs.append(certutils.SSLCert(i))
+
# Validate TLS Hostname
try:
crt = dict(
@@ -734,6 +739,7 @@ class BaseHandler(_Connection):
request_client_cert=None,
chain_file=None,
dhparams=None,
+ extra_chain_certs=None,
**sslctx_kwargs):
"""
cert: A certutils.SSLCert object or the path to a certificate
@@ -769,6 +775,10 @@ class BaseHandler(_Connection):
else:
context.use_certificate_chain_file(cert)
+ if extra_chain_certs:
+ for i in extra_chain_certs:
+ context.add_extra_chain_cert(i.x509)
+
if handle_sni:
# SNI callback happens during do_handshake()
context.set_tlsext_servername_callback(handle_sni)