diff options
| -rw-r--r-- | libmproxy/protocol/http.py | 17 | ||||
| -rw-r--r-- | libmproxy/proxy/connection.py | 2 | ||||
| -rw-r--r-- | test/test_protocol_http.py | 6 | ||||
| -rw-r--r-- | test/tutils.py | 2 | 
4 files changed, 24 insertions, 3 deletions
diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py index e4f994c9..7c4d9cbb 100644 --- a/libmproxy/protocol/http.py +++ b/libmproxy/protocol/http.py @@ -461,7 +461,12 @@ class HTTPRequest(HTTPMessage):              if self.host:                  host = self.host              else: -                host = self.flow.server_conn.address.host +                for s in self.flow.server_conn.state: +                    if s[0] == "http" and s[1].get("state") == "connect": +                        host = s[1]["host"] +                        break +                if not host: +                    host = self.flow.server_conn.address.host          host = host.encode("idna")          return host @@ -479,6 +484,9 @@ class HTTPRequest(HTTPMessage):          """          if self.port:              return self.port +        for s in self.flow.server_conn.state: +            if s[0] == "http" and s[1].get("state") == "connect": +                return s[1]["port"]          return self.flow.server_conn.address.port      def get_url(self, hostheader=False): @@ -974,11 +982,16 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin):                      return False              if flow.request.form_in == "authority" and flow.response.code == 200: -                self.ssl_upgrade()                  # TODO: Eventually add headers (space/usefulness tradeoff) +                # Make sure to add state info before the actual upgrade happens. +                # During the upgrade, we may receive an SNI indication from the client, +                # which resets the upstream connection. If this is the case, we must +                # already re-issue the CONNECT request at this point.                  self.c.server_conn.state.append(("http", {"state": "connect",                                                            "host": flow.request.host,                                                            "port": flow.request.port})) +                self.ssl_upgrade() +              # If the user has changed the target server on this connection,              # restore the original target server diff --git a/libmproxy/proxy/connection.py b/libmproxy/proxy/connection.py index 38436233..a19e3e71 100644 --- a/libmproxy/proxy/connection.py +++ b/libmproxy/proxy/connection.py @@ -138,7 +138,7 @@ class ServerConnection(tcp.TCPClient, stateobject.SimpleStateObject):              self.convert_to_ssl(cert=clientcert, sni=sni)              self.timestamp_ssl_setup = utils.timestamp()          except tcp.NetLibError, v: -            raise ProxyError(400, str(v)) +            raise ProxyError(400, repr(v))      def finish(self):          tcp.TCPClient.finish(self) diff --git a/test/test_protocol_http.py b/test/test_protocol_http.py index 451b7b5d..3b922c06 100644 --- a/test/test_protocol_http.py +++ b/test/test_protocol_http.py @@ -141,6 +141,12 @@ class TestProxyChainingSSL(tservers.HTTPChainProxyTest):          finally:              self.chain[0].tmaster.handle_request = _handle_request +    def test_sni(self): +        p = self.pathoc(sni="foo.com") +        req = p.request("get:'/p/418:b\"content\"'") +        assert req.content == "content" +        assert req.status_code == 418 +  class TestProxyChainingSSLReconnect(tservers.HTTPChainProxyTest):      ssl = True diff --git a/test/tutils.py b/test/tutils.py index c527a64a..dc049adb 100644 --- a/test/tutils.py +++ b/test/tutils.py @@ -33,6 +33,7 @@ def tclient_conn():  def tserver_conn():      c = ServerConnection._from_state(dict(          address=dict(address=("address", 22), use_ipv6=True), +        state=[],          source_address=dict(address=("address", 22), use_ipv6=True),          cert=None      )) @@ -72,6 +73,7 @@ def tresp(req=None, content="message"):      cert = certutils.SSLCert.from_der(file(test_data.path("data/dercert"), "rb").read())      f.server_conn = ServerConnection._from_state(dict(          address=dict(address=("address", 22), use_ipv6=True), +        state=[],          source_address=None,          cert=cert.to_pem()))      f.response = http.HTTPResponse((1, 1), 200, "OK", headers, content, time(), time())  | 
