blob: a2c79ff5927f122d25f00624f9897ac65578da83 [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
Christian Heimes9424bb42013-06-17 15:32:57 +020015import datetime
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000016import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000017import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000018import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000019import pprint
Antoine Pitrou803e6d62010-10-13 10:36:15 +000020import urllib.request
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020021import threading
Thomas Woutersed03b412007-08-28 21:37:11 +000022import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000023import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000024import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000025import platform
Christian Heimes892d66e2018-01-29 14:10:18 +010026import sysconfig
Christian Heimesdf6ac7e2019-09-26 17:02:59 +020027import functools
Christian Heimes888bbdc2017-09-07 14:18:21 -070028try:
29 import ctypes
30except ImportError:
31 ctypes = None
Thomas Woutersed03b412007-08-28 21:37:11 +000032
Hai Shia7f5d932020-08-04 00:41:24 +080033ssl = import_helper.import_module("ssl")
Antoine Pitrou05d936d2010-10-13 11:38:36 +000034
Victor Stinner8f4ef3b2019-07-01 18:28:25 +020035from ssl import TLSVersion, _TLSContentType, _TLSMessageType
Martin Panter3840b2a2016-03-27 01:53:46 +000036
Paul Monsonf3550692019-06-19 13:09:54 -070037Py_DEBUG = hasattr(sys, 'gettotalrefcount')
38Py_DEBUG_WIN32 = Py_DEBUG and sys.platform == 'win32'
39
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010040PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Serhiy Storchaka16994912020-04-25 10:06:29 +030041HOST = socket_helper.HOST
Christian Heimes598894f2016-09-05 23:19:05 +020042IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
Christian Heimes05d9fe32018-02-27 08:55:39 +010043IS_OPENSSL_1_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1)
Christian Heimes5151d642021-04-09 15:43:06 +020044IS_OPENSSL_3_0_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
Christian Heimes892d66e2018-01-29 14:10:18 +010045PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
Antoine Pitrou152efa22010-05-16 18:19:27 +000046
Victor Stinner3ef63442019-02-19 18:06:03 +010047PROTOCOL_TO_TLS_VERSION = {}
48for proto, ver in (
49 ("PROTOCOL_SSLv23", "SSLv3"),
50 ("PROTOCOL_TLSv1", "TLSv1"),
51 ("PROTOCOL_TLSv1_1", "TLSv1_1"),
52):
53 try:
54 proto = getattr(ssl, proto)
55 ver = getattr(ssl.TLSVersion, ver)
56 except AttributeError:
57 continue
58 PROTOCOL_TO_TLS_VERSION[proto] = ver
59
Christian Heimesefff7062013-11-21 03:35:02 +010060def data_file(*name):
61 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000062
Antoine Pitrou81564092010-10-08 23:06:24 +000063# The custom key and certificate files used in test_ssl are generated
64# using Lib/test/make_ssl_certs.py.
65# Other certificates are simply fetched from the Internet servers they
66# are meant to authenticate.
67
Antoine Pitrou152efa22010-05-16 18:19:27 +000068CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000069BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000070ONLYCERT = data_file("ssl_cert.pem")
71ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000072BYTES_ONLYCERT = os.fsencode(ONLYCERT)
73BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020074CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
75ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
76KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000077CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000078BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010079CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
80CAFILE_CACERT = data_file("capath", "5ed36f99.0")
81
Christian Heimesbd5c7d22018-01-20 15:16:30 +010082CERTFILE_INFO = {
83 'issuer': ((('countryName', 'XY'),),
84 (('localityName', 'Castle Anthrax'),),
85 (('organizationName', 'Python Software Foundation'),),
86 (('commonName', 'localhost'),)),
Christian Heimese6dac002018-08-30 07:25:49 +020087 'notAfter': 'Aug 26 14:23:15 2028 GMT',
88 'notBefore': 'Aug 29 14:23:15 2018 GMT',
89 'serialNumber': '98A7CF88C74A32ED',
Christian Heimesbd5c7d22018-01-20 15:16:30 +010090 'subject': ((('countryName', 'XY'),),
91 (('localityName', 'Castle Anthrax'),),
92 (('organizationName', 'Python Software Foundation'),),
93 (('commonName', 'localhost'),)),
94 'subjectAltName': (('DNS', 'localhost'),),
95 'version': 3
96}
Antoine Pitrou152efa22010-05-16 18:19:27 +000097
Christian Heimes22587792013-11-21 23:56:13 +010098# empty CRL
99CRLFILE = data_file("revocation.crl")
100
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100101# Two keys and certs signed by the same CA (for SNI tests)
102SIGNED_CERTFILE = data_file("keycert3.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200103SIGNED_CERTFILE_HOSTNAME = 'localhost'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100104
105SIGNED_CERTFILE_INFO = {
106 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
107 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
108 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
109 'issuer': ((('countryName', 'XY'),),
110 (('organizationName', 'Python Software Foundation CA'),),
111 (('commonName', 'our-ca-server'),)),
Christian Heimesb467d9a2021-04-17 10:07:19 +0200112 'notAfter': 'Oct 28 14:23:16 2037 GMT',
Christian Heimese6dac002018-08-30 07:25:49 +0200113 'notBefore': 'Aug 29 14:23:16 2018 GMT',
114 'serialNumber': 'CB2D80995A69525C',
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100115 'subject': ((('countryName', 'XY'),),
116 (('localityName', 'Castle Anthrax'),),
117 (('organizationName', 'Python Software Foundation'),),
118 (('commonName', 'localhost'),)),
119 'subjectAltName': (('DNS', 'localhost'),),
120 'version': 3
121}
122
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100123SIGNED_CERTFILE2 = data_file("keycert4.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200124SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100125SIGNED_CERTFILE_ECC = data_file("keycertecc.pem")
126SIGNED_CERTFILE_ECC_HOSTNAME = 'localhost-ecc'
127
Martin Panter3840b2a2016-03-27 01:53:46 +0000128# Same certificate as pycacert.pem, but without extra text in file
129SIGNING_CA = data_file("capath", "ceff1710.0")
Christian Heimes1c03abd2016-09-06 23:25:35 +0200130# cert with all kinds of subject alt names
131ALLSANFILE = data_file("allsans.pem")
Christian Heimes66e57422018-01-29 14:25:13 +0100132IDNSANSFILE = data_file("idnsans.pem")
Christian Heimesb467d9a2021-04-17 10:07:19 +0200133NOSANFILE = data_file("nosan.pem")
134NOSAN_HOSTNAME = 'localhost'
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100135
Martin Panter3d81d932016-01-14 09:36:00 +0000136REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +0000137
138EMPTYCERT = data_file("nullcert.pem")
139BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +0000140NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000141BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200142NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +0200143NULLBYTECERT = data_file("nullbytecert.pem")
Christian Heimesa37f5242019-01-15 23:47:42 +0100144TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000145
Christian Heimes88bfd0b2018-08-14 12:54:19 +0200146DHFILE = data_file("ffdh3072.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100147BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +0000148
Christian Heimes358cfd42016-09-10 22:43:48 +0200149# Not defined in all versions of OpenSSL
150OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
151OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
152OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
153OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
Christian Heimes05d9fe32018-02-27 08:55:39 +0100154OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
Christian Heimes6f37ebc2021-04-09 17:59:21 +0200155OP_IGNORE_UNEXPECTED_EOF = getattr(ssl, "OP_IGNORE_UNEXPECTED_EOF", 0)
Christian Heimes358cfd42016-09-10 22:43:48 +0200156
Christian Heimesf6c6b582021-03-18 23:06:50 +0100157# Ubuntu has patched OpenSSL and changed behavior of security level 2
158# see https://bugs.python.org/issue41561#msg389003
159def is_ubuntu():
160 try:
161 # Assume that any references of "ubuntu" implies Ubuntu-like distro
162 # The workaround is not required for 18.04, but doesn't hurt either.
163 with open("/etc/os-release", encoding="utf-8") as f:
164 return "ubuntu" in f.read()
165 except FileNotFoundError:
166 return False
167
168if is_ubuntu():
169 def seclevel_workaround(*ctxs):
170 """"Lower security level to '1' and allow all ciphers for TLS 1.0/1"""
171 for ctx in ctxs:
Christian Heimes34477502021-04-12 12:00:38 +0200172 if (
173 hasattr(ctx, "minimum_version") and
174 ctx.minimum_version <= ssl.TLSVersion.TLSv1_1
175 ):
Christian Heimesf6c6b582021-03-18 23:06:50 +0100176 ctx.set_ciphers("@SECLEVEL=1:ALL")
177else:
178 def seclevel_workaround(*ctxs):
179 pass
180
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100181
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200182def has_tls_protocol(protocol):
183 """Check if a TLS protocol is available and enabled
184
185 :param protocol: enum ssl._SSLMethod member or name
186 :return: bool
187 """
188 if isinstance(protocol, str):
189 assert protocol.startswith('PROTOCOL_')
190 protocol = getattr(ssl, protocol, None)
191 if protocol is None:
192 return False
193 if protocol in {
194 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
195 ssl.PROTOCOL_TLS_CLIENT
196 }:
197 # auto-negotiate protocols are always available
198 return True
199 name = protocol.name
200 return has_tls_version(name[len('PROTOCOL_'):])
201
202
203@functools.lru_cache
204def has_tls_version(version):
205 """Check if a TLS/SSL version is enabled
206
207 :param version: TLS version name or ssl.TLSVersion member
208 :return: bool
209 """
210 if version == "SSLv2":
211 # never supported and not even in TLSVersion enum
212 return False
213
214 if isinstance(version, str):
215 version = ssl.TLSVersion.__members__[version]
216
217 # check compile time flags like ssl.HAS_TLSv1_2
218 if not getattr(ssl, f'HAS_{version.name}'):
219 return False
220
Christian Heimes5151d642021-04-09 15:43:06 +0200221 if IS_OPENSSL_3_0_0 and version < ssl.TLSVersion.TLSv1_2:
222 # bpo43791: 3.0.0-alpha14 fails with TLSV1_ALERT_INTERNAL_ERROR
223 return False
224
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200225 # check runtime and dynamic crypto policy settings. A TLS version may
226 # be compiled in but disabled by a policy or config option.
Christian Heimes2875c602021-04-19 07:27:10 +0200227 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200228 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200229 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200230 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
231 version < ctx.minimum_version
232 ):
233 return False
234 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200235 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200236 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
237 version > ctx.maximum_version
238 ):
239 return False
240
241 return True
242
243
244def requires_tls_version(version):
245 """Decorator to skip tests when a required TLS version is not available
246
247 :param version: TLS version name or ssl.TLSVersion member
248 :return:
249 """
250 def decorator(func):
251 @functools.wraps(func)
252 def wrapper(*args, **kw):
253 if not has_tls_version(version):
254 raise unittest.SkipTest(f"{version} is not available.")
255 else:
256 return func(*args, **kw)
257 return wrapper
258 return decorator
259
260
261requires_minimum_version = unittest.skipUnless(
262 hasattr(ssl.SSLContext, 'minimum_version'),
263 "required OpenSSL >= 1.1.0g"
264)
265
266
Thomas Woutersed03b412007-08-28 21:37:11 +0000267def handle_error(prefix):
268 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000269 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000270 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000271
Christian Heimesb7b92252018-02-25 09:49:31 +0100272def _have_secp_curves():
273 if not ssl.HAS_ECDH:
274 return False
275 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
276 try:
277 ctx.set_ecdh_curve("secp384r1")
278 except ValueError:
279 return False
280 else:
281 return True
282
283
284HAVE_SECP_CURVES = _have_secp_curves()
285
286
Antoine Pitrouc695c952014-04-28 20:57:36 +0200287def utc_offset(): #NOTE: ignore issues like #1647654
288 # local time = utc time + utc offset
289 if time.daylight and time.localtime().tm_isdst > 0:
290 return -time.altzone # seconds
291 return -time.timezone
292
Christian Heimes9424bb42013-06-17 15:32:57 +0200293def asn1time(cert_time):
294 # Some versions of OpenSSL ignore seconds, see #18207
295 # 0.9.8.i
296 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
297 fmt = "%b %d %H:%M:%S %Y GMT"
298 dt = datetime.datetime.strptime(cert_time, fmt)
299 dt = dt.replace(second=0)
300 cert_time = dt.strftime(fmt)
301 # %d adds leading zero but ASN1_TIME_print() uses leading space
302 if cert_time[4] == "0":
303 cert_time = cert_time[:4] + " " + cert_time[5:]
304
305 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000306
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100307needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
308
Christian Heimes2875c602021-04-19 07:27:10 +0200309ignore_deprecation = warnings_helper.ignore_warnings(
310 category=DeprecationWarning
311)
Antoine Pitrou23df4832010-08-04 17:14:06 +0000312
Christian Heimes2875c602021-04-19 07:27:10 +0200313
314def test_wrap_socket(sock, *,
Christian Heimesd0486372016-09-10 23:23:33 +0200315 cert_reqs=ssl.CERT_NONE, ca_certs=None,
316 ciphers=None, certfile=None, keyfile=None,
317 **kwargs):
Christian Heimes2875c602021-04-19 07:27:10 +0200318 if not kwargs.get("server_side"):
319 kwargs["server_hostname"] = SIGNED_CERTFILE_HOSTNAME
320 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
321 else:
322 context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimesd0486372016-09-10 23:23:33 +0200323 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200324 if cert_reqs == ssl.CERT_NONE:
325 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200326 context.verify_mode = cert_reqs
327 if ca_certs is not None:
328 context.load_verify_locations(ca_certs)
329 if certfile is not None or keyfile is not None:
330 context.load_cert_chain(certfile, keyfile)
331 if ciphers is not None:
332 context.set_ciphers(ciphers)
333 return context.wrap_socket(sock, **kwargs)
334
Christian Heimesa170fa12017-09-15 20:27:30 +0200335
336def testing_context(server_cert=SIGNED_CERTFILE):
337 """Create context
338
339 client_context, server_context, hostname = testing_context()
340 """
341 if server_cert == SIGNED_CERTFILE:
342 hostname = SIGNED_CERTFILE_HOSTNAME
343 elif server_cert == SIGNED_CERTFILE2:
344 hostname = SIGNED_CERTFILE2_HOSTNAME
Christian Heimesb467d9a2021-04-17 10:07:19 +0200345 elif server_cert == NOSANFILE:
346 hostname = NOSAN_HOSTNAME
Christian Heimesa170fa12017-09-15 20:27:30 +0200347 else:
348 raise ValueError(server_cert)
349
350 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
351 client_context.load_verify_locations(SIGNING_CA)
352
353 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
354 server_context.load_cert_chain(server_cert)
Christian Heimes9fb051f2018-09-23 08:32:31 +0200355 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200356
357 return client_context, server_context, hostname
358
359
Antoine Pitrou152efa22010-05-16 18:19:27 +0000360class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000361
Antoine Pitrou480a1242010-04-28 21:37:09 +0000362 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000363 ssl.CERT_NONE
364 ssl.CERT_OPTIONAL
365 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100366 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100367 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100368 if ssl.HAS_ECDH:
369 ssl.OP_SINGLE_ECDH_USE
Christian Heimes39258d32021-04-17 11:36:35 +0200370 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000371 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100372 self.assertIn(ssl.HAS_ECDH, {True, False})
Christian Heimescb5b68a2017-09-07 18:07:00 -0700373 ssl.OP_NO_SSLv2
374 ssl.OP_NO_SSLv3
375 ssl.OP_NO_TLSv1
376 ssl.OP_NO_TLSv1_3
Christian Heimes39258d32021-04-17 11:36:35 +0200377 ssl.OP_NO_TLSv1_1
378 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200379 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000380
Christian Heimes9d50ab52018-02-27 10:17:30 +0100381 def test_private_init(self):
382 with self.assertRaisesRegex(TypeError, "public constructor"):
383 with socket.socket() as s:
384 ssl.SSLSocket(s)
385
Antoine Pitrou172f0252014-04-18 20:33:08 +0200386 def test_str_for_enums(self):
387 # Make sure that the PROTOCOL_* constants have enum-like string
388 # reprs.
Christian Heimes2875c602021-04-19 07:27:10 +0200389 proto = ssl.PROTOCOL_TLS_CLIENT
390 self.assertEqual(str(proto), 'PROTOCOL_TLS_CLIENT')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200391 ctx = ssl.SSLContext(proto)
392 self.assertIs(ctx.protocol, proto)
393
Antoine Pitrou480a1242010-04-28 21:37:09 +0000394 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000395 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000396 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000397 sys.stdout.write("\n RAND_status is %d (%s)\n"
398 % (v, (v and "sufficient randomness") or
399 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200400
Christian Heimes2875c602021-04-19 07:27:10 +0200401 with warnings_helper.check_warnings():
402 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200403 self.assertEqual(len(data), 16)
404 self.assertEqual(is_cryptographic, v == 1)
405 if v:
406 data = ssl.RAND_bytes(16)
407 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200408 else:
409 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200410
Victor Stinner1e81a392013-12-19 16:47:04 +0100411 # negative num is invalid
412 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
Christian Heimes2875c602021-04-19 07:27:10 +0200413 with warnings_helper.check_warnings():
414 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
Victor Stinner1e81a392013-12-19 16:47:04 +0100415
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000416 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200417 ssl.RAND_add(b"this is a random bytes object", 75.0)
418 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000419
Antoine Pitrou480a1242010-04-28 21:37:09 +0000420 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000421 # note that this uses an 'unofficial' function in _ssl.c,
422 # provided solely for this test, to exercise the certificate
423 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100424 self.assertEqual(
425 ssl._ssl._test_decode_cert(CERTFILE),
426 CERTFILE_INFO
427 )
428 self.assertEqual(
429 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
430 SIGNED_CERTFILE_INFO
431 )
432
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200433 # Issue #13034: the subjectAltName in some certificates
434 # (notably projects.developer.nokia.com:443) wasn't parsed
435 p = ssl._ssl._test_decode_cert(NOKIACERT)
436 if support.verbose:
437 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
438 self.assertEqual(p['subjectAltName'],
439 (('DNS', 'projects.developer.nokia.com'),
440 ('DNS', 'projects.forum.nokia.com'))
441 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100442 # extra OCSP and AIA fields
443 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
444 self.assertEqual(p['caIssuers'],
445 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
446 self.assertEqual(p['crlDistributionPoints'],
447 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000448
Christian Heimesa37f5242019-01-15 23:47:42 +0100449 def test_parse_cert_CVE_2019_5010(self):
450 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
451 if support.verbose:
452 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
453 self.assertEqual(
454 p,
455 {
456 'issuer': (
457 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
458 'notAfter': 'Jun 14 18:00:58 2028 GMT',
459 'notBefore': 'Jun 18 18:00:58 2018 GMT',
460 'serialNumber': '02',
461 'subject': ((('countryName', 'UK'),),
462 (('commonName',
463 'codenomicon-vm-2.test.lal.cisco.com'),)),
464 'subjectAltName': (
465 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
466 'version': 3
467 }
468 )
469
Christian Heimes824f7f32013-08-17 00:54:47 +0200470 def test_parse_cert_CVE_2013_4238(self):
471 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
472 if support.verbose:
473 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
474 subject = ((('countryName', 'US'),),
475 (('stateOrProvinceName', 'Oregon'),),
476 (('localityName', 'Beaverton'),),
477 (('organizationName', 'Python Software Foundation'),),
478 (('organizationalUnitName', 'Python Core Development'),),
479 (('commonName', 'null.python.org\x00example.org'),),
480 (('emailAddress', 'python-dev@python.org'),))
481 self.assertEqual(p['subject'], subject)
482 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200483 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
484 san = (('DNS', 'altnull.python.org\x00example.com'),
485 ('email', 'null@python.org\x00user@example.org'),
486 ('URI', 'http://null.python.org\x00http://example.org'),
487 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100488 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200489 else:
490 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
491 san = (('DNS', 'altnull.python.org\x00example.com'),
492 ('email', 'null@python.org\x00user@example.org'),
493 ('URI', 'http://null.python.org\x00http://example.org'),
494 ('IP Address', '192.0.2.1'),
495 ('IP Address', '<invalid>'))
496
497 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200498
Christian Heimes1c03abd2016-09-06 23:25:35 +0200499 def test_parse_all_sans(self):
500 p = ssl._ssl._test_decode_cert(ALLSANFILE)
501 self.assertEqual(p['subjectAltName'],
502 (
503 ('DNS', 'allsans'),
504 ('othername', '<unsupported>'),
505 ('othername', '<unsupported>'),
506 ('email', 'user@example.org'),
507 ('DNS', 'www.example.org'),
508 ('DirName',
509 ((('countryName', 'XY'),),
510 (('localityName', 'Castle Anthrax'),),
511 (('organizationName', 'Python Software Foundation'),),
512 (('commonName', 'dirname example'),))),
513 ('URI', 'https://www.python.org/'),
514 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100515 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200516 ('Registered ID', '1.2.3.4.5')
517 )
518 )
519
Antoine Pitrou480a1242010-04-28 21:37:09 +0000520 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000521 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000522 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000523 d1 = ssl.PEM_cert_to_DER_cert(pem)
524 p2 = ssl.DER_cert_to_PEM_cert(d1)
525 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000526 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000527 if not p2.startswith(ssl.PEM_HEADER + '\n'):
528 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
529 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
530 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000531
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000532 def test_openssl_version(self):
533 n = ssl.OPENSSL_VERSION_NUMBER
534 t = ssl.OPENSSL_VERSION_INFO
535 s = ssl.OPENSSL_VERSION
536 self.assertIsInstance(n, int)
537 self.assertIsInstance(t, tuple)
538 self.assertIsInstance(s, str)
539 # Some sanity checks follow
540 # >= 0.9
541 self.assertGreaterEqual(n, 0x900000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100542 # < 4.0
543 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000544 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100545 self.assertGreaterEqual(major, 1)
546 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000547 self.assertGreaterEqual(minor, 0)
548 self.assertLess(minor, 256)
549 self.assertGreaterEqual(fix, 0)
550 self.assertLess(fix, 256)
551 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100552 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000553 self.assertGreaterEqual(status, 0)
554 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400555 # Version string as returned by {Open,Libre}SSL, the format might change
Christian Heimes598894f2016-09-05 23:19:05 +0200556 if IS_LIBRESSL:
557 self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
Victor Stinner789b8052015-01-06 11:51:06 +0100558 (s, t, hex(n)))
Antoine Pitroudfab9352014-07-21 18:35:01 -0400559 else:
560 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
Victor Stinner789b8052015-01-06 11:51:06 +0100561 (s, t, hex(n)))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000562
Antoine Pitrou9d543662010-04-23 23:10:32 +0000563 @support.cpython_only
564 def test_refcycle(self):
565 # Issue #7943: an SSL object doesn't create reference cycles with
566 # itself.
567 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200568 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000569 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800570 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100571 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100572 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000573
Antoine Pitroua468adc2010-09-14 14:43:44 +0000574 def test_wrapped_unconnected(self):
575 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200576 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000577 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200578 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100579 self.assertRaises(OSError, ss.recv, 1)
580 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
581 self.assertRaises(OSError, ss.recvfrom, 1)
582 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
583 self.assertRaises(OSError, ss.send, b'x')
584 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200585 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100586 self.assertRaises(NotImplementedError, ss.sendmsg,
587 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200588 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
589 self.assertRaises(NotImplementedError, ss.recvmsg_into,
590 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000591
Antoine Pitrou40f08742010-04-24 22:04:40 +0000592 def test_timeout(self):
593 # Issue #8524: when creating an SSL socket, the timeout of the
594 # original socket should be retained.
595 for timeout in (None, 0.0, 5.0):
596 s = socket.socket(socket.AF_INET)
597 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200598 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100599 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000600
Christian Heimes2875c602021-04-19 07:27:10 +0200601 @ignore_deprecation
Christian Heimesd0486372016-09-10 23:23:33 +0200602 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000603 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000604 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000605 "certfile must be specified",
606 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000607 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000608 "certfile must be specified for server-side operations",
609 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000610 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000611 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200612 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100613 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
614 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200615 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200616 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000617 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000618 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000619 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200620 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000621 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000622 ssl.wrap_socket(sock,
623 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000624 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200625 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000626 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000627 ssl.wrap_socket(sock,
628 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000629 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000630
Martin Panter3464ea22016-02-01 21:58:11 +0000631 def bad_cert_test(self, certfile):
632 """Check that trying to use the given client certificate fails"""
633 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
634 certfile)
635 sock = socket.socket()
636 self.addCleanup(sock.close)
637 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200638 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200639 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000640
641 def test_empty_cert(self):
642 """Wrapping with an empty cert file"""
643 self.bad_cert_test("nullcert.pem")
644
645 def test_malformed_cert(self):
646 """Wrapping with a badly formatted certificate (syntax error)"""
647 self.bad_cert_test("badcert.pem")
648
649 def test_malformed_key(self):
650 """Wrapping with a badly formatted key (syntax error)"""
651 self.bad_cert_test("badkey.pem")
652
Christian Heimes2875c602021-04-19 07:27:10 +0200653 @ignore_deprecation
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000654 def test_match_hostname(self):
655 def ok(cert, hostname):
656 ssl.match_hostname(cert, hostname)
657 def fail(cert, hostname):
658 self.assertRaises(ssl.CertificateError,
659 ssl.match_hostname, cert, hostname)
660
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100661 # -- Hostname matching --
662
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000663 cert = {'subject': ((('commonName', 'example.com'),),)}
664 ok(cert, 'example.com')
665 ok(cert, 'ExAmple.cOm')
666 fail(cert, 'www.example.com')
667 fail(cert, '.example.com')
668 fail(cert, 'example.org')
669 fail(cert, 'exampleXcom')
670
671 cert = {'subject': ((('commonName', '*.a.com'),),)}
672 ok(cert, 'foo.a.com')
673 fail(cert, 'bar.foo.a.com')
674 fail(cert, 'a.com')
675 fail(cert, 'Xa.com')
676 fail(cert, '.a.com')
677
Mandeep Singhede2ac92017-11-27 04:01:27 +0530678 # only match wildcards when they are the only thing
679 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000680 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530681 fail(cert, 'foo.com')
682 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000683 fail(cert, 'bar.com')
684 fail(cert, 'foo.a.com')
685 fail(cert, 'bar.foo.com')
686
Christian Heimes824f7f32013-08-17 00:54:47 +0200687 # NULL bytes are bad, CVE-2013-4073
688 cert = {'subject': ((('commonName',
689 'null.python.org\x00example.org'),),)}
690 ok(cert, 'null.python.org\x00example.org') # or raise an error?
691 fail(cert, 'example.org')
692 fail(cert, 'null.python.org')
693
Georg Brandl72c98d32013-10-27 07:16:53 +0100694 # error cases with wildcards
695 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
696 fail(cert, 'bar.foo.a.com')
697 fail(cert, 'a.com')
698 fail(cert, 'Xa.com')
699 fail(cert, '.a.com')
700
701 cert = {'subject': ((('commonName', 'a.*.com'),),)}
702 fail(cert, 'a.foo.com')
703 fail(cert, 'a..com')
704 fail(cert, 'a.com')
705
706 # wildcard doesn't match IDNA prefix 'xn--'
707 idna = 'püthon.python.org'.encode("idna").decode("ascii")
708 cert = {'subject': ((('commonName', idna),),)}
709 ok(cert, idna)
710 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
711 fail(cert, idna)
712 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
713 fail(cert, idna)
714
715 # wildcard in first fragment and IDNA A-labels in sequent fragments
716 # are supported.
717 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
718 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530719 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
720 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100721 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
722 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
723
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000724 # Slightly fake real-world example
725 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
726 'subject': ((('commonName', 'linuxfrz.org'),),),
727 'subjectAltName': (('DNS', 'linuxfr.org'),
728 ('DNS', 'linuxfr.com'),
729 ('othername', '<unsupported>'))}
730 ok(cert, 'linuxfr.org')
731 ok(cert, 'linuxfr.com')
732 # Not a "DNS" entry
733 fail(cert, '<unsupported>')
734 # When there is a subjectAltName, commonName isn't used
735 fail(cert, 'linuxfrz.org')
736
737 # A pristine real-world example
738 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
739 'subject': ((('countryName', 'US'),),
740 (('stateOrProvinceName', 'California'),),
741 (('localityName', 'Mountain View'),),
742 (('organizationName', 'Google Inc'),),
743 (('commonName', 'mail.google.com'),))}
744 ok(cert, 'mail.google.com')
745 fail(cert, 'gmail.com')
746 # Only commonName is considered
747 fail(cert, 'California')
748
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100749 # -- IPv4 matching --
750 cert = {'subject': ((('commonName', 'example.com'),),),
751 'subjectAltName': (('DNS', 'example.com'),
752 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200753 ('IP Address', '14.15.16.17'),
754 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100755 ok(cert, '10.11.12.13')
756 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200757 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
758 fail(cert, '127.1')
759 fail(cert, '14.15.16.17 ')
760 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100761 fail(cert, '14.15.16.18')
762 fail(cert, 'example.net')
763
764 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300765 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100766 cert = {'subject': ((('commonName', 'example.com'),),),
767 'subjectAltName': (
768 ('DNS', 'example.com'),
769 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
770 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
771 ok(cert, '2001::cafe')
772 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200773 fail(cert, '2003::baba ')
774 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100775 fail(cert, '2003::bebe')
776 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100777
778 # -- Miscellaneous --
779
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000780 # Neither commonName nor subjectAltName
781 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
782 'subject': ((('countryName', 'US'),),
783 (('stateOrProvinceName', 'California'),),
784 (('localityName', 'Mountain View'),),
785 (('organizationName', 'Google Inc'),))}
786 fail(cert, 'mail.google.com')
787
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200788 # No DNS entry in subjectAltName but a commonName
789 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
790 'subject': ((('countryName', 'US'),),
791 (('stateOrProvinceName', 'California'),),
792 (('localityName', 'Mountain View'),),
793 (('commonName', 'mail.google.com'),)),
794 'subjectAltName': (('othername', 'blabla'), )}
795 ok(cert, 'mail.google.com')
796
797 # No DNS entry subjectAltName and no commonName
798 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
799 'subject': ((('countryName', 'US'),),
800 (('stateOrProvinceName', 'California'),),
801 (('localityName', 'Mountain View'),),
802 (('organizationName', 'Google Inc'),)),
803 'subjectAltName': (('othername', 'blabla'),)}
804 fail(cert, 'google.com')
805
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000806 # Empty cert / no cert
807 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
808 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
809
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200810 # Issue #17980: avoid denials of service by refusing more than one
811 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100812 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
813 with self.assertRaisesRegex(
814 ssl.CertificateError,
815 "partial wildcards in leftmost label are not supported"):
816 ssl.match_hostname(cert, 'axxb.example.com')
817
818 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
819 with self.assertRaisesRegex(
820 ssl.CertificateError,
821 "wildcard can only be present in the leftmost label"):
822 ssl.match_hostname(cert, 'www.sub.example.com')
823
824 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
825 with self.assertRaisesRegex(
826 ssl.CertificateError,
827 "too many wildcards"):
828 ssl.match_hostname(cert, 'axxbxxc.example.com')
829
830 cert = {'subject': ((('commonName', '*'),),)}
831 with self.assertRaisesRegex(
832 ssl.CertificateError,
833 "sole wildcard without additional labels are not support"):
834 ssl.match_hostname(cert, 'host')
835
836 cert = {'subject': ((('commonName', '*.com'),),)}
837 with self.assertRaisesRegex(
838 ssl.CertificateError,
839 r"hostname 'com' doesn't match '\*.com'"):
840 ssl.match_hostname(cert, 'com')
841
842 # extra checks for _inet_paton()
843 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
844 with self.assertRaises(ValueError):
845 ssl._inet_paton(invalid)
846 for ipaddr in ['127.0.0.1', '192.168.0.1']:
847 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300848 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100849 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
850 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200851
Antoine Pitroud5323212010-10-22 18:19:07 +0000852 def test_server_side(self):
853 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200854 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000855 with socket.socket() as sock:
856 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
857 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000858
Antoine Pitroud6494802011-07-21 01:11:30 +0200859 def test_unknown_channel_binding(self):
860 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200861 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200862 c = socket.socket(socket.AF_INET)
863 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200864 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100865 with self.assertRaises(ValueError):
866 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200867 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200868
869 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
870 "'tls-unique' channel binding not available")
871 def test_tls_unique_channel_binding(self):
872 # unconnected should return None for known type
873 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200874 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100875 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200876 # the same for server-side
877 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200878 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100879 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200880
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600881 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200882 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600883 r = repr(ss)
884 with self.assertWarns(ResourceWarning) as cm:
885 ss = None
886 support.gc_collect()
887 self.assertIn(r, str(cm.warning.args[0]))
888
Christian Heimes6d7ad132013-06-09 18:02:55 +0200889 def test_get_default_verify_paths(self):
890 paths = ssl.get_default_verify_paths()
891 self.assertEqual(len(paths), 6)
892 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
893
Hai Shia7f5d932020-08-04 00:41:24 +0800894 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200895 env["SSL_CERT_DIR"] = CAPATH
896 env["SSL_CERT_FILE"] = CERTFILE
897 paths = ssl.get_default_verify_paths()
898 self.assertEqual(paths.cafile, CERTFILE)
899 self.assertEqual(paths.capath, CAPATH)
900
Christian Heimes44109d72013-11-22 01:51:30 +0100901 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
902 def test_enum_certificates(self):
903 self.assertTrue(ssl.enum_certificates("CA"))
904 self.assertTrue(ssl.enum_certificates("ROOT"))
905
906 self.assertRaises(TypeError, ssl.enum_certificates)
907 self.assertRaises(WindowsError, ssl.enum_certificates, "")
908
Christian Heimesc2d65e12013-11-22 16:13:55 +0100909 trust_oids = set()
910 for storename in ("CA", "ROOT"):
911 store = ssl.enum_certificates(storename)
912 self.assertIsInstance(store, list)
913 for element in store:
914 self.assertIsInstance(element, tuple)
915 self.assertEqual(len(element), 3)
916 cert, enc, trust = element
917 self.assertIsInstance(cert, bytes)
918 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200919 self.assertIsInstance(trust, (frozenset, set, bool))
920 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100921 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100922
923 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100924 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200925
Christian Heimes46bebee2013-06-09 19:03:31 +0200926 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100927 def test_enum_crls(self):
928 self.assertTrue(ssl.enum_crls("CA"))
929 self.assertRaises(TypeError, ssl.enum_crls)
930 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200931
Christian Heimes44109d72013-11-22 01:51:30 +0100932 crls = ssl.enum_crls("CA")
933 self.assertIsInstance(crls, list)
934 for element in crls:
935 self.assertIsInstance(element, tuple)
936 self.assertEqual(len(element), 2)
937 self.assertIsInstance(element[0], bytes)
938 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200939
Christian Heimes46bebee2013-06-09 19:03:31 +0200940
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100941 def test_asn1object(self):
942 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
943 '1.3.6.1.5.5.7.3.1')
944
945 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
946 self.assertEqual(val, expected)
947 self.assertEqual(val.nid, 129)
948 self.assertEqual(val.shortname, 'serverAuth')
949 self.assertEqual(val.longname, 'TLS Web Server Authentication')
950 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
951 self.assertIsInstance(val, ssl._ASN1Object)
952 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
953
954 val = ssl._ASN1Object.fromnid(129)
955 self.assertEqual(val, expected)
956 self.assertIsInstance(val, ssl._ASN1Object)
957 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100958 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
959 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100960 for i in range(1000):
961 try:
962 obj = ssl._ASN1Object.fromnid(i)
963 except ValueError:
964 pass
965 else:
966 self.assertIsInstance(obj.nid, int)
967 self.assertIsInstance(obj.shortname, str)
968 self.assertIsInstance(obj.longname, str)
969 self.assertIsInstance(obj.oid, (str, type(None)))
970
971 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
972 self.assertEqual(val, expected)
973 self.assertIsInstance(val, ssl._ASN1Object)
974 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
975 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
976 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100977 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
978 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100979
Christian Heimes72d28502013-11-23 13:56:58 +0100980 def test_purpose_enum(self):
981 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
982 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
983 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
984 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
985 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
986 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
987 '1.3.6.1.5.5.7.3.1')
988
989 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
990 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
991 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
992 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
993 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
994 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
995 '1.3.6.1.5.5.7.3.2')
996
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100997 def test_unsupported_dtls(self):
998 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
999 self.addCleanup(s.close)
1000 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +02001001 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001002 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +02001003 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001004 with self.assertRaises(NotImplementedError) as cx:
1005 ctx.wrap_socket(s)
1006 self.assertEqual(str(cx.exception), "only stream sockets are supported")
1007
Antoine Pitrouc695c952014-04-28 20:57:36 +02001008 def cert_time_ok(self, timestring, timestamp):
1009 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
1010
1011 def cert_time_fail(self, timestring):
1012 with self.assertRaises(ValueError):
1013 ssl.cert_time_to_seconds(timestring)
1014
1015 @unittest.skipUnless(utc_offset(),
1016 'local time needs to be different from UTC')
1017 def test_cert_time_to_seconds_timezone(self):
1018 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
1019 # results if local timezone is not UTC
1020 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
1021 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
1022
1023 def test_cert_time_to_seconds(self):
1024 timestring = "Jan 5 09:34:43 2018 GMT"
1025 ts = 1515144883.0
1026 self.cert_time_ok(timestring, ts)
1027 # accept keyword parameter, assert its name
1028 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
1029 # accept both %e and %d (space or zero generated by strftime)
1030 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
1031 # case-insensitive
1032 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
1033 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
1034 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1035 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1036 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1037 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1038 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1039 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1040
1041 newyear_ts = 1230768000.0
1042 # leap seconds
1043 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1044 # same timestamp
1045 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1046
1047 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1048 # allow 60th second (even if it is not a leap second)
1049 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1050 # allow 2nd leap second for compatibility with time.strptime()
1051 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1052 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1053
Mike53f7a7c2017-12-14 14:04:53 +03001054 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001055 # 99991231235959Z (rfc 5280)
1056 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1057
1058 @support.run_with_locale('LC_ALL', '')
1059 def test_cert_time_to_seconds_locale(self):
1060 # `cert_time_to_seconds()` should be locale independent
1061
1062 def local_february_name():
1063 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1064
1065 if local_february_name().lower() == 'feb':
1066 self.skipTest("locale-specific month name needs to be "
1067 "different from C locale")
1068
1069 # locale-independent
1070 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1071 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1072
Martin Panter3840b2a2016-03-27 01:53:46 +00001073 def test_connect_ex_error(self):
1074 server = socket.socket(socket.AF_INET)
1075 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001076 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001077 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001078 cert_reqs=ssl.CERT_REQUIRED)
1079 self.addCleanup(s.close)
1080 rc = s.connect_ex((HOST, port))
1081 # Issue #19919: Windows machines or VMs hosted on Windows
1082 # machines sometimes return EWOULDBLOCK.
1083 errors = (
1084 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1085 errno.EWOULDBLOCK,
1086 )
1087 self.assertIn(rc, errors)
1088
Christian Heimes89d15502021-04-19 06:55:30 +02001089 def test_read_write_zero(self):
1090 # empty reads and writes now work, bpo-42854, bpo-31711
1091 client_context, server_context, hostname = testing_context()
1092 server = ThreadedEchoServer(context=server_context)
1093 with server:
1094 with client_context.wrap_socket(socket.socket(),
1095 server_hostname=hostname) as s:
1096 s.connect((HOST, server.port))
1097 self.assertEqual(s.recv(0), b"")
1098 self.assertEqual(s.send(b""), 0)
1099
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001100
Antoine Pitrou152efa22010-05-16 18:19:27 +00001101class ContextTests(unittest.TestCase):
1102
1103 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001104 for protocol in PROTOCOLS:
Christian Heimes2875c602021-04-19 07:27:10 +02001105 with warnings_helper.check_warnings():
1106 ctx = ssl.SSLContext(protocol)
1107 self.assertEqual(ctx.protocol, protocol)
1108 with warnings_helper.check_warnings():
1109 ctx = ssl.SSLContext()
Christian Heimes598894f2016-09-05 23:19:05 +02001110 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001111 self.assertRaises(ValueError, ssl.SSLContext, -1)
1112 self.assertRaises(ValueError, ssl.SSLContext, 42)
1113
Antoine Pitrou152efa22010-05-16 18:19:27 +00001114 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001115 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001116 ctx.set_ciphers("ALL")
1117 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001118 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001119 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001120
Christian Heimes892d66e2018-01-29 14:10:18 +01001121 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1122 "Test applies only to Python default ciphers")
1123 def test_python_ciphers(self):
1124 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1125 ciphers = ctx.get_ciphers()
1126 for suite in ciphers:
1127 name = suite['name']
1128 self.assertNotIn("PSK", name)
1129 self.assertNotIn("SRP", name)
1130 self.assertNotIn("MD5", name)
1131 self.assertNotIn("RC4", name)
1132 self.assertNotIn("3DES", name)
1133
Christian Heimes25bfcd52016-09-06 00:04:45 +02001134 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001135 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001136 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001137 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001138 self.assertIn('AES256-GCM-SHA384', names)
1139 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001140
Antoine Pitroub5218772010-05-21 09:56:06 +00001141 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001142 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001143 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001144 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001145 # SSLContext also enables these by default
1146 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001147 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001148 OP_ENABLE_MIDDLEBOX_COMPAT |
1149 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001150 self.assertEqual(default, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001151 with warnings_helper.check_warnings():
1152 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001153 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001154 with warnings_helper.check_warnings():
1155 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
Christian Heimes39258d32021-04-17 11:36:35 +02001156 self.assertEqual(default, ctx.options)
1157 ctx.options = 0
1158 # Ubuntu has OP_NO_SSLv3 forced on by default
1159 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001160
Christian Heimesa170fa12017-09-15 20:27:30 +02001161 def test_verify_mode_protocol(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001162 with warnings_helper.check_warnings():
1163 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001164 # Default value
1165 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1166 ctx.verify_mode = ssl.CERT_OPTIONAL
1167 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1168 ctx.verify_mode = ssl.CERT_REQUIRED
1169 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1170 ctx.verify_mode = ssl.CERT_NONE
1171 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1172 with self.assertRaises(TypeError):
1173 ctx.verify_mode = None
1174 with self.assertRaises(ValueError):
1175 ctx.verify_mode = 42
1176
Christian Heimesa170fa12017-09-15 20:27:30 +02001177 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1178 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1179 self.assertFalse(ctx.check_hostname)
1180
1181 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1182 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1183 self.assertTrue(ctx.check_hostname)
1184
Christian Heimes61d478c2018-01-27 15:51:38 +01001185 def test_hostname_checks_common_name(self):
1186 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1187 self.assertTrue(ctx.hostname_checks_common_name)
1188 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1189 ctx.hostname_checks_common_name = True
1190 self.assertTrue(ctx.hostname_checks_common_name)
1191 ctx.hostname_checks_common_name = False
1192 self.assertFalse(ctx.hostname_checks_common_name)
1193 ctx.hostname_checks_common_name = True
1194 self.assertTrue(ctx.hostname_checks_common_name)
1195 else:
1196 with self.assertRaises(AttributeError):
1197 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001198
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001199 @requires_minimum_version
Christian Heimesc9bc49c2019-09-11 19:24:47 +02001200 @unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
Christian Heimes2875c602021-04-19 07:27:10 +02001201 @ignore_deprecation
Christian Heimes698dde12018-02-27 11:54:43 +01001202 def test_min_max_version(self):
1203 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001204 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1205 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001206 minimum_range = {
1207 # stock OpenSSL
1208 ssl.TLSVersion.MINIMUM_SUPPORTED,
1209 # Fedora 29 uses TLS 1.0 by default
1210 ssl.TLSVersion.TLSv1,
1211 # RHEL 8 uses TLS 1.2 by default
1212 ssl.TLSVersion.TLSv1_2
1213 }
torsava34864d12019-12-02 17:15:42 +01001214 maximum_range = {
1215 # stock OpenSSL
1216 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1217 # Fedora 32 uses TLS 1.3 by default
1218 ssl.TLSVersion.TLSv1_3
1219 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001220
Christian Heimes34de2d32019-01-18 16:09:30 +01001221 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001222 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001223 )
torsava34864d12019-12-02 17:15:42 +01001224 self.assertIn(
1225 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001226 )
1227
1228 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1229 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1230 self.assertEqual(
1231 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1232 )
1233 self.assertEqual(
1234 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1235 )
1236
1237 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1238 ctx.maximum_version = ssl.TLSVersion.TLSv1
1239 self.assertEqual(
1240 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1241 )
1242 self.assertEqual(
1243 ctx.maximum_version, ssl.TLSVersion.TLSv1
1244 )
1245
1246 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1247 self.assertEqual(
1248 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1249 )
1250
1251 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1252 self.assertIn(
1253 ctx.maximum_version,
1254 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1255 )
1256
1257 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1258 self.assertIn(
1259 ctx.minimum_version,
1260 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1261 )
1262
1263 with self.assertRaises(ValueError):
1264 ctx.minimum_version = 42
1265
1266 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1267
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001268 self.assertIn(
1269 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001270 )
1271 self.assertEqual(
1272 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1273 )
1274 with self.assertRaises(ValueError):
1275 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1276 with self.assertRaises(ValueError):
1277 ctx.maximum_version = ssl.TLSVersion.TLSv1
1278
1279
matthewhughes9348e836bb2020-07-17 09:59:15 +01001280 @unittest.skipUnless(
1281 hasattr(ssl.SSLContext, 'security_level'),
1282 "requires OpenSSL >= 1.1.0"
1283 )
1284 def test_security_level(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001285 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
matthewhughes9348e836bb2020-07-17 09:59:15 +01001286 # The default security callback allows for levels between 0-5
1287 # with OpenSSL defaulting to 1, however some vendors override the
1288 # default value (e.g. Debian defaults to 2)
1289 security_level_range = {
1290 0,
1291 1, # OpenSSL default
1292 2, # Debian
1293 3,
1294 4,
1295 5,
1296 }
1297 self.assertIn(ctx.security_level, security_level_range)
1298
Christian Heimes22587792013-11-21 23:56:13 +01001299 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001300 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001301 # default value
1302 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1303 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001304 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1305 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1306 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1307 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1308 ctx.verify_flags = ssl.VERIFY_DEFAULT
1309 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001310 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1311 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001312 # supports any value
1313 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1314 self.assertEqual(ctx.verify_flags,
1315 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1316 with self.assertRaises(TypeError):
1317 ctx.verify_flags = None
1318
Antoine Pitrou152efa22010-05-16 18:19:27 +00001319 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001320 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001321 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001322 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001323 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1324 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001325 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001326 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001327 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001328 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001329 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001330 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001331 ctx.load_cert_chain(EMPTYCERT)
1332 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001333 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001334 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1335 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1336 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001337 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001338 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001339 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001340 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001341 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001342 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1343 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001344 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001345 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001346 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001347 # Password protected key and cert
1348 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1349 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1350 ctx.load_cert_chain(CERTFILE_PROTECTED,
1351 password=bytearray(KEY_PASSWORD.encode()))
1352 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1353 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1354 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1355 bytearray(KEY_PASSWORD.encode()))
1356 with self.assertRaisesRegex(TypeError, "should be a string"):
1357 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1358 with self.assertRaises(ssl.SSLError):
1359 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1360 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1361 # openssl has a fixed limit on the password buffer.
1362 # PEM_BUFSIZE is generally set to 1kb.
1363 # Return a string larger than this.
1364 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1365 # Password callback
1366 def getpass_unicode():
1367 return KEY_PASSWORD
1368 def getpass_bytes():
1369 return KEY_PASSWORD.encode()
1370 def getpass_bytearray():
1371 return bytearray(KEY_PASSWORD.encode())
1372 def getpass_badpass():
1373 return "badpass"
1374 def getpass_huge():
1375 return b'a' * (1024 * 1024)
1376 def getpass_bad_type():
1377 return 9
1378 def getpass_exception():
1379 raise Exception('getpass error')
1380 class GetPassCallable:
1381 def __call__(self):
1382 return KEY_PASSWORD
1383 def getpass(self):
1384 return KEY_PASSWORD
1385 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1386 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1387 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1388 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1389 ctx.load_cert_chain(CERTFILE_PROTECTED,
1390 password=GetPassCallable().getpass)
1391 with self.assertRaises(ssl.SSLError):
1392 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1393 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1394 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1395 with self.assertRaisesRegex(TypeError, "must return a string"):
1396 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1397 with self.assertRaisesRegex(Exception, "getpass error"):
1398 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1399 # Make sure the password function isn't called if it isn't needed
1400 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001401
1402 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001403 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001404 ctx.load_verify_locations(CERTFILE)
1405 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1406 ctx.load_verify_locations(BYTES_CERTFILE)
1407 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1408 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001409 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001410 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001411 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001412 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001413 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001414 ctx.load_verify_locations(BADCERT)
1415 ctx.load_verify_locations(CERTFILE, CAPATH)
1416 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1417
Victor Stinner80f75e62011-01-29 11:31:20 +00001418 # Issue #10989: crash if the second argument type is invalid
1419 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1420
Christian Heimesefff7062013-11-21 03:35:02 +01001421 def test_load_verify_cadata(self):
1422 # test cadata
1423 with open(CAFILE_CACERT) as f:
1424 cacert_pem = f.read()
1425 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1426 with open(CAFILE_NEURONIO) as f:
1427 neuronio_pem = f.read()
1428 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1429
1430 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001431 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001432 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1433 ctx.load_verify_locations(cadata=cacert_pem)
1434 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1435 ctx.load_verify_locations(cadata=neuronio_pem)
1436 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1437 # cert already in hash table
1438 ctx.load_verify_locations(cadata=neuronio_pem)
1439 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1440
1441 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001442 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001443 combined = "\n".join((cacert_pem, neuronio_pem))
1444 ctx.load_verify_locations(cadata=combined)
1445 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1446
1447 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001448 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001449 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1450 neuronio_pem, "tail"]
1451 ctx.load_verify_locations(cadata="\n".join(combined))
1452 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1453
1454 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001455 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001456 ctx.load_verify_locations(cadata=cacert_der)
1457 ctx.load_verify_locations(cadata=neuronio_der)
1458 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1459 # cert already in hash table
1460 ctx.load_verify_locations(cadata=cacert_der)
1461 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1462
1463 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001464 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001465 combined = b"".join((cacert_der, neuronio_der))
1466 ctx.load_verify_locations(cadata=combined)
1467 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1468
1469 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001470 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001471 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1472
1473 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1474 ctx.load_verify_locations(cadata="broken")
1475 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1476 ctx.load_verify_locations(cadata=b"broken")
1477
1478
Paul Monsonf3550692019-06-19 13:09:54 -07001479 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001480 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001481 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001482 ctx.load_dh_params(DHFILE)
1483 if os.name != 'nt':
1484 ctx.load_dh_params(BYTES_DHFILE)
1485 self.assertRaises(TypeError, ctx.load_dh_params)
1486 self.assertRaises(TypeError, ctx.load_dh_params, None)
1487 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001488 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001489 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001490 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001491 ctx.load_dh_params(CERTFILE)
1492
Antoine Pitroub0182c82010-10-12 20:09:02 +00001493 def test_session_stats(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001494 for proto in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
Antoine Pitroub0182c82010-10-12 20:09:02 +00001495 ctx = ssl.SSLContext(proto)
1496 self.assertEqual(ctx.session_stats(), {
1497 'number': 0,
1498 'connect': 0,
1499 'connect_good': 0,
1500 'connect_renegotiate': 0,
1501 'accept': 0,
1502 'accept_good': 0,
1503 'accept_renegotiate': 0,
1504 'hits': 0,
1505 'misses': 0,
1506 'timeouts': 0,
1507 'cache_full': 0,
1508 })
1509
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001510 def test_set_default_verify_paths(self):
1511 # There's not much we can do to test that it acts as expected,
1512 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001513 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001514 ctx.set_default_verify_paths()
1515
Antoine Pitrou501da612011-12-21 09:27:41 +01001516 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001517 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001518 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001519 ctx.set_ecdh_curve("prime256v1")
1520 ctx.set_ecdh_curve(b"prime256v1")
1521 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1522 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1523 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1524 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1525
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001526 @needs_sni
1527 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001528 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001529
1530 # set_servername_callback expects a callable, or None
1531 self.assertRaises(TypeError, ctx.set_servername_callback)
1532 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1533 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1534 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1535
1536 def dummycallback(sock, servername, ctx):
1537 pass
1538 ctx.set_servername_callback(None)
1539 ctx.set_servername_callback(dummycallback)
1540
1541 @needs_sni
1542 def test_sni_callback_refcycle(self):
1543 # Reference cycles through the servername callback are detected
1544 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001545 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001546 def dummycallback(sock, servername, ctx, cycle=ctx):
1547 pass
1548 ctx.set_servername_callback(dummycallback)
1549 wr = weakref.ref(ctx)
1550 del ctx, dummycallback
1551 gc.collect()
1552 self.assertIs(wr(), None)
1553
Christian Heimes9a5395a2013-06-17 15:44:12 +02001554 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001555 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001556 self.assertEqual(ctx.cert_store_stats(),
1557 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1558 ctx.load_cert_chain(CERTFILE)
1559 self.assertEqual(ctx.cert_store_stats(),
1560 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1561 ctx.load_verify_locations(CERTFILE)
1562 self.assertEqual(ctx.cert_store_stats(),
1563 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001564 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001565 self.assertEqual(ctx.cert_store_stats(),
1566 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1567
1568 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001569 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001570 self.assertEqual(ctx.get_ca_certs(), [])
1571 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1572 ctx.load_verify_locations(CERTFILE)
1573 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001574 # but CAFILE_CACERT is a CA cert
1575 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001576 self.assertEqual(ctx.get_ca_certs(),
1577 [{'issuer': ((('organizationName', 'Root CA'),),
1578 (('organizationalUnitName', 'http://www.cacert.org'),),
1579 (('commonName', 'CA Cert Signing Authority'),),
1580 (('emailAddress', 'support@cacert.org'),)),
1581 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1582 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1583 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001584 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001585 'subject': ((('organizationName', 'Root CA'),),
1586 (('organizationalUnitName', 'http://www.cacert.org'),),
1587 (('commonName', 'CA Cert Signing Authority'),),
1588 (('emailAddress', 'support@cacert.org'),)),
1589 'version': 3}])
1590
Martin Panterb55f8b72016-01-14 12:53:56 +00001591 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001592 pem = f.read()
1593 der = ssl.PEM_cert_to_DER_cert(pem)
1594 self.assertEqual(ctx.get_ca_certs(True), [der])
1595
Christian Heimes72d28502013-11-23 13:56:58 +01001596 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001597 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001598 ctx.load_default_certs()
1599
Christian Heimesa170fa12017-09-15 20:27:30 +02001600 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001601 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1602 ctx.load_default_certs()
1603
Christian Heimesa170fa12017-09-15 20:27:30 +02001604 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001605 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1606
Christian Heimesa170fa12017-09-15 20:27:30 +02001607 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001608 self.assertRaises(TypeError, ctx.load_default_certs, None)
1609 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1610
Benjamin Peterson91244e02014-10-03 18:17:15 -04001611 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimes598894f2016-09-05 23:19:05 +02001612 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001613 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001614 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001615 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001616 env["SSL_CERT_DIR"] = CAPATH
1617 env["SSL_CERT_FILE"] = CERTFILE
1618 ctx.load_default_certs()
1619 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1620
Benjamin Peterson91244e02014-10-03 18:17:15 -04001621 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001622 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001623 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001624 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001625 ctx.load_default_certs()
1626 stats = ctx.cert_store_stats()
1627
Christian Heimesa170fa12017-09-15 20:27:30 +02001628 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001629 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001630 env["SSL_CERT_DIR"] = CAPATH
1631 env["SSL_CERT_FILE"] = CERTFILE
1632 ctx.load_default_certs()
1633 stats["x509"] += 1
1634 self.assertEqual(ctx.cert_store_stats(), stats)
1635
Christian Heimes358cfd42016-09-10 22:43:48 +02001636 def _assert_context_options(self, ctx):
1637 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1638 if OP_NO_COMPRESSION != 0:
1639 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1640 OP_NO_COMPRESSION)
1641 if OP_SINGLE_DH_USE != 0:
1642 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1643 OP_SINGLE_DH_USE)
1644 if OP_SINGLE_ECDH_USE != 0:
1645 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1646 OP_SINGLE_ECDH_USE)
1647 if OP_CIPHER_SERVER_PREFERENCE != 0:
1648 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1649 OP_CIPHER_SERVER_PREFERENCE)
1650
Christian Heimes4c05b472013-11-23 15:58:30 +01001651 def test_create_default_context(self):
1652 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001653
Christian Heimes2875c602021-04-19 07:27:10 +02001654 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001655 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001656 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001657 self._assert_context_options(ctx)
1658
Christian Heimes4c05b472013-11-23 15:58:30 +01001659 with open(SIGNING_CA) as f:
1660 cadata = f.read()
1661 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1662 cadata=cadata)
Christian Heimes2875c602021-04-19 07:27:10 +02001663 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001664 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001665 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001666
1667 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001668 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes4c05b472013-11-23 15:58:30 +01001669 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001670 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001671
Christian Heimes2875c602021-04-19 07:27:10 +02001672
1673
Christian Heimes67986f92013-11-23 22:43:47 +01001674 def test__create_stdlib_context(self):
1675 ctx = ssl._create_stdlib_context()
Christian Heimes2875c602021-04-19 07:27:10 +02001676 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes67986f92013-11-23 22:43:47 +01001677 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001678 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001679 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001680
Christian Heimes2875c602021-04-19 07:27:10 +02001681 with warnings_helper.check_warnings():
1682 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
Christian Heimes67986f92013-11-23 22:43:47 +01001683 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1684 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001685 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001686
Christian Heimes2875c602021-04-19 07:27:10 +02001687 with warnings_helper.check_warnings():
1688 ctx = ssl._create_stdlib_context(
1689 ssl.PROTOCOL_TLSv1_2,
1690 cert_reqs=ssl.CERT_REQUIRED,
1691 check_hostname=True
1692 )
1693 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
Christian Heimes67986f92013-11-23 22:43:47 +01001694 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001695 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001696 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001697
1698 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001699 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes67986f92013-11-23 22:43:47 +01001700 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001701 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001702
Christian Heimes1aa9a752013-12-02 02:41:19 +01001703 def test_check_hostname(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001704 with warnings_helper.check_warnings():
1705 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001706 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001707 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001708
Christian Heimese82c0342017-09-15 20:29:57 +02001709 # Auto set CERT_REQUIRED
1710 ctx.check_hostname = True
1711 self.assertTrue(ctx.check_hostname)
1712 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1713 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001714 ctx.verify_mode = ssl.CERT_REQUIRED
1715 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001716 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001717
Christian Heimese82c0342017-09-15 20:29:57 +02001718 # Changing verify_mode does not affect check_hostname
1719 ctx.check_hostname = False
1720 ctx.verify_mode = ssl.CERT_NONE
1721 ctx.check_hostname = False
1722 self.assertFalse(ctx.check_hostname)
1723 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1724 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001725 ctx.check_hostname = True
1726 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001727 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1728
1729 ctx.check_hostname = False
1730 ctx.verify_mode = ssl.CERT_OPTIONAL
1731 ctx.check_hostname = False
1732 self.assertFalse(ctx.check_hostname)
1733 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1734 # keep CERT_OPTIONAL
1735 ctx.check_hostname = True
1736 self.assertTrue(ctx.check_hostname)
1737 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001738
1739 # Cannot set CERT_NONE with check_hostname enabled
1740 with self.assertRaises(ValueError):
1741 ctx.verify_mode = ssl.CERT_NONE
1742 ctx.check_hostname = False
1743 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001744 ctx.verify_mode = ssl.CERT_NONE
1745 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001746
Christian Heimes5fe668c2016-09-12 00:01:11 +02001747 def test_context_client_server(self):
1748 # PROTOCOL_TLS_CLIENT has sane defaults
1749 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1750 self.assertTrue(ctx.check_hostname)
1751 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1752
1753 # PROTOCOL_TLS_SERVER has different but also sane defaults
1754 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1755 self.assertFalse(ctx.check_hostname)
1756 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1757
Christian Heimes4df60f12017-09-15 20:26:05 +02001758 def test_context_custom_class(self):
1759 class MySSLSocket(ssl.SSLSocket):
1760 pass
1761
1762 class MySSLObject(ssl.SSLObject):
1763 pass
1764
1765 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1766 ctx.sslsocket_class = MySSLSocket
1767 ctx.sslobject_class = MySSLObject
1768
1769 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1770 self.assertIsInstance(sock, MySSLSocket)
1771 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1772 self.assertIsInstance(obj, MySSLObject)
1773
Christian Heimes78c7d522019-06-03 21:00:10 +02001774 def test_num_tickest(self):
1775 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1776 self.assertEqual(ctx.num_tickets, 2)
1777 ctx.num_tickets = 1
1778 self.assertEqual(ctx.num_tickets, 1)
1779 ctx.num_tickets = 0
1780 self.assertEqual(ctx.num_tickets, 0)
1781 with self.assertRaises(ValueError):
1782 ctx.num_tickets = -1
1783 with self.assertRaises(TypeError):
1784 ctx.num_tickets = None
1785
1786 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1787 self.assertEqual(ctx.num_tickets, 2)
1788 with self.assertRaises(ValueError):
1789 ctx.num_tickets = 1
1790
Antoine Pitrou152efa22010-05-16 18:19:27 +00001791
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001792class SSLErrorTests(unittest.TestCase):
1793
1794 def test_str(self):
1795 # The str() of a SSLError doesn't include the errno
1796 e = ssl.SSLError(1, "foo")
1797 self.assertEqual(str(e), "foo")
1798 self.assertEqual(e.errno, 1)
1799 # Same for a subclass
1800 e = ssl.SSLZeroReturnError(1, "foo")
1801 self.assertEqual(str(e), "foo")
1802 self.assertEqual(e.errno, 1)
1803
Paul Monsonf3550692019-06-19 13:09:54 -07001804 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001805 def test_lib_reason(self):
1806 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001807 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001808 with self.assertRaises(ssl.SSLError) as cm:
1809 ctx.load_dh_params(CERTFILE)
1810 self.assertEqual(cm.exception.library, 'PEM')
1811 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1812 s = str(cm.exception)
1813 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1814
1815 def test_subclass(self):
1816 # Check that the appropriate SSLError subclass is raised
1817 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001818 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1819 ctx.check_hostname = False
1820 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001821 with socket.create_server(("127.0.0.1", 0)) as s:
1822 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001823 c.setblocking(False)
1824 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001825 with self.assertRaises(ssl.SSLWantReadError) as cm:
1826 c.do_handshake()
1827 s = str(cm.exception)
1828 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1829 # For compatibility
1830 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1831
1832
Christian Heimes61d478c2018-01-27 15:51:38 +01001833 def test_bad_server_hostname(self):
1834 ctx = ssl.create_default_context()
1835 with self.assertRaises(ValueError):
1836 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1837 server_hostname="")
1838 with self.assertRaises(ValueError):
1839 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1840 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001841 with self.assertRaises(TypeError):
1842 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1843 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001844
1845
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001846class MemoryBIOTests(unittest.TestCase):
1847
1848 def test_read_write(self):
1849 bio = ssl.MemoryBIO()
1850 bio.write(b'foo')
1851 self.assertEqual(bio.read(), b'foo')
1852 self.assertEqual(bio.read(), b'')
1853 bio.write(b'foo')
1854 bio.write(b'bar')
1855 self.assertEqual(bio.read(), b'foobar')
1856 self.assertEqual(bio.read(), b'')
1857 bio.write(b'baz')
1858 self.assertEqual(bio.read(2), b'ba')
1859 self.assertEqual(bio.read(1), b'z')
1860 self.assertEqual(bio.read(1), b'')
1861
1862 def test_eof(self):
1863 bio = ssl.MemoryBIO()
1864 self.assertFalse(bio.eof)
1865 self.assertEqual(bio.read(), b'')
1866 self.assertFalse(bio.eof)
1867 bio.write(b'foo')
1868 self.assertFalse(bio.eof)
1869 bio.write_eof()
1870 self.assertFalse(bio.eof)
1871 self.assertEqual(bio.read(2), b'fo')
1872 self.assertFalse(bio.eof)
1873 self.assertEqual(bio.read(1), b'o')
1874 self.assertTrue(bio.eof)
1875 self.assertEqual(bio.read(), b'')
1876 self.assertTrue(bio.eof)
1877
1878 def test_pending(self):
1879 bio = ssl.MemoryBIO()
1880 self.assertEqual(bio.pending, 0)
1881 bio.write(b'foo')
1882 self.assertEqual(bio.pending, 3)
1883 for i in range(3):
1884 bio.read(1)
1885 self.assertEqual(bio.pending, 3-i-1)
1886 for i in range(3):
1887 bio.write(b'x')
1888 self.assertEqual(bio.pending, i+1)
1889 bio.read()
1890 self.assertEqual(bio.pending, 0)
1891
1892 def test_buffer_types(self):
1893 bio = ssl.MemoryBIO()
1894 bio.write(b'foo')
1895 self.assertEqual(bio.read(), b'foo')
1896 bio.write(bytearray(b'bar'))
1897 self.assertEqual(bio.read(), b'bar')
1898 bio.write(memoryview(b'baz'))
1899 self.assertEqual(bio.read(), b'baz')
1900
1901 def test_error_types(self):
1902 bio = ssl.MemoryBIO()
1903 self.assertRaises(TypeError, bio.write, 'foo')
1904 self.assertRaises(TypeError, bio.write, None)
1905 self.assertRaises(TypeError, bio.write, True)
1906 self.assertRaises(TypeError, bio.write, 1)
1907
1908
Christian Heimes9d50ab52018-02-27 10:17:30 +01001909class SSLObjectTests(unittest.TestCase):
1910 def test_private_init(self):
1911 bio = ssl.MemoryBIO()
1912 with self.assertRaisesRegex(TypeError, "public constructor"):
1913 ssl.SSLObject(bio, bio)
1914
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001915 def test_unwrap(self):
1916 client_ctx, server_ctx, hostname = testing_context()
1917 c_in = ssl.MemoryBIO()
1918 c_out = ssl.MemoryBIO()
1919 s_in = ssl.MemoryBIO()
1920 s_out = ssl.MemoryBIO()
1921 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1922 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1923
1924 # Loop on the handshake for a bit to get it settled
1925 for _ in range(5):
1926 try:
1927 client.do_handshake()
1928 except ssl.SSLWantReadError:
1929 pass
1930 if c_out.pending:
1931 s_in.write(c_out.read())
1932 try:
1933 server.do_handshake()
1934 except ssl.SSLWantReadError:
1935 pass
1936 if s_out.pending:
1937 c_in.write(s_out.read())
1938 # Now the handshakes should be complete (don't raise WantReadError)
1939 client.do_handshake()
1940 server.do_handshake()
1941
1942 # Now if we unwrap one side unilaterally, it should send close-notify
1943 # and raise WantReadError:
1944 with self.assertRaises(ssl.SSLWantReadError):
1945 client.unwrap()
1946
1947 # But server.unwrap() does not raise, because it reads the client's
1948 # close-notify:
1949 s_in.write(c_out.read())
1950 server.unwrap()
1951
1952 # And now that the client gets the server's close-notify, it doesn't
1953 # raise either.
1954 c_in.write(s_out.read())
1955 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001956
Martin Panter3840b2a2016-03-27 01:53:46 +00001957class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001958 """Tests that connect to a simple server running in the background"""
1959
1960 def setUp(self):
juhovh49fdf112021-04-18 21:11:48 +10001961 self.server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1962 self.server_context.load_cert_chain(SIGNED_CERTFILE)
1963 server = ThreadedEchoServer(context=self.server_context)
Martin Panter3840b2a2016-03-27 01:53:46 +00001964 self.server_addr = (HOST, server.port)
1965 server.__enter__()
1966 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001967
Antoine Pitrou480a1242010-04-28 21:37:09 +00001968 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001969 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001970 cert_reqs=ssl.CERT_NONE) as s:
1971 s.connect(self.server_addr)
1972 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001973 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001974
Martin Panter3840b2a2016-03-27 01:53:46 +00001975 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001976 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001977 cert_reqs=ssl.CERT_REQUIRED,
1978 ca_certs=SIGNING_CA) as s:
1979 s.connect(self.server_addr)
1980 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001981 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001982
Martin Panter3840b2a2016-03-27 01:53:46 +00001983 def test_connect_fail(self):
1984 # This should fail because we have no verification certs. Connection
1985 # failure crashes ThreadedEchoServer, so run this in an independent
1986 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001987 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001988 cert_reqs=ssl.CERT_REQUIRED)
1989 self.addCleanup(s.close)
1990 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1991 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001992
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001993 def test_connect_ex(self):
1994 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02001995 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001996 cert_reqs=ssl.CERT_REQUIRED,
1997 ca_certs=SIGNING_CA)
1998 self.addCleanup(s.close)
1999 self.assertEqual(0, s.connect_ex(self.server_addr))
2000 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002001
2002 def test_non_blocking_connect_ex(self):
2003 # Issue #11326: non-blocking connect_ex() should allow handshake
2004 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02002005 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002006 cert_reqs=ssl.CERT_REQUIRED,
2007 ca_certs=SIGNING_CA,
2008 do_handshake_on_connect=False)
2009 self.addCleanup(s.close)
2010 s.setblocking(False)
2011 rc = s.connect_ex(self.server_addr)
2012 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2013 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2014 # Wait for connect to finish
2015 select.select([], [s], [], 5.0)
2016 # Non-blocking handshake
2017 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002018 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002019 s.do_handshake()
2020 break
2021 except ssl.SSLWantReadError:
2022 select.select([s], [], [], 5.0)
2023 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002024 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002025 # SSL established
2026 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002027
Antoine Pitrou152efa22010-05-16 18:19:27 +00002028 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002029 # Same as test_connect, but with a separately created context
Christian Heimes2875c602021-04-19 07:27:10 +02002030 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2031 ctx.check_hostname = False
2032 ctx.verify_mode = ssl.CERT_NONE
Martin Panter3840b2a2016-03-27 01:53:46 +00002033 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2034 s.connect(self.server_addr)
2035 self.assertEqual({}, s.getpeercert())
2036 # Same with a server hostname
2037 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2038 server_hostname="dummy") as s:
2039 s.connect(self.server_addr)
2040 ctx.verify_mode = ssl.CERT_REQUIRED
2041 # This should succeed because we specify the root cert
2042 ctx.load_verify_locations(SIGNING_CA)
2043 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2044 s.connect(self.server_addr)
2045 cert = s.getpeercert()
2046 self.assertTrue(cert)
2047
2048 def test_connect_with_context_fail(self):
2049 # This should fail because we have no verification certs. Connection
2050 # failure crashes ThreadedEchoServer, so run this in an independent
2051 # test method.
Christian Heimes2875c602021-04-19 07:27:10 +02002052 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2053 s = ctx.wrap_socket(
2054 socket.socket(socket.AF_INET),
2055 server_hostname=SIGNED_CERTFILE_HOSTNAME
2056 )
Martin Panter3840b2a2016-03-27 01:53:46 +00002057 self.addCleanup(s.close)
2058 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2059 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002060
2061 def test_connect_capath(self):
2062 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002063 # NOTE: the subject hashing algorithm has been changed between
2064 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2065 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002066 # filename) for this test to be portable across OpenSSL releases.
Christian Heimes2875c602021-04-19 07:27:10 +02002067 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002068 ctx.load_verify_locations(capath=CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002069 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2070 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002071 s.connect(self.server_addr)
2072 cert = s.getpeercert()
2073 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002074
Martin Panter3840b2a2016-03-27 01:53:46 +00002075 # Same with a bytes `capath` argument
Christian Heimes2875c602021-04-19 07:27:10 +02002076 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002077 ctx.load_verify_locations(capath=BYTES_CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002078 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2079 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002080 s.connect(self.server_addr)
2081 cert = s.getpeercert()
2082 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002083
Christian Heimesefff7062013-11-21 03:35:02 +01002084 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002085 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002086 pem = f.read()
2087 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002088 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002089 ctx.load_verify_locations(cadata=pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002090 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2091 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002092 s.connect(self.server_addr)
2093 cert = s.getpeercert()
2094 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002095
Martin Panter3840b2a2016-03-27 01:53:46 +00002096 # same with DER
Christian Heimes2875c602021-04-19 07:27:10 +02002097 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002098 ctx.load_verify_locations(cadata=der)
Christian Heimes2875c602021-04-19 07:27:10 +02002099 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2100 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002101 s.connect(self.server_addr)
2102 cert = s.getpeercert()
2103 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002104
Antoine Pitroue3220242010-04-24 11:13:53 +00002105 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2106 def test_makefile_close(self):
2107 # Issue #5238: creating a file-like object with makefile() shouldn't
2108 # delay closing the underlying "real socket" (here tested with its
2109 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002110 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002111 ss.connect(self.server_addr)
2112 fd = ss.fileno()
2113 f = ss.makefile()
2114 f.close()
2115 # The fd is still open
2116 os.read(fd, 0)
2117 # Closing the SSL socket should close the fd too
2118 ss.close()
2119 gc.collect()
2120 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002121 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002122 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002123
Antoine Pitrou480a1242010-04-28 21:37:09 +00002124 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002125 s = socket.socket(socket.AF_INET)
2126 s.connect(self.server_addr)
2127 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002128 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002129 cert_reqs=ssl.CERT_NONE,
2130 do_handshake_on_connect=False)
2131 self.addCleanup(s.close)
2132 count = 0
2133 while True:
2134 try:
2135 count += 1
2136 s.do_handshake()
2137 break
2138 except ssl.SSLWantReadError:
2139 select.select([s], [], [])
2140 except ssl.SSLWantWriteError:
2141 select.select([], [s], [])
2142 if support.verbose:
2143 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002144
Antoine Pitrou480a1242010-04-28 21:37:09 +00002145 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002146 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002147
juhovh49fdf112021-04-18 21:11:48 +10002148 @needs_sni
2149 def test_get_server_certificate_sni(self):
2150 host, port = self.server_addr
2151 server_names = []
2152
2153 # We store servername_cb arguments to make sure they match the host
2154 def servername_cb(ssl_sock, server_name, initial_context):
2155 server_names.append(server_name)
2156 self.server_context.set_servername_callback(servername_cb)
2157
2158 pem = ssl.get_server_certificate((host, port))
2159 if not pem:
2160 self.fail("No server certificate on %s:%s!" % (host, port))
2161
2162 pem = ssl.get_server_certificate((host, port), ca_certs=SIGNING_CA)
2163 if not pem:
2164 self.fail("No server certificate on %s:%s!" % (host, port))
2165 if support.verbose:
2166 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port, pem))
2167
2168 self.assertEqual(server_names, [host, host])
2169
Martin Panter3840b2a2016-03-27 01:53:46 +00002170 def test_get_server_certificate_fail(self):
2171 # Connection failure crashes ThreadedEchoServer, so run this in an
2172 # independent test method
2173 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002174
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002175 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002176 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002177 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2178 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002179 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002180 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2181 s.connect(self.server_addr)
2182 # Error checking can happen at instantiation or when connecting
2183 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2184 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002185 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002186 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2187 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002188
Christian Heimes9a5395a2013-06-17 15:44:12 +02002189 def test_get_ca_certs_capath(self):
2190 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002191 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002192 ctx.load_verify_locations(capath=CAPATH)
2193 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002194 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2195 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002196 s.connect(self.server_addr)
2197 cert = s.getpeercert()
2198 self.assertTrue(cert)
2199 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002200
Christian Heimes575596e2013-12-15 21:49:17 +01002201 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01002202 def test_context_setget(self):
2203 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002204 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2205 ctx1.load_verify_locations(capath=CAPATH)
2206 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2207 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002208 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002209 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002210 ss.connect(self.server_addr)
2211 self.assertIs(ss.context, ctx1)
2212 self.assertIs(ss._sslobj.context, ctx1)
2213 ss.context = ctx2
2214 self.assertIs(ss.context, ctx2)
2215 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002216
2217 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2218 # A simple IO loop. Call func(*args) depending on the error we get
2219 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002220 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002221 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002222 count = 0
2223 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002224 if time.monotonic() > deadline:
2225 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002226 errno = None
2227 count += 1
2228 try:
2229 ret = func(*args)
2230 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002231 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002232 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002233 raise
2234 errno = e.errno
2235 # Get any data from the outgoing BIO irrespective of any error, and
2236 # send it to the socket.
2237 buf = outgoing.read()
2238 sock.sendall(buf)
2239 # If there's no error, we're done. For WANT_READ, we need to get
2240 # data from the socket and put it in the incoming BIO.
2241 if errno is None:
2242 break
2243 elif errno == ssl.SSL_ERROR_WANT_READ:
2244 buf = sock.recv(32768)
2245 if buf:
2246 incoming.write(buf)
2247 else:
2248 incoming.write_eof()
2249 if support.verbose:
2250 sys.stdout.write("Needed %d calls to complete %s().\n"
2251 % (count, func.__name__))
2252 return ret
2253
Martin Panter3840b2a2016-03-27 01:53:46 +00002254 def test_bio_handshake(self):
2255 sock = socket.socket(socket.AF_INET)
2256 self.addCleanup(sock.close)
2257 sock.connect(self.server_addr)
2258 incoming = ssl.MemoryBIO()
2259 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002260 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2261 self.assertTrue(ctx.check_hostname)
2262 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002263 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002264 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2265 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002266 self.assertIs(sslobj._sslobj.owner, sslobj)
2267 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002268 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002269 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002270 self.assertRaises(ValueError, sslobj.getpeercert)
2271 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2272 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2273 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2274 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002275 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002276 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002277 self.assertTrue(sslobj.getpeercert())
2278 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2279 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2280 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002281 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002282 except ssl.SSLSyscallError:
2283 # If the server shuts down the TCP connection without sending a
2284 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2285 pass
2286 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2287
2288 def test_bio_read_write_data(self):
2289 sock = socket.socket(socket.AF_INET)
2290 self.addCleanup(sock.close)
2291 sock.connect(self.server_addr)
2292 incoming = ssl.MemoryBIO()
2293 outgoing = ssl.MemoryBIO()
Christian Heimes2875c602021-04-19 07:27:10 +02002294 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2295 ctx.check_hostname = False
Martin Panter3840b2a2016-03-27 01:53:46 +00002296 ctx.verify_mode = ssl.CERT_NONE
2297 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2298 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2299 req = b'FOO\n'
2300 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2301 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2302 self.assertEqual(buf, b'foo\n')
2303 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002304
2305
Martin Panter3840b2a2016-03-27 01:53:46 +00002306class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002307
Martin Panter3840b2a2016-03-27 01:53:46 +00002308 def test_timeout_connect_ex(self):
2309 # Issue #12065: on a timeout, connect_ex() should return the original
2310 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002311 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002312 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002313 cert_reqs=ssl.CERT_REQUIRED,
2314 do_handshake_on_connect=False)
2315 self.addCleanup(s.close)
2316 s.settimeout(0.0000001)
2317 rc = s.connect_ex((REMOTE_HOST, 443))
2318 if rc == 0:
2319 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002320 elif rc == errno.ENETUNREACH:
2321 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002322 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2323
Serhiy Storchaka16994912020-04-25 10:06:29 +03002324 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002325 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002326 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002327 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2328 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2329
Martin Panter3840b2a2016-03-27 01:53:46 +00002330
2331def _test_get_server_certificate(test, host, port, cert=None):
2332 pem = ssl.get_server_certificate((host, port))
2333 if not pem:
2334 test.fail("No server certificate on %s:%s!" % (host, port))
2335
2336 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2337 if not pem:
2338 test.fail("No server certificate on %s:%s!" % (host, port))
2339 if support.verbose:
2340 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2341
2342def _test_get_server_certificate_fail(test, host, port):
2343 try:
2344 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2345 except ssl.SSLError as x:
2346 #should fail
2347 if support.verbose:
2348 sys.stdout.write("%s\n" % x)
2349 else:
2350 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2351
2352
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002353from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002354
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002355class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002356
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002357 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002358
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002359 """A mildly complicated class, because we want it to work both
2360 with and without the SSL wrapper around the socket connection, so
2361 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002362
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002363 def __init__(self, server, connsock, addr):
2364 self.server = server
2365 self.running = False
2366 self.sock = connsock
2367 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002368 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002369 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002370 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002371 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002372
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002373 def wrap_conn(self):
2374 try:
2375 self.sslconn = self.server.context.wrap_socket(
2376 self.sock, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002377 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002378 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002379 # We treat ConnectionResetError as though it were an
2380 # SSLError - OpenSSL on Ubuntu abruptly closes the
2381 # connection when asked to use an unsupported protocol.
2382 #
Christian Heimes529525f2018-05-23 22:24:45 +02002383 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2384 # tries to send session tickets after handshake.
2385 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002386 #
2387 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2388 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002389 self.server.conn_errors.append(str(e))
2390 if self.server.chatty:
2391 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2392 self.running = False
2393 self.close()
2394 return False
2395 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002396 # OSError may occur with wrong protocols, e.g. both
2397 # sides use PROTOCOL_TLS_SERVER.
2398 #
2399 # XXX Various errors can have happened here, for example
2400 # a mismatching protocol version, an invalid certificate,
2401 # or a low-level bug. This should be made more discriminating.
2402 #
2403 # bpo-31323: Store the exception as string to prevent
2404 # a reference leak: server -> conn_errors -> exception
2405 # -> traceback -> self (ConnectionHandler) -> server
2406 self.server.conn_errors.append(str(e))
2407 if self.server.chatty:
2408 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2409 self.running = False
2410 self.server.stop()
2411 self.close()
2412 return False
2413 else:
2414 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2415 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2416 cert = self.sslconn.getpeercert()
2417 if support.verbose and self.server.chatty:
2418 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2419 cert_binary = self.sslconn.getpeercert(True)
2420 if support.verbose and self.server.chatty:
2421 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2422 cipher = self.sslconn.cipher()
2423 if support.verbose and self.server.chatty:
2424 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002425 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002426
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002427 def read(self):
2428 if self.sslconn:
2429 return self.sslconn.read()
2430 else:
2431 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002432
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002433 def write(self, bytes):
2434 if self.sslconn:
2435 return self.sslconn.write(bytes)
2436 else:
2437 return self.sock.send(bytes)
2438
2439 def close(self):
2440 if self.sslconn:
2441 self.sslconn.close()
2442 else:
2443 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002444
Antoine Pitrou480a1242010-04-28 21:37:09 +00002445 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002446 self.running = True
2447 if not self.server.starttls_server:
2448 if not self.wrap_conn():
2449 return
2450 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002451 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002452 msg = self.read()
2453 stripped = msg.strip()
2454 if not stripped:
2455 # eof, so quit this handler
2456 self.running = False
2457 try:
2458 self.sock = self.sslconn.unwrap()
2459 except OSError:
2460 # Many tests shut the TCP connection down
2461 # without an SSL shutdown. This causes
2462 # unwrap() to raise OSError with errno=0!
2463 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002464 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002465 self.sslconn = None
2466 self.close()
2467 elif stripped == b'over':
2468 if support.verbose and self.server.connectionchatty:
2469 sys.stdout.write(" server: client closed connection\n")
2470 self.close()
2471 return
2472 elif (self.server.starttls_server and
2473 stripped == b'STARTTLS'):
2474 if support.verbose and self.server.connectionchatty:
2475 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2476 self.write(b"OK\n")
2477 if not self.wrap_conn():
2478 return
2479 elif (self.server.starttls_server and self.sslconn
2480 and stripped == b'ENDTLS'):
2481 if support.verbose and self.server.connectionchatty:
2482 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2483 self.write(b"OK\n")
2484 self.sock = self.sslconn.unwrap()
2485 self.sslconn = None
2486 if support.verbose and self.server.connectionchatty:
2487 sys.stdout.write(" server: connection is now unencrypted...\n")
2488 elif stripped == b'CB tls-unique':
2489 if support.verbose and self.server.connectionchatty:
2490 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2491 data = self.sslconn.get_channel_binding("tls-unique")
2492 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002493 elif stripped == b'PHA':
2494 if support.verbose and self.server.connectionchatty:
2495 sys.stdout.write(" server: initiating post handshake auth\n")
2496 try:
2497 self.sslconn.verify_client_post_handshake()
2498 except ssl.SSLError as e:
2499 self.write(repr(e).encode("us-ascii") + b"\n")
2500 else:
2501 self.write(b"OK\n")
2502 elif stripped == b'HASCERT':
2503 if self.sslconn.getpeercert() is not None:
2504 self.write(b'TRUE\n')
2505 else:
2506 self.write(b'FALSE\n')
2507 elif stripped == b'GETCERT':
2508 cert = self.sslconn.getpeercert()
2509 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002510 else:
2511 if (support.verbose and
2512 self.server.connectionchatty):
2513 ctype = (self.sslconn and "encrypted") or "unencrypted"
2514 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2515 % (msg, ctype, msg.lower(), ctype))
2516 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002517 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002518 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2519 # when connection is not shut down gracefully.
2520 if self.server.chatty and support.verbose:
2521 sys.stdout.write(
2522 " Connection reset by peer: {}\n".format(
2523 self.addr)
2524 )
2525 self.close()
2526 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002527 except ssl.SSLError as err:
2528 # On Windows sometimes test_pha_required_nocert receives the
2529 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2530 # before the 'tlsv13 alert certificate required' exception.
2531 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2532 # is received test_pha_required_nocert fails with ConnectionResetError
2533 # because the underlying socket is closed
2534 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2535 if self.server.chatty and support.verbose:
2536 sys.stdout.write(err.args[1])
2537 # test_pha_required_nocert is expecting this exception
2538 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002539 except OSError:
2540 if self.server.chatty:
2541 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002542 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002543 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002544
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002545 # normally, we'd just stop here, but for the test
2546 # harness, we want to stop the server
2547 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002548
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002549 def __init__(self, certificate=None, ssl_version=None,
2550 certreqs=None, cacerts=None,
2551 chatty=True, connectionchatty=False, starttls_server=False,
Christian Heimes2875c602021-04-19 07:27:10 +02002552 alpn_protocols=None,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002553 ciphers=None, context=None):
2554 if context:
2555 self.context = context
2556 else:
2557 self.context = ssl.SSLContext(ssl_version
2558 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002559 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002560 self.context.verify_mode = (certreqs if certreqs is not None
2561 else ssl.CERT_NONE)
2562 if cacerts:
2563 self.context.load_verify_locations(cacerts)
2564 if certificate:
2565 self.context.load_cert_chain(certificate)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002566 if alpn_protocols:
2567 self.context.set_alpn_protocols(alpn_protocols)
2568 if ciphers:
2569 self.context.set_ciphers(ciphers)
2570 self.chatty = chatty
2571 self.connectionchatty = connectionchatty
2572 self.starttls_server = starttls_server
2573 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002574 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002575 self.flag = None
2576 self.active = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002577 self.selected_alpn_protocols = []
2578 self.shared_ciphers = []
2579 self.conn_errors = []
2580 threading.Thread.__init__(self)
2581 self.daemon = True
2582
2583 def __enter__(self):
2584 self.start(threading.Event())
2585 self.flag.wait()
2586 return self
2587
2588 def __exit__(self, *args):
2589 self.stop()
2590 self.join()
2591
2592 def start(self, flag=None):
2593 self.flag = flag
2594 threading.Thread.start(self)
2595
2596 def run(self):
2597 self.sock.settimeout(0.05)
2598 self.sock.listen()
2599 self.active = True
2600 if self.flag:
2601 # signal an event
2602 self.flag.set()
2603 while self.active:
2604 try:
2605 newconn, connaddr = self.sock.accept()
2606 if support.verbose and self.chatty:
2607 sys.stdout.write(' server: new connection from '
2608 + repr(connaddr) + '\n')
2609 handler = self.ConnectionHandler(self, newconn, connaddr)
2610 handler.start()
2611 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002612 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002613 pass
2614 except KeyboardInterrupt:
2615 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002616 except BaseException as e:
2617 if support.verbose and self.chatty:
2618 sys.stdout.write(
2619 ' connection handling failed: ' + repr(e) + '\n')
2620
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002621 self.sock.close()
2622
2623 def stop(self):
2624 self.active = False
2625
2626class AsyncoreEchoServer(threading.Thread):
2627
2628 # this one's based on asyncore.dispatcher
2629
2630 class EchoServer (asyncore.dispatcher):
2631
2632 class ConnectionHandler(asyncore.dispatcher_with_send):
2633
2634 def __init__(self, conn, certfile):
2635 self.socket = test_wrap_socket(conn, server_side=True,
2636 certfile=certfile,
2637 do_handshake_on_connect=False)
2638 asyncore.dispatcher_with_send.__init__(self, self.socket)
2639 self._ssl_accepting = True
2640 self._do_ssl_handshake()
2641
2642 def readable(self):
2643 if isinstance(self.socket, ssl.SSLSocket):
2644 while self.socket.pending() > 0:
2645 self.handle_read_event()
2646 return True
2647
2648 def _do_ssl_handshake(self):
2649 try:
2650 self.socket.do_handshake()
2651 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2652 return
2653 except ssl.SSLEOFError:
2654 return self.handle_close()
2655 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002656 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002657 except OSError as err:
2658 if err.args[0] == errno.ECONNABORTED:
2659 return self.handle_close()
2660 else:
2661 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002662
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002663 def handle_read(self):
2664 if self._ssl_accepting:
2665 self._do_ssl_handshake()
2666 else:
2667 data = self.recv(1024)
2668 if support.verbose:
2669 sys.stdout.write(" server: read %s from client\n" % repr(data))
2670 if not data:
2671 self.close()
2672 else:
2673 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002674
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002675 def handle_close(self):
2676 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002677 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002678 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002679
2680 def handle_error(self):
2681 raise
2682
Trent Nelson78520002008-04-10 20:54:35 +00002683 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002684 self.certfile = certfile
2685 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002686 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002687 asyncore.dispatcher.__init__(self, sock)
2688 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002689
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002690 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002691 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002692 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2693 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002694
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002695 def handle_error(self):
2696 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002697
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002698 def __init__(self, certfile):
2699 self.flag = None
2700 self.active = False
2701 self.server = self.EchoServer(certfile)
2702 self.port = self.server.port
2703 threading.Thread.__init__(self)
2704 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002705
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002706 def __str__(self):
2707 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002708
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002709 def __enter__(self):
2710 self.start(threading.Event())
2711 self.flag.wait()
2712 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002713
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002714 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002715 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002716 sys.stdout.write(" cleanup: stopping server.\n")
2717 self.stop()
2718 if support.verbose:
2719 sys.stdout.write(" cleanup: joining server thread.\n")
2720 self.join()
2721 if support.verbose:
2722 sys.stdout.write(" cleanup: successfully joined.\n")
2723 # make sure that ConnectionHandler is removed from socket_map
2724 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002725
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002726 def start (self, flag=None):
2727 self.flag = flag
2728 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002729
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002730 def run(self):
2731 self.active = True
2732 if self.flag:
2733 self.flag.set()
2734 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002735 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002736 asyncore.loop(1)
2737 except:
2738 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002739
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002740 def stop(self):
2741 self.active = False
2742 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002743
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002744def server_params_test(client_context, server_context, indata=b"FOO\n",
2745 chatty=True, connectionchatty=False, sni_name=None,
2746 session=None):
2747 """
2748 Launch a server, connect a client to it and try various reads
2749 and writes.
2750 """
2751 stats = {}
2752 server = ThreadedEchoServer(context=server_context,
2753 chatty=chatty,
2754 connectionchatty=False)
2755 with server:
2756 with client_context.wrap_socket(socket.socket(),
2757 server_hostname=sni_name, session=session) as s:
2758 s.connect((HOST, server.port))
2759 for arg in [indata, bytearray(indata), memoryview(indata)]:
2760 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002761 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002762 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002763 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002764 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002765 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002766 if connectionchatty:
2767 if support.verbose:
2768 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002769 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002770 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002771 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2772 % (outdata[:20], len(outdata),
2773 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002774 s.write(b"over\n")
2775 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002776 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002777 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002778 stats.update({
2779 'compression': s.compression(),
2780 'cipher': s.cipher(),
2781 'peercert': s.getpeercert(),
2782 'client_alpn_protocol': s.selected_alpn_protocol(),
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002783 'version': s.version(),
2784 'session_reused': s.session_reused,
2785 'session': s.session,
2786 })
2787 s.close()
2788 stats['server_alpn_protocols'] = server.selected_alpn_protocols
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002789 stats['server_shared_ciphers'] = server.shared_ciphers
2790 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002791
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002792def try_protocol_combo(server_protocol, client_protocol, expect_success,
2793 certsreqs=None, server_options=0, client_options=0):
2794 """
2795 Try to SSL-connect using *client_protocol* to *server_protocol*.
2796 If *expect_success* is true, assert that the connection succeeds,
2797 if it's false, assert that the connection fails.
2798 Also, if *expect_success* is a string, assert that it is the protocol
2799 version actually used by the connection.
2800 """
2801 if certsreqs is None:
2802 certsreqs = ssl.CERT_NONE
2803 certtype = {
2804 ssl.CERT_NONE: "CERT_NONE",
2805 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2806 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2807 }[certsreqs]
2808 if support.verbose:
2809 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2810 sys.stdout.write(formatstr %
2811 (ssl.get_protocol_name(client_protocol),
2812 ssl.get_protocol_name(server_protocol),
2813 certtype))
Christian Heimes2875c602021-04-19 07:27:10 +02002814
2815 with warnings_helper.check_warnings():
2816 # ignore Deprecation warnings
2817 client_context = ssl.SSLContext(client_protocol)
2818 client_context.options |= client_options
2819 server_context = ssl.SSLContext(server_protocol)
2820 server_context.options |= server_options
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002821
Victor Stinner3ef63442019-02-19 18:06:03 +01002822 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2823 if (min_version is not None
Christian Heimes2875c602021-04-19 07:27:10 +02002824 # SSLContext.minimum_version is only available on recent OpenSSL
2825 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2826 and hasattr(server_context, 'minimum_version')
2827 and server_protocol == ssl.PROTOCOL_TLS
2828 and server_context.minimum_version > min_version
2829 ):
Victor Stinner3ef63442019-02-19 18:06:03 +01002830 # If OpenSSL configuration is strict and requires more recent TLS
2831 # version, we have to change the minimum to test old TLS versions.
Christian Heimes2875c602021-04-19 07:27:10 +02002832 with warnings_helper.check_warnings():
2833 server_context.minimum_version = min_version
Victor Stinner3ef63442019-02-19 18:06:03 +01002834
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002835 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2836 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2837 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002838 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002839 client_context.set_ciphers("ALL")
2840
Christian Heimesf6c6b582021-03-18 23:06:50 +01002841 seclevel_workaround(server_context, client_context)
2842
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002843 for ctx in (client_context, server_context):
2844 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002845 ctx.load_cert_chain(SIGNED_CERTFILE)
2846 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002847 try:
2848 stats = server_params_test(client_context, server_context,
2849 chatty=False, connectionchatty=False)
2850 # Protocol mismatch can result in either an SSLError, or a
2851 # "Connection reset by peer" error.
2852 except ssl.SSLError:
2853 if expect_success:
2854 raise
2855 except OSError as e:
2856 if expect_success or e.errno != errno.ECONNRESET:
2857 raise
2858 else:
2859 if not expect_success:
2860 raise AssertionError(
2861 "Client protocol %s succeeded with server protocol %s!"
2862 % (ssl.get_protocol_name(client_protocol),
2863 ssl.get_protocol_name(server_protocol)))
2864 elif (expect_success is not True
2865 and expect_success != stats['version']):
2866 raise AssertionError("version mismatch: expected %r, got %r"
2867 % (expect_success, stats['version']))
2868
2869
2870class ThreadedTests(unittest.TestCase):
2871
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002872 def test_echo(self):
2873 """Basic test of an SSL client connecting to a server"""
2874 if support.verbose:
2875 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002876
Christian Heimesa170fa12017-09-15 20:27:30 +02002877 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002878
2879 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2880 server_params_test(client_context=client_context,
2881 server_context=server_context,
2882 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002883 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002884
2885 client_context.check_hostname = False
2886 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2887 with self.assertRaises(ssl.SSLError) as e:
2888 server_params_test(client_context=server_context,
2889 server_context=client_context,
2890 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002891 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002892 self.assertIn('called a function you should not call',
2893 str(e.exception))
2894
2895 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2896 with self.assertRaises(ssl.SSLError) as e:
2897 server_params_test(client_context=server_context,
2898 server_context=server_context,
2899 chatty=True, connectionchatty=True)
2900 self.assertIn('called a function you should not call',
2901 str(e.exception))
2902
2903 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2904 with self.assertRaises(ssl.SSLError) as e:
2905 server_params_test(client_context=server_context,
2906 server_context=client_context,
2907 chatty=True, connectionchatty=True)
2908 self.assertIn('called a function you should not call',
2909 str(e.exception))
2910
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002911 def test_getpeercert(self):
2912 if support.verbose:
2913 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002914
2915 client_context, server_context, hostname = testing_context()
2916 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002917 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002918 with client_context.wrap_socket(socket.socket(),
2919 do_handshake_on_connect=False,
2920 server_hostname=hostname) as s:
2921 s.connect((HOST, server.port))
2922 # getpeercert() raise ValueError while the handshake isn't
2923 # done.
2924 with self.assertRaises(ValueError):
2925 s.getpeercert()
2926 s.do_handshake()
2927 cert = s.getpeercert()
2928 self.assertTrue(cert, "Can't get peer certificate.")
2929 cipher = s.cipher()
2930 if support.verbose:
2931 sys.stdout.write(pprint.pformat(cert) + '\n')
2932 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2933 if 'subject' not in cert:
2934 self.fail("No subject field in certificate: %s." %
2935 pprint.pformat(cert))
2936 if ((('organizationName', 'Python Software Foundation'),)
2937 not in cert['subject']):
2938 self.fail(
2939 "Missing or invalid 'organizationName' field in certificate subject; "
2940 "should be 'Python Software Foundation'.")
2941 self.assertIn('notBefore', cert)
2942 self.assertIn('notAfter', cert)
2943 before = ssl.cert_time_to_seconds(cert['notBefore'])
2944 after = ssl.cert_time_to_seconds(cert['notAfter'])
2945 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002946
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002947 def test_crl_check(self):
2948 if support.verbose:
2949 sys.stdout.write("\n")
2950
Christian Heimesa170fa12017-09-15 20:27:30 +02002951 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002952
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002953 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002954 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002955
2956 # VERIFY_DEFAULT should pass
2957 server = ThreadedEchoServer(context=server_context, chatty=True)
2958 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002959 with client_context.wrap_socket(socket.socket(),
2960 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002961 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002962 cert = s.getpeercert()
2963 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002964
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002965 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002966 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002967
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002968 server = ThreadedEchoServer(context=server_context, chatty=True)
2969 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002970 with client_context.wrap_socket(socket.socket(),
2971 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002972 with self.assertRaisesRegex(ssl.SSLError,
2973 "certificate verify failed"):
2974 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002975
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002976 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002977 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002978
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002979 server = ThreadedEchoServer(context=server_context, chatty=True)
2980 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002981 with client_context.wrap_socket(socket.socket(),
2982 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002983 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002984 cert = s.getpeercert()
2985 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002986
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002987 def test_check_hostname(self):
2988 if support.verbose:
2989 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002990
Christian Heimesa170fa12017-09-15 20:27:30 +02002991 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002992
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002993 # correct hostname should verify
2994 server = ThreadedEchoServer(context=server_context, chatty=True)
2995 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002996 with client_context.wrap_socket(socket.socket(),
2997 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002998 s.connect((HOST, server.port))
2999 cert = s.getpeercert()
3000 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003001
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003002 # incorrect hostname should raise an exception
3003 server = ThreadedEchoServer(context=server_context, chatty=True)
3004 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003005 with client_context.wrap_socket(socket.socket(),
3006 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01003007 with self.assertRaisesRegex(
3008 ssl.CertificateError,
3009 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003010 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003011
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003012 # missing server_hostname arg should cause an exception, too
3013 server = ThreadedEchoServer(context=server_context, chatty=True)
3014 with server:
3015 with socket.socket() as s:
3016 with self.assertRaisesRegex(ValueError,
3017 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02003018 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003019
Christian Heimesb467d9a2021-04-17 10:07:19 +02003020 @unittest.skipUnless(
3021 ssl.HAS_NEVER_CHECK_COMMON_NAME, "test requires hostname_checks_common_name"
3022 )
3023 def test_hostname_checks_common_name(self):
3024 client_context, server_context, hostname = testing_context()
3025 assert client_context.hostname_checks_common_name
3026 client_context.hostname_checks_common_name = False
3027
3028 # default cert has a SAN
3029 server = ThreadedEchoServer(context=server_context, chatty=True)
3030 with server:
3031 with client_context.wrap_socket(socket.socket(),
3032 server_hostname=hostname) as s:
3033 s.connect((HOST, server.port))
3034
3035 client_context, server_context, hostname = testing_context(NOSANFILE)
3036 client_context.hostname_checks_common_name = False
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 with self.assertRaises(ssl.SSLCertVerificationError):
3042 s.connect((HOST, server.port))
3043
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003044 def test_ecc_cert(self):
3045 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3046 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003047 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003048 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3049
3050 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3051 # load ECC cert
3052 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3053
3054 # correct hostname should verify
3055 server = ThreadedEchoServer(context=server_context, chatty=True)
3056 with server:
3057 with client_context.wrap_socket(socket.socket(),
3058 server_hostname=hostname) as s:
3059 s.connect((HOST, server.port))
3060 cert = s.getpeercert()
3061 self.assertTrue(cert, "Can't get peer certificate.")
3062 cipher = s.cipher()[0].split('-')
3063 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3064
3065 def test_dual_rsa_ecc(self):
3066 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3067 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003068 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3069 # algorithms.
3070 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003071 # only ECDSA certs
3072 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3073 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3074
3075 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3076 # load ECC and RSA key/cert pairs
3077 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3078 server_context.load_cert_chain(SIGNED_CERTFILE)
3079
3080 # correct hostname should verify
3081 server = ThreadedEchoServer(context=server_context, chatty=True)
3082 with server:
3083 with client_context.wrap_socket(socket.socket(),
3084 server_hostname=hostname) as s:
3085 s.connect((HOST, server.port))
3086 cert = s.getpeercert()
3087 self.assertTrue(cert, "Can't get peer certificate.")
3088 cipher = s.cipher()[0].split('-')
3089 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3090
Christian Heimes66e57422018-01-29 14:25:13 +01003091 def test_check_hostname_idn(self):
3092 if support.verbose:
3093 sys.stdout.write("\n")
3094
Christian Heimes11a14932018-02-24 02:35:08 +01003095 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003096 server_context.load_cert_chain(IDNSANSFILE)
3097
Christian Heimes11a14932018-02-24 02:35:08 +01003098 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003099 context.verify_mode = ssl.CERT_REQUIRED
3100 context.check_hostname = True
3101 context.load_verify_locations(SIGNING_CA)
3102
3103 # correct hostname should verify, when specified in several
3104 # different ways
3105 idn_hostnames = [
3106 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003107 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003108 ('xn--knig-5qa.idn.pythontest.net',
3109 'xn--knig-5qa.idn.pythontest.net'),
3110 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003111 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003112
3113 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003114 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003115 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3116 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3117 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003118 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3119
3120 # ('königsgäßchen.idna2008.pythontest.net',
3121 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3122 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3123 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3124 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3125 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3126
Christian Heimes66e57422018-01-29 14:25:13 +01003127 ]
3128 for server_hostname, expected_hostname in idn_hostnames:
3129 server = ThreadedEchoServer(context=server_context, chatty=True)
3130 with server:
3131 with context.wrap_socket(socket.socket(),
3132 server_hostname=server_hostname) as s:
3133 self.assertEqual(s.server_hostname, expected_hostname)
3134 s.connect((HOST, server.port))
3135 cert = s.getpeercert()
3136 self.assertEqual(s.server_hostname, expected_hostname)
3137 self.assertTrue(cert, "Can't get peer certificate.")
3138
Christian Heimes66e57422018-01-29 14:25:13 +01003139 # incorrect hostname should raise an exception
3140 server = ThreadedEchoServer(context=server_context, chatty=True)
3141 with server:
3142 with context.wrap_socket(socket.socket(),
3143 server_hostname="python.example.org") as s:
3144 with self.assertRaises(ssl.CertificateError):
3145 s.connect((HOST, server.port))
3146
Christian Heimes529525f2018-05-23 22:24:45 +02003147 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003148 """Connecting when the server rejects the client's certificate
3149
3150 Launch a server with CERT_REQUIRED, and check that trying to
3151 connect to it with a wrong client certificate fails.
3152 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003153 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003154 # load client cert that is not signed by trusted CA
3155 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003156 # require TLS client authentication
3157 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003158 # TLS 1.3 has different handshake
3159 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003160
3161 server = ThreadedEchoServer(
3162 context=server_context, chatty=True, connectionchatty=True,
3163 )
3164
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003165 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003166 client_context.wrap_socket(socket.socket(),
3167 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003168 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003169 # Expect either an SSL error about the server rejecting
3170 # the connection, or a low-level connection reset (which
3171 # sometimes happens on Windows)
3172 s.connect((HOST, server.port))
3173 except ssl.SSLError as e:
3174 if support.verbose:
3175 sys.stdout.write("\nSSLError is %r\n" % e)
3176 except OSError as e:
3177 if e.errno != errno.ECONNRESET:
3178 raise
3179 if support.verbose:
3180 sys.stdout.write("\nsocket.error is %r\n" % e)
3181 else:
3182 self.fail("Use of invalid cert should have failed!")
3183
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003184 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003185 def test_wrong_cert_tls13(self):
3186 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003187 # load client cert that is not signed by trusted CA
3188 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003189 server_context.verify_mode = ssl.CERT_REQUIRED
3190 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3191 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3192
3193 server = ThreadedEchoServer(
3194 context=server_context, chatty=True, connectionchatty=True,
3195 )
3196 with server, \
3197 client_context.wrap_socket(socket.socket(),
3198 server_hostname=hostname) as s:
3199 # TLS 1.3 perform client cert exchange after handshake
3200 s.connect((HOST, server.port))
3201 try:
3202 s.write(b'data')
3203 s.read(4)
3204 except ssl.SSLError as e:
3205 if support.verbose:
3206 sys.stdout.write("\nSSLError is %r\n" % e)
3207 except OSError as e:
3208 if e.errno != errno.ECONNRESET:
3209 raise
3210 if support.verbose:
3211 sys.stdout.write("\nsocket.error is %r\n" % e)
3212 else:
3213 self.fail("Use of invalid cert should have failed!")
3214
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003215 def test_rude_shutdown(self):
3216 """A brutal shutdown of an SSL server should raise an OSError
3217 in the client when attempting handshake.
3218 """
3219 listener_ready = threading.Event()
3220 listener_gone = threading.Event()
3221
3222 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003223 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003224
3225 # `listener` runs in a thread. It sits in an accept() until
3226 # the main thread connects. Then it rudely closes the socket,
3227 # and sets Event `listener_gone` to let the main thread know
3228 # the socket is gone.
3229 def listener():
3230 s.listen()
3231 listener_ready.set()
3232 newsock, addr = s.accept()
3233 newsock.close()
3234 s.close()
3235 listener_gone.set()
3236
3237 def connector():
3238 listener_ready.wait()
3239 with socket.socket() as c:
3240 c.connect((HOST, port))
3241 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003242 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003243 ssl_sock = test_wrap_socket(c)
3244 except OSError:
3245 pass
3246 else:
3247 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003248
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003249 t = threading.Thread(target=listener)
3250 t.start()
3251 try:
3252 connector()
3253 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003254 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003255
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003256 def test_ssl_cert_verify_error(self):
3257 if support.verbose:
3258 sys.stdout.write("\n")
3259
3260 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3261 server_context.load_cert_chain(SIGNED_CERTFILE)
3262
3263 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3264
3265 server = ThreadedEchoServer(context=server_context, chatty=True)
3266 with server:
3267 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003268 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003269 try:
3270 s.connect((HOST, server.port))
3271 except ssl.SSLError as e:
3272 msg = 'unable to get local issuer certificate'
3273 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3274 self.assertEqual(e.verify_code, 20)
3275 self.assertEqual(e.verify_message, msg)
3276 self.assertIn(msg, repr(e))
3277 self.assertIn('certificate verify failed', repr(e))
3278
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003279 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003280 def test_protocol_sslv2(self):
3281 """Connecting to an SSLv2 server with various client options"""
3282 if support.verbose:
3283 sys.stdout.write("\n")
3284 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3285 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3286 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003287 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003288 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003289 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3290 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3291 # SSLv23 client with specific SSL options
3292 if no_sslv2_implies_sslv3_hello():
3293 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003294 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003295 client_options=ssl.OP_NO_SSLv2)
Christian Heimesa170fa12017-09-15 20:27:30 +02003296 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003297 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003298 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003299 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003300
Christian Heimesa170fa12017-09-15 20:27:30 +02003301 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003302 """Connecting to an SSLv23 server with various client options"""
3303 if support.verbose:
3304 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003305 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003306 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003307 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003308 except OSError as x:
3309 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3310 if support.verbose:
3311 sys.stdout.write(
3312 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3313 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003314 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003315 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3316 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003317 if has_tls_version('TLSv1'):
3318 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003319
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003320 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003321 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3322 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003323 if has_tls_version('TLSv1'):
3324 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003325
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003326 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003327 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3328 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003329 if has_tls_version('TLSv1'):
3330 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003331
3332 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003333 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003334 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003335 server_options=ssl.OP_NO_SSLv3)
3336 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003337 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003338 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003339 if has_tls_version('TLSv1'):
3340 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3341 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003342
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003343 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003344 def test_protocol_sslv3(self):
3345 """Connecting to an SSLv3 server with various client options"""
3346 if support.verbose:
3347 sys.stdout.write("\n")
3348 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3349 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3350 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003351 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003352 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003353 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003354 client_options=ssl.OP_NO_SSLv3)
3355 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3356 if no_sslv2_implies_sslv3_hello():
3357 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003358 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003359 False, client_options=ssl.OP_NO_SSLv2)
3360
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003361 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003362 def test_protocol_tlsv1(self):
3363 """Connecting to a TLSv1 server with various client options"""
3364 if support.verbose:
3365 sys.stdout.write("\n")
3366 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3367 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3368 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003369 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003370 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003371 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003372 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003373 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003374 client_options=ssl.OP_NO_TLSv1)
3375
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003376 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003377 def test_protocol_tlsv1_1(self):
3378 """Connecting to a TLSv1.1 server with various client options.
3379 Testing against older TLS versions."""
3380 if support.verbose:
3381 sys.stdout.write("\n")
3382 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003383 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003384 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003385 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003386 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003387 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003388 client_options=ssl.OP_NO_TLSv1_1)
3389
Christian Heimesa170fa12017-09-15 20:27:30 +02003390 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003391 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3392 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003393
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003394 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003395 def test_protocol_tlsv1_2(self):
3396 """Connecting to a TLSv1.2 server with various client options.
3397 Testing against older TLS versions."""
3398 if support.verbose:
3399 sys.stdout.write("\n")
3400 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3401 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3402 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003403 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003404 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003405 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003406 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003407 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003408 client_options=ssl.OP_NO_TLSv1_2)
3409
Christian Heimesa170fa12017-09-15 20:27:30 +02003410 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003411 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3412 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3413 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3414 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3415
3416 def test_starttls(self):
3417 """Switching from clear text to encrypted and back again."""
3418 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3419
3420 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003421 starttls_server=True,
3422 chatty=True,
3423 connectionchatty=True)
3424 wrapped = False
3425 with server:
3426 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003427 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003428 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003429 if support.verbose:
3430 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003431 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003432 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003433 sys.stdout.write(
3434 " client: sending %r...\n" % indata)
3435 if wrapped:
3436 conn.write(indata)
3437 outdata = conn.read()
3438 else:
3439 s.send(indata)
3440 outdata = s.recv(1024)
3441 msg = outdata.strip().lower()
3442 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3443 # STARTTLS ok, switch to secure mode
3444 if support.verbose:
3445 sys.stdout.write(
3446 " client: read %r from server, starting TLS...\n"
3447 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003448 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003449 wrapped = True
3450 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3451 # ENDTLS ok, switch back to clear text
3452 if support.verbose:
3453 sys.stdout.write(
3454 " client: read %r from server, ending TLS...\n"
3455 % msg)
3456 s = conn.unwrap()
3457 wrapped = False
3458 else:
3459 if support.verbose:
3460 sys.stdout.write(
3461 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003462 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003463 sys.stdout.write(" client: closing connection.\n")
3464 if wrapped:
3465 conn.write(b"over\n")
3466 else:
3467 s.send(b"over\n")
3468 if wrapped:
3469 conn.close()
3470 else:
3471 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003472
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003473 def test_socketserver(self):
3474 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003475 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003476 # try to connect
3477 if support.verbose:
3478 sys.stdout.write('\n')
3479 with open(CERTFILE, 'rb') as f:
3480 d1 = f.read()
3481 d2 = ''
3482 # now fetch the same data from the HTTPS server
3483 url = 'https://localhost:%d/%s' % (
3484 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003485 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003486 f = urllib.request.urlopen(url, context=context)
3487 try:
3488 dlen = f.info().get("content-length")
3489 if dlen and (int(dlen) > 0):
3490 d2 = f.read(int(dlen))
3491 if support.verbose:
3492 sys.stdout.write(
3493 " client: read %d bytes from remote server '%s'\n"
3494 % (len(d2), server))
3495 finally:
3496 f.close()
3497 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003498
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003499 def test_asyncore_server(self):
3500 """Check the example asyncore integration."""
3501 if support.verbose:
3502 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003503
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003504 indata = b"FOO\n"
3505 server = AsyncoreEchoServer(CERTFILE)
3506 with server:
3507 s = test_wrap_socket(socket.socket())
3508 s.connect(('127.0.0.1', server.port))
3509 if support.verbose:
3510 sys.stdout.write(
3511 " client: sending %r...\n" % indata)
3512 s.write(indata)
3513 outdata = s.read()
3514 if support.verbose:
3515 sys.stdout.write(" client: read %r\n" % outdata)
3516 if outdata != indata.lower():
3517 self.fail(
3518 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3519 % (outdata[:20], len(outdata),
3520 indata[:20].lower(), len(indata)))
3521 s.write(b"over\n")
3522 if support.verbose:
3523 sys.stdout.write(" client: closing connection.\n")
3524 s.close()
3525 if support.verbose:
3526 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003527
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003528 def test_recv_send(self):
3529 """Test recv(), send() and friends."""
3530 if support.verbose:
3531 sys.stdout.write("\n")
3532
3533 server = ThreadedEchoServer(CERTFILE,
3534 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003535 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003536 cacerts=CERTFILE,
3537 chatty=True,
3538 connectionchatty=False)
3539 with server:
3540 s = test_wrap_socket(socket.socket(),
3541 server_side=False,
3542 certfile=CERTFILE,
3543 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003544 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003545 s.connect((HOST, server.port))
3546 # helper methods for standardising recv* method signatures
3547 def _recv_into():
3548 b = bytearray(b"\0"*100)
3549 count = s.recv_into(b)
3550 return b[:count]
3551
3552 def _recvfrom_into():
3553 b = bytearray(b"\0"*100)
3554 count, addr = s.recvfrom_into(b)
3555 return b[:count]
3556
3557 # (name, method, expect success?, *args, return value func)
3558 send_methods = [
3559 ('send', s.send, True, [], len),
3560 ('sendto', s.sendto, False, ["some.address"], len),
3561 ('sendall', s.sendall, True, [], lambda x: None),
3562 ]
3563 # (name, method, whether to expect success, *args)
3564 recv_methods = [
3565 ('recv', s.recv, True, []),
3566 ('recvfrom', s.recvfrom, False, ["some.address"]),
3567 ('recv_into', _recv_into, True, []),
3568 ('recvfrom_into', _recvfrom_into, False, []),
3569 ]
3570 data_prefix = "PREFIX_"
3571
3572 for (meth_name, send_meth, expect_success, args,
3573 ret_val_meth) in send_methods:
3574 indata = (data_prefix + meth_name).encode('ascii')
3575 try:
3576 ret = send_meth(indata, *args)
3577 msg = "sending with {}".format(meth_name)
3578 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3579 outdata = s.read()
3580 if outdata != indata.lower():
3581 self.fail(
3582 "While sending with <<{name:s}>> bad data "
3583 "<<{outdata:r}>> ({nout:d}) received; "
3584 "expected <<{indata:r}>> ({nin:d})\n".format(
3585 name=meth_name, outdata=outdata[:20],
3586 nout=len(outdata),
3587 indata=indata[:20], nin=len(indata)
3588 )
3589 )
3590 except ValueError as e:
3591 if expect_success:
3592 self.fail(
3593 "Failed to send with method <<{name:s}>>; "
3594 "expected to succeed.\n".format(name=meth_name)
3595 )
3596 if not str(e).startswith(meth_name):
3597 self.fail(
3598 "Method <<{name:s}>> failed with unexpected "
3599 "exception message: {exp:s}\n".format(
3600 name=meth_name, exp=e
3601 )
3602 )
3603
3604 for meth_name, recv_meth, expect_success, args in recv_methods:
3605 indata = (data_prefix + meth_name).encode('ascii')
3606 try:
3607 s.send(indata)
3608 outdata = recv_meth(*args)
3609 if outdata != indata.lower():
3610 self.fail(
3611 "While receiving with <<{name:s}>> bad data "
3612 "<<{outdata:r}>> ({nout:d}) received; "
3613 "expected <<{indata:r}>> ({nin:d})\n".format(
3614 name=meth_name, outdata=outdata[:20],
3615 nout=len(outdata),
3616 indata=indata[:20], nin=len(indata)
3617 )
3618 )
3619 except ValueError as e:
3620 if expect_success:
3621 self.fail(
3622 "Failed to receive with method <<{name:s}>>; "
3623 "expected to succeed.\n".format(name=meth_name)
3624 )
3625 if not str(e).startswith(meth_name):
3626 self.fail(
3627 "Method <<{name:s}>> failed with unexpected "
3628 "exception message: {exp:s}\n".format(
3629 name=meth_name, exp=e
3630 )
3631 )
3632 # consume data
3633 s.read()
3634
3635 # read(-1, buffer) is supported, even though read(-1) is not
3636 data = b"data"
3637 s.send(data)
3638 buffer = bytearray(len(data))
3639 self.assertEqual(s.read(-1, buffer), len(data))
3640 self.assertEqual(buffer, data)
3641
Christian Heimes888bbdc2017-09-07 14:18:21 -07003642 # sendall accepts bytes-like objects
3643 if ctypes is not None:
3644 ubyte = ctypes.c_ubyte * len(data)
3645 byteslike = ubyte.from_buffer_copy(data)
3646 s.sendall(byteslike)
3647 self.assertEqual(s.read(), data)
3648
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003649 # Make sure sendmsg et al are disallowed to avoid
3650 # inadvertent disclosure of data and/or corruption
3651 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003652 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003653 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3654 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3655 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003656 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003657 s.write(b"over\n")
3658
3659 self.assertRaises(ValueError, s.recv, -1)
3660 self.assertRaises(ValueError, s.read, -1)
3661
3662 s.close()
3663
3664 def test_recv_zero(self):
3665 server = ThreadedEchoServer(CERTFILE)
3666 server.__enter__()
3667 self.addCleanup(server.__exit__, None, None)
3668 s = socket.create_connection((HOST, server.port))
3669 self.addCleanup(s.close)
3670 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3671 self.addCleanup(s.close)
3672
3673 # recv/read(0) should return no data
3674 s.send(b"data")
3675 self.assertEqual(s.recv(0), b"")
3676 self.assertEqual(s.read(0), b"")
3677 self.assertEqual(s.read(), b"data")
3678
3679 # Should not block if the other end sends no data
3680 s.setblocking(False)
3681 self.assertEqual(s.recv(0), b"")
3682 self.assertEqual(s.recv_into(bytearray()), 0)
3683
3684 def test_nonblocking_send(self):
3685 server = ThreadedEchoServer(CERTFILE,
3686 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003687 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003688 cacerts=CERTFILE,
3689 chatty=True,
3690 connectionchatty=False)
3691 with server:
3692 s = test_wrap_socket(socket.socket(),
3693 server_side=False,
3694 certfile=CERTFILE,
3695 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003696 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003697 s.connect((HOST, server.port))
3698 s.setblocking(False)
3699
3700 # If we keep sending data, at some point the buffers
3701 # will be full and the call will block
3702 buf = bytearray(8192)
3703 def fill_buffer():
3704 while True:
3705 s.send(buf)
3706 self.assertRaises((ssl.SSLWantWriteError,
3707 ssl.SSLWantReadError), fill_buffer)
3708
3709 # Now read all the output and discard it
3710 s.setblocking(True)
3711 s.close()
3712
3713 def test_handshake_timeout(self):
3714 # Issue #5103: SSL handshake must respect the socket timeout
3715 server = socket.socket(socket.AF_INET)
3716 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003717 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003718 started = threading.Event()
3719 finish = False
3720
3721 def serve():
3722 server.listen()
3723 started.set()
3724 conns = []
3725 while not finish:
3726 r, w, e = select.select([server], [], [], 0.1)
3727 if server in r:
3728 # Let the socket hang around rather than having
3729 # it closed by garbage collection.
3730 conns.append(server.accept()[0])
3731 for sock in conns:
3732 sock.close()
3733
3734 t = threading.Thread(target=serve)
3735 t.start()
3736 started.wait()
3737
3738 try:
3739 try:
3740 c = socket.socket(socket.AF_INET)
3741 c.settimeout(0.2)
3742 c.connect((host, port))
3743 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003744 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003745 test_wrap_socket, c)
3746 finally:
3747 c.close()
3748 try:
3749 c = socket.socket(socket.AF_INET)
3750 c = test_wrap_socket(c)
3751 c.settimeout(0.2)
3752 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003753 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003754 c.connect, (host, port))
3755 finally:
3756 c.close()
3757 finally:
3758 finish = True
3759 t.join()
3760 server.close()
3761
3762 def test_server_accept(self):
3763 # Issue #16357: accept() on a SSLSocket created through
3764 # SSLContext.wrap_socket().
Christian Heimes2875c602021-04-19 07:27:10 +02003765 client_ctx, server_ctx, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003766 server = socket.socket(socket.AF_INET)
3767 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003768 port = socket_helper.bind_port(server)
Christian Heimes2875c602021-04-19 07:27:10 +02003769 server = server_ctx.wrap_socket(server, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003770 self.assertTrue(server.server_side)
3771
3772 evt = threading.Event()
3773 remote = None
3774 peer = None
3775 def serve():
3776 nonlocal remote, peer
3777 server.listen()
3778 # Block on the accept and wait on the connection to close.
3779 evt.set()
3780 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003781 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003782
3783 t = threading.Thread(target=serve)
3784 t.start()
3785 # Client wait until server setup and perform a connect.
3786 evt.wait()
Christian Heimes2875c602021-04-19 07:27:10 +02003787 client = client_ctx.wrap_socket(
3788 socket.socket(), server_hostname=hostname
3789 )
3790 client.connect((hostname, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003791 client.send(b'data')
3792 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003793 client_addr = client.getsockname()
3794 client.close()
3795 t.join()
3796 remote.close()
3797 server.close()
3798 # Sanity checks.
3799 self.assertIsInstance(remote, ssl.SSLSocket)
3800 self.assertEqual(peer, client_addr)
3801
3802 def test_getpeercert_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003803 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3804 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003805 with context.wrap_socket(socket.socket()) as sock:
3806 with self.assertRaises(OSError) as cm:
3807 sock.getpeercert()
3808 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3809
3810 def test_do_handshake_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003811 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3812 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003813 with context.wrap_socket(socket.socket()) as sock:
3814 with self.assertRaises(OSError) as cm:
3815 sock.do_handshake()
3816 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3817
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003818 def test_no_shared_ciphers(self):
3819 client_context, server_context, hostname = testing_context()
3820 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3821 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003822 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003823 client_context.set_ciphers("AES128")
3824 server_context.set_ciphers("AES256")
3825 with ThreadedEchoServer(context=server_context) as server:
3826 with client_context.wrap_socket(socket.socket(),
3827 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003828 with self.assertRaises(OSError):
3829 s.connect((HOST, server.port))
3830 self.assertIn("no shared cipher", server.conn_errors[0])
3831
3832 def test_version_basic(self):
3833 """
3834 Basic tests for SSLSocket.version().
3835 More tests are done in the test_protocol_*() methods.
3836 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003837 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3838 context.check_hostname = False
3839 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003840 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003841 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003842 chatty=False) as server:
3843 with context.wrap_socket(socket.socket()) as s:
3844 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003845 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003846 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003847 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003848 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003849 self.assertIs(s.version(), None)
3850
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003851 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003852 def test_tls1_3(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003853 client_context, server_context, hostname = testing_context()
3854 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3855 with ThreadedEchoServer(context=server_context) as server:
3856 with client_context.wrap_socket(socket.socket(),
3857 server_hostname=hostname) as s:
Christian Heimescb5b68a2017-09-07 18:07:00 -07003858 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003859 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003860 'TLS_AES_256_GCM_SHA384',
3861 'TLS_CHACHA20_POLY1305_SHA256',
3862 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003863 })
3864 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003865
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003866 @requires_minimum_version
3867 @requires_tls_version('TLSv1_2')
Christian Heimes2875c602021-04-19 07:27:10 +02003868 @requires_tls_version('TLSv1')
3869 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003870 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003871 client_context, server_context, hostname = testing_context()
3872 # client TLSv1.0 to 1.2
3873 client_context.minimum_version = ssl.TLSVersion.TLSv1
3874 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3875 # server only TLSv1.2
3876 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3877 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3878
3879 with ThreadedEchoServer(context=server_context) as server:
3880 with client_context.wrap_socket(socket.socket(),
3881 server_hostname=hostname) as s:
3882 s.connect((HOST, server.port))
3883 self.assertEqual(s.version(), 'TLSv1.2')
3884
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003885 @requires_minimum_version
3886 @requires_tls_version('TLSv1_1')
Christian Heimes2875c602021-04-19 07:27:10 +02003887 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003888 def test_min_max_version_tlsv1_1(self):
3889 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003890 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003891 client_context.minimum_version = ssl.TLSVersion.TLSv1
3892 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003893 server_context.minimum_version = ssl.TLSVersion.TLSv1
3894 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003895 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003896
3897 with ThreadedEchoServer(context=server_context) as server:
3898 with client_context.wrap_socket(socket.socket(),
3899 server_hostname=hostname) as s:
3900 s.connect((HOST, server.port))
3901 self.assertEqual(s.version(), 'TLSv1.1')
3902
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003903 @requires_minimum_version
3904 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003905 @requires_tls_version('TLSv1')
Christian Heimes2875c602021-04-19 07:27:10 +02003906 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003907 def test_min_max_version_mismatch(self):
3908 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003909 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003910 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003911 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003912 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003913 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003914 seclevel_workaround(client_context, server_context)
3915
Christian Heimes698dde12018-02-27 11:54:43 +01003916 with ThreadedEchoServer(context=server_context) as server:
3917 with client_context.wrap_socket(socket.socket(),
3918 server_hostname=hostname) as s:
3919 with self.assertRaises(ssl.SSLError) as e:
3920 s.connect((HOST, server.port))
3921 self.assertIn("alert", str(e.exception))
3922
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003923 @requires_minimum_version
3924 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003925 def test_min_max_version_sslv3(self):
3926 client_context, server_context, hostname = testing_context()
3927 server_context.minimum_version = ssl.TLSVersion.SSLv3
3928 client_context.minimum_version = ssl.TLSVersion.SSLv3
3929 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003930 seclevel_workaround(client_context, server_context)
3931
Christian Heimes698dde12018-02-27 11:54:43 +01003932 with ThreadedEchoServer(context=server_context) as server:
3933 with client_context.wrap_socket(socket.socket(),
3934 server_hostname=hostname) as s:
3935 s.connect((HOST, server.port))
3936 self.assertEqual(s.version(), 'SSLv3')
3937
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003938 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3939 def test_default_ecdh_curve(self):
3940 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3941 # should be enabled by default on SSL contexts.
Christian Heimes2875c602021-04-19 07:27:10 +02003942 client_context, server_context, hostname = testing_context()
Christian Heimescb5b68a2017-09-07 18:07:00 -07003943 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3944 # cipher name.
Christian Heimes2875c602021-04-19 07:27:10 +02003945 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003946 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3947 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3948 # our default cipher list should prefer ECDH-based ciphers
3949 # automatically.
Christian Heimes2875c602021-04-19 07:27:10 +02003950 with ThreadedEchoServer(context=server_context) as server:
3951 with client_context.wrap_socket(socket.socket(),
3952 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003953 s.connect((HOST, server.port))
3954 self.assertIn("ECDH", s.cipher()[0])
3955
3956 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3957 "'tls-unique' channel binding not available")
3958 def test_tls_unique_channel_binding(self):
3959 """Test tls-unique channel binding."""
3960 if support.verbose:
3961 sys.stdout.write("\n")
3962
Christian Heimes05d9fe32018-02-27 08:55:39 +01003963 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003964
3965 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003966 chatty=True,
3967 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003968
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003969 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003970 with client_context.wrap_socket(
3971 socket.socket(),
3972 server_hostname=hostname) as s:
3973 s.connect((HOST, server.port))
3974 # get the data
3975 cb_data = s.get_channel_binding("tls-unique")
3976 if support.verbose:
3977 sys.stdout.write(
3978 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003979
Christian Heimes05d9fe32018-02-27 08:55:39 +01003980 # check if it is sane
3981 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003982 if s.version() == 'TLSv1.3':
3983 self.assertEqual(len(cb_data), 48)
3984 else:
3985 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003986
Christian Heimes05d9fe32018-02-27 08:55:39 +01003987 # and compare with the peers version
3988 s.write(b"CB tls-unique\n")
3989 peer_data_repr = s.read().strip()
3990 self.assertEqual(peer_data_repr,
3991 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003992
3993 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003994 with client_context.wrap_socket(
3995 socket.socket(),
3996 server_hostname=hostname) as s:
3997 s.connect((HOST, server.port))
3998 new_cb_data = s.get_channel_binding("tls-unique")
3999 if support.verbose:
4000 sys.stdout.write(
4001 "got another channel binding data: {0!r}\n".format(
4002 new_cb_data)
4003 )
4004 # is it really unique
4005 self.assertNotEqual(cb_data, new_cb_data)
4006 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02004007 if s.version() == 'TLSv1.3':
4008 self.assertEqual(len(cb_data), 48)
4009 else:
4010 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01004011 s.write(b"CB tls-unique\n")
4012 peer_data_repr = s.read().strip()
4013 self.assertEqual(peer_data_repr,
4014 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004015
4016 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004017 client_context, server_context, hostname = testing_context()
4018 stats = server_params_test(client_context, server_context,
4019 chatty=True, connectionchatty=True,
4020 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004021 if support.verbose:
4022 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
4023 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
4024
4025 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
4026 "ssl.OP_NO_COMPRESSION needed for this test")
4027 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004028 client_context, server_context, hostname = testing_context()
4029 client_context.options |= ssl.OP_NO_COMPRESSION
4030 server_context.options |= ssl.OP_NO_COMPRESSION
4031 stats = server_params_test(client_context, server_context,
4032 chatty=True, connectionchatty=True,
4033 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004034 self.assertIs(stats['compression'], None)
4035
Paul Monsonf3550692019-06-19 13:09:54 -07004036 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004037 def test_dh_params(self):
4038 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004039 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004040 # test scenario needs TLS <= 1.2
4041 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004042 server_context.load_dh_params(DHFILE)
4043 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004044 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004045 stats = server_params_test(client_context, server_context,
4046 chatty=True, connectionchatty=True,
4047 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004048 cipher = stats["cipher"][0]
4049 parts = cipher.split("-")
4050 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4051 self.fail("Non-DH cipher: " + cipher[0])
4052
Christian Heimesb7b92252018-02-25 09:49:31 +01004053 @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004054 @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
Christian Heimesb7b92252018-02-25 09:49:31 +01004055 def test_ecdh_curve(self):
4056 # server secp384r1, client auto
4057 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004058
Christian Heimesb7b92252018-02-25 09:49:31 +01004059 server_context.set_ecdh_curve("secp384r1")
4060 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4061 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4062 stats = server_params_test(client_context, server_context,
4063 chatty=True, connectionchatty=True,
4064 sni_name=hostname)
4065
4066 # server auto, client secp384r1
4067 client_context, server_context, hostname = testing_context()
4068 client_context.set_ecdh_curve("secp384r1")
4069 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4070 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4071 stats = server_params_test(client_context, server_context,
4072 chatty=True, connectionchatty=True,
4073 sni_name=hostname)
4074
4075 # server / client curve mismatch
4076 client_context, server_context, hostname = testing_context()
4077 client_context.set_ecdh_curve("prime256v1")
4078 server_context.set_ecdh_curve("secp384r1")
4079 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4080 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4081 try:
Christian Heimes39258d32021-04-17 11:36:35 +02004082 server_params_test(client_context, server_context,
4083 chatty=True, connectionchatty=True,
4084 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004085 except ssl.SSLError:
Christian Heimes39258d32021-04-17 11:36:35 +02004086 self.fail("mismatch curve did not fail")
Christian Heimesb7b92252018-02-25 09:49:31 +01004087
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004088 def test_selected_alpn_protocol(self):
4089 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004090 client_context, server_context, hostname = testing_context()
4091 stats = server_params_test(client_context, server_context,
4092 chatty=True, connectionchatty=True,
4093 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004094 self.assertIs(stats['client_alpn_protocol'], None)
4095
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004096 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4097 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004098 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004099 server_context.set_alpn_protocols(['foo', 'bar'])
4100 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004101 chatty=True, connectionchatty=True,
4102 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004103 self.assertIs(stats['client_alpn_protocol'], None)
4104
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004105 def test_alpn_protocols(self):
4106 server_protocols = ['foo', 'bar', 'milkshake']
4107 protocol_tests = [
4108 (['foo', 'bar'], 'foo'),
4109 (['bar', 'foo'], 'foo'),
4110 (['milkshake'], 'milkshake'),
4111 (['http/3.0', 'http/4.0'], None)
4112 ]
4113 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004114 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004115 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004116 client_context.set_alpn_protocols(client_protocols)
4117
4118 try:
4119 stats = server_params_test(client_context,
4120 server_context,
4121 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004122 connectionchatty=True,
4123 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004124 except ssl.SSLError as e:
4125 stats = e
4126
Christian Heimes39258d32021-04-17 11:36:35 +02004127 msg = "failed trying %s (s) and %s (c).\n" \
4128 "was expecting %s, but got %%s from the %%s" \
4129 % (str(server_protocols), str(client_protocols),
4130 str(expected))
4131 client_result = stats['client_alpn_protocol']
4132 self.assertEqual(client_result, expected,
4133 msg % (client_result, "client"))
4134 server_result = stats['server_alpn_protocols'][-1] \
4135 if len(stats['server_alpn_protocols']) else 'nothing'
4136 self.assertEqual(server_result, expected,
4137 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004138
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004139 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004140 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004141
4142 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004143 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004144 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004145 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004146 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004147 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004148 client_context.load_verify_locations(SIGNING_CA)
4149 return server_context, other_context, client_context
4150
4151 def check_common_name(self, stats, name):
4152 cert = stats['peercert']
4153 self.assertIn((('commonName', name),), cert['subject'])
4154
4155 @needs_sni
4156 def test_sni_callback(self):
4157 calls = []
4158 server_context, other_context, client_context = self.sni_contexts()
4159
Christian Heimesa170fa12017-09-15 20:27:30 +02004160 client_context.check_hostname = False
4161
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004162 def servername_cb(ssl_sock, server_name, initial_context):
4163 calls.append((server_name, initial_context))
4164 if server_name is not None:
4165 ssl_sock.context = other_context
4166 server_context.set_servername_callback(servername_cb)
4167
4168 stats = server_params_test(client_context, server_context,
4169 chatty=True,
4170 sni_name='supermessage')
4171 # The hostname was fetched properly, and the certificate was
4172 # changed for the connection.
4173 self.assertEqual(calls, [("supermessage", server_context)])
4174 # CERTFILE4 was selected
4175 self.check_common_name(stats, 'fakehostname')
4176
4177 calls = []
4178 # The callback is called with server_name=None
4179 stats = server_params_test(client_context, server_context,
4180 chatty=True,
4181 sni_name=None)
4182 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004183 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004184
4185 # Check disabling the callback
4186 calls = []
4187 server_context.set_servername_callback(None)
4188
4189 stats = server_params_test(client_context, server_context,
4190 chatty=True,
4191 sni_name='notfunny')
4192 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004193 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004194 self.assertEqual(calls, [])
4195
4196 @needs_sni
4197 def test_sni_callback_alert(self):
4198 # Returning a TLS alert is reflected to the connecting client
4199 server_context, other_context, client_context = self.sni_contexts()
4200
4201 def cb_returning_alert(ssl_sock, server_name, initial_context):
4202 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4203 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004204 with self.assertRaises(ssl.SSLError) as cm:
4205 stats = server_params_test(client_context, server_context,
4206 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004207 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004208 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004209
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004210 @needs_sni
4211 def test_sni_callback_raising(self):
4212 # Raising fails the connection with a TLS handshake failure alert.
4213 server_context, other_context, client_context = self.sni_contexts()
4214
4215 def cb_raising(ssl_sock, server_name, initial_context):
4216 1/0
4217 server_context.set_servername_callback(cb_raising)
4218
Victor Stinner00253502019-06-03 03:51:43 +02004219 with support.catch_unraisable_exception() as catch:
4220 with self.assertRaises(ssl.SSLError) as cm:
4221 stats = server_params_test(client_context, server_context,
4222 chatty=False,
4223 sni_name='supermessage')
4224
4225 self.assertEqual(cm.exception.reason,
4226 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4227 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004228
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004229 @needs_sni
4230 def test_sni_callback_wrong_return_type(self):
4231 # Returning the wrong return type terminates the TLS connection
4232 # with an internal error alert.
4233 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004234
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004235 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4236 return "foo"
4237 server_context.set_servername_callback(cb_wrong_return_type)
4238
Victor Stinner00253502019-06-03 03:51:43 +02004239 with support.catch_unraisable_exception() as catch:
4240 with self.assertRaises(ssl.SSLError) as cm:
4241 stats = server_params_test(client_context, server_context,
4242 chatty=False,
4243 sni_name='supermessage')
4244
4245
4246 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4247 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004248
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004249 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004250 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004251 client_context.set_ciphers("AES128:AES256")
4252 server_context.set_ciphers("AES256")
4253 expected_algs = [
4254 "AES256", "AES-256",
4255 # TLS 1.3 ciphers are always enabled
4256 "TLS_CHACHA20", "TLS_AES",
4257 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004258
Christian Heimesa170fa12017-09-15 20:27:30 +02004259 stats = server_params_test(client_context, server_context,
4260 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004261 ciphers = stats['server_shared_ciphers'][0]
4262 self.assertGreater(len(ciphers), 0)
4263 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004264 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004265 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004266
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004267 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004268 client_context, server_context, hostname = testing_context()
4269 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004270
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004271 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004272 s = client_context.wrap_socket(socket.socket(),
4273 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004274 s.connect((HOST, server.port))
4275 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004276
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004277 self.assertRaises(ValueError, s.read, 1024)
4278 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004279
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004280 def test_sendfile(self):
4281 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004282 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004283 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004284 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimes2875c602021-04-19 07:27:10 +02004285 client_context, server_context, hostname = testing_context()
4286 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004287 with server:
Christian Heimes2875c602021-04-19 07:27:10 +02004288 with client_context.wrap_socket(socket.socket(),
4289 server_hostname=hostname) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004290 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004291 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004292 s.sendfile(file)
4293 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004294
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004295 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004296 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004297 # TODO: sessions aren't compatible with TLSv1.3 yet
4298 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004299
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004300 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004301 stats = server_params_test(client_context, server_context,
4302 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004303 session = stats['session']
4304 self.assertTrue(session.id)
4305 self.assertGreater(session.time, 0)
4306 self.assertGreater(session.timeout, 0)
4307 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004308 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004309 self.assertFalse(stats['session_reused'])
4310 sess_stat = server_context.session_stats()
4311 self.assertEqual(sess_stat['accept'], 1)
4312 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004313
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004314 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004315 stats = server_params_test(client_context, server_context,
4316 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004317 sess_stat = server_context.session_stats()
4318 self.assertEqual(sess_stat['accept'], 2)
4319 self.assertEqual(sess_stat['hits'], 1)
4320 self.assertTrue(stats['session_reused'])
4321 session2 = stats['session']
4322 self.assertEqual(session2.id, session.id)
4323 self.assertEqual(session2, session)
4324 self.assertIsNot(session2, session)
4325 self.assertGreaterEqual(session2.time, session.time)
4326 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004327
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004328 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004329 stats = server_params_test(client_context, server_context,
4330 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004331 self.assertFalse(stats['session_reused'])
4332 session3 = stats['session']
4333 self.assertNotEqual(session3.id, session.id)
4334 self.assertNotEqual(session3, session)
4335 sess_stat = server_context.session_stats()
4336 self.assertEqual(sess_stat['accept'], 3)
4337 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004338
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004339 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004340 stats = server_params_test(client_context, server_context,
4341 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004342 self.assertTrue(stats['session_reused'])
4343 session4 = stats['session']
4344 self.assertEqual(session4.id, session.id)
4345 self.assertEqual(session4, session)
4346 self.assertGreaterEqual(session4.time, session.time)
4347 self.assertGreaterEqual(session4.timeout, session.timeout)
4348 sess_stat = server_context.session_stats()
4349 self.assertEqual(sess_stat['accept'], 4)
4350 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004351
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004352 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004353 client_context, server_context, hostname = testing_context()
4354 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004355
Christian Heimes05d9fe32018-02-27 08:55:39 +01004356 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004357 client_context.options |= ssl.OP_NO_TLSv1_3
4358 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004359
Christian Heimesa170fa12017-09-15 20:27:30 +02004360 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004361 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004362 with client_context.wrap_socket(socket.socket(),
4363 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004364 # session is None before handshake
4365 self.assertEqual(s.session, None)
4366 self.assertEqual(s.session_reused, None)
4367 s.connect((HOST, server.port))
4368 session = s.session
4369 self.assertTrue(session)
4370 with self.assertRaises(TypeError) as e:
4371 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004372 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004373
Christian Heimesa170fa12017-09-15 20:27:30 +02004374 with client_context.wrap_socket(socket.socket(),
4375 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004376 s.connect((HOST, server.port))
4377 # cannot set session after handshake
4378 with self.assertRaises(ValueError) as e:
4379 s.session = session
4380 self.assertEqual(str(e.exception),
4381 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004382
Christian Heimesa170fa12017-09-15 20:27:30 +02004383 with client_context.wrap_socket(socket.socket(),
4384 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004385 # can set session before handshake and before the
4386 # connection was established
4387 s.session = session
4388 s.connect((HOST, server.port))
4389 self.assertEqual(s.session.id, session.id)
4390 self.assertEqual(s.session, session)
4391 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004392
Christian Heimesa170fa12017-09-15 20:27:30 +02004393 with client_context2.wrap_socket(socket.socket(),
4394 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004395 # cannot re-use session with a different SSLContext
4396 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004397 s.session = session
4398 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004399 self.assertEqual(str(e.exception),
4400 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004401
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004402
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004403@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004404class TestPostHandshakeAuth(unittest.TestCase):
4405 def test_pha_setter(self):
4406 protocols = [
Christian Heimes2875c602021-04-19 07:27:10 +02004407 ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
Christian Heimes9fb051f2018-09-23 08:32:31 +02004408 ]
4409 for protocol in protocols:
4410 ctx = ssl.SSLContext(protocol)
4411 self.assertEqual(ctx.post_handshake_auth, False)
4412
4413 ctx.post_handshake_auth = True
4414 self.assertEqual(ctx.post_handshake_auth, True)
4415
4416 ctx.verify_mode = ssl.CERT_REQUIRED
4417 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4418 self.assertEqual(ctx.post_handshake_auth, True)
4419
4420 ctx.post_handshake_auth = False
4421 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4422 self.assertEqual(ctx.post_handshake_auth, False)
4423
4424 ctx.verify_mode = ssl.CERT_OPTIONAL
4425 ctx.post_handshake_auth = True
4426 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4427 self.assertEqual(ctx.post_handshake_auth, True)
4428
4429 def test_pha_required(self):
4430 client_context, server_context, hostname = testing_context()
4431 server_context.post_handshake_auth = True
4432 server_context.verify_mode = ssl.CERT_REQUIRED
4433 client_context.post_handshake_auth = True
4434 client_context.load_cert_chain(SIGNED_CERTFILE)
4435
4436 server = ThreadedEchoServer(context=server_context, chatty=False)
4437 with server:
4438 with client_context.wrap_socket(socket.socket(),
4439 server_hostname=hostname) as s:
4440 s.connect((HOST, server.port))
4441 s.write(b'HASCERT')
4442 self.assertEqual(s.recv(1024), b'FALSE\n')
4443 s.write(b'PHA')
4444 self.assertEqual(s.recv(1024), b'OK\n')
4445 s.write(b'HASCERT')
4446 self.assertEqual(s.recv(1024), b'TRUE\n')
4447 # PHA method just returns true when cert is already available
4448 s.write(b'PHA')
4449 self.assertEqual(s.recv(1024), b'OK\n')
4450 s.write(b'GETCERT')
4451 cert_text = s.recv(4096).decode('us-ascii')
4452 self.assertIn('Python Software Foundation CA', cert_text)
4453
4454 def test_pha_required_nocert(self):
4455 client_context, server_context, hostname = testing_context()
4456 server_context.post_handshake_auth = True
4457 server_context.verify_mode = ssl.CERT_REQUIRED
4458 client_context.post_handshake_auth = True
4459
Victor Stinner73ea5462019-07-09 14:33:49 +02004460 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4461 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004462 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004463 server = ThreadedEchoServer(context=server_context, chatty=False)
4464 with server:
4465 with client_context.wrap_socket(socket.socket(),
4466 server_hostname=hostname) as s:
4467 s.connect((HOST, server.port))
4468 s.write(b'PHA')
4469 # receive CertificateRequest
4470 self.assertEqual(s.recv(1024), b'OK\n')
4471 # send empty Certificate + Finish
4472 s.write(b'HASCERT')
4473 # receive alert
4474 with self.assertRaisesRegex(
4475 ssl.SSLError,
4476 'tlsv13 alert certificate required'):
4477 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004478
4479 def test_pha_optional(self):
4480 if support.verbose:
4481 sys.stdout.write("\n")
4482
4483 client_context, server_context, hostname = testing_context()
4484 server_context.post_handshake_auth = True
4485 server_context.verify_mode = ssl.CERT_REQUIRED
4486 client_context.post_handshake_auth = True
4487 client_context.load_cert_chain(SIGNED_CERTFILE)
4488
4489 # check CERT_OPTIONAL
4490 server_context.verify_mode = ssl.CERT_OPTIONAL
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'FALSE\n')
4498 s.write(b'PHA')
4499 self.assertEqual(s.recv(1024), b'OK\n')
4500 s.write(b'HASCERT')
4501 self.assertEqual(s.recv(1024), b'TRUE\n')
4502
4503 def test_pha_optional_nocert(self):
4504 if support.verbose:
4505 sys.stdout.write("\n")
4506
4507 client_context, server_context, hostname = testing_context()
4508 server_context.post_handshake_auth = True
4509 server_context.verify_mode = ssl.CERT_OPTIONAL
4510 client_context.post_handshake_auth = True
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 s.write(b'HASCERT')
4518 self.assertEqual(s.recv(1024), b'FALSE\n')
4519 s.write(b'PHA')
4520 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004521 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004522 s.write(b'HASCERT')
4523 self.assertEqual(s.recv(1024), b'FALSE\n')
4524
4525 def test_pha_no_pha_client(self):
4526 client_context, server_context, hostname = testing_context()
4527 server_context.post_handshake_auth = True
4528 server_context.verify_mode = ssl.CERT_REQUIRED
4529 client_context.load_cert_chain(SIGNED_CERTFILE)
4530
4531 server = ThreadedEchoServer(context=server_context, chatty=False)
4532 with server:
4533 with client_context.wrap_socket(socket.socket(),
4534 server_hostname=hostname) as s:
4535 s.connect((HOST, server.port))
4536 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4537 s.verify_client_post_handshake()
4538 s.write(b'PHA')
4539 self.assertIn(b'extension not received', s.recv(1024))
4540
4541 def test_pha_no_pha_server(self):
4542 # server doesn't have PHA enabled, cert is requested in handshake
4543 client_context, server_context, hostname = testing_context()
4544 server_context.verify_mode = ssl.CERT_REQUIRED
4545 client_context.post_handshake_auth = True
4546 client_context.load_cert_chain(SIGNED_CERTFILE)
4547
4548 server = ThreadedEchoServer(context=server_context, chatty=False)
4549 with server:
4550 with client_context.wrap_socket(socket.socket(),
4551 server_hostname=hostname) as s:
4552 s.connect((HOST, server.port))
4553 s.write(b'HASCERT')
4554 self.assertEqual(s.recv(1024), b'TRUE\n')
4555 # PHA doesn't fail if there is already a cert
4556 s.write(b'PHA')
4557 self.assertEqual(s.recv(1024), b'OK\n')
4558 s.write(b'HASCERT')
4559 self.assertEqual(s.recv(1024), b'TRUE\n')
4560
4561 def test_pha_not_tls13(self):
4562 # TLS 1.2
4563 client_context, server_context, hostname = testing_context()
4564 server_context.verify_mode = ssl.CERT_REQUIRED
4565 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4566 client_context.post_handshake_auth = True
4567 client_context.load_cert_chain(SIGNED_CERTFILE)
4568
4569 server = ThreadedEchoServer(context=server_context, chatty=False)
4570 with server:
4571 with client_context.wrap_socket(socket.socket(),
4572 server_hostname=hostname) as s:
4573 s.connect((HOST, server.port))
4574 # PHA fails for TLS != 1.3
4575 s.write(b'PHA')
4576 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4577
Christian Heimesf0f59302019-07-01 08:29:17 +02004578 def test_bpo37428_pha_cert_none(self):
4579 # verify that post_handshake_auth does not implicitly enable cert
4580 # validation.
4581 hostname = SIGNED_CERTFILE_HOSTNAME
4582 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4583 client_context.post_handshake_auth = True
4584 client_context.load_cert_chain(SIGNED_CERTFILE)
4585 # no cert validation and CA on client side
4586 client_context.check_hostname = False
4587 client_context.verify_mode = ssl.CERT_NONE
4588
4589 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4590 server_context.load_cert_chain(SIGNED_CERTFILE)
4591 server_context.load_verify_locations(SIGNING_CA)
4592 server_context.post_handshake_auth = True
4593 server_context.verify_mode = ssl.CERT_REQUIRED
4594
4595 server = ThreadedEchoServer(context=server_context, chatty=False)
4596 with server:
4597 with client_context.wrap_socket(socket.socket(),
4598 server_hostname=hostname) as s:
4599 s.connect((HOST, server.port))
4600 s.write(b'HASCERT')
4601 self.assertEqual(s.recv(1024), b'FALSE\n')
4602 s.write(b'PHA')
4603 self.assertEqual(s.recv(1024), b'OK\n')
4604 s.write(b'HASCERT')
4605 self.assertEqual(s.recv(1024), b'TRUE\n')
4606 # server cert has not been validated
4607 self.assertEqual(s.getpeercert(), {})
4608
Christian Heimes9fb051f2018-09-23 08:32:31 +02004609
Christian Heimesc7f70692019-05-31 11:44:05 +02004610HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4611requires_keylog = unittest.skipUnless(
4612 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4613
4614class TestSSLDebug(unittest.TestCase):
4615
Hai Shia7f5d932020-08-04 00:41:24 +08004616 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004617 with open(fname) as f:
4618 return len(list(f))
4619
4620 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004621 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004622 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004623 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004624 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4625 self.assertEqual(ctx.keylog_filename, None)
4626
Hai Shia7f5d932020-08-04 00:41:24 +08004627 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4628 ctx.keylog_filename = os_helper.TESTFN
4629 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4630 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004631 self.assertEqual(self.keylog_lines(), 1)
4632
4633 ctx.keylog_filename = None
4634 self.assertEqual(ctx.keylog_filename, None)
4635
4636 with self.assertRaises((IsADirectoryError, PermissionError)):
4637 # Windows raises PermissionError
4638 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004639 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004640
4641 with self.assertRaises(TypeError):
4642 ctx.keylog_filename = 1
4643
4644 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004645 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004646 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004647 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004648 client_context, server_context, hostname = testing_context()
4649
Hai Shia7f5d932020-08-04 00:41:24 +08004650 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004651 server = ThreadedEchoServer(context=server_context, chatty=False)
4652 with server:
4653 with client_context.wrap_socket(socket.socket(),
4654 server_hostname=hostname) as s:
4655 s.connect((HOST, server.port))
4656 # header, 5 lines for TLS 1.3
4657 self.assertEqual(self.keylog_lines(), 6)
4658
4659 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004660 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004661 server = ThreadedEchoServer(context=server_context, chatty=False)
4662 with server:
4663 with client_context.wrap_socket(socket.socket(),
4664 server_hostname=hostname) as s:
4665 s.connect((HOST, server.port))
4666 self.assertGreaterEqual(self.keylog_lines(), 11)
4667
Hai Shia7f5d932020-08-04 00:41:24 +08004668 client_context.keylog_filename = os_helper.TESTFN
4669 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004670 server = ThreadedEchoServer(context=server_context, chatty=False)
4671 with server:
4672 with client_context.wrap_socket(socket.socket(),
4673 server_hostname=hostname) as s:
4674 s.connect((HOST, server.port))
4675 self.assertGreaterEqual(self.keylog_lines(), 21)
4676
4677 client_context.keylog_filename = None
4678 server_context.keylog_filename = None
4679
4680 @requires_keylog
4681 @unittest.skipIf(sys.flags.ignore_environment,
4682 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004683 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004684 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004685 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004686 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004687 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4688 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004689
4690 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4691 self.assertEqual(ctx.keylog_filename, None)
4692
4693 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004694 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004695
4696 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004697 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004698
4699 def test_msg_callback(self):
4700 client_context, server_context, hostname = testing_context()
4701
4702 def msg_cb(conn, direction, version, content_type, msg_type, data):
4703 pass
4704
4705 self.assertIs(client_context._msg_callback, None)
4706 client_context._msg_callback = msg_cb
4707 self.assertIs(client_context._msg_callback, msg_cb)
4708 with self.assertRaises(TypeError):
4709 client_context._msg_callback = object()
4710
4711 def test_msg_callback_tls12(self):
4712 client_context, server_context, hostname = testing_context()
4713 client_context.options |= ssl.OP_NO_TLSv1_3
4714
4715 msg = []
4716
4717 def msg_cb(conn, direction, version, content_type, msg_type, data):
4718 self.assertIsInstance(conn, ssl.SSLSocket)
4719 self.assertIsInstance(data, bytes)
4720 self.assertIn(direction, {'read', 'write'})
4721 msg.append((direction, version, content_type, msg_type))
4722
4723 client_context._msg_callback = msg_cb
4724
4725 server = ThreadedEchoServer(context=server_context, chatty=False)
4726 with server:
4727 with client_context.wrap_socket(socket.socket(),
4728 server_hostname=hostname) as s:
4729 s.connect((HOST, server.port))
4730
Christian Heimese35d1ba2019-06-03 20:40:15 +02004731 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004732 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4733 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004734 msg
4735 )
4736 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004737 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4738 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004739 msg
4740 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004741
Christian Heimes77cde502021-03-21 16:13:09 +01004742 def test_msg_callback_deadlock_bpo43577(self):
4743 client_context, server_context, hostname = testing_context()
4744 server_context2 = testing_context()[1]
4745
4746 def msg_cb(conn, direction, version, content_type, msg_type, data):
4747 pass
4748
4749 def sni_cb(sock, servername, ctx):
4750 sock.context = server_context2
4751
4752 server_context._msg_callback = msg_cb
4753 server_context.sni_callback = sni_cb
4754
4755 server = ThreadedEchoServer(context=server_context, chatty=False)
4756 with server:
4757 with client_context.wrap_socket(socket.socket(),
4758 server_hostname=hostname) as s:
4759 s.connect((HOST, server.port))
4760 with client_context.wrap_socket(socket.socket(),
4761 server_hostname=hostname) as s:
4762 s.connect((HOST, server.port))
4763
Christian Heimesc7f70692019-05-31 11:44:05 +02004764
Thomas Woutersed03b412007-08-28 21:37:11 +00004765def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004766 if support.verbose:
4767 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004768 'Mac': platform.mac_ver,
4769 'Windows': platform.win32_ver,
4770 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004771 for name, func in plats.items():
4772 plat = func()
4773 if plat and plat[0]:
4774 plat = '%s %r' % (name, plat)
4775 break
4776 else:
4777 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004778 print("test_ssl: testing with %r %r" %
4779 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4780 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004781 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004782 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4783 try:
4784 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4785 except AttributeError:
4786 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004787
Antoine Pitrou152efa22010-05-16 18:19:27 +00004788 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004789 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004790 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004791 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004792 BADCERT, BADKEY, EMPTYCERT]:
4793 if not os.path.exists(filename):
4794 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004795
Martin Panter3840b2a2016-03-27 01:53:46 +00004796 tests = [
4797 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004798 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004799 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004800 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004801
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004802 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004803 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004804
Hai Shie80697d2020-05-28 06:10:27 +08004805 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004806 try:
4807 support.run_unittest(*tests)
4808 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004809 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004810
4811if __name__ == "__main__":
4812 test_main()