Skip to content

Commit d37b74f

Browse files
authored
bpo-43669: More test_ssl cleanups (GH-25470)
Signed-off-by: Christian Heimes <[email protected]>
1 parent 2875c60 commit d37b74f

File tree

1 file changed

+21
-78
lines changed

1 file changed

+21
-78
lines changed

Lib/test/test_ssl.py

Lines changed: 21 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import socket
1313
import select
1414
import time
15-
import datetime
1615
import gc
1716
import os
1817
import errno
@@ -39,9 +38,7 @@
3938

4039
PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
4140
HOST = socket_helper.HOST
42-
IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
43-
IS_OPENSSL_1_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1)
44-
IS_OPENSSL_3_0_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
41+
IS_OPENSSL_3_0_0 = ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
4542
PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
4643

4744
PROTOCOL_TO_TLS_VERSION = {}
@@ -258,53 +255,18 @@ def wrapper(*args, **kw):
258255
return decorator
259256

260257

261-
requires_minimum_version = unittest.skipUnless(
262-
hasattr(ssl.SSLContext, 'minimum_version'),
263-
"required OpenSSL >= 1.1.0g"
264-
)
265-
266-
267258
def handle_error(prefix):
268259
exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
269260
if support.verbose:
270261
sys.stdout.write(prefix + exc_format)
271262

272-
def _have_secp_curves():
273-
if not ssl.HAS_ECDH:
274-
return False
275-
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
276-
try:
277-
ctx.set_ecdh_curve("secp384r1")
278-
except ValueError:
279-
return False
280-
else:
281-
return True
282-
283-
284-
HAVE_SECP_CURVES = _have_secp_curves()
285-
286263

287264
def utc_offset(): #NOTE: ignore issues like #1647654
288265
# local time = utc time + utc offset
289266
if time.daylight and time.localtime().tm_isdst > 0:
290267
return -time.altzone # seconds
291268
return -time.timezone
292269

293-
def asn1time(cert_time):
294-
# Some versions of OpenSSL ignore seconds, see #18207
295-
# 0.9.8.i
296-
if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
297-
fmt = "%b %d %H:%M:%S %Y GMT"
298-
dt = datetime.datetime.strptime(cert_time, fmt)
299-
dt = dt.replace(second=0)
300-
cert_time = dt.strftime(fmt)
301-
# %d adds leading zero but ASN1_TIME_print() uses leading space
302-
if cert_time[4] == "0":
303-
cert_time = cert_time[:4] + " " + cert_time[5:]
304-
305-
return cert_time
306-
307-
needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
308270

309271
ignore_deprecation = warnings_helper.ignore_warnings(
310272
category=DeprecationWarning
@@ -365,11 +327,12 @@ def test_constants(self):
365327
ssl.CERT_REQUIRED
366328
ssl.OP_CIPHER_SERVER_PREFERENCE
367329
ssl.OP_SINGLE_DH_USE
368-
if ssl.HAS_ECDH:
369-
ssl.OP_SINGLE_ECDH_USE
330+
ssl.OP_SINGLE_ECDH_USE
370331
ssl.OP_NO_COMPRESSION
371-
self.assertIn(ssl.HAS_SNI, {True, False})
372-
self.assertIn(ssl.HAS_ECDH, {True, False})
332+
self.assertEqual(ssl.HAS_SNI, True)
333+
self.assertEqual(ssl.HAS_ECDH, True)
334+
self.assertEqual(ssl.HAS_TLSv1_2, True)
335+
self.assertEqual(ssl.HAS_TLSv1_3, True)
373336
ssl.OP_NO_SSLv2
374337
ssl.OP_NO_SSLv3
375338
ssl.OP_NO_TLSv1
@@ -537,8 +500,8 @@ def test_openssl_version(self):
537500
self.assertIsInstance(t, tuple)
538501
self.assertIsInstance(s, str)
539502
# Some sanity checks follow
540-
# >= 0.9
541-
self.assertGreaterEqual(n, 0x900000)
503+
# >= 1.1.1
504+
self.assertGreaterEqual(n, 0x10101000)
542505
# < 4.0
543506
self.assertLess(n, 0x40000000)
544507
major, minor, fix, patch, status = t
@@ -552,13 +515,13 @@ def test_openssl_version(self):
552515
self.assertLessEqual(patch, 63)
553516
self.assertGreaterEqual(status, 0)
554517
self.assertLessEqual(status, 15)
555-
# Version string as returned by {Open,Libre}SSL, the format might change
556-
if IS_LIBRESSL:
557-
self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
558-
(s, t, hex(n)))
559-
else:
560-
self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
561-
(s, t, hex(n)))
518+
519+
libressl_ver = f"LibreSSL {major:d}"
520+
openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}"
521+
self.assertTrue(
522+
s.startswith((openssl_ver, libressl_ver)),
523+
(s, t, hex(n))
524+
)
562525

