aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mitmproxy/cmdline.py9
-rw-r--r--mitmproxy/console/master.py6
-rw-r--r--mitmproxy/console/options.py6
-rw-r--r--mitmproxy/dump.py2
-rw-r--r--mitmproxy/exceptions.py6
-rw-r--r--mitmproxy/models/http.py2
-rw-r--r--mitmproxy/options.py4
-rw-r--r--mitmproxy/protocol/tls.py21
-rw-r--r--mitmproxy/proxy/config.py22
-rw-r--r--mitmproxy/proxy/server.py7
-rw-r--r--netlib/tcp.py46
-rw-r--r--test/mitmproxy/data/servercert/9da13359.021
-rw-r--r--test/mitmproxy/data/servercert/self-signed.pem46
-rw-r--r--test/mitmproxy/data/servercert/trusted-leaf.pem45
-rw-r--r--test/mitmproxy/data/servercert/trusted-root.pem48
-rw-r--r--test/mitmproxy/data/trusted-cadir/8117bdb9.014
-rw-r--r--test/mitmproxy/data/trusted-cadir/9d45e6a9.014
-rw-r--r--test/mitmproxy/data/trusted-cadir/trusted-ca.pem14
-rw-r--r--test/mitmproxy/data/trusted-server.crt33
-rw-r--r--test/mitmproxy/data/untrusted-server.crt32
-rw-r--r--test/mitmproxy/test_protocol_http2.py6
-rw-r--r--test/mitmproxy/test_proxy.py6
-rw-r--r--test/mitmproxy/test_server.py109
-rw-r--r--test/mitmproxy/tservers.py3
-rw-r--r--test/netlib/test_tcp.py12
25 files changed, 303 insertions, 231 deletions
diff --git a/mitmproxy/cmdline.py b/mitmproxy/cmdline.py
index a6844241..4eadce11 100644
--- a/mitmproxy/cmdline.py
+++ b/mitmproxy/cmdline.py
@@ -260,7 +260,7 @@ def get_common_options(args):
upstream_auth = args.upstream_auth,
ssl_version_client = args.ssl_version_client,
ssl_version_server = args.ssl_version_server,
- ssl_verify_upstream_cert = args.ssl_verify_upstream_cert,
+ ssl_insecure = args.ssl_insecure,
ssl_verify_upstream_trusted_cadir = args.ssl_verify_upstream_trusted_cadir,
ssl_verify_upstream_trusted_ca = args.ssl_verify_upstream_trusted_ca,
tcp_hosts = args.tcp_hosts,
@@ -519,10 +519,9 @@ def proxy_ssl_options(parser):
"that will be served to the proxy 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 "
- "or not present."
+ "--insecure", default=False,
+ action="store_true", dest="ssl_insecure",
+ help="Do not verify upstream server SSL/TLS certificates."
)
group.add_argument(
"--upstream-trusted-cadir", default=None, action="store",
diff --git a/mitmproxy/console/master.py b/mitmproxy/console/master.py
index 9a9addc5..7a7ed9fd 100644
--- a/mitmproxy/console/master.py
+++ b/mitmproxy/console/master.py
@@ -277,11 +277,11 @@ class ConsoleMaster(flow.FlowMaster):
if self.options.verbosity < utils.log_tier(level):
return
- if level == "error":
+ if level in ("error", "warn"):
signals.status_message.send(
- message = "Error: %s" % str(e)
+ message = "{}: {}".format(level.title(), e)
)
- e = urwid.Text(("error", str(e)))
+ e = urwid.Text((level, str(e)))
else:
e = urwid.Text(str(e))
self.logbuffer.append(e)
diff --git a/mitmproxy/console/options.py b/mitmproxy/console/options.py
index f9fc3764..2205bf6f 100644
--- a/mitmproxy/console/options.py
+++ b/mitmproxy/console/options.py
@@ -91,6 +91,12 @@ class Options(urwid.WidgetWrap):
lambda: master.options.tcp_hosts,
self.tcp_hosts
),
+ select.Option(
+ "Don't Verify SSL/TLS Certificates",
+ "V",
+ lambda: master.server.config.ssl_insecure,
+ master.options.toggler("ssl_insecure")
+ ),
select.Heading("Utility"),
select.Option(
diff --git a/mitmproxy/dump.py b/mitmproxy/dump.py
index e59fd23e..51124224 100644
--- a/mitmproxy/dump.py
+++ b/mitmproxy/dump.py
@@ -104,7 +104,7 @@ class DumpMaster(flow.FlowMaster):
click.secho(
e,
file=self.options.tfile,
- fg="red" if level == "error" else None,
+ fg=dict(error="red", warn="yellow").get(level),
dim=(level == "debug"),
err=(level == "error")
)
diff --git a/mitmproxy/exceptions.py b/mitmproxy/exceptions.py
index 3b41fe1c..6ca11b25 100644
--- a/mitmproxy/exceptions.py
+++ b/mitmproxy/exceptions.py
@@ -44,6 +44,12 @@ class ClientHandshakeException(TlsProtocolException):
self.server = server
+class InvalidServerCertificate(TlsProtocolException):
+ def __repr__(self):
+ # In contrast to most others, this is a user-facing error which needs to look good.
+ return str(self)
+
+
class Socks5ProtocolException(ProtocolException):
pass
diff --git a/mitmproxy/models/http.py b/mitmproxy/models/http.py
index 7781e61f..d56eb29a 100644
--- a/mitmproxy/models/http.py
+++ b/mitmproxy/models/http.py
@@ -225,7 +225,7 @@ class HTTPFlow(Flow):
def make_error_response(status_code, message, headers=None):
- response = status_codes.RESPONSES.get(status_code, "Unknown").encode()
+ response = status_codes.RESPONSES.get(status_code, "Unknown")
body = """
<html>
<head>
diff --git a/mitmproxy/options.py b/mitmproxy/options.py
index bdc0db4e..75798381 100644
--- a/mitmproxy/options.py
+++ b/mitmproxy/options.py
@@ -73,7 +73,7 @@ class Options(optmanager.OptManager):
upstream_auth = "", # type: str
ssl_version_client="secure", # type: str
ssl_version_server="secure", # type: str
- ssl_verify_upstream_cert=False, # type: bool
+ ssl_insecure=False, # type: bool
ssl_verify_upstream_trusted_cadir=None, # type: str
ssl_verify_upstream_trusted_ca=None, # type: str
tcp_hosts = (), # type: Sequence[str]
@@ -130,7 +130,7 @@ class Options(optmanager.OptManager):
self.upstream_auth = upstream_auth
self.ssl_version_client = ssl_version_client
self.ssl_version_server = ssl_version_server
- self.ssl_verify_upstream_cert = ssl_verify_upstream_cert
+ self.ssl_insecure = ssl_insecure
self.ssl_verify_upstream_trusted_cadir = ssl_verify_upstream_trusted_cadir
self.ssl_verify_upstream_trusted_ca = ssl_verify_upstream_trusted_ca
self.tcp_hosts = tcp_hosts
diff --git a/mitmproxy/protocol/tls.py b/mitmproxy/protocol/tls.py
index 51f4d80d..d08e2e32 100644
--- a/mitmproxy/protocol/tls.py
+++ b/mitmproxy/protocol/tls.py
@@ -543,25 +543,12 @@ class TlsLayer(base.Layer):
)
tls_cert_err = self.server_conn.ssl_verification_error
if tls_cert_err is not None:
- self.log(
- "TLS verification failed for upstream server at depth %s with error: %s" %
- (tls_cert_err['depth'], tls_cert_err['errno']),
- "error")
- self.log("Ignoring server verification error, continuing with connection", "error")
+ self.log(str(tls_cert_err), "warn")
+ self.log("Ignoring server verification error, continuing with connection", "warn")
except netlib.exceptions.InvalidCertificateException as e:
- tls_cert_err = self.server_conn.ssl_verification_error
- self.log(
- "TLS verification failed for upstream server at depth %s with error: %s" %
- (tls_cert_err['depth'], tls_cert_err['errno']),
- "error")
- self.log("Aborting connection attempt", "error")
six.reraise(
- exceptions.TlsProtocolException,
- exceptions.TlsProtocolException("Cannot establish TLS with {address} (sni: {sni}): {e}".format(
- address=repr(self.server_conn.address),
- sni=self.server_sni,
- e=repr(e),
- )),
+ exceptions.InvalidServerCertificate,
+ exceptions.InvalidServerCertificate(str(e)),
sys.exc_info()[2]
)
except netlib.exceptions.TlsException as e:
diff --git a/mitmproxy/proxy/config.py b/mitmproxy/proxy/config.py
index a74ba7e2..cf75830a 100644
--- a/mitmproxy/proxy/config.py
+++ b/mitmproxy/proxy/config.py
@@ -83,24 +83,18 @@ class ProxyConfig:
options.changed.connect(self.configure)
def configure(self, options, updated):
- conflict = all(
- [
- options.add_upstream_certs_to_client_chain,
- options.ssl_verify_upstream_cert
- ]
- )
- if conflict:
+ # type: (mitmproxy.options.Options, Any) -> None
+ if options.add_upstream_certs_to_client_chain and not options.ssl_insecure:
raise exceptions.OptionsError(
- "The verify-upstream-cert and add-upstream-certs-to-client-chain "
- "options are mutually exclusive. If upstream certificates are verified "
- "then extra upstream certificates are not available for inclusion "
- "to the client chain."
+ "The verify-upstream-cert requires certificate verification to be disabled. "
+ "If upstream certificates are verified then extra upstream certificates are "
+ "not available for inclusion to the client chain."
)
- if options.ssl_verify_upstream_cert:
- self.openssl_verification_mode_server = SSL.VERIFY_PEER
- else:
+ if options.ssl_insecure:
self.openssl_verification_mode_server = SSL.VERIFY_NONE
+ else:
+ self.openssl_verification_mode_server = SSL.VERIFY_PEER
self.check_ignore = HostMatcher(options.ignore_hosts)
self.check_tcp = HostMatcher(options.tcp_hosts)
diff --git a/mitmproxy/proxy/server.py b/mitmproxy/proxy/server.py
index 26f2e294..4fd5755a 100644
--- a/mitmproxy/proxy/server.py
+++ b/mitmproxy/proxy/server.py
@@ -125,11 +125,14 @@ class ConnectionHandler(object):
self.log(
"Client Handshake failed. "
"The client may not trust the proxy's certificate for {}.".format(e.server),
- "error"
+ "warn"
)
self.log(repr(e), "debug")
+ elif isinstance(e, exceptions.InvalidServerCertificate):
+ self.log(str(e), "warn")
+ self.log("Invalid certificate, closing connection. Pass --insecure to disable validation.", "warn")
else:
- self.log(repr(e), "info")
+ self.log(repr(e), "warn")
self.log(traceback.format_exc(), "debug")
# If an error propagates to the topmost level,
diff --git a/netlib/tcp.py b/netlib/tcp.py
index cf099edd..e5c84165 100644
--- a/netlib/tcp.py
+++ b/netlib/tcp.py
@@ -8,6 +8,10 @@ import time
import traceback
import binascii
+
+from typing import Optional # noqa
+
+from netlib import strutils
from six.moves import range
import certifi
@@ -35,7 +39,7 @@ EINTR = 4
if os.environ.get("NO_ALPN"):
HAS_ALPN = False
else:
- HAS_ALPN = OpenSSL._util.lib.Cryptography_HAS_ALPN
+ HAS_ALPN = SSL._lib.Cryptography_HAS_ALPN
# To enable all SSL methods use: SSLv23
# then add options to disable certain methods
@@ -287,16 +291,7 @@ class Reader(_FileLike):
raise exceptions.TcpException(repr(e))
elif isinstance(self.o, SSL.Connection):
try:
- if tuple(int(x) for x in OpenSSL.__version__.split(".")[:2]) > (0, 15):
- return self.o.recv(length, socket.MSG_PEEK)
- else:
- # TODO: remove once a new version is released
- # Polyfill for pyOpenSSL <= 0.15.1
- # Taken from https://github.com/pyca/pyopenssl/commit/1d95dea7fea03c7c0df345a5ea30c12d8a0378d2
- buf = SSL._ffi.new("char[]", length)
- result = SSL._lib.SSL_peek(self.o._ssl, buf, length)
- self.o._raise_ssl_error(self.o._ssl, result)
- return SSL._ffi.buffer(buf, result)[:]
+ return self.o.recv(length, socket.MSG_PEEK)
except SSL.Error as e:
six.reraise(exceptions.TlsException, exceptions.TlsException(str(e)), sys.exc_info()[2])
else:
@@ -511,6 +506,7 @@ class _Connection(object):
alpn_protos=None,
alpn_select=None,
alpn_select_callback=None,
+ sni=None,
):
"""
Creates an SSL Context.
@@ -532,8 +528,14 @@ class _Connection(object):
if verify_options is not None:
def verify_cert(conn, x509, errno, err_depth, is_cert_verified):
if not is_cert_verified:
- self.ssl_verification_error = dict(errno=errno,
- depth=err_depth)
+ self.ssl_verification_error = exceptions.InvalidCertificateException(
+ "Certificate Verification Error for {}: {} (errno: {}, depth: {})".format(
+ sni,
+ strutils.native(SSL._ffi.string(SSL._lib.X509_verify_cert_error_string(errno)), "utf8"),
+ errno,
+ err_depth
+ )
+ )
return is_cert_verified
context.set_verify(verify_options, verify_cert)
@@ -609,7 +611,7 @@ class TCPClient(_Connection):
self.source_address = source_address
self.cert = None
self.server_certs = []
- self.ssl_verification_error = None
+ self.ssl_verification_error = None # type: Optional[exceptions.InvalidCertificateException]
self.sni = None
@property
@@ -671,6 +673,7 @@ class TCPClient(_Connection):
context = self.create_ssl_context(
alpn_protos=alpn_protos,
+ sni=sni,
**sslctx_kwargs
)
self.connection = SSL.Connection(context, self.connection)
@@ -682,14 +685,14 @@ class TCPClient(_Connection):
self.connection.do_handshake()
except SSL.Error as v:
if self.ssl_verification_error:
- raise exceptions.InvalidCertificateException("SSL handshake error: %s" % repr(v))
+ raise self.ssl_verification_error
else:
raise exceptions.TlsException("SSL handshake error: %s" % repr(v))
else:
# Fix for pre v1.0 OpenSSL, which doesn't throw an exception on
# certificate validation failure
- if verification_mode == SSL.VERIFY_PEER and self.ssl_verification_error is not None:
- raise exceptions.InvalidCertificateException("SSL handshake error: certificate verify failed")
+ if verification_mode == SSL.VERIFY_PEER and self.ssl_verification_error:
+ raise self.ssl_verification_error
self.cert = certutils.SSLCert(self.connection.get_peer_certificate())
@@ -710,9 +713,14 @@ class TCPClient(_Connection):
hostname = "no-hostname"
ssl_match_hostname.match_hostname(crt, hostname)
except (ValueError, ssl_match_hostname.CertificateError) as e:
- self.ssl_verification_error = dict(depth=0, errno="Invalid Hostname")
+ self.ssl_verification_error = exceptions.InvalidCertificateException(
+ "Certificate Verification Error for {}: {}".format(
+ sni or repr(self.address),
+ str(e)
+ )
+ )
if verification_mode == SSL.VERIFY_PEER:
- raise exceptions.InvalidCertificateException("Presented certificate for {} is not valid: {}".format(sni, str(e)))
+ raise self.ssl_verification_error
self.ssl_established = True
self.rfile.set_descriptor(self.connection)
diff --git a/test/mitmproxy/data/servercert/9da13359.0 b/test/mitmproxy/data/servercert/9da13359.0
new file mode 100644
index 00000000..b22e4d20
--- /dev/null
+++ b/test/mitmproxy/data/servercert/9da13359.0
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDXTCCAkWgAwIBAgIJAPAfPQGCV/Z4MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTUxMTAxMTY0ODAxWhcNMTgwODIxMTY0ODAxWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEArp8LD34JhKCwcQbwIYQMg4+eCgLVN8fwB7+/qOfJbArPs0djFBN+F7c6
+HGvMr24BKUk5u8pn4dPtNurm/vPC8ovNGmcXz62BQJpcMX2veVdRsF7yNwhNacNJ
+Arq+70zNMwYBznx0XUxMF6j6nVFf3AW6SU04ylT4Mp3SY/BUUDAdfl1eRo0mPLNS
+8rpsN+8YBw1Q7SCuBRVqpOgVIsL88svgQUSOlzvMZPBpG/cmB3BNKNrltwb5iFEI
+1jAV7uSj5IcIuNO/246kfsDVPTFMJIzav/CUoidd5UNw+SoFDlzh8sA7L1Bm7D1/
+3KHYSKswGsSR3kynAl10w/SJKDtn8wIDAQABo1AwTjAdBgNVHQ4EFgQUgOcrtxBX
+LxbpnOT65d+vpfyWUkgwHwYDVR0jBBgwFoAUgOcrtxBXLxbpnOT65d+vpfyWUkgw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAEE9bFmUCA+6cvESKPoi2
+TGSpV652d0xd2U66LpEXeiWRJFLz8YGgoJCx3QFGBscJDXxrLxrBBBV/tCpEqypo
+pYIqsawH7M66jpOr83Us3M8JC2eFBZJocMpXxdytWqHik5VKZNx6VQFT8bS7+yVC
+VoUKePhlgcg+pmo41qjqieBNKRMh/1tXS77DI1lgO5wZLVrLXcdqWuDpmaQOKJeq
+G/nxytCW/YJA7bFn/8Gjy8DYypJSeeaKu7o3P3+ONJHdIMHb+MdcheDBS9AOFSeo
+xI0D5EbO9F873O77l7nbD7B0X34HFN0nGczC4poexIpbDFG3hAPekwZ5KC6VwJLc
+1Q==
+-----END CERTIFICATE-----
diff --git a/test/mitmproxy/data/servercert/self-signed.pem b/test/mitmproxy/data/servercert/self-signed.pem
new file mode 100644
index 00000000..cd066a24
--- /dev/null
+++ b/test/mitmproxy/data/servercert/self-signed.pem
@@ -0,0 +1,46 @@
+-----BEGIN CERTIFICATE-----
+MIIDEzCCAfugAwIBAgIJAJ945xt1FRsfMA0GCSqGSIb3DQEBCwUAMCAxHjAcBgNV
+BAMMFWV4YW1wbGUubWl0bXByb3h5Lm9yZzAeFw0xNTExMDExNjQ4MDJaFw0xODA4
+MjExNjQ4MDJaMCAxHjAcBgNVBAMMFWV4YW1wbGUubWl0bXByb3h5Lm9yZzCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALFxyzPfjgIghOMMnJlW80yB84xC
+nJtko3tuyOdozgTCyha2W+NdIKPNZJtWrzN4P0B5PlozCDwfcSYffLs0WZs8LRWv
+BfZX8+oX+14qQjKFsiqgO65cTLP3qlPySYPJQQ37vOP1Y5Yf8nQq2mwQdC18hLtT
+QOANG6OFoSplpBLsYF+QeoMgqCTa6hrl/5GLmQoDRTjXkv3Sj379AUDMybuBqccm
+q5EIqCrE4+xJ8JywJclAVn2YP14baiFrrYCsYYg4sS1Od6xFj+xtpLe7My3AYjB9
+/aeHd8vDiob0cqOW1TFwhqgJKuErfFyg8lZ2hJmStJKyfofWuY/gl/vnvX0CAwEA
+AaNQME4wHQYDVR0OBBYEFB8d32zK8eqZIoKw4jXzYzhw4amPMB8GA1UdIwQYMBaA
+FB8d32zK8eqZIoKw4jXzYzhw4amPMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBAJmo2oKv1OEjZ0Q4yELO6BAnHAkmBKpW+zmLyQa8idxtLVkI9uXk3iqY
+GWugkmcUZCTVFRWv/QXQQSex+00IY3x2rdHbtuZwcyKiz2u8WEmfW1rOIwBaFJ1i
+v7+SA2aZs6vepN2sE56X54c/YbwQooaKZtOb+djWXYMJrc/Ezj0J7oQIJTptYV8v
+/3216yCHRp/KCL7yTLtiw25xKuXNu/gkcd8wZOY9rS2qMUD897MJF0MvgJoauRBd
+d4XEYCNKkrIRmfqrkiRQfAZpvpoutH6NCk7KuQYcI0BlOHlsnHHcs/w72EEqHwFq
+x6476tW/t8GJDZVD74+pNBcLifXxArE=
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAsXHLM9+OAiCE4wycmVbzTIHzjEKcm2Sje27I52jOBMLKFrZb
+410go81km1avM3g/QHk+WjMIPB9xJh98uzRZmzwtFa8F9lfz6hf7XipCMoWyKqA7
+rlxMs/eqU/JJg8lBDfu84/Vjlh/ydCrabBB0LXyEu1NA4A0bo4WhKmWkEuxgX5B6
+gyCoJNrqGuX/kYuZCgNFONeS/dKPfv0BQMzJu4GpxyarkQioKsTj7EnwnLAlyUBW
+fZg/XhtqIWutgKxhiDixLU53rEWP7G2kt7szLcBiMH39p4d3y8OKhvRyo5bVMXCG
+qAkq4St8XKDyVnaEmZK0krJ+h9a5j+CX++e9fQIDAQABAoIBAQCT+FvGbych2PJX
+0D2KlXqgE0IAdc/YuYymstSwPLKIP9N8KyfnKtK8Jdw+uYOyfRTp8/EuEJ5OXL3j
+V6CRD++lRwIlseVb7y5EySjh9oVrUhgn+aSrGucPsHkGNeZeEmbAfWugARLBrvRl
+MRMhyHrJL6wT9jIEZInmy9mA3G99IuFW3rS8UR1Yu7zyvhtjvop1xg/wfEUu24Ty
+PvMfnwaDcZHCz2tmu2KJvaxSBAG3FKmAqeMvk1Gt5m2keKgw03M+EX0LrM8ybWqn
+VwB8tnSyMBLVFLIXMpIiSfpji10+p9fdKFMRF++D6qVwyoxPiIq+yEJapxXiqLea
+mkhtJW91AoGBAOvIb7bZvH4wYvi6txs2pygF3ZMjqg/fycnplrmYMrjeeDeeN4v1
+h/5tkN9TeTkHRaN3L7v49NEUDhDyuopLTNfWpYdv63U/BVzvgMm/guacTYkx9whB
+OvQ2YekR/WKg7kuyrTZidTDz+mjU+1b8JaWGjiDc6vFwxZA7uWicaGGHAoGBAMCo
+y/2AwFGwCR+5bET1nTTyxok6iKo4k6R/7DJe4Bq8VLifoyX3zDlGG/33KN3xVqBU
+xnT9gkii1lfX2U+4iM+GOSPl0nG0hOEqEH+vFHszpHybDeNez3FEyIbgOzg6u7sV
+NOy+P94L5EMQVEmWp5g6Vm3k9kr92Bd9UacKQPnbAoGAMN8KyMu41i8RVJze9zUM
+0K7mjmkGBuRL3x4br7xsRwVVxbF1sfzig0oSjTewGLH5LTi3HC8uD2gowjqNj7yr
+4NEM3lXEaDj305uRBkA70bD0IUvJ+FwM7DGZecXQz3Cr8+TFIlCmGc94R+Jddlot
+M3IAY69mw0SsroiylYxV1mECgYAcSGtx8rXJCDO+sYTgdsI2ZLGasbogax/ZlWIC
+XwU9R4qUc/MKft8/RTiUxvT76BMUhH2B7Tl0GlunF6vyVR/Yf1biGzoSsTKUr40u
+gXBbSdCK7mRSjbecZEGf80keTxkCNPHJE4DiwxImej41c2V1JpNLnMI/bhaMFDyp
+bgrt4wKBgHFzZgAgM1v07F038tAkIBGrYLukY1ZFBaZoGZ9xHfy/EmLJM3HCHLO5
+8wszMGhMTe2+39EeChwgj0kFaq1YnDiucU74BC57KR1tD59y7l6UnsQXTm4/32j8
+Or6i8GekBibCb97DzzOU0ZK//fNhHTXpDDXsYt5lJUWSmgW+S9Qp
+-----END RSA PRIVATE KEY-----
diff --git a/test/mitmproxy/data/servercert/trusted-leaf.pem b/test/mitmproxy/data/servercert/trusted-leaf.pem
new file mode 100644
index 00000000..71700f2a
--- /dev/null
+++ b/test/mitmproxy/data/servercert/trusted-leaf.pem
@@ -0,0 +1,45 @@
+-----BEGIN CERTIFICATE-----
+MIIC4TCCAckCCQCj6D9oVylb8jANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMB4XDTE1MTEwMTE2NDgwMloXDTE4MDgyMTE2NDgwMlowIDEeMBwG
+A1UEAwwVZXhhbXBsZS5taXRtcHJveHkub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAy/L5JYHS7QFhSIsjmd6bJTgs2rdqEn6tsmPBVZKZ7SqCAVjW
+hPpEu7Q23akmU6Zm9Fp/vENc3jzxQLlEKhrv7eWmFYSOrCYtbJOz3RQorlwjjfdY
+LlNQh1wYUXQX3PN3r3dyYtt5vTtXKc8+aP4M4vX7qlbW+4j4LrQfmPjS0XOdYpu3
+wh+i1ZMIhZye3hpCjwnpjTf7/ff45ZFxtkoi1uzEC/+swr1RSvamY8Foe12Re17Z
+5ij8ZB0NIdoSk1tDkY3sJ8iNi35+qartl0UYeG9IUXRwDRrPsEKpF4RxY1+X2bdZ
+r6PKb/E4CA5JlMvS5SVmrvxjCVqTQBmTjXfxqwIDAQABMA0GCSqGSIb3DQEBCwUA
+A4IBAQBmpSZJrTDvzSlo6P7P7x1LoETzHyVjwgPeqGYw6ndGXeJMN9rhhsFvRsiB
+I/aHh58MIlSjti7paikDAoFHB3dBvFHR+JUa/ailWEbcZReWRSE3lV6wFiN3G3lU
+OyofR7MKnPW7bv8hSqOLqP1mbupXuQFB5M6vPLRwg5VgiCHI/XBiTvzMamzvNAR3
+UHHZtsJkRqzogYm6K9YJaga7jteSx2nNo+ujLwrxeXsLChTyFMJGnVkp5IyKeNfc
+qwlzNncb3y+4KnUdNkPEtuydgAxAfuyXufiFBYRcUWbQ5/9ycgF7131ySaj9f/Y2
+kMsv2jg+soKvwwVYCABsk1KSHtfz
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAy/L5JYHS7QFhSIsjmd6bJTgs2rdqEn6tsmPBVZKZ7SqCAVjW
+hPpEu7Q23akmU6Zm9Fp/vENc3jzxQLlEKhrv7eWmFYSOrCYtbJOz3RQorlwjjfdY
+LlNQh1wYUXQX3PN3r3dyYtt5vTtXKc8+aP4M4vX7qlbW+4j4LrQfmPjS0XOdYpu3
+wh+i1ZMIhZye3hpCjwnpjTf7/ff45ZFxtkoi1uzEC/+swr1RSvamY8Foe12Re17Z
+5ij8ZB0NIdoSk1tDkY3sJ8iNi35+qartl0UYeG9IUXRwDRrPsEKpF4RxY1+X2bdZ
+r6PKb/E4CA5JlMvS5SVmrvxjCVqTQBmTjXfxqwIDAQABAoIBAQC956DWq+wbhA1x
+3x1nSUBth8E8Z0z9q7dRRFHhvIBXth0X5ADcEa2umj/8ZmSpv2heX2ZRhugSh+yc
+t+YgzrRacFwV7ThsU6A4WdBBK2Q19tWke4xAlpOFdtut/Mu7kXkAidiY9ISHD5o5
+9B/I48ZcD3AnTHUiAogV9OL3LbogDD4HasLt4mWkbq8U2thdjxMIvxdg36olJEuo
+iAZrAUCPZEXuU89BtvPLUYioe9n90nzkyneGNS0SHxotlEc9ZYK9VTsivtXJb4wB
+ptDMCp+TH3tjo8BTGnbnoZEybgyyOEd0UTzxK4DlxnvRVWexFY6NXwPFhIxKlB0Y
+Bg8NkAkBAoGBAOiRnmbC5QkqrKrTkLx3fghIHPqgEXPPYgHLSuY3UjTlMb3APXpq
+vzQnlCn3QuSse/1fWnQj+9vLVbx1XNgKjzk7dQhn5IUY+mGN4lLmoSnTebxvSQ43
+VAgTYjST9JFmJ3wK4KkWDsEsVao8LAx0h5JEQXUTT5xZpFA2MLztYbgfAoGBAOB/
+MvhLMAwlx8+m/zXMEPLk/KOd2dVZ4q5se8bAT/GiGsi8JUcPnCk140ZZabJqryAp
+JFzUHIjfVsS9ejAfocDk1JeIm7Uus4um6fQEKIPMBxI/M/UAwYCXAG9ULXqilbO3
+pTdeeuraVKrTu1Z4ea6x4du1JWKcyDfYfsHepcT1AoGBAM2fskV5G7e3G2MOG3IG
+1E/OMpEE5WlXenfLnjVdxDkwS4JRbgnGR7d9JurTyzkTp6ylmfwFtLDoXq15ttTs
+wSUBBMCh2tIy+201XV2eu++XIpMQca84C/v352RFTH8hqtdpZqkY74KsCDGzcd6x
+SQxxfM5efIzoVPb2crEX0MZRAoGAQ2EqFSfL9flo7UQ8GRN0itJ7mUgJV2WxCZT5
+2X9i/y0eSN1feuKOhjfsTPMNLEWk5kwy48GuBs6xpj8Qa10zGUgVHp4bzdeEgAfK
+9DhDSLt1694YZBKkAUpRERj8xXAC6nvWFLZAwjhhbRw7gAqMywgMt/q4i85usYRD
+F0ESE/kCgYBbc083PcLmlHbkn/d1i4IcLI6wFk+tZYIEVYDid7xDOgZOBcOTTyYB
+BrDzNqbKNexKRt7QHVlwR+VOGMdN5P0hf7oH3SMW23OxBKoQe8pUSGF9a4DjCS1v
+vCXMekifb9kIhhUWaG71L8+MaOzNBVAmk1+3NzPZgV/YxHjAWWhGHQ==
+-----END RSA PRIVATE KEY-----
diff --git a/test/mitmproxy/data/servercert/trusted-root.pem b/test/mitmproxy/data/servercert/trusted-root.pem
new file mode 100644
index 00000000..2c75b88e
--- /dev/null
+++ b/test/mitmproxy/data/servercert/trusted-root.pem
@@ -0,0 +1,48 @@
+-----BEGIN CERTIFICATE-----
+MIIDXTCCAkWgAwIBAgIJAPAfPQGCV/Z4MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTUxMTAxMTY0ODAxWhcNMTgwODIxMTY0ODAxWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEArp8LD34JhKCwcQbwIYQMg4+eCgLVN8fwB7+/qOfJbArPs0djFBN+F7c6
+HGvMr24BKUk5u8pn4dPtNurm/vPC8ovNGmcXz62BQJpcMX2veVdRsF7yNwhNacNJ
+Arq+70zNMwYBznx0XUxMF6j6nVFf3AW6SU04ylT4Mp3SY/BUUDAdfl1eRo0mPLNS
+8rpsN+8YBw1Q7SCuBRVqpOgVIsL88svgQUSOlzvMZPBpG/cmB3BNKNrltwb5iFEI
+1jAV7uSj5IcIuNO/246kfsDVPTFMJIzav/CUoidd5UNw+SoFDlzh8sA7L1Bm7D1/
+3KHYSKswGsSR3kynAl10w/SJKDtn8wIDAQABo1AwTjAdBgNVHQ4EFgQUgOcrtxBX
+LxbpnOT65d+vpfyWUkgwHwYDVR0jBBgwFoAUgOcrtxBXLxbpnOT65d+vpfyWUkgw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAEE9bFmUCA+6cvESKPoi2
+TGSpV652d0xd2U66LpEXeiWRJFLz8YGgoJCx3QFGBscJDXxrLxrBBBV/tCpEqypo
+pYIqsawH7M66jpOr83Us3M8JC2eFBZJocMpXxdytWqHik5VKZNx6VQFT8bS7+yVC
+VoUKePhlgcg+pmo41qjqieBNKRMh/1tXS77DI1lgO5wZLVrLXcdqWuDpmaQOKJeq
+G/nxytCW/YJA7bFn/8Gjy8DYypJSeeaKu7o3P3+ONJHdIMHb+MdcheDBS9AOFSeo
+xI0D5EbO9F873O77l7nbD7B0X34HFN0nGczC4poexIpbDFG3hAPekwZ5KC6VwJLc
+1Q==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEArp8LD34JhKCwcQbwIYQMg4+eCgLVN8fwB7+/qOfJbArPs0dj
+FBN+F7c6HGvMr24BKUk5u8pn4dPtNurm/vPC8ovNGmcXz62BQJpcMX2veVdRsF7y
+NwhNacNJArq+70zNMwYBznx0XUxMF6j6nVFf3AW6SU04ylT4Mp3SY/BUUDAdfl1e
+Ro0mPLNS8rpsN+8YBw1Q7SCuBRVqpOgVIsL88svgQUSOlzvMZPBpG/cmB3BNKNrl
+twb5iFEI1jAV7uSj5IcIuNO/246kfsDVPTFMJIzav/CUoidd5UNw+SoFDlzh8sA7
+L1Bm7D1/3KHYSKswGsSR3kynAl10w/SJKDtn8wIDAQABAoIBAFgMzjDzpqz/sbhs
+fS0JPp4gDtqRbx3/bSMbJvNuXPxjvzNxLZ5z7cLbmyu1l7Jlz6QXzkrI1vTiPdzR
+OcUY+RYANF252iHYJTKEIzS5YX/X7dL3LT9eqlpIJEqCC8Dygw3VW5fY3Xwl+sB7
+blNhMuro4HQRwi8UBUrQlcPa7Ui5BBi323Q6en+VjYctkqpJHzNKPSqPTbsdLaK+
+B0XuXxFatM09rmeRKZCL71Lk1T8N/l0hqEzej7zxgVD7vG/x1kMFN4T3yCmXCbPa
+izGHYr1EBHglm4qMNWveXCZiVJ+wmwCjdjqvggyHiZFXE2N0OCrWPhxQPdqFf5y7
+bUO9U2ECgYEA6GM1UzRnbVpjb20ezFy7dU7rlWM0nHBfG27M3bcXh4HnPpnvKp0/
+8a1WFi4kkRywrNXx8hFEd43vTbdObLpVXScXRKiY3MHmFk4k4hbWuTpmumCubQZO
+AWlX6TE0HRKn1wQahgpQcxcWaDN2xJJmRQ1zVmlnNkT48/4kFgRxyykCgYEAwF08
+ngrF35oYoU/x+KKq2NXGeNUzoZMj568dE1oWW0ZFpqCi+DGT+hAbG3yUOBSaPqy9
+zn1obGo0YRlrayvtebz118kG7a/rzY02VcAPlT/GpEhvkZlXTwEK17zRJc1nJrfP
+39QAZWZsaOru9NRIg/8HcdG3JPR2MhRD/De9GbsCgYAaiZnBUq6s8jGAu/lUZRKT
+JtwIRzfu1XZG77Q9bXcmZlM99t41A5gVxTGbftF2MMyMMDJc7lPfQzocqd4u1GiD
+Jr+le4tZSls4GNxlZS5IIL8ycW/5y0qFJr5/RrsoxsSb7UAKJothWTWZ2Karc/xx
+zkNpjsfWjrHPSypbyU4lYQKBgFh1R5/BgnatjO/5LGNSok/uFkOQfxqo6BTtYOh6
+P9efO/5A1lBdtBeE+oIsSphzWO7DTtE6uB9Kw2V3Y/83hw+5RjABoG8Cu+OdMURD
+eqb+WeFH8g45Pn31E8Bbcq34g5u5YR0jhz8Z13ZzuojZabNRPmIntxmGVSf4S78a
+/plrAoGBANMHNng2lyr03nqnHrOM6NXD+60af0YR/YJ+2d/H40RnXxGJ4DXn7F00
+a4vJFPa97uq+xpd0HE+TE+NIrOdVDXPePD2qzBzMTsctGtj30vLzojMOT+Yf/nvO
+WxTL5Q8GruJz2Dn0awSZO2z/3A8S1rmpuVZ/jT5NtRrvOSY6hmxF
+-----END RSA PRIVATE KEY-----
diff --git a/test/mitmproxy/data/trusted-cadir/8117bdb9.0 b/test/mitmproxy/data/trusted-cadir/8117bdb9.0
deleted file mode 100644
index ae78b546..00000000
--- a/test/mitmproxy/data/trusted-cadir/8117bdb9.0
+++ /dev/null
@@ -1,14 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICJzCCAZACCQCo1BdopddN/TANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJB
-VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
-cyBQdHkgTHRkMRAwDgYDVQQDEwdUUlVTVEVEMCAXDTE1MDYxOTE4MDEzMVoYDzIx
-MTUwNTI2MTgwMTMxWjBXMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0
-ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRAwDgYDVQQDEwdU
-UlVTVEVEMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC00Jf3KrBAmLQWl+Dz
-8Qrig8ActB94kv0/Lu03P/2DwOR8kH2h3w4OC3b3CFKX31h7hm/H1PPHq7cIX6IR
-fwrYCtBE77UbxklSlrwn06j6YSotz0/dwLEQEFDXWITJq7AyntaiafDHazbbXESN
-m/+I/YEl2wKemEHE//qWbeM9kwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAF0NREP3
-X+fTebzJGttzrFkDhGVFKRNyLXblXRVanlGOYF+q8grgZY2ufC/55gqf+ub6FRT5
-gKPhL4V2rqL8UAvCE7jq8ujpVfTB8kRAKC675W2DBZk2EJX9mjlr89t7qXGsI5nF
-onpfJ1UtiJshNoV7h/NFHeoag91kx628807n
------END CERTIFICATE-----
diff --git a/test/mitmproxy/data/trusted-cadir/9d45e6a9.0 b/test/mitmproxy/data/trusted-cadir/9d45e6a9.0
deleted file mode 100644
index ae78b546..00000000
--- a/test/mitmproxy/data/trusted-cadir/9d45e6a9.0
+++ /dev/null
@@ -1,14 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICJzCCAZACCQCo1BdopddN/TANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJB
-VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
-cyBQdHkgTHRkMRAwDgYDVQQDEwdUUlVTVEVEMCAXDTE1MDYxOTE4MDEzMVoYDzIx
-MTUwNTI2MTgwMTMxWjBXMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0
-ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRAwDgYDVQQDEwdU
-UlVTVEVEMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC00Jf3KrBAmLQWl+Dz
-8Qrig8ActB94kv0/Lu03P/2DwOR8kH2h3w4OC3b3CFKX31h7hm/H1PPHq7cIX6IR
-fwrYCtBE77UbxklSlrwn06j6YSotz0/dwLEQEFDXWITJq7AyntaiafDHazbbXESN
-m/+I/YEl2wKemEHE//qWbeM9kwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAF0NREP3
-X+fTebzJGttzrFkDhGVFKRNyLXblXRVanlGOYF+q8grgZY2ufC/55gqf+ub6FRT5
-gKPhL4V2rqL8UAvCE7jq8ujpVfTB8kRAKC675W2DBZk2EJX9mjlr89t7qXGsI5nF
-onpfJ1UtiJshNoV7h/NFHeoag91kx628807n
------END CERTIFICATE-----
diff --git a/test/mitmproxy/data/trusted-cadir/trusted-ca.pem b/test/mitmproxy/data/trusted-cadir/trusted-ca.pem
deleted file mode 100644
index ae78b546..00000000
--- a/test/mitmproxy/data/trusted-cadir/trusted-ca.pem
+++ /dev/null
@@ -1,14 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICJzCCAZACCQCo1BdopddN/TANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJB
-VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
-cyBQdHkgTHRkMRAwDgYDVQQDEwdUUlVTVEVEMCAXDTE1MDYxOTE4MDEzMVoYDzIx
-MTUwNTI2MTgwMTMxWjBXMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0
-ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRAwDgYDVQQDEwdU
-UlVTVEVEMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC00Jf3KrBAmLQWl+Dz
-8Qrig8ActB94kv0/Lu03P/2DwOR8kH2h3w4OC3b3CFKX31h7hm/H1PPHq7cIX6IR
-fwrYCtBE77UbxklSlrwn06j6YSotz0/dwLEQEFDXWITJq7AyntaiafDHazbbXESN
-m/+I/YEl2wKemEHE//qWbeM9kwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAF0NREP3
-X+fTebzJGttzrFkDhGVFKRNyLXblXRVanlGOYF+q8grgZY2ufC/55gqf+ub6FRT5
-gKPhL4V2rqL8UAvCE7jq8ujpVfTB8kRAKC675W2DBZk2EJX9mjlr89t7qXGsI5nF
-onpfJ1UtiJshNoV7h/NFHeoag91kx628807n
------END CERTIFICATE-----
diff --git a/test/mitmproxy/data/trusted-server.crt b/test/mitmproxy/data/trusted-server.crt
deleted file mode 100644
index 76f8559a..00000000
--- a/test/mitmproxy/data/trusted-server.crt
+++ /dev/null
@@ -1,33 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC8jCCAlugAwIBAgICEAcwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQVUx
-EzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMg
-UHR5IEx0ZDEQMA4GA1UEAxMHVFJVU1RFRDAgFw0xNTA2MjAwMTE4MjdaGA8yMTE1
-MDUyNzAxMTgyN1owfjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx
-ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UECxMLSU5U
-RVJNIFVOSVQxITAfBgNVBAMTGE9SRyBXSVRIIElOVEVSTUVESUFURSBDQTCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtRPNKgh4WdYGmU2Ae6Tf2Mbd3oaRI/uY
-Qm6aKeYk1i7g41C0vVowNcD/qdNpGUNnai/Kak9anHOYyppNo7zHgf3EO8zQ4NTQ
-pkDKsdCqbUQcjGfhjWXKnOw+I5er4Rj+MwM1f5cbwb8bYHiSPmXaxzdL0/SNXGAA
-ys/UswgwkU8CAwEAAaOBozCBoDAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBTPkPQW
-DAPOIy8mipuEsZcP1694EDBxBgNVHSMEajBooVukWTBXMQswCQYDVQQGEwJBVTET
-MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMRAwDgYDVQQDEwdUUlVTVEVEggkAqNQXaKXXTf0wDQYJKoZIhvcNAQEF
-BQADgYEApaPbwonY8l+zSxlY2Fw4WNKfl5nwcTW4fuv/0tZLzvsS6P4hTXxbYJNa
-k3hQ1qlrr8DiWJewF85hYvEI2F/7eqS5dhhPTEUFPpsjhbgiqnASvW+WKQIgoY2r
-aHgOXi7RNFtTcCgk0UZISWOY7ORLy8Xu6vKrLRjDhyfIbGlqnAs=
------END CERTIFICATE-----
------BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQC1E80qCHhZ1gaZTYB7pN/Yxt3ehpEj+5hCbpop5iTWLuDjULS9
-WjA1wP+p02kZQ2dqL8pqT1qcc5jKmk2jvMeB/cQ7zNDg1NCmQMqx0KptRByMZ+GN
-Zcqc7D4jl6vhGP4zAzV/lxvBvxtgeJI+ZdrHN0vT9I1cYADKz9SzCDCRTwIDAQAB
-AoGAfKHocKnrzEmXuSSy7meI+vfF9kfA1ndxUSg3S+dwK0uQ1mTSQhI1ZIo2bnlo
-uU6/e0Lxm0KLJ2wZGjoifjSNTC8pcxIfAQY4kM9fqoUcXVSBVSS2kByTunhNSVZQ
-yQyc+UTq9g1zBnJsZAltn7/PaihU4heWgP/++lposuShqmECQQDaG+7l0qul1xak
-9kuZgc88BSTfn9iMK2zIQRcVKuidK4dT3QEp0wmWR5Ue8jq8lvTmVTGNGZbHcheh
-KhoZfLgLAkEA1IjwAw/8z02yV3lbc2QUjIl9m9lvjHBoE2sGuSfq/cZskLKrGat+
-CVj3spqVAg22tpQwVBuHiipBziWVnEtiTQJAB9FKfchQSLBt6lm9mfHyKJeSm8VR
-8Kw5yO+0URjpn4CI6DOasBIVXOKR8LsD6fCLNJpHHWSWZ+2p9SfaKaGzwwJBAM31
-Scld89qca4fzNZkT0goCrvOZeUy6HVE79Q72zPVSFSD/02kT1BaQ3bB5to5/5aD2
-6AKJjwZoPs7bgykrsD0CQBzU8U/8x2dNQnG0QeqaKQu5kKhZSZ9bsawvrCkxSl6b
-WAjl/Jehi5bbQ07zQo3cge6qeR38FCWVCHQ/5wNbc54=
------END RSA PRIVATE KEY-----
diff --git a/test/mitmproxy/data/untrusted-server.crt b/test/mitmproxy/data/untrusted-server.crt
deleted file mode 100644
index 62e58601..00000000
--- a/test/mitmproxy/data/untrusted-server.crt
+++ /dev/null
@@ -1,32 +0,0 @@
-# untrusted-interm.crt, self-signed
------BEGIN CERTIFICATE-----
-MIICdTCCAd4CCQDRSKOnIMbTgDANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJB
-VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
-cyBQdHkgTHRkMRQwEgYDVQQLEwtJTlRFUk0gVU5JVDEhMB8GA1UEAxMYT1JHIFdJ
-VEggSU5URVJNRURJQVRFIENBMCAXDTE1MDYyMDAxMzY0M1oYDzIxMTUwNTI3MDEz
-NjQzWjB+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UE
-ChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRQwEgYDVQQLEwtJTlRFUk0gVU5J
-VDEhMB8GA1UEAxMYT1JHIFdJVEggSU5URVJNRURJQVRFIENBMIGfMA0GCSqGSIb3
-DQEBAQUAA4GNADCBiQKBgQC1E80qCHhZ1gaZTYB7pN/Yxt3ehpEj+5hCbpop5iTW
-LuDjULS9WjA1wP+p02kZQ2dqL8pqT1qcc5jKmk2jvMeB/cQ7zNDg1NCmQMqx0Kpt
-RByMZ+GNZcqc7D4jl6vhGP4zAzV/lxvBvxtgeJI+ZdrHN0vT9I1cYADKz9SzCDCR
-TwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAGbObAMEajCz4kj7OP2/DB5SRy2+H/G3
-8Qvc43xlMMNQyYxsDuLOFL0UMRzoKgntrrm2nni8jND+tuMt+hv3ZlBcJlYJ6ynR
-sC1ITTC/1SwwwO0AFIyduUEIJYr/B3sgcVYPLcEfeDZgmEQc9Tnc01aEu3lx2+l9
-0JTSPL2L9LdA
------END CERTIFICATE-----
------BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQC1E80qCHhZ1gaZTYB7pN/Yxt3ehpEj+5hCbpop5iTWLuDjULS9
-WjA1wP+p02kZQ2dqL8pqT1qcc5jKmk2jvMeB/cQ7zNDg1NCmQMqx0KptRByMZ+GN
-Zcqc7D4jl6vhGP4zAzV/lxvBvxtgeJI+ZdrHN0vT9I1cYADKz9SzCDCRTwIDAQAB
-AoGAfKHocKnrzEmXuSSy7meI+vfF9kfA1ndxUSg3S+dwK0uQ1mTSQhI1ZIo2bnlo
-uU6/e0Lxm0KLJ2wZGjoifjSNTC8pcxIfAQY4kM9fqoUcXVSBVSS2kByTunhNSVZQ
-yQyc+UTq9g1zBnJsZAltn7/PaihU4heWgP/++lposuShqmECQQDaG+7l0qul1xak
-9kuZgc88BSTfn9iMK2zIQRcVKuidK4dT3QEp0wmWR5Ue8jq8lvTmVTGNGZbHcheh
-KhoZfLgLAkEA1IjwAw/8z02yV3lbc2QUjIl9m9lvjHBoE2sGuSfq/cZskLKrGat+
-CVj3spqVAg22tpQwVBuHiipBziWVnEtiTQJAB9FKfchQSLBt6lm9mfHyKJeSm8VR
-8Kw5yO+0URjpn4CI6DOasBIVXOKR8LsD6fCLNJpHHWSWZ+2p9SfaKaGzwwJBAM31
-Scld89qca4fzNZkT0goCrvOZeUy6HVE79Q72zPVSFSD/02kT1BaQ3bB5to5/5aD2
-6AKJjwZoPs7bgykrsD0CQBzU8U/8x2dNQnG0QeqaKQu5kKhZSZ9bsawvrCkxSl6b
-WAjl/Jehi5bbQ07zQo3cge6qeR38FCWVCHQ/5wNbc54=
------END RSA PRIVATE KEY-----
diff --git a/test/mitmproxy/test_protocol_http2.py b/test/mitmproxy/test_protocol_http2.py
index aa096a72..f0fa9a40 100644
--- a/test/mitmproxy/test_protocol_http2.py
+++ b/test/mitmproxy/test_protocol_http2.py
@@ -102,7 +102,11 @@ class _Http2TestBase(object):
@classmethod
def get_options(cls):
- opts = options.Options(listen_port=0, no_upstream_cert=False)
+ opts = options.Options(
+ listen_port=0,
+ no_upstream_cert=False,
+ ssl_insecure=True
+ )
opts.cadir = os.path.join(tempfile.gettempdir(), "mitmproxy")
return opts
diff --git a/test/mitmproxy/test_proxy.py b/test/mitmproxy/test_proxy.py
index 6e790e28..84838018 100644
--- a/test/mitmproxy/test_proxy.py
+++ b/test/mitmproxy/test_proxy.py
@@ -146,9 +146,9 @@ class TestProcessProxyOptions:
"--singleuser",
"test")
- def test_verify_upstream_cert(self):
- p = self.assert_noerr("--verify-upstream-cert")
- assert p.openssl_verification_mode_server == SSL.VERIFY_PEER
+ def test_insecure(self):
+ p = self.assert_noerr("--insecure")
+ assert p.openssl_verification_mode_server == SSL.VERIFY_NONE
def test_upstream_trusted_cadir(self):
expected_dir = "/path/to/a/ca/dir"
diff --git a/test/mitmproxy/test_server.py b/test/mitmproxy/test_server.py
index 6230fc1f..78e9b5c7 100644
--- a/test/mitmproxy/test_server.py
+++ b/test/mitmproxy/test_server.py
@@ -2,22 +2,21 @@ import os
import socket
import time
import types
-from OpenSSL import SSL
-from netlib.exceptions import HttpReadDisconnect, HttpException
-from netlib.tcp import Address
import netlib.tutils
+from mitmproxy import controller
+from mitmproxy import options
+from mitmproxy.builtins import script
+from mitmproxy.models import Error, HTTPResponse, HTTPFlow
+from mitmproxy.proxy.config import HostMatcher, parse_server_spec
from netlib import tcp, http, socks
from netlib.certutils import SSLCert
+from netlib.exceptions import HttpReadDisconnect, HttpException
from netlib.http import authentication, http1
+from netlib.tcp import Address
from netlib.tutils import raises
from pathod import pathoc, pathod
-from mitmproxy.builtins import script
-from mitmproxy import controller
-from mitmproxy.proxy.config import HostMatcher, parse_server_spec
-from mitmproxy.models import Error, HTTPResponse, HTTPFlow
-
from . import tutils, tservers
"""
@@ -350,6 +349,15 @@ class TestHTTPSCertfile(tservers.HTTPProxyTest, CommonMixin):
assert self.pathod("304")
+class TestHTTPSSecureByDefault:
+ def test_secure_by_default(self):
+ """
+ Certificate verification should be turned on by default.
+ """
+ default_opts = options.Options()
+ assert not default_opts.ssl_insecure
+
+
class TestHTTPSUpstreamServerVerificationWTrustedCert(tservers.HTTPProxyTest):
"""
@@ -357,26 +365,35 @@ class TestHTTPSUpstreamServerVerificationWTrustedCert(tservers.HTTPProxyTest):
"""
ssl = True
ssloptions = pathod.SSLOptions(
- cn=b"trusted-cert",
+ cn=b"example.mitmproxy.org",
certs=[
- ("trusted-cert", tutils.test_data.path("data/trusted-server.crt"))
- ])
+ ("example.mitmproxy.org", tutils.test_data.path("data/servercert/trusted-leaf.pem"))
+ ]
+ )
+
+ def _request(self):
+ p = self.pathoc(sni="example.mitmproxy.org")
+ return p.request("get:/p/242")
def test_verification_w_cadir(self):
self.config.options.update(
- ssl_verify_upstream_cert = True,
- ssl_verify_upstream_trusted_cadir = tutils.test_data.path(
- "data/trusted-cadir/"
- )
+ ssl_insecure=False,
+ ssl_verify_upstream_trusted_cadir=tutils.test_data.path(
+ "data/servercert/"
+ ),
+ ssl_verify_upstream_trusted_ca=None,
)
- self.pathoc()
+ assert self._request().status_code == 242
def test_verification_w_pemfile(self):
- self.config.openssl_verification_mode_server = SSL.VERIFY_PEER
- self.config.options.ssl_verify_upstream_trusted_ca = tutils.test_data.path(
- "data/trusted-cadir/trusted-ca.pem")
-
- self.pathoc()
+ self.config.options.update(
+ ssl_insecure=False,
+ ssl_verify_upstream_trusted_cadir=None,
+ ssl_verify_upstream_trusted_ca=tutils.test_data.path(
+ "data/servercert/trusted-root.pem"
+ ),
+ )
+ assert self._request().status_code == 242
class TestHTTPSUpstreamServerVerificationWBadCert(tservers.HTTPProxyTest):
@@ -386,42 +403,36 @@ class TestHTTPSUpstreamServerVerificationWBadCert(tservers.HTTPProxyTest):
"""
ssl = True
ssloptions = pathod.SSLOptions(
- cn=b"untrusted-cert",
+ cn=b"example.mitmproxy.org",
certs=[
- ("untrusted-cert", tutils.test_data.path("data/untrusted-server.crt"))
+ ("example.mitmproxy.org", tutils.test_data.path("data/servercert/self-signed.pem"))
])
def _request(self):
- p = self.pathoc()
- # We need to make an actual request because the upstream connection is lazy-loaded.
+ p = self.pathoc(sni="example.mitmproxy.org")
return p.request("get:/p/242")
- def test_default_verification_w_bad_cert(self):
- """Should use no verification."""
- self.config.options.update(
- ssl_verify_upstream_trusted_ca = tutils.test_data.path(
- "data/trusted-cadir/trusted-ca.pem"
- )
+ @classmethod
+ def get_options(cls):
+ opts = super(tservers.HTTPProxyTest, cls).get_options()
+ opts.ssl_verify_upstream_trusted_ca = tutils.test_data.path(
+ "data/servercert/trusted-root.pem"
)
- assert self._request().status_code == 242
+ return opts
def test_no_verification_w_bad_cert(self):
- self.config.options.update(
- ssl_verify_upstream_cert = False,
- ssl_verify_upstream_trusted_ca = tutils.test_data.path(
- "data/trusted-cadir/trusted-ca.pem"
- )
- )
- assert self._request().status_code == 242
+ self.config.options.ssl_insecure = True
+ r = self._request()
+ assert r.status_code == 242
def test_verification_w_bad_cert(self):
- self.config.options.update(
- ssl_verify_upstream_cert = True,
- ssl_verify_upstream_trusted_ca = tutils.test_data.path(
- "data/trusted-cadir/trusted-ca.pem"
- )
- )
- assert self._request().status_code == 502
+ # We only test for a single invalid cert here.
+ # Actual testing of different root-causes (invalid hostname, expired, ...)
+ # is done in netlib.
+ self.config.options.ssl_insecure = False
+ r = self._request()
+ assert r.status_code == 502
+ assert b"Certificate Verification Error" in r.raw_content
class TestHTTPSNoCommonName(tservers.HTTPProxyTest):
@@ -1021,11 +1032,11 @@ class TestProxyChainingSSLReconnect(tservers.HTTPUpstreamProxyTest):
class AddUpstreamCertsToClientChainMixin:
ssl = True
- servercert = tutils.test_data.path("data/trusted-server.crt")
+ servercert = tutils.test_data.path("data/servercert/trusted-root.pem")
ssloptions = pathod.SSLOptions(
- cn=b"trusted-cert",
+ cn=b"example.mitmproxy.org",
certs=[
- (b"trusted-cert", servercert)
+ (b"example.mitmproxy.org", servercert)
]
)
diff --git a/test/mitmproxy/tservers.py b/test/mitmproxy/tservers.py
index d364162c..1597f59c 100644
--- a/test/mitmproxy/tservers.py
+++ b/test/mitmproxy/tservers.py
@@ -120,7 +120,8 @@ class ProxyTestBase(object):
return options.Options(
listen_port=0,
cadir=cls.cadir,
- add_upstream_certs_to_client_chain=cls.add_upstream_certs_to_client_chain
+ add_upstream_certs_to_client_chain=cls.add_upstream_certs_to_client_chain,
+ ssl_insecure=True,
)
diff --git a/test/netlib/test_tcp.py b/test/netlib/test_tcp.py
index 273427d5..dc2f4e7e 100644
--- a/test/netlib/test_tcp.py
+++ b/test/netlib/test_tcp.py
@@ -213,7 +213,7 @@ class TestSSLUpstreamCertVerificationWBadServerCert(tservers.ServerTestBase):
# Verification errors should be saved even if connection isn't aborted
# aborted
- assert c.ssl_verification_error is not None
+ assert c.ssl_verification_error
testval = b"echo!\n"
c.wfile.write(testval)
@@ -226,7 +226,7 @@ class TestSSLUpstreamCertVerificationWBadServerCert(tservers.ServerTestBase):
c.convert_to_ssl(verify_options=SSL.VERIFY_NONE)
# Verification errors should be saved even if connection isn't aborted
- assert c.ssl_verification_error is not None
+ assert c.ssl_verification_error
testval = b"echo!\n"
c.wfile.write(testval)
@@ -243,11 +243,11 @@ class TestSSLUpstreamCertVerificationWBadServerCert(tservers.ServerTestBase):
ca_pemfile=tutils.test_data.path("data/verificationcerts/trusted-root.crt")
)
- assert c.ssl_verification_error is not None
+ assert c.ssl_verification_error
# Unknown issuing certificate authority for first certificate
- assert c.ssl_verification_error['errno'] == 18
- assert c.ssl_verification_error['depth'] == 0
+ assert "errno: 18" in str(c.ssl_verification_error)
+ assert "depth: 0" in str(c.ssl_verification_error)
class TestSSLUpstreamCertVerificationWBadHostname(tservers.ServerTestBase):
@@ -276,7 +276,7 @@ class TestSSLUpstreamCertVerificationWBadHostname(tservers.ServerTestBase):
verify_options=SSL.VERIFY_PEER,
ca_pemfile=tutils.test_data.path("data/verificationcerts/trusted-root.crt")
)
- assert c.ssl_verification_error is not None
+ assert c.ssl_verification_error
class TestSSLUpstreamCertVerificationWValidCertChain(tservers.ServerTestBase):