mirror of
https://github.com/python/cpython.git
synced 2025-08-02 08:02:56 +00:00
bpo-38275: Skip ssl tests for disabled versions (GH-16386)
test_ssl now handles disabled TLS/SSL versions better. OpenSSL's crypto policy and run-time settings are recognized and tests for disabled versions are skipped. Signed-off-by: Christian Heimes <christian@python.org> https://bugs.python.org/issue38275
This commit is contained in:
parent
64b4a3a2de
commit
df6ac7e2b8
2 changed files with 147 additions and 51 deletions
|
@ -19,6 +19,7 @@ import asyncore
|
||||||
import weakref
|
import weakref
|
||||||
import platform
|
import platform
|
||||||
import sysconfig
|
import sysconfig
|
||||||
|
import functools
|
||||||
try:
|
try:
|
||||||
import ctypes
|
import ctypes
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -146,6 +147,85 @@ OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
|
||||||
OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
|
OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
|
||||||
|
|
||||||
|
|
||||||
|
def has_tls_protocol(protocol):
|
||||||
|
"""Check if a TLS protocol is available and enabled
|
||||||
|
|
||||||
|
:param protocol: enum ssl._SSLMethod member or name
|
||||||
|
:return: bool
|
||||||
|
"""
|
||||||
|
if isinstance(protocol, str):
|
||||||
|
assert protocol.startswith('PROTOCOL_')
|
||||||
|
protocol = getattr(ssl, protocol, None)
|
||||||
|
if protocol is None:
|
||||||
|
return False
|
||||||
|
if protocol in {
|
||||||
|
ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
|
||||||
|
ssl.PROTOCOL_TLS_CLIENT
|
||||||
|
}:
|
||||||
|
# auto-negotiate protocols are always available
|
||||||
|
return True
|
||||||
|
name = protocol.name
|
||||||
|
return has_tls_version(name[len('PROTOCOL_'):])
|
||||||
|
|
||||||
|
|
||||||
|
@functools.lru_cache
|
||||||
|
def has_tls_version(version):
|
||||||
|
"""Check if a TLS/SSL version is enabled
|
||||||
|
|
||||||
|
:param version: TLS version name or ssl.TLSVersion member
|
||||||
|
:return: bool
|
||||||
|
"""
|
||||||
|
if version == "SSLv2":
|
||||||
|
# never supported and not even in TLSVersion enum
|
||||||
|
return False
|
||||||
|
|
||||||
|
if isinstance(version, str):
|
||||||
|
version = ssl.TLSVersion.__members__[version]
|
||||||
|
|
||||||
|
# check compile time flags like ssl.HAS_TLSv1_2
|
||||||
|
if not getattr(ssl, f'HAS_{version.name}'):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# check runtime and dynamic crypto policy settings. A TLS version may
|
||||||
|
# be compiled in but disabled by a policy or config option.
|
||||||
|
ctx = ssl.SSLContext()
|
||||||
|
if (
|
||||||
|
ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
|
||||||
|
version < ctx.minimum_version
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
if (
|
||||||
|
ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
|
||||||
|
version > ctx.maximum_version
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def requires_tls_version(version):
|
||||||
|
"""Decorator to skip tests when a required TLS version is not available
|
||||||
|
|
||||||
|
:param version: TLS version name or ssl.TLSVersion member
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
def decorator(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(*args, **kw):
|
||||||
|
if not has_tls_version(version):
|
||||||
|
raise unittest.SkipTest(f"{version} is not available.")
|
||||||
|
else:
|
||||||
|
return func(*args, **kw)
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
requires_minimum_version = unittest.skipUnless(
|
||||||
|
hasattr(ssl.SSLContext, 'minimum_version'),
|
||||||
|
"required OpenSSL >= 1.1.0g"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def handle_error(prefix):
|
def handle_error(prefix):
|
||||||
exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
|
exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
|
||||||
if support.verbose:
|
if support.verbose:
|
||||||
|
@ -1107,20 +1187,23 @@ class ContextTests(unittest.TestCase):
|
||||||
with self.assertRaises(AttributeError):
|
with self.assertRaises(AttributeError):
|
||||||
ctx.hostname_checks_common_name = True
|
ctx.hostname_checks_common_name = True
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'),
|
@requires_minimum_version
|
||||||
"required OpenSSL 1.1.0g")
|
|
||||||
@unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
|
@unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
|
||||||
def test_min_max_version(self):
|
def test_min_max_version(self):
|
||||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||||
# OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
|
# OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
|
||||||
# Fedora override the setting to TLS 1.0.
|
# Fedora override the setting to TLS 1.0.
|
||||||
|
minimum_range = {
|
||||||
|
# stock OpenSSL
|
||||||
|
ssl.TLSVersion.MINIMUM_SUPPORTED,
|
||||||
|
# Fedora 29 uses TLS 1.0 by default
|
||||||
|
ssl.TLSVersion.TLSv1,
|
||||||
|
# RHEL 8 uses TLS 1.2 by default
|
||||||
|
ssl.TLSVersion.TLSv1_2
|
||||||
|
}
|
||||||
|
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
ctx.minimum_version,
|
ctx.minimum_version, minimum_range
|
||||||
{ssl.TLSVersion.MINIMUM_SUPPORTED,
|
|
||||||
# Fedora 29 uses TLS 1.0 by default
|
|
||||||
ssl.TLSVersion.TLSv1,
|
|
||||||
# RHEL 8 uses TLS 1.2 by default
|
|
||||||
ssl.TLSVersion.TLSv1_2}
|
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
|
ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
|
||||||
|
@ -1166,8 +1249,8 @@ class ContextTests(unittest.TestCase):
|
||||||
|
|
||||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertIn(
|
||||||
ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
|
ctx.minimum_version, minimum_range
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
|
ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
|
||||||
|
@ -2722,6 +2805,8 @@ class ThreadedTests(unittest.TestCase):
|
||||||
for protocol in PROTOCOLS:
|
for protocol in PROTOCOLS:
|
||||||
if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
|
if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
|
||||||
continue
|
continue
|
||||||
|
if not has_tls_protocol(protocol):
|
||||||
|
continue
|
||||||
with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
|
with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
|
||||||
context = ssl.SSLContext(protocol)
|
context = ssl.SSLContext(protocol)
|
||||||
context.load_cert_chain(CERTFILE)
|
context.load_cert_chain(CERTFILE)
|
||||||
|
@ -3013,7 +3098,7 @@ class ThreadedTests(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.fail("Use of invalid cert should have failed!")
|
self.fail("Use of invalid cert should have failed!")
|
||||||
|
|
||||||
@unittest.skipUnless(ssl.HAS_TLSv1_3, "Test needs TLS 1.3")
|
@requires_tls_version('TLSv1_3')
|
||||||
def test_wrong_cert_tls13(self):
|
def test_wrong_cert_tls13(self):
|
||||||
client_context, server_context, hostname = testing_context()
|
client_context, server_context, hostname = testing_context()
|
||||||
# load client cert that is not signed by trusted CA
|
# load client cert that is not signed by trusted CA
|
||||||
|
@ -3108,8 +3193,7 @@ class ThreadedTests(unittest.TestCase):
|
||||||
self.assertIn(msg, repr(e))
|
self.assertIn(msg, repr(e))
|
||||||
self.assertIn('certificate verify failed', repr(e))
|
self.assertIn('certificate verify failed', repr(e))
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
|
@requires_tls_version('SSLv2')
|
||||||
"OpenSSL is compiled without SSLv2 support")
|
|
||||||
def test_protocol_sslv2(self):
|
def test_protocol_sslv2(self):
|
||||||
"""Connecting to an SSLv2 server with various client options"""
|
"""Connecting to an SSLv2 server with various client options"""
|
||||||
if support.verbose:
|
if support.verbose:
|
||||||
|
@ -3118,7 +3202,7 @@ class ThreadedTests(unittest.TestCase):
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
|
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
|
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
|
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv3'):
|
if has_tls_version('SSLv3'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
|
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
|
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
|
||||||
# SSLv23 client with specific SSL options
|
# SSLv23 client with specific SSL options
|
||||||
|
@ -3135,7 +3219,7 @@ class ThreadedTests(unittest.TestCase):
|
||||||
"""Connecting to an SSLv23 server with various client options"""
|
"""Connecting to an SSLv23 server with various client options"""
|
||||||
if support.verbose:
|
if support.verbose:
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv2'):
|
if has_tls_version('SSLv2'):
|
||||||
try:
|
try:
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
|
||||||
except OSError as x:
|
except OSError as x:
|
||||||
|
@ -3144,34 +3228,36 @@ class ThreadedTests(unittest.TestCase):
|
||||||
sys.stdout.write(
|
sys.stdout.write(
|
||||||
" SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
|
" SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
|
||||||
% str(x))
|
% str(x))
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv3'):
|
if has_tls_version('SSLv3'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
|
if has_tls_version('TLSv1'):
|
||||||
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
|
||||||
|
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv3'):
|
if has_tls_version('SSLv3'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
|
if has_tls_version('TLSv1'):
|
||||||
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
|
||||||
|
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv3'):
|
if has_tls_version('SSLv3'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
|
if has_tls_version('TLSv1'):
|
||||||
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
|
||||||
|
|
||||||
# Server with specific SSL options
|
# Server with specific SSL options
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv3'):
|
if has_tls_version('SSLv3'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
|
||||||
server_options=ssl.OP_NO_SSLv3)
|
server_options=ssl.OP_NO_SSLv3)
|
||||||
# Will choose TLSv1
|
# Will choose TLSv1
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
|
||||||
server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
|
server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
|
if has_tls_version('TLSv1'):
|
||||||
server_options=ssl.OP_NO_TLSv1)
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
|
||||||
|
server_options=ssl.OP_NO_TLSv1)
|
||||||
|
|
||||||
|
@requires_tls_version('SSLv3')
|
||||||
@unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
|
|
||||||
"OpenSSL is compiled without SSLv3 support")
|
|
||||||
def test_protocol_sslv3(self):
|
def test_protocol_sslv3(self):
|
||||||
"""Connecting to an SSLv3 server with various client options"""
|
"""Connecting to an SSLv3 server with various client options"""
|
||||||
if support.verbose:
|
if support.verbose:
|
||||||
|
@ -3179,7 +3265,7 @@ class ThreadedTests(unittest.TestCase):
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
|
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
|
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
|
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv2'):
|
if has_tls_version('SSLv2'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
|
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
|
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
|
||||||
client_options=ssl.OP_NO_SSLv3)
|
client_options=ssl.OP_NO_SSLv3)
|
||||||
|
@ -3189,6 +3275,7 @@ class ThreadedTests(unittest.TestCase):
|
||||||
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
|
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
|
||||||
False, client_options=ssl.OP_NO_SSLv2)
|
False, client_options=ssl.OP_NO_SSLv2)
|
||||||
|
|
||||||
|
@requires_tls_version('TLSv1')
|
||||||
def test_protocol_tlsv1(self):
|
def test_protocol_tlsv1(self):
|
||||||
"""Connecting to a TLSv1 server with various client options"""
|
"""Connecting to a TLSv1 server with various client options"""
|
||||||
if support.verbose:
|
if support.verbose:
|
||||||
|
@ -3196,34 +3283,32 @@ class ThreadedTests(unittest.TestCase):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
|
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
|
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
|
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv2'):
|
if has_tls_version('SSLv2'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
|
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv3'):
|
if has_tls_version('SSLv3'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
|
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
|
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
|
||||||
client_options=ssl.OP_NO_TLSv1)
|
client_options=ssl.OP_NO_TLSv1)
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
|
@requires_tls_version('TLSv1_1')
|
||||||
"TLS version 1.1 not supported.")
|
|
||||||
def test_protocol_tlsv1_1(self):
|
def test_protocol_tlsv1_1(self):
|
||||||
"""Connecting to a TLSv1.1 server with various client options.
|
"""Connecting to a TLSv1.1 server with various client options.
|
||||||
Testing against older TLS versions."""
|
Testing against older TLS versions."""
|
||||||
if support.verbose:
|
if support.verbose:
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
|
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv2'):
|
if has_tls_version('SSLv2'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
|
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv3'):
|
if has_tls_version('SSLv3'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
|
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
|
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
|
||||||
client_options=ssl.OP_NO_TLSv1_1)
|
client_options=ssl.OP_NO_TLSv1_1)
|
||||||
|
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
|
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
|
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
|
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
|
@requires_tls_version('TLSv1_2')
|
||||||
"TLS version 1.2 not supported.")
|
|
||||||
def test_protocol_tlsv1_2(self):
|
def test_protocol_tlsv1_2(self):
|
||||||
"""Connecting to a TLSv1.2 server with various client options.
|
"""Connecting to a TLSv1.2 server with various client options.
|
||||||
Testing against older TLS versions."""
|
Testing against older TLS versions."""
|
||||||
|
@ -3232,9 +3317,9 @@ class ThreadedTests(unittest.TestCase):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
|
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
|
||||||
server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
|
server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
|
||||||
client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
|
client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv2'):
|
if has_tls_version('SSLv2'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
|
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
|
||||||
if hasattr(ssl, 'PROTOCOL_SSLv3'):
|
if has_tls_version('SSLv3'):
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
|
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
|
||||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
|
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
|
||||||
client_options=ssl.OP_NO_TLSv1_2)
|
client_options=ssl.OP_NO_TLSv1_2)
|
||||||
|
@ -3677,7 +3762,7 @@ class ThreadedTests(unittest.TestCase):
|
||||||
self.assertIs(s.version(), None)
|
self.assertIs(s.version(), None)
|
||||||
self.assertIs(s._sslobj, None)
|
self.assertIs(s._sslobj, None)
|
||||||
s.connect((HOST, server.port))
|
s.connect((HOST, server.port))
|
||||||
if IS_OPENSSL_1_1_1 and ssl.HAS_TLSv1_3:
|
if IS_OPENSSL_1_1_1 and has_tls_version('TLSv1_3'):
|
||||||
self.assertEqual(s.version(), 'TLSv1.3')
|
self.assertEqual(s.version(), 'TLSv1.3')
|
||||||
elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
|
elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
|
||||||
self.assertEqual(s.version(), 'TLSv1.2')
|
self.assertEqual(s.version(), 'TLSv1.2')
|
||||||
|
@ -3686,8 +3771,7 @@ class ThreadedTests(unittest.TestCase):
|
||||||
self.assertIs(s._sslobj, None)
|
self.assertIs(s._sslobj, None)
|
||||||
self.assertIs(s.version(), None)
|
self.assertIs(s.version(), None)
|
||||||
|
|
||||||
@unittest.skipUnless(ssl.HAS_TLSv1_3,
|
@requires_tls_version('TLSv1_3')
|
||||||
"test requires TLSv1.3 enabled OpenSSL")
|
|
||||||
def test_tls1_3(self):
|
def test_tls1_3(self):
|
||||||
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
|
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
|
||||||
context.load_cert_chain(CERTFILE)
|
context.load_cert_chain(CERTFILE)
|
||||||
|
@ -3704,9 +3788,9 @@ class ThreadedTests(unittest.TestCase):
|
||||||
})
|
})
|
||||||
self.assertEqual(s.version(), 'TLSv1.3')
|
self.assertEqual(s.version(), 'TLSv1.3')
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'),
|
@requires_minimum_version
|
||||||
"required OpenSSL 1.1.0g")
|
@requires_tls_version('TLSv1_2')
|
||||||
def test_min_max_version(self):
|
def test_min_max_version_tlsv1_2(self):
|
||||||
client_context, server_context, hostname = testing_context()
|
client_context, server_context, hostname = testing_context()
|
||||||
# client TLSv1.0 to 1.2
|
# client TLSv1.0 to 1.2
|
||||||
client_context.minimum_version = ssl.TLSVersion.TLSv1
|
client_context.minimum_version = ssl.TLSVersion.TLSv1
|
||||||
|
@ -3721,7 +3805,13 @@ class ThreadedTests(unittest.TestCase):
|
||||||
s.connect((HOST, server.port))
|
s.connect((HOST, server.port))
|
||||||
self.assertEqual(s.version(), 'TLSv1.2')
|
self.assertEqual(s.version(), 'TLSv1.2')
|
||||||
|
|
||||||
|
@requires_minimum_version
|
||||||
|
@requires_tls_version('TLSv1_1')
|
||||||
|
def test_min_max_version_tlsv1_1(self):
|
||||||
|
client_context, server_context, hostname = testing_context()
|
||||||
# client 1.0 to 1.2, server 1.0 to 1.1
|
# client 1.0 to 1.2, server 1.0 to 1.1
|
||||||
|
client_context.minimum_version = ssl.TLSVersion.TLSv1
|
||||||
|
client_context.maximum_version = ssl.TLSVersion.TLSv1_2
|
||||||
server_context.minimum_version = ssl.TLSVersion.TLSv1
|
server_context.minimum_version = ssl.TLSVersion.TLSv1
|
||||||
server_context.maximum_version = ssl.TLSVersion.TLSv1_1
|
server_context.maximum_version = ssl.TLSVersion.TLSv1_1
|
||||||
|
|
||||||
|
@ -3731,6 +3821,10 @@ class ThreadedTests(unittest.TestCase):
|
||||||
s.connect((HOST, server.port))
|
s.connect((HOST, server.port))
|
||||||
self.assertEqual(s.version(), 'TLSv1.1')
|
self.assertEqual(s.version(), 'TLSv1.1')
|
||||||
|
|
||||||
|
@requires_minimum_version
|
||||||
|
@requires_tls_version('TLSv1_2')
|
||||||
|
def test_min_max_version_mismatch(self):
|
||||||
|
client_context, server_context, hostname = testing_context()
|
||||||
# client 1.0, server 1.2 (mismatch)
|
# client 1.0, server 1.2 (mismatch)
|
||||||
server_context.maximum_version = ssl.TLSVersion.TLSv1_2
|
server_context.maximum_version = ssl.TLSVersion.TLSv1_2
|
||||||
server_context.minimum_version = ssl.TLSVersion.TLSv1_2
|
server_context.minimum_version = ssl.TLSVersion.TLSv1_2
|
||||||
|
@ -3743,10 +3837,8 @@ class ThreadedTests(unittest.TestCase):
|
||||||
s.connect((HOST, server.port))
|
s.connect((HOST, server.port))
|
||||||
self.assertIn("alert", str(e.exception))
|
self.assertIn("alert", str(e.exception))
|
||||||
|
|
||||||
|
@requires_minimum_version
|
||||||
@unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'),
|
@requires_tls_version('SSLv3')
|
||||||
"required OpenSSL 1.1.0g")
|
|
||||||
@unittest.skipUnless(ssl.HAS_SSLv3, "requires SSLv3 support")
|
|
||||||
def test_min_max_version_sslv3(self):
|
def test_min_max_version_sslv3(self):
|
||||||
client_context, server_context, hostname = testing_context()
|
client_context, server_context, hostname = testing_context()
|
||||||
server_context.minimum_version = ssl.TLSVersion.SSLv3
|
server_context.minimum_version = ssl.TLSVersion.SSLv3
|
||||||
|
@ -4270,7 +4362,7 @@ class ThreadedTests(unittest.TestCase):
|
||||||
'Session refers to a different SSLContext.')
|
'Session refers to a different SSLContext.')
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(ssl.HAS_TLSv1_3, "Test needs TLS 1.3")
|
@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
|
||||||
class TestPostHandshakeAuth(unittest.TestCase):
|
class TestPostHandshakeAuth(unittest.TestCase):
|
||||||
def test_pha_setter(self):
|
def test_pha_setter(self):
|
||||||
protocols = [
|
protocols = [
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
test_ssl now handles disabled TLS/SSL versions better. OpenSSL's crypto
|
||||||
|
policy and run-time settings are recognized and tests for disabled versions
|
||||||
|
are skipped. Tests also accept more TLS minimum_versions for platforms that
|
||||||
|
override OpenSSL's default with strict settings.
|
Loading…
Add table
Add a link
Reference in a new issue