Skip to content

Commit 8ab624b

Browse files
gpsheadned-deily
authored andcommitted
[3.6] bpo-35925: Skip SSL tests that fail due to weak external certs or old TLS (GH-13124) (GH-13252)
* [3.6] bpo-35925: Skip SSL tests that fail due to weak external certs. (GH-13124) Modern Linux distros such as Debian Buster have default OpenSSL system configurations that reject connections to servers with weak certificates by default. This causes our test suite run with external networking resources enabled to skip these tests when they encounter such a failure. Fixing the network servers is a separate issue.. (cherry picked from commit 2cc0223) Co-authored-by: Gregory P. Smith <[email protected]> * Also skip ssl tests that fail when the system rejects TLSv1. * Remove the test_httplib change; server was updated. self-signed.pythontest.net was updated so the test_httplib change is no longer necessary.
1 parent 3dbc43f commit 8ab624b

File tree

3 files changed

+66
-8
lines changed

3 files changed

+66
-8
lines changed

Lib/test/test_nntplib.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import functools
77
import contextlib
88
import os.path
9+
import re
10+
911
from test import support
1012
from nntplib import NNTP, GroupInfo
1113
import nntplib
@@ -22,6 +24,13 @@
2224
TIMEOUT = 30
2325
certfile = os.path.join(os.path.dirname(__file__), 'keycert3.pem')
2426

27+
if ssl is not None:
28+
SSLError = ssl.SSLError
29+
else:
30+
class SSLError(Exception):
31+
"""Non-existent exception class when we lack SSL support."""
32+
reason = "This will never be raised."
33+
2534
# TODO:
2635
# - test the `file` arg to more commands
2736
# - test error conditions
@@ -262,14 +271,21 @@ def is_connected():
262271
return False
263272
return True
264273

265-
with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server:
266-
self.assertTrue(is_connected())
267-
self.assertTrue(server.help())
268-
self.assertFalse(is_connected())
269-
270-
with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server:
271-
server.quit()
272-
self.assertFalse(is_connected())
274+
try:
275+
with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server:
276+
self.assertTrue(is_connected())
277+
self.assertTrue(server.help())
278+
self.assertFalse(is_connected())
279+
280+
with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server:
281+
server.quit()
282+
self.assertFalse(is_connected())
283+
except SSLError as ssl_err:
284+
# matches "[SSL: DH_KEY_TOO_SMALL] dh key too small"
285+
if re.search(r'(?i)KEY.TOO.SMALL', ssl_err.reason):
286+
raise unittest.SkipTest(f"Got {ssl_err} connecting "
287+
f"to {self.NNTP_HOST!r}")
288+
raise
273289

274290

275291
NetworkedNNTPTestsMixin.wrap_methods()
@@ -290,6 +306,12 @@ def setUpClass(cls):
290306
try:
291307
cls.server = cls.NNTP_CLASS(cls.NNTP_HOST, timeout=TIMEOUT,
292308
usenetrc=False)
309+
except SSLError as ssl_err:
310+
# matches "[SSL: DH_KEY_TOO_SMALL] dh key too small"
311+
if re.search(r'(?i)KEY.TOO.SMALL', ssl_err.reason):
312+
raise unittest.SkipTest(f"{cls} got {ssl_err} connecting "
313+
f"to {cls.NNTP_HOST!r}")
314+
raise
293315
except EOFError:
294316
raise unittest.SkipTest(f"{cls} got EOF error on connecting "
295317
f"to {cls.NNTP_HOST!r}")

Lib/test/test_ssl.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import asyncore
1818
import weakref
1919
import platform
20+
import re
2021
import functools
2122
try:
2223
import ctypes
@@ -145,6 +146,38 @@ def f(*args, **kwargs):
145146
else:
146147
return func
147148

149+
def skip_if_openssl_cnf_minprotocol_gt_tls1(func):
150+
"""Skip a test if the OpenSSL config MinProtocol is > TLSv1.
151+
152+
OS distros with an /etc/ssl/openssl.cnf and MinProtocol set often do so to
153+
require TLSv1.2 or higher (Debian Buster). Some of our tests for older
154+
protocol versions will fail under such a config.
155+
156+
Alternative workaround: Run this test in a process with
157+
OPENSSL_CONF=/dev/null in the environment.
158+
"""
159+
@functools.wraps(func)
160+
def f(*args, **kwargs):
161+
openssl_cnf = os.environ.get("OPENSSL_CONF", "/etc/ssl/openssl.cnf")
162+
try:
163+
with open(openssl_cnf, "r") as config:
164+
for line in config:
165+
match = re.match(r"MinProtocol\s*=\s*(TLSv\d+\S*)", line)
166+
if match:
167+
tls_ver = match.group(1)
168+
if tls_ver > "TLSv1":
169+
raise unittest.SkipTest(
170+
"%s has MinProtocol = %s which is > TLSv1." %
171+
(openssl_cnf, tls_ver))
172+
except (EnvironmentError, UnicodeDecodeError) as err:
173+
# no config file found, etc.
174+
if support.verbose:
175+
sys.stdout.write("\n Could not scan %s for MinProtocol: %s\n"
176+
% (openssl_cnf, err))
177+
return func(*args, **kwargs)
178+
return f
179+
180+
148181
needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
149182

150183

@@ -2629,6 +2662,7 @@ def test_protocol_sslv2(self):
26292662
client_options=ssl.OP_NO_TLSv1)
26302663

26312664
@skip_if_broken_ubuntu_ssl
2665+
@skip_if_openssl_cnf_minprotocol_gt_tls1
26322666
def test_protocol_sslv23(self):
26332667
"""Connecting to an SSLv23 server with various client options"""
26342668
if support.verbose:
@@ -2706,6 +2740,7 @@ def test_protocol_tlsv1(self):
27062740
@skip_if_broken_ubuntu_ssl
27072741
@unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
27082742
"TLS version 1.1 not supported.")
2743+
@skip_if_openssl_cnf_minprotocol_gt_tls1
27092744
def test_protocol_tlsv1_1(self):
27102745
"""Connecting to a TLSv1.1 server with various client options.
27112746
Testing against older TLS versions."""
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Skip specific nntplib and ssl networking tests when they would otherwise fail due to a modern OS or distro with a default OpenSSL policy of rejecting connections to servers with weak certificates or disabling TLS below TLSv1.2.

0 commit comments

Comments
 (0)