diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py index c9ceb8de5..54cb6f8ef 100644 --- a/libmproxy/proxy.py +++ b/libmproxy/proxy.py @@ -126,7 +126,7 @@ class HandleSNI: self.handler.sni = sn.decode("utf8").encode("idna") # An unhandled exception in this method will core dump PyOpenSSL, so # make dang sure it doesn't happen. - except Exception, e: + except Exception, e: # pragma: no cover pass @@ -141,6 +141,8 @@ class ProxyHandler(tcp.BaseHandler): def get_server_connection(self, cc, scheme, host, port, sni): sc = self.server_conn + if not sni: + sni = host if sc and (scheme, host, port, sni) != (sc.scheme, sc.host, sc.port, sc.sni): sc.terminate() self.server_conn = None @@ -214,7 +216,7 @@ class ProxyHandler(tcp.BaseHandler): # the case, we want to reconnect without sending an error # to the client. while 1: - sc = self.get_server_connection(cc, scheme, host, port, host) + sc = self.get_server_connection(cc, scheme, host, port, self.sni) sc.send(request) sc.rfile.reset_timestamps() try: @@ -362,14 +364,13 @@ class ProxyHandler(tcp.BaseHandler): '\r\n' ) self.wfile.flush() - certfile = self.find_cert(client_conn, host, port, host) - - sni = HandleSNI( - self, client_conn, host, port, - dummycert, self.config.certfile or self.config.cacert - ) + dummycert = self.find_cert(client_conn, host, port, host) try: - self.convert_to_ssl(certfile, self.config.certfile or self.config.cacert, handle_sni=sni) + sni = HandleSNI( + self, client_conn, host, port, + dummycert, self.config.certfile or self.config.cacert + ) + self.convert_to_ssl(dummycert, self.config.certfile or self.config.cacert, handle_sni=sni) except tcp.NetLibError, v: raise ProxyError(400, str(v)) self.proxy_connect_state = (host, port, httpversion) diff --git a/test/test_server.py b/test/test_server.py index 466c0f946..244f972f1 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -131,10 +131,14 @@ class TestHTTPS(tservers.HTTPProxTest, CommonMixin): clientcerts = True def test_clientcert(self): f = self.pathod("304") + assert f.status_code == 304 assert self.server.last_log()["request"]["clientcert"]["keyinfo"] def test_sni(self): - pass + f = self.pathod("304", sni="testserver.com") + assert f.status_code == 304 + l = self.server.last_log() + assert self.server.last_log()["request"]["sni"] == "testserver.com" class TestHTTPSCertfile(tservers.HTTPProxTest, CommonMixin): diff --git a/test/tservers.py b/test/tservers.py index c8bc7100e..d1878f7af 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -28,7 +28,7 @@ class TestMaster(flow.FlowMaster): state = flow.State() flow.FlowMaster.__init__(self, s, state) self.testq = testq - self.log = [] + self.clear_log() def handle_request(self, m): flow.FlowMaster.handle_request(self, m) @@ -38,6 +38,9 @@ class TestMaster(flow.FlowMaster): flow.FlowMaster.handle_response(self, m) m.reply() + def clear_log(self): + self.log = [] + def handle_log(self, l): self.log.append(l.msg) l.reply() @@ -96,7 +99,10 @@ class ProxTestBase: cls.server2.shutdown() def setUp(self): + self.master.clear_log() self.master.state.clear() + self.server.clear_log() + self.server2.clear_log() @property def scheme(self): @@ -122,20 +128,20 @@ class ProxTestBase: class HTTPProxTest(ProxTestBase): - def pathoc(self, connect_to = None): + def pathoc(self, connect_to = None, sni=None): """ Returns a connected Pathoc instance. """ - p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl) + p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl, sni=sni) p.connect(connect_to) return p - def pathod(self, spec): + def pathod(self, spec, sni=None): """ Constructs a pathod GET request, with the appropriate base and proxy. """ if self.ssl: - p = self.pathoc(("127.0.0.1", self.server.port)) + p = self.pathoc(("127.0.0.1", self.server.port), sni=sni) q = "get:'/p/%s'"%spec else: p = self.pathoc()