diff --git a/libmproxy/exceptions.py b/libmproxy/exceptions.py index 7d80ce31b..0e11c136d 100644 --- a/libmproxy/exceptions.py +++ b/libmproxy/exceptions.py @@ -16,13 +16,11 @@ class ProxyException(Exception): message: the error message cause: (optional) an error object that caused this exception, e.g. an IOError. """ - def __init__(self, message, cause=None): + def __init__(self, message): """ :param message: Error Message - :param cause: Exception object that caused this exception to be thrown. """ super(ProxyException, self).__init__(message) - self.cause = cause class ProtocolException(ProxyException): @@ -34,8 +32,9 @@ class TlsException(ProtocolException): class ClientHandshakeException(TlsException): - # This subclass is quite useful to give hints about cert errors. - pass + def __init__(self, message, server): + super(ClientHandshakeException, self).__init__(message) + self.server = server class Socks5Exception(ProtocolException): diff --git a/libmproxy/protocol/base.py b/libmproxy/protocol/base.py index 6793d3df3..b92aeea15 100644 --- a/libmproxy/protocol/base.py +++ b/libmproxy/protocol/base.py @@ -1,6 +1,8 @@ from __future__ import (absolute_import, print_function, division) -import six import sys + +import six + from netlib import tcp from ..models import ServerConnection from ..exceptions import ProtocolException @@ -176,8 +178,11 @@ class ServerConnectionMixin(object): except tcp.NetLibError as e: six.reraise( ProtocolException, - ProtocolException("Server connection to %s failed: %s" % - (repr(self.server_conn.address), e), e), + ProtocolException( + "Server connection to {} failed: {}".format( + repr(self.server_conn.address), str(e) + ) + ), sys.exc_info()[2] ) diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py index 636b72f4a..3a4153201 100644 --- a/libmproxy/protocol/http.py +++ b/libmproxy/protocol/http.py @@ -397,7 +397,7 @@ class HttpLayer(Layer): if isinstance(e, ProtocolException): six.reraise(ProtocolException, e, sys.exc_info()[2]) else: - six.reraise(ProtocolException, ProtocolException("Error in HTTP connection: %s" % repr(e), e), sys.exc_info()[2]) + six.reraise(ProtocolException, ProtocolException("Error in HTTP connection: %s" % repr(e)), sys.exc_info()[2]) finally: flow.live = False diff --git a/libmproxy/protocol/rawtcp.py b/libmproxy/protocol/rawtcp.py index 8a597a15a..9b155412a 100644 --- a/libmproxy/protocol/rawtcp.py +++ b/libmproxy/protocol/rawtcp.py @@ -67,6 +67,6 @@ class RawTCPLayer(Layer): except (socket.error, NetLibError, SSL.Error) as e: six.reraise( ProtocolException, - ProtocolException("TCP connection closed unexpectedly: {}".format(repr(e)), e), + ProtocolException("TCP connection closed unexpectedly: {}".format(repr(e))), sys.exc_info()[2] ) diff --git a/libmproxy/protocol/tls.py b/libmproxy/protocol/tls.py index 1164681cb..4f7c9300a 100644 --- a/libmproxy/protocol/tls.py +++ b/libmproxy/protocol/tls.py @@ -416,7 +416,12 @@ class TlsLayer(Layer): except NetLibError as e: six.reraise( ClientHandshakeException, - ClientHandshakeException("Cannot establish TLS with client: %s" % repr(e), e), + ClientHandshakeException( + "Cannot establish TLS with client (sni: {sni}): {e}".format( + sni=self.client_sni, e=repr(e) + ), + self.client_sni or repr(self.server_conn.address) + ), sys.exc_info()[2] ) @@ -473,7 +478,7 @@ class TlsLayer(Layer): address=repr(self.server_conn.address), sni=self.sni_for_server_connection, e=repr(e), - ), e), + )), sys.exc_info()[2] ) except NetLibError as e: @@ -483,7 +488,7 @@ class TlsLayer(Layer): address=repr(self.server_conn.address), sni=self.sni_for_server_connection, e=repr(e), - ), e), + )), sys.exc_info()[2] ) diff --git a/libmproxy/proxy/modes/socks_proxy.py b/libmproxy/proxy/modes/socks_proxy.py index 0efeab673..545c38d65 100644 --- a/libmproxy/proxy/modes/socks_proxy.py +++ b/libmproxy/proxy/modes/socks_proxy.py @@ -48,7 +48,7 @@ class Socks5Proxy(Layer, ServerConnectionMixin): self.client_conn.wfile.flush() except (socks.SocksError, NetLibError) as e: - raise Socks5Exception("SOCKS5 mode failure: %s" % repr(e), e) + raise Socks5Exception("SOCKS5 mode failure: %s" % repr(e)) self.server_conn.address = connect_request.addr diff --git a/libmproxy/proxy/modes/transparent_proxy.py b/libmproxy/proxy/modes/transparent_proxy.py index d99485c98..da1d46326 100644 --- a/libmproxy/proxy/modes/transparent_proxy.py +++ b/libmproxy/proxy/modes/transparent_proxy.py @@ -14,7 +14,7 @@ class TransparentProxy(Layer, ServerConnectionMixin): try: self.server_conn.address = self.resolver.original_addr(self.client_conn.connection) except Exception as e: - raise ProtocolException("Transparent mode failure: %s" % repr(e), e) + raise ProtocolException("Transparent mode failure: %s" % repr(e)) layer = self.ctx.next_layer(self) try: diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py index c00bb815a..88448172a 100644 --- a/libmproxy/proxy/server.py +++ b/libmproxy/proxy/server.py @@ -8,7 +8,7 @@ import six from netlib import tcp from netlib.http.http1 import HTTP1Protocol from netlib.tcp import NetLibError -from ..exceptions import ProtocolException, ServerException +from ..exceptions import ProtocolException, ServerException, ClientHandshakeException from ..protocol import Kill from ..models import ClientConnection, make_error_response from .modes import HttpUpstreamProxy, HttpProxy, ReverseProxy, TransparentProxy, Socks5Proxy @@ -42,7 +42,7 @@ class ProxyServer(tcp.TCPServer): except socket.error as e: six.reraise( ServerException, - ServerException('Error starting proxy server: ' + repr(e), e), + ServerException('Error starting proxy server: ' + repr(e)), sys.exc_info()[2] ) self.channel = None @@ -121,8 +121,18 @@ class ConnectionHandler(object): except Kill: self.log("Connection killed", "info") except ProtocolException as e: - self.log(repr(e), "info") - self.log(traceback.format_exc(), "debug") + + if isinstance(e, ClientHandshakeException): + self.log( + "Client Handshake failed. " + "The client may not trust the proxy's certificate for {}.".format(e.server), + "error" + ) + self.log(repr(e), "debug") + else: + self.log(repr(e), "error") + + self.log(traceback.format_exc(), "debug") # If an error propagates to the topmost level, # we send an HTTP error response, which is both # understandable by HTTP clients and humans.