From: Antoine Pitrou Date: Tue, 3 Jan 2012 21:49:08 +0000 (+0100) Subject: Issue #13636: Weak ciphers are now disabled by default in the ssl module X-Git-Tag: v3.3.0a1~485 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=72aeec35a14b6a708e7cbacdf48a07adf999f215;p=thirdparty%2FPython%2Fcpython.git Issue #13636: Weak ciphers are now disabled by default in the ssl module (except when SSLv2 is explicitly asked for). --- 72aeec35a14b6a708e7cbacdf48a07adf999f215 diff --cc Lib/ssl.py index b56a8c849afd,813723171188..0282ee924a09 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@@ -110,11 -99,11 +111,16 @@@ import base64 # for DER-to-PEM t import traceback import errno +if _ssl.HAS_TLS_UNIQUE: + CHANNEL_BINDING_TYPES = ['tls-unique'] +else: + CHANNEL_BINDING_TYPES = [] + + # 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 diff --cc Lib/test/test_ssl.py index a4bcdd017ea9,c6c26bcee3af..86d1cd8df700 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@@ -1739,98 -1608,22 +1743,114 @@@ 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])) + + @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES, + "'tls-unique' channel binding not available") + def test_tls_unique_channel_binding(self): + """Test tls-unique channel binding.""" + if support.verbose: + sys.stdout.write("\n") + + server = ThreadedEchoServer(CERTFILE, + certreqs=ssl.CERT_NONE, + ssl_version=ssl.PROTOCOL_TLSv1, + cacerts=CERTFILE, + chatty=True, + connectionchatty=False) + with server: + s = ssl.wrap_socket(socket.socket(), + server_side=False, + certfile=CERTFILE, + ca_certs=CERTFILE, + cert_reqs=ssl.CERT_NONE, + ssl_version=ssl.PROTOCOL_TLSv1) + s.connect((HOST, server.port)) + # get the data + cb_data = s.get_channel_binding("tls-unique") + if support.verbose: + sys.stdout.write(" got channel binding data: {0!r}\n" + .format(cb_data)) + + # check if it is sane + self.assertIsNotNone(cb_data) + self.assertEqual(len(cb_data), 12) # True for TLSv1 + + # and compare with the peers version + s.write(b"CB tls-unique\n") + peer_data_repr = s.read().strip() + self.assertEqual(peer_data_repr, + repr(cb_data).encode("us-ascii")) + s.close() + + # now, again + s = ssl.wrap_socket(socket.socket(), + server_side=False, + certfile=CERTFILE, + ca_certs=CERTFILE, + cert_reqs=ssl.CERT_NONE, + ssl_version=ssl.PROTOCOL_TLSv1) + s.connect((HOST, server.port)) + new_cb_data = s.get_channel_binding("tls-unique") + if support.verbose: + sys.stdout.write(" got another channel binding data: {0!r}\n" + .format(new_cb_data)) + # is it really unique + self.assertNotEqual(cb_data, new_cb_data) + self.assertIsNotNone(cb_data) + self.assertEqual(len(cb_data), 12) # True for TLSv1 + s.write(b"CB tls-unique\n") + peer_data_repr = s.read().strip() + self.assertEqual(peer_data_repr, + repr(new_cb_data).encode("us-ascii")) + s.close() + + def test_compression(self): + context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context.load_cert_chain(CERTFILE) + stats = server_params_test(context, context, + chatty=True, connectionchatty=True) + if support.verbose: + sys.stdout.write(" got compression: {!r}\n".format(stats['compression'])) + self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' }) + + @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'), + "ssl.OP_NO_COMPRESSION needed for this test") + def test_compression_disabled(self): + context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context.load_cert_chain(CERTFILE) + context.options |= ssl.OP_NO_COMPRESSION + stats = server_params_test(context, context, + chatty=True, connectionchatty=True) + self.assertIs(stats['compression'], None) + + def test_dh_params(self): + # Check we can get a connection with ephemeral Diffie-Hellman + context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context.load_cert_chain(CERTFILE) + context.load_dh_params(DHFILE) + context.set_ciphers("kEDH") + stats = server_params_test(context, context, + chatty=True, connectionchatty=True) + cipher = stats["cipher"][0] + parts = cipher.split("-") + if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts: + self.fail("Non-DH cipher: " + cipher[0]) + def test_main(verbose=False): if support.verbose: diff --cc Misc/NEWS index 827aa4e32a9b,6e5b7f303aa2..2df62e5c9a7e --- a/Misc/NEWS +++ b/Misc/NEWS @@@ -422,23 -97,13 +422,26 @@@ Core and Builtin Library ------- + - Issue #13636: Weak ciphers are now disabled by default in the ssl module + (except when SSLv2 is explicitly asked for). + +- Issue #12715: Add an optional symlinks argument to shutil functions + (copyfile, copymode, copystat, copy, copy2). When that parameter is + true, symlinks aren't dereferenced and the operation instead acts on the + symlink itself (or creates one, if relevant). Patch by Hynek Schlawack. + +- Add a flags parameter to select.epoll. + - Issue #12798: Updated the mimetypes documentation. +- Issue #13626: Add support for SSL Diffie-Hellman key exchange, through the + SSLContext.load_dh_params() method and the ssl.OP_SINGLE_DH_USE option. + - Issue #11006: Don't issue low level warning in subprocess when pipe2() fails. +- Issue #13620: Support for Chrome browser in webbrowser.py Patch contributed + by Arnaud Calmettes. + - Issue #11829: Fix code execution holes in inspect.getattr_static for metaclasses with metaclasses. Patch by Andreas Stührk.