]> granicus.if.org Git - python/commitdiff
Issue #26470: Port ssl and hashlib module to OpenSSL 1.1.0.
authorChristian Heimes <christian@python.org>
Mon, 5 Sep 2016 21:23:24 +0000 (23:23 +0200)
committerChristian Heimes <christian@python.org>
Mon, 5 Sep 2016 21:23:24 +0000 (23:23 +0200)
1  2 
Doc/library/ssl.rst
Lib/ssl.py
Lib/test/test_ssl.py
Misc/NEWS
Modules/_hashopenssl.c
Modules/_ssl.c

index 5792d0d407ba224bc4b42c78af613630f341ff51,d8fc8de115f913e4d66a218ea34b80b4e9292b7d..04fad06a64f898d8f04addbd421eec50f1e0b9a0
@@@ -49,6 -49,6 +49,12 @@@ For more sophisticated applications, th
  helps manage settings and certificates, which can then be inherited
  by SSL sockets created through the :meth:`SSLContext.wrap_socket` method.
  
++.. versionchanged:: 3.6
++
++   OpenSSL 0.9.8, 1.0.0 and 1.0.1 are deprecated and no longer supported.
++   In the future the ssl module will require at least OpenSSL 1.0.2 or
++   1.1.0.
++
  
  Functions, Constants, and Exceptions
  ------------------------------------
@@@ -316,6 -316,11 +322,11 @@@ Random generatio
  
     .. versionadded:: 3.3
  
 -   .. deprecated:: 3.5.3
++   .. deprecated:: 3.6
+       OpenSSL has deprecated :func:`ssl.RAND_pseudo_bytes`, use
+       :func:`ssl.RAND_bytes` instead.
  .. function:: RAND_status()
  
     Return ``True`` if the SSL pseudo-random number generator has been seeded
@@@ -573,6 -581,16 +587,16 @@@ Constant
     Selects the highest protocol version that both the client and server support.
     Despite the name, this option can select "TLS" protocols as well as "SSL".
  
 -   .. versionadded:: 3.5.3
++   .. versionadded:: 3.6
+ .. data:: PROTOCOL_SSLv23
+    Alias for data:`PROTOCOL_TLS`.
 -   .. deprecated:: 3.5.3
++   .. deprecated:: 3.6
+       Use data:`PROTOCOL_TLS` instead.
  .. data:: PROTOCOL_SSLv2
  
     Selects SSL version 2 as the channel encryption protocol.
  
        SSL version 2 is insecure.  Its use is highly discouraged.
  
 -   .. deprecated:: 3.5.3
++   .. deprecated:: 3.6
+       OpenSSL has removed support for SSLv2.
  .. data:: PROTOCOL_SSLv3
  
     Selects SSL version 3 as the channel encryption protocol.
  
        SSL version 3 is insecure.  Its use is highly discouraged.
  
 -   .. deprecated:: 3.5.3
++   .. deprecated:: 3.6
+       OpenSSL has deprecated all version specific protocols. Use the default
+       protocol data:`PROTOCOL_TLS` with flags like data:`OP_NO_SSLv3` instead.
  .. data:: PROTOCOL_TLSv1
  
     Selects TLS version 1.0 as the channel encryption protocol.
  
 -   .. deprecated:: 3.5.3
++   .. deprecated:: 3.6
+       OpenSSL has deprecated all version specific protocols. Use the default
+       protocol data:`PROTOCOL_TLS` with flags like data:`OP_NO_SSLv3` instead.
  .. data:: PROTOCOL_TLSv1_1
  
     Selects TLS version 1.1 as the channel encryption protocol.
  
     .. versionadded:: 3.4
  
 -   .. deprecated:: 3.5.3
++   .. deprecated:: 3.6
+       OpenSSL has deprecated all version specific protocols. Use the default
+       protocol data:`PROTOCOL_TLS` with flags like data:`OP_NO_SSLv3` instead.
  .. data:: PROTOCOL_TLSv1_2
  
     Selects TLS version 1.2 as the channel encryption protocol. This is the
  
     .. versionadded:: 3.4
  
 -   .. deprecated:: 3.5.3
