diff -r 725131a5f6cf Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py Sat Jul 04 22:52:33 2015 -0500 +++ b/Lib/test/test_ssl.py Sun Jul 05 20:26:28 2015 +1000 @@ -21,7 +21,31 @@ ssl = support.import_module("ssl") -PROTOCOLS = sorted(ssl._PROTOCOL_NAMES) +# Issue #9415: some platforms may completely disable SSLv2 support +# Issue #23965: some platforms may completely disable SSLv3 support +def _skip_protocol(candidates, protocol_name): + try: + protocol_id = getattr(ssl, protocol_name) + except AttributeError: + return + del candidates[protocol_id] + +def _get_testable_protocols(): + candidates = sorted(ssl._PROTOCOL_NAMES) + expected_options = ssl.OP_ALL + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + if ctx.options & ssl.OP_NO_SSLv2: + _skip_protocol(candidates, "SSLv2") + expected_options |= ssl.OP_NO_SSLv2 + if ctx.options & ssl.OP_NO_SSLv3: + _skip_protocol(candidates, "PROTOCOL_SSLv3") + _skip_protocol(candidates, "PROTOCOL_SSLv23") + expected_options |= ssl.OP_NO_SSLv3 + return candidates, expected_options + +PROTOCOLS, EXPECTED_CONTEXT_OPTIONS = _get_testable_protocols() +HAVE_SSLv2 = not (EXPECTED_CONTEXT_OPTIONS & ssl.OP_NO_SSLv2) +HAVE_SSLv3 = not (EXPECTED_CONTEXT_OPTIONS & ssl.OP_NO_SSLv3) HOST = support.HOST def data_file(*name): @@ -99,22 +123,6 @@ return cert_time -# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2 -def skip_if_broken_ubuntu_ssl(func): - if hasattr(ssl, 'PROTOCOL_SSLv2'): - @functools.wraps(func) - def f(*args, **kwargs): - try: - ssl.SSLContext(ssl.PROTOCOL_SSLv2) - except ssl.SSLError: - if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and - platform.linux_distribution() == ('debian', 'squeeze/sid', '')): - raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour") - return func(*args, **kwargs) - return f - else: - return func - needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test") @@ -650,7 +658,6 @@ class ContextTests(unittest.TestCase): - @skip_if_broken_ubuntu_ssl def test_constructor(self): for protocol in PROTOCOLS: ssl.SSLContext(protocol) @@ -658,7 +665,6 @@ self.assertRaises(ValueError, ssl.SSLContext, -1) self.assertRaises(ValueError, ssl.SSLContext, 42) - @skip_if_broken_ubuntu_ssl def test_protocol(self): for proto in PROTOCOLS: ctx = ssl.SSLContext(proto) @@ -671,19 +677,22 @@ with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"): ctx.set_ciphers("^$:,;?*'dorothyx") - @skip_if_broken_ubuntu_ssl def test_options(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) - # OP_ALL | OP_NO_SSLv2 is the default value - self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2, - ctx.options) - ctx.options |= ssl.OP_NO_SSLv3 - self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3, - ctx.options) + # Acceptable defaults are OP_ALL, OP_ALL | OP_NO_SSLv2 or + # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3. See above for the calculation + # of which of those we're expecting + self.assertEqual(bin(EXPECTED_CONTEXT_OPTIONS), bin(ctx.options)) + ctx.options |= ssl.OP_NO_COMPRESSION + self.assertEqual(bin(EXPECTED_CONTEXT_OPTIONS | ssl.OP_NO_COMPRESSION), + bin(ctx.options)) if can_clear_options(): - ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1 - self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3, - ctx.options) + ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2 + & ~ssl.OP_NO_SSLv3) | ssl.OP_NO_TLSv1 + self.assertEqual(bin(ssl.OP_ALL | + ssl.OP_NO_TLSv1 | + ssl.OP_NO_COMPRESSION), + bin(ctx.options)) ctx.options = 0 self.assertEqual(0, ctx.options) else: @@ -898,7 +907,6 @@ with self.assertRaises(ssl.SSLError) as cm: ctx.load_dh_params(CERTFILE) - @skip_if_broken_ubuntu_ssl def test_session_stats(self): for proto in PROTOCOLS: ctx = ssl.SSLContext(proto) @@ -1944,7 +1952,6 @@ class ThreadedTests(unittest.TestCase): - @skip_if_broken_ubuntu_ssl def test_echo(self): """Basic test of an SSL client connecting to a server""" if support.verbose: @@ -2133,9 +2140,14 @@ finally: t.join() - @skip_if_broken_ubuntu_ssl - @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), - "OpenSSL is compiled without SSLv2 support") + @unittest.skipIf(HAVE_SSLv2, "SSLv2 is available in linked OpenSSL") + def test_protocol_sslv2_not_available(self): + if support.verbose: + sys.stdout.write("\n") + try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, False) + + @unittest.skipUnless(HAVE_SSLv2, + "SSLv2 is not available in linked OpenSSL") def test_protocol_sslv2(self): """Connecting to an SSLv2 server with various client options""" if support.verbose: @@ -2157,7 +2169,14 @@ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, client_options=ssl.OP_NO_TLSv1) - @skip_if_broken_ubuntu_ssl + @unittest.skipIf(HAVE_SSLv3, "SSLv23 is available in linked OpenSSL") + def test_protocol_sslv23_not_available(self): + if support.verbose: + sys.stdout.write("\n") + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, False) + + @unittest.skipUnless(HAVE_SSLv3, + "SSLv23 is not available in linked OpenSSL") def test_protocol_sslv23(self): """Connecting to an SSLv23 server with various client options""" if support.verbose: @@ -2196,10 +2215,14 @@ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False, server_options=ssl.OP_NO_TLSv1) + @unittest.skipIf(HAVE_SSLv3, "SSLv3 is available in linked OpenSSL") + def test_protocol_sslv3_not_available(self): + if support.verbose: + sys.stdout.write("\n") + try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, False) - @skip_if_broken_ubuntu_ssl - @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'), - "OpenSSL is compiled without SSLv3 support") + @unittest.skipUnless(HAVE_SSLv3, + "SSLv3 is not available in linked OpenSSL") def test_protocol_sslv3(self): """Connecting to an SSLv3 server with various client options""" if support.verbose: @@ -2217,7 +2240,6 @@ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True, client_options=ssl.OP_NO_SSLv2) - @skip_if_broken_ubuntu_ssl def test_protocol_tlsv1(self): """Connecting to a TLSv1 server with various client options""" if support.verbose: @@ -2232,7 +2254,6 @@ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False, client_options=ssl.OP_NO_TLSv1) - @skip_if_broken_ubuntu_ssl @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"), "TLS version 1.1 not supported.") def test_protocol_tlsv1_1(self): @@ -2253,7 +2274,6 @@ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False) - @skip_if_broken_ubuntu_ssl @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"), "TLS version 1.2 not supported.") def test_protocol_tlsv1_2(self):