]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #13636: Weak ciphers are now disabled by default in the ssl module
authorAntoine Pitrou <solipsis@pitrou.net>
Tue, 3 Jan 2012 21:46:48 +0000 (22:46 +0100)
committerAntoine Pitrou <solipsis@pitrou.net>
Tue, 3 Jan 2012 21:46:48 +0000 (22:46 +0100)
(except when SSLv2 is explicitly asked for).

Lib/ssl.py
Lib/test/test_ssl.py
Misc/NEWS

index f3e5123976145e36def1479f87c242d4ca204b3a..1951a620d961ae51f6a5f414dbea280a0f51d008 100644 (file)
@@ -81,8 +81,9 @@ _PROTOCOL_NAMES = {
 }
 try:
     from _ssl import PROTOCOL_SSLv2
+    _SSLv2_IF_EXISTS = PROTOCOL_SSLv2
 except ImportError:
-    pass
+    _SSLv2_IF_EXISTS = None
 else:
     _PROTOCOL_NAMES[PROTOCOL_SSLv2] = "SSLv2"
 
@@ -91,6 +92,11 @@ from socket import getnameinfo as _getnameinfo
 import base64        # for DER-to-PEM translation
 import errno
 
+# Disable weak or insecure ciphers by default
+# (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL')
+_DEFAULT_CIPHERS = 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2'
+
+
 class SSLSocket(socket):
 
     """This class implements a subtype of socket.socket that wraps
@@ -112,6 +118,9 @@ class SSLSocket(socket):
             except AttributeError:
                 pass
 
+        if ciphers is None and ssl_version != _SSLv2_IF_EXISTS:
+            ciphers = _DEFAULT_CIPHERS
+
         if certfile and not keyfile:
             keyfile = certfile
         # see if it's connected
index e5addf807778bc6b688db949bb88c7dfcdd016d6..e64d1b22fa535e6482a7809617a8cb9ffc4081b8 100644 (file)
@@ -417,10 +417,11 @@ else:
                                                    ca_certs=self.server.cacerts,
                                                    cert_reqs=self.server.certreqs,
                                                    ciphers=self.server.ciphers)
-                except ssl.SSLError:
+                except ssl.SSLError as e:
                     # XXX Various errors can have happened here, for example
                     # a mismatching protocol version, an invalid certificate,
                     # or a low-level bug. This should be made more discriminating.
+                    self.server.conn_errors.append(e)
                     if self.server.chatty:
                         handle_error("\n server:  bad connection attempt from " +
                                      str(self.sock.getpeername()) + ":\n")
@@ -529,12 +530,14 @@ else:
                     sys.stdout.write(' server:  wrapped server socket as %s\n' % str(self.sock))
             self.port = test_support.bind_port(self.sock)
             self.active = False
+            self.conn_errors = []
             threading.Thread.__init__(self)
             self.daemon = True
 
         def __enter__(self):
             self.start(threading.Event())
             self.flag.wait()
+            return self
 
         def __exit__(self, *args):
             self.stop()
@@ -649,6 +652,7 @@ else:
         def __enter__(self):
             self.start(threading.Event())
             self.flag.wait()
+            return self
 
         def __exit__(self, *args):
             if test_support.verbose:
@@ -1310,6 +1314,25 @@ else:
                 t.join()
                 server.close()
 
+        def test_default_ciphers(self):
+            with ThreadedEchoServer(CERTFILE,
+                                    ssl_version=ssl.PROTOCOL_SSLv23,
+                                    chatty=False) as server:
+                sock = socket.socket()
+                try:
+                    # Force a set of weak ciphers on our client socket
+                    try:
+                        s = ssl.wrap_socket(sock,
+                                            ssl_version=ssl.PROTOCOL_SSLv23,
+                                            ciphers="DES")
+                    except ssl.SSLError:
+                        self.skipTest("no DES cipher available")
+                    with self.assertRaises((OSError, ssl.SSLError)):
+                        s.connect((HOST, server.port))
+                finally:
+                    sock.close()
+            self.assertIn("no shared cipher", str(server.conn_errors[0]))
+
 
 def test_main(verbose=False):
     global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT
index 82551d2defcdb3b0ebe2c0b7ca0f48008e79e41d..8bd308bd2699c1b29d6c4c8191466995e5e1847b 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -89,6 +89,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #13636: Weak ciphers are now disabled by default in the ssl module
+  (except when SSLv2 is explicitly asked for).
+
 - Issue #12798: Updated the mimetypes documentation.
 
 - Issue #13639: Accept unicode filenames in tarfile.open(mode="w|gz").