++   .. deprecated:: 3.6
+       OpenSSL has deprecated all version specific protocols. Use the default
+       protocol data:`PROTOCOL_TLS` with flags like data:`OP_NO_SSLv3` instead.
  .. data:: OP_ALL
  
     Enables workarounds for various bugs present in other SSL implementations.
  
     .. versionadded:: 3.2
  
 -   .. deprecated:: 3.5.3
++   .. deprecated:: 3.6
+       SSLv2 is deprecated
  .. data:: OP_NO_SSLv3
  
     Prevents an SSLv3 connection.  This option is only applicable in
  
     .. versionadded:: 3.2
  
 -   .. deprecated:: 3.5.3
++   .. deprecated:: 3.6
+       SSLv3 is deprecated
  .. data:: OP_NO_TLSv1
  
     Prevents a TLSv1 connection.  This option is only applicable in
@@@ -1092,6 -1143,10 +1149,10 @@@ to speed up repeated connections from t
        :func:`create_default_context` lets the :mod:`ssl` module choose
        security settings for a given purpose.
  
 -   .. versionchanged:: 3.5.3
++   .. versionchanged:: 3.6
+       :data:`PROTOCOL_TLS` is the default value.
  
  :class:`SSLContext` objects have the following methods and attributes:
  
diff --cc Lib/ssl.py
Simple merge
index 6cd5454ab4d06fdfff0b295b35b90938476aeec9,79e26ba45b73e7479725d7961143b4b4d1dcd052..f6afa267c564df388588859926b98be9023ed4aa
@@@ -21,15 -21,11 +21,18 @@@ import functool
  
  ssl = support.import_module("ssl")
  
 +try:
 +    import threading
 +except ImportError:
 +    _have_threads = False
 +else:
 +    _have_threads = True
 +
  PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
  HOST = support.HOST
+ IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
+ IS_OPENSSL_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0)
  
  def data_file(*name):
      return os.path.join(os.path.dirname(__file__), *name)
@@@ -1655,128 -1742,64 +1660,128 @@@ class SimpleBackgroundTests(unittest.Te
                               % (count, func.__name__))
          return ret
  
 -    def test_handshake(self):
 +    def test_bio_handshake(self):
 +        sock = socket.socket(socket.AF_INET)
 +        self.addCleanup(sock.close)
 +        sock.connect(self.server_addr)
 +        incoming = ssl.MemoryBIO()
 +        outgoing = ssl.MemoryBIO()
 +        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 +        ctx.verify_mode = ssl.CERT_REQUIRED
 +        ctx.load_verify_locations(SIGNING_CA)
 +        ctx.check_hostname = True
 +        sslobj = ctx.wrap_bio(incoming, outgoing, False, 'localhost')
 +        self.assertIs(sslobj._sslobj.owner, sslobj)
 +        self.assertIsNone(sslobj.cipher())
-         self.assertIsNone(sslobj.shared_ciphers())
++        self.assertIsNotNone(sslobj.shared_ciphers())
 +        self.assertRaises(ValueError, sslobj.getpeercert)
 +        if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
 +            self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
 +        self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
 +        self.assertTrue(sslobj.cipher())
