[Python-checkins] cpython (2.7): allow hostname to be passed to SSLContext even if OpenSSL doesn't support SNI

benjamin.peterson python-checkins at python.org
Mon Nov 24 03:13:47 CET 2014


https://hg.python.org/cpython/rev/ce4073afd992
changeset:   93561:ce4073afd992
branch:      2.7
parent:      93556:a69da17e7060
user:        Benjamin Peterson <benjamin at python.org>
date:        Sun Nov 23 20:13:31 2014 -0600
summary:
  allow hostname to be passed to SSLContext even if OpenSSL doesn't support SNI (closes #22921)

Patch from Donald Stufft.

files:
  Doc/library/ssl.rst  |  14 +++++++-------
  Lib/httplib.py       |   3 +--
  Lib/ssl.py           |   7 +------
  Lib/test/test_ssl.py |   8 ++------
  Modules/_ssl.c       |   6 ------
  5 files changed, 11 insertions(+), 27 deletions(-)


diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -645,8 +645,7 @@
 .. data:: HAS_SNI
 
    Whether the OpenSSL library has built-in support for the *Server Name
-   Indication* extension (as defined in :rfc:`4366`).  When true, you can
-   use the *server_hostname* argument to :meth:`SSLContext.wrap_socket`.
+   Indication* extension (as defined in :rfc:`4366`).
 
    .. versionadded:: 2.7.9
 
@@ -1136,11 +1135,12 @@
    On client connections, the optional parameter *server_hostname* specifies
    the hostname of the service which we are connecting to.  This allows a
    single server to host multiple SSL-based services with distinct certificates,
-   quite similarly to HTTP virtual hosts.  Specifying *server_hostname*
-   will raise a :exc:`ValueError` if the OpenSSL library doesn't have support
-   for it (that is, if :data:`HAS_SNI` is :const:`False`).  Specifying
-   *server_hostname* will also raise a :exc:`ValueError` if *server_side*
-   is true.
+   quite similarly to HTTP virtual hosts. Specifying *server_hostname* will
+   raise a :exc:`ValueError` if *server_side* is true.
+
+   .. versionchanged:: 3.5
+      Always allow a server_hostname to be passed, even if OpenSSL does not
+      have SNI.
 
 .. method:: SSLContext.session_stats()
 
diff --git a/Lib/httplib.py b/Lib/httplib.py
--- a/Lib/httplib.py
+++ b/Lib/httplib.py
@@ -1214,10 +1214,9 @@
                 server_hostname = self._tunnel_host
             else:
                 server_hostname = self.host
-            sni_hostname = server_hostname if ssl.HAS_SNI else None
 
             self.sock = self._context.wrap_socket(self.sock,
-                                                  server_hostname=sni_hostname)
+                                                  server_hostname=server_hostname)
             if not self._context.check_hostname and self._check_hostname:
                 try:
                     ssl.match_hostname(self.sock.getpeercert(), server_hostname)
diff --git a/Lib/ssl.py b/Lib/ssl.py
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -527,12 +527,7 @@
             raise ValueError("server_hostname can only be specified "
                              "in client mode")
         if self._context.check_hostname and not server_hostname:
-            if HAS_SNI:
-                raise ValueError("check_hostname requires server_hostname")
-            else:
-                raise ValueError("check_hostname requires server_hostname, "
-                                 "but it's not supported by your OpenSSL "
-                                 "library")
+            raise ValueError("check_hostname requires server_hostname")
         self.server_side = server_side
         self.server_hostname = server_hostname
         self.do_handshake_on_connect = do_handshake_on_connect
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -1323,11 +1323,8 @@
             # Same with a server hostname
             s = ctx.wrap_socket(socket.socket(socket.AF_INET),
                                 server_hostname="svn.python.org")
-            if ssl.HAS_SNI:
-                s.connect(("svn.python.org", 443))
-                s.close()
-            else:
-                self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
+            s.connect(("svn.python.org", 443))
+            s.close()
             # This should fail because we have no verification certs
             ctx.verify_mode = ssl.CERT_REQUIRED
             s = ctx.wrap_socket(socket.socket(socket.AF_INET))
@@ -2089,7 +2086,6 @@
                     cert = s.getpeercert()
                     self.assertTrue(cert, "Can't get peer certificate.")
 
-        @needs_sni
         def test_check_hostname(self):
             if support.verbose:
                 sys.stdout.write("\n")
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -2824,12 +2824,6 @@
             &sock, &server_side,
             "idna", &hostname, &ssl_sock))
             return NULL;
-#if !HAVE_SNI
-        PyMem_Free(hostname);
-        PyErr_SetString(PyExc_ValueError, "server_hostname is not supported "
-                        "by your OpenSSL library");
-        return NULL;
-#endif
     }
 
     res = (PyObject *) newPySSLSocket(self, sock, server_side,

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list