diff options
author | ikoz <john@kozyrakis.gr> | 2016-03-02 15:23:33 +0000 |
---|---|---|
committer | ikoz <john@kozyrakis.gr> | 2016-03-08 18:13:36 +0000 |
commit | 0169271bf993aa16b4d5627eda8523552661d7ef (patch) | |
tree | fa176d5c0f94b4b380364f1cf493b06b4ea1f7de | |
parent | ea3742c3938248c273be159d15ac49b4d2884ed8 (diff) | |
download | mitmproxy-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.py | 6 | ||||
-rw-r--r-- | mitmproxy/protocol/tls.py | 6 | ||||
-rw-r--r-- | mitmproxy/proxy/config.py | 5 | ||||
-rw-r--r-- | netlib/tcp.py | 10 |
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) |