-         self.assertIsNone(sslobj.shared_ciphers())
++        self.assertIsNotNone(sslobj.shared_ciphers())
 +        self.assertTrue(sslobj.getpeercert())
 +        if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
 +            self.assertTrue(sslobj.get_channel_binding('tls-unique'))
 +        try:
 +            self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
 +        except ssl.SSLSyscallError:
 +            # If the server shuts down the TCP connection without sending a
 +            # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
 +            pass
 +        self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
 +
 +    def test_bio_read_write_data(self):
 +        sock = socket.socket(socket.AF_INET)
 +        self.addCleanup(sock.close)
 +        sock.connect(self.server_addr)
 +        incoming = ssl.MemoryBIO()
 +        outgoing = ssl.MemoryBIO()
 +        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 +        ctx.verify_mode = ssl.CERT_NONE
 +        sslobj = ctx.wrap_bio(incoming, outgoing, False)
 +        self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
 +        req = b'FOO\n'
 +        self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
 +        buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
 +        self.assertEqual(buf, b'foo\n')
 +        self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
 +
 +
 +class NetworkedTests(unittest.TestCase):
 +
 +    def test_timeout_connect_ex(self):
 +        # Issue #12065: on a timeout, connect_ex() should return the original
 +        # errno (mimicking the behaviour of non-SSL sockets).
          with support.transient_internet(REMOTE_HOST):
 -            sock = socket.socket(socket.AF_INET)
 -            sock.connect((REMOTE_HOST, 443))
 -            incoming = ssl.MemoryBIO()
 -            outgoing = ssl.MemoryBIO()
 -            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 +            s = ssl.wrap_socket(socket.socket(socket.AF_INET),
 +                                cert_reqs=ssl.CERT_REQUIRED,
 +                                do_handshake_on_connect=False)
 +            self.addCleanup(s.close)
 +            s.settimeout(0.0000001)
 +            rc = s.connect_ex((REMOTE_HOST, 443))
 +            if rc == 0:
 +                self.skipTest("REMOTE_HOST responded too quickly")
 +            self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
 +
 +    @unittest.skipUnless(support.IPV6_ENABLED, 'Needs IPv6')
 +    def test_get_server_certificate_ipv6(self):
 +        with support.transient_internet('ipv6.google.com'):
 +            _test_get_server_certificate(self, 'ipv6.google.com', 443)
 +            _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
 +
 +    def test_algorithms(self):
 +        # Issue #8484: all algorithms should be available when verifying a
 +        # certificate.
 +        # SHA256 was added in OpenSSL 0.9.8
 +        if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
 +            self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
 +        # sha256.tbs-internet.com needs SNI to use the correct certificate
 +        if not ssl.HAS_SNI:
 +            self.skipTest("SNI needed for this test")
 +        # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
 +        remote = ("sha256.tbs-internet.com", 443)
 +        sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
 +        with support.transient_internet("sha256.tbs-internet.com"):
 +            ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
              ctx.verify_mode = ssl.CERT_REQUIRED
 -            ctx.load_verify_locations(REMOTE_ROOT_CERT)
 -            ctx.check_hostname = True
 -            sslobj = ctx.wrap_bio(incoming, outgoing, False, REMOTE_HOST)
 -            self.assertIs(sslobj._sslobj.owner, sslobj)
 -            self.assertIsNone(sslobj.cipher())
 -            self.assertIsNotNone(sslobj.shared_ciphers())
 -            self.assertRaises(ValueError, sslobj.getpeercert)
 -            if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
 -                self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
 -            self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
 -            self.assertTrue(sslobj.cipher())
 -            self.assertIsNotNone(sslobj.shared_ciphers())
 -            self.assertTrue(sslobj.getpeercert())
 -            if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
 -                self.assertTrue(sslobj.get_channel_binding('tls-unique'))
 +            ctx.load_verify_locations(sha256_cert)
 +            s = ctx.wrap_socket(socket.socket(socket.AF_INET),
 +                                server_hostname="sha256.tbs-internet.com")
              try:
 -                self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
 -            except ssl.SSLSyscallError:
 -                # self-signed.pythontest.net probably shuts down the TCP
 -                # connection without sending a secure shutdown message, and
 -                # this is reported as SSL_ERROR_SYSCALL
 -                pass
 -            self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
 -            sock.close()
 +                s.connect(remote)
 +                if support.verbose:
 +                    sys.stdout.write("\nCipher with %r is %r\n" %
 +                                     (remote, s.cipher()))
 +                    sys.stdout.write("Certificate is:\n%s\n" %
 +                                     pprint.pformat(s.getpeercert()))
 +            finally:
 +                s.close()
  
 -    def test_read_write_data(self):
 -        with support.transient_internet(REMOTE_HOST):
 -            sock = socket.socket(socket.AF_INET)
 -            sock.connect((REMOTE_HOST, 443))
 -            incoming = ssl.MemoryBIO()
 -            outgoing = ssl.MemoryBIO()
 -            ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
 -            ctx.verify_mode = ssl.CERT_NONE
 -            sslobj = ctx.wrap_bio(incoming, outgoing, False)
 -            self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
 -            req = b'GET / HTTP/1.0\r\n\r\n'
 -            self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
 -            buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
 -            self.assertEqual(buf[:5], b'HTTP/')
 -            self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
 -            sock.close()
  
 +def _test_get_server_certificate(test, host, port, cert=None):
 +    pem = ssl.get_server_certificate((host, port))
 +    if not pem:
 +        test.fail("No server certificate on %s:%s!" % (host, port))
  
 -try:
 -    import threading
 -except ImportError:
 -    _have_threads = False
 -else:
 -    _have_threads = True
 +    pem = ssl.get_server_certificate((host, port), ca_certs=cert)
 +    if not pem:
 +        test.fail("No server certificate on %s:%s!" % (host, port))
 +    if support.verbose:
 +        sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
  
 +def _test_get_server_certificate_fail(test, host, port):
 +    try:
 +        pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
 +    except ssl.SSLError as x:
 +        #should fail
 +        if support.verbose:
 +            sys.stdout.write("%s\n" % x)
 +    else:
 +        test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
 +
 +
 +if _have_threads:
      from test.ssl_servers import make_https_server
  
      class ThreadedEchoServer(threading.Thread):
