Commit 2cc0223f authored by Gregory P. Smith's avatar Gregory P. Smith Committed by GitHub

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.
parent 7b3a028c
...@@ -4,6 +4,7 @@ import io ...@@ -4,6 +4,7 @@ import io
import itertools import itertools
import os import os
import array import array
import re
import socket import socket
import threading import threading
...@@ -1619,14 +1620,30 @@ class HTTPSTest(TestCase): ...@@ -1619,14 +1620,30 @@ class HTTPSTest(TestCase):
# We feed the server's cert as a validating cert # We feed the server's cert as a validating cert
import ssl import ssl
support.requires('network') support.requires('network')
with support.transient_internet('self-signed.pythontest.net'): selfsigned_pythontestdotnet = 'self-signed.pythontest.net'
with support.transient_internet(selfsigned_pythontestdotnet):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
self.assertEqual(context.verify_mode, ssl.CERT_REQUIRED) self.assertEqual(context.verify_mode, ssl.CERT_REQUIRED)
self.assertEqual(context.check_hostname, True) self.assertEqual(context.check_hostname, True)
context.load_verify_locations(CERT_selfsigned_pythontestdotnet) context.load_verify_locations(CERT_selfsigned_pythontestdotnet)
h = client.HTTPSConnection('self-signed.pythontest.net', 443, context=context) try:
h.request('GET', '/') h = client.HTTPSConnection(selfsigned_pythontestdotnet, 443,
resp = h.getresponse() context=context)
h.request('GET', '/')
resp = h.getresponse()
except ssl.SSLError as ssl_err:
ssl_err_str = str(ssl_err)
# In the error message of [SSL: CERTIFICATE_VERIFY_FAILED] on
# modern Linux distros (Debian Buster, etc) default OpenSSL
# configurations it'll fail saying "key too weak" until we
# address https://bugs.python.org/issue36816 to use a proper
# key size on self-signed.pythontest.net.
if re.search(r'(?i)key.too.weak', ssl_err_str):
raise unittest.SkipTest(
f'Got {ssl_err_str} trying to connect '
f'to {selfsigned_pythontestdotnet}. '
'See https://bugs.python.org/issue36816.')
raise
server_string = resp.getheader('server') server_string = resp.getheader('server')
resp.close() resp.close()
h.close() h.close()
......
...@@ -6,6 +6,7 @@ import unittest ...@@ -6,6 +6,7 @@ import unittest
import functools import functools
import contextlib import contextlib
import os.path import os.path
import re
import threading import threading
from test import support from test import support
...@@ -21,6 +22,13 @@ except ImportError: ...@@ -21,6 +22,13 @@ except ImportError:
TIMEOUT = 30 TIMEOUT = 30
certfile = os.path.join(os.path.dirname(__file__), 'keycert3.pem') certfile = os.path.join(os.path.dirname(__file__), 'keycert3.pem')
if ssl is not None:
SSLError = ssl.SSLError
else:
class SSLError(Exception):
"""Non-existent exception class when we lack SSL support."""
reason = "This will never be raised."
# TODO: # TODO:
# - test the `file` arg to more commands # - test the `file` arg to more commands
# - test error conditions # - test error conditions
...@@ -261,14 +269,21 @@ class NetworkedNNTPTestsMixin: ...@@ -261,14 +269,21 @@ class NetworkedNNTPTestsMixin:
return False return False
return True return True
with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server: try:
self.assertTrue(is_connected()) with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server:
self.assertTrue(server.help()) self.assertTrue(is_connected())
self.assertFalse(is_connected()) self.assertTrue(server.help())
self.assertFalse(is_connected())
with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server:
server.quit() with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server:
self.assertFalse(is_connected()) server.quit()
self.assertFalse(is_connected())
except SSLError as ssl_err:
# matches "[SSL: DH_KEY_TOO_SMALL] dh key too small"
if re.search(r'(?i)KEY.TOO.SMALL', ssl_err.reason):
raise unittest.SkipTest(f"Got {ssl_err} connecting "
f"to {self.NNTP_HOST!r}")
raise
NetworkedNNTPTestsMixin.wrap_methods() NetworkedNNTPTestsMixin.wrap_methods()
...@@ -294,6 +309,12 @@ class NetworkedNNTPTests(NetworkedNNTPTestsMixin, unittest.TestCase): ...@@ -294,6 +309,12 @@ class NetworkedNNTPTests(NetworkedNNTPTestsMixin, unittest.TestCase):
try: try:
cls.server = cls.NNTP_CLASS(cls.NNTP_HOST, timeout=TIMEOUT, cls.server = cls.NNTP_CLASS(cls.NNTP_HOST, timeout=TIMEOUT,
usenetrc=False) usenetrc=False)
except SSLError as ssl_err:
# matches "[SSL: DH_KEY_TOO_SMALL] dh key too small"
if re.search(r'(?i)KEY.TOO.SMALL', ssl_err.reason):
raise unittest.SkipTest(f"{cls} got {ssl_err} connecting "
f"to {cls.NNTP_HOST!r}")
raise
except EOF_ERRORS: except EOF_ERRORS:
raise unittest.SkipTest(f"{cls} got EOF error on connecting " raise unittest.SkipTest(f"{cls} got EOF error on connecting "
f"to {cls.NNTP_HOST!r}") f"to {cls.NNTP_HOST!r}")
......
Skip httplib and nntplib 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.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment