]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Use SSLContext APIs in simple_httpclient
authorBen Darnell <ben@bendarnell.com>
Sun, 22 Oct 2017 17:14:44 +0000 (13:14 -0400)
committerBen Darnell <ben@bendarnell.com>
Sun, 22 Oct 2017 18:08:55 +0000 (14:08 -0400)
Set OP_NO_COMPRESSION more consistently.

tornado/netutil.py
tornado/simple_httpclient.py

index 63c80cb33148347b9268b51d28a3e374cf8f53da..1469b90c0b972d502da0a10be8e501c12b012079 100644 (file)
@@ -45,6 +45,10 @@ if ssl is not None:
         ssl.Purpose.SERVER_AUTH)
     _server_ssl_defaults = ssl.create_default_context(
         ssl.Purpose.CLIENT_AUTH)
+    if hasattr(ssl, 'OP_NO_COMPRESSION'):
+        # See netutil.ssl_options_to_context
+        _client_ssl_defaults.options |= ssl.OP_NO_COMPRESSION
+        _server_ssl_defaults.options |= ssl.OP_NO_COMPRESSION
 else:
     # Google App Engine
     _client_ssl_defaults = dict(cert_reqs=None,
@@ -465,6 +469,8 @@ def ssl_options_to_context(ssl_options):
         return ssl_options
     assert isinstance(ssl_options, dict)
     assert all(k in _SSL_CONTEXT_KEYWORDS for k in ssl_options), ssl_options
+    # Can't use create_default_context since this interface doesn't
+    # tell us client vs server.
     context = ssl.SSLContext(
         ssl_options.get('ssl_version', ssl.PROTOCOL_SSLv23))
     if 'certfile' in ssl_options:
@@ -477,7 +483,9 @@ def ssl_options_to_context(ssl_options):
         context.set_ciphers(ssl_options['ciphers'])
     if hasattr(ssl, 'OP_NO_COMPRESSION'):
         # Disable TLS compression to avoid CRIME and related attacks.
-        # This constant wasn't added until python 3.3.
+        # This constant depends on openssl version 1.0.
+        # TODO: Do we need to do this ourselves or can we trust
+        # the defaults?
         context.options |= ssl.OP_NO_COMPRESSION
     return context
 
index 6534399117a842ee3919273e7a16d7bc556cf234..6d90352f1a80673a3ced0cd1159fb6b0cc0cd251 100644 (file)
@@ -244,37 +244,19 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
                     self.request.client_cert is None and
                     self.request.client_key is None):
                 return _client_ssl_defaults
-            ssl_options = {}
-            if self.request.validate_cert:
-                ssl_options["cert_reqs"] = ssl.CERT_REQUIRED
-            if self.request.ca_certs is not None:
-                ssl_options["ca_certs"] = self.request.ca_certs
-            if self.request.client_key is not None:
-                ssl_options["keyfile"] = self.request.client_key
+            ssl_ctx = ssl.create_default_context(
+                ssl.Purpose.SERVER_AUTH,
+                cafile=self.request.ca_certs)
+            if not self.request.validate_cert:
+                ssl_ctx.check_hostname = False
+                ssl_ctx.verify_mode = ssl.CERT_NONE
             if self.request.client_cert is not None:
-                ssl_options["certfile"] = self.request.client_cert
-
-            # SSL interoperability is tricky.  We want to disable
-            # SSLv2 for security reasons; it wasn't disabled by default
-            # until openssl 1.0.  The best way to do this is to use
-            # the SSL_OP_NO_SSLv2, but that wasn't exposed to python
-            # until 3.2.  Python 2.7 adds the ciphers argument, which
-            # can also be used to disable SSLv2.  As a last resort
-            # on python 2.6, we set ssl_version to TLSv1.  This is
-            # more narrow than we'd like since it also breaks
-            # compatibility with servers configured for SSLv3 only,
-            # but nearly all servers support both SSLv3 and TLSv1:
-            # http://blog.ivanristic.com/2011/09/ssl-survey-protocol-support.html
-            if sys.version_info >= (2, 7):
-                # In addition to disabling SSLv2, we also exclude certain
-                # classes of insecure ciphers.
-                ssl_options["ciphers"] = "DEFAULT:!SSLv2:!EXPORT:!DES"
-            else:
-                # This is really only necessary for pre-1.0 versions
-                # of openssl, but python 2.6 doesn't expose version
-                # information.
-                ssl_options["ssl_version"] = ssl.PROTOCOL_TLSv1
-            return ssl_options
+                ssl_ctx.load_cert_chain(self.request.client_cert,
+                                        self.request.client_key)
+            if hasattr(ssl, 'OP_NO_COMPRESSION'):
+                # See netutil.ssl_options_to_context
+                ssl_ctx.options |= ssl.OP_NO_COMPRESSION
+            return ssl_ctx
         return None
 
     def _on_timeout(self, info=None):