blob: ae66c3e7d4a56c55161206a7585c50f5bc8c1f29 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Christian Heimesc7f70692019-05-31 11:44:05 +02005import unittest.mock
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Hai Shia7f5d932020-08-04 00:41:24 +08007from test.support import import_helper
8from test.support import os_helper
Serhiy Storchaka16994912020-04-25 10:06:29 +03009from test.support import socket_helper
Hai Shie80697d2020-05-28 06:10:27 +080010from test.support import threading_helper
Hai Shia7f5d932020-08-04 00:41:24 +080011from test.support import warnings_helper
Thomas Woutersed03b412007-08-28 21:37:11 +000012import socket
Bill Janssen6e027db2007-11-15 22:23:56 +000013import select
Thomas Woutersed03b412007-08-28 21:37:11 +000014import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000015import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000016import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000017import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000018import pprint
Antoine Pitrou803e6d62010-10-13 10:36:15 +000019import urllib.request
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020020import threading
Thomas Woutersed03b412007-08-28 21:37:11 +000021import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000022import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000023import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000024import platform
Christian Heimes892d66e2018-01-29 14:10:18 +010025import sysconfig
Christian Heimesdf6ac7e2019-09-26 17:02:59 +020026import functools
Christian Heimes888bbdc2017-09-07 14:18:21 -070027try:
28 import ctypes
29except ImportError:
30 ctypes = None
Thomas Woutersed03b412007-08-28 21:37:11 +000031
Hai Shia7f5d932020-08-04 00:41:24 +080032ssl = import_helper.import_module("ssl")
Antoine Pitrou05d936d2010-10-13 11:38:36 +000033
Victor Stinner8f4ef3b2019-07-01 18:28:25 +020034from ssl import TLSVersion, _TLSContentType, _TLSMessageType
Martin Panter3840b2a2016-03-27 01:53:46 +000035
Paul Monsonf3550692019-06-19 13:09:54 -070036Py_DEBUG = hasattr(sys, 'gettotalrefcount')
37Py_DEBUG_WIN32 = Py_DEBUG and sys.platform == 'win32'
38
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010039PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Serhiy Storchaka16994912020-04-25 10:06:29 +030040HOST = socket_helper.HOST
Christian Heimesd37b74f2021-04-19 08:31:29 +020041IS_OPENSSL_3_0_0 = ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
Christian Heimes892d66e2018-01-29 14:10:18 +010042PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
Antoine Pitrou152efa22010-05-16 18:19:27 +000043
Victor Stinner3ef63442019-02-19 18:06:03 +010044PROTOCOL_TO_TLS_VERSION = {}
45for proto, ver in (
46 ("PROTOCOL_SSLv23", "SSLv3"),
47 ("PROTOCOL_TLSv1", "TLSv1"),
48 ("PROTOCOL_TLSv1_1", "TLSv1_1"),
49):
50 try:
51 proto = getattr(ssl, proto)
52 ver = getattr(ssl.TLSVersion, ver)
53 except AttributeError:
54 continue
55 PROTOCOL_TO_TLS_VERSION[proto] = ver
56
Christian Heimesefff7062013-11-21 03:35:02 +010057def data_file(*name):
58 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000059
Antoine Pitrou81564092010-10-08 23:06:24 +000060# The custom key and certificate files used in test_ssl are generated
61# using Lib/test/make_ssl_certs.py.
62# Other certificates are simply fetched from the Internet servers they
63# are meant to authenticate.
64
Antoine Pitrou152efa22010-05-16 18:19:27 +000065CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000066BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000067ONLYCERT = data_file("ssl_cert.pem")
68ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000069BYTES_ONLYCERT = os.fsencode(ONLYCERT)
70BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020071CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
72ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
73KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000074CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000075BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010076CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
77CAFILE_CACERT = data_file("capath", "5ed36f99.0")
78
Christian Heimesbd5c7d22018-01-20 15:16:30 +010079CERTFILE_INFO = {
80 'issuer': ((('countryName', 'XY'),),
81 (('localityName', 'Castle Anthrax'),),
82 (('organizationName', 'Python Software Foundation'),),
83 (('commonName', 'localhost'),)),
Christian Heimese6dac002018-08-30 07:25:49 +020084 'notAfter': 'Aug 26 14:23:15 2028 GMT',
85 'notBefore': 'Aug 29 14:23:15 2018 GMT',
86 'serialNumber': '98A7CF88C74A32ED',
Christian Heimesbd5c7d22018-01-20 15:16:30 +010087 'subject': ((('countryName', 'XY'),),
88 (('localityName', 'Castle Anthrax'),),
89 (('organizationName', 'Python Software Foundation'),),
90 (('commonName', 'localhost'),)),
91 'subjectAltName': (('DNS', 'localhost'),),
92 'version': 3
93}
Antoine Pitrou152efa22010-05-16 18:19:27 +000094
Christian Heimes22587792013-11-21 23:56:13 +010095# empty CRL
96CRLFILE = data_file("revocation.crl")
97
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010098# Two keys and certs signed by the same CA (for SNI tests)
99SIGNED_CERTFILE = data_file("keycert3.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200100SIGNED_CERTFILE_HOSTNAME = 'localhost'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100101
102SIGNED_CERTFILE_INFO = {
103 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
104 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
105 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
106 'issuer': ((('countryName', 'XY'),),
107 (('organizationName', 'Python Software Foundation CA'),),
108 (('commonName', 'our-ca-server'),)),
Christian Heimesb467d9a2021-04-17 10:07:19 +0200109 'notAfter': 'Oct 28 14:23:16 2037 GMT',
Christian Heimese6dac002018-08-30 07:25:49 +0200110 'notBefore': 'Aug 29 14:23:16 2018 GMT',
111 'serialNumber': 'CB2D80995A69525C',
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100112 'subject': ((('countryName', 'XY'),),
113 (('localityName', 'Castle Anthrax'),),
114 (('organizationName', 'Python Software Foundation'),),
115 (('commonName', 'localhost'),)),
116 'subjectAltName': (('DNS', 'localhost'),),
117 'version': 3
118}
119
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100120SIGNED_CERTFILE2 = data_file("keycert4.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200121SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100122SIGNED_CERTFILE_ECC = data_file("keycertecc.pem")
123SIGNED_CERTFILE_ECC_HOSTNAME = 'localhost-ecc'
124
Martin Panter3840b2a2016-03-27 01:53:46 +0000125# Same certificate as pycacert.pem, but without extra text in file
126SIGNING_CA = data_file("capath", "ceff1710.0")
Christian Heimes1c03abd2016-09-06 23:25:35 +0200127# cert with all kinds of subject alt names
128ALLSANFILE = data_file("allsans.pem")
Christian Heimes66e57422018-01-29 14:25:13 +0100129IDNSANSFILE = data_file("idnsans.pem")
Christian Heimesb467d9a2021-04-17 10:07:19 +0200130NOSANFILE = data_file("nosan.pem")
131NOSAN_HOSTNAME = 'localhost'
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100132
Martin Panter3d81d932016-01-14 09:36:00 +0000133REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +0000134
135EMPTYCERT = data_file("nullcert.pem")
136BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +0000137NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000138BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200139NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +0200140NULLBYTECERT = data_file("nullbytecert.pem")
Christian Heimesa37f5242019-01-15 23:47:42 +0100141TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000142
Christian Heimes88bfd0b2018-08-14 12:54:19 +0200143DHFILE = data_file("ffdh3072.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100144BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +0000145
Christian Heimes358cfd42016-09-10 22:43:48 +0200146# Not defined in all versions of OpenSSL
147OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
148OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
149OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
150OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
Christian Heimes05d9fe32018-02-27 08:55:39 +0100151OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
Christian Heimes6f37ebc2021-04-09 17:59:21 +0200152OP_IGNORE_UNEXPECTED_EOF = getattr(ssl, "OP_IGNORE_UNEXPECTED_EOF", 0)
Christian Heimes358cfd42016-09-10 22:43:48 +0200153
Christian Heimesf6c6b582021-03-18 23:06:50 +0100154# Ubuntu has patched OpenSSL and changed behavior of security level 2
155# see https://bugs.python.org/issue41561#msg389003
156def is_ubuntu():
157 try:
158 # Assume that any references of "ubuntu" implies Ubuntu-like distro
159 # The workaround is not required for 18.04, but doesn't hurt either.
160 with open("/etc/os-release", encoding="utf-8") as f:
161 return "ubuntu" in f.read()
162 except FileNotFoundError:
163 return False
164
165if is_ubuntu():
166 def seclevel_workaround(*ctxs):
167 """"Lower security level to '1' and allow all ciphers for TLS 1.0/1"""
168 for ctx in ctxs:
Christian Heimes34477502021-04-12 12:00:38 +0200169 if (
170 hasattr(ctx, "minimum_version") and
171 ctx.minimum_version <= ssl.TLSVersion.TLSv1_1
172 ):
Christian Heimesf6c6b582021-03-18 23:06:50 +0100173 ctx.set_ciphers("@SECLEVEL=1:ALL")
174else:
175 def seclevel_workaround(*ctxs):
176 pass
177
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100178
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200179def has_tls_protocol(protocol):
180 """Check if a TLS protocol is available and enabled
181
182 :param protocol: enum ssl._SSLMethod member or name
183 :return: bool
184 """
185 if isinstance(protocol, str):
186 assert protocol.startswith('PROTOCOL_')
187 protocol = getattr(ssl, protocol, None)
188 if protocol is None:
189 return False
190 if protocol in {
191 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
192 ssl.PROTOCOL_TLS_CLIENT
193 }:
194 # auto-negotiate protocols are always available
195 return True
196 name = protocol.name
197 return has_tls_version(name[len('PROTOCOL_'):])
198
199
200@functools.lru_cache
201def has_tls_version(version):
202 """Check if a TLS/SSL version is enabled
203
204 :param version: TLS version name or ssl.TLSVersion member
205 :return: bool
206 """
207 if version == "SSLv2":
208 # never supported and not even in TLSVersion enum
209 return False
210
211 if isinstance(version, str):
212 version = ssl.TLSVersion.__members__[version]
213
214 # check compile time flags like ssl.HAS_TLSv1_2
215 if not getattr(ssl, f'HAS_{version.name}'):
216 return False
217
Christian Heimes5151d642021-04-09 15:43:06 +0200218 if IS_OPENSSL_3_0_0 and version < ssl.TLSVersion.TLSv1_2:
219 # bpo43791: 3.0.0-alpha14 fails with TLSV1_ALERT_INTERNAL_ERROR
220 return False
221
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200222 # check runtime and dynamic crypto policy settings. A TLS version may
223 # be compiled in but disabled by a policy or config option.
Christian Heimes2875c602021-04-19 07:27:10 +0200224 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200225 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200226 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200227 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
228 version < ctx.minimum_version
229 ):
230 return False
231 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200232 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200233 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
234 version > ctx.maximum_version
235 ):
236 return False
237
238 return True
239
240
241def requires_tls_version(version):
242 """Decorator to skip tests when a required TLS version is not available
243
244 :param version: TLS version name or ssl.TLSVersion member
245 :return:
246 """
247 def decorator(func):
248 @functools.wraps(func)
249 def wrapper(*args, **kw):
250 if not has_tls_version(version):
251 raise unittest.SkipTest(f"{version} is not available.")
252 else:
253 return func(*args, **kw)
254 return wrapper
255 return decorator
256
257
Thomas Woutersed03b412007-08-28 21:37:11 +0000258def handle_error(prefix):
259 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000260 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000261 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000262
Christian Heimesb7b92252018-02-25 09:49:31 +0100263
Antoine Pitrouc695c952014-04-28 20:57:36 +0200264def utc_offset(): #NOTE: ignore issues like #1647654
265 # local time = utc time + utc offset
266 if time.daylight and time.localtime().tm_isdst > 0:
267 return -time.altzone # seconds
268 return -time.timezone
269
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100270
Christian Heimes2875c602021-04-19 07:27:10 +0200271ignore_deprecation = warnings_helper.ignore_warnings(
272 category=DeprecationWarning
273)
Antoine Pitrou23df4832010-08-04 17:14:06 +0000274
Christian Heimes2875c602021-04-19 07:27:10 +0200275
276def test_wrap_socket(sock, *,
Christian Heimesd0486372016-09-10 23:23:33 +0200277 cert_reqs=ssl.CERT_NONE, ca_certs=None,
278 ciphers=None, certfile=None, keyfile=None,
279 **kwargs):
Christian Heimes2875c602021-04-19 07:27:10 +0200280 if not kwargs.get("server_side"):
281 kwargs["server_hostname"] = SIGNED_CERTFILE_HOSTNAME
282 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
283 else:
284 context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimesd0486372016-09-10 23:23:33 +0200285 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200286 if cert_reqs == ssl.CERT_NONE:
287 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200288 context.verify_mode = cert_reqs
289 if ca_certs is not None:
290 context.load_verify_locations(ca_certs)
291 if certfile is not None or keyfile is not None:
292 context.load_cert_chain(certfile, keyfile)
293 if ciphers is not None:
294 context.set_ciphers(ciphers)
295 return context.wrap_socket(sock, **kwargs)
296
Christian Heimesa170fa12017-09-15 20:27:30 +0200297
298def testing_context(server_cert=SIGNED_CERTFILE):
299 """Create context
300
301 client_context, server_context, hostname = testing_context()
302 """
303 if server_cert == SIGNED_CERTFILE:
304 hostname = SIGNED_CERTFILE_HOSTNAME
305 elif server_cert == SIGNED_CERTFILE2:
306 hostname = SIGNED_CERTFILE2_HOSTNAME
Christian Heimesb467d9a2021-04-17 10:07:19 +0200307 elif server_cert == NOSANFILE:
308 hostname = NOSAN_HOSTNAME
Christian Heimesa170fa12017-09-15 20:27:30 +0200309 else:
310 raise ValueError(server_cert)
311
312 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
313 client_context.load_verify_locations(SIGNING_CA)
314
315 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
316 server_context.load_cert_chain(server_cert)
Christian Heimes9fb051f2018-09-23 08:32:31 +0200317 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200318
319 return client_context, server_context, hostname
320
321
Antoine Pitrou152efa22010-05-16 18:19:27 +0000322class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000323
Antoine Pitrou480a1242010-04-28 21:37:09 +0000324 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000325 ssl.CERT_NONE
326 ssl.CERT_OPTIONAL
327 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100328 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100329 ssl.OP_SINGLE_DH_USE
Christian Heimesd37b74f2021-04-19 08:31:29 +0200330 ssl.OP_SINGLE_ECDH_USE
Christian Heimes39258d32021-04-17 11:36:35 +0200331 ssl.OP_NO_COMPRESSION
Christian Heimesd37b74f2021-04-19 08:31:29 +0200332 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)
Christian Heimescb5b68a2017-09-07 18:07:00 -0700336 ssl.OP_NO_SSLv2
337 ssl.OP_NO_SSLv3
338 ssl.OP_NO_TLSv1
339 ssl.OP_NO_TLSv1_3
Christian Heimes39258d32021-04-17 11:36:35 +0200340 ssl.OP_NO_TLSv1_1
341 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200342 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000343
Christian Heimes9d50ab52018-02-27 10:17:30 +0100344 def test_private_init(self):
345 with self.assertRaisesRegex(TypeError, "public constructor"):
346 with socket.socket() as s:
347 ssl.SSLSocket(s)
348
Antoine Pitrou172f0252014-04-18 20:33:08 +0200349 def test_str_for_enums(self):
350 # Make sure that the PROTOCOL_* constants have enum-like string
351 # reprs.
Christian Heimes2875c602021-04-19 07:27:10 +0200352 proto = ssl.PROTOCOL_TLS_CLIENT
353 self.assertEqual(str(proto), 'PROTOCOL_TLS_CLIENT')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200354 ctx = ssl.SSLContext(proto)
355 self.assertIs(ctx.protocol, proto)
356
Antoine Pitrou480a1242010-04-28 21:37:09 +0000357 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000358 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000359 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000360 sys.stdout.write("\n RAND_status is %d (%s)\n"
361 % (v, (v and "sufficient randomness") or
362 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200363
Christian Heimes2875c602021-04-19 07:27:10 +0200364 with warnings_helper.check_warnings():
365 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200366 self.assertEqual(len(data), 16)
367 self.assertEqual(is_cryptographic, v == 1)
368 if v:
369 data = ssl.RAND_bytes(16)
370 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200371 else:
372 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200373
Victor Stinner1e81a392013-12-19 16:47:04 +0100374 # negative num is invalid
375 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
Christian Heimes2875c602021-04-19 07:27:10 +0200376 with warnings_helper.check_warnings():
377 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
Victor Stinner1e81a392013-12-19 16:47:04 +0100378
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000379 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200380 ssl.RAND_add(b"this is a random bytes object", 75.0)
381 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000382
Antoine Pitrou480a1242010-04-28 21:37:09 +0000383 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000384 # note that this uses an 'unofficial' function in _ssl.c,
385 # provided solely for this test, to exercise the certificate
386 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100387 self.assertEqual(
388 ssl._ssl._test_decode_cert(CERTFILE),
389 CERTFILE_INFO
390 )
391 self.assertEqual(
392 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
393 SIGNED_CERTFILE_INFO
394 )
395
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200396 # Issue #13034: the subjectAltName in some certificates
397 # (notably projects.developer.nokia.com:443) wasn't parsed
398 p = ssl._ssl._test_decode_cert(NOKIACERT)
399 if support.verbose:
400 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
401 self.assertEqual(p['subjectAltName'],
402 (('DNS', 'projects.developer.nokia.com'),
403 ('DNS', 'projects.forum.nokia.com'))
404 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100405 # extra OCSP and AIA fields
406 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
407 self.assertEqual(p['caIssuers'],
408 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
409 self.assertEqual(p['crlDistributionPoints'],
410 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000411
Christian Heimesa37f5242019-01-15 23:47:42 +0100412 def test_parse_cert_CVE_2019_5010(self):
413 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
414 if support.verbose:
415 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
416 self.assertEqual(
417 p,
418 {
419 'issuer': (
420 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
421 'notAfter': 'Jun 14 18:00:58 2028 GMT',
422 'notBefore': 'Jun 18 18:00:58 2018 GMT',
423 'serialNumber': '02',
424 'subject': ((('countryName', 'UK'),),
425 (('commonName',
426 'codenomicon-vm-2.test.lal.cisco.com'),)),
427 'subjectAltName': (
428 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
429 'version': 3
430 }
431 )
432
Christian Heimes824f7f32013-08-17 00:54:47 +0200433 def test_parse_cert_CVE_2013_4238(self):
434 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
435 if support.verbose:
436 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
437 subject = ((('countryName', 'US'),),
438 (('stateOrProvinceName', 'Oregon'),),
439 (('localityName', 'Beaverton'),),
440 (('organizationName', 'Python Software Foundation'),),
441 (('organizationalUnitName', 'Python Core Development'),),
442 (('commonName', 'null.python.org\x00example.org'),),
443 (('emailAddress', 'python-dev@python.org'),))
444 self.assertEqual(p['subject'], subject)
445 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200446 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
447 san = (('DNS', 'altnull.python.org\x00example.com'),
448 ('email', 'null@python.org\x00user@example.org'),
449 ('URI', 'http://null.python.org\x00http://example.org'),
450 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100451 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200452 else:
453 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
454 san = (('DNS', 'altnull.python.org\x00example.com'),
455 ('email', 'null@python.org\x00user@example.org'),
456 ('URI', 'http://null.python.org\x00http://example.org'),
457 ('IP Address', '192.0.2.1'),
458 ('IP Address', '<invalid>'))
459
460 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200461
Christian Heimes1c03abd2016-09-06 23:25:35 +0200462 def test_parse_all_sans(self):
463 p = ssl._ssl._test_decode_cert(ALLSANFILE)
464 self.assertEqual(p['subjectAltName'],
465 (
466 ('DNS', 'allsans'),
467 ('othername', '<unsupported>'),
468 ('othername', '<unsupported>'),
469 ('email', 'user@example.org'),
470 ('DNS', 'www.example.org'),
471 ('DirName',
472 ((('countryName', 'XY'),),
473 (('localityName', 'Castle Anthrax'),),
474 (('organizationName', 'Python Software Foundation'),),
475 (('commonName', 'dirname example'),))),
476 ('URI', 'https://www.python.org/'),
477 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100478 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200479 ('Registered ID', '1.2.3.4.5')
480 )
481 )
482
Antoine Pitrou480a1242010-04-28 21:37:09 +0000483 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000484 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000485 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000486 d1 = ssl.PEM_cert_to_DER_cert(pem)
487 p2 = ssl.DER_cert_to_PEM_cert(d1)
488 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000489 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000490 if not p2.startswith(ssl.PEM_HEADER + '\n'):
491 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
492 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
493 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000494
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000495 def test_openssl_version(self):
496 n = ssl.OPENSSL_VERSION_NUMBER
497 t = ssl.OPENSSL_VERSION_INFO
498 s = ssl.OPENSSL_VERSION
499 self.assertIsInstance(n, int)
500 self.assertIsInstance(t, tuple)
501 self.assertIsInstance(s, str)
502 # Some sanity checks follow
Christian Heimesd37b74f2021-04-19 08:31:29 +0200503 # >= 1.1.1
504 self.assertGreaterEqual(n, 0x10101000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100505 # < 4.0
506 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000507 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100508 self.assertGreaterEqual(major, 1)
509 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000510 self.assertGreaterEqual(minor, 0)
511 self.assertLess(minor, 256)
512 self.assertGreaterEqual(fix, 0)
513 self.assertLess(fix, 256)
514 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100515 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000516 self.assertGreaterEqual(status, 0)
517 self.assertLessEqual(status, 15)
Christian Heimesd37b74f2021-04-19 08:31:29 +0200518
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 )
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000525
Antoine Pitrou9d543662010-04-23 23:10:32 +0000526 @support.cpython_only
527 def test_refcycle(self):
528 # Issue #7943: an SSL object doesn't create reference cycles with
529 # itself.
530 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200531 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000532 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800533 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100534 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100535 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000536
Antoine Pitroua468adc2010-09-14 14:43:44 +0000537 def test_wrapped_unconnected(self):
538 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200539 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000540 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200541 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100542 self.assertRaises(OSError, ss.recv, 1)
543 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
544 self.assertRaises(OSError, ss.recvfrom, 1)
545 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
546 self.assertRaises(OSError, ss.send, b'x')
547 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200548 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100549 self.assertRaises(NotImplementedError, ss.sendmsg,
550 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200551 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
552 self.assertRaises(NotImplementedError, ss.recvmsg_into,
553 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000554
Antoine Pitrou40f08742010-04-24 22:04:40 +0000555 def test_timeout(self):
556 # Issue #8524: when creating an SSL socket, the timeout of the
557 # original socket should be retained.
558 for timeout in (None, 0.0, 5.0):
559 s = socket.socket(socket.AF_INET)
560 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200561 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100562 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000563
Christian Heimes2875c602021-04-19 07:27:10 +0200564 @ignore_deprecation
Christian Heimesd0486372016-09-10 23:23:33 +0200565 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000566 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000567 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000568 "certfile must be specified",
569 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000570 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000571 "certfile must be specified for server-side operations",
572 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000573 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000574 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200575 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100576 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
577 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200578 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200579 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000580 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000581 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000582 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200583 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000584 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000585 ssl.wrap_socket(sock,
586 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000587 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200588 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000589 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000590 ssl.wrap_socket(sock,
591 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000592 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000593
Martin Panter3464ea22016-02-01 21:58:11 +0000594 def bad_cert_test(self, certfile):
595 """Check that trying to use the given client certificate fails"""
596 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
597 certfile)
598 sock = socket.socket()
599 self.addCleanup(sock.close)
600 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200601 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200602 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000603
604 def test_empty_cert(self):
605 """Wrapping with an empty cert file"""
606 self.bad_cert_test("nullcert.pem")
607
608 def test_malformed_cert(self):
609 """Wrapping with a badly formatted certificate (syntax error)"""
610 self.bad_cert_test("badcert.pem")
611
612 def test_malformed_key(self):
613 """Wrapping with a badly formatted key (syntax error)"""
614 self.bad_cert_test("badkey.pem")
615
Christian Heimes2875c602021-04-19 07:27:10 +0200616 @ignore_deprecation
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000617 def test_match_hostname(self):
618 def ok(cert, hostname):
619 ssl.match_hostname(cert, hostname)
620 def fail(cert, hostname):
621 self.assertRaises(ssl.CertificateError,
622 ssl.match_hostname, cert, hostname)
623
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100624 # -- Hostname matching --
625
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000626 cert = {'subject': ((('commonName', 'example.com'),),)}
627 ok(cert, 'example.com')
628 ok(cert, 'ExAmple.cOm')
629 fail(cert, 'www.example.com')
630 fail(cert, '.example.com')
631 fail(cert, 'example.org')
632 fail(cert, 'exampleXcom')
633
634 cert = {'subject': ((('commonName', '*.a.com'),),)}
635 ok(cert, 'foo.a.com')
636 fail(cert, 'bar.foo.a.com')
637 fail(cert, 'a.com')
638 fail(cert, 'Xa.com')
639 fail(cert, '.a.com')
640
Mandeep Singhede2ac92017-11-27 04:01:27 +0530641 # only match wildcards when they are the only thing
642 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000643 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530644 fail(cert, 'foo.com')
645 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000646 fail(cert, 'bar.com')
647 fail(cert, 'foo.a.com')
648 fail(cert, 'bar.foo.com')
649
Christian Heimes824f7f32013-08-17 00:54:47 +0200650 # NULL bytes are bad, CVE-2013-4073
651 cert = {'subject': ((('commonName',
652 'null.python.org\x00example.org'),),)}
653 ok(cert, 'null.python.org\x00example.org') # or raise an error?
654 fail(cert, 'example.org')
655 fail(cert, 'null.python.org')
656
Georg Brandl72c98d32013-10-27 07:16:53 +0100657 # error cases with wildcards
658 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
659 fail(cert, 'bar.foo.a.com')
660 fail(cert, 'a.com')
661 fail(cert, 'Xa.com')
662 fail(cert, '.a.com')
663
664 cert = {'subject': ((('commonName', 'a.*.com'),),)}
665 fail(cert, 'a.foo.com')
666 fail(cert, 'a..com')
667 fail(cert, 'a.com')
668
669 # wildcard doesn't match IDNA prefix 'xn--'
670 idna = 'püthon.python.org'.encode("idna").decode("ascii")
671 cert = {'subject': ((('commonName', idna),),)}
672 ok(cert, idna)
673 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
674 fail(cert, idna)
675 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
676 fail(cert, idna)
677
678 # wildcard in first fragment and IDNA A-labels in sequent fragments
679 # are supported.
680 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
681 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530682 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
683 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100684 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
685 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
686
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000687 # Slightly fake real-world example
688 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
689 'subject': ((('commonName', 'linuxfrz.org'),),),
690 'subjectAltName': (('DNS', 'linuxfr.org'),
691 ('DNS', 'linuxfr.com'),
692 ('othername', '<unsupported>'))}
693 ok(cert, 'linuxfr.org')
694 ok(cert, 'linuxfr.com')
695 # Not a "DNS" entry
696 fail(cert, '<unsupported>')
697 # When there is a subjectAltName, commonName isn't used
698 fail(cert, 'linuxfrz.org')
699
700 # A pristine real-world example
701 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
702 'subject': ((('countryName', 'US'),),
703 (('stateOrProvinceName', 'California'),),
704 (('localityName', 'Mountain View'),),
705 (('organizationName', 'Google Inc'),),
706 (('commonName', 'mail.google.com'),))}
707 ok(cert, 'mail.google.com')
708 fail(cert, 'gmail.com')
709 # Only commonName is considered
710 fail(cert, 'California')
711
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100712 # -- IPv4 matching --
713 cert = {'subject': ((('commonName', 'example.com'),),),
714 'subjectAltName': (('DNS', 'example.com'),
715 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200716 ('IP Address', '14.15.16.17'),
717 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100718 ok(cert, '10.11.12.13')
719 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200720 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
721 fail(cert, '127.1')
722 fail(cert, '14.15.16.17 ')
723 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100724 fail(cert, '14.15.16.18')
725 fail(cert, 'example.net')
726
727 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300728 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100729 cert = {'subject': ((('commonName', 'example.com'),),),
730 'subjectAltName': (
731 ('DNS', 'example.com'),
732 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
733 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
734 ok(cert, '2001::cafe')
735 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200736 fail(cert, '2003::baba ')
737 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100738 fail(cert, '2003::bebe')
739 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100740
741 # -- Miscellaneous --
742
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000743 # Neither commonName nor subjectAltName
744 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
745 'subject': ((('countryName', 'US'),),
746 (('stateOrProvinceName', 'California'),),
747 (('localityName', 'Mountain View'),),
748 (('organizationName', 'Google Inc'),))}
749 fail(cert, 'mail.google.com')
750
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200751 # No DNS entry in subjectAltName but a commonName
752 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
753 'subject': ((('countryName', 'US'),),
754 (('stateOrProvinceName', 'California'),),
755 (('localityName', 'Mountain View'),),
756 (('commonName', 'mail.google.com'),)),
757 'subjectAltName': (('othername', 'blabla'), )}
758 ok(cert, 'mail.google.com')
759
760 # No DNS entry subjectAltName and no commonName
761 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
762 'subject': ((('countryName', 'US'),),
763 (('stateOrProvinceName', 'California'),),
764 (('localityName', 'Mountain View'),),
765 (('organizationName', 'Google Inc'),)),
766 'subjectAltName': (('othername', 'blabla'),)}
767 fail(cert, 'google.com')
768
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000769 # Empty cert / no cert
770 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
771 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
772
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200773 # Issue #17980: avoid denials of service by refusing more than one
774 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100775 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
776 with self.assertRaisesRegex(
777 ssl.CertificateError,
778 "partial wildcards in leftmost label are not supported"):
779 ssl.match_hostname(cert, 'axxb.example.com')
780
781 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
782 with self.assertRaisesRegex(
783 ssl.CertificateError,
784 "wildcard can only be present in the leftmost label"):
785 ssl.match_hostname(cert, 'www.sub.example.com')
786
787 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
788 with self.assertRaisesRegex(
789 ssl.CertificateError,
790 "too many wildcards"):
791 ssl.match_hostname(cert, 'axxbxxc.example.com')
792
793 cert = {'subject': ((('commonName', '*'),),)}
794 with self.assertRaisesRegex(
795 ssl.CertificateError,
796 "sole wildcard without additional labels are not support"):
797 ssl.match_hostname(cert, 'host')
798
799 cert = {'subject': ((('commonName', '*.com'),),)}
800 with self.assertRaisesRegex(
801 ssl.CertificateError,
802 r"hostname 'com' doesn't match '\*.com'"):
803 ssl.match_hostname(cert, 'com')
804
805 # extra checks for _inet_paton()
806 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
807 with self.assertRaises(ValueError):
808 ssl._inet_paton(invalid)
809 for ipaddr in ['127.0.0.1', '192.168.0.1']:
810 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300811 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100812 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
813 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200814
Antoine Pitroud5323212010-10-22 18:19:07 +0000815 def test_server_side(self):
816 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200817 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000818 with socket.socket() as sock:
819 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
820 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000821
Antoine Pitroud6494802011-07-21 01:11:30 +0200822 def test_unknown_channel_binding(self):
823 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200824 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200825 c = socket.socket(socket.AF_INET)
826 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200827 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100828 with self.assertRaises(ValueError):
829 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200830 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200831
832 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
833 "'tls-unique' channel binding not available")
834 def test_tls_unique_channel_binding(self):
835 # unconnected should return None for known type
836 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200837 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100838 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200839 # the same for server-side
840 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200841 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100842 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200843
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600844 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200845 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600846 r = repr(ss)
847 with self.assertWarns(ResourceWarning) as cm:
848 ss = None
849 support.gc_collect()
850 self.assertIn(r, str(cm.warning.args[0]))
851
Christian Heimes6d7ad132013-06-09 18:02:55 +0200852 def test_get_default_verify_paths(self):
853 paths = ssl.get_default_verify_paths()
854 self.assertEqual(len(paths), 6)
855 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
856
Hai Shia7f5d932020-08-04 00:41:24 +0800857 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200858 env["SSL_CERT_DIR"] = CAPATH
859 env["SSL_CERT_FILE"] = CERTFILE
860 paths = ssl.get_default_verify_paths()
861 self.assertEqual(paths.cafile, CERTFILE)
862 self.assertEqual(paths.capath, CAPATH)
863
Christian Heimes44109d72013-11-22 01:51:30 +0100864 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
865 def test_enum_certificates(self):
866 self.assertTrue(ssl.enum_certificates("CA"))
867 self.assertTrue(ssl.enum_certificates("ROOT"))
868
869 self.assertRaises(TypeError, ssl.enum_certificates)
870 self.assertRaises(WindowsError, ssl.enum_certificates, "")
871
Christian Heimesc2d65e12013-11-22 16:13:55 +0100872 trust_oids = set()
873 for storename in ("CA", "ROOT"):
874 store = ssl.enum_certificates(storename)
875 self.assertIsInstance(store, list)
876 for element in store:
877 self.assertIsInstance(element, tuple)
878 self.assertEqual(len(element), 3)
879 cert, enc, trust = element
880 self.assertIsInstance(cert, bytes)
881 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200882 self.assertIsInstance(trust, (frozenset, set, bool))
883 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100884 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100885
886 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100887 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200888
Christian Heimes46bebee2013-06-09 19:03:31 +0200889 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100890 def test_enum_crls(self):
891 self.assertTrue(ssl.enum_crls("CA"))
892 self.assertRaises(TypeError, ssl.enum_crls)
893 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200894
Christian Heimes44109d72013-11-22 01:51:30 +0100895 crls = ssl.enum_crls("CA")
896 self.assertIsInstance(crls, list)
897 for element in crls:
898 self.assertIsInstance(element, tuple)
899 self.assertEqual(len(element), 2)
900 self.assertIsInstance(element[0], bytes)
901 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200902
Christian Heimes46bebee2013-06-09 19:03:31 +0200903
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100904 def test_asn1object(self):
905 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
906 '1.3.6.1.5.5.7.3.1')
907
908 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
909 self.assertEqual(val, expected)
910 self.assertEqual(val.nid, 129)
911 self.assertEqual(val.shortname, 'serverAuth')
912 self.assertEqual(val.longname, 'TLS Web Server Authentication')
913 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
914 self.assertIsInstance(val, ssl._ASN1Object)
915 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
916
917 val = ssl._ASN1Object.fromnid(129)
918 self.assertEqual(val, expected)
919 self.assertIsInstance(val, ssl._ASN1Object)
920 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100921 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
922 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100923 for i in range(1000):
924 try:
925 obj = ssl._ASN1Object.fromnid(i)
926 except ValueError:
927 pass
928 else:
929 self.assertIsInstance(obj.nid, int)
930 self.assertIsInstance(obj.shortname, str)
931 self.assertIsInstance(obj.longname, str)
932 self.assertIsInstance(obj.oid, (str, type(None)))
933
934 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
935 self.assertEqual(val, expected)
936 self.assertIsInstance(val, ssl._ASN1Object)
937 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
938 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
939 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100940 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
941 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100942
Christian Heimes72d28502013-11-23 13:56:58 +0100943 def test_purpose_enum(self):
944 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
945 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
946 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
947 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
948 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
949 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
950 '1.3.6.1.5.5.7.3.1')
951
952 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
953 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
954 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
955 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
956 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
957 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
958 '1.3.6.1.5.5.7.3.2')
959
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100960 def test_unsupported_dtls(self):
961 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
962 self.addCleanup(s.close)
963 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +0200964 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100965 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +0200966 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100967 with self.assertRaises(NotImplementedError) as cx:
968 ctx.wrap_socket(s)
969 self.assertEqual(str(cx.exception), "only stream sockets are supported")
970
Antoine Pitrouc695c952014-04-28 20:57:36 +0200971 def cert_time_ok(self, timestring, timestamp):
972 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
973
974 def cert_time_fail(self, timestring):
975 with self.assertRaises(ValueError):
976 ssl.cert_time_to_seconds(timestring)
977
978 @unittest.skipUnless(utc_offset(),
979 'local time needs to be different from UTC')
980 def test_cert_time_to_seconds_timezone(self):
981 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
982 # results if local timezone is not UTC
983 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
984 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
985
986 def test_cert_time_to_seconds(self):
987 timestring = "Jan 5 09:34:43 2018 GMT"
988 ts = 1515144883.0
989 self.cert_time_ok(timestring, ts)
990 # accept keyword parameter, assert its name
991 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
992 # accept both %e and %d (space or zero generated by strftime)
993 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
994 # case-insensitive
995 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
996 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
997 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
998 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
999 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1000 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1001 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1002 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1003
1004 newyear_ts = 1230768000.0
1005 # leap seconds
1006 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1007 # same timestamp
1008 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1009
1010 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1011 # allow 60th second (even if it is not a leap second)
1012 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1013 # allow 2nd leap second for compatibility with time.strptime()
1014 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1015 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1016
Mike53f7a7c2017-12-14 14:04:53 +03001017 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001018 # 99991231235959Z (rfc 5280)
1019 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1020
1021 @support.run_with_locale('LC_ALL', '')
1022 def test_cert_time_to_seconds_locale(self):
1023 # `cert_time_to_seconds()` should be locale independent
1024
1025 def local_february_name():
1026 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1027
1028 if local_february_name().lower() == 'feb':
1029 self.skipTest("locale-specific month name needs to be "
1030 "different from C locale")
1031
1032 # locale-independent
1033 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1034 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1035
Martin Panter3840b2a2016-03-27 01:53:46 +00001036 def test_connect_ex_error(self):
1037 server = socket.socket(socket.AF_INET)
1038 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001039 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001040 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001041 cert_reqs=ssl.CERT_REQUIRED)
1042 self.addCleanup(s.close)
1043 rc = s.connect_ex((HOST, port))
1044 # Issue #19919: Windows machines or VMs hosted on Windows
1045 # machines sometimes return EWOULDBLOCK.
1046 errors = (
1047 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1048 errno.EWOULDBLOCK,
1049 )
1050 self.assertIn(rc, errors)
1051
Christian Heimes89d15502021-04-19 06:55:30 +02001052 def test_read_write_zero(self):
1053 # empty reads and writes now work, bpo-42854, bpo-31711
1054 client_context, server_context, hostname = testing_context()
1055 server = ThreadedEchoServer(context=server_context)
1056 with server:
1057 with client_context.wrap_socket(socket.socket(),
1058 server_hostname=hostname) as s:
1059 s.connect((HOST, server.port))
1060 self.assertEqual(s.recv(0), b"")
1061 self.assertEqual(s.send(b""), 0)
1062
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001063
Antoine Pitrou152efa22010-05-16 18:19:27 +00001064class ContextTests(unittest.TestCase):
1065
1066 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001067 for protocol in PROTOCOLS:
Christian Heimes2875c602021-04-19 07:27:10 +02001068 with warnings_helper.check_warnings():
1069 ctx = ssl.SSLContext(protocol)
1070 self.assertEqual(ctx.protocol, protocol)
1071 with warnings_helper.check_warnings():
1072 ctx = ssl.SSLContext()
Christian Heimes598894f2016-09-05 23:19:05 +02001073 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001074 self.assertRaises(ValueError, ssl.SSLContext, -1)
1075 self.assertRaises(ValueError, ssl.SSLContext, 42)
1076
Antoine Pitrou152efa22010-05-16 18:19:27 +00001077 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001078 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001079 ctx.set_ciphers("ALL")
1080 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001081 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001082 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001083
Christian Heimes892d66e2018-01-29 14:10:18 +01001084 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1085 "Test applies only to Python default ciphers")
1086 def test_python_ciphers(self):
1087 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1088 ciphers = ctx.get_ciphers()
1089 for suite in ciphers:
1090 name = suite['name']
1091 self.assertNotIn("PSK", name)
1092 self.assertNotIn("SRP", name)
1093 self.assertNotIn("MD5", name)
1094 self.assertNotIn("RC4", name)
1095 self.assertNotIn("3DES", name)
1096
Christian Heimes25bfcd52016-09-06 00:04:45 +02001097 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001098 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001099 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001100 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001101 self.assertIn('AES256-GCM-SHA384', names)
1102 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001103
Antoine Pitroub5218772010-05-21 09:56:06 +00001104 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001105 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001106 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001107 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001108 # SSLContext also enables these by default
1109 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001110 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001111 OP_ENABLE_MIDDLEBOX_COMPAT |
1112 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001113 self.assertEqual(default, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001114 with warnings_helper.check_warnings():
1115 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001116 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001117 with warnings_helper.check_warnings():
1118 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
Christian Heimes39258d32021-04-17 11:36:35 +02001119 self.assertEqual(default, ctx.options)
1120 ctx.options = 0
1121 # Ubuntu has OP_NO_SSLv3 forced on by default
1122 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001123
Christian Heimesa170fa12017-09-15 20:27:30 +02001124 def test_verify_mode_protocol(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001125 with warnings_helper.check_warnings():
1126 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001127 # Default value
1128 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1129 ctx.verify_mode = ssl.CERT_OPTIONAL
1130 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1131 ctx.verify_mode = ssl.CERT_REQUIRED
1132 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1133 ctx.verify_mode = ssl.CERT_NONE
1134 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1135 with self.assertRaises(TypeError):
1136 ctx.verify_mode = None
1137 with self.assertRaises(ValueError):
1138 ctx.verify_mode = 42
1139
Christian Heimesa170fa12017-09-15 20:27:30 +02001140 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1141 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1142 self.assertFalse(ctx.check_hostname)
1143
1144 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1145 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1146 self.assertTrue(ctx.check_hostname)
1147
Christian Heimes61d478c2018-01-27 15:51:38 +01001148 def test_hostname_checks_common_name(self):
1149 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1150 self.assertTrue(ctx.hostname_checks_common_name)
1151 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1152 ctx.hostname_checks_common_name = True
1153 self.assertTrue(ctx.hostname_checks_common_name)
1154 ctx.hostname_checks_common_name = False
1155 self.assertFalse(ctx.hostname_checks_common_name)
1156 ctx.hostname_checks_common_name = True
1157 self.assertTrue(ctx.hostname_checks_common_name)
1158 else:
1159 with self.assertRaises(AttributeError):
1160 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001161
Christian Heimes2875c602021-04-19 07:27:10 +02001162 @ignore_deprecation
Christian Heimes698dde12018-02-27 11:54:43 +01001163 def test_min_max_version(self):
1164 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001165 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1166 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001167 minimum_range = {
1168 # stock OpenSSL
1169 ssl.TLSVersion.MINIMUM_SUPPORTED,
1170 # Fedora 29 uses TLS 1.0 by default
1171 ssl.TLSVersion.TLSv1,
1172 # RHEL 8 uses TLS 1.2 by default
1173 ssl.TLSVersion.TLSv1_2
1174 }
torsava34864d12019-12-02 17:15:42 +01001175 maximum_range = {
1176 # stock OpenSSL
1177 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1178 # Fedora 32 uses TLS 1.3 by default
1179 ssl.TLSVersion.TLSv1_3
1180 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001181
Christian Heimes34de2d32019-01-18 16:09:30 +01001182 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001183 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001184 )
torsava34864d12019-12-02 17:15:42 +01001185 self.assertIn(
1186 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001187 )
1188
1189 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1190 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1191 self.assertEqual(
1192 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1193 )
1194 self.assertEqual(
1195 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1196 )
1197
1198 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1199 ctx.maximum_version = ssl.TLSVersion.TLSv1
1200 self.assertEqual(
1201 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1202 )
1203 self.assertEqual(
1204 ctx.maximum_version, ssl.TLSVersion.TLSv1
1205 )
1206
1207 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1208 self.assertEqual(
1209 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1210 )
1211
1212 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1213 self.assertIn(
1214 ctx.maximum_version,
1215 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1216 )
1217
1218 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1219 self.assertIn(
1220 ctx.minimum_version,
1221 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1222 )
1223
1224 with self.assertRaises(ValueError):
1225 ctx.minimum_version = 42
1226
1227 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1228
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001229 self.assertIn(
1230 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001231 )
1232 self.assertEqual(
1233 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1234 )
1235 with self.assertRaises(ValueError):
1236 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1237 with self.assertRaises(ValueError):
1238 ctx.maximum_version = ssl.TLSVersion.TLSv1
1239
1240
matthewhughes9348e836bb2020-07-17 09:59:15 +01001241 @unittest.skipUnless(
1242 hasattr(ssl.SSLContext, 'security_level'),
1243 "requires OpenSSL >= 1.1.0"
1244 )
1245 def test_security_level(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001246 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
matthewhughes9348e836bb2020-07-17 09:59:15 +01001247 # The default security callback allows for levels between 0-5
1248 # with OpenSSL defaulting to 1, however some vendors override the
1249 # default value (e.g. Debian defaults to 2)
1250 security_level_range = {
1251 0,
1252 1, # OpenSSL default
1253 2, # Debian
1254 3,
1255 4,
1256 5,
1257 }
1258 self.assertIn(ctx.security_level, security_level_range)
1259
Christian Heimes22587792013-11-21 23:56:13 +01001260 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001261 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001262 # default value
1263 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1264 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001265 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1266 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1267 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1268 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1269 ctx.verify_flags = ssl.VERIFY_DEFAULT
1270 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001271 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1272 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001273 # supports any value
1274 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1275 self.assertEqual(ctx.verify_flags,
1276 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1277 with self.assertRaises(TypeError):
1278 ctx.verify_flags = None
1279
Antoine Pitrou152efa22010-05-16 18:19:27 +00001280 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001281 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001282 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001283 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001284 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1285 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001286 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001287 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001288 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001289 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001290 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001291 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001292 ctx.load_cert_chain(EMPTYCERT)
1293 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001294 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001295 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1296 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1297 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001298 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001299 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001300 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001301 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001302 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001303 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1304 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001305 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001306 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001307 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001308 # Password protected key and cert
1309 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1310 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1311 ctx.load_cert_chain(CERTFILE_PROTECTED,
1312 password=bytearray(KEY_PASSWORD.encode()))
1313 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1314 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1315 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1316 bytearray(KEY_PASSWORD.encode()))
1317 with self.assertRaisesRegex(TypeError, "should be a string"):
1318 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1319 with self.assertRaises(ssl.SSLError):
1320 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1321 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1322 # openssl has a fixed limit on the password buffer.
1323 # PEM_BUFSIZE is generally set to 1kb.
1324 # Return a string larger than this.
1325 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1326 # Password callback
1327 def getpass_unicode():
1328 return KEY_PASSWORD
1329 def getpass_bytes():
1330 return KEY_PASSWORD.encode()
1331 def getpass_bytearray():
1332 return bytearray(KEY_PASSWORD.encode())
1333 def getpass_badpass():
1334 return "badpass"
1335 def getpass_huge():
1336 return b'a' * (1024 * 1024)
1337 def getpass_bad_type():
1338 return 9
1339 def getpass_exception():
1340 raise Exception('getpass error')
1341 class GetPassCallable:
1342 def __call__(self):
1343 return KEY_PASSWORD
1344 def getpass(self):
1345 return KEY_PASSWORD
1346 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1347 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1348 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1349 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1350 ctx.load_cert_chain(CERTFILE_PROTECTED,
1351 password=GetPassCallable().getpass)
1352 with self.assertRaises(ssl.SSLError):
1353 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1354 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1355 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1356 with self.assertRaisesRegex(TypeError, "must return a string"):
1357 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1358 with self.assertRaisesRegex(Exception, "getpass error"):
1359 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1360 # Make sure the password function isn't called if it isn't needed
1361 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001362
1363 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001364 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001365 ctx.load_verify_locations(CERTFILE)
1366 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1367 ctx.load_verify_locations(BYTES_CERTFILE)
1368 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1369 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001370 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001371 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001372 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001373 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001374 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001375 ctx.load_verify_locations(BADCERT)
1376 ctx.load_verify_locations(CERTFILE, CAPATH)
1377 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1378
Victor Stinner80f75e62011-01-29 11:31:20 +00001379 # Issue #10989: crash if the second argument type is invalid
1380 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1381
Christian Heimesefff7062013-11-21 03:35:02 +01001382 def test_load_verify_cadata(self):
1383 # test cadata
1384 with open(CAFILE_CACERT) as f:
1385 cacert_pem = f.read()
1386 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1387 with open(CAFILE_NEURONIO) as f:
1388 neuronio_pem = f.read()
1389 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1390
1391 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001392 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001393 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1394 ctx.load_verify_locations(cadata=cacert_pem)
1395 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1396 ctx.load_verify_locations(cadata=neuronio_pem)
1397 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1398 # cert already in hash table
1399 ctx.load_verify_locations(cadata=neuronio_pem)
1400 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1401
1402 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001403 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001404 combined = "\n".join((cacert_pem, neuronio_pem))
1405 ctx.load_verify_locations(cadata=combined)
1406 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1407
1408 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001409 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001410 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1411 neuronio_pem, "tail"]
1412 ctx.load_verify_locations(cadata="\n".join(combined))
1413 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1414
1415 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001416 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001417 ctx.load_verify_locations(cadata=cacert_der)
1418 ctx.load_verify_locations(cadata=neuronio_der)
1419 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1420 # cert already in hash table
1421 ctx.load_verify_locations(cadata=cacert_der)
1422 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1423
1424 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001425 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001426 combined = b"".join((cacert_der, neuronio_der))
1427 ctx.load_verify_locations(cadata=combined)
1428 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1429
1430 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001431 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001432 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1433
1434 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1435 ctx.load_verify_locations(cadata="broken")
1436 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1437 ctx.load_verify_locations(cadata=b"broken")
1438
1439
Paul Monsonf3550692019-06-19 13:09:54 -07001440 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001441 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001442 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001443 ctx.load_dh_params(DHFILE)
1444 if os.name != 'nt':
1445 ctx.load_dh_params(BYTES_DHFILE)
1446 self.assertRaises(TypeError, ctx.load_dh_params)
1447 self.assertRaises(TypeError, ctx.load_dh_params, None)
1448 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001449 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001450 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001451 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001452 ctx.load_dh_params(CERTFILE)
1453
Antoine Pitroub0182c82010-10-12 20:09:02 +00001454 def test_session_stats(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001455 for proto in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
Antoine Pitroub0182c82010-10-12 20:09:02 +00001456 ctx = ssl.SSLContext(proto)
1457 self.assertEqual(ctx.session_stats(), {
1458 'number': 0,
1459 'connect': 0,
1460 'connect_good': 0,
1461 'connect_renegotiate': 0,
1462 'accept': 0,
1463 'accept_good': 0,
1464 'accept_renegotiate': 0,
1465 'hits': 0,
1466 'misses': 0,
1467 'timeouts': 0,
1468 'cache_full': 0,
1469 })
1470
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001471 def test_set_default_verify_paths(self):
1472 # There's not much we can do to test that it acts as expected,
1473 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001474 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001475 ctx.set_default_verify_paths()
1476
Antoine Pitrou501da612011-12-21 09:27:41 +01001477 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001478 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001479 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001480 ctx.set_ecdh_curve("prime256v1")
1481 ctx.set_ecdh_curve(b"prime256v1")
1482 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1483 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1484 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1485 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1486
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001487 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001488 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001489
1490 # set_servername_callback expects a callable, or None
1491 self.assertRaises(TypeError, ctx.set_servername_callback)
1492 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1493 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1494 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1495
1496 def dummycallback(sock, servername, ctx):
1497 pass
1498 ctx.set_servername_callback(None)
1499 ctx.set_servername_callback(dummycallback)
1500
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001501 def test_sni_callback_refcycle(self):
1502 # Reference cycles through the servername callback are detected
1503 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001504 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001505 def dummycallback(sock, servername, ctx, cycle=ctx):
1506 pass
1507 ctx.set_servername_callback(dummycallback)
1508 wr = weakref.ref(ctx)
1509 del ctx, dummycallback
1510 gc.collect()
1511 self.assertIs(wr(), None)
1512
Christian Heimes9a5395a2013-06-17 15:44:12 +02001513 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001514 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001515 self.assertEqual(ctx.cert_store_stats(),
1516 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1517 ctx.load_cert_chain(CERTFILE)
1518 self.assertEqual(ctx.cert_store_stats(),
1519 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1520 ctx.load_verify_locations(CERTFILE)
1521 self.assertEqual(ctx.cert_store_stats(),
1522 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001523 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001524 self.assertEqual(ctx.cert_store_stats(),
1525 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1526
1527 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001528 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001529 self.assertEqual(ctx.get_ca_certs(), [])
1530 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1531 ctx.load_verify_locations(CERTFILE)
1532 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001533 # but CAFILE_CACERT is a CA cert
1534 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001535 self.assertEqual(ctx.get_ca_certs(),
1536 [{'issuer': ((('organizationName', 'Root CA'),),
1537 (('organizationalUnitName', 'http://www.cacert.org'),),
1538 (('commonName', 'CA Cert Signing Authority'),),
1539 (('emailAddress', 'support@cacert.org'),)),
Christian Heimesd37b74f2021-04-19 08:31:29 +02001540 'notAfter': 'Mar 29 12:29:49 2033 GMT',
1541 'notBefore': 'Mar 30 12:29:49 2003 GMT',
Christian Heimes9a5395a2013-06-17 15:44:12 +02001542 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001543 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001544 'subject': ((('organizationName', 'Root CA'),),
1545 (('organizationalUnitName', 'http://www.cacert.org'),),
1546 (('commonName', 'CA Cert Signing Authority'),),
1547 (('emailAddress', 'support@cacert.org'),)),
1548 'version': 3}])
1549
Martin Panterb55f8b72016-01-14 12:53:56 +00001550 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001551 pem = f.read()
1552 der = ssl.PEM_cert_to_DER_cert(pem)
1553 self.assertEqual(ctx.get_ca_certs(True), [der])
1554
Christian Heimes72d28502013-11-23 13:56:58 +01001555 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001556 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001557 ctx.load_default_certs()
1558
Christian Heimesa170fa12017-09-15 20:27:30 +02001559 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001560 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1561 ctx.load_default_certs()
1562
Christian Heimesa170fa12017-09-15 20:27:30 +02001563 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001564 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1565
Christian Heimesa170fa12017-09-15 20:27:30 +02001566 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001567 self.assertRaises(TypeError, ctx.load_default_certs, None)
1568 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1569
Benjamin Peterson91244e02014-10-03 18:17:15 -04001570 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001571 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001572 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001573 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001574 env["SSL_CERT_DIR"] = CAPATH
1575 env["SSL_CERT_FILE"] = CERTFILE
1576 ctx.load_default_certs()
1577 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1578
Benjamin Peterson91244e02014-10-03 18:17:15 -04001579 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001580 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001581 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001582 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001583 ctx.load_default_certs()
1584 stats = ctx.cert_store_stats()
1585
Christian Heimesa170fa12017-09-15 20:27:30 +02001586 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001587 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001588 env["SSL_CERT_DIR"] = CAPATH
1589 env["SSL_CERT_FILE"] = CERTFILE
1590 ctx.load_default_certs()
1591 stats["x509"] += 1
1592 self.assertEqual(ctx.cert_store_stats(), stats)
1593
Christian Heimes358cfd42016-09-10 22:43:48 +02001594 def _assert_context_options(self, ctx):
1595 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1596 if OP_NO_COMPRESSION != 0:
1597 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1598 OP_NO_COMPRESSION)
1599 if OP_SINGLE_DH_USE != 0:
1600 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1601 OP_SINGLE_DH_USE)
1602 if OP_SINGLE_ECDH_USE != 0:
1603 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1604 OP_SINGLE_ECDH_USE)
1605 if OP_CIPHER_SERVER_PREFERENCE != 0:
1606 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1607 OP_CIPHER_SERVER_PREFERENCE)
1608
Christian Heimes4c05b472013-11-23 15:58:30 +01001609 def test_create_default_context(self):
1610 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001611
Christian Heimes2875c602021-04-19 07:27:10 +02001612 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001613 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001614 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001615 self._assert_context_options(ctx)
1616
Christian Heimes4c05b472013-11-23 15:58:30 +01001617 with open(SIGNING_CA) as f:
1618 cadata = f.read()
1619 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1620 cadata=cadata)
Christian Heimes2875c602021-04-19 07:27:10 +02001621 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001622 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001623 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001624
1625 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001626 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes4c05b472013-11-23 15:58:30 +01001627 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001628 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001629
Christian Heimes2875c602021-04-19 07:27:10 +02001630
1631
Christian Heimes67986f92013-11-23 22:43:47 +01001632 def test__create_stdlib_context(self):
1633 ctx = ssl._create_stdlib_context()
Christian Heimes2875c602021-04-19 07:27:10 +02001634 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes67986f92013-11-23 22:43:47 +01001635 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001636 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001637 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001638
Christian Heimes2875c602021-04-19 07:27:10 +02001639 with warnings_helper.check_warnings():
1640 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
Christian Heimes67986f92013-11-23 22:43:47 +01001641 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1642 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001643 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001644
Christian Heimes2875c602021-04-19 07:27:10 +02001645 with warnings_helper.check_warnings():
1646 ctx = ssl._create_stdlib_context(
1647 ssl.PROTOCOL_TLSv1_2,
1648 cert_reqs=ssl.CERT_REQUIRED,
1649 check_hostname=True
1650 )
1651 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
Christian Heimes67986f92013-11-23 22:43:47 +01001652 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001653 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001654 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001655
1656 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001657 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes67986f92013-11-23 22:43:47 +01001658 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001659 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001660
Christian Heimes1aa9a752013-12-02 02:41:19 +01001661 def test_check_hostname(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001662 with warnings_helper.check_warnings():
1663 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001664 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001665 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001666
Christian Heimese82c0342017-09-15 20:29:57 +02001667 # Auto set CERT_REQUIRED
1668 ctx.check_hostname = True
1669 self.assertTrue(ctx.check_hostname)
1670 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1671 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001672 ctx.verify_mode = ssl.CERT_REQUIRED
1673 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001674 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001675
Christian Heimese82c0342017-09-15 20:29:57 +02001676 # Changing verify_mode does not affect check_hostname
1677 ctx.check_hostname = False
1678 ctx.verify_mode = ssl.CERT_NONE
1679 ctx.check_hostname = False
1680 self.assertFalse(ctx.check_hostname)
1681 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1682 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001683 ctx.check_hostname = True
1684 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001685 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1686
1687 ctx.check_hostname = False
1688 ctx.verify_mode = ssl.CERT_OPTIONAL
1689 ctx.check_hostname = False
1690 self.assertFalse(ctx.check_hostname)
1691 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1692 # keep CERT_OPTIONAL
1693 ctx.check_hostname = True
1694 self.assertTrue(ctx.check_hostname)
1695 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001696
1697 # Cannot set CERT_NONE with check_hostname enabled
1698 with self.assertRaises(ValueError):
1699 ctx.verify_mode = ssl.CERT_NONE
1700 ctx.check_hostname = False
1701 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001702 ctx.verify_mode = ssl.CERT_NONE
1703 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001704
Christian Heimes5fe668c2016-09-12 00:01:11 +02001705 def test_context_client_server(self):
1706 # PROTOCOL_TLS_CLIENT has sane defaults
1707 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1708 self.assertTrue(ctx.check_hostname)
1709 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1710
1711 # PROTOCOL_TLS_SERVER has different but also sane defaults
1712 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1713 self.assertFalse(ctx.check_hostname)
1714 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1715
Christian Heimes4df60f12017-09-15 20:26:05 +02001716 def test_context_custom_class(self):
1717 class MySSLSocket(ssl.SSLSocket):
1718 pass
1719
1720 class MySSLObject(ssl.SSLObject):
1721 pass
1722
1723 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1724 ctx.sslsocket_class = MySSLSocket
1725 ctx.sslobject_class = MySSLObject
1726
1727 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1728 self.assertIsInstance(sock, MySSLSocket)
1729 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1730 self.assertIsInstance(obj, MySSLObject)
1731
Christian Heimes78c7d522019-06-03 21:00:10 +02001732 def test_num_tickest(self):
1733 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1734 self.assertEqual(ctx.num_tickets, 2)
1735 ctx.num_tickets = 1
1736 self.assertEqual(ctx.num_tickets, 1)
1737 ctx.num_tickets = 0
1738 self.assertEqual(ctx.num_tickets, 0)
1739 with self.assertRaises(ValueError):
1740 ctx.num_tickets = -1
1741 with self.assertRaises(TypeError):
1742 ctx.num_tickets = None
1743
1744 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1745 self.assertEqual(ctx.num_tickets, 2)
1746 with self.assertRaises(ValueError):
1747 ctx.num_tickets = 1
1748
Antoine Pitrou152efa22010-05-16 18:19:27 +00001749
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001750class SSLErrorTests(unittest.TestCase):
1751
1752 def test_str(self):
1753 # The str() of a SSLError doesn't include the errno
1754 e = ssl.SSLError(1, "foo")
1755 self.assertEqual(str(e), "foo")
1756 self.assertEqual(e.errno, 1)
1757 # Same for a subclass
1758 e = ssl.SSLZeroReturnError(1, "foo")
1759 self.assertEqual(str(e), "foo")
1760 self.assertEqual(e.errno, 1)
1761
Paul Monsonf3550692019-06-19 13:09:54 -07001762 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001763 def test_lib_reason(self):
1764 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001765 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001766 with self.assertRaises(ssl.SSLError) as cm:
1767 ctx.load_dh_params(CERTFILE)
1768 self.assertEqual(cm.exception.library, 'PEM')
1769 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1770 s = str(cm.exception)
1771 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1772
1773 def test_subclass(self):
1774 # Check that the appropriate SSLError subclass is raised
1775 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001776 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1777 ctx.check_hostname = False
1778 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001779 with socket.create_server(("127.0.0.1", 0)) as s:
1780 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001781 c.setblocking(False)
1782 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001783 with self.assertRaises(ssl.SSLWantReadError) as cm:
1784 c.do_handshake()
1785 s = str(cm.exception)
1786 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1787 # For compatibility
1788 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1789
1790
Christian Heimes61d478c2018-01-27 15:51:38 +01001791 def test_bad_server_hostname(self):
1792 ctx = ssl.create_default_context()
1793 with self.assertRaises(ValueError):
1794 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1795 server_hostname="")
1796 with self.assertRaises(ValueError):
1797 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1798 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001799 with self.assertRaises(TypeError):
1800 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1801 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001802
1803
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001804class MemoryBIOTests(unittest.TestCase):
1805
1806 def test_read_write(self):
1807 bio = ssl.MemoryBIO()
1808 bio.write(b'foo')
1809 self.assertEqual(bio.read(), b'foo')
1810 self.assertEqual(bio.read(), b'')
1811 bio.write(b'foo')
1812 bio.write(b'bar')
1813 self.assertEqual(bio.read(), b'foobar')
1814 self.assertEqual(bio.read(), b'')
1815 bio.write(b'baz')
1816 self.assertEqual(bio.read(2), b'ba')
1817 self.assertEqual(bio.read(1), b'z')
1818 self.assertEqual(bio.read(1), b'')
1819
1820 def test_eof(self):
1821 bio = ssl.MemoryBIO()
1822 self.assertFalse(bio.eof)
1823 self.assertEqual(bio.read(), b'')
1824 self.assertFalse(bio.eof)
1825 bio.write(b'foo')
1826 self.assertFalse(bio.eof)
1827 bio.write_eof()
1828 self.assertFalse(bio.eof)
1829 self.assertEqual(bio.read(2), b'fo')
1830 self.assertFalse(bio.eof)
1831 self.assertEqual(bio.read(1), b'o')
1832 self.assertTrue(bio.eof)
1833 self.assertEqual(bio.read(), b'')
1834 self.assertTrue(bio.eof)
1835
1836 def test_pending(self):
1837 bio = ssl.MemoryBIO()
1838 self.assertEqual(bio.pending, 0)
1839 bio.write(b'foo')
1840 self.assertEqual(bio.pending, 3)
1841 for i in range(3):
1842 bio.read(1)
1843 self.assertEqual(bio.pending, 3-i-1)
1844 for i in range(3):
1845 bio.write(b'x')
1846 self.assertEqual(bio.pending, i+1)
1847 bio.read()
1848 self.assertEqual(bio.pending, 0)
1849
1850 def test_buffer_types(self):
1851 bio = ssl.MemoryBIO()
1852 bio.write(b'foo')
1853 self.assertEqual(bio.read(), b'foo')
1854 bio.write(bytearray(b'bar'))
1855 self.assertEqual(bio.read(), b'bar')
1856 bio.write(memoryview(b'baz'))
1857 self.assertEqual(bio.read(), b'baz')
1858
1859 def test_error_types(self):
1860 bio = ssl.MemoryBIO()
1861 self.assertRaises(TypeError, bio.write, 'foo')
1862 self.assertRaises(TypeError, bio.write, None)
1863 self.assertRaises(TypeError, bio.write, True)
1864 self.assertRaises(TypeError, bio.write, 1)
1865
1866
Christian Heimes9d50ab52018-02-27 10:17:30 +01001867class SSLObjectTests(unittest.TestCase):
1868 def test_private_init(self):
1869 bio = ssl.MemoryBIO()
1870 with self.assertRaisesRegex(TypeError, "public constructor"):
1871 ssl.SSLObject(bio, bio)
1872
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001873 def test_unwrap(self):
1874 client_ctx, server_ctx, hostname = testing_context()
1875 c_in = ssl.MemoryBIO()
1876 c_out = ssl.MemoryBIO()
1877 s_in = ssl.MemoryBIO()
1878 s_out = ssl.MemoryBIO()
1879 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1880 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1881
1882 # Loop on the handshake for a bit to get it settled
1883 for _ in range(5):
1884 try:
1885 client.do_handshake()
1886 except ssl.SSLWantReadError:
1887 pass
1888 if c_out.pending:
1889 s_in.write(c_out.read())
1890 try:
1891 server.do_handshake()
1892 except ssl.SSLWantReadError:
1893 pass
1894 if s_out.pending:
1895 c_in.write(s_out.read())
1896 # Now the handshakes should be complete (don't raise WantReadError)
1897 client.do_handshake()
1898 server.do_handshake()
1899
1900 # Now if we unwrap one side unilaterally, it should send close-notify
1901 # and raise WantReadError:
1902 with self.assertRaises(ssl.SSLWantReadError):
1903 client.unwrap()
1904
1905 # But server.unwrap() does not raise, because it reads the client's
1906 # close-notify:
1907 s_in.write(c_out.read())
1908 server.unwrap()
1909
1910 # And now that the client gets the server's close-notify, it doesn't
1911 # raise either.
1912 c_in.write(s_out.read())
1913 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001914
Martin Panter3840b2a2016-03-27 01:53:46 +00001915class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001916 """Tests that connect to a simple server running in the background"""
1917
1918 def setUp(self):
juhovh49fdf112021-04-18 21:11:48 +10001919 self.server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1920 self.server_context.load_cert_chain(SIGNED_CERTFILE)
1921 server = ThreadedEchoServer(context=self.server_context)
Martin Panter3840b2a2016-03-27 01:53:46 +00001922 self.server_addr = (HOST, server.port)
1923 server.__enter__()
1924 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001925
Antoine Pitrou480a1242010-04-28 21:37:09 +00001926 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001927 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001928 cert_reqs=ssl.CERT_NONE) as s:
1929 s.connect(self.server_addr)
1930 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001931 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001932
Martin Panter3840b2a2016-03-27 01:53:46 +00001933 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001934 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001935 cert_reqs=ssl.CERT_REQUIRED,
1936 ca_certs=SIGNING_CA) as s:
1937 s.connect(self.server_addr)
1938 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001939 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001940
Martin Panter3840b2a2016-03-27 01:53:46 +00001941 def test_connect_fail(self):
1942 # This should fail because we have no verification certs. Connection
1943 # failure crashes ThreadedEchoServer, so run this in an independent
1944 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001945 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001946 cert_reqs=ssl.CERT_REQUIRED)
1947 self.addCleanup(s.close)
1948 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1949 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001950
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001951 def test_connect_ex(self):
1952 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02001953 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001954 cert_reqs=ssl.CERT_REQUIRED,
1955 ca_certs=SIGNING_CA)
1956 self.addCleanup(s.close)
1957 self.assertEqual(0, s.connect_ex(self.server_addr))
1958 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001959
1960 def test_non_blocking_connect_ex(self):
1961 # Issue #11326: non-blocking connect_ex() should allow handshake
1962 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02001963 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001964 cert_reqs=ssl.CERT_REQUIRED,
1965 ca_certs=SIGNING_CA,
1966 do_handshake_on_connect=False)
1967 self.addCleanup(s.close)
1968 s.setblocking(False)
1969 rc = s.connect_ex(self.server_addr)
1970 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1971 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
1972 # Wait for connect to finish
1973 select.select([], [s], [], 5.0)
1974 # Non-blocking handshake
1975 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001976 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00001977 s.do_handshake()
1978 break
1979 except ssl.SSLWantReadError:
1980 select.select([s], [], [], 5.0)
1981 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001982 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00001983 # SSL established
1984 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001985
Antoine Pitrou152efa22010-05-16 18:19:27 +00001986 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001987 # Same as test_connect, but with a separately created context
Christian Heimes2875c602021-04-19 07:27:10 +02001988 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1989 ctx.check_hostname = False
1990 ctx.verify_mode = ssl.CERT_NONE
Martin Panter3840b2a2016-03-27 01:53:46 +00001991 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1992 s.connect(self.server_addr)
1993 self.assertEqual({}, s.getpeercert())
1994 # Same with a server hostname
1995 with ctx.wrap_socket(socket.socket(socket.AF_INET),
1996 server_hostname="dummy") as s:
1997 s.connect(self.server_addr)
1998 ctx.verify_mode = ssl.CERT_REQUIRED
1999 # This should succeed because we specify the root cert
2000 ctx.load_verify_locations(SIGNING_CA)
2001 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2002 s.connect(self.server_addr)
2003 cert = s.getpeercert()
2004 self.assertTrue(cert)
2005
2006 def test_connect_with_context_fail(self):
2007 # This should fail because we have no verification certs. Connection
2008 # failure crashes ThreadedEchoServer, so run this in an independent
2009 # test method.
Christian Heimes2875c602021-04-19 07:27:10 +02002010 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2011 s = ctx.wrap_socket(
2012 socket.socket(socket.AF_INET),
2013 server_hostname=SIGNED_CERTFILE_HOSTNAME
2014 )
Martin Panter3840b2a2016-03-27 01:53:46 +00002015 self.addCleanup(s.close)
2016 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2017 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002018
2019 def test_connect_capath(self):
2020 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002021 # NOTE: the subject hashing algorithm has been changed between
2022 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2023 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002024 # filename) for this test to be portable across OpenSSL releases.
Christian Heimes2875c602021-04-19 07:27:10 +02002025 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002026 ctx.load_verify_locations(capath=CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002027 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2028 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002029 s.connect(self.server_addr)
2030 cert = s.getpeercert()
2031 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002032
Martin Panter3840b2a2016-03-27 01:53:46 +00002033 # Same with a bytes `capath` argument
Christian Heimes2875c602021-04-19 07:27:10 +02002034 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002035 ctx.load_verify_locations(capath=BYTES_CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002036 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2037 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002038 s.connect(self.server_addr)
2039 cert = s.getpeercert()
2040 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002041
Christian Heimesefff7062013-11-21 03:35:02 +01002042 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002043 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002044 pem = f.read()
2045 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002046 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002047 ctx.load_verify_locations(cadata=pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002048 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2049 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002050 s.connect(self.server_addr)
2051 cert = s.getpeercert()
2052 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002053
Martin Panter3840b2a2016-03-27 01:53:46 +00002054 # same with DER
Christian Heimes2875c602021-04-19 07:27:10 +02002055 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002056 ctx.load_verify_locations(cadata=der)
Christian Heimes2875c602021-04-19 07:27:10 +02002057 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2058 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002059 s.connect(self.server_addr)
2060 cert = s.getpeercert()
2061 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002062
Antoine Pitroue3220242010-04-24 11:13:53 +00002063 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2064 def test_makefile_close(self):
2065 # Issue #5238: creating a file-like object with makefile() shouldn't
2066 # delay closing the underlying "real socket" (here tested with its
2067 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002068 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002069 ss.connect(self.server_addr)
2070 fd = ss.fileno()
2071 f = ss.makefile()
2072 f.close()
2073 # The fd is still open
2074 os.read(fd, 0)
2075 # Closing the SSL socket should close the fd too
2076 ss.close()
2077 gc.collect()
2078 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002079 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002080 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002081
Antoine Pitrou480a1242010-04-28 21:37:09 +00002082 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002083 s = socket.socket(socket.AF_INET)
2084 s.connect(self.server_addr)
2085 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002086 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002087 cert_reqs=ssl.CERT_NONE,
2088 do_handshake_on_connect=False)
2089 self.addCleanup(s.close)
2090 count = 0
2091 while True:
2092 try:
2093 count += 1
2094 s.do_handshake()
2095 break
2096 except ssl.SSLWantReadError:
2097 select.select([s], [], [])
2098 except ssl.SSLWantWriteError:
2099 select.select([], [s], [])
2100 if support.verbose:
2101 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002102
Antoine Pitrou480a1242010-04-28 21:37:09 +00002103 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002104 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002105
juhovh49fdf112021-04-18 21:11:48 +10002106 def test_get_server_certificate_sni(self):
2107 host, port = self.server_addr
2108 server_names = []
2109
2110 # We store servername_cb arguments to make sure they match the host
2111 def servername_cb(ssl_sock, server_name, initial_context):
2112 server_names.append(server_name)
2113 self.server_context.set_servername_callback(servername_cb)
2114
2115 pem = ssl.get_server_certificate((host, port))
2116 if not pem:
2117 self.fail("No server certificate on %s:%s!" % (host, port))
2118
2119 pem = ssl.get_server_certificate((host, port), ca_certs=SIGNING_CA)
2120 if not pem:
2121 self.fail("No server certificate on %s:%s!" % (host, port))
2122 if support.verbose:
2123 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port, pem))
2124
2125 self.assertEqual(server_names, [host, host])
2126
Martin Panter3840b2a2016-03-27 01:53:46 +00002127 def test_get_server_certificate_fail(self):
2128 # Connection failure crashes ThreadedEchoServer, so run this in an
2129 # independent test method
2130 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002131
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002132 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002133 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002134 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2135 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002136 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002137 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2138 s.connect(self.server_addr)
2139 # Error checking can happen at instantiation or when connecting
2140 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2141 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002142 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002143 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2144 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002145
Christian Heimes9a5395a2013-06-17 15:44:12 +02002146 def test_get_ca_certs_capath(self):
2147 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002148 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002149 ctx.load_verify_locations(capath=CAPATH)
2150 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002151 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2152 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002153 s.connect(self.server_addr)
2154 cert = s.getpeercert()
2155 self.assertTrue(cert)
2156 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002157
Christian Heimes8e7f3942013-12-05 07:41:08 +01002158 def test_context_setget(self):
2159 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002160 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2161 ctx1.load_verify_locations(capath=CAPATH)
2162 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2163 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002164 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002165 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002166 ss.connect(self.server_addr)
2167 self.assertIs(ss.context, ctx1)
2168 self.assertIs(ss._sslobj.context, ctx1)
2169 ss.context = ctx2
2170 self.assertIs(ss.context, ctx2)
2171 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002172
2173 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2174 # A simple IO loop. Call func(*args) depending on the error we get
2175 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002176 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002177 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002178 count = 0
2179 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002180 if time.monotonic() > deadline:
2181 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002182 errno = None
2183 count += 1
2184 try:
2185 ret = func(*args)
2186 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002187 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002188 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002189 raise
2190 errno = e.errno
2191 # Get any data from the outgoing BIO irrespective of any error, and
2192 # send it to the socket.
2193 buf = outgoing.read()
2194 sock.sendall(buf)
2195 # If there's no error, we're done. For WANT_READ, we need to get
2196 # data from the socket and put it in the incoming BIO.
2197 if errno is None:
2198 break
2199 elif errno == ssl.SSL_ERROR_WANT_READ:
2200 buf = sock.recv(32768)
2201 if buf:
2202 incoming.write(buf)
2203 else:
2204 incoming.write_eof()
2205 if support.verbose:
2206 sys.stdout.write("Needed %d calls to complete %s().\n"
2207 % (count, func.__name__))
2208 return ret
2209
Martin Panter3840b2a2016-03-27 01:53:46 +00002210 def test_bio_handshake(self):
2211 sock = socket.socket(socket.AF_INET)
2212 self.addCleanup(sock.close)
2213 sock.connect(self.server_addr)
2214 incoming = ssl.MemoryBIO()
2215 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002216 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2217 self.assertTrue(ctx.check_hostname)
2218 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002219 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002220 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2221 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002222 self.assertIs(sslobj._sslobj.owner, sslobj)
2223 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002224 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002225 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002226 self.assertRaises(ValueError, sslobj.getpeercert)
2227 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2228 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2229 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2230 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002231 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002232 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002233 self.assertTrue(sslobj.getpeercert())
2234 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2235 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2236 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002237 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002238 except ssl.SSLSyscallError:
2239 # If the server shuts down the TCP connection without sending a
2240 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2241 pass
2242 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2243
2244 def test_bio_read_write_data(self):
2245 sock = socket.socket(socket.AF_INET)
2246 self.addCleanup(sock.close)
2247 sock.connect(self.server_addr)
2248 incoming = ssl.MemoryBIO()
2249 outgoing = ssl.MemoryBIO()
Christian Heimes2875c602021-04-19 07:27:10 +02002250 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2251 ctx.check_hostname = False
Martin Panter3840b2a2016-03-27 01:53:46 +00002252 ctx.verify_mode = ssl.CERT_NONE
2253 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2254 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2255 req = b'FOO\n'
2256 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2257 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2258 self.assertEqual(buf, b'foo\n')
2259 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002260
2261
Martin Panter3840b2a2016-03-27 01:53:46 +00002262class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002263
Martin Panter3840b2a2016-03-27 01:53:46 +00002264 def test_timeout_connect_ex(self):
2265 # Issue #12065: on a timeout, connect_ex() should return the original
2266 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002267 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002268 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002269 cert_reqs=ssl.CERT_REQUIRED,
2270 do_handshake_on_connect=False)
2271 self.addCleanup(s.close)
2272 s.settimeout(0.0000001)
2273 rc = s.connect_ex((REMOTE_HOST, 443))
2274 if rc == 0:
2275 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002276 elif rc == errno.ENETUNREACH:
2277 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002278 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2279
Serhiy Storchaka16994912020-04-25 10:06:29 +03002280 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002281 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002282 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002283 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2284 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2285
Martin Panter3840b2a2016-03-27 01:53:46 +00002286
2287def _test_get_server_certificate(test, host, port, cert=None):
2288 pem = ssl.get_server_certificate((host, port))
2289 if not pem:
2290 test.fail("No server certificate on %s:%s!" % (host, port))
2291
2292 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2293 if not pem:
2294 test.fail("No server certificate on %s:%s!" % (host, port))
2295 if support.verbose:
2296 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2297
2298def _test_get_server_certificate_fail(test, host, port):
2299 try:
2300 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2301 except ssl.SSLError as x:
2302 #should fail
2303 if support.verbose:
2304 sys.stdout.write("%s\n" % x)
2305 else:
2306 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2307
2308
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002309from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002310
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002311class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002312
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002313 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002314
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002315 """A mildly complicated class, because we want it to work both
2316 with and without the SSL wrapper around the socket connection, so
2317 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002318
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002319 def __init__(self, server, connsock, addr):
2320 self.server = server
2321 self.running = False
2322 self.sock = connsock
2323 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002324 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002325 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002326 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002327 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002328
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002329 def wrap_conn(self):
2330 try:
2331 self.sslconn = self.server.context.wrap_socket(
2332 self.sock, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002333 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002334 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002335 # We treat ConnectionResetError as though it were an
2336 # SSLError - OpenSSL on Ubuntu abruptly closes the
2337 # connection when asked to use an unsupported protocol.
2338 #
Christian Heimes529525f2018-05-23 22:24:45 +02002339 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2340 # tries to send session tickets after handshake.
2341 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002342 #
2343 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2344 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002345 self.server.conn_errors.append(str(e))
2346 if self.server.chatty:
2347 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2348 self.running = False
2349 self.close()
2350 return False
2351 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002352 # OSError may occur with wrong protocols, e.g. both
2353 # sides use PROTOCOL_TLS_SERVER.
2354 #
2355 # XXX Various errors can have happened here, for example
2356 # a mismatching protocol version, an invalid certificate,
2357 # or a low-level bug. This should be made more discriminating.
2358 #
2359 # bpo-31323: Store the exception as string to prevent
2360 # a reference leak: server -> conn_errors -> exception
2361 # -> traceback -> self (ConnectionHandler) -> server
2362 self.server.conn_errors.append(str(e))
2363 if self.server.chatty:
2364 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2365 self.running = False
2366 self.server.stop()
2367 self.close()
2368 return False
2369 else:
2370 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2371 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2372 cert = self.sslconn.getpeercert()
2373 if support.verbose and self.server.chatty:
2374 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2375 cert_binary = self.sslconn.getpeercert(True)
2376 if support.verbose and self.server.chatty:
2377 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2378 cipher = self.sslconn.cipher()
2379 if support.verbose and self.server.chatty:
2380 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002381 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002382
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002383 def read(self):
2384 if self.sslconn:
2385 return self.sslconn.read()
2386 else:
2387 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002388
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002389 def write(self, bytes):
2390 if self.sslconn:
2391 return self.sslconn.write(bytes)
2392 else:
2393 return self.sock.send(bytes)
2394
2395 def close(self):
2396 if self.sslconn:
2397 self.sslconn.close()
2398 else:
2399 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002400
Antoine Pitrou480a1242010-04-28 21:37:09 +00002401 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002402 self.running = True
2403 if not self.server.starttls_server:
2404 if not self.wrap_conn():
2405 return
2406 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002407 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002408 msg = self.read()
2409 stripped = msg.strip()
2410 if not stripped:
2411 # eof, so quit this handler
2412 self.running = False
2413 try:
2414 self.sock = self.sslconn.unwrap()
2415 except OSError:
2416 # Many tests shut the TCP connection down
2417 # without an SSL shutdown. This causes
2418 # unwrap() to raise OSError with errno=0!
2419 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002420 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002421 self.sslconn = None
2422 self.close()
2423 elif stripped == b'over':
2424 if support.verbose and self.server.connectionchatty:
2425 sys.stdout.write(" server: client closed connection\n")
2426 self.close()
2427 return
2428 elif (self.server.starttls_server and
2429 stripped == b'STARTTLS'):
2430 if support.verbose and self.server.connectionchatty:
2431 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2432 self.write(b"OK\n")
2433 if not self.wrap_conn():
2434 return
2435 elif (self.server.starttls_server and self.sslconn
2436 and stripped == b'ENDTLS'):
2437 if support.verbose and self.server.connectionchatty:
2438 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2439 self.write(b"OK\n")
2440 self.sock = self.sslconn.unwrap()
2441 self.sslconn = None
2442 if support.verbose and self.server.connectionchatty:
2443 sys.stdout.write(" server: connection is now unencrypted...\n")
2444 elif stripped == b'CB tls-unique':
2445 if support.verbose and self.server.connectionchatty:
2446 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2447 data = self.sslconn.get_channel_binding("tls-unique")
2448 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002449 elif stripped == b'PHA':
2450 if support.verbose and self.server.connectionchatty:
2451 sys.stdout.write(" server: initiating post handshake auth\n")
2452 try:
2453 self.sslconn.verify_client_post_handshake()
2454 except ssl.SSLError as e:
2455 self.write(repr(e).encode("us-ascii") + b"\n")
2456 else:
2457 self.write(b"OK\n")
2458 elif stripped == b'HASCERT':
2459 if self.sslconn.getpeercert() is not None:
2460 self.write(b'TRUE\n')
2461 else:
2462 self.write(b'FALSE\n')
2463 elif stripped == b'GETCERT':
2464 cert = self.sslconn.getpeercert()
2465 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002466 else:
2467 if (support.verbose and
2468 self.server.connectionchatty):
2469 ctype = (self.sslconn and "encrypted") or "unencrypted"
2470 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2471 % (msg, ctype, msg.lower(), ctype))
2472 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002473 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002474 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2475 # when connection is not shut down gracefully.
2476 if self.server.chatty and support.verbose:
2477 sys.stdout.write(
2478 " Connection reset by peer: {}\n".format(
2479 self.addr)
2480 )
2481 self.close()
2482 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002483 except ssl.SSLError as err:
2484 # On Windows sometimes test_pha_required_nocert receives the
2485 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2486 # before the 'tlsv13 alert certificate required' exception.
2487 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2488 # is received test_pha_required_nocert fails with ConnectionResetError
2489 # because the underlying socket is closed
2490 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2491 if self.server.chatty and support.verbose:
2492 sys.stdout.write(err.args[1])
2493 # test_pha_required_nocert is expecting this exception
2494 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002495 except OSError:
2496 if self.server.chatty:
2497 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002498 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002499 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002500
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002501 # normally, we'd just stop here, but for the test
2502 # harness, we want to stop the server
2503 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002504
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002505 def __init__(self, certificate=None, ssl_version=None,
2506 certreqs=None, cacerts=None,
2507 chatty=True, connectionchatty=False, starttls_server=False,
Christian Heimes2875c602021-04-19 07:27:10 +02002508 alpn_protocols=None,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002509 ciphers=None, context=None):
2510 if context:
2511 self.context = context
2512 else:
2513 self.context = ssl.SSLContext(ssl_version
2514 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002515 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002516 self.context.verify_mode = (certreqs if certreqs is not None
2517 else ssl.CERT_NONE)
2518 if cacerts:
2519 self.context.load_verify_locations(cacerts)
2520 if certificate:
2521 self.context.load_cert_chain(certificate)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002522 if alpn_protocols:
2523 self.context.set_alpn_protocols(alpn_protocols)
2524 if ciphers:
2525 self.context.set_ciphers(ciphers)
2526 self.chatty = chatty
2527 self.connectionchatty = connectionchatty
2528 self.starttls_server = starttls_server
2529 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002530 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002531 self.flag = None
2532 self.active = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002533 self.selected_alpn_protocols = []
2534 self.shared_ciphers = []
2535 self.conn_errors = []
2536 threading.Thread.__init__(self)
2537 self.daemon = True
2538
2539 def __enter__(self):
2540 self.start(threading.Event())
2541 self.flag.wait()
2542 return self
2543
2544 def __exit__(self, *args):
2545 self.stop()
2546 self.join()
2547
2548 def start(self, flag=None):
2549 self.flag = flag
2550 threading.Thread.start(self)
2551
2552 def run(self):
2553 self.sock.settimeout(0.05)
2554 self.sock.listen()
2555 self.active = True
2556 if self.flag:
2557 # signal an event
2558 self.flag.set()
2559 while self.active:
2560 try:
2561 newconn, connaddr = self.sock.accept()
2562 if support.verbose and self.chatty:
2563 sys.stdout.write(' server: new connection from '
2564 + repr(connaddr) + '\n')
2565 handler = self.ConnectionHandler(self, newconn, connaddr)
2566 handler.start()
2567 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002568 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002569 pass
2570 except KeyboardInterrupt:
2571 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002572 except BaseException as e:
2573 if support.verbose and self.chatty:
2574 sys.stdout.write(
2575 ' connection handling failed: ' + repr(e) + '\n')
2576
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002577 self.sock.close()
2578
2579 def stop(self):
2580 self.active = False
2581
2582class AsyncoreEchoServer(threading.Thread):
2583
2584 # this one's based on asyncore.dispatcher
2585
2586 class EchoServer (asyncore.dispatcher):
2587
2588 class ConnectionHandler(asyncore.dispatcher_with_send):
2589
2590 def __init__(self, conn, certfile):
2591 self.socket = test_wrap_socket(conn, server_side=True,
2592 certfile=certfile,
2593 do_handshake_on_connect=False)
2594 asyncore.dispatcher_with_send.__init__(self, self.socket)
2595 self._ssl_accepting = True
2596 self._do_ssl_handshake()
2597
2598 def readable(self):
2599 if isinstance(self.socket, ssl.SSLSocket):
2600 while self.socket.pending() > 0:
2601 self.handle_read_event()
2602 return True
2603
2604 def _do_ssl_handshake(self):
2605 try:
2606 self.socket.do_handshake()
2607 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2608 return
2609 except ssl.SSLEOFError:
2610 return self.handle_close()
2611 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002612 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002613 except OSError as err:
2614 if err.args[0] == errno.ECONNABORTED:
2615 return self.handle_close()
2616 else:
2617 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002618
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002619 def handle_read(self):
2620 if self._ssl_accepting:
2621 self._do_ssl_handshake()
2622 else:
2623 data = self.recv(1024)
2624 if support.verbose:
2625 sys.stdout.write(" server: read %s from client\n" % repr(data))
2626 if not data:
2627 self.close()
2628 else:
2629 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002630
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002631 def handle_close(self):
2632 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002633 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002634 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002635
2636 def handle_error(self):
2637 raise
2638
Trent Nelson78520002008-04-10 20:54:35 +00002639 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002640 self.certfile = certfile
2641 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002642 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002643 asyncore.dispatcher.__init__(self, sock)
2644 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002645
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002646 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002647 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002648 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2649 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002650
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002651 def handle_error(self):
2652 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002653
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002654 def __init__(self, certfile):
2655 self.flag = None
2656 self.active = False
2657 self.server = self.EchoServer(certfile)
2658 self.port = self.server.port
2659 threading.Thread.__init__(self)
2660 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002661
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002662 def __str__(self):
2663 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002664
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002665 def __enter__(self):
2666 self.start(threading.Event())
2667 self.flag.wait()
2668 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002669
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002670 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002671 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002672 sys.stdout.write(" cleanup: stopping server.\n")
2673 self.stop()
2674 if support.verbose:
2675 sys.stdout.write(" cleanup: joining server thread.\n")
2676 self.join()
2677 if support.verbose:
2678 sys.stdout.write(" cleanup: successfully joined.\n")
2679 # make sure that ConnectionHandler is removed from socket_map
2680 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002681
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002682 def start (self, flag=None):
2683 self.flag = flag
2684 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002685
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002686 def run(self):
2687 self.active = True
2688 if self.flag:
2689 self.flag.set()
2690 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002691 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002692 asyncore.loop(1)
2693 except:
2694 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002695
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002696 def stop(self):
2697 self.active = False
2698 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002699
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002700def server_params_test(client_context, server_context, indata=b"FOO\n",
2701 chatty=True, connectionchatty=False, sni_name=None,
2702 session=None):
2703 """
2704 Launch a server, connect a client to it and try various reads
2705 and writes.
2706 """
2707 stats = {}
2708 server = ThreadedEchoServer(context=server_context,
2709 chatty=chatty,
2710 connectionchatty=False)
2711 with server:
2712 with client_context.wrap_socket(socket.socket(),
2713 server_hostname=sni_name, session=session) as s:
2714 s.connect((HOST, server.port))
2715 for arg in [indata, bytearray(indata), memoryview(indata)]:
2716 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002717 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002718 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002719 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002720 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002721 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002722 if connectionchatty:
2723 if support.verbose:
2724 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002725 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002726 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002727 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2728 % (outdata[:20], len(outdata),
2729 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002730 s.write(b"over\n")
2731 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002732 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002733 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002734 stats.update({
2735 'compression': s.compression(),
2736 'cipher': s.cipher(),
2737 'peercert': s.getpeercert(),
2738 'client_alpn_protocol': s.selected_alpn_protocol(),
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002739 'version': s.version(),
2740 'session_reused': s.session_reused,
2741 'session': s.session,
2742 })
2743 s.close()
2744 stats['server_alpn_protocols'] = server.selected_alpn_protocols
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002745 stats['server_shared_ciphers'] = server.shared_ciphers
2746 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002747
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002748def try_protocol_combo(server_protocol, client_protocol, expect_success,
2749 certsreqs=None, server_options=0, client_options=0):
2750 """
2751 Try to SSL-connect using *client_protocol* to *server_protocol*.
2752 If *expect_success* is true, assert that the connection succeeds,
2753 if it's false, assert that the connection fails.
2754 Also, if *expect_success* is a string, assert that it is the protocol
2755 version actually used by the connection.
2756 """
2757 if certsreqs is None:
2758 certsreqs = ssl.CERT_NONE
2759 certtype = {
2760 ssl.CERT_NONE: "CERT_NONE",
2761 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2762 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2763 }[certsreqs]
2764 if support.verbose:
2765 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2766 sys.stdout.write(formatstr %
2767 (ssl.get_protocol_name(client_protocol),
2768 ssl.get_protocol_name(server_protocol),
2769 certtype))
Christian Heimes2875c602021-04-19 07:27:10 +02002770
2771 with warnings_helper.check_warnings():
2772 # ignore Deprecation warnings
2773 client_context = ssl.SSLContext(client_protocol)
2774 client_context.options |= client_options
2775 server_context = ssl.SSLContext(server_protocol)
2776 server_context.options |= server_options
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002777
Victor Stinner3ef63442019-02-19 18:06:03 +01002778 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2779 if (min_version is not None
Christian Heimes2875c602021-04-19 07:27:10 +02002780 # SSLContext.minimum_version is only available on recent OpenSSL
2781 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2782 and hasattr(server_context, 'minimum_version')
2783 and server_protocol == ssl.PROTOCOL_TLS
2784 and server_context.minimum_version > min_version
2785 ):
Victor Stinner3ef63442019-02-19 18:06:03 +01002786 # If OpenSSL configuration is strict and requires more recent TLS
2787 # version, we have to change the minimum to test old TLS versions.
Christian Heimes2875c602021-04-19 07:27:10 +02002788 with warnings_helper.check_warnings():
2789 server_context.minimum_version = min_version
Victor Stinner3ef63442019-02-19 18:06:03 +01002790
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002791 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2792 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2793 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002794 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002795 client_context.set_ciphers("ALL")
2796
Christian Heimesf6c6b582021-03-18 23:06:50 +01002797 seclevel_workaround(server_context, client_context)
2798
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002799 for ctx in (client_context, server_context):
2800 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002801 ctx.load_cert_chain(SIGNED_CERTFILE)
2802 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002803 try:
2804 stats = server_params_test(client_context, server_context,
2805 chatty=False, connectionchatty=False)
2806 # Protocol mismatch can result in either an SSLError, or a
2807 # "Connection reset by peer" error.
2808 except ssl.SSLError:
2809 if expect_success:
2810 raise
2811 except OSError as e:
2812 if expect_success or e.errno != errno.ECONNRESET:
2813 raise
2814 else:
2815 if not expect_success:
2816 raise AssertionError(
2817 "Client protocol %s succeeded with server protocol %s!"
2818 % (ssl.get_protocol_name(client_protocol),
2819 ssl.get_protocol_name(server_protocol)))
2820 elif (expect_success is not True
2821 and expect_success != stats['version']):
2822 raise AssertionError("version mismatch: expected %r, got %r"
2823 % (expect_success, stats['version']))
2824
2825
2826class ThreadedTests(unittest.TestCase):
2827
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002828 def test_echo(self):
2829 """Basic test of an SSL client connecting to a server"""
2830 if support.verbose:
2831 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002832
Christian Heimesa170fa12017-09-15 20:27:30 +02002833 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002834
2835 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2836 server_params_test(client_context=client_context,
2837 server_context=server_context,
2838 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002839 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002840
2841 client_context.check_hostname = False
2842 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2843 with self.assertRaises(ssl.SSLError) as e:
2844 server_params_test(client_context=server_context,
2845 server_context=client_context,
2846 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002847 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002848 self.assertIn('called a function you should not call',
2849 str(e.exception))
2850
2851 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2852 with self.assertRaises(ssl.SSLError) as e:
2853 server_params_test(client_context=server_context,
2854 server_context=server_context,
2855 chatty=True, connectionchatty=True)
2856 self.assertIn('called a function you should not call',
2857 str(e.exception))
2858
2859 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2860 with self.assertRaises(ssl.SSLError) as e:
2861 server_params_test(client_context=server_context,
2862 server_context=client_context,
2863 chatty=True, connectionchatty=True)
2864 self.assertIn('called a function you should not call',
2865 str(e.exception))
2866
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002867 def test_getpeercert(self):
2868 if support.verbose:
2869 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002870
2871 client_context, server_context, hostname = testing_context()
2872 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002873 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002874 with client_context.wrap_socket(socket.socket(),
2875 do_handshake_on_connect=False,
2876 server_hostname=hostname) as s:
2877 s.connect((HOST, server.port))
2878 # getpeercert() raise ValueError while the handshake isn't
2879 # done.
2880 with self.assertRaises(ValueError):
2881 s.getpeercert()
2882 s.do_handshake()
2883 cert = s.getpeercert()
2884 self.assertTrue(cert, "Can't get peer certificate.")
2885 cipher = s.cipher()
2886 if support.verbose:
2887 sys.stdout.write(pprint.pformat(cert) + '\n')
2888 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2889 if 'subject' not in cert:
2890 self.fail("No subject field in certificate: %s." %
2891 pprint.pformat(cert))
2892 if ((('organizationName', 'Python Software Foundation'),)
2893 not in cert['subject']):
2894 self.fail(
2895 "Missing or invalid 'organizationName' field in certificate subject; "
2896 "should be 'Python Software Foundation'.")
2897 self.assertIn('notBefore', cert)
2898 self.assertIn('notAfter', cert)
2899 before = ssl.cert_time_to_seconds(cert['notBefore'])
2900 after = ssl.cert_time_to_seconds(cert['notAfter'])
2901 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002902
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002903 def test_crl_check(self):
2904 if support.verbose:
2905 sys.stdout.write("\n")
2906
Christian Heimesa170fa12017-09-15 20:27:30 +02002907 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002908
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002909 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002910 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002911
2912 # VERIFY_DEFAULT should pass
2913 server = ThreadedEchoServer(context=server_context, chatty=True)
2914 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002915 with client_context.wrap_socket(socket.socket(),
2916 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002917 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002918 cert = s.getpeercert()
2919 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002920
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002921 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002922 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002923
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002924 server = ThreadedEchoServer(context=server_context, chatty=True)
2925 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002926 with client_context.wrap_socket(socket.socket(),
2927 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002928 with self.assertRaisesRegex(ssl.SSLError,
2929 "certificate verify failed"):
2930 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002931
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002932 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002933 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002934
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002935 server = ThreadedEchoServer(context=server_context, chatty=True)
2936 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002937 with client_context.wrap_socket(socket.socket(),
2938 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002939 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002940 cert = s.getpeercert()
2941 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002942
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002943 def test_check_hostname(self):
2944 if support.verbose:
2945 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002946
Christian Heimesa170fa12017-09-15 20:27:30 +02002947 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002948
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002949 # correct hostname should verify
2950 server = ThreadedEchoServer(context=server_context, chatty=True)
2951 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002952 with client_context.wrap_socket(socket.socket(),
2953 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002954 s.connect((HOST, server.port))
2955 cert = s.getpeercert()
2956 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002957
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002958 # incorrect hostname should raise an exception
2959 server = ThreadedEchoServer(context=server_context, chatty=True)
2960 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002961 with client_context.wrap_socket(socket.socket(),
2962 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01002963 with self.assertRaisesRegex(
2964 ssl.CertificateError,
2965 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002966 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002967
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002968 # missing server_hostname arg should cause an exception, too
2969 server = ThreadedEchoServer(context=server_context, chatty=True)
2970 with server:
2971 with socket.socket() as s:
2972 with self.assertRaisesRegex(ValueError,
2973 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02002974 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002975
Christian Heimesb467d9a2021-04-17 10:07:19 +02002976 @unittest.skipUnless(
2977 ssl.HAS_NEVER_CHECK_COMMON_NAME, "test requires hostname_checks_common_name"
2978 )
2979 def test_hostname_checks_common_name(self):
2980 client_context, server_context, hostname = testing_context()
2981 assert client_context.hostname_checks_common_name
2982 client_context.hostname_checks_common_name = False
2983
2984 # default cert has a SAN
2985 server = ThreadedEchoServer(context=server_context, chatty=True)
2986 with server:
2987 with client_context.wrap_socket(socket.socket(),
2988 server_hostname=hostname) as s:
2989 s.connect((HOST, server.port))
2990
2991 client_context, server_context, hostname = testing_context(NOSANFILE)
2992 client_context.hostname_checks_common_name = False
2993 server = ThreadedEchoServer(context=server_context, chatty=True)
2994 with server:
2995 with client_context.wrap_socket(socket.socket(),
2996 server_hostname=hostname) as s:
2997 with self.assertRaises(ssl.SSLCertVerificationError):
2998 s.connect((HOST, server.port))
2999
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003000 def test_ecc_cert(self):
3001 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3002 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003003 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003004 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3005
3006 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3007 # load ECC cert
3008 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3009
3010 # correct hostname should verify
3011 server = ThreadedEchoServer(context=server_context, chatty=True)
3012 with server:
3013 with client_context.wrap_socket(socket.socket(),
3014 server_hostname=hostname) as s:
3015 s.connect((HOST, server.port))
3016 cert = s.getpeercert()
3017 self.assertTrue(cert, "Can't get peer certificate.")
3018 cipher = s.cipher()[0].split('-')
3019 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3020
3021 def test_dual_rsa_ecc(self):
3022 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3023 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003024 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3025 # algorithms.
3026 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003027 # only ECDSA certs
3028 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3029 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3030
3031 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3032 # load ECC and RSA key/cert pairs
3033 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3034 server_context.load_cert_chain(SIGNED_CERTFILE)
3035
3036 # correct hostname should verify
3037 server = ThreadedEchoServer(context=server_context, chatty=True)
3038 with server:
3039 with client_context.wrap_socket(socket.socket(),
3040 server_hostname=hostname) as s:
3041 s.connect((HOST, server.port))
3042 cert = s.getpeercert()
3043 self.assertTrue(cert, "Can't get peer certificate.")
3044 cipher = s.cipher()[0].split('-')
3045 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3046
Christian Heimes66e57422018-01-29 14:25:13 +01003047 def test_check_hostname_idn(self):
3048 if support.verbose:
3049 sys.stdout.write("\n")
3050
Christian Heimes11a14932018-02-24 02:35:08 +01003051 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003052 server_context.load_cert_chain(IDNSANSFILE)
3053
Christian Heimes11a14932018-02-24 02:35:08 +01003054 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003055 context.verify_mode = ssl.CERT_REQUIRED
3056 context.check_hostname = True
3057 context.load_verify_locations(SIGNING_CA)
3058
3059 # correct hostname should verify, when specified in several
3060 # different ways
3061 idn_hostnames = [
3062 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003063 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003064 ('xn--knig-5qa.idn.pythontest.net',
3065 'xn--knig-5qa.idn.pythontest.net'),
3066 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003067 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003068
3069 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003070 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003071 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3072 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3073 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003074 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3075
3076 # ('königsgäßchen.idna2008.pythontest.net',
3077 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3078 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3079 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3080 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3081 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3082
Christian Heimes66e57422018-01-29 14:25:13 +01003083 ]
3084 for server_hostname, expected_hostname in idn_hostnames:
3085 server = ThreadedEchoServer(context=server_context, chatty=True)
3086 with server:
3087 with context.wrap_socket(socket.socket(),
3088 server_hostname=server_hostname) as s:
3089 self.assertEqual(s.server_hostname, expected_hostname)
3090 s.connect((HOST, server.port))
3091 cert = s.getpeercert()
3092 self.assertEqual(s.server_hostname, expected_hostname)
3093 self.assertTrue(cert, "Can't get peer certificate.")
3094
Christian Heimes66e57422018-01-29 14:25:13 +01003095 # incorrect hostname should raise an exception
3096 server = ThreadedEchoServer(context=server_context, chatty=True)
3097 with server:
3098 with context.wrap_socket(socket.socket(),
3099 server_hostname="python.example.org") as s:
3100 with self.assertRaises(ssl.CertificateError):
3101 s.connect((HOST, server.port))
3102
Christian Heimes529525f2018-05-23 22:24:45 +02003103 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003104 """Connecting when the server rejects the client's certificate
3105
3106 Launch a server with CERT_REQUIRED, and check that trying to
3107 connect to it with a wrong client certificate fails.
3108 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003109 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003110 # load client cert that is not signed by trusted CA
3111 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003112 # require TLS client authentication
3113 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003114 # TLS 1.3 has different handshake
3115 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003116
3117 server = ThreadedEchoServer(
3118 context=server_context, chatty=True, connectionchatty=True,
3119 )
3120
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003121 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003122 client_context.wrap_socket(socket.socket(),
3123 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003124 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003125 # Expect either an SSL error about the server rejecting
3126 # the connection, or a low-level connection reset (which
3127 # sometimes happens on Windows)
3128 s.connect((HOST, server.port))
3129 except ssl.SSLError as e:
3130 if support.verbose:
3131 sys.stdout.write("\nSSLError is %r\n" % e)
3132 except OSError as e:
3133 if e.errno != errno.ECONNRESET:
3134 raise
3135 if support.verbose:
3136 sys.stdout.write("\nsocket.error is %r\n" % e)
3137 else:
3138 self.fail("Use of invalid cert should have failed!")
3139
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003140 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003141 def test_wrong_cert_tls13(self):
3142 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003143 # load client cert that is not signed by trusted CA
3144 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003145 server_context.verify_mode = ssl.CERT_REQUIRED
3146 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3147 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3148
3149 server = ThreadedEchoServer(
3150 context=server_context, chatty=True, connectionchatty=True,
3151 )
3152 with server, \
3153 client_context.wrap_socket(socket.socket(),
3154 server_hostname=hostname) as s:
3155 # TLS 1.3 perform client cert exchange after handshake
3156 s.connect((HOST, server.port))
3157 try:
3158 s.write(b'data')
3159 s.read(4)
3160 except ssl.SSLError as e:
3161 if support.verbose:
3162 sys.stdout.write("\nSSLError is %r\n" % e)
3163 except OSError as e:
3164 if e.errno != errno.ECONNRESET:
3165 raise
3166 if support.verbose:
3167 sys.stdout.write("\nsocket.error is %r\n" % e)
3168 else:
3169 self.fail("Use of invalid cert should have failed!")
3170
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003171 def test_rude_shutdown(self):
3172 """A brutal shutdown of an SSL server should raise an OSError
3173 in the client when attempting handshake.
3174 """
3175 listener_ready = threading.Event()
3176 listener_gone = threading.Event()
3177
3178 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003179 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003180
3181 # `listener` runs in a thread. It sits in an accept() until
3182 # the main thread connects. Then it rudely closes the socket,
3183 # and sets Event `listener_gone` to let the main thread know
3184 # the socket is gone.
3185 def listener():
3186 s.listen()
3187 listener_ready.set()
3188 newsock, addr = s.accept()
3189 newsock.close()
3190 s.close()
3191 listener_gone.set()
3192
3193 def connector():
3194 listener_ready.wait()
3195 with socket.socket() as c:
3196 c.connect((HOST, port))
3197 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003198 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003199 ssl_sock = test_wrap_socket(c)
3200 except OSError:
3201 pass
3202 else:
3203 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003204
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003205 t = threading.Thread(target=listener)
3206 t.start()
3207 try:
3208 connector()
3209 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003210 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003211
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003212 def test_ssl_cert_verify_error(self):
3213 if support.verbose:
3214 sys.stdout.write("\n")
3215
3216 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3217 server_context.load_cert_chain(SIGNED_CERTFILE)
3218
3219 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3220
3221 server = ThreadedEchoServer(context=server_context, chatty=True)
3222 with server:
3223 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003224 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003225 try:
3226 s.connect((HOST, server.port))
3227 except ssl.SSLError as e:
3228 msg = 'unable to get local issuer certificate'
3229 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3230 self.assertEqual(e.verify_code, 20)
3231 self.assertEqual(e.verify_message, msg)
3232 self.assertIn(msg, repr(e))
3233 self.assertIn('certificate verify failed', repr(e))
3234
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003235 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003236 def test_protocol_sslv2(self):
3237 """Connecting to an SSLv2 server with various client options"""
3238 if support.verbose:
3239 sys.stdout.write("\n")
3240 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3241 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3242 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003243 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003244 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003245 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3246 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3247 # SSLv23 client with specific SSL options
3248 if no_sslv2_implies_sslv3_hello():
3249 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003250 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003251 client_options=ssl.OP_NO_SSLv2)
Christian Heimesa170fa12017-09-15 20:27:30 +02003252 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003253 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003254 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003255 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003256
Christian Heimesa170fa12017-09-15 20:27:30 +02003257 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003258 """Connecting to an SSLv23 server with various client options"""
3259 if support.verbose:
3260 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003261 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003262 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003263 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003264 except OSError as x:
3265 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3266 if support.verbose:
3267 sys.stdout.write(
3268 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3269 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003270 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003271 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3272 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003273 if has_tls_version('TLSv1'):
3274 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003275
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003276 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003277 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3278 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003279 if has_tls_version('TLSv1'):
3280 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003281
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003282 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003283 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3284 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003285 if has_tls_version('TLSv1'):
3286 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003287
3288 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003289 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003290 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003291 server_options=ssl.OP_NO_SSLv3)
3292 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003293 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003294 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003295 if has_tls_version('TLSv1'):
3296 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3297 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003298
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003299 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003300 def test_protocol_sslv3(self):
3301 """Connecting to an SSLv3 server with various client options"""
3302 if support.verbose:
3303 sys.stdout.write("\n")
3304 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3305 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3306 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003307 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003308 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003309 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003310 client_options=ssl.OP_NO_SSLv3)
3311 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3312 if no_sslv2_implies_sslv3_hello():
3313 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003314 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003315 False, client_options=ssl.OP_NO_SSLv2)
3316
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003317 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003318 def test_protocol_tlsv1(self):
3319 """Connecting to a TLSv1 server with various client options"""
3320 if support.verbose:
3321 sys.stdout.write("\n")
3322 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3323 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3324 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003325 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003326 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003327 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003328 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003329 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003330 client_options=ssl.OP_NO_TLSv1)
3331
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003332 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003333 def test_protocol_tlsv1_1(self):
3334 """Connecting to a TLSv1.1 server with various client options.
3335 Testing against older TLS versions."""
3336 if support.verbose:
3337 sys.stdout.write("\n")
3338 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003339 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003340 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003341 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003342 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003343 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003344 client_options=ssl.OP_NO_TLSv1_1)
3345
Christian Heimesa170fa12017-09-15 20:27:30 +02003346 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003347 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3348 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003349
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003350 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003351 def test_protocol_tlsv1_2(self):
3352 """Connecting to a TLSv1.2 server with various client options.
3353 Testing against older TLS versions."""
3354 if support.verbose:
3355 sys.stdout.write("\n")
3356 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3357 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3358 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003359 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003360 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003361 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003362 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003363 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003364 client_options=ssl.OP_NO_TLSv1_2)
3365
Christian Heimesa170fa12017-09-15 20:27:30 +02003366 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003367 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3368 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3369 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3370 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3371
3372 def test_starttls(self):
3373 """Switching from clear text to encrypted and back again."""
3374 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3375
3376 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003377 starttls_server=True,
3378 chatty=True,
3379 connectionchatty=True)
3380 wrapped = False
3381 with server:
3382 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003383 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003384 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003385 if support.verbose:
3386 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003387 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003388 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003389 sys.stdout.write(
3390 " client: sending %r...\n" % indata)
3391 if wrapped:
3392 conn.write(indata)
3393 outdata = conn.read()
3394 else:
3395 s.send(indata)
3396 outdata = s.recv(1024)
3397 msg = outdata.strip().lower()
3398 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3399 # STARTTLS ok, switch to secure mode
3400 if support.verbose:
3401 sys.stdout.write(
3402 " client: read %r from server, starting TLS...\n"
3403 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003404 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003405 wrapped = True
3406 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3407 # ENDTLS ok, switch back to clear text
3408 if support.verbose:
3409 sys.stdout.write(
3410 " client: read %r from server, ending TLS...\n"
3411 % msg)
3412 s = conn.unwrap()
3413 wrapped = False
3414 else:
3415 if support.verbose:
3416 sys.stdout.write(
3417 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003418 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003419 sys.stdout.write(" client: closing connection.\n")
3420 if wrapped:
3421 conn.write(b"over\n")
3422 else:
3423 s.send(b"over\n")
3424 if wrapped:
3425 conn.close()
3426 else:
3427 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003428
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003429 def test_socketserver(self):
3430 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003431 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003432 # try to connect
3433 if support.verbose:
3434 sys.stdout.write('\n')
3435 with open(CERTFILE, 'rb') as f:
3436 d1 = f.read()
3437 d2 = ''
3438 # now fetch the same data from the HTTPS server
3439 url = 'https://localhost:%d/%s' % (
3440 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003441 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003442 f = urllib.request.urlopen(url, context=context)
3443 try:
3444 dlen = f.info().get("content-length")
3445 if dlen and (int(dlen) > 0):
3446 d2 = f.read(int(dlen))
3447 if support.verbose:
3448 sys.stdout.write(
3449 " client: read %d bytes from remote server '%s'\n"
3450 % (len(d2), server))
3451 finally:
3452 f.close()
3453 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003454
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003455 def test_asyncore_server(self):
3456 """Check the example asyncore integration."""
3457 if support.verbose:
3458 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003459
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003460 indata = b"FOO\n"
3461 server = AsyncoreEchoServer(CERTFILE)
3462 with server:
3463 s = test_wrap_socket(socket.socket())
3464 s.connect(('127.0.0.1', server.port))
3465 if support.verbose:
3466 sys.stdout.write(
3467 " client: sending %r...\n" % indata)
3468 s.write(indata)
3469 outdata = s.read()
3470 if support.verbose:
3471 sys.stdout.write(" client: read %r\n" % outdata)
3472 if outdata != indata.lower():
3473 self.fail(
3474 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3475 % (outdata[:20], len(outdata),
3476 indata[:20].lower(), len(indata)))
3477 s.write(b"over\n")
3478 if support.verbose:
3479 sys.stdout.write(" client: closing connection.\n")
3480 s.close()
3481 if support.verbose:
3482 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003483
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003484 def test_recv_send(self):
3485 """Test recv(), send() and friends."""
3486 if support.verbose:
3487 sys.stdout.write("\n")
3488
3489 server = ThreadedEchoServer(CERTFILE,
3490 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003491 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003492 cacerts=CERTFILE,
3493 chatty=True,
3494 connectionchatty=False)
3495 with server:
3496 s = test_wrap_socket(socket.socket(),
3497 server_side=False,
3498 certfile=CERTFILE,
3499 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003500 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003501 s.connect((HOST, server.port))
3502 # helper methods for standardising recv* method signatures
3503 def _recv_into():
3504 b = bytearray(b"\0"*100)
3505 count = s.recv_into(b)
3506 return b[:count]
3507
3508 def _recvfrom_into():
3509 b = bytearray(b"\0"*100)
3510 count, addr = s.recvfrom_into(b)
3511 return b[:count]
3512
3513 # (name, method, expect success?, *args, return value func)
3514 send_methods = [
3515 ('send', s.send, True, [], len),
3516 ('sendto', s.sendto, False, ["some.address"], len),
3517 ('sendall', s.sendall, True, [], lambda x: None),
3518 ]
3519 # (name, method, whether to expect success, *args)
3520 recv_methods = [
3521 ('recv', s.recv, True, []),
3522 ('recvfrom', s.recvfrom, False, ["some.address"]),
3523 ('recv_into', _recv_into, True, []),
3524 ('recvfrom_into', _recvfrom_into, False, []),
3525 ]
3526 data_prefix = "PREFIX_"
3527
3528 for (meth_name, send_meth, expect_success, args,
3529 ret_val_meth) in send_methods:
3530 indata = (data_prefix + meth_name).encode('ascii')
3531 try:
3532 ret = send_meth(indata, *args)
3533 msg = "sending with {}".format(meth_name)
3534 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3535 outdata = s.read()
3536 if outdata != indata.lower():
3537 self.fail(
3538 "While sending with <<{name:s}>> bad data "
3539 "<<{outdata:r}>> ({nout:d}) received; "
3540 "expected <<{indata:r}>> ({nin:d})\n".format(
3541 name=meth_name, outdata=outdata[:20],
3542 nout=len(outdata),
3543 indata=indata[:20], nin=len(indata)
3544 )
3545 )
3546 except ValueError as e:
3547 if expect_success:
3548 self.fail(
3549 "Failed to send with method <<{name:s}>>; "
3550 "expected to succeed.\n".format(name=meth_name)
3551 )
3552 if not str(e).startswith(meth_name):
3553 self.fail(
3554 "Method <<{name:s}>> failed with unexpected "
3555 "exception message: {exp:s}\n".format(
3556 name=meth_name, exp=e
3557 )
3558 )
3559
3560 for meth_name, recv_meth, expect_success, args in recv_methods:
3561 indata = (data_prefix + meth_name).encode('ascii')
3562 try:
3563 s.send(indata)
3564 outdata = recv_meth(*args)
3565 if outdata != indata.lower():
3566 self.fail(
3567 "While receiving with <<{name:s}>> bad data "
3568 "<<{outdata:r}>> ({nout:d}) received; "
3569 "expected <<{indata:r}>> ({nin:d})\n".format(
3570 name=meth_name, outdata=outdata[:20],
3571 nout=len(outdata),
3572 indata=indata[:20], nin=len(indata)
3573 )
3574 )
3575 except ValueError as e:
3576 if expect_success:
3577 self.fail(
3578 "Failed to receive with method <<{name:s}>>; "
3579 "expected to succeed.\n".format(name=meth_name)
3580 )
3581 if not str(e).startswith(meth_name):
3582 self.fail(
3583 "Method <<{name:s}>> failed with unexpected "
3584 "exception message: {exp:s}\n".format(
3585 name=meth_name, exp=e
3586 )
3587 )
3588 # consume data
3589 s.read()
3590
3591 # read(-1, buffer) is supported, even though read(-1) is not
3592 data = b"data"
3593 s.send(data)
3594 buffer = bytearray(len(data))
3595 self.assertEqual(s.read(-1, buffer), len(data))
3596 self.assertEqual(buffer, data)
3597
Christian Heimes888bbdc2017-09-07 14:18:21 -07003598 # sendall accepts bytes-like objects
3599 if ctypes is not None:
3600 ubyte = ctypes.c_ubyte * len(data)
3601 byteslike = ubyte.from_buffer_copy(data)
3602 s.sendall(byteslike)
3603 self.assertEqual(s.read(), data)
3604
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003605 # Make sure sendmsg et al are disallowed to avoid
3606 # inadvertent disclosure of data and/or corruption
3607 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003608 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003609 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3610 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3611 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003612 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003613 s.write(b"over\n")
3614
3615 self.assertRaises(ValueError, s.recv, -1)
3616 self.assertRaises(ValueError, s.read, -1)
3617
3618 s.close()
3619
3620 def test_recv_zero(self):
3621 server = ThreadedEchoServer(CERTFILE)
3622 server.__enter__()
3623 self.addCleanup(server.__exit__, None, None)
3624 s = socket.create_connection((HOST, server.port))
3625 self.addCleanup(s.close)
3626 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3627 self.addCleanup(s.close)
3628
3629 # recv/read(0) should return no data
3630 s.send(b"data")
3631 self.assertEqual(s.recv(0), b"")
3632 self.assertEqual(s.read(0), b"")
3633 self.assertEqual(s.read(), b"data")
3634
3635 # Should not block if the other end sends no data
3636 s.setblocking(False)
3637 self.assertEqual(s.recv(0), b"")
3638 self.assertEqual(s.recv_into(bytearray()), 0)
3639
3640 def test_nonblocking_send(self):
3641 server = ThreadedEchoServer(CERTFILE,
3642 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003643 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003644 cacerts=CERTFILE,
3645 chatty=True,
3646 connectionchatty=False)
3647 with server:
3648 s = test_wrap_socket(socket.socket(),
3649 server_side=False,
3650 certfile=CERTFILE,
3651 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003652 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003653 s.connect((HOST, server.port))
3654 s.setblocking(False)
3655
3656 # If we keep sending data, at some point the buffers
3657 # will be full and the call will block
3658 buf = bytearray(8192)
3659 def fill_buffer():
3660 while True:
3661 s.send(buf)
3662 self.assertRaises((ssl.SSLWantWriteError,
3663 ssl.SSLWantReadError), fill_buffer)
3664
3665 # Now read all the output and discard it
3666 s.setblocking(True)
3667 s.close()
3668
3669 def test_handshake_timeout(self):
3670 # Issue #5103: SSL handshake must respect the socket timeout
3671 server = socket.socket(socket.AF_INET)
3672 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003673 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003674 started = threading.Event()
3675 finish = False
3676
3677 def serve():
3678 server.listen()
3679 started.set()
3680 conns = []
3681 while not finish:
3682 r, w, e = select.select([server], [], [], 0.1)
3683 if server in r:
3684 # Let the socket hang around rather than having
3685 # it closed by garbage collection.
3686 conns.append(server.accept()[0])
3687 for sock in conns:
3688 sock.close()
3689
3690 t = threading.Thread(target=serve)
3691 t.start()
3692 started.wait()
3693
3694 try:
3695 try:
3696 c = socket.socket(socket.AF_INET)
3697 c.settimeout(0.2)
3698 c.connect((host, port))
3699 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003700 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003701 test_wrap_socket, c)
3702 finally:
3703 c.close()
3704 try:
3705 c = socket.socket(socket.AF_INET)
3706 c = test_wrap_socket(c)
3707 c.settimeout(0.2)
3708 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003709 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003710 c.connect, (host, port))
3711 finally:
3712 c.close()
3713 finally:
3714 finish = True
3715 t.join()
3716 server.close()
3717
3718 def test_server_accept(self):
3719 # Issue #16357: accept() on a SSLSocket created through
3720 # SSLContext.wrap_socket().
Christian Heimes2875c602021-04-19 07:27:10 +02003721 client_ctx, server_ctx, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003722 server = socket.socket(socket.AF_INET)
3723 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003724 port = socket_helper.bind_port(server)
Christian Heimes2875c602021-04-19 07:27:10 +02003725 server = server_ctx.wrap_socket(server, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003726 self.assertTrue(server.server_side)
3727
3728 evt = threading.Event()
3729 remote = None
3730 peer = None
3731 def serve():
3732 nonlocal remote, peer
3733 server.listen()
3734 # Block on the accept and wait on the connection to close.
3735 evt.set()
3736 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003737 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003738
3739 t = threading.Thread(target=serve)
3740 t.start()
3741 # Client wait until server setup and perform a connect.
3742 evt.wait()
Christian Heimes2875c602021-04-19 07:27:10 +02003743 client = client_ctx.wrap_socket(
3744 socket.socket(), server_hostname=hostname
3745 )
3746 client.connect((hostname, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003747 client.send(b'data')
3748 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003749 client_addr = client.getsockname()
3750 client.close()
3751 t.join()
3752 remote.close()
3753 server.close()
3754 # Sanity checks.
3755 self.assertIsInstance(remote, ssl.SSLSocket)
3756 self.assertEqual(peer, client_addr)
3757
3758 def test_getpeercert_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003759 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3760 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003761 with context.wrap_socket(socket.socket()) as sock:
3762 with self.assertRaises(OSError) as cm:
3763 sock.getpeercert()
3764 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3765
3766 def test_do_handshake_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003767 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3768 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003769 with context.wrap_socket(socket.socket()) as sock:
3770 with self.assertRaises(OSError) as cm:
3771 sock.do_handshake()
3772 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3773
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003774 def test_no_shared_ciphers(self):
3775 client_context, server_context, hostname = testing_context()
3776 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3777 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003778 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003779 client_context.set_ciphers("AES128")
3780 server_context.set_ciphers("AES256")
3781 with ThreadedEchoServer(context=server_context) as server:
3782 with client_context.wrap_socket(socket.socket(),
3783 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003784 with self.assertRaises(OSError):
3785 s.connect((HOST, server.port))
3786 self.assertIn("no shared cipher", server.conn_errors[0])
3787
3788 def test_version_basic(self):
3789 """
3790 Basic tests for SSLSocket.version().
3791 More tests are done in the test_protocol_*() methods.
3792 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003793 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3794 context.check_hostname = False
3795 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003796 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003797 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003798 chatty=False) as server:
3799 with context.wrap_socket(socket.socket()) as s:
3800 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003801 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003802 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003803 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003804 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003805 self.assertIs(s.version(), None)
3806
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003807 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003808 def test_tls1_3(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003809 client_context, server_context, hostname = testing_context()
3810 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3811 with ThreadedEchoServer(context=server_context) as server:
3812 with client_context.wrap_socket(socket.socket(),
3813 server_hostname=hostname) as s:
Christian Heimescb5b68a2017-09-07 18:07:00 -07003814 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003815 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003816 'TLS_AES_256_GCM_SHA384',
3817 'TLS_CHACHA20_POLY1305_SHA256',
3818 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003819 })
3820 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003821
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003822 @requires_tls_version('TLSv1_2')
Christian Heimes2875c602021-04-19 07:27:10 +02003823 @requires_tls_version('TLSv1')
3824 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003825 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003826 client_context, server_context, hostname = testing_context()
3827 # client TLSv1.0 to 1.2
3828 client_context.minimum_version = ssl.TLSVersion.TLSv1
3829 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3830 # server only TLSv1.2
3831 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3832 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3833
3834 with ThreadedEchoServer(context=server_context) as server:
3835 with client_context.wrap_socket(socket.socket(),
3836 server_hostname=hostname) as s:
3837 s.connect((HOST, server.port))
3838 self.assertEqual(s.version(), 'TLSv1.2')
3839
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003840 @requires_tls_version('TLSv1_1')
Christian Heimes2875c602021-04-19 07:27:10 +02003841 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003842 def test_min_max_version_tlsv1_1(self):
3843 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003844 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003845 client_context.minimum_version = ssl.TLSVersion.TLSv1
3846 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003847 server_context.minimum_version = ssl.TLSVersion.TLSv1
3848 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003849 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003850
3851 with ThreadedEchoServer(context=server_context) as server:
3852 with client_context.wrap_socket(socket.socket(),
3853 server_hostname=hostname) as s:
3854 s.connect((HOST, server.port))
3855 self.assertEqual(s.version(), 'TLSv1.1')
3856
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003857 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003858 @requires_tls_version('TLSv1')
Christian Heimes2875c602021-04-19 07:27:10 +02003859 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003860 def test_min_max_version_mismatch(self):
3861 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003862 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003863 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003864 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003865 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003866 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003867 seclevel_workaround(client_context, server_context)
3868
Christian Heimes698dde12018-02-27 11:54:43 +01003869 with ThreadedEchoServer(context=server_context) as server:
3870 with client_context.wrap_socket(socket.socket(),
3871 server_hostname=hostname) as s:
3872 with self.assertRaises(ssl.SSLError) as e:
3873 s.connect((HOST, server.port))
3874 self.assertIn("alert", str(e.exception))
3875
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003876 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003877 def test_min_max_version_sslv3(self):
3878 client_context, server_context, hostname = testing_context()
3879 server_context.minimum_version = ssl.TLSVersion.SSLv3
3880 client_context.minimum_version = ssl.TLSVersion.SSLv3
3881 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003882 seclevel_workaround(client_context, server_context)
3883
Christian Heimes698dde12018-02-27 11:54:43 +01003884 with ThreadedEchoServer(context=server_context) as server:
3885 with client_context.wrap_socket(socket.socket(),
3886 server_hostname=hostname) as s:
3887 s.connect((HOST, server.port))
3888 self.assertEqual(s.version(), 'SSLv3')
3889
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003890 def test_default_ecdh_curve(self):
3891 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3892 # should be enabled by default on SSL contexts.
Christian Heimes2875c602021-04-19 07:27:10 +02003893 client_context, server_context, hostname = testing_context()
Christian Heimescb5b68a2017-09-07 18:07:00 -07003894 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3895 # cipher name.
Christian Heimes2875c602021-04-19 07:27:10 +02003896 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003897 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3898 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3899 # our default cipher list should prefer ECDH-based ciphers
3900 # automatically.
Christian Heimes2875c602021-04-19 07:27:10 +02003901 with ThreadedEchoServer(context=server_context) as server:
3902 with client_context.wrap_socket(socket.socket(),
3903 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003904 s.connect((HOST, server.port))
3905 self.assertIn("ECDH", s.cipher()[0])
3906
3907 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3908 "'tls-unique' channel binding not available")
3909 def test_tls_unique_channel_binding(self):
3910 """Test tls-unique channel binding."""
3911 if support.verbose:
3912 sys.stdout.write("\n")
3913
Christian Heimes05d9fe32018-02-27 08:55:39 +01003914 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003915
3916 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003917 chatty=True,
3918 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003919
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003920 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003921 with client_context.wrap_socket(
3922 socket.socket(),
3923 server_hostname=hostname) as s:
3924 s.connect((HOST, server.port))
3925 # get the data
3926 cb_data = s.get_channel_binding("tls-unique")
3927 if support.verbose:
3928 sys.stdout.write(
3929 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003930
Christian Heimes05d9fe32018-02-27 08:55:39 +01003931 # check if it is sane
3932 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003933 if s.version() == 'TLSv1.3':
3934 self.assertEqual(len(cb_data), 48)
3935 else:
3936 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003937
Christian Heimes05d9fe32018-02-27 08:55:39 +01003938 # and compare with the peers version
3939 s.write(b"CB tls-unique\n")
3940 peer_data_repr = s.read().strip()
3941 self.assertEqual(peer_data_repr,
3942 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003943
3944 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003945 with client_context.wrap_socket(
3946 socket.socket(),
3947 server_hostname=hostname) as s:
3948 s.connect((HOST, server.port))
3949 new_cb_data = s.get_channel_binding("tls-unique")
3950 if support.verbose:
3951 sys.stdout.write(
3952 "got another channel binding data: {0!r}\n".format(
3953 new_cb_data)
3954 )
3955 # is it really unique
3956 self.assertNotEqual(cb_data, new_cb_data)
3957 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003958 if s.version() == 'TLSv1.3':
3959 self.assertEqual(len(cb_data), 48)
3960 else:
3961 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003962 s.write(b"CB tls-unique\n")
3963 peer_data_repr = s.read().strip()
3964 self.assertEqual(peer_data_repr,
3965 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003966
3967 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003968 client_context, server_context, hostname = testing_context()
3969 stats = server_params_test(client_context, server_context,
3970 chatty=True, connectionchatty=True,
3971 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003972 if support.verbose:
3973 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
3974 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
3975
3976 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
3977 "ssl.OP_NO_COMPRESSION needed for this test")
3978 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003979 client_context, server_context, hostname = testing_context()
3980 client_context.options |= ssl.OP_NO_COMPRESSION
3981 server_context.options |= ssl.OP_NO_COMPRESSION
3982 stats = server_params_test(client_context, server_context,
3983 chatty=True, connectionchatty=True,
3984 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003985 self.assertIs(stats['compression'], None)
3986
Paul Monsonf3550692019-06-19 13:09:54 -07003987 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003988 def test_dh_params(self):
3989 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02003990 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003991 # test scenario needs TLS <= 1.2
3992 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02003993 server_context.load_dh_params(DHFILE)
3994 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01003995 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02003996 stats = server_params_test(client_context, server_context,
3997 chatty=True, connectionchatty=True,
3998 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003999 cipher = stats["cipher"][0]
4000 parts = cipher.split("-")
4001 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4002 self.fail("Non-DH cipher: " + cipher[0])
4003
Christian Heimesb7b92252018-02-25 09:49:31 +01004004 def test_ecdh_curve(self):
4005 # server secp384r1, client auto
4006 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004007
Christian Heimesb7b92252018-02-25 09:49:31 +01004008 server_context.set_ecdh_curve("secp384r1")
4009 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004010 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004011 stats = server_params_test(client_context, server_context,
4012 chatty=True, connectionchatty=True,
4013 sni_name=hostname)
4014
4015 # server auto, client secp384r1
4016 client_context, server_context, hostname = testing_context()
4017 client_context.set_ecdh_curve("secp384r1")
4018 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004019 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004020 stats = server_params_test(client_context, server_context,
4021 chatty=True, connectionchatty=True,
4022 sni_name=hostname)
4023
4024 # server / client curve mismatch
4025 client_context, server_context, hostname = testing_context()
4026 client_context.set_ecdh_curve("prime256v1")
4027 server_context.set_ecdh_curve("secp384r1")
4028 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004029 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
4030 with self.assertRaises(ssl.SSLError):
Christian Heimes39258d32021-04-17 11:36:35 +02004031 server_params_test(client_context, server_context,
4032 chatty=True, connectionchatty=True,
4033 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004034
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004035 def test_selected_alpn_protocol(self):
4036 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004037 client_context, server_context, hostname = testing_context()
4038 stats = server_params_test(client_context, server_context,
4039 chatty=True, connectionchatty=True,
4040 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004041 self.assertIs(stats['client_alpn_protocol'], None)
4042
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004043 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4044 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004045 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004046 server_context.set_alpn_protocols(['foo', 'bar'])
4047 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004048 chatty=True, connectionchatty=True,
4049 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004050 self.assertIs(stats['client_alpn_protocol'], None)
4051
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004052 def test_alpn_protocols(self):
4053 server_protocols = ['foo', 'bar', 'milkshake']
4054 protocol_tests = [
4055 (['foo', 'bar'], 'foo'),
4056 (['bar', 'foo'], 'foo'),
4057 (['milkshake'], 'milkshake'),
4058 (['http/3.0', 'http/4.0'], None)
4059 ]
4060 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004061 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004062 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004063 client_context.set_alpn_protocols(client_protocols)
4064
4065 try:
4066 stats = server_params_test(client_context,
4067 server_context,
4068 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004069 connectionchatty=True,
4070 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004071 except ssl.SSLError as e:
4072 stats = e
4073
Christian Heimes39258d32021-04-17 11:36:35 +02004074 msg = "failed trying %s (s) and %s (c).\n" \
4075 "was expecting %s, but got %%s from the %%s" \
4076 % (str(server_protocols), str(client_protocols),
4077 str(expected))
4078 client_result = stats['client_alpn_protocol']
4079 self.assertEqual(client_result, expected,
4080 msg % (client_result, "client"))
4081 server_result = stats['server_alpn_protocols'][-1] \
4082 if len(stats['server_alpn_protocols']) else 'nothing'
4083 self.assertEqual(server_result, expected,
4084 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004085
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004086 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004087 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004088
4089 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004090 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004091 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004092 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004093 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004094 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004095 client_context.load_verify_locations(SIGNING_CA)
4096 return server_context, other_context, client_context
4097
4098 def check_common_name(self, stats, name):
4099 cert = stats['peercert']
4100 self.assertIn((('commonName', name),), cert['subject'])
4101
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004102 def test_sni_callback(self):
4103 calls = []
4104 server_context, other_context, client_context = self.sni_contexts()
4105
Christian Heimesa170fa12017-09-15 20:27:30 +02004106 client_context.check_hostname = False
4107
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004108 def servername_cb(ssl_sock, server_name, initial_context):
4109 calls.append((server_name, initial_context))
4110 if server_name is not None:
4111 ssl_sock.context = other_context
4112 server_context.set_servername_callback(servername_cb)
4113
4114 stats = server_params_test(client_context, server_context,
4115 chatty=True,
4116 sni_name='supermessage')
4117 # The hostname was fetched properly, and the certificate was
4118 # changed for the connection.
4119 self.assertEqual(calls, [("supermessage", server_context)])
4120 # CERTFILE4 was selected
4121 self.check_common_name(stats, 'fakehostname')
4122
4123 calls = []
4124 # The callback is called with server_name=None
4125 stats = server_params_test(client_context, server_context,
4126 chatty=True,
4127 sni_name=None)
4128 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004129 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004130
4131 # Check disabling the callback
4132 calls = []
4133 server_context.set_servername_callback(None)
4134
4135 stats = server_params_test(client_context, server_context,
4136 chatty=True,
4137 sni_name='notfunny')
4138 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004139 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004140 self.assertEqual(calls, [])
4141
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004142 def test_sni_callback_alert(self):
4143 # Returning a TLS alert is reflected to the connecting client
4144 server_context, other_context, client_context = self.sni_contexts()
4145
4146 def cb_returning_alert(ssl_sock, server_name, initial_context):
4147 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4148 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004149 with self.assertRaises(ssl.SSLError) as cm:
4150 stats = server_params_test(client_context, server_context,
4151 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004152 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004153 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004154
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004155 def test_sni_callback_raising(self):
4156 # Raising fails the connection with a TLS handshake failure alert.
4157 server_context, other_context, client_context = self.sni_contexts()
4158
4159 def cb_raising(ssl_sock, server_name, initial_context):
4160 1/0
4161 server_context.set_servername_callback(cb_raising)
4162
Victor Stinner00253502019-06-03 03:51:43 +02004163 with support.catch_unraisable_exception() as catch:
4164 with self.assertRaises(ssl.SSLError) as cm:
4165 stats = server_params_test(client_context, server_context,
4166 chatty=False,
4167 sni_name='supermessage')
4168
4169 self.assertEqual(cm.exception.reason,
4170 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4171 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004172
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004173 def test_sni_callback_wrong_return_type(self):
4174 # Returning the wrong return type terminates the TLS connection
4175 # with an internal error alert.
4176 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004177
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004178 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4179 return "foo"
4180 server_context.set_servername_callback(cb_wrong_return_type)
4181
Victor Stinner00253502019-06-03 03:51:43 +02004182 with support.catch_unraisable_exception() as catch:
4183 with self.assertRaises(ssl.SSLError) as cm:
4184 stats = server_params_test(client_context, server_context,
4185 chatty=False,
4186 sni_name='supermessage')
4187
4188
4189 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4190 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004191
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004192 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004193 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004194 client_context.set_ciphers("AES128:AES256")
4195 server_context.set_ciphers("AES256")
4196 expected_algs = [
4197 "AES256", "AES-256",
4198 # TLS 1.3 ciphers are always enabled
4199 "TLS_CHACHA20", "TLS_AES",
4200 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004201
Christian Heimesa170fa12017-09-15 20:27:30 +02004202 stats = server_params_test(client_context, server_context,
4203 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004204 ciphers = stats['server_shared_ciphers'][0]
4205 self.assertGreater(len(ciphers), 0)
4206 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004207 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004208 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004209
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004210 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004211 client_context, server_context, hostname = testing_context()
4212 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004213
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004214 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004215 s = client_context.wrap_socket(socket.socket(),
4216 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004217 s.connect((HOST, server.port))
4218 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004219
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004220 self.assertRaises(ValueError, s.read, 1024)
4221 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004222
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004223 def test_sendfile(self):
4224 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004225 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004226 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004227 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimes2875c602021-04-19 07:27:10 +02004228 client_context, server_context, hostname = testing_context()
4229 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004230 with server:
Christian Heimes2875c602021-04-19 07:27:10 +02004231 with client_context.wrap_socket(socket.socket(),
4232 server_hostname=hostname) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004233 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004234 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004235 s.sendfile(file)
4236 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004237
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004238 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004239 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004240 # TODO: sessions aren't compatible with TLSv1.3 yet
4241 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004242
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004243 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004244 stats = server_params_test(client_context, server_context,
4245 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004246 session = stats['session']
4247 self.assertTrue(session.id)
4248 self.assertGreater(session.time, 0)
4249 self.assertGreater(session.timeout, 0)
4250 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004251 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004252 self.assertFalse(stats['session_reused'])
4253 sess_stat = server_context.session_stats()
4254 self.assertEqual(sess_stat['accept'], 1)
4255 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004256
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004257 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004258 stats = server_params_test(client_context, server_context,
4259 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004260 sess_stat = server_context.session_stats()
4261 self.assertEqual(sess_stat['accept'], 2)
4262 self.assertEqual(sess_stat['hits'], 1)
4263 self.assertTrue(stats['session_reused'])
4264 session2 = stats['session']
4265 self.assertEqual(session2.id, session.id)
4266 self.assertEqual(session2, session)
4267 self.assertIsNot(session2, session)
4268 self.assertGreaterEqual(session2.time, session.time)
4269 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004270
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004271 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004272 stats = server_params_test(client_context, server_context,
4273 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004274 self.assertFalse(stats['session_reused'])
4275 session3 = stats['session']
4276 self.assertNotEqual(session3.id, session.id)
4277 self.assertNotEqual(session3, session)
4278 sess_stat = server_context.session_stats()
4279 self.assertEqual(sess_stat['accept'], 3)
4280 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004281
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004282 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004283 stats = server_params_test(client_context, server_context,
4284 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004285 self.assertTrue(stats['session_reused'])
4286 session4 = stats['session']
4287 self.assertEqual(session4.id, session.id)
4288 self.assertEqual(session4, session)
4289 self.assertGreaterEqual(session4.time, session.time)
4290 self.assertGreaterEqual(session4.timeout, session.timeout)
4291 sess_stat = server_context.session_stats()
4292 self.assertEqual(sess_stat['accept'], 4)
4293 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004294
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004295 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004296 client_context, server_context, hostname = testing_context()
4297 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004298
Christian Heimes05d9fe32018-02-27 08:55:39 +01004299 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004300 client_context.options |= ssl.OP_NO_TLSv1_3
4301 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004302
Christian Heimesa170fa12017-09-15 20:27:30 +02004303 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004304 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004305 with client_context.wrap_socket(socket.socket(),
4306 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004307 # session is None before handshake
4308 self.assertEqual(s.session, None)
4309 self.assertEqual(s.session_reused, None)
4310 s.connect((HOST, server.port))
4311 session = s.session
4312 self.assertTrue(session)
4313 with self.assertRaises(TypeError) as e:
4314 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004315 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004316
Christian Heimesa170fa12017-09-15 20:27:30 +02004317 with client_context.wrap_socket(socket.socket(),
4318 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004319 s.connect((HOST, server.port))
4320 # cannot set session after handshake
4321 with self.assertRaises(ValueError) as e:
4322 s.session = session
4323 self.assertEqual(str(e.exception),
4324 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004325
Christian Heimesa170fa12017-09-15 20:27:30 +02004326 with client_context.wrap_socket(socket.socket(),
4327 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004328 # can set session before handshake and before the
4329 # connection was established
4330 s.session = session
4331 s.connect((HOST, server.port))
4332 self.assertEqual(s.session.id, session.id)
4333 self.assertEqual(s.session, session)
4334 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004335
Christian Heimesa170fa12017-09-15 20:27:30 +02004336 with client_context2.wrap_socket(socket.socket(),
4337 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004338 # cannot re-use session with a different SSLContext
4339 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004340 s.session = session
4341 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004342 self.assertEqual(str(e.exception),
4343 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004344
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004345
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004346@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004347class TestPostHandshakeAuth(unittest.TestCase):
4348 def test_pha_setter(self):
4349 protocols = [
Christian Heimes2875c602021-04-19 07:27:10 +02004350 ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
Christian Heimes9fb051f2018-09-23 08:32:31 +02004351 ]
4352 for protocol in protocols:
4353 ctx = ssl.SSLContext(protocol)
4354 self.assertEqual(ctx.post_handshake_auth, False)
4355
4356 ctx.post_handshake_auth = True
4357 self.assertEqual(ctx.post_handshake_auth, True)
4358
4359 ctx.verify_mode = ssl.CERT_REQUIRED
4360 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4361 self.assertEqual(ctx.post_handshake_auth, True)
4362
4363 ctx.post_handshake_auth = False
4364 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4365 self.assertEqual(ctx.post_handshake_auth, False)
4366
4367 ctx.verify_mode = ssl.CERT_OPTIONAL
4368 ctx.post_handshake_auth = True
4369 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4370 self.assertEqual(ctx.post_handshake_auth, True)
4371
4372 def test_pha_required(self):
4373 client_context, server_context, hostname = testing_context()
4374 server_context.post_handshake_auth = True
4375 server_context.verify_mode = ssl.CERT_REQUIRED
4376 client_context.post_handshake_auth = True
4377 client_context.load_cert_chain(SIGNED_CERTFILE)
4378
4379 server = ThreadedEchoServer(context=server_context, chatty=False)
4380 with server:
4381 with client_context.wrap_socket(socket.socket(),
4382 server_hostname=hostname) as s:
4383 s.connect((HOST, server.port))
4384 s.write(b'HASCERT')
4385 self.assertEqual(s.recv(1024), b'FALSE\n')
4386 s.write(b'PHA')
4387 self.assertEqual(s.recv(1024), b'OK\n')
4388 s.write(b'HASCERT')
4389 self.assertEqual(s.recv(1024), b'TRUE\n')
4390 # PHA method just returns true when cert is already available
4391 s.write(b'PHA')
4392 self.assertEqual(s.recv(1024), b'OK\n')
4393 s.write(b'GETCERT')
4394 cert_text = s.recv(4096).decode('us-ascii')
4395 self.assertIn('Python Software Foundation CA', cert_text)
4396
4397 def test_pha_required_nocert(self):
4398 client_context, server_context, hostname = testing_context()
4399 server_context.post_handshake_auth = True
4400 server_context.verify_mode = ssl.CERT_REQUIRED
4401 client_context.post_handshake_auth = True
4402
Victor Stinner73ea5462019-07-09 14:33:49 +02004403 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4404 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004405 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004406 server = ThreadedEchoServer(context=server_context, chatty=False)
4407 with server:
4408 with client_context.wrap_socket(socket.socket(),
4409 server_hostname=hostname) as s:
4410 s.connect((HOST, server.port))
4411 s.write(b'PHA')
4412 # receive CertificateRequest
4413 self.assertEqual(s.recv(1024), b'OK\n')
4414 # send empty Certificate + Finish
4415 s.write(b'HASCERT')
4416 # receive alert
4417 with self.assertRaisesRegex(
4418 ssl.SSLError,
4419 'tlsv13 alert certificate required'):
4420 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004421
4422 def test_pha_optional(self):
4423 if support.verbose:
4424 sys.stdout.write("\n")
4425
4426 client_context, server_context, hostname = testing_context()
4427 server_context.post_handshake_auth = True
4428 server_context.verify_mode = ssl.CERT_REQUIRED
4429 client_context.post_handshake_auth = True
4430 client_context.load_cert_chain(SIGNED_CERTFILE)
4431
4432 # check CERT_OPTIONAL
4433 server_context.verify_mode = ssl.CERT_OPTIONAL
4434 server = ThreadedEchoServer(context=server_context, chatty=False)
4435 with server:
4436 with client_context.wrap_socket(socket.socket(),
4437 server_hostname=hostname) as s:
4438 s.connect((HOST, server.port))
4439 s.write(b'HASCERT')
4440 self.assertEqual(s.recv(1024), b'FALSE\n')
4441 s.write(b'PHA')
4442 self.assertEqual(s.recv(1024), b'OK\n')
4443 s.write(b'HASCERT')
4444 self.assertEqual(s.recv(1024), b'TRUE\n')
4445
4446 def test_pha_optional_nocert(self):
4447 if support.verbose:
4448 sys.stdout.write("\n")
4449
4450 client_context, server_context, hostname = testing_context()
4451 server_context.post_handshake_auth = True
4452 server_context.verify_mode = ssl.CERT_OPTIONAL
4453 client_context.post_handshake_auth = True
4454
4455 server = ThreadedEchoServer(context=server_context, chatty=False)
4456 with server:
4457 with client_context.wrap_socket(socket.socket(),
4458 server_hostname=hostname) as s:
4459 s.connect((HOST, server.port))
4460 s.write(b'HASCERT')
4461 self.assertEqual(s.recv(1024), b'FALSE\n')
4462 s.write(b'PHA')
4463 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004464 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004465 s.write(b'HASCERT')
4466 self.assertEqual(s.recv(1024), b'FALSE\n')
4467
4468 def test_pha_no_pha_client(self):
4469 client_context, server_context, hostname = testing_context()
4470 server_context.post_handshake_auth = True
4471 server_context.verify_mode = ssl.CERT_REQUIRED
4472 client_context.load_cert_chain(SIGNED_CERTFILE)
4473
4474 server = ThreadedEchoServer(context=server_context, chatty=False)
4475 with server:
4476 with client_context.wrap_socket(socket.socket(),
4477 server_hostname=hostname) as s:
4478 s.connect((HOST, server.port))
4479 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4480 s.verify_client_post_handshake()
4481 s.write(b'PHA')
4482 self.assertIn(b'extension not received', s.recv(1024))
4483
4484 def test_pha_no_pha_server(self):
4485 # server doesn't have PHA enabled, cert is requested in handshake
4486 client_context, server_context, hostname = testing_context()
4487 server_context.verify_mode = ssl.CERT_REQUIRED
4488 client_context.post_handshake_auth = True
4489 client_context.load_cert_chain(SIGNED_CERTFILE)
4490
4491 server = ThreadedEchoServer(context=server_context, chatty=False)
4492 with server:
4493 with client_context.wrap_socket(socket.socket(),
4494 server_hostname=hostname) as s:
4495 s.connect((HOST, server.port))
4496 s.write(b'HASCERT')
4497 self.assertEqual(s.recv(1024), b'TRUE\n')
4498 # PHA doesn't fail if there is already a cert
4499 s.write(b'PHA')
4500 self.assertEqual(s.recv(1024), b'OK\n')
4501 s.write(b'HASCERT')
4502 self.assertEqual(s.recv(1024), b'TRUE\n')
4503
4504 def test_pha_not_tls13(self):
4505 # TLS 1.2
4506 client_context, server_context, hostname = testing_context()
4507 server_context.verify_mode = ssl.CERT_REQUIRED
4508 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4509 client_context.post_handshake_auth = True
4510 client_context.load_cert_chain(SIGNED_CERTFILE)
4511
4512 server = ThreadedEchoServer(context=server_context, chatty=False)
4513 with server:
4514 with client_context.wrap_socket(socket.socket(),
4515 server_hostname=hostname) as s:
4516 s.connect((HOST, server.port))
4517 # PHA fails for TLS != 1.3
4518 s.write(b'PHA')
4519 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4520
Christian Heimesf0f59302019-07-01 08:29:17 +02004521 def test_bpo37428_pha_cert_none(self):
4522 # verify that post_handshake_auth does not implicitly enable cert
4523 # validation.
4524 hostname = SIGNED_CERTFILE_HOSTNAME
4525 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4526 client_context.post_handshake_auth = True
4527 client_context.load_cert_chain(SIGNED_CERTFILE)
4528 # no cert validation and CA on client side
4529 client_context.check_hostname = False
4530 client_context.verify_mode = ssl.CERT_NONE
4531
4532 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4533 server_context.load_cert_chain(SIGNED_CERTFILE)
4534 server_context.load_verify_locations(SIGNING_CA)
4535 server_context.post_handshake_auth = True
4536 server_context.verify_mode = ssl.CERT_REQUIRED
4537
4538 server = ThreadedEchoServer(context=server_context, chatty=False)
4539 with server:
4540 with client_context.wrap_socket(socket.socket(),
4541 server_hostname=hostname) as s:
4542 s.connect((HOST, server.port))
4543 s.write(b'HASCERT')
4544 self.assertEqual(s.recv(1024), b'FALSE\n')
4545 s.write(b'PHA')
4546 self.assertEqual(s.recv(1024), b'OK\n')
4547 s.write(b'HASCERT')
4548 self.assertEqual(s.recv(1024), b'TRUE\n')
4549 # server cert has not been validated
4550 self.assertEqual(s.getpeercert(), {})
4551
Christian Heimes9fb051f2018-09-23 08:32:31 +02004552
Christian Heimesc7f70692019-05-31 11:44:05 +02004553HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4554requires_keylog = unittest.skipUnless(
4555 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4556
4557class TestSSLDebug(unittest.TestCase):
4558
Hai Shia7f5d932020-08-04 00:41:24 +08004559 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004560 with open(fname) as f:
4561 return len(list(f))
4562
4563 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004564 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004565 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004566 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004567 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4568 self.assertEqual(ctx.keylog_filename, None)
4569
Hai Shia7f5d932020-08-04 00:41:24 +08004570 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4571 ctx.keylog_filename = os_helper.TESTFN
4572 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4573 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004574 self.assertEqual(self.keylog_lines(), 1)
4575
4576 ctx.keylog_filename = None
4577 self.assertEqual(ctx.keylog_filename, None)
4578
4579 with self.assertRaises((IsADirectoryError, PermissionError)):
4580 # Windows raises PermissionError
4581 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004582 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004583
4584 with self.assertRaises(TypeError):
4585 ctx.keylog_filename = 1
4586
4587 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004588 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004589 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004590 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004591 client_context, server_context, hostname = testing_context()
4592
Hai Shia7f5d932020-08-04 00:41:24 +08004593 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004594 server = ThreadedEchoServer(context=server_context, chatty=False)
4595 with server:
4596 with client_context.wrap_socket(socket.socket(),
4597 server_hostname=hostname) as s:
4598 s.connect((HOST, server.port))
4599 # header, 5 lines for TLS 1.3
4600 self.assertEqual(self.keylog_lines(), 6)
4601
4602 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004603 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004604 server = ThreadedEchoServer(context=server_context, chatty=False)
4605 with server:
4606 with client_context.wrap_socket(socket.socket(),
4607 server_hostname=hostname) as s:
4608 s.connect((HOST, server.port))
4609 self.assertGreaterEqual(self.keylog_lines(), 11)
4610
Hai Shia7f5d932020-08-04 00:41:24 +08004611 client_context.keylog_filename = os_helper.TESTFN
4612 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004613 server = ThreadedEchoServer(context=server_context, chatty=False)
4614 with server:
4615 with client_context.wrap_socket(socket.socket(),
4616 server_hostname=hostname) as s:
4617 s.connect((HOST, server.port))
4618 self.assertGreaterEqual(self.keylog_lines(), 21)
4619
4620 client_context.keylog_filename = None
4621 server_context.keylog_filename = None
4622
4623 @requires_keylog
4624 @unittest.skipIf(sys.flags.ignore_environment,
4625 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004626 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004627 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004628 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004629 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004630 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4631 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004632
4633 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4634 self.assertEqual(ctx.keylog_filename, None)
4635
4636 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004637 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004638
4639 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004640 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004641
4642 def test_msg_callback(self):
4643 client_context, server_context, hostname = testing_context()
4644
4645 def msg_cb(conn, direction, version, content_type, msg_type, data):
4646 pass
4647
4648 self.assertIs(client_context._msg_callback, None)
4649 client_context._msg_callback = msg_cb
4650 self.assertIs(client_context._msg_callback, msg_cb)
4651 with self.assertRaises(TypeError):
4652 client_context._msg_callback = object()
4653
4654 def test_msg_callback_tls12(self):
4655 client_context, server_context, hostname = testing_context()
4656 client_context.options |= ssl.OP_NO_TLSv1_3
4657
4658 msg = []
4659
4660 def msg_cb(conn, direction, version, content_type, msg_type, data):
4661 self.assertIsInstance(conn, ssl.SSLSocket)
4662 self.assertIsInstance(data, bytes)
4663 self.assertIn(direction, {'read', 'write'})
4664 msg.append((direction, version, content_type, msg_type))
4665
4666 client_context._msg_callback = msg_cb
4667
4668 server = ThreadedEchoServer(context=server_context, chatty=False)
4669 with server:
4670 with client_context.wrap_socket(socket.socket(),
4671 server_hostname=hostname) as s:
4672 s.connect((HOST, server.port))
4673
Christian Heimese35d1ba2019-06-03 20:40:15 +02004674 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004675 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4676 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004677 msg
4678 )
4679 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004680 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4681 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004682 msg
4683 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004684
Christian Heimes77cde502021-03-21 16:13:09 +01004685 def test_msg_callback_deadlock_bpo43577(self):
4686 client_context, server_context, hostname = testing_context()
4687 server_context2 = testing_context()[1]
4688
4689 def msg_cb(conn, direction, version, content_type, msg_type, data):
4690 pass
4691
4692 def sni_cb(sock, servername, ctx):
4693 sock.context = server_context2
4694
4695 server_context._msg_callback = msg_cb
4696 server_context.sni_callback = sni_cb
4697
4698 server = ThreadedEchoServer(context=server_context, chatty=False)
4699 with server:
4700 with client_context.wrap_socket(socket.socket(),
4701 server_hostname=hostname) as s:
4702 s.connect((HOST, server.port))
4703 with client_context.wrap_socket(socket.socket(),
4704 server_hostname=hostname) as s:
4705 s.connect((HOST, server.port))
4706
Christian Heimesc7f70692019-05-31 11:44:05 +02004707
Thomas Woutersed03b412007-08-28 21:37:11 +00004708def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004709 if support.verbose:
4710 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004711 'Mac': platform.mac_ver,
4712 'Windows': platform.win32_ver,
4713 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004714 for name, func in plats.items():
4715 plat = func()
4716 if plat and plat[0]:
4717 plat = '%s %r' % (name, plat)
4718 break
4719 else:
4720 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004721 print("test_ssl: testing with %r %r" %
4722 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4723 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004724 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004725 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4726 try:
4727 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4728 except AttributeError:
4729 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004730
Antoine Pitrou152efa22010-05-16 18:19:27 +00004731 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004732 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004733 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004734 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004735 BADCERT, BADKEY, EMPTYCERT]:
4736 if not os.path.exists(filename):
4737 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004738
Martin Panter3840b2a2016-03-27 01:53:46 +00004739 tests = [
4740 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004741 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004742 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004743 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004744
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004745 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004746 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004747
Hai Shie80697d2020-05-28 06:10:27 +08004748 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004749 try:
4750 support.run_unittest(*tests)
4751 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004752 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004753
4754if __name__ == "__main__":
4755 test_main()