]> granicus.if.org Git - python/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 ce9ebdf30ae6fa9e51ff8331890dedbd49f8fadf..813723171188488e0c2f74f1abb3dea011823c35 100644 (file)
@@ -86,8 +86,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"
 
@@ -98,6 +99,10 @@ import base64        # for DER-to-PEM translation
 import traceback
 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 CertificateError(ValueError):
     pass
@@ -165,7 +170,10 @@ class SSLContext(_SSLContext):
     __slots__ = ('protocol',)
 
     def __new__(cls, protocol, *args, **kwargs):
-        return _SSLContext.__new__(cls, protocol)
+        self = _SSLContext.__new__(cls, protocol)
+        if protocol != _SSLv2_IF_EXISTS:
+            self.set_ciphers(_DEFAULT_CIPHERS)
+        return self
 
     def __init__(self, protocol):
         self.protocol = protocol
index e9fbc8afebb9e1fe5e53b13aa382d1a9291319d8..c6c26bcee3af12536a568364566bc43d83d11726 100644 (file)
@@ -762,10 +762,11 @@ else:
                 try:
                     self.sslconn = self.server.context.wrap_socket(
                         self.sock, server_side=True)
-                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 " + repr(self.addr) + ":\n")
                     self.running = False
@@ -878,12 +879,14 @@ else:
             self.port = support.bind_port(self.sock)
             self.flag = None
             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()
@@ -1004,6 +1007,7 @@ else:
         def __enter__(self):
             self.start(threading.Event())
             self.flag.wait()
+            return self
 
         def __exit__(self, *args):
             if support.verbose:
@@ -1604,6 +1608,22 @@ else:
                 t.join()
                 server.close()
 
+        def test_default_ciphers(self):
+            context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
+            try:
+                # Force a set of weak ciphers on our client context
+                context.set_ciphers("DES")
+            except ssl.SSLError:
+                self.skipTest("no DES cipher available")
+            with ThreadedEchoServer(CERTFILE,
+                                    ssl_version=ssl.PROTOCOL_SSLv23,
+                                    chatty=False) as server:
+                with socket.socket() as sock:
+                    s = context.wrap_socket(sock)
+                    with self.assertRaises((OSError, ssl.SSLError)):
+                        s.connect((HOST, server.port))
+            self.assertIn("no shared cipher", str(server.conn_errors[0]))
+
 
 def test_main(verbose=False):
     if support.verbose:
index da9e9de1b6da7496ab052311cf26e05c614eae97..6e5b7f303aa25b4da468b9bc959c5a1d9c89e761 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -97,6 +97,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 #11006: Don't issue low level warning in subprocess when pipe2() fails.