diff --cc Misc/NEWS
index 5fdabe0359a26c7ddc2988850503aecd6ff5d223,49b1ce21790127dd829839fcb3c26a8bd1465285..428cf2fd9e70282f0f83d4ea5cb4be24bdcb9cbd
+++ b/Misc/NEWS
@@@ -72,24 -36,31 +72,26 @@@ Core and Builtin
    In a brand new thread, raise a RuntimeError since there is no active
    exception to reraise. Patch written by Xiang Zhang.
  
 -- Issue #27419: Standard __import__() no longer look up "__import__" in globals
 -  or builtins for importing submodules or "from import".  Fixed handling an
 -  error of non-string package name.
 -
 -- Issue #27083: Respect the PYTHONCASEOK environment variable under Windows.
 -
 -- Issue #27514: Make having too many statically nested blocks a SyntaxError
 -  instead of SystemError.
 +Library
 +-------
  
 -- Issue #27473: Fixed possible integer overflow in bytes and bytearray
 -  concatenations.  Patch by Xiang Zhang.
++- Issue #26470: Port ssl and hashlib module to OpenSSL 1.1.0.
 -- Issue #27507: Add integer overflow check in bytearray.extend().  Patch by
 -  Xiang Zhang.
 +- Issue #11620: Fix support for SND_MEMORY in winsound.PlaySound.  Based on a
 +  patch by Tim Lesher.
  
 -- Issue #27581: Don't rely on wrapping for overflow check in
 -  PySequence_Tuple().  Patch by Xiang Zhang.
 +- Issue #11734: Add support for IEEE 754 half-precision floats to the
 +  struct module. Based on a patch by Eli Stevens.
  
 -- Issue #27443: __length_hint__() of bytearray iterators no longer return a
 -  negative integer for a resized bytearray.
 +- Issue #27919: Deprecated ``extra_path`` distribution option in distutils
 +  packaging.
  
 -Library
 --------
 +- Issue #23229: Add new ``cmath`` constants: ``cmath.inf`` and ``cmath.nan`` to
 +  match ``math.inf`` and ``math.nan``, and also ``cmath.infj`` and
 +  ``cmath.nanj`` to match the format used by complex repr.
  
 -- Issue #26470: Port ssl and hashlib module to OpenSSL 1.1.0.
 +- Issue #27842: The csv.DictReader now returns rows of type OrderedDict.
 +  (Contributed by Steve Holden.)
  
  - Issue #12885: Fix error when distutils encounters symlink.
  
Simple merge
diff --cc Modules/_ssl.c
Simple merge