From: Ben Darnell Date: Mon, 20 Feb 2012 03:33:08 +0000 (-0800) Subject: Pass parsed hostname around explictly instead of storing it on the urlsplit result. X-Git-Tag: v2.3.0~93 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=56ec1ee597f91fb59ec660dfe7a4fdd68f2209eb;p=thirdparty%2Ftornado.git Pass parsed hostname around explictly instead of storing it on the urlsplit result. In some versions of python (including 2.5 and 3.2 but not 2.6 or 2.7), urlsplit results use __slots__ and therefore don't allow artibrary attributes to be set. Also move the storing of the parsed hostname above hostname_mapping, since the cert should be checked against the requested url, not the remapped one. Closes #448. --- diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py index 9617472bc..aa2bec637 100644 --- a/tornado/simple_httpclient.py +++ b/tornado/simple_httpclient.py @@ -160,9 +160,9 @@ class _HTTPConnection(object): if re.match(r'^\[.*\]$', host): # raw ipv6 addresses in urls are enclosed in brackets host = host[1:-1] + parsed_hostname = host # save final parsed host for _on_connect if self.client.hostname_mapping is not None: host = self.client.hostname_mapping.get(host, host) - parsed._hostname = host # save correct hostname for _on_connect if request.allow_ipv6: af = socket.AF_UNSPEC @@ -222,7 +222,8 @@ class _HTTPConnection(object): self._on_timeout) self.stream.set_close_callback(self._on_close) self.stream.connect(sockaddr, - functools.partial(self._on_connect, parsed)) + functools.partial(self._on_connect, parsed, + parsed_hostname)) def _on_timeout(self): self._timeout = None @@ -231,7 +232,7 @@ class _HTTPConnection(object): error=HTTPError(599, "Timeout"))) self.stream.close() - def _on_connect(self, parsed): + def _on_connect(self, parsed, parsed_hostname): if self._timeout is not None: self.io_loop.remove_timeout(self._timeout) self._timeout = None @@ -242,9 +243,11 @@ class _HTTPConnection(object): if (self.request.validate_cert and isinstance(self.stream, SSLIOStream)): match_hostname(self.stream.socket.getpeercert(), - # ipv6 addresses are broken until 2.7, here is - # correctly parsed value calculated in __init__ - parsed._hostname) + # ipv6 addresses are broken (in + # parsed.hostname) until 2.7, here is + # correctly parsed value calculated in + # __init__ + parsed_hostname) if (self.request.method not in self._SUPPORTED_METHODS and not self.request.allow_nonstandard_methods): raise KeyError("unknown method %s" % self.request.method) diff --git a/tornado/test/httpserver_test.py b/tornado/test/httpserver_test.py index 01f8f837e..71134f115 100644 --- a/tornado/test/httpserver_test.py +++ b/tornado/test/httpserver_test.py @@ -173,7 +173,7 @@ class RawRequestHTTPConnection(simple_httpclient._HTTPConnection): def set_request(self, request): self.__next_request = request - def _on_connect(self, parsed): + def _on_connect(self, parsed, parsed_hostname): self.stream.write(self.__next_request) self.__next_request = None self.stream.read_until(b("\r\n\r\n"), self._on_headers) diff --git a/website/sphinx/releases/next.rst b/website/sphinx/releases/next.rst index 107507ce4..a6c7faf41 100644 --- a/website/sphinx/releases/next.rst +++ b/website/sphinx/releases/next.rst @@ -11,3 +11,5 @@ In progress instead of leaving them for garbage collection. * Repeated calls to `RequestHandler.set_cookie` with the same name now overwrite the previous cookie instead of producing additional copies. +* `tornado.simple_httpclient` correctly verifies SSL certificates for + URLs containing IPv6 literals (This bug affected Python 2.5 and 2.6).