563526
@support.cpython_only
564527
def test_refcycle(self):
@@ -1196,8 +1159,6 @@ def test_hostname_checks_common_name(self):
11961159
with self.assertRaises(AttributeError):
11971160
ctx.hostname_checks_common_name = True
11981161

1199-
@requires_minimum_version
1200-
@unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
12011162
@ignore_deprecation
12021163
def test_min_max_version(self):
12031164
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
@@ -1523,7 +1484,6 @@ def test_set_ecdh_curve(self):
15231484
self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
15241485
self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
15251486

1526-
@needs_sni
15271487
def test_sni_callback(self):
15281488
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
15291489

@@ -1538,7 +1498,6 @@ def dummycallback(sock, servername, ctx):
15381498
ctx.set_servername_callback(None)
15391499
ctx.set_servername_callback(dummycallback)
15401500

1541-
@needs_sni
15421501
def test_sni_callback_refcycle(self):
15431502
# Reference cycles through the servername callback are detected
15441503
# and cleared.
@@ -1578,8 +1537,8 @@ def test_get_ca_certs(self):
15781537
(('organizationalUnitName', 'http://www.cacert.org'),),
15791538
(('commonName', 'CA Cert Signing Authority'),),
15801539
(('emailAddress', '[email protected]'),)),
1581-
'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1582-
'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1540+
'notAfter': 'Mar 29 12:29:49 2033 GMT',
1541+
'notBefore': 'Mar 30 12:29:49 2003 GMT',
15831542
'serialNumber': '00',
15841543
'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
15851544
'subject': ((('organizationName', 'Root CA'),),
@@ -1609,7 +1568,6 @@ def test_load_default_certs(self):
16091568
self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
16101569

16111570
@unittest.skipIf(sys.platform == "win32", "not-Windows specific")
1612-
@unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
16131571
def test_load_default_certs_env(self):
16141572
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
16151573
with os_helper.EnvironmentVarGuard() as env:
@@ -2145,7 +2103,6 @@ def test_non_blocking_handshake(self):
21452103
def test_get_server_certificate(self):
21462104
_test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
21472105

2148-
@needs_sni
21492106
def test_get_server_certificate_sni(self):
21502107
host, port = self.server_addr
21512108
server_names = []
@@ -2198,7 +2155,6 @@ def test_get_ca_certs_capath(self):
21982155
self.assertTrue(cert)
21992156
self.assertEqual(len(ctx.get_ca_certs()), 1)
22002157

2201-
@needs_sni
22022158
def test_context_setget(self):
22032159
# Check that the context of a connected socket can be replaced.
22042160
ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
@@ -3863,7 +3819,6 @@ def test_tls1_3(self):
38633819
})
38643820
self.assertEqual(s.version(), 'TLSv1.3')
38653821

3866-
@requires_minimum_version
38673822
@requires_tls_version('TLSv1_2')
38683823
@requires_tls_version('TLSv1')
38693824
@ignore_deprecation
@@ -3882,7 +3837,6 @@ def test_min_max_version_tlsv1_2(self):
38823837
s.connect((HOST, server.port))
38833838
self.assertEqual(s.version(), 'TLSv1.2')
38843839

3885-
@requires_minimum_version
38863840
@requires_tls_version('TLSv1_1')
38873841
@ignore_deprecation
38883842
def test_min_max_version_tlsv1_1(self):
@@ -3900,7 +3854,6 @@ def test_min_max_version_tlsv1_1(self):
39003854
s.connect((HOST, server.port))
39013855
self.assertEqual(s.version(), 'TLSv1.1')
39023856

