Merge branch 'master' of github.com:mitmproxy/mitmproxy

This commit is contained in:
Maximilian Hils 2014-03-11 02:16:30 +01:00
commit 14db30080f
4 changed files with 44 additions and 23 deletions

View File

@ -13,7 +13,7 @@ class ProxyConfig:
def __init__(self, confdir=CONF_DIR, clientcerts=None, def __init__(self, confdir=CONF_DIR, clientcerts=None,
no_upstream_cert=False, body_size_limit=None, get_upstream_server=None, no_upstream_cert=False, body_size_limit=None, get_upstream_server=None,
http_form_in="absolute", http_form_out="relative", authenticator=None, http_form_in="absolute", http_form_out="relative", authenticator=None,
ciphers=None, certs=None ciphers=None, certs=None, certforward = False
): ):
self.ciphers = ciphers self.ciphers = ciphers
self.clientcerts = clientcerts self.clientcerts = clientcerts
@ -25,6 +25,7 @@ class ProxyConfig:
self.authenticator = authenticator self.authenticator = authenticator
self.confdir = os.path.expanduser(confdir) self.confdir = os.path.expanduser(confdir)
self.certstore = certutils.CertStore.from_store(self.confdir, CONF_BASENAME) self.certstore = certutils.CertStore.from_store(self.confdir, CONF_BASENAME)
self.certforward = certforward
def process_proxy_options(parser, options): def process_proxy_options(parser, options):
@ -93,15 +94,17 @@ def process_proxy_options(parser, options):
certs.append(parts) certs.append(parts)
return ProxyConfig( return ProxyConfig(
clientcerts=options.clientcerts, clientcerts = options.clientcerts,
body_size_limit=body_size_limit, body_size_limit = body_size_limit,
no_upstream_cert=options.no_upstream_cert, no_upstream_cert = options.no_upstream_cert,
get_upstream_server=get_upstream_server, get_upstream_server = get_upstream_server,
http_form_in=http_form_in, confdir = options.confdir,
http_form_out=http_form_out, http_form_in = http_form_in,
authenticator=authenticator, http_form_out = http_form_out,
ciphers=options.ciphers, authenticator = authenticator,
ciphers = options.ciphers,
certs = certs, certs = certs,
certforward = options.certforward,
) )
@ -124,4 +127,9 @@ def ssl_option_group(parser):
"--ciphers", action="store", "--ciphers", action="store",
type=str, dest="ciphers", default=None, type=str, dest="ciphers", default=None,
help="SSL cipher specification." help="SSL cipher specification."
) )
group.add_argument(
"--cert-forward", action="store_true",
dest="certforward", default=False,
help="Simply forward SSL certificates from upstream."
)

View File

@ -190,7 +190,8 @@ class ConnectionHandler:
self.client_conn.convert_to_ssl( self.client_conn.convert_to_ssl(
cert, key, cert, key,
handle_sni = self.handle_sni, handle_sni = self.handle_sni,
cipher_list = self.config.ciphers cipher_list = self.config.ciphers,
dhparams = self.config.certstore.dhparams
) )
def server_reconnect(self, no_ssl=False): def server_reconnect(self, no_ssl=False):
@ -219,18 +220,21 @@ class ConnectionHandler:
self.channel.tell("log", Log(msg)) self.channel.tell("log", Log(msg))
def find_cert(self): def find_cert(self):
host = self.server_conn.address.host if self.config.certforward and self.server_conn.ssl_established:
sans = [] return self.server_conn.cert, self.config.certstore.gen_pkey(self.server_conn.cert)
if not self.config.no_upstream_cert or not self.server_conn.ssl_established: else:
upstream_cert = self.server_conn.cert host = self.server_conn.address.host
if upstream_cert.cn: sans = []
host = upstream_cert.cn.decode("utf8").encode("idna") if not self.config.no_upstream_cert or not self.server_conn.ssl_established:
sans = upstream_cert.altnames upstream_cert = self.server_conn.cert
if upstream_cert.cn:
host = upstream_cert.cn.decode("utf8").encode("idna")
sans = upstream_cert.altnames
ret = self.config.certstore.get_cert(host, sans) ret = self.config.certstore.get_cert(host, sans)
if not ret: if not ret:
raise ProxyError(502, "Unable to generate dummy cert.") raise ProxyError(502, "Unable to generate dummy cert.")
return ret return ret
def handle_sni(self, connection): def handle_sni(self, connection):
""" """
@ -253,4 +257,4 @@ class ConnectionHandler:
# An unhandled exception in this method will core dump PyOpenSSL, so # An unhandled exception in this method will core dump PyOpenSSL, so
# make dang sure it doesn't happen. # make dang sure it doesn't happen.
except Exception, e: # pragma: no cover except Exception, e: # pragma: no cover
pass pass

View File

@ -446,3 +446,10 @@ class TestIncompleteResponse(tservers.HTTPProxTest):
def test_incomplete(self): def test_incomplete(self):
assert self.pathod("200").status_code == 502 assert self.pathod("200").status_code == 502
class TestCertForward(tservers.HTTPProxTest):
certforward = True
ssl = True
def test_app_err(self):
tutils.raises("handshake error", self.pathod, "200:b@100")

View File

@ -81,6 +81,7 @@ class ProxTestBase(object):
authenticator = None authenticator = None
masterclass = TestMaster masterclass = TestMaster
externalapp = False externalapp = False
certforward = False
@classmethod @classmethod
def setupAll(cls): def setupAll(cls):
cls.server = libpathod.test.Daemon(ssl=cls.ssl, ssloptions=cls.ssloptions) cls.server = libpathod.test.Daemon(ssl=cls.ssl, ssloptions=cls.ssloptions)
@ -91,6 +92,7 @@ class ProxTestBase(object):
no_upstream_cert = cls.no_upstream_cert, no_upstream_cert = cls.no_upstream_cert,
confdir = cls.confdir, confdir = cls.confdir,
authenticator = cls.authenticator, authenticator = cls.authenticator,
certforward = cls.certforward,
**pconf **pconf
) )
tmaster = cls.masterclass(config) tmaster = cls.masterclass(config)