From 81a274eb51ea7552667a872f0b6db1aeca9315b3 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Fri, 27 Feb 2015 09:17:41 +0100 Subject: [PATCH] fix #479 --- libmproxy/proxy/server.py | 7 ++++++- test/test_server.py | 31 +++++++++++++++++++++++++++++++ test/tservers.py | 4 ++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py index ea78d964b..4e5760679 100644 --- a/libmproxy/proxy/server.py +++ b/libmproxy/proxy/server.py @@ -285,7 +285,12 @@ class ConnectionHandler: if sni != self.server_conn.sni: self.log("SNI received: %s" % sni, "debug") - self.server_reconnect(sni) # reconnect to upstream server with SNI + # We should only re-establish upstream SSL if one of the following conditions is true: + # - We established SSL with the server previously + # - We initially wanted to establish SSL with the server, + # but the server refused to negotiate without SNI. + if self.server_conn.ssl_established or hasattr(self.server_conn, "may_require_sni"): + self.server_reconnect(sni) # reconnect to upstream server with SNI # Now, change client context to reflect changed certificate: cert, key, chain_file = self.find_cert() new_context = self.client_conn._create_ssl_context( diff --git a/test/test_server.py b/test/test_server.py index a611d30f3..e387293fe 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -1,5 +1,6 @@ import socket, time from libmproxy.proxy.config import HostMatcher +import libpathod from netlib import tcp, http_auth, http from libpathod import pathoc, pathod from netlib.certutils import SSLCert @@ -332,6 +333,36 @@ class TestReverse(tservers.ReverseProxTest, CommonMixin, TcpMixin): reverse = True +class TestHttps2Http(tservers.ReverseProxTest): + @classmethod + def get_proxy_config(cls): + d = super(TestHttps2Http, cls).get_proxy_config() + d["upstream_server"][0] = True + return d + + def pathoc(self, ssl, sni=None): + """ + Returns a connected Pathoc instance. + """ + p = libpathod.pathoc.Pathoc(("localhost", self.proxy.port), ssl=ssl, sni=sni) + p.connect() + return p + + def test_all(self): + p = self.pathoc(ssl=True) + assert p.request("get:'/p/200'").status_code == 200 + + def test_sni(self): + p = self.pathoc(ssl=True, sni="example.com") + assert p.request("get:'/p/200'").status_code == 200 + assert all("Error in handle_sni" not in msg for msg in self.proxy.log) + + def test_http(self): + p = self.pathoc(ssl=False) + assert p.request("get:'/p/200'").status_code == 400 + + + class TestTransparent(tservers.TransparentProxTest, CommonMixin, TcpMixin): ssl = False diff --git a/test/tservers.py b/test/tservers.py index 37929d1ab..30c8b52e3 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -218,12 +218,12 @@ class ReverseProxTest(ProxTestBase): @classmethod def get_proxy_config(cls): d = ProxTestBase.get_proxy_config() - d["upstream_server"] = ( + d["upstream_server"] = [ True if cls.ssl else False, True if cls.ssl else False, "127.0.0.1", cls.server.port - ) + ] d["mode"] = "reverse" return d