Repository: mitmproxy/mitmproxy

Issue:
Empty `--upstream-trusted-ca` file crashes mitmproxy.
##### Steps to reproduce the problem:

1. `touch foo`
2. `mitmdump --upstream-trusted-ca foo`
3. `curl -x localhost:8080 https://example.com/`
```
127.0.0.1:61162: clientconnect
127.0.0.1:61162: Traceback (most recent call last):
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/server.py", line 115, in handle
    root_layer()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/modes/http_proxy.py", line 9, in __call__
    layer()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/tls.py", line 379, in __call__
    layer()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/http1.py", line 72, in __call__
    layer()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/http.py", line 177, in __call__
    if not self._process_flow(flow):
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/http.py", line 246, in _process_flow
    return self.handle_regular_connect(f)
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/http.py", line 204, in handle_regular_connect
    layer()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/tls.py", line 372, in __call__
    self._establish_tls_with_client_and_server()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/tls.py", line 448, in _establish_tls_with_client_and_server
    self._establish_tls_with_server()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/tls.py", line 534, in _establish_tls_with_server
    alpn_protos=alpn,
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/connections.py", line 229, in establish_ssl
    self.convert_to_ssl(cert=clientcert, sni=sni, **kwargs)
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/net/tcp.py", line 688, in convert_to_ssl
    **sslctx_kwargs
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/net/tcp.py", line 662, in create_ssl_context
    **sslctx_kwargs)
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/net/tcp.py", line 554, in _create_ssl_context
    context.load_verify_locations(ca_pemfile, ca_path)
  File "/usr/local/lib/python3.5/dist-packages/OpenSSL/SSL.py", line 525, in load_verify_locations
    _raise_current_error()
  File "/usr/local/lib/python3.5/dist-packages/OpenSSL/_util.py", line 48, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.SSL.Error: []
```


##### System information

Mitmproxy version: 0.19
Python version: 3.5.2
Platform: Linux-3.4.0+-x86_64-with-Ubuntu-14.04-trusty
SSL version: OpenSSL 1.0.2g-fips  1 Mar 2016
Linux distro: Ubuntu 14.04 trusty
Empty `--upstream-trusted-ca` file crashes mitmproxy.
##### Steps to reproduce the problem:

1. `touch foo`
2. `mitmdump --upstream-trusted-ca foo`
3. `curl -x localhost:8080 https://example.com/`
```
127.0.0.1:61162: clientconnect
127.0.0.1:61162: Traceback (most recent call last):
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/server.py", line 115, in handle
    root_layer()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/modes/http_proxy.py", line 9, in __call__
    layer()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/tls.py", line 379, in __call__
    layer()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/http1.py", line 72, in __call__
    layer()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/http.py", line 177, in __call__
    if not self._process_flow(flow):
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/http.py", line 246, in _process_flow
    return self.handle_regular_connect(f)
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/http.py", line 204, in handle_regular_connect
    layer()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/tls.py", line 372, in __call__
    self._establish_tls_with_client_and_server()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/tls.py", line 448, in _establish_tls_with_client_and_server
    self._establish_tls_with_server()
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/proxy/protocol/tls.py", line 534, in _establish_tls_with_server
    alpn_protos=alpn,
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/connections.py", line 229, in establish_ssl
    self.convert_to_ssl(cert=clientcert, sni=sni, **kwargs)
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/net/tcp.py", line 688, in convert_to_ssl
    **sslctx_kwargs
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/net/tcp.py", line 662, in create_ssl_context
    **sslctx_kwargs)
  File "/mnt/c/Users/user/git/mitmproxy/mitmproxy/net/tcp.py", line 554, in _create_ssl_context
    context.load_verify_locations(ca_pemfile, ca_path)
  File "/usr/local/lib/python3.5/dist-packages/OpenSSL/SSL.py", line 525, in load_verify_locations
    _raise_current_error()
  File "/usr/local/lib/python3.5/dist-packages/OpenSSL/_util.py", line 48, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.SSL.Error: []
```


##### System information

Mitmproxy version: 0.19
Python version: 3.5.2
Platform: Linux-3.4.0+-x86_64-with-Ubuntu-14.04-trusty
SSL version: OpenSSL 1.0.2g-fips  1 Mar 2016
Linux distro: Ubuntu 14.04 trusty


Discussion:

Resolving patch:
diff --git a/mitmproxy/net/tcp.py b/mitmproxy/net/tcp.py
--- a/mitmproxy/net/tcp.py
+++ b/mitmproxy/net/tcp.py
@@ -551,7 +551,14 @@ def verify_cert(conn, x509, errno, err_depth, is_cert_verified):
             context.set_verify(verify_options, verify_cert)
             if ca_path is None and ca_pemfile is None:
                 ca_pemfile = certifi.where()
-            context.load_verify_locations(ca_pemfile, ca_path)
+            try:
+                context.load_verify_locations(ca_pemfile, ca_path)
+            except SSL.Error:
+                raise exceptions.TlsException(
+                    "Cannot load trusted certificates ({}, {}).".format(
+                        ca_pemfile, ca_path
+                    )
+                )
 
         # Workaround for
         # https://github.com/pyca/pyopenssl/issues/190


Test patch:
diff --git a/test/mitmproxy/net/test_tcp.py b/test/mitmproxy/net/test_tcp.py
--- a/test/mitmproxy/net/test_tcp.py
+++ b/test/mitmproxy/net/test_tcp.py
@@ -199,6 +199,18 @@ def test_failure(self):
             tutils.raises(exceptions.TlsException, c.convert_to_ssl, sni="foo.com")
 
 
+class TestInvalidTrustFile(tservers.ServerTestBase):
+    def test_invalid_trust_file_should_fail(self):
+        c = tcp.TCPClient(("127.0.0.1", self.port))
+        with c.connect():
+            with tutils.raises(exceptions.TlsException):
+                c.convert_to_ssl(
+                    sni="example.mitmproxy.org",
+                    verify_options=SSL.VERIFY_PEER,
+                    ca_pemfile=tutils.test_data.path("mitmproxy/net/data/verificationcerts/generate.py")
+                )
+
+
 class TestSSLUpstreamCertVerificationWBadServerCert(tservers.ServerTestBase):
     handler = EchoHandler