3903-
@requires_minimum_version
39043857
@requires_tls_version('TLSv1_2')
39053858
@requires_tls_version('TLSv1')
39063859
@ignore_deprecation
@@ -3920,7 +3873,6 @@ def test_min_max_version_mismatch(self):
39203873
s.connect((HOST, server.port))
39213874
self.assertIn("alert", str(e.exception))
39223875

3923-
@requires_minimum_version
39243876
@requires_tls_version('SSLv3')
39253877
def test_min_max_version_sslv3(self):
39263878
client_context, server_context, hostname = testing_context()
@@ -3935,7 +3887,6 @@ def test_min_max_version_sslv3(self):
39353887
s.connect((HOST, server.port))
39363888
self.assertEqual(s.version(), 'SSLv3')
39373889

3938-
@unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
39393890
def test_default_ecdh_curve(self):
39403891
# Issue #21015: elliptic curve-based Diffie Hellman key exchange
39413892
# should be enabled by default on SSL contexts.
@@ -4050,15 +4001,13 @@ def test_dh_params(self):
40504001
if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
40514002
self.fail("Non-DH cipher: " + cipher[0])
40524003

4053-
@unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
4054-
@unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
40554004
def test_ecdh_curve(self):
40564005
# server secp384r1, client auto
40574006
client_context, server_context, hostname = testing_context()
40584007

40594008
server_context.set_ecdh_curve("secp384r1")
40604009
server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4061-
server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4010+
server_context.minimum_version = ssl.TLSVersion.TLSv1_2
40624011
stats = server_params_test(client_context, server_context,
40634012
chatty=True, connectionchatty=True,
40644013
sni_name=hostname)
@@ -4067,7 +4016,7 @@ def test_ecdh_curve(self):
40674016
client_context, server_context, hostname = testing_context()
40684017
client_context.set_ecdh_curve("secp384r1")
40694018
server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4070-
server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4019+
server_context.minimum_version = ssl.TLSVersion.TLSv1_2
40714020
stats = server_params_test(client_context, server_context,
40724021
chatty=True, connectionchatty=True,
40734022
sni_name=hostname)
@@ -4077,13 +4026,11 @@ def test_ecdh_curve(self):
40774026
client_context.set_ecdh_curve("prime256v1")
40784027
server_context.set_ecdh_curve("secp384r1")
40794028
server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4080-
server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4081-
try:
4029+
server_context.minimum_version = ssl.TLSVersion.TLSv1_2
4030+
with self.assertRaises(ssl.SSLError):
40824031
server_params_test(client_context, server_context,
40834032
chatty=True, connectionchatty=True,
40844033
sni_name=hostname)
4085-
except ssl.SSLError:
4086-
self.fail("mismatch curve did not fail")
40874034

40884035
def test_selected_alpn_protocol(self):
40894036
# selected_alpn_protocol() is None unless ALPN is used.
@@ -4152,7 +4099,6 @@ def check_common_name(self, stats, name):
41524099
cert = stats['peercert']
41534100
self.assertIn((('commonName', name),), cert['subject'])
41544101

4155-
@needs_sni
41564102
def test_sni_callback(self):
41574103
calls = []
41584104
server_context, other_context, client_context = self.sni_contexts()
@@ -4193,7 +4139,6 @@ def servername_cb(ssl_sock, server_name, initial_context):
41934139
self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
41944140
self.assertEqual(calls, [])
41954141

4196-
@needs_sni
41974142
def test_sni_callback_alert(self):
41984143
# Returning a TLS alert is reflected to the connecting client
41994144
server_context, other_context, client_context = self.sni_contexts()
@@ -4207,7 +4152,6 @@ def cb_returning_alert(ssl_sock, server_name, initial_context):
42074152
sni_name='supermessage')
42084153
self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
42094154

4210-
@needs_sni
42114155
def test_sni_callback_raising(self):
42124156
# Raising fails the connection with a TLS handshake failure alert.
42134157
server_context, other_context, client_context = self.sni_contexts()
@@ -4226,7 +4170,6 @@ def cb_raising(ssl_sock, server_name, initial_context):
42264170
'SSLV3_ALERT_HANDSHAKE_FAILURE')
42274171
self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
42284172

4229-
@needs_sni
42304173
def test_sni_callback_wrong_return_type(self):
42314174
# Returning the wrong return type terminates the TLS connection
42324175
# with an internal error alert.

0 commit comments

Comments
 (0)