Commit d76088d9 authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #13636: Weak ciphers are now disabled by default in the ssl module

(except when SSLv2 is explicitly asked for).
parent 499718de
...@@ -81,8 +81,9 @@ _PROTOCOL_NAMES = { ...@@ -81,8 +81,9 @@ _PROTOCOL_NAMES = {
} }
try: try:
from _ssl import PROTOCOL_SSLv2 from _ssl import PROTOCOL_SSLv2
_SSLv2_IF_EXISTS = PROTOCOL_SSLv2
except ImportError: except ImportError:
pass _SSLv2_IF_EXISTS = None
else: else:
_PROTOCOL_NAMES[PROTOCOL_SSLv2] = "SSLv2" _PROTOCOL_NAMES[PROTOCOL_SSLv2] = "SSLv2"
...@@ -91,6 +92,11 @@ from socket import getnameinfo as _getnameinfo ...@@ -91,6 +92,11 @@ from socket import getnameinfo as _getnameinfo
import base64 # for DER-to-PEM translation import base64 # for DER-to-PEM translation
import errno 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): class SSLSocket(socket):
"""This class implements a subtype of socket.socket that wraps """This class implements a subtype of socket.socket that wraps
...@@ -112,6 +118,9 @@ class SSLSocket(socket): ...@@ -112,6 +118,9 @@ class SSLSocket(socket):
except AttributeError: except AttributeError:
pass pass
if ciphers is None and ssl_version != _SSLv2_IF_EXISTS:
ciphers = _DEFAULT_CIPHERS
if certfile and not keyfile: if certfile and not keyfile:
keyfile = certfile keyfile = certfile
# see if it's connected # see if it's connected
......
...@@ -417,10 +417,11 @@ else: ...@@ -417,10 +417,11 @@ else:
ca_certs=self.server.cacerts, ca_certs=self.server.cacerts,
cert_reqs=self.server.certreqs, cert_reqs=self.server.certreqs,
ciphers=self.server.ciphers) ciphers=self.server.ciphers)
except ssl.SSLError: except ssl.SSLError as e:
# XXX Various errors can have happened here, for example # XXX Various errors can have happened here, for example
# a mismatching protocol version, an invalid certificate, # a mismatching protocol version, an invalid certificate,
# or a low-level bug. This should be made more discriminating. # or a low-level bug. This should be made more discriminating.
self.server.conn_errors.append(e)
if self.server.chatty: if self.server.chatty:
handle_error("\n server: bad connection attempt from " + handle_error("\n server: bad connection attempt from " +
str(self.sock.getpeername()) + ":\n") str(self.sock.getpeername()) + ":\n")
...@@ -529,12 +530,14 @@ else: ...@@ -529,12 +530,14 @@ else:
sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock)) sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
self.port = test_support.bind_port(self.sock) self.port = test_support.bind_port(self.sock)
self.active = False self.active = False
self.conn_errors = []
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.daemon = True self.daemon = True
def __enter__(self): def __enter__(self):
self.start(threading.Event()) self.start(threading.Event())
self.flag.wait() self.flag.wait()
return self
def __exit__(self, *args): def __exit__(self, *args):
self.stop() self.stop()
...@@ -649,6 +652,7 @@ else: ...@@ -649,6 +652,7 @@ else:
def __enter__(self): def __enter__(self):
self.start(threading.Event()) self.start(threading.Event())
self.flag.wait() self.flag.wait()
return self
def __exit__(self, *args): def __exit__(self, *args):
if test_support.verbose: if test_support.verbose:
...@@ -1310,6 +1314,25 @@ else: ...@@ -1310,6 +1314,25 @@ else:
t.join() t.join()
server.close() 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): def test_main(verbose=False):
global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT
......
...@@ -89,6 +89,9 @@ Core and Builtins ...@@ -89,6 +89,9 @@ Core and Builtins
Library 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 #12798: Updated the mimetypes documentation.
- Issue #13639: Accept unicode filenames in tarfile.open(mode="w|gz"). - Issue #13639: Accept unicode filenames in tarfile.open(mode="w|gz").
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment