blob: 3ad14c63968e641e43c14766e84a59cbf1b87bcb [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.
227 ctx = ssl.SSLContext()
228 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
Antoine Pitrou23df4832010-08-04 17:14:06 +0000309
Christian Heimesd0486372016-09-10 23:23:33 +0200310def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLS, *,
311 cert_reqs=ssl.CERT_NONE, ca_certs=None,
312 ciphers=None, certfile=None, keyfile=None,
313 **kwargs):
314 context = ssl.SSLContext(ssl_version)
315 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200316 if cert_reqs == ssl.CERT_NONE:
317 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200318 context.verify_mode = cert_reqs
319 if ca_certs is not None:
320 context.load_verify_locations(ca_certs)
321 if certfile is not None or keyfile is not None:
322 context.load_cert_chain(certfile, keyfile)
323 if ciphers is not None:
324 context.set_ciphers(ciphers)
325 return context.wrap_socket(sock, **kwargs)
326
Christian Heimesa170fa12017-09-15 20:27:30 +0200327
328def testing_context(server_cert=SIGNED_CERTFILE):
329 """Create context
330
331 client_context, server_context, hostname = testing_context()
332 """
333 if server_cert == SIGNED_CERTFILE:
334 hostname = SIGNED_CERTFILE_HOSTNAME
335 elif server_cert == SIGNED_CERTFILE2:
336 hostname = SIGNED_CERTFILE2_HOSTNAME
Christian Heimesb467d9a2021-04-17 10:07:19 +0200337 elif server_cert == NOSANFILE:
338 hostname = NOSAN_HOSTNAME
Christian Heimesa170fa12017-09-15 20:27:30 +0200339 else:
340 raise ValueError(server_cert)
341
342 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
343 client_context.load_verify_locations(SIGNING_CA)
344
345 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
346 server_context.load_cert_chain(server_cert)
Christian Heimes9fb051f2018-09-23 08:32:31 +0200347 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200348
349 return client_context, server_context, hostname
350
351
Antoine Pitrou152efa22010-05-16 18:19:27 +0000352class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000353
Antoine Pitrou480a1242010-04-28 21:37:09 +0000354 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000355 ssl.CERT_NONE
356 ssl.CERT_OPTIONAL
357 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100358 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100359 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100360 if ssl.HAS_ECDH:
361 ssl.OP_SINGLE_ECDH_USE
Christian Heimes39258d32021-04-17 11:36:35 +0200362 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000363 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100364 self.assertIn(ssl.HAS_ECDH, {True, False})
Christian Heimescb5b68a2017-09-07 18:07:00 -0700365 ssl.OP_NO_SSLv2
366 ssl.OP_NO_SSLv3
367 ssl.OP_NO_TLSv1
368 ssl.OP_NO_TLSv1_3
Christian Heimes39258d32021-04-17 11:36:35 +0200369 ssl.OP_NO_TLSv1_1
370 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200371 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000372
Christian Heimes9d50ab52018-02-27 10:17:30 +0100373 def test_private_init(self):
374 with self.assertRaisesRegex(TypeError, "public constructor"):
375 with socket.socket() as s:
376 ssl.SSLSocket(s)
377
Antoine Pitrou172f0252014-04-18 20:33:08 +0200378 def test_str_for_enums(self):
379 # Make sure that the PROTOCOL_* constants have enum-like string
380 # reprs.
Christian Heimes598894f2016-09-05 23:19:05 +0200381 proto = ssl.PROTOCOL_TLS
Ethan Furmanb7751062021-03-30 21:17:26 -0700382 self.assertEqual(str(proto), 'PROTOCOL_TLS')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200383 ctx = ssl.SSLContext(proto)
384 self.assertIs(ctx.protocol, proto)
385
Antoine Pitrou480a1242010-04-28 21:37:09 +0000386 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000387 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000388 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000389 sys.stdout.write("\n RAND_status is %d (%s)\n"
390 % (v, (v and "sufficient randomness") or
391 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200392
393 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
394 self.assertEqual(len(data), 16)
395 self.assertEqual(is_cryptographic, v == 1)
396 if v:
397 data = ssl.RAND_bytes(16)
398 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200399 else:
400 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200401
Victor Stinner1e81a392013-12-19 16:47:04 +0100402 # negative num is invalid
403 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
404 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
405
Victor Stinnerbeeb5122014-11-28 13:28:25 +0100406 if hasattr(ssl, 'RAND_egd'):
407 self.assertRaises(TypeError, ssl.RAND_egd, 1)
408 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000409 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200410 ssl.RAND_add(b"this is a random bytes object", 75.0)
411 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000412
pxinwr98a54172020-12-09 07:20:19 +0800413 @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
Christian Heimesf77b4b22013-08-21 13:26:05 +0200414 def test_random_fork(self):
415 status = ssl.RAND_status()
416 if not status:
417 self.fail("OpenSSL's PRNG has insufficient randomness")
418
419 rfd, wfd = os.pipe()
420 pid = os.fork()
421 if pid == 0:
422 try:
423 os.close(rfd)
424 child_random = ssl.RAND_pseudo_bytes(16)[0]
425 self.assertEqual(len(child_random), 16)
426 os.write(wfd, child_random)
427 os.close(wfd)
428 except BaseException:
429 os._exit(1)
430 else:
431 os._exit(0)
432 else:
433 os.close(wfd)
434 self.addCleanup(os.close, rfd)
Victor Stinner278c1e12020-03-31 20:08:12 +0200435 support.wait_process(pid, exitcode=0)
Christian Heimesf77b4b22013-08-21 13:26:05 +0200436
437 child_random = os.read(rfd, 16)
438 self.assertEqual(len(child_random), 16)
439 parent_random = ssl.RAND_pseudo_bytes(16)[0]
440 self.assertEqual(len(parent_random), 16)
441
442 self.assertNotEqual(child_random, parent_random)
443
Christian Heimese6dac002018-08-30 07:25:49 +0200444 maxDiff = None
445
Antoine Pitrou480a1242010-04-28 21:37:09 +0000446 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000447 # note that this uses an 'unofficial' function in _ssl.c,
448 # provided solely for this test, to exercise the certificate
449 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100450 self.assertEqual(
451 ssl._ssl._test_decode_cert(CERTFILE),
452 CERTFILE_INFO
453 )
454 self.assertEqual(
455 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
456 SIGNED_CERTFILE_INFO
457 )
458
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200459 # Issue #13034: the subjectAltName in some certificates
460 # (notably projects.developer.nokia.com:443) wasn't parsed
461 p = ssl._ssl._test_decode_cert(NOKIACERT)
462 if support.verbose:
463 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
464 self.assertEqual(p['subjectAltName'],
465 (('DNS', 'projects.developer.nokia.com'),
466 ('DNS', 'projects.forum.nokia.com'))
467 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100468 # extra OCSP and AIA fields
469 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
470 self.assertEqual(p['caIssuers'],
471 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
472 self.assertEqual(p['crlDistributionPoints'],
473 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000474
Christian Heimesa37f5242019-01-15 23:47:42 +0100475 def test_parse_cert_CVE_2019_5010(self):
476 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
477 if support.verbose:
478 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
479 self.assertEqual(
480 p,
481 {
482 'issuer': (
483 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
484 'notAfter': 'Jun 14 18:00:58 2028 GMT',
485 'notBefore': 'Jun 18 18:00:58 2018 GMT',
486 'serialNumber': '02',
487 'subject': ((('countryName', 'UK'),),
488 (('commonName',
489 'codenomicon-vm-2.test.lal.cisco.com'),)),
490 'subjectAltName': (
491 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
492 'version': 3
493 }
494 )
495
Christian Heimes824f7f32013-08-17 00:54:47 +0200496 def test_parse_cert_CVE_2013_4238(self):
497 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
498 if support.verbose:
499 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
500 subject = ((('countryName', 'US'),),
501 (('stateOrProvinceName', 'Oregon'),),
502 (('localityName', 'Beaverton'),),
503 (('organizationName', 'Python Software Foundation'),),
504 (('organizationalUnitName', 'Python Core Development'),),
505 (('commonName', 'null.python.org\x00example.org'),),
506 (('emailAddress', 'python-dev@python.org'),))
507 self.assertEqual(p['subject'], subject)
508 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200509 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
510 san = (('DNS', 'altnull.python.org\x00example.com'),
511 ('email', 'null@python.org\x00user@example.org'),
512 ('URI', 'http://null.python.org\x00http://example.org'),
513 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100514 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200515 else:
516 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
517 san = (('DNS', 'altnull.python.org\x00example.com'),
518 ('email', 'null@python.org\x00user@example.org'),
519 ('URI', 'http://null.python.org\x00http://example.org'),
520 ('IP Address', '192.0.2.1'),
521 ('IP Address', '<invalid>'))
522
523 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200524
Christian Heimes1c03abd2016-09-06 23:25:35 +0200525 def test_parse_all_sans(self):
526 p = ssl._ssl._test_decode_cert(ALLSANFILE)
527 self.assertEqual(p['subjectAltName'],
528 (
529 ('DNS', 'allsans'),
530 ('othername', '<unsupported>'),
531 ('othername', '<unsupported>'),
532 ('email', 'user@example.org'),
533 ('DNS', 'www.example.org'),
534 ('DirName',
535 ((('countryName', 'XY'),),
536 (('localityName', 'Castle Anthrax'),),
537 (('organizationName', 'Python Software Foundation'),),
538 (('commonName', 'dirname example'),))),
539 ('URI', 'https://www.python.org/'),
540 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100541 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200542 ('Registered ID', '1.2.3.4.5')
543 )
544 )
545
Antoine Pitrou480a1242010-04-28 21:37:09 +0000546 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000547 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000548 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000549 d1 = ssl.PEM_cert_to_DER_cert(pem)
550 p2 = ssl.DER_cert_to_PEM_cert(d1)
551 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000552 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000553 if not p2.startswith(ssl.PEM_HEADER + '\n'):
554 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
555 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
556 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000557
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000558 def test_openssl_version(self):
559 n = ssl.OPENSSL_VERSION_NUMBER
560 t = ssl.OPENSSL_VERSION_INFO
561 s = ssl.OPENSSL_VERSION
562 self.assertIsInstance(n, int)
563 self.assertIsInstance(t, tuple)
564 self.assertIsInstance(s, str)
565 # Some sanity checks follow
566 # >= 0.9
567 self.assertGreaterEqual(n, 0x900000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100568 # < 4.0
569 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000570 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100571 self.assertGreaterEqual(major, 1)
572 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000573 self.assertGreaterEqual(minor, 0)
574 self.assertLess(minor, 256)
575 self.assertGreaterEqual(fix, 0)
576 self.assertLess(fix, 256)
577 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100578 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000579 self.assertGreaterEqual(status, 0)
580 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400581 # Version string as returned by {Open,Libre}SSL, the format might change
Christian Heimes598894f2016-09-05 23:19:05 +0200582 if IS_LIBRESSL:
583 self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
Victor Stinner789b8052015-01-06 11:51:06 +0100584 (s, t, hex(n)))
Antoine Pitroudfab9352014-07-21 18:35:01 -0400585 else:
586 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
Victor Stinner789b8052015-01-06 11:51:06 +0100587 (s, t, hex(n)))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000588
Antoine Pitrou9d543662010-04-23 23:10:32 +0000589 @support.cpython_only
590 def test_refcycle(self):
591 # Issue #7943: an SSL object doesn't create reference cycles with
592 # itself.
593 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200594 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000595 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800596 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100597 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100598 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000599
Antoine Pitroua468adc2010-09-14 14:43:44 +0000600 def test_wrapped_unconnected(self):
601 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200602 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000603 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200604 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100605 self.assertRaises(OSError, ss.recv, 1)
606 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
607 self.assertRaises(OSError, ss.recvfrom, 1)
608 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
609 self.assertRaises(OSError, ss.send, b'x')
610 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200611 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100612 self.assertRaises(NotImplementedError, ss.sendmsg,
613 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200614 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
615 self.assertRaises(NotImplementedError, ss.recvmsg_into,
616 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000617
Antoine Pitrou40f08742010-04-24 22:04:40 +0000618 def test_timeout(self):
619 # Issue #8524: when creating an SSL socket, the timeout of the
620 # original socket should be retained.
621 for timeout in (None, 0.0, 5.0):
622 s = socket.socket(socket.AF_INET)
623 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200624 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100625 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000626
Christian Heimesd0486372016-09-10 23:23:33 +0200627 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000628 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000629 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000630 "certfile must be specified",
631 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000632 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000633 "certfile must be specified for server-side operations",
634 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000635 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000636 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200637 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100638 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
639 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200640 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200641 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000642 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000643 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000644 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200645 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000646 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000647 ssl.wrap_socket(sock,
648 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000649 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200650 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000651 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000652 ssl.wrap_socket(sock,
653 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000654 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000655
Martin Panter3464ea22016-02-01 21:58:11 +0000656 def bad_cert_test(self, certfile):
657 """Check that trying to use the given client certificate fails"""
658 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
659 certfile)
660 sock = socket.socket()
661 self.addCleanup(sock.close)
662 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200663 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200664 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000665
666 def test_empty_cert(self):
667 """Wrapping with an empty cert file"""
668 self.bad_cert_test("nullcert.pem")
669
670 def test_malformed_cert(self):
671 """Wrapping with a badly formatted certificate (syntax error)"""
672 self.bad_cert_test("badcert.pem")
673
674 def test_malformed_key(self):
675 """Wrapping with a badly formatted key (syntax error)"""
676 self.bad_cert_test("badkey.pem")
677
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000678 def test_match_hostname(self):
679 def ok(cert, hostname):
680 ssl.match_hostname(cert, hostname)
681 def fail(cert, hostname):
682 self.assertRaises(ssl.CertificateError,
683 ssl.match_hostname, cert, hostname)
684
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100685 # -- Hostname matching --
686
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000687 cert = {'subject': ((('commonName', 'example.com'),),)}
688 ok(cert, 'example.com')
689 ok(cert, 'ExAmple.cOm')
690 fail(cert, 'www.example.com')
691 fail(cert, '.example.com')
692 fail(cert, 'example.org')
693 fail(cert, 'exampleXcom')
694
695 cert = {'subject': ((('commonName', '*.a.com'),),)}
696 ok(cert, 'foo.a.com')
697 fail(cert, 'bar.foo.a.com')
698 fail(cert, 'a.com')
699 fail(cert, 'Xa.com')
700 fail(cert, '.a.com')
701
Mandeep Singhede2ac92017-11-27 04:01:27 +0530702 # only match wildcards when they are the only thing
703 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000704 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530705 fail(cert, 'foo.com')
706 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000707 fail(cert, 'bar.com')
708 fail(cert, 'foo.a.com')
709 fail(cert, 'bar.foo.com')
710
Christian Heimes824f7f32013-08-17 00:54:47 +0200711 # NULL bytes are bad, CVE-2013-4073
712 cert = {'subject': ((('commonName',
713 'null.python.org\x00example.org'),),)}
714 ok(cert, 'null.python.org\x00example.org') # or raise an error?
715 fail(cert, 'example.org')
716 fail(cert, 'null.python.org')
717
Georg Brandl72c98d32013-10-27 07:16:53 +0100718 # error cases with wildcards
719 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
720 fail(cert, 'bar.foo.a.com')
721 fail(cert, 'a.com')
722 fail(cert, 'Xa.com')
723 fail(cert, '.a.com')
724
725 cert = {'subject': ((('commonName', 'a.*.com'),),)}
726 fail(cert, 'a.foo.com')
727 fail(cert, 'a..com')
728 fail(cert, 'a.com')
729
730 # wildcard doesn't match IDNA prefix 'xn--'
731 idna = 'püthon.python.org'.encode("idna").decode("ascii")
732 cert = {'subject': ((('commonName', idna),),)}
733 ok(cert, idna)
734 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
735 fail(cert, idna)
736 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
737 fail(cert, idna)
738
739 # wildcard in first fragment and IDNA A-labels in sequent fragments
740 # are supported.
741 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
742 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530743 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
744 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100745 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
746 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
747
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000748 # Slightly fake real-world example
749 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
750 'subject': ((('commonName', 'linuxfrz.org'),),),
751 'subjectAltName': (('DNS', 'linuxfr.org'),
752 ('DNS', 'linuxfr.com'),
753 ('othername', '<unsupported>'))}
754 ok(cert, 'linuxfr.org')
755 ok(cert, 'linuxfr.com')
756 # Not a "DNS" entry
757 fail(cert, '<unsupported>')
758 # When there is a subjectAltName, commonName isn't used
759 fail(cert, 'linuxfrz.org')
760
761 # A pristine real-world example
762 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
763 'subject': ((('countryName', 'US'),),
764 (('stateOrProvinceName', 'California'),),
765 (('localityName', 'Mountain View'),),
766 (('organizationName', 'Google Inc'),),
767 (('commonName', 'mail.google.com'),))}
768 ok(cert, 'mail.google.com')
769 fail(cert, 'gmail.com')
770 # Only commonName is considered
771 fail(cert, 'California')
772
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100773 # -- IPv4 matching --
774 cert = {'subject': ((('commonName', 'example.com'),),),
775 'subjectAltName': (('DNS', 'example.com'),
776 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200777 ('IP Address', '14.15.16.17'),
778 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100779 ok(cert, '10.11.12.13')
780 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200781 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
782 fail(cert, '127.1')
783 fail(cert, '14.15.16.17 ')
784 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100785 fail(cert, '14.15.16.18')
786 fail(cert, 'example.net')
787
788 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300789 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100790 cert = {'subject': ((('commonName', 'example.com'),),),
791 'subjectAltName': (
792 ('DNS', 'example.com'),
793 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
794 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
795 ok(cert, '2001::cafe')
796 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200797 fail(cert, '2003::baba ')
798 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100799 fail(cert, '2003::bebe')
800 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100801
802 # -- Miscellaneous --
803
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000804 # Neither commonName nor subjectAltName
805 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
806 'subject': ((('countryName', 'US'),),
807 (('stateOrProvinceName', 'California'),),
808 (('localityName', 'Mountain View'),),
809 (('organizationName', 'Google Inc'),))}
810 fail(cert, 'mail.google.com')
811
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200812 # No DNS entry in subjectAltName but a commonName
813 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
814 'subject': ((('countryName', 'US'),),
815 (('stateOrProvinceName', 'California'),),
816 (('localityName', 'Mountain View'),),
817 (('commonName', 'mail.google.com'),)),
818 'subjectAltName': (('othername', 'blabla'), )}
819 ok(cert, 'mail.google.com')
820
821 # No DNS entry subjectAltName and no commonName
822 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
823 'subject': ((('countryName', 'US'),),
824 (('stateOrProvinceName', 'California'),),
825 (('localityName', 'Mountain View'),),
826 (('organizationName', 'Google Inc'),)),
827 'subjectAltName': (('othername', 'blabla'),)}
828 fail(cert, 'google.com')
829
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000830 # Empty cert / no cert
831 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
832 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
833
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200834 # Issue #17980: avoid denials of service by refusing more than one
835 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100836 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
837 with self.assertRaisesRegex(
838 ssl.CertificateError,
839 "partial wildcards in leftmost label are not supported"):
840 ssl.match_hostname(cert, 'axxb.example.com')
841
842 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
843 with self.assertRaisesRegex(
844 ssl.CertificateError,
845 "wildcard can only be present in the leftmost label"):
846 ssl.match_hostname(cert, 'www.sub.example.com')
847
848 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
849 with self.assertRaisesRegex(
850 ssl.CertificateError,
851 "too many wildcards"):
852 ssl.match_hostname(cert, 'axxbxxc.example.com')
853
854 cert = {'subject': ((('commonName', '*'),),)}
855 with self.assertRaisesRegex(
856 ssl.CertificateError,
857 "sole wildcard without additional labels are not support"):
858 ssl.match_hostname(cert, 'host')
859
860 cert = {'subject': ((('commonName', '*.com'),),)}
861 with self.assertRaisesRegex(
862 ssl.CertificateError,
863 r"hostname 'com' doesn't match '\*.com'"):
864 ssl.match_hostname(cert, 'com')
865
866 # extra checks for _inet_paton()
867 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
868 with self.assertRaises(ValueError):
869 ssl._inet_paton(invalid)
870 for ipaddr in ['127.0.0.1', '192.168.0.1']:
871 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300872 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100873 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
874 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200875
Antoine Pitroud5323212010-10-22 18:19:07 +0000876 def test_server_side(self):
877 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200878 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000879 with socket.socket() as sock:
880 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
881 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000882
Antoine Pitroud6494802011-07-21 01:11:30 +0200883 def test_unknown_channel_binding(self):
884 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200885 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200886 c = socket.socket(socket.AF_INET)
887 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200888 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100889 with self.assertRaises(ValueError):
890 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200891 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200892
893 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
894 "'tls-unique' channel binding not available")
895 def test_tls_unique_channel_binding(self):
896 # unconnected should return None for known type
897 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200898 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100899 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200900 # the same for server-side
901 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200902 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100903 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200904
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600905 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200906 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600907 r = repr(ss)
908 with self.assertWarns(ResourceWarning) as cm:
909 ss = None
910 support.gc_collect()
911 self.assertIn(r, str(cm.warning.args[0]))
912
Christian Heimes6d7ad132013-06-09 18:02:55 +0200913 def test_get_default_verify_paths(self):
914 paths = ssl.get_default_verify_paths()
915 self.assertEqual(len(paths), 6)
916 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
917
Hai Shia7f5d932020-08-04 00:41:24 +0800918 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200919 env["SSL_CERT_DIR"] = CAPATH
920 env["SSL_CERT_FILE"] = CERTFILE
921 paths = ssl.get_default_verify_paths()
922 self.assertEqual(paths.cafile, CERTFILE)
923 self.assertEqual(paths.capath, CAPATH)
924
Christian Heimes44109d72013-11-22 01:51:30 +0100925 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
926 def test_enum_certificates(self):
927 self.assertTrue(ssl.enum_certificates("CA"))
928 self.assertTrue(ssl.enum_certificates("ROOT"))
929
930 self.assertRaises(TypeError, ssl.enum_certificates)
931 self.assertRaises(WindowsError, ssl.enum_certificates, "")
932
Christian Heimesc2d65e12013-11-22 16:13:55 +0100933 trust_oids = set()
934 for storename in ("CA", "ROOT"):
935 store = ssl.enum_certificates(storename)
936 self.assertIsInstance(store, list)
937 for element in store:
938 self.assertIsInstance(element, tuple)
939 self.assertEqual(len(element), 3)
940 cert, enc, trust = element
941 self.assertIsInstance(cert, bytes)
942 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200943 self.assertIsInstance(trust, (frozenset, set, bool))
944 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100945 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100946
947 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100948 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200949
Christian Heimes46bebee2013-06-09 19:03:31 +0200950 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100951 def test_enum_crls(self):
952 self.assertTrue(ssl.enum_crls("CA"))
953 self.assertRaises(TypeError, ssl.enum_crls)
954 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200955
Christian Heimes44109d72013-11-22 01:51:30 +0100956 crls = ssl.enum_crls("CA")
957 self.assertIsInstance(crls, list)
958 for element in crls:
959 self.assertIsInstance(element, tuple)
960 self.assertEqual(len(element), 2)
961 self.assertIsInstance(element[0], bytes)
962 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200963
Christian Heimes46bebee2013-06-09 19:03:31 +0200964
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100965 def test_asn1object(self):
966 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
967 '1.3.6.1.5.5.7.3.1')
968
969 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
970 self.assertEqual(val, expected)
971 self.assertEqual(val.nid, 129)
972 self.assertEqual(val.shortname, 'serverAuth')
973 self.assertEqual(val.longname, 'TLS Web Server Authentication')
974 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
975 self.assertIsInstance(val, ssl._ASN1Object)
976 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
977
978 val = ssl._ASN1Object.fromnid(129)
979 self.assertEqual(val, expected)
980 self.assertIsInstance(val, ssl._ASN1Object)
981 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100982 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
983 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100984 for i in range(1000):
985 try:
986 obj = ssl._ASN1Object.fromnid(i)
987 except ValueError:
988 pass
989 else:
990 self.assertIsInstance(obj.nid, int)
991 self.assertIsInstance(obj.shortname, str)
992 self.assertIsInstance(obj.longname, str)
993 self.assertIsInstance(obj.oid, (str, type(None)))
994
995 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
996 self.assertEqual(val, expected)
997 self.assertIsInstance(val, ssl._ASN1Object)
998 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
999 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
1000 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +01001001 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
1002 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001003
Christian Heimes72d28502013-11-23 13:56:58 +01001004 def test_purpose_enum(self):
1005 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
1006 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
1007 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
1008 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
1009 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
1010 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
1011 '1.3.6.1.5.5.7.3.1')
1012
1013 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
1014 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
1015 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
1016 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
1017 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
1018 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
1019 '1.3.6.1.5.5.7.3.2')
1020
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001021 def test_unsupported_dtls(self):
1022 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1023 self.addCleanup(s.close)
1024 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +02001025 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001026 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +02001027 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001028 with self.assertRaises(NotImplementedError) as cx:
1029 ctx.wrap_socket(s)
1030 self.assertEqual(str(cx.exception), "only stream sockets are supported")
1031
Antoine Pitrouc695c952014-04-28 20:57:36 +02001032 def cert_time_ok(self, timestring, timestamp):
1033 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
1034
1035 def cert_time_fail(self, timestring):
1036 with self.assertRaises(ValueError):
1037 ssl.cert_time_to_seconds(timestring)
1038
1039 @unittest.skipUnless(utc_offset(),
1040 'local time needs to be different from UTC')
1041 def test_cert_time_to_seconds_timezone(self):
1042 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
1043 # results if local timezone is not UTC
1044 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
1045 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
1046
1047 def test_cert_time_to_seconds(self):
1048 timestring = "Jan 5 09:34:43 2018 GMT"
1049 ts = 1515144883.0
1050 self.cert_time_ok(timestring, ts)
1051 # accept keyword parameter, assert its name
1052 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
1053 # accept both %e and %d (space or zero generated by strftime)
1054 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
1055 # case-insensitive
1056 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
1057 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
1058 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1059 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1060 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1061 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1062 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1063 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1064
1065 newyear_ts = 1230768000.0
1066 # leap seconds
1067 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1068 # same timestamp
1069 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1070
1071 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1072 # allow 60th second (even if it is not a leap second)
1073 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1074 # allow 2nd leap second for compatibility with time.strptime()
1075 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1076 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1077
Mike53f7a7c2017-12-14 14:04:53 +03001078 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001079 # 99991231235959Z (rfc 5280)
1080 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1081
1082 @support.run_with_locale('LC_ALL', '')
1083 def test_cert_time_to_seconds_locale(self):
1084 # `cert_time_to_seconds()` should be locale independent
1085
1086 def local_february_name():
1087 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1088
1089 if local_february_name().lower() == 'feb':
1090 self.skipTest("locale-specific month name needs to be "
1091 "different from C locale")
1092
1093 # locale-independent
1094 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1095 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1096
Martin Panter3840b2a2016-03-27 01:53:46 +00001097 def test_connect_ex_error(self):
1098 server = socket.socket(socket.AF_INET)
1099 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001100 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001101 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001102 cert_reqs=ssl.CERT_REQUIRED)
1103 self.addCleanup(s.close)
1104 rc = s.connect_ex((HOST, port))
1105 # Issue #19919: Windows machines or VMs hosted on Windows
1106 # machines sometimes return EWOULDBLOCK.
1107 errors = (
1108 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1109 errno.EWOULDBLOCK,
1110 )
1111 self.assertIn(rc, errors)
1112
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001113
Antoine Pitrou152efa22010-05-16 18:19:27 +00001114class ContextTests(unittest.TestCase):
1115
1116 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001117 for protocol in PROTOCOLS:
1118 ssl.SSLContext(protocol)
Christian Heimes598894f2016-09-05 23:19:05 +02001119 ctx = ssl.SSLContext()
1120 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001121 self.assertRaises(ValueError, ssl.SSLContext, -1)
1122 self.assertRaises(ValueError, ssl.SSLContext, 42)
1123
1124 def test_protocol(self):
1125 for proto in PROTOCOLS:
1126 ctx = ssl.SSLContext(proto)
1127 self.assertEqual(ctx.protocol, proto)
1128
1129 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001130 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001131 ctx.set_ciphers("ALL")
1132 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001133 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001134 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001135
Christian Heimes892d66e2018-01-29 14:10:18 +01001136 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1137 "Test applies only to Python default ciphers")
1138 def test_python_ciphers(self):
1139 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1140 ciphers = ctx.get_ciphers()
1141 for suite in ciphers:
1142 name = suite['name']
1143 self.assertNotIn("PSK", name)
1144 self.assertNotIn("SRP", name)
1145 self.assertNotIn("MD5", name)
1146 self.assertNotIn("RC4", name)
1147 self.assertNotIn("3DES", name)
1148
Christian Heimes25bfcd52016-09-06 00:04:45 +02001149 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001150 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001151 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001152 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001153 self.assertIn('AES256-GCM-SHA384', names)
1154 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001155
Antoine Pitroub5218772010-05-21 09:56:06 +00001156 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001157 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001158 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001159 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001160 # SSLContext also enables these by default
1161 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001162 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001163 OP_ENABLE_MIDDLEBOX_COMPAT |
1164 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001165 self.assertEqual(default, ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001166 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001167 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Christian Heimes39258d32021-04-17 11:36:35 +02001168 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
1169 self.assertEqual(default, ctx.options)
1170 ctx.options = 0
1171 # Ubuntu has OP_NO_SSLv3 forced on by default
1172 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001173
Christian Heimesa170fa12017-09-15 20:27:30 +02001174 def test_verify_mode_protocol(self):
1175 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001176 # Default value
1177 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1178 ctx.verify_mode = ssl.CERT_OPTIONAL
1179 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1180 ctx.verify_mode = ssl.CERT_REQUIRED
1181 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1182 ctx.verify_mode = ssl.CERT_NONE
1183 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1184 with self.assertRaises(TypeError):
1185 ctx.verify_mode = None
1186 with self.assertRaises(ValueError):
1187 ctx.verify_mode = 42
1188
Christian Heimesa170fa12017-09-15 20:27:30 +02001189 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1190 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1191 self.assertFalse(ctx.check_hostname)
1192
1193 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1194 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1195 self.assertTrue(ctx.check_hostname)
1196
Christian Heimes61d478c2018-01-27 15:51:38 +01001197 def test_hostname_checks_common_name(self):
1198 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1199 self.assertTrue(ctx.hostname_checks_common_name)
1200 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1201 ctx.hostname_checks_common_name = True
1202 self.assertTrue(ctx.hostname_checks_common_name)
1203 ctx.hostname_checks_common_name = False
1204 self.assertFalse(ctx.hostname_checks_common_name)
1205 ctx.hostname_checks_common_name = True
1206 self.assertTrue(ctx.hostname_checks_common_name)
1207 else:
1208 with self.assertRaises(AttributeError):
1209 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001210
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001211 @requires_minimum_version
Christian Heimesc9bc49c2019-09-11 19:24:47 +02001212 @unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
Christian Heimes698dde12018-02-27 11:54:43 +01001213 def test_min_max_version(self):
1214 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001215 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1216 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001217 minimum_range = {
1218 # stock OpenSSL
1219 ssl.TLSVersion.MINIMUM_SUPPORTED,
1220 # Fedora 29 uses TLS 1.0 by default
1221 ssl.TLSVersion.TLSv1,
1222 # RHEL 8 uses TLS 1.2 by default
1223 ssl.TLSVersion.TLSv1_2
1224 }
torsava34864d12019-12-02 17:15:42 +01001225 maximum_range = {
1226 # stock OpenSSL
1227 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1228 # Fedora 32 uses TLS 1.3 by default
1229 ssl.TLSVersion.TLSv1_3
1230 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001231
Christian Heimes34de2d32019-01-18 16:09:30 +01001232 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001233 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001234 )
torsava34864d12019-12-02 17:15:42 +01001235 self.assertIn(
1236 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001237 )
1238
1239 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1240 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1241 self.assertEqual(
1242 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1243 )
1244 self.assertEqual(
1245 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1246 )
1247
1248 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1249 ctx.maximum_version = ssl.TLSVersion.TLSv1
1250 self.assertEqual(
1251 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1252 )
1253 self.assertEqual(
1254 ctx.maximum_version, ssl.TLSVersion.TLSv1
1255 )
1256
1257 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1258 self.assertEqual(
1259 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1260 )
1261
1262 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1263 self.assertIn(
1264 ctx.maximum_version,
1265 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1266 )
1267
1268 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1269 self.assertIn(
1270 ctx.minimum_version,
1271 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1272 )
1273
1274 with self.assertRaises(ValueError):
1275 ctx.minimum_version = 42
1276
1277 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1278
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001279 self.assertIn(
1280 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001281 )
1282 self.assertEqual(
1283 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1284 )
1285 with self.assertRaises(ValueError):
1286 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1287 with self.assertRaises(ValueError):
1288 ctx.maximum_version = ssl.TLSVersion.TLSv1
1289
1290
matthewhughes9348e836bb2020-07-17 09:59:15 +01001291 @unittest.skipUnless(
1292 hasattr(ssl.SSLContext, 'security_level'),
1293 "requires OpenSSL >= 1.1.0"
1294 )
1295 def test_security_level(self):
1296 ctx = ssl.SSLContext()
1297 # The default security callback allows for levels between 0-5
1298 # with OpenSSL defaulting to 1, however some vendors override the
1299 # default value (e.g. Debian defaults to 2)
1300 security_level_range = {
1301 0,
1302 1, # OpenSSL default
1303 2, # Debian
1304 3,
1305 4,
1306 5,
1307 }
1308 self.assertIn(ctx.security_level, security_level_range)
1309
Christian Heimes22587792013-11-21 23:56:13 +01001310 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001311 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001312 # default value
1313 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1314 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001315 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1316 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1317 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1318 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1319 ctx.verify_flags = ssl.VERIFY_DEFAULT
1320 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001321 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1322 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001323 # supports any value
1324 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1325 self.assertEqual(ctx.verify_flags,
1326 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1327 with self.assertRaises(TypeError):
1328 ctx.verify_flags = None
1329
Antoine Pitrou152efa22010-05-16 18:19:27 +00001330 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001331 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001332 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001333 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001334 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1335 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001336 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001337 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001338 self.assertEqual(cm.exception.errno, errno.ENOENT)
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(BADCERT)
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(EMPTYCERT)
1343 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001344 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001345 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1346 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1347 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001348 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001349 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001350 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001351 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001352 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001353 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1354 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001355 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001356 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001357 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001358 # Password protected key and cert
1359 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1360 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1361 ctx.load_cert_chain(CERTFILE_PROTECTED,
1362 password=bytearray(KEY_PASSWORD.encode()))
1363 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1364 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1365 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1366 bytearray(KEY_PASSWORD.encode()))
1367 with self.assertRaisesRegex(TypeError, "should be a string"):
1368 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1369 with self.assertRaises(ssl.SSLError):
1370 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1371 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1372 # openssl has a fixed limit on the password buffer.
1373 # PEM_BUFSIZE is generally set to 1kb.
1374 # Return a string larger than this.
1375 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1376 # Password callback
1377 def getpass_unicode():
1378 return KEY_PASSWORD
1379 def getpass_bytes():
1380 return KEY_PASSWORD.encode()
1381 def getpass_bytearray():
1382 return bytearray(KEY_PASSWORD.encode())
1383 def getpass_badpass():
1384 return "badpass"
1385 def getpass_huge():
1386 return b'a' * (1024 * 1024)
1387 def getpass_bad_type():
1388 return 9
1389 def getpass_exception():
1390 raise Exception('getpass error')
1391 class GetPassCallable:
1392 def __call__(self):
1393 return KEY_PASSWORD
1394 def getpass(self):
1395 return KEY_PASSWORD
1396 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1397 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1398 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1399 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1400 ctx.load_cert_chain(CERTFILE_PROTECTED,
1401 password=GetPassCallable().getpass)
1402 with self.assertRaises(ssl.SSLError):
1403 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1404 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1405 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1406 with self.assertRaisesRegex(TypeError, "must return a string"):
1407 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1408 with self.assertRaisesRegex(Exception, "getpass error"):
1409 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1410 # Make sure the password function isn't called if it isn't needed
1411 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001412
1413 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001414 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001415 ctx.load_verify_locations(CERTFILE)
1416 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1417 ctx.load_verify_locations(BYTES_CERTFILE)
1418 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1419 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001420 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001421 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001422 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001423 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001424 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001425 ctx.load_verify_locations(BADCERT)
1426 ctx.load_verify_locations(CERTFILE, CAPATH)
1427 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1428
Victor Stinner80f75e62011-01-29 11:31:20 +00001429 # Issue #10989: crash if the second argument type is invalid
1430 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1431
Christian Heimesefff7062013-11-21 03:35:02 +01001432 def test_load_verify_cadata(self):
1433 # test cadata
1434 with open(CAFILE_CACERT) as f:
1435 cacert_pem = f.read()
1436 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1437 with open(CAFILE_NEURONIO) as f:
1438 neuronio_pem = f.read()
1439 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1440
1441 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001442 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001443 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1444 ctx.load_verify_locations(cadata=cacert_pem)
1445 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1446 ctx.load_verify_locations(cadata=neuronio_pem)
1447 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1448 # cert already in hash table
1449 ctx.load_verify_locations(cadata=neuronio_pem)
1450 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1451
1452 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001453 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001454 combined = "\n".join((cacert_pem, neuronio_pem))
1455 ctx.load_verify_locations(cadata=combined)
1456 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1457
1458 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001459 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001460 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1461 neuronio_pem, "tail"]
1462 ctx.load_verify_locations(cadata="\n".join(combined))
1463 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1464
1465 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001466 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001467 ctx.load_verify_locations(cadata=cacert_der)
1468 ctx.load_verify_locations(cadata=neuronio_der)
1469 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1470 # cert already in hash table
1471 ctx.load_verify_locations(cadata=cacert_der)
1472 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1473
1474 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001475 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001476 combined = b"".join((cacert_der, neuronio_der))
1477 ctx.load_verify_locations(cadata=combined)
1478 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1479
1480 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001481 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001482 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1483
1484 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1485 ctx.load_verify_locations(cadata="broken")
1486 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1487 ctx.load_verify_locations(cadata=b"broken")
1488
1489
Paul Monsonf3550692019-06-19 13:09:54 -07001490 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001491 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001492 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001493 ctx.load_dh_params(DHFILE)
1494 if os.name != 'nt':
1495 ctx.load_dh_params(BYTES_DHFILE)
1496 self.assertRaises(TypeError, ctx.load_dh_params)
1497 self.assertRaises(TypeError, ctx.load_dh_params, None)
1498 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001499 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001500 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001501 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001502 ctx.load_dh_params(CERTFILE)
1503
Antoine Pitroub0182c82010-10-12 20:09:02 +00001504 def test_session_stats(self):
1505 for proto in PROTOCOLS:
1506 ctx = ssl.SSLContext(proto)
1507 self.assertEqual(ctx.session_stats(), {
1508 'number': 0,
1509 'connect': 0,
1510 'connect_good': 0,
1511 'connect_renegotiate': 0,
1512 'accept': 0,
1513 'accept_good': 0,
1514 'accept_renegotiate': 0,
1515 'hits': 0,
1516 'misses': 0,
1517 'timeouts': 0,
1518 'cache_full': 0,
1519 })
1520
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001521 def test_set_default_verify_paths(self):
1522 # There's not much we can do to test that it acts as expected,
1523 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001524 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001525 ctx.set_default_verify_paths()
1526
Antoine Pitrou501da612011-12-21 09:27:41 +01001527 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001528 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001529 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001530 ctx.set_ecdh_curve("prime256v1")
1531 ctx.set_ecdh_curve(b"prime256v1")
1532 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1533 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1534 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1535 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1536
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001537 @needs_sni
1538 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001539 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001540
1541 # set_servername_callback expects a callable, or None
1542 self.assertRaises(TypeError, ctx.set_servername_callback)
1543 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1544 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1545 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1546
1547 def dummycallback(sock, servername, ctx):
1548 pass
1549 ctx.set_servername_callback(None)
1550 ctx.set_servername_callback(dummycallback)
1551
1552 @needs_sni
1553 def test_sni_callback_refcycle(self):
1554 # Reference cycles through the servername callback are detected
1555 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001556 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001557 def dummycallback(sock, servername, ctx, cycle=ctx):
1558 pass
1559 ctx.set_servername_callback(dummycallback)
1560 wr = weakref.ref(ctx)
1561 del ctx, dummycallback
1562 gc.collect()
1563 self.assertIs(wr(), None)
1564
Christian Heimes9a5395a2013-06-17 15:44:12 +02001565 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001566 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001567 self.assertEqual(ctx.cert_store_stats(),
1568 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1569 ctx.load_cert_chain(CERTFILE)
1570 self.assertEqual(ctx.cert_store_stats(),
1571 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1572 ctx.load_verify_locations(CERTFILE)
1573 self.assertEqual(ctx.cert_store_stats(),
1574 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001575 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001576 self.assertEqual(ctx.cert_store_stats(),
1577 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1578
1579 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001580 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001581 self.assertEqual(ctx.get_ca_certs(), [])
1582 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1583 ctx.load_verify_locations(CERTFILE)
1584 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001585 # but CAFILE_CACERT is a CA cert
1586 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001587 self.assertEqual(ctx.get_ca_certs(),
1588 [{'issuer': ((('organizationName', 'Root CA'),),
1589 (('organizationalUnitName', 'http://www.cacert.org'),),
1590 (('commonName', 'CA Cert Signing Authority'),),
1591 (('emailAddress', 'support@cacert.org'),)),
1592 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1593 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1594 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001595 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001596 'subject': ((('organizationName', 'Root CA'),),
1597 (('organizationalUnitName', 'http://www.cacert.org'),),
1598 (('commonName', 'CA Cert Signing Authority'),),
1599 (('emailAddress', 'support@cacert.org'),)),
1600 'version': 3}])
1601
Martin Panterb55f8b72016-01-14 12:53:56 +00001602 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001603 pem = f.read()
1604 der = ssl.PEM_cert_to_DER_cert(pem)
1605 self.assertEqual(ctx.get_ca_certs(True), [der])
1606
Christian Heimes72d28502013-11-23 13:56:58 +01001607 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001608 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001609 ctx.load_default_certs()
1610
Christian Heimesa170fa12017-09-15 20:27:30 +02001611 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001612 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1613 ctx.load_default_certs()
1614
Christian Heimesa170fa12017-09-15 20:27:30 +02001615 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001616 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1617
Christian Heimesa170fa12017-09-15 20:27:30 +02001618 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001619 self.assertRaises(TypeError, ctx.load_default_certs, None)
1620 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1621
Benjamin Peterson91244e02014-10-03 18:17:15 -04001622 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimes598894f2016-09-05 23:19:05 +02001623 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001624 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001625 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001626 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001627 env["SSL_CERT_DIR"] = CAPATH
1628 env["SSL_CERT_FILE"] = CERTFILE
1629 ctx.load_default_certs()
1630 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1631
Benjamin Peterson91244e02014-10-03 18:17:15 -04001632 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001633 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001634 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001635 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001636 ctx.load_default_certs()
1637 stats = ctx.cert_store_stats()
1638
Christian Heimesa170fa12017-09-15 20:27:30 +02001639 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001640 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001641 env["SSL_CERT_DIR"] = CAPATH
1642 env["SSL_CERT_FILE"] = CERTFILE
1643 ctx.load_default_certs()
1644 stats["x509"] += 1
1645 self.assertEqual(ctx.cert_store_stats(), stats)
1646
Christian Heimes358cfd42016-09-10 22:43:48 +02001647 def _assert_context_options(self, ctx):
1648 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1649 if OP_NO_COMPRESSION != 0:
1650 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1651 OP_NO_COMPRESSION)
1652 if OP_SINGLE_DH_USE != 0:
1653 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1654 OP_SINGLE_DH_USE)
1655 if OP_SINGLE_ECDH_USE != 0:
1656 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1657 OP_SINGLE_ECDH_USE)
1658 if OP_CIPHER_SERVER_PREFERENCE != 0:
1659 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1660 OP_CIPHER_SERVER_PREFERENCE)
1661
Christian Heimes4c05b472013-11-23 15:58:30 +01001662 def test_create_default_context(self):
1663 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001664
Christian Heimesa170fa12017-09-15 20:27:30 +02001665 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001666 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001667 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001668 self._assert_context_options(ctx)
1669
Christian Heimes4c05b472013-11-23 15:58:30 +01001670 with open(SIGNING_CA) as f:
1671 cadata = f.read()
1672 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1673 cadata=cadata)
Christian Heimesa170fa12017-09-15 20:27:30 +02001674 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001675 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001676 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001677
1678 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001679 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001680 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001681 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001682
Christian Heimes67986f92013-11-23 22:43:47 +01001683 def test__create_stdlib_context(self):
1684 ctx = ssl._create_stdlib_context()
Christian Heimesa170fa12017-09-15 20:27:30 +02001685 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001686 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001687 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001688 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001689
1690 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1691 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1692 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001693 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001694
1695 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001696 cert_reqs=ssl.CERT_REQUIRED,
1697 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001698 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1699 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001700 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001701 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001702
1703 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001704 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001705 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001706 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001707
Christian Heimes1aa9a752013-12-02 02:41:19 +01001708 def test_check_hostname(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001709 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001710 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001711 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001712
Christian Heimese82c0342017-09-15 20:29:57 +02001713 # Auto set CERT_REQUIRED
1714 ctx.check_hostname = True
1715 self.assertTrue(ctx.check_hostname)
1716 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1717 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001718 ctx.verify_mode = ssl.CERT_REQUIRED
1719 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001720 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001721
Christian Heimese82c0342017-09-15 20:29:57 +02001722 # Changing verify_mode does not affect check_hostname
1723 ctx.check_hostname = False
1724 ctx.verify_mode = ssl.CERT_NONE
1725 ctx.check_hostname = False
1726 self.assertFalse(ctx.check_hostname)
1727 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1728 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001729 ctx.check_hostname = True
1730 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001731 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1732
1733 ctx.check_hostname = False
1734 ctx.verify_mode = ssl.CERT_OPTIONAL
1735 ctx.check_hostname = False
1736 self.assertFalse(ctx.check_hostname)
1737 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1738 # keep CERT_OPTIONAL
1739 ctx.check_hostname = True
1740 self.assertTrue(ctx.check_hostname)
1741 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001742
1743 # Cannot set CERT_NONE with check_hostname enabled
1744 with self.assertRaises(ValueError):
1745 ctx.verify_mode = ssl.CERT_NONE
1746 ctx.check_hostname = False
1747 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001748 ctx.verify_mode = ssl.CERT_NONE
1749 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001750
Christian Heimes5fe668c2016-09-12 00:01:11 +02001751 def test_context_client_server(self):
1752 # PROTOCOL_TLS_CLIENT has sane defaults
1753 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1754 self.assertTrue(ctx.check_hostname)
1755 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1756
1757 # PROTOCOL_TLS_SERVER has different but also sane defaults
1758 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1759 self.assertFalse(ctx.check_hostname)
1760 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1761
Christian Heimes4df60f12017-09-15 20:26:05 +02001762 def test_context_custom_class(self):
1763 class MySSLSocket(ssl.SSLSocket):
1764 pass
1765
1766 class MySSLObject(ssl.SSLObject):
1767 pass
1768
1769 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1770 ctx.sslsocket_class = MySSLSocket
1771 ctx.sslobject_class = MySSLObject
1772
1773 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1774 self.assertIsInstance(sock, MySSLSocket)
1775 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1776 self.assertIsInstance(obj, MySSLObject)
1777
Christian Heimes78c7d522019-06-03 21:00:10 +02001778 def test_num_tickest(self):
1779 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1780 self.assertEqual(ctx.num_tickets, 2)
1781 ctx.num_tickets = 1
1782 self.assertEqual(ctx.num_tickets, 1)
1783 ctx.num_tickets = 0
1784 self.assertEqual(ctx.num_tickets, 0)
1785 with self.assertRaises(ValueError):
1786 ctx.num_tickets = -1
1787 with self.assertRaises(TypeError):
1788 ctx.num_tickets = None
1789
1790 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1791 self.assertEqual(ctx.num_tickets, 2)
1792 with self.assertRaises(ValueError):
1793 ctx.num_tickets = 1
1794
Antoine Pitrou152efa22010-05-16 18:19:27 +00001795
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001796class SSLErrorTests(unittest.TestCase):
1797
1798 def test_str(self):
1799 # The str() of a SSLError doesn't include the errno
1800 e = ssl.SSLError(1, "foo")
1801 self.assertEqual(str(e), "foo")
1802 self.assertEqual(e.errno, 1)
1803 # Same for a subclass
1804 e = ssl.SSLZeroReturnError(1, "foo")
1805 self.assertEqual(str(e), "foo")
1806 self.assertEqual(e.errno, 1)
1807
Paul Monsonf3550692019-06-19 13:09:54 -07001808 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001809 def test_lib_reason(self):
1810 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001811 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001812 with self.assertRaises(ssl.SSLError) as cm:
1813 ctx.load_dh_params(CERTFILE)
1814 self.assertEqual(cm.exception.library, 'PEM')
1815 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1816 s = str(cm.exception)
1817 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1818
1819 def test_subclass(self):
1820 # Check that the appropriate SSLError subclass is raised
1821 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001822 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1823 ctx.check_hostname = False
1824 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001825 with socket.create_server(("127.0.0.1", 0)) as s:
1826 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001827 c.setblocking(False)
1828 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001829 with self.assertRaises(ssl.SSLWantReadError) as cm:
1830 c.do_handshake()
1831 s = str(cm.exception)
1832 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1833 # For compatibility
1834 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1835
1836
Christian Heimes61d478c2018-01-27 15:51:38 +01001837 def test_bad_server_hostname(self):
1838 ctx = ssl.create_default_context()
1839 with self.assertRaises(ValueError):
1840 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1841 server_hostname="")
1842 with self.assertRaises(ValueError):
1843 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1844 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001845 with self.assertRaises(TypeError):
1846 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1847 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001848
1849
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001850class MemoryBIOTests(unittest.TestCase):
1851
1852 def test_read_write(self):
1853 bio = ssl.MemoryBIO()
1854 bio.write(b'foo')
1855 self.assertEqual(bio.read(), b'foo')
1856 self.assertEqual(bio.read(), b'')
1857 bio.write(b'foo')
1858 bio.write(b'bar')
1859 self.assertEqual(bio.read(), b'foobar')
1860 self.assertEqual(bio.read(), b'')
1861 bio.write(b'baz')
1862 self.assertEqual(bio.read(2), b'ba')
1863 self.assertEqual(bio.read(1), b'z')
1864 self.assertEqual(bio.read(1), b'')
1865
1866 def test_eof(self):
1867 bio = ssl.MemoryBIO()
1868 self.assertFalse(bio.eof)
1869 self.assertEqual(bio.read(), b'')
1870 self.assertFalse(bio.eof)
1871 bio.write(b'foo')
1872 self.assertFalse(bio.eof)
1873 bio.write_eof()
1874 self.assertFalse(bio.eof)
1875 self.assertEqual(bio.read(2), b'fo')
1876 self.assertFalse(bio.eof)
1877 self.assertEqual(bio.read(1), b'o')
1878 self.assertTrue(bio.eof)
1879 self.assertEqual(bio.read(), b'')
1880 self.assertTrue(bio.eof)
1881
1882 def test_pending(self):
1883 bio = ssl.MemoryBIO()
1884 self.assertEqual(bio.pending, 0)
1885 bio.write(b'foo')
1886 self.assertEqual(bio.pending, 3)
1887 for i in range(3):
1888 bio.read(1)
1889 self.assertEqual(bio.pending, 3-i-1)
1890 for i in range(3):
1891 bio.write(b'x')
1892 self.assertEqual(bio.pending, i+1)
1893 bio.read()
1894 self.assertEqual(bio.pending, 0)
1895
1896 def test_buffer_types(self):
1897 bio = ssl.MemoryBIO()
1898 bio.write(b'foo')
1899 self.assertEqual(bio.read(), b'foo')
1900 bio.write(bytearray(b'bar'))
1901 self.assertEqual(bio.read(), b'bar')
1902 bio.write(memoryview(b'baz'))
1903 self.assertEqual(bio.read(), b'baz')
1904
1905 def test_error_types(self):
1906 bio = ssl.MemoryBIO()
1907 self.assertRaises(TypeError, bio.write, 'foo')
1908 self.assertRaises(TypeError, bio.write, None)
1909 self.assertRaises(TypeError, bio.write, True)
1910 self.assertRaises(TypeError, bio.write, 1)
1911
1912
Christian Heimes9d50ab52018-02-27 10:17:30 +01001913class SSLObjectTests(unittest.TestCase):
1914 def test_private_init(self):
1915 bio = ssl.MemoryBIO()
1916 with self.assertRaisesRegex(TypeError, "public constructor"):
1917 ssl.SSLObject(bio, bio)
1918
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001919 def test_unwrap(self):
1920 client_ctx, server_ctx, hostname = testing_context()
1921 c_in = ssl.MemoryBIO()
1922 c_out = ssl.MemoryBIO()
1923 s_in = ssl.MemoryBIO()
1924 s_out = ssl.MemoryBIO()
1925 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1926 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1927
1928 # Loop on the handshake for a bit to get it settled
1929 for _ in range(5):
1930 try:
1931 client.do_handshake()
1932 except ssl.SSLWantReadError:
1933 pass
1934 if c_out.pending:
1935 s_in.write(c_out.read())
1936 try:
1937 server.do_handshake()
1938 except ssl.SSLWantReadError:
1939 pass
1940 if s_out.pending:
1941 c_in.write(s_out.read())
1942 # Now the handshakes should be complete (don't raise WantReadError)
1943 client.do_handshake()
1944 server.do_handshake()
1945
1946 # Now if we unwrap one side unilaterally, it should send close-notify
1947 # and raise WantReadError:
1948 with self.assertRaises(ssl.SSLWantReadError):
1949 client.unwrap()
1950
1951 # But server.unwrap() does not raise, because it reads the client's
1952 # close-notify:
1953 s_in.write(c_out.read())
1954 server.unwrap()
1955
1956 # And now that the client gets the server's close-notify, it doesn't
1957 # raise either.
1958 c_in.write(s_out.read())
1959 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001960
Martin Panter3840b2a2016-03-27 01:53:46 +00001961class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001962 """Tests that connect to a simple server running in the background"""
1963
1964 def setUp(self):
1965 server = ThreadedEchoServer(SIGNED_CERTFILE)
1966 self.server_addr = (HOST, server.port)
1967 server.__enter__()
1968 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001969
Antoine Pitrou480a1242010-04-28 21:37:09 +00001970 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001971 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001972 cert_reqs=ssl.CERT_NONE) as s:
1973 s.connect(self.server_addr)
1974 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001975 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001976
Martin Panter3840b2a2016-03-27 01:53:46 +00001977 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001978 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001979 cert_reqs=ssl.CERT_REQUIRED,
1980 ca_certs=SIGNING_CA) as s:
1981 s.connect(self.server_addr)
1982 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001983 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001984
Martin Panter3840b2a2016-03-27 01:53:46 +00001985 def test_connect_fail(self):
1986 # This should fail because we have no verification certs. Connection
1987 # failure crashes ThreadedEchoServer, so run this in an independent
1988 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001989 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001990 cert_reqs=ssl.CERT_REQUIRED)
1991 self.addCleanup(s.close)
1992 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1993 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001994
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001995 def test_connect_ex(self):
1996 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02001997 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001998 cert_reqs=ssl.CERT_REQUIRED,
1999 ca_certs=SIGNING_CA)
2000 self.addCleanup(s.close)
2001 self.assertEqual(0, s.connect_ex(self.server_addr))
2002 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002003
2004 def test_non_blocking_connect_ex(self):
2005 # Issue #11326: non-blocking connect_ex() should allow handshake
2006 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02002007 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002008 cert_reqs=ssl.CERT_REQUIRED,
2009 ca_certs=SIGNING_CA,
2010 do_handshake_on_connect=False)
2011 self.addCleanup(s.close)
2012 s.setblocking(False)
2013 rc = s.connect_ex(self.server_addr)
2014 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2015 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2016 # Wait for connect to finish
2017 select.select([], [s], [], 5.0)
2018 # Non-blocking handshake
2019 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002020 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002021 s.do_handshake()
2022 break
2023 except ssl.SSLWantReadError:
2024 select.select([s], [], [], 5.0)
2025 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002026 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002027 # SSL established
2028 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002029
Antoine Pitrou152efa22010-05-16 18:19:27 +00002030 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002031 # Same as test_connect, but with a separately created context
Christian Heimesa170fa12017-09-15 20:27:30 +02002032 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
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 Heimesa170fa12017-09-15 20:27:30 +02002052 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002053 ctx.verify_mode = ssl.CERT_REQUIRED
2054 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
2055 self.addCleanup(s.close)
2056 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2057 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002058
2059 def test_connect_capath(self):
2060 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002061 # NOTE: the subject hashing algorithm has been changed between
2062 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2063 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002064 # filename) for this test to be portable across OpenSSL releases.
Christian Heimesa170fa12017-09-15 20:27:30 +02002065 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002066 ctx.verify_mode = ssl.CERT_REQUIRED
2067 ctx.load_verify_locations(capath=CAPATH)
2068 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2069 s.connect(self.server_addr)
2070 cert = s.getpeercert()
2071 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002072
Martin Panter3840b2a2016-03-27 01:53:46 +00002073 # Same with a bytes `capath` argument
Christian Heimesa170fa12017-09-15 20:27:30 +02002074 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002075 ctx.verify_mode = ssl.CERT_REQUIRED
2076 ctx.load_verify_locations(capath=BYTES_CAPATH)
2077 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2078 s.connect(self.server_addr)
2079 cert = s.getpeercert()
2080 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002081
Christian Heimesefff7062013-11-21 03:35:02 +01002082 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002083 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002084 pem = f.read()
2085 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimesa170fa12017-09-15 20:27:30 +02002086 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002087 ctx.verify_mode = ssl.CERT_REQUIRED
2088 ctx.load_verify_locations(cadata=pem)
2089 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2090 s.connect(self.server_addr)
2091 cert = s.getpeercert()
2092 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002093
Martin Panter3840b2a2016-03-27 01:53:46 +00002094 # same with DER
Christian Heimesa170fa12017-09-15 20:27:30 +02002095 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002096 ctx.verify_mode = ssl.CERT_REQUIRED
2097 ctx.load_verify_locations(cadata=der)
2098 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2099 s.connect(self.server_addr)
2100 cert = s.getpeercert()
2101 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002102
Antoine Pitroue3220242010-04-24 11:13:53 +00002103 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2104 def test_makefile_close(self):
2105 # Issue #5238: creating a file-like object with makefile() shouldn't
2106 # delay closing the underlying "real socket" (here tested with its
2107 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002108 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002109 ss.connect(self.server_addr)
2110 fd = ss.fileno()
2111 f = ss.makefile()
2112 f.close()
2113 # The fd is still open
2114 os.read(fd, 0)
2115 # Closing the SSL socket should close the fd too
2116 ss.close()
2117 gc.collect()
2118 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002119 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002120 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002121
Antoine Pitrou480a1242010-04-28 21:37:09 +00002122 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002123 s = socket.socket(socket.AF_INET)
2124 s.connect(self.server_addr)
2125 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002126 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002127 cert_reqs=ssl.CERT_NONE,
2128 do_handshake_on_connect=False)
2129 self.addCleanup(s.close)
2130 count = 0
2131 while True:
2132 try:
2133 count += 1
2134 s.do_handshake()
2135 break
2136 except ssl.SSLWantReadError:
2137 select.select([s], [], [])
2138 except ssl.SSLWantWriteError:
2139 select.select([], [s], [])
2140 if support.verbose:
2141 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002142
Antoine Pitrou480a1242010-04-28 21:37:09 +00002143 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002144 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002145
Martin Panter3840b2a2016-03-27 01:53:46 +00002146 def test_get_server_certificate_fail(self):
2147 # Connection failure crashes ThreadedEchoServer, so run this in an
2148 # independent test method
2149 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002150
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002151 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002152 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002153 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2154 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002155 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002156 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2157 s.connect(self.server_addr)
2158 # Error checking can happen at instantiation or when connecting
2159 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2160 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002161 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002162 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2163 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002164
Christian Heimes9a5395a2013-06-17 15:44:12 +02002165 def test_get_ca_certs_capath(self):
2166 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002167 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002168 ctx.load_verify_locations(capath=CAPATH)
2169 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002170 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2171 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002172 s.connect(self.server_addr)
2173 cert = s.getpeercert()
2174 self.assertTrue(cert)
2175 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002176
Christian Heimes575596e2013-12-15 21:49:17 +01002177 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01002178 def test_context_setget(self):
2179 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002180 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2181 ctx1.load_verify_locations(capath=CAPATH)
2182 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2183 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002184 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002185 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002186 ss.connect(self.server_addr)
2187 self.assertIs(ss.context, ctx1)
2188 self.assertIs(ss._sslobj.context, ctx1)
2189 ss.context = ctx2
2190 self.assertIs(ss.context, ctx2)
2191 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002192
2193 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2194 # A simple IO loop. Call func(*args) depending on the error we get
2195 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002196 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002197 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002198 count = 0
2199 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002200 if time.monotonic() > deadline:
2201 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002202 errno = None
2203 count += 1
2204 try:
2205 ret = func(*args)
2206 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002207 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002208 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002209 raise
2210 errno = e.errno
2211 # Get any data from the outgoing BIO irrespective of any error, and
2212 # send it to the socket.
2213 buf = outgoing.read()
2214 sock.sendall(buf)
2215 # If there's no error, we're done. For WANT_READ, we need to get
2216 # data from the socket and put it in the incoming BIO.
2217 if errno is None:
2218 break
2219 elif errno == ssl.SSL_ERROR_WANT_READ:
2220 buf = sock.recv(32768)
2221 if buf:
2222 incoming.write(buf)
2223 else:
2224 incoming.write_eof()
2225 if support.verbose:
2226 sys.stdout.write("Needed %d calls to complete %s().\n"
2227 % (count, func.__name__))
2228 return ret
2229
Martin Panter3840b2a2016-03-27 01:53:46 +00002230 def test_bio_handshake(self):
2231 sock = socket.socket(socket.AF_INET)
2232 self.addCleanup(sock.close)
2233 sock.connect(self.server_addr)
2234 incoming = ssl.MemoryBIO()
2235 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002236 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2237 self.assertTrue(ctx.check_hostname)
2238 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002239 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002240 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2241 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002242 self.assertIs(sslobj._sslobj.owner, sslobj)
2243 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002244 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002245 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002246 self.assertRaises(ValueError, sslobj.getpeercert)
2247 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2248 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2249 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2250 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002251 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002252 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002253 self.assertTrue(sslobj.getpeercert())
2254 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2255 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2256 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002257 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002258 except ssl.SSLSyscallError:
2259 # If the server shuts down the TCP connection without sending a
2260 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2261 pass
2262 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2263
2264 def test_bio_read_write_data(self):
2265 sock = socket.socket(socket.AF_INET)
2266 self.addCleanup(sock.close)
2267 sock.connect(self.server_addr)
2268 incoming = ssl.MemoryBIO()
2269 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002270 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002271 ctx.verify_mode = ssl.CERT_NONE
2272 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2273 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2274 req = b'FOO\n'
2275 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2276 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2277 self.assertEqual(buf, b'foo\n')
2278 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002279
2280
Martin Panter3840b2a2016-03-27 01:53:46 +00002281class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002282
Martin Panter3840b2a2016-03-27 01:53:46 +00002283 def test_timeout_connect_ex(self):
2284 # Issue #12065: on a timeout, connect_ex() should return the original
2285 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002286 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002287 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002288 cert_reqs=ssl.CERT_REQUIRED,
2289 do_handshake_on_connect=False)
2290 self.addCleanup(s.close)
2291 s.settimeout(0.0000001)
2292 rc = s.connect_ex((REMOTE_HOST, 443))
2293 if rc == 0:
2294 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002295 elif rc == errno.ENETUNREACH:
2296 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002297 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2298
Serhiy Storchaka16994912020-04-25 10:06:29 +03002299 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002300 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002301 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002302 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2303 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2304
Martin Panter3840b2a2016-03-27 01:53:46 +00002305
2306def _test_get_server_certificate(test, host, port, cert=None):
2307 pem = ssl.get_server_certificate((host, port))
2308 if not pem:
2309 test.fail("No server certificate on %s:%s!" % (host, port))
2310
2311 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2312 if not pem:
2313 test.fail("No server certificate on %s:%s!" % (host, port))
2314 if support.verbose:
2315 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2316
2317def _test_get_server_certificate_fail(test, host, port):
2318 try:
2319 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2320 except ssl.SSLError as x:
2321 #should fail
2322 if support.verbose:
2323 sys.stdout.write("%s\n" % x)
2324 else:
2325 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2326
2327
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002328from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002329
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002330class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002331
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002332 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002333
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002334 """A mildly complicated class, because we want it to work both
2335 with and without the SSL wrapper around the socket connection, so
2336 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002337
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002338 def __init__(self, server, connsock, addr):
2339 self.server = server
2340 self.running = False
2341 self.sock = connsock
2342 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002343 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002344 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002345 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002346 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002347
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002348 def wrap_conn(self):
2349 try:
2350 self.sslconn = self.server.context.wrap_socket(
2351 self.sock, server_side=True)
2352 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
2353 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002354 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002355 # We treat ConnectionResetError as though it were an
2356 # SSLError - OpenSSL on Ubuntu abruptly closes the
2357 # connection when asked to use an unsupported protocol.
2358 #
Christian Heimes529525f2018-05-23 22:24:45 +02002359 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2360 # tries to send session tickets after handshake.
2361 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002362 #
2363 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2364 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002365 self.server.conn_errors.append(str(e))
2366 if self.server.chatty:
2367 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2368 self.running = False
2369 self.close()
2370 return False
2371 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002372 # OSError may occur with wrong protocols, e.g. both
2373 # sides use PROTOCOL_TLS_SERVER.
2374 #
2375 # XXX Various errors can have happened here, for example
2376 # a mismatching protocol version, an invalid certificate,
2377 # or a low-level bug. This should be made more discriminating.
2378 #
2379 # bpo-31323: Store the exception as string to prevent
2380 # a reference leak: server -> conn_errors -> exception
2381 # -> traceback -> self (ConnectionHandler) -> server
2382 self.server.conn_errors.append(str(e))
2383 if self.server.chatty:
2384 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2385 self.running = False
2386 self.server.stop()
2387 self.close()
2388 return False
2389 else:
2390 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2391 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2392 cert = self.sslconn.getpeercert()
2393 if support.verbose and self.server.chatty:
2394 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2395 cert_binary = self.sslconn.getpeercert(True)
2396 if support.verbose and self.server.chatty:
2397 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2398 cipher = self.sslconn.cipher()
2399 if support.verbose and self.server.chatty:
2400 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
2401 sys.stdout.write(" server: selected protocol is now "
2402 + str(self.sslconn.selected_npn_protocol()) + "\n")
2403 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002404
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002405 def read(self):
2406 if self.sslconn:
2407 return self.sslconn.read()
2408 else:
2409 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002410
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002411 def write(self, bytes):
2412 if self.sslconn:
2413 return self.sslconn.write(bytes)
2414 else:
2415 return self.sock.send(bytes)
2416
2417 def close(self):
2418 if self.sslconn:
2419 self.sslconn.close()
2420 else:
2421 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002422
Antoine Pitrou480a1242010-04-28 21:37:09 +00002423 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002424 self.running = True
2425 if not self.server.starttls_server:
2426 if not self.wrap_conn():
2427 return
2428 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002429 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002430 msg = self.read()
2431 stripped = msg.strip()
2432 if not stripped:
2433 # eof, so quit this handler
2434 self.running = False
2435 try:
2436 self.sock = self.sslconn.unwrap()
2437 except OSError:
2438 # Many tests shut the TCP connection down
2439 # without an SSL shutdown. This causes
2440 # unwrap() to raise OSError with errno=0!
2441 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002442 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002443 self.sslconn = None
2444 self.close()
2445 elif stripped == b'over':
2446 if support.verbose and self.server.connectionchatty:
2447 sys.stdout.write(" server: client closed connection\n")
2448 self.close()
2449 return
2450 elif (self.server.starttls_server and
2451 stripped == b'STARTTLS'):
2452 if support.verbose and self.server.connectionchatty:
2453 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2454 self.write(b"OK\n")
2455 if not self.wrap_conn():
2456 return
2457 elif (self.server.starttls_server and self.sslconn
2458 and stripped == b'ENDTLS'):
2459 if support.verbose and self.server.connectionchatty:
2460 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2461 self.write(b"OK\n")
2462 self.sock = self.sslconn.unwrap()
2463 self.sslconn = None
2464 if support.verbose and self.server.connectionchatty:
2465 sys.stdout.write(" server: connection is now unencrypted...\n")
2466 elif stripped == b'CB tls-unique':
2467 if support.verbose and self.server.connectionchatty:
2468 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2469 data = self.sslconn.get_channel_binding("tls-unique")
2470 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002471 elif stripped == b'PHA':
2472 if support.verbose and self.server.connectionchatty:
2473 sys.stdout.write(" server: initiating post handshake auth\n")
2474 try:
2475 self.sslconn.verify_client_post_handshake()
2476 except ssl.SSLError as e:
2477 self.write(repr(e).encode("us-ascii") + b"\n")
2478 else:
2479 self.write(b"OK\n")
2480 elif stripped == b'HASCERT':
2481 if self.sslconn.getpeercert() is not None:
2482 self.write(b'TRUE\n')
2483 else:
2484 self.write(b'FALSE\n')
2485 elif stripped == b'GETCERT':
2486 cert = self.sslconn.getpeercert()
2487 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002488 else:
2489 if (support.verbose and
2490 self.server.connectionchatty):
2491 ctype = (self.sslconn and "encrypted") or "unencrypted"
2492 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2493 % (msg, ctype, msg.lower(), ctype))
2494 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002495 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002496 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2497 # when connection is not shut down gracefully.
2498 if self.server.chatty and support.verbose:
2499 sys.stdout.write(
2500 " Connection reset by peer: {}\n".format(
2501 self.addr)
2502 )
2503 self.close()
2504 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002505 except ssl.SSLError as err:
2506 # On Windows sometimes test_pha_required_nocert receives the
2507 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2508 # before the 'tlsv13 alert certificate required' exception.
2509 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2510 # is received test_pha_required_nocert fails with ConnectionResetError
2511 # because the underlying socket is closed
2512 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2513 if self.server.chatty and support.verbose:
2514 sys.stdout.write(err.args[1])
2515 # test_pha_required_nocert is expecting this exception
2516 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002517 except OSError:
2518 if self.server.chatty:
2519 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002520 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002521 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002522
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002523 # normally, we'd just stop here, but for the test
2524 # harness, we want to stop the server
2525 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002526
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002527 def __init__(self, certificate=None, ssl_version=None,
2528 certreqs=None, cacerts=None,
2529 chatty=True, connectionchatty=False, starttls_server=False,
2530 npn_protocols=None, alpn_protocols=None,
2531 ciphers=None, context=None):
2532 if context:
2533 self.context = context
2534 else:
2535 self.context = ssl.SSLContext(ssl_version
2536 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002537 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002538 self.context.verify_mode = (certreqs if certreqs is not None
2539 else ssl.CERT_NONE)
2540 if cacerts:
2541 self.context.load_verify_locations(cacerts)
2542 if certificate:
2543 self.context.load_cert_chain(certificate)
2544 if npn_protocols:
2545 self.context.set_npn_protocols(npn_protocols)
2546 if alpn_protocols:
2547 self.context.set_alpn_protocols(alpn_protocols)
2548 if ciphers:
2549 self.context.set_ciphers(ciphers)
2550 self.chatty = chatty
2551 self.connectionchatty = connectionchatty
2552 self.starttls_server = starttls_server
2553 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002554 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002555 self.flag = None
2556 self.active = False
2557 self.selected_npn_protocols = []
2558 self.selected_alpn_protocols = []
2559 self.shared_ciphers = []
2560 self.conn_errors = []
2561 threading.Thread.__init__(self)
2562 self.daemon = True
2563
2564 def __enter__(self):
2565 self.start(threading.Event())
2566 self.flag.wait()
2567 return self
2568
2569 def __exit__(self, *args):
2570 self.stop()
2571 self.join()
2572
2573 def start(self, flag=None):
2574 self.flag = flag
2575 threading.Thread.start(self)
2576
2577 def run(self):
2578 self.sock.settimeout(0.05)
2579 self.sock.listen()
2580 self.active = True
2581 if self.flag:
2582 # signal an event
2583 self.flag.set()
2584 while self.active:
2585 try:
2586 newconn, connaddr = self.sock.accept()
2587 if support.verbose and self.chatty:
2588 sys.stdout.write(' server: new connection from '
2589 + repr(connaddr) + '\n')
2590 handler = self.ConnectionHandler(self, newconn, connaddr)
2591 handler.start()
2592 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002593 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002594 pass
2595 except KeyboardInterrupt:
2596 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002597 except BaseException as e:
2598 if support.verbose and self.chatty:
2599 sys.stdout.write(
2600 ' connection handling failed: ' + repr(e) + '\n')
2601
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002602 self.sock.close()
2603
2604 def stop(self):
2605 self.active = False
2606
2607class AsyncoreEchoServer(threading.Thread):
2608
2609 # this one's based on asyncore.dispatcher
2610
2611 class EchoServer (asyncore.dispatcher):
2612
2613 class ConnectionHandler(asyncore.dispatcher_with_send):
2614
2615 def __init__(self, conn, certfile):
2616 self.socket = test_wrap_socket(conn, server_side=True,
2617 certfile=certfile,
2618 do_handshake_on_connect=False)
2619 asyncore.dispatcher_with_send.__init__(self, self.socket)
2620 self._ssl_accepting = True
2621 self._do_ssl_handshake()
2622
2623 def readable(self):
2624 if isinstance(self.socket, ssl.SSLSocket):
2625 while self.socket.pending() > 0:
2626 self.handle_read_event()
2627 return True
2628
2629 def _do_ssl_handshake(self):
2630 try:
2631 self.socket.do_handshake()
2632 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2633 return
2634 except ssl.SSLEOFError:
2635 return self.handle_close()
2636 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002637 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002638 except OSError as err:
2639 if err.args[0] == errno.ECONNABORTED:
2640 return self.handle_close()
2641 else:
2642 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002643
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002644 def handle_read(self):
2645 if self._ssl_accepting:
2646 self._do_ssl_handshake()
2647 else:
2648 data = self.recv(1024)
2649 if support.verbose:
2650 sys.stdout.write(" server: read %s from client\n" % repr(data))
2651 if not data:
2652 self.close()
2653 else:
2654 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002655
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002656 def handle_close(self):
2657 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002658 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002659 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002660
2661 def handle_error(self):
2662 raise
2663
Trent Nelson78520002008-04-10 20:54:35 +00002664 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002665 self.certfile = certfile
2666 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002667 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002668 asyncore.dispatcher.__init__(self, sock)
2669 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002670
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002671 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002672 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002673 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2674 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002675
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002676 def handle_error(self):
2677 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002678
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002679 def __init__(self, certfile):
2680 self.flag = None
2681 self.active = False
2682 self.server = self.EchoServer(certfile)
2683 self.port = self.server.port
2684 threading.Thread.__init__(self)
2685 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002686
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002687 def __str__(self):
2688 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002689
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002690 def __enter__(self):
2691 self.start(threading.Event())
2692 self.flag.wait()
2693 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002694
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002695 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002696 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002697 sys.stdout.write(" cleanup: stopping server.\n")
2698 self.stop()
2699 if support.verbose:
2700 sys.stdout.write(" cleanup: joining server thread.\n")
2701 self.join()
2702 if support.verbose:
2703 sys.stdout.write(" cleanup: successfully joined.\n")
2704 # make sure that ConnectionHandler is removed from socket_map
2705 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002706
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002707 def start (self, flag=None):
2708 self.flag = flag
2709 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002710
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002711 def run(self):
2712 self.active = True
2713 if self.flag:
2714 self.flag.set()
2715 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002716 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002717 asyncore.loop(1)
2718 except:
2719 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002720
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002721 def stop(self):
2722 self.active = False
2723 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002724
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002725def server_params_test(client_context, server_context, indata=b"FOO\n",
2726 chatty=True, connectionchatty=False, sni_name=None,
2727 session=None):
2728 """
2729 Launch a server, connect a client to it and try various reads
2730 and writes.
2731 """
2732 stats = {}
2733 server = ThreadedEchoServer(context=server_context,
2734 chatty=chatty,
2735 connectionchatty=False)
2736 with server:
2737 with client_context.wrap_socket(socket.socket(),
2738 server_hostname=sni_name, session=session) as s:
2739 s.connect((HOST, server.port))
2740 for arg in [indata, bytearray(indata), memoryview(indata)]:
2741 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002742 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002743 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002744 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002745 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002746 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002747 if connectionchatty:
2748 if support.verbose:
2749 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002750 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002751 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002752 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2753 % (outdata[:20], len(outdata),
2754 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002755 s.write(b"over\n")
2756 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002757 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002758 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002759 stats.update({
2760 'compression': s.compression(),
2761 'cipher': s.cipher(),
2762 'peercert': s.getpeercert(),
2763 'client_alpn_protocol': s.selected_alpn_protocol(),
2764 'client_npn_protocol': s.selected_npn_protocol(),
2765 'version': s.version(),
2766 'session_reused': s.session_reused,
2767 'session': s.session,
2768 })
2769 s.close()
2770 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2771 stats['server_npn_protocols'] = server.selected_npn_protocols
2772 stats['server_shared_ciphers'] = server.shared_ciphers
2773 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002774
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002775def try_protocol_combo(server_protocol, client_protocol, expect_success,
2776 certsreqs=None, server_options=0, client_options=0):
2777 """
2778 Try to SSL-connect using *client_protocol* to *server_protocol*.
2779 If *expect_success* is true, assert that the connection succeeds,
2780 if it's false, assert that the connection fails.
2781 Also, if *expect_success* is a string, assert that it is the protocol
2782 version actually used by the connection.
2783 """
2784 if certsreqs is None:
2785 certsreqs = ssl.CERT_NONE
2786 certtype = {
2787 ssl.CERT_NONE: "CERT_NONE",
2788 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2789 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2790 }[certsreqs]
2791 if support.verbose:
2792 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2793 sys.stdout.write(formatstr %
2794 (ssl.get_protocol_name(client_protocol),
2795 ssl.get_protocol_name(server_protocol),
2796 certtype))
2797 client_context = ssl.SSLContext(client_protocol)
2798 client_context.options |= client_options
2799 server_context = ssl.SSLContext(server_protocol)
2800 server_context.options |= server_options
2801
Victor Stinner3ef63442019-02-19 18:06:03 +01002802 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2803 if (min_version is not None
2804 # SSLContext.minimum_version is only available on recent OpenSSL
2805 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2806 and hasattr(server_context, 'minimum_version')
2807 and server_protocol == ssl.PROTOCOL_TLS
2808 and server_context.minimum_version > min_version):
2809 # If OpenSSL configuration is strict and requires more recent TLS
2810 # version, we have to change the minimum to test old TLS versions.
2811 server_context.minimum_version = min_version
2812
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002813 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2814 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2815 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002816 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002817 client_context.set_ciphers("ALL")
2818
Christian Heimesf6c6b582021-03-18 23:06:50 +01002819 seclevel_workaround(server_context, client_context)
2820
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002821 for ctx in (client_context, server_context):
2822 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002823 ctx.load_cert_chain(SIGNED_CERTFILE)
2824 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002825 try:
2826 stats = server_params_test(client_context, server_context,
2827 chatty=False, connectionchatty=False)
2828 # Protocol mismatch can result in either an SSLError, or a
2829 # "Connection reset by peer" error.
2830 except ssl.SSLError:
2831 if expect_success:
2832 raise
2833 except OSError as e:
2834 if expect_success or e.errno != errno.ECONNRESET:
2835 raise
2836 else:
2837 if not expect_success:
2838 raise AssertionError(
2839 "Client protocol %s succeeded with server protocol %s!"
2840 % (ssl.get_protocol_name(client_protocol),
2841 ssl.get_protocol_name(server_protocol)))
2842 elif (expect_success is not True
2843 and expect_success != stats['version']):
2844 raise AssertionError("version mismatch: expected %r, got %r"
2845 % (expect_success, stats['version']))
2846
2847
2848class ThreadedTests(unittest.TestCase):
2849
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002850 def test_echo(self):
2851 """Basic test of an SSL client connecting to a server"""
2852 if support.verbose:
2853 sys.stdout.write("\n")
2854 for protocol in PROTOCOLS:
2855 if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
2856 continue
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02002857 if not has_tls_protocol(protocol):
2858 continue
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002859 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2860 context = ssl.SSLContext(protocol)
2861 context.load_cert_chain(CERTFILE)
Christian Heimesf6c6b582021-03-18 23:06:50 +01002862 seclevel_workaround(context)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002863 server_params_test(context, context,
2864 chatty=True, connectionchatty=True)
2865
Christian Heimesa170fa12017-09-15 20:27:30 +02002866 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002867
2868 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2869 server_params_test(client_context=client_context,
2870 server_context=server_context,
2871 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002872 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002873
2874 client_context.check_hostname = False
2875 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2876 with self.assertRaises(ssl.SSLError) as e:
2877 server_params_test(client_context=server_context,
2878 server_context=client_context,
2879 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002880 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002881 self.assertIn('called a function you should not call',
2882 str(e.exception))
2883
2884 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2885 with self.assertRaises(ssl.SSLError) as e:
2886 server_params_test(client_context=server_context,
2887 server_context=server_context,
2888 chatty=True, connectionchatty=True)
2889 self.assertIn('called a function you should not call',
2890 str(e.exception))
2891
2892 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2893 with self.assertRaises(ssl.SSLError) as e:
2894 server_params_test(client_context=server_context,
2895 server_context=client_context,
2896 chatty=True, connectionchatty=True)
2897 self.assertIn('called a function you should not call',
2898 str(e.exception))
2899
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002900 def test_getpeercert(self):
2901 if support.verbose:
2902 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002903
2904 client_context, server_context, hostname = testing_context()
2905 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002906 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002907 with client_context.wrap_socket(socket.socket(),
2908 do_handshake_on_connect=False,
2909 server_hostname=hostname) as s:
2910 s.connect((HOST, server.port))
2911 # getpeercert() raise ValueError while the handshake isn't
2912 # done.
2913 with self.assertRaises(ValueError):
2914 s.getpeercert()
2915 s.do_handshake()
2916 cert = s.getpeercert()
2917 self.assertTrue(cert, "Can't get peer certificate.")
2918 cipher = s.cipher()
2919 if support.verbose:
2920 sys.stdout.write(pprint.pformat(cert) + '\n')
2921 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2922 if 'subject' not in cert:
2923 self.fail("No subject field in certificate: %s." %
2924 pprint.pformat(cert))
2925 if ((('organizationName', 'Python Software Foundation'),)
2926 not in cert['subject']):
2927 self.fail(
2928 "Missing or invalid 'organizationName' field in certificate subject; "
2929 "should be 'Python Software Foundation'.")
2930 self.assertIn('notBefore', cert)
2931 self.assertIn('notAfter', cert)
2932 before = ssl.cert_time_to_seconds(cert['notBefore'])
2933 after = ssl.cert_time_to_seconds(cert['notAfter'])
2934 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002935
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002936 def test_crl_check(self):
2937 if support.verbose:
2938 sys.stdout.write("\n")
2939
Christian Heimesa170fa12017-09-15 20:27:30 +02002940 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002941
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002942 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002943 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002944
2945 # VERIFY_DEFAULT should pass
2946 server = ThreadedEchoServer(context=server_context, chatty=True)
2947 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002948 with client_context.wrap_socket(socket.socket(),
2949 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002950 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002951 cert = s.getpeercert()
2952 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002953
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002954 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002955 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002956
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002957 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 Pitroua6a4dc82017-09-07 18:56:24 +02002961 with self.assertRaisesRegex(ssl.SSLError,
2962 "certificate verify failed"):
2963 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002964
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002965 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002966 client_context.load_verify_locations(CRLFILE)
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 Pitroub4bebda2014-04-29 10:03:28 +02002972 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002973 cert = s.getpeercert()
2974 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002975
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002976 def test_check_hostname(self):
2977 if support.verbose:
2978 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002979
Christian Heimesa170fa12017-09-15 20:27:30 +02002980 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002981
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002982 # correct hostname should verify
2983 server = ThreadedEchoServer(context=server_context, chatty=True)
2984 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002985 with client_context.wrap_socket(socket.socket(),
2986 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002987 s.connect((HOST, server.port))
2988 cert = s.getpeercert()
2989 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002990
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002991 # incorrect hostname should raise an exception
2992 server = ThreadedEchoServer(context=server_context, chatty=True)
2993 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002994 with client_context.wrap_socket(socket.socket(),
2995 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01002996 with self.assertRaisesRegex(
2997 ssl.CertificateError,
2998 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002999 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003000
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003001 # missing server_hostname arg should cause an exception, too
3002 server = ThreadedEchoServer(context=server_context, chatty=True)
3003 with server:
3004 with socket.socket() as s:
3005 with self.assertRaisesRegex(ValueError,
3006 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02003007 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003008
Christian Heimesb467d9a2021-04-17 10:07:19 +02003009 @unittest.skipUnless(
3010 ssl.HAS_NEVER_CHECK_COMMON_NAME, "test requires hostname_checks_common_name"
3011 )
3012 def test_hostname_checks_common_name(self):
3013 client_context, server_context, hostname = testing_context()
3014 assert client_context.hostname_checks_common_name
3015 client_context.hostname_checks_common_name = False
3016
3017 # default cert has a SAN
3018 server = ThreadedEchoServer(context=server_context, chatty=True)
3019 with server:
3020 with client_context.wrap_socket(socket.socket(),
3021 server_hostname=hostname) as s:
3022 s.connect((HOST, server.port))
3023
3024 client_context, server_context, hostname = testing_context(NOSANFILE)
3025 client_context.hostname_checks_common_name = False
3026 server = ThreadedEchoServer(context=server_context, chatty=True)
3027 with server:
3028 with client_context.wrap_socket(socket.socket(),
3029 server_hostname=hostname) as s:
3030 with self.assertRaises(ssl.SSLCertVerificationError):
3031 s.connect((HOST, server.port))
3032
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003033 def test_ecc_cert(self):
3034 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3035 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003036 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003037 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3038
3039 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3040 # load ECC cert
3041 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3042
3043 # correct hostname should verify
3044 server = ThreadedEchoServer(context=server_context, chatty=True)
3045 with server:
3046 with client_context.wrap_socket(socket.socket(),
3047 server_hostname=hostname) as s:
3048 s.connect((HOST, server.port))
3049 cert = s.getpeercert()
3050 self.assertTrue(cert, "Can't get peer certificate.")
3051 cipher = s.cipher()[0].split('-')
3052 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3053
3054 def test_dual_rsa_ecc(self):
3055 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3056 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003057 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3058 # algorithms.
3059 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003060 # only ECDSA certs
3061 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3062 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3063
3064 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3065 # load ECC and RSA key/cert pairs
3066 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3067 server_context.load_cert_chain(SIGNED_CERTFILE)
3068
3069 # correct hostname should verify
3070 server = ThreadedEchoServer(context=server_context, chatty=True)
3071 with server:
3072 with client_context.wrap_socket(socket.socket(),
3073 server_hostname=hostname) as s:
3074 s.connect((HOST, server.port))
3075 cert = s.getpeercert()
3076 self.assertTrue(cert, "Can't get peer certificate.")
3077 cipher = s.cipher()[0].split('-')
3078 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3079
Christian Heimes66e57422018-01-29 14:25:13 +01003080 def test_check_hostname_idn(self):
3081 if support.verbose:
3082 sys.stdout.write("\n")
3083
Christian Heimes11a14932018-02-24 02:35:08 +01003084 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003085 server_context.load_cert_chain(IDNSANSFILE)
3086
Christian Heimes11a14932018-02-24 02:35:08 +01003087 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003088 context.verify_mode = ssl.CERT_REQUIRED
3089 context.check_hostname = True
3090 context.load_verify_locations(SIGNING_CA)
3091
3092 # correct hostname should verify, when specified in several
3093 # different ways
3094 idn_hostnames = [
3095 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003096 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003097 ('xn--knig-5qa.idn.pythontest.net',
3098 'xn--knig-5qa.idn.pythontest.net'),
3099 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003100 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003101
3102 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003103 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003104 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3105 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3106 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003107 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3108
3109 # ('königsgäßchen.idna2008.pythontest.net',
3110 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3111 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3112 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3113 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3114 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3115
Christian Heimes66e57422018-01-29 14:25:13 +01003116 ]
3117 for server_hostname, expected_hostname in idn_hostnames:
3118 server = ThreadedEchoServer(context=server_context, chatty=True)
3119 with server:
3120 with context.wrap_socket(socket.socket(),
3121 server_hostname=server_hostname) as s:
3122 self.assertEqual(s.server_hostname, expected_hostname)
3123 s.connect((HOST, server.port))
3124 cert = s.getpeercert()
3125 self.assertEqual(s.server_hostname, expected_hostname)
3126 self.assertTrue(cert, "Can't get peer certificate.")
3127
Christian Heimes66e57422018-01-29 14:25:13 +01003128 # incorrect hostname should raise an exception
3129 server = ThreadedEchoServer(context=server_context, chatty=True)
3130 with server:
3131 with context.wrap_socket(socket.socket(),
3132 server_hostname="python.example.org") as s:
3133 with self.assertRaises(ssl.CertificateError):
3134 s.connect((HOST, server.port))
3135
Christian Heimes529525f2018-05-23 22:24:45 +02003136 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003137 """Connecting when the server rejects the client's certificate
3138
3139 Launch a server with CERT_REQUIRED, and check that trying to
3140 connect to it with a wrong client certificate fails.
3141 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003142 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003143 # load client cert that is not signed by trusted CA
3144 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003145 # require TLS client authentication
3146 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003147 # TLS 1.3 has different handshake
3148 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003149
3150 server = ThreadedEchoServer(
3151 context=server_context, chatty=True, connectionchatty=True,
3152 )
3153
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003154 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003155 client_context.wrap_socket(socket.socket(),
3156 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003157 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003158 # Expect either an SSL error about the server rejecting
3159 # the connection, or a low-level connection reset (which
3160 # sometimes happens on Windows)
3161 s.connect((HOST, server.port))
3162 except ssl.SSLError as e:
3163 if support.verbose:
3164 sys.stdout.write("\nSSLError is %r\n" % e)
3165 except OSError as e:
3166 if e.errno != errno.ECONNRESET:
3167 raise
3168 if support.verbose:
3169 sys.stdout.write("\nsocket.error is %r\n" % e)
3170 else:
3171 self.fail("Use of invalid cert should have failed!")
3172
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003173 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003174 def test_wrong_cert_tls13(self):
3175 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003176 # load client cert that is not signed by trusted CA
3177 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003178 server_context.verify_mode = ssl.CERT_REQUIRED
3179 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3180 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3181
3182 server = ThreadedEchoServer(
3183 context=server_context, chatty=True, connectionchatty=True,
3184 )
3185 with server, \
3186 client_context.wrap_socket(socket.socket(),
3187 server_hostname=hostname) as s:
3188 # TLS 1.3 perform client cert exchange after handshake
3189 s.connect((HOST, server.port))
3190 try:
3191 s.write(b'data')
3192 s.read(4)
3193 except ssl.SSLError as e:
3194 if support.verbose:
3195 sys.stdout.write("\nSSLError is %r\n" % e)
3196 except OSError as e:
3197 if e.errno != errno.ECONNRESET:
3198 raise
3199 if support.verbose:
3200 sys.stdout.write("\nsocket.error is %r\n" % e)
3201 else:
3202 self.fail("Use of invalid cert should have failed!")
3203
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003204 def test_rude_shutdown(self):
3205 """A brutal shutdown of an SSL server should raise an OSError
3206 in the client when attempting handshake.
3207 """
3208 listener_ready = threading.Event()
3209 listener_gone = threading.Event()
3210
3211 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003212 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003213
3214 # `listener` runs in a thread. It sits in an accept() until
3215 # the main thread connects. Then it rudely closes the socket,
3216 # and sets Event `listener_gone` to let the main thread know
3217 # the socket is gone.
3218 def listener():
3219 s.listen()
3220 listener_ready.set()
3221 newsock, addr = s.accept()
3222 newsock.close()
3223 s.close()
3224 listener_gone.set()
3225
3226 def connector():
3227 listener_ready.wait()
3228 with socket.socket() as c:
3229 c.connect((HOST, port))
3230 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003231 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003232 ssl_sock = test_wrap_socket(c)
3233 except OSError:
3234 pass
3235 else:
3236 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003237
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003238 t = threading.Thread(target=listener)
3239 t.start()
3240 try:
3241 connector()
3242 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003243 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003244
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003245 def test_ssl_cert_verify_error(self):
3246 if support.verbose:
3247 sys.stdout.write("\n")
3248
3249 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3250 server_context.load_cert_chain(SIGNED_CERTFILE)
3251
3252 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3253
3254 server = ThreadedEchoServer(context=server_context, chatty=True)
3255 with server:
3256 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003257 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003258 try:
3259 s.connect((HOST, server.port))
3260 except ssl.SSLError as e:
3261 msg = 'unable to get local issuer certificate'
3262 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3263 self.assertEqual(e.verify_code, 20)
3264 self.assertEqual(e.verify_message, msg)
3265 self.assertIn(msg, repr(e))
3266 self.assertIn('certificate verify failed', repr(e))
3267
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003268 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003269 def test_protocol_sslv2(self):
3270 """Connecting to an SSLv2 server with various client options"""
3271 if support.verbose:
3272 sys.stdout.write("\n")
3273 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3274 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3275 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003276 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003277 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003278 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3279 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3280 # SSLv23 client with specific SSL options
3281 if no_sslv2_implies_sslv3_hello():
3282 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003283 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003284 client_options=ssl.OP_NO_SSLv2)
Christian Heimesa170fa12017-09-15 20:27:30 +02003285 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003286 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003287 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003288 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003289
Christian Heimesa170fa12017-09-15 20:27:30 +02003290 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003291 """Connecting to an SSLv23 server with various client options"""
3292 if support.verbose:
3293 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003294 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003295 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003296 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003297 except OSError as x:
3298 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3299 if support.verbose:
3300 sys.stdout.write(
3301 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3302 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003303 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003304 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3305 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003306 if has_tls_version('TLSv1'):
3307 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003308
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003309 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003310 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3311 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003312 if has_tls_version('TLSv1'):
3313 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003314
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003315 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003316 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3317 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003318 if has_tls_version('TLSv1'):
3319 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003320
3321 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003322 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003323 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003324 server_options=ssl.OP_NO_SSLv3)
3325 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003326 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003327 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003328 if has_tls_version('TLSv1'):
3329 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3330 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003331
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003332 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003333 def test_protocol_sslv3(self):
3334 """Connecting to an SSLv3 server with various client options"""
3335 if support.verbose:
3336 sys.stdout.write("\n")
3337 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3338 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3339 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003340 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003341 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003342 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003343 client_options=ssl.OP_NO_SSLv3)
3344 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3345 if no_sslv2_implies_sslv3_hello():
3346 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003347 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003348 False, client_options=ssl.OP_NO_SSLv2)
3349
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003350 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003351 def test_protocol_tlsv1(self):
3352 """Connecting to a TLSv1 server with various client options"""
3353 if support.verbose:
3354 sys.stdout.write("\n")
3355 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3356 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3357 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003358 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003359 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003360 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003361 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003362 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003363 client_options=ssl.OP_NO_TLSv1)
3364
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003365 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003366 def test_protocol_tlsv1_1(self):
3367 """Connecting to a TLSv1.1 server with various client options.
3368 Testing against older TLS versions."""
3369 if support.verbose:
3370 sys.stdout.write("\n")
3371 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003372 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003373 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003374 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003375 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003376 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003377 client_options=ssl.OP_NO_TLSv1_1)
3378
Christian Heimesa170fa12017-09-15 20:27:30 +02003379 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003380 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3381 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003382
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003383 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003384 def test_protocol_tlsv1_2(self):
3385 """Connecting to a TLSv1.2 server with various client options.
3386 Testing against older TLS versions."""
3387 if support.verbose:
3388 sys.stdout.write("\n")
3389 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3390 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3391 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003392 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003393 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003394 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003395 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003396 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003397 client_options=ssl.OP_NO_TLSv1_2)
3398
Christian Heimesa170fa12017-09-15 20:27:30 +02003399 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003400 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3401 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3402 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3403 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3404
3405 def test_starttls(self):
3406 """Switching from clear text to encrypted and back again."""
3407 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3408
3409 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003410 starttls_server=True,
3411 chatty=True,
3412 connectionchatty=True)
3413 wrapped = False
3414 with server:
3415 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003416 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003417 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003418 if support.verbose:
3419 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003420 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003421 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003422 sys.stdout.write(
3423 " client: sending %r...\n" % indata)
3424 if wrapped:
3425 conn.write(indata)
3426 outdata = conn.read()
3427 else:
3428 s.send(indata)
3429 outdata = s.recv(1024)
3430 msg = outdata.strip().lower()
3431 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3432 # STARTTLS ok, switch to secure mode
3433 if support.verbose:
3434 sys.stdout.write(
3435 " client: read %r from server, starting TLS...\n"
3436 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003437 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003438 wrapped = True
3439 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3440 # ENDTLS ok, switch back to clear text
3441 if support.verbose:
3442 sys.stdout.write(
3443 " client: read %r from server, ending TLS...\n"
3444 % msg)
3445 s = conn.unwrap()
3446 wrapped = False
3447 else:
3448 if support.verbose:
3449 sys.stdout.write(
3450 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003451 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003452 sys.stdout.write(" client: closing connection.\n")
3453 if wrapped:
3454 conn.write(b"over\n")
3455 else:
3456 s.send(b"over\n")
3457 if wrapped:
3458 conn.close()
3459 else:
3460 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003461
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003462 def test_socketserver(self):
3463 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003464 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003465 # try to connect
3466 if support.verbose:
3467 sys.stdout.write('\n')
3468 with open(CERTFILE, 'rb') as f:
3469 d1 = f.read()
3470 d2 = ''
3471 # now fetch the same data from the HTTPS server
3472 url = 'https://localhost:%d/%s' % (
3473 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003474 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003475 f = urllib.request.urlopen(url, context=context)
3476 try:
3477 dlen = f.info().get("content-length")
3478 if dlen and (int(dlen) > 0):
3479 d2 = f.read(int(dlen))
3480 if support.verbose:
3481 sys.stdout.write(
3482 " client: read %d bytes from remote server '%s'\n"
3483 % (len(d2), server))
3484 finally:
3485 f.close()
3486 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003487
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003488 def test_asyncore_server(self):
3489 """Check the example asyncore integration."""
3490 if support.verbose:
3491 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003492
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003493 indata = b"FOO\n"
3494 server = AsyncoreEchoServer(CERTFILE)
3495 with server:
3496 s = test_wrap_socket(socket.socket())
3497 s.connect(('127.0.0.1', server.port))
3498 if support.verbose:
3499 sys.stdout.write(
3500 " client: sending %r...\n" % indata)
3501 s.write(indata)
3502 outdata = s.read()
3503 if support.verbose:
3504 sys.stdout.write(" client: read %r\n" % outdata)
3505 if outdata != indata.lower():
3506 self.fail(
3507 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3508 % (outdata[:20], len(outdata),
3509 indata[:20].lower(), len(indata)))
3510 s.write(b"over\n")
3511 if support.verbose:
3512 sys.stdout.write(" client: closing connection.\n")
3513 s.close()
3514 if support.verbose:
3515 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003516
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003517 def test_recv_send(self):
3518 """Test recv(), send() and friends."""
3519 if support.verbose:
3520 sys.stdout.write("\n")
3521
3522 server = ThreadedEchoServer(CERTFILE,
3523 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003524 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003525 cacerts=CERTFILE,
3526 chatty=True,
3527 connectionchatty=False)
3528 with server:
3529 s = test_wrap_socket(socket.socket(),
3530 server_side=False,
3531 certfile=CERTFILE,
3532 ca_certs=CERTFILE,
3533 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003534 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003535 s.connect((HOST, server.port))
3536 # helper methods for standardising recv* method signatures
3537 def _recv_into():
3538 b = bytearray(b"\0"*100)
3539 count = s.recv_into(b)
3540 return b[:count]
3541
3542 def _recvfrom_into():
3543 b = bytearray(b"\0"*100)
3544 count, addr = s.recvfrom_into(b)
3545 return b[:count]
3546
3547 # (name, method, expect success?, *args, return value func)
3548 send_methods = [
3549 ('send', s.send, True, [], len),
3550 ('sendto', s.sendto, False, ["some.address"], len),
3551 ('sendall', s.sendall, True, [], lambda x: None),
3552 ]
3553 # (name, method, whether to expect success, *args)
3554 recv_methods = [
3555 ('recv', s.recv, True, []),
3556 ('recvfrom', s.recvfrom, False, ["some.address"]),
3557 ('recv_into', _recv_into, True, []),
3558 ('recvfrom_into', _recvfrom_into, False, []),
3559 ]
3560 data_prefix = "PREFIX_"
3561
3562 for (meth_name, send_meth, expect_success, args,
3563 ret_val_meth) in send_methods:
3564 indata = (data_prefix + meth_name).encode('ascii')
3565 try:
3566 ret = send_meth(indata, *args)
3567 msg = "sending with {}".format(meth_name)
3568 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3569 outdata = s.read()
3570 if outdata != indata.lower():
3571 self.fail(
3572 "While sending with <<{name:s}>> bad data "
3573 "<<{outdata:r}>> ({nout:d}) received; "
3574 "expected <<{indata:r}>> ({nin:d})\n".format(
3575 name=meth_name, outdata=outdata[:20],
3576 nout=len(outdata),
3577 indata=indata[:20], nin=len(indata)
3578 )
3579 )
3580 except ValueError as e:
3581 if expect_success:
3582 self.fail(
3583 "Failed to send with method <<{name:s}>>; "
3584 "expected to succeed.\n".format(name=meth_name)
3585 )
3586 if not str(e).startswith(meth_name):
3587 self.fail(
3588 "Method <<{name:s}>> failed with unexpected "
3589 "exception message: {exp:s}\n".format(
3590 name=meth_name, exp=e
3591 )
3592 )
3593
3594 for meth_name, recv_meth, expect_success, args in recv_methods:
3595 indata = (data_prefix + meth_name).encode('ascii')
3596 try:
3597 s.send(indata)
3598 outdata = recv_meth(*args)
3599 if outdata != indata.lower():
3600 self.fail(
3601 "While receiving with <<{name:s}>> bad data "
3602 "<<{outdata:r}>> ({nout:d}) received; "
3603 "expected <<{indata:r}>> ({nin:d})\n".format(
3604 name=meth_name, outdata=outdata[:20],
3605 nout=len(outdata),
3606 indata=indata[:20], nin=len(indata)
3607 )
3608 )
3609 except ValueError as e:
3610 if expect_success:
3611 self.fail(
3612 "Failed to receive with method <<{name:s}>>; "
3613 "expected to succeed.\n".format(name=meth_name)
3614 )
3615 if not str(e).startswith(meth_name):
3616 self.fail(
3617 "Method <<{name:s}>> failed with unexpected "
3618 "exception message: {exp:s}\n".format(
3619 name=meth_name, exp=e
3620 )
3621 )
3622 # consume data
3623 s.read()
3624
3625 # read(-1, buffer) is supported, even though read(-1) is not
3626 data = b"data"
3627 s.send(data)
3628 buffer = bytearray(len(data))
3629 self.assertEqual(s.read(-1, buffer), len(data))
3630 self.assertEqual(buffer, data)
3631
Christian Heimes888bbdc2017-09-07 14:18:21 -07003632 # sendall accepts bytes-like objects
3633 if ctypes is not None:
3634 ubyte = ctypes.c_ubyte * len(data)
3635 byteslike = ubyte.from_buffer_copy(data)
3636 s.sendall(byteslike)
3637 self.assertEqual(s.read(), data)
3638
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003639 # Make sure sendmsg et al are disallowed to avoid
3640 # inadvertent disclosure of data and/or corruption
3641 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003642 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003643 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3644 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3645 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003646 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003647 s.write(b"over\n")
3648
3649 self.assertRaises(ValueError, s.recv, -1)
3650 self.assertRaises(ValueError, s.read, -1)
3651
3652 s.close()
3653
3654 def test_recv_zero(self):
3655 server = ThreadedEchoServer(CERTFILE)
3656 server.__enter__()
3657 self.addCleanup(server.__exit__, None, None)
3658 s = socket.create_connection((HOST, server.port))
3659 self.addCleanup(s.close)
3660 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3661 self.addCleanup(s.close)
3662
3663 # recv/read(0) should return no data
3664 s.send(b"data")
3665 self.assertEqual(s.recv(0), b"")
3666 self.assertEqual(s.read(0), b"")
3667 self.assertEqual(s.read(), b"data")
3668
3669 # Should not block if the other end sends no data
3670 s.setblocking(False)
3671 self.assertEqual(s.recv(0), b"")
3672 self.assertEqual(s.recv_into(bytearray()), 0)
3673
3674 def test_nonblocking_send(self):
3675 server = ThreadedEchoServer(CERTFILE,
3676 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003677 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003678 cacerts=CERTFILE,
3679 chatty=True,
3680 connectionchatty=False)
3681 with server:
3682 s = test_wrap_socket(socket.socket(),
3683 server_side=False,
3684 certfile=CERTFILE,
3685 ca_certs=CERTFILE,
3686 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003687 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003688 s.connect((HOST, server.port))
3689 s.setblocking(False)
3690
3691 # If we keep sending data, at some point the buffers
3692 # will be full and the call will block
3693 buf = bytearray(8192)
3694 def fill_buffer():
3695 while True:
3696 s.send(buf)
3697 self.assertRaises((ssl.SSLWantWriteError,
3698 ssl.SSLWantReadError), fill_buffer)
3699
3700 # Now read all the output and discard it
3701 s.setblocking(True)
3702 s.close()
3703
3704 def test_handshake_timeout(self):
3705 # Issue #5103: SSL handshake must respect the socket timeout
3706 server = socket.socket(socket.AF_INET)
3707 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003708 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003709 started = threading.Event()
3710 finish = False
3711
3712 def serve():
3713 server.listen()
3714 started.set()
3715 conns = []
3716 while not finish:
3717 r, w, e = select.select([server], [], [], 0.1)
3718 if server in r:
3719 # Let the socket hang around rather than having
3720 # it closed by garbage collection.
3721 conns.append(server.accept()[0])
3722 for sock in conns:
3723 sock.close()
3724
3725 t = threading.Thread(target=serve)
3726 t.start()
3727 started.wait()
3728
3729 try:
3730 try:
3731 c = socket.socket(socket.AF_INET)
3732 c.settimeout(0.2)
3733 c.connect((host, port))
3734 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003735 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003736 test_wrap_socket, c)
3737 finally:
3738 c.close()
3739 try:
3740 c = socket.socket(socket.AF_INET)
3741 c = test_wrap_socket(c)
3742 c.settimeout(0.2)
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 c.connect, (host, port))
3746 finally:
3747 c.close()
3748 finally:
3749 finish = True
3750 t.join()
3751 server.close()
3752
3753 def test_server_accept(self):
3754 # Issue #16357: accept() on a SSLSocket created through
3755 # SSLContext.wrap_socket().
Christian Heimesa170fa12017-09-15 20:27:30 +02003756 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003757 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003758 context.load_verify_locations(SIGNING_CA)
3759 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003760 server = socket.socket(socket.AF_INET)
3761 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003762 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003763 server = context.wrap_socket(server, server_side=True)
3764 self.assertTrue(server.server_side)
3765
3766 evt = threading.Event()
3767 remote = None
3768 peer = None
3769 def serve():
3770 nonlocal remote, peer
3771 server.listen()
3772 # Block on the accept and wait on the connection to close.
3773 evt.set()
3774 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003775 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003776
3777 t = threading.Thread(target=serve)
3778 t.start()
3779 # Client wait until server setup and perform a connect.
3780 evt.wait()
3781 client = context.wrap_socket(socket.socket())
3782 client.connect((host, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003783 client.send(b'data')
3784 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003785 client_addr = client.getsockname()
3786 client.close()
3787 t.join()
3788 remote.close()
3789 server.close()
3790 # Sanity checks.
3791 self.assertIsInstance(remote, ssl.SSLSocket)
3792 self.assertEqual(peer, client_addr)
3793
3794 def test_getpeercert_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003795 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003796 with context.wrap_socket(socket.socket()) as sock:
3797 with self.assertRaises(OSError) as cm:
3798 sock.getpeercert()
3799 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3800
3801 def test_do_handshake_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003802 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003803 with context.wrap_socket(socket.socket()) as sock:
3804 with self.assertRaises(OSError) as cm:
3805 sock.do_handshake()
3806 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3807
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003808 def test_no_shared_ciphers(self):
3809 client_context, server_context, hostname = testing_context()
3810 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3811 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003812 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003813 client_context.set_ciphers("AES128")
3814 server_context.set_ciphers("AES256")
3815 with ThreadedEchoServer(context=server_context) as server:
3816 with client_context.wrap_socket(socket.socket(),
3817 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003818 with self.assertRaises(OSError):
3819 s.connect((HOST, server.port))
3820 self.assertIn("no shared cipher", server.conn_errors[0])
3821
3822 def test_version_basic(self):
3823 """
3824 Basic tests for SSLSocket.version().
3825 More tests are done in the test_protocol_*() methods.
3826 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003827 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3828 context.check_hostname = False
3829 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003830 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003831 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003832 chatty=False) as server:
3833 with context.wrap_socket(socket.socket()) as s:
3834 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003835 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003836 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003837 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003838 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003839 self.assertIs(s.version(), None)
3840
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003841 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003842 def test_tls1_3(self):
3843 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
3844 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003845 context.options |= (
3846 ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2
3847 )
3848 with ThreadedEchoServer(context=context) as server:
3849 with context.wrap_socket(socket.socket()) as s:
3850 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003851 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003852 'TLS_AES_256_GCM_SHA384',
3853 'TLS_CHACHA20_POLY1305_SHA256',
3854 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003855 })
3856 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003857
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003858 @requires_minimum_version
3859 @requires_tls_version('TLSv1_2')
3860 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003861 client_context, server_context, hostname = testing_context()
3862 # client TLSv1.0 to 1.2
3863 client_context.minimum_version = ssl.TLSVersion.TLSv1
3864 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3865 # server only TLSv1.2
3866 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3867 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3868
3869 with ThreadedEchoServer(context=server_context) as server:
3870 with client_context.wrap_socket(socket.socket(),
3871 server_hostname=hostname) as s:
3872 s.connect((HOST, server.port))
3873 self.assertEqual(s.version(), 'TLSv1.2')
3874
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003875 @requires_minimum_version
3876 @requires_tls_version('TLSv1_1')
3877 def test_min_max_version_tlsv1_1(self):
3878 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003879 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003880 client_context.minimum_version = ssl.TLSVersion.TLSv1
3881 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003882 server_context.minimum_version = ssl.TLSVersion.TLSv1
3883 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003884 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003885
3886 with ThreadedEchoServer(context=server_context) as server:
3887 with client_context.wrap_socket(socket.socket(),
3888 server_hostname=hostname) as s:
3889 s.connect((HOST, server.port))
3890 self.assertEqual(s.version(), 'TLSv1.1')
3891
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003892 @requires_minimum_version
3893 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003894 @requires_tls_version('TLSv1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003895 def test_min_max_version_mismatch(self):
3896 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003897 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003898 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003899 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003900 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003901 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003902 seclevel_workaround(client_context, server_context)
3903
Christian Heimes698dde12018-02-27 11:54:43 +01003904 with ThreadedEchoServer(context=server_context) as server:
3905 with client_context.wrap_socket(socket.socket(),
3906 server_hostname=hostname) as s:
3907 with self.assertRaises(ssl.SSLError) as e:
3908 s.connect((HOST, server.port))
3909 self.assertIn("alert", str(e.exception))
3910
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003911 @requires_minimum_version
3912 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003913 def test_min_max_version_sslv3(self):
3914 client_context, server_context, hostname = testing_context()
3915 server_context.minimum_version = ssl.TLSVersion.SSLv3
3916 client_context.minimum_version = ssl.TLSVersion.SSLv3
3917 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003918 seclevel_workaround(client_context, server_context)
3919
Christian Heimes698dde12018-02-27 11:54:43 +01003920 with ThreadedEchoServer(context=server_context) as server:
3921 with client_context.wrap_socket(socket.socket(),
3922 server_hostname=hostname) as s:
3923 s.connect((HOST, server.port))
3924 self.assertEqual(s.version(), 'SSLv3')
3925
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003926 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3927 def test_default_ecdh_curve(self):
3928 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3929 # should be enabled by default on SSL contexts.
Christian Heimesa170fa12017-09-15 20:27:30 +02003930 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003931 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003932 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3933 # cipher name.
3934 context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003935 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3936 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3937 # our default cipher list should prefer ECDH-based ciphers
3938 # automatically.
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003939 with ThreadedEchoServer(context=context) as server:
3940 with context.wrap_socket(socket.socket()) as s:
3941 s.connect((HOST, server.port))
3942 self.assertIn("ECDH", s.cipher()[0])
3943
3944 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3945 "'tls-unique' channel binding not available")
3946 def test_tls_unique_channel_binding(self):
3947 """Test tls-unique channel binding."""
3948 if support.verbose:
3949 sys.stdout.write("\n")
3950
Christian Heimes05d9fe32018-02-27 08:55:39 +01003951 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003952
3953 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003954 chatty=True,
3955 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003956
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003957 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003958 with client_context.wrap_socket(
3959 socket.socket(),
3960 server_hostname=hostname) as s:
3961 s.connect((HOST, server.port))
3962 # get the data
3963 cb_data = s.get_channel_binding("tls-unique")
3964 if support.verbose:
3965 sys.stdout.write(
3966 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003967
Christian Heimes05d9fe32018-02-27 08:55:39 +01003968 # check if it is sane
3969 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003970 if s.version() == 'TLSv1.3':
3971 self.assertEqual(len(cb_data), 48)
3972 else:
3973 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003974
Christian Heimes05d9fe32018-02-27 08:55:39 +01003975 # and compare with the peers version
3976 s.write(b"CB tls-unique\n")
3977 peer_data_repr = s.read().strip()
3978 self.assertEqual(peer_data_repr,
3979 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003980
3981 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003982 with client_context.wrap_socket(
3983 socket.socket(),
3984 server_hostname=hostname) as s:
3985 s.connect((HOST, server.port))
3986 new_cb_data = s.get_channel_binding("tls-unique")
3987 if support.verbose:
3988 sys.stdout.write(
3989 "got another channel binding data: {0!r}\n".format(
3990 new_cb_data)
3991 )
3992 # is it really unique
3993 self.assertNotEqual(cb_data, new_cb_data)
3994 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003995 if s.version() == 'TLSv1.3':
3996 self.assertEqual(len(cb_data), 48)
3997 else:
3998 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003999 s.write(b"CB tls-unique\n")
4000 peer_data_repr = s.read().strip()
4001 self.assertEqual(peer_data_repr,
4002 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004003
4004 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004005 client_context, server_context, hostname = testing_context()
4006 stats = server_params_test(client_context, server_context,
4007 chatty=True, connectionchatty=True,
4008 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004009 if support.verbose:
4010 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
4011 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
4012
4013 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
4014 "ssl.OP_NO_COMPRESSION needed for this test")
4015 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004016 client_context, server_context, hostname = testing_context()
4017 client_context.options |= ssl.OP_NO_COMPRESSION
4018 server_context.options |= ssl.OP_NO_COMPRESSION
4019 stats = server_params_test(client_context, server_context,
4020 chatty=True, connectionchatty=True,
4021 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004022 self.assertIs(stats['compression'], None)
4023
Paul Monsonf3550692019-06-19 13:09:54 -07004024 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004025 def test_dh_params(self):
4026 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004027 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004028 # test scenario needs TLS <= 1.2
4029 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004030 server_context.load_dh_params(DHFILE)
4031 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004032 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004033 stats = server_params_test(client_context, server_context,
4034 chatty=True, connectionchatty=True,
4035 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004036 cipher = stats["cipher"][0]
4037 parts = cipher.split("-")
4038 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4039 self.fail("Non-DH cipher: " + cipher[0])
4040
Christian Heimesb7b92252018-02-25 09:49:31 +01004041 @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004042 @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
Christian Heimesb7b92252018-02-25 09:49:31 +01004043 def test_ecdh_curve(self):
4044 # server secp384r1, client auto
4045 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004046
Christian Heimesb7b92252018-02-25 09:49:31 +01004047 server_context.set_ecdh_curve("secp384r1")
4048 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4049 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4050 stats = server_params_test(client_context, server_context,
4051 chatty=True, connectionchatty=True,
4052 sni_name=hostname)
4053
4054 # server auto, client secp384r1
4055 client_context, server_context, hostname = testing_context()
4056 client_context.set_ecdh_curve("secp384r1")
4057 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4058 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4059 stats = server_params_test(client_context, server_context,
4060 chatty=True, connectionchatty=True,
4061 sni_name=hostname)
4062
4063 # server / client curve mismatch
4064 client_context, server_context, hostname = testing_context()
4065 client_context.set_ecdh_curve("prime256v1")
4066 server_context.set_ecdh_curve("secp384r1")
4067 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4068 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4069 try:
Christian Heimes39258d32021-04-17 11:36:35 +02004070 server_params_test(client_context, server_context,
4071 chatty=True, connectionchatty=True,
4072 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004073 except ssl.SSLError:
Christian Heimes39258d32021-04-17 11:36:35 +02004074 self.fail("mismatch curve did not fail")
Christian Heimesb7b92252018-02-25 09:49:31 +01004075
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004076 def test_selected_alpn_protocol(self):
4077 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004078 client_context, server_context, hostname = testing_context()
4079 stats = server_params_test(client_context, server_context,
4080 chatty=True, connectionchatty=True,
4081 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004082 self.assertIs(stats['client_alpn_protocol'], None)
4083
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004084 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4085 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004086 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004087 server_context.set_alpn_protocols(['foo', 'bar'])
4088 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004089 chatty=True, connectionchatty=True,
4090 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004091 self.assertIs(stats['client_alpn_protocol'], None)
4092
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004093 def test_alpn_protocols(self):
4094 server_protocols = ['foo', 'bar', 'milkshake']
4095 protocol_tests = [
4096 (['foo', 'bar'], 'foo'),
4097 (['bar', 'foo'], 'foo'),
4098 (['milkshake'], 'milkshake'),
4099 (['http/3.0', 'http/4.0'], None)
4100 ]
4101 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004102 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004103 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004104 client_context.set_alpn_protocols(client_protocols)
4105
4106 try:
4107 stats = server_params_test(client_context,
4108 server_context,
4109 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004110 connectionchatty=True,
4111 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004112 except ssl.SSLError as e:
4113 stats = e
4114
Christian Heimes39258d32021-04-17 11:36:35 +02004115 msg = "failed trying %s (s) and %s (c).\n" \
4116 "was expecting %s, but got %%s from the %%s" \
4117 % (str(server_protocols), str(client_protocols),
4118 str(expected))
4119 client_result = stats['client_alpn_protocol']
4120 self.assertEqual(client_result, expected,
4121 msg % (client_result, "client"))
4122 server_result = stats['server_alpn_protocols'][-1] \
4123 if len(stats['server_alpn_protocols']) else 'nothing'
4124 self.assertEqual(server_result, expected,
4125 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004126
4127 def test_selected_npn_protocol(self):
4128 # selected_npn_protocol() is None unless NPN is used
Christian Heimesa170fa12017-09-15 20:27:30 +02004129 client_context, server_context, hostname = testing_context()
4130 stats = server_params_test(client_context, server_context,
4131 chatty=True, connectionchatty=True,
4132 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004133 self.assertIs(stats['client_npn_protocol'], None)
4134
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004135 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004136 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004137
4138 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004139 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004140 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004141 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004142 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004143 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004144 client_context.load_verify_locations(SIGNING_CA)
4145 return server_context, other_context, client_context
4146
4147 def check_common_name(self, stats, name):
4148 cert = stats['peercert']
4149 self.assertIn((('commonName', name),), cert['subject'])
4150
4151 @needs_sni
4152 def test_sni_callback(self):
4153 calls = []
4154 server_context, other_context, client_context = self.sni_contexts()
4155
Christian Heimesa170fa12017-09-15 20:27:30 +02004156 client_context.check_hostname = False
4157
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004158 def servername_cb(ssl_sock, server_name, initial_context):
4159 calls.append((server_name, initial_context))
4160 if server_name is not None:
4161 ssl_sock.context = other_context
4162 server_context.set_servername_callback(servername_cb)
4163
4164 stats = server_params_test(client_context, server_context,
4165 chatty=True,
4166 sni_name='supermessage')
4167 # The hostname was fetched properly, and the certificate was
4168 # changed for the connection.
4169 self.assertEqual(calls, [("supermessage", server_context)])
4170 # CERTFILE4 was selected
4171 self.check_common_name(stats, 'fakehostname')
4172
4173 calls = []
4174 # The callback is called with server_name=None
4175 stats = server_params_test(client_context, server_context,
4176 chatty=True,
4177 sni_name=None)
4178 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004179 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004180
4181 # Check disabling the callback
4182 calls = []
4183 server_context.set_servername_callback(None)
4184
4185 stats = server_params_test(client_context, server_context,
4186 chatty=True,
4187 sni_name='notfunny')
4188 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004189 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004190 self.assertEqual(calls, [])
4191
4192 @needs_sni
4193 def test_sni_callback_alert(self):
4194 # Returning a TLS alert is reflected to the connecting client
4195 server_context, other_context, client_context = self.sni_contexts()
4196
4197 def cb_returning_alert(ssl_sock, server_name, initial_context):
4198 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4199 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004200 with self.assertRaises(ssl.SSLError) as cm:
4201 stats = server_params_test(client_context, server_context,
4202 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004203 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004204 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004205
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004206 @needs_sni
4207 def test_sni_callback_raising(self):
4208 # Raising fails the connection with a TLS handshake failure alert.
4209 server_context, other_context, client_context = self.sni_contexts()
4210
4211 def cb_raising(ssl_sock, server_name, initial_context):
4212 1/0
4213 server_context.set_servername_callback(cb_raising)
4214
Victor Stinner00253502019-06-03 03:51:43 +02004215 with support.catch_unraisable_exception() as catch:
4216 with self.assertRaises(ssl.SSLError) as cm:
4217 stats = server_params_test(client_context, server_context,
4218 chatty=False,
4219 sni_name='supermessage')
4220
4221 self.assertEqual(cm.exception.reason,
4222 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4223 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004224
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004225 @needs_sni
4226 def test_sni_callback_wrong_return_type(self):
4227 # Returning the wrong return type terminates the TLS connection
4228 # with an internal error alert.
4229 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004230
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004231 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4232 return "foo"
4233 server_context.set_servername_callback(cb_wrong_return_type)
4234
Victor Stinner00253502019-06-03 03:51:43 +02004235 with support.catch_unraisable_exception() as catch:
4236 with self.assertRaises(ssl.SSLError) as cm:
4237 stats = server_params_test(client_context, server_context,
4238 chatty=False,
4239 sni_name='supermessage')
4240
4241
4242 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4243 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004244
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004245 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004246 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004247 client_context.set_ciphers("AES128:AES256")
4248 server_context.set_ciphers("AES256")
4249 expected_algs = [
4250 "AES256", "AES-256",
4251 # TLS 1.3 ciphers are always enabled
4252 "TLS_CHACHA20", "TLS_AES",
4253 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004254
Christian Heimesa170fa12017-09-15 20:27:30 +02004255 stats = server_params_test(client_context, server_context,
4256 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004257 ciphers = stats['server_shared_ciphers'][0]
4258 self.assertGreater(len(ciphers), 0)
4259 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004260 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004261 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004262
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004263 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004264 client_context, server_context, hostname = testing_context()
4265 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004266
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004267 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004268 s = client_context.wrap_socket(socket.socket(),
4269 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004270 s.connect((HOST, server.port))
4271 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004272
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004273 self.assertRaises(ValueError, s.read, 1024)
4274 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004275
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004276 def test_sendfile(self):
4277 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004278 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004279 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004280 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesa170fa12017-09-15 20:27:30 +02004281 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004282 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01004283 context.load_verify_locations(SIGNING_CA)
4284 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004285 server = ThreadedEchoServer(context=context, chatty=False)
4286 with server:
4287 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004288 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004289 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004290 s.sendfile(file)
4291 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004292
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004293 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004294 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004295 # TODO: sessions aren't compatible with TLSv1.3 yet
4296 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004297
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004298 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004299 stats = server_params_test(client_context, server_context,
4300 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004301 session = stats['session']
4302 self.assertTrue(session.id)
4303 self.assertGreater(session.time, 0)
4304 self.assertGreater(session.timeout, 0)
4305 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004306 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004307 self.assertFalse(stats['session_reused'])
4308 sess_stat = server_context.session_stats()
4309 self.assertEqual(sess_stat['accept'], 1)
4310 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004311
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004312 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004313 stats = server_params_test(client_context, server_context,
4314 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004315 sess_stat = server_context.session_stats()
4316 self.assertEqual(sess_stat['accept'], 2)
4317 self.assertEqual(sess_stat['hits'], 1)
4318 self.assertTrue(stats['session_reused'])
4319 session2 = stats['session']
4320 self.assertEqual(session2.id, session.id)
4321 self.assertEqual(session2, session)
4322 self.assertIsNot(session2, session)
4323 self.assertGreaterEqual(session2.time, session.time)
4324 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004325
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004326 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004327 stats = server_params_test(client_context, server_context,
4328 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004329 self.assertFalse(stats['session_reused'])
4330 session3 = stats['session']
4331 self.assertNotEqual(session3.id, session.id)
4332 self.assertNotEqual(session3, session)
4333 sess_stat = server_context.session_stats()
4334 self.assertEqual(sess_stat['accept'], 3)
4335 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004336
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004337 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004338 stats = server_params_test(client_context, server_context,
4339 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004340 self.assertTrue(stats['session_reused'])
4341 session4 = stats['session']
4342 self.assertEqual(session4.id, session.id)
4343 self.assertEqual(session4, session)
4344 self.assertGreaterEqual(session4.time, session.time)
4345 self.assertGreaterEqual(session4.timeout, session.timeout)
4346 sess_stat = server_context.session_stats()
4347 self.assertEqual(sess_stat['accept'], 4)
4348 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004349
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004350 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004351 client_context, server_context, hostname = testing_context()
4352 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004353
Christian Heimes05d9fe32018-02-27 08:55:39 +01004354 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004355 client_context.options |= ssl.OP_NO_TLSv1_3
4356 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004357
Christian Heimesa170fa12017-09-15 20:27:30 +02004358 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004359 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004360 with client_context.wrap_socket(socket.socket(),
4361 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004362 # session is None before handshake
4363 self.assertEqual(s.session, None)
4364 self.assertEqual(s.session_reused, None)
4365 s.connect((HOST, server.port))
4366 session = s.session
4367 self.assertTrue(session)
4368 with self.assertRaises(TypeError) as e:
4369 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004370 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004371
Christian Heimesa170fa12017-09-15 20:27:30 +02004372 with client_context.wrap_socket(socket.socket(),
4373 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004374 s.connect((HOST, server.port))
4375 # cannot set session after handshake
4376 with self.assertRaises(ValueError) as e:
4377 s.session = session
4378 self.assertEqual(str(e.exception),
4379 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004380
Christian Heimesa170fa12017-09-15 20:27:30 +02004381 with client_context.wrap_socket(socket.socket(),
4382 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004383 # can set session before handshake and before the
4384 # connection was established
4385 s.session = session
4386 s.connect((HOST, server.port))
4387 self.assertEqual(s.session.id, session.id)
4388 self.assertEqual(s.session, session)
4389 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004390
Christian Heimesa170fa12017-09-15 20:27:30 +02004391 with client_context2.wrap_socket(socket.socket(),
4392 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004393 # cannot re-use session with a different SSLContext
4394 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004395 s.session = session
4396 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004397 self.assertEqual(str(e.exception),
4398 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004399
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004400
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004401@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004402class TestPostHandshakeAuth(unittest.TestCase):
4403 def test_pha_setter(self):
4404 protocols = [
4405 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
4406 ]
4407 for protocol in protocols:
4408 ctx = ssl.SSLContext(protocol)
4409 self.assertEqual(ctx.post_handshake_auth, False)
4410
4411 ctx.post_handshake_auth = True
4412 self.assertEqual(ctx.post_handshake_auth, True)
4413
4414 ctx.verify_mode = ssl.CERT_REQUIRED
4415 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4416 self.assertEqual(ctx.post_handshake_auth, True)
4417
4418 ctx.post_handshake_auth = False
4419 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4420 self.assertEqual(ctx.post_handshake_auth, False)
4421
4422 ctx.verify_mode = ssl.CERT_OPTIONAL
4423 ctx.post_handshake_auth = True
4424 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4425 self.assertEqual(ctx.post_handshake_auth, True)
4426
4427 def test_pha_required(self):
4428 client_context, server_context, hostname = testing_context()
4429 server_context.post_handshake_auth = True
4430 server_context.verify_mode = ssl.CERT_REQUIRED
4431 client_context.post_handshake_auth = True
4432 client_context.load_cert_chain(SIGNED_CERTFILE)
4433
4434 server = ThreadedEchoServer(context=server_context, chatty=False)
4435 with server:
4436 with client_context.wrap_socket(socket.socket(),
4437 server_hostname=hostname) as s:
4438 s.connect((HOST, server.port))
4439 s.write(b'HASCERT')
4440 self.assertEqual(s.recv(1024), b'FALSE\n')
4441 s.write(b'PHA')
4442 self.assertEqual(s.recv(1024), b'OK\n')
4443 s.write(b'HASCERT')
4444 self.assertEqual(s.recv(1024), b'TRUE\n')
4445 # PHA method just returns true when cert is already available
4446 s.write(b'PHA')
4447 self.assertEqual(s.recv(1024), b'OK\n')
4448 s.write(b'GETCERT')
4449 cert_text = s.recv(4096).decode('us-ascii')
4450 self.assertIn('Python Software Foundation CA', cert_text)
4451
4452 def test_pha_required_nocert(self):
4453 client_context, server_context, hostname = testing_context()
4454 server_context.post_handshake_auth = True
4455 server_context.verify_mode = ssl.CERT_REQUIRED
4456 client_context.post_handshake_auth = True
4457
Victor Stinner73ea5462019-07-09 14:33:49 +02004458 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4459 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004460 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004461 server = ThreadedEchoServer(context=server_context, chatty=False)
4462 with server:
4463 with client_context.wrap_socket(socket.socket(),
4464 server_hostname=hostname) as s:
4465 s.connect((HOST, server.port))
4466 s.write(b'PHA')
4467 # receive CertificateRequest
4468 self.assertEqual(s.recv(1024), b'OK\n')
4469 # send empty Certificate + Finish
4470 s.write(b'HASCERT')
4471 # receive alert
4472 with self.assertRaisesRegex(
4473 ssl.SSLError,
4474 'tlsv13 alert certificate required'):
4475 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004476
4477 def test_pha_optional(self):
4478 if support.verbose:
4479 sys.stdout.write("\n")
4480
4481 client_context, server_context, hostname = testing_context()
4482 server_context.post_handshake_auth = True
4483 server_context.verify_mode = ssl.CERT_REQUIRED
4484 client_context.post_handshake_auth = True
4485 client_context.load_cert_chain(SIGNED_CERTFILE)
4486
4487 # check CERT_OPTIONAL
4488 server_context.verify_mode = ssl.CERT_OPTIONAL
4489 server = ThreadedEchoServer(context=server_context, chatty=False)
4490 with server:
4491 with client_context.wrap_socket(socket.socket(),
4492 server_hostname=hostname) as s:
4493 s.connect((HOST, server.port))
4494 s.write(b'HASCERT')
4495 self.assertEqual(s.recv(1024), b'FALSE\n')
4496 s.write(b'PHA')
4497 self.assertEqual(s.recv(1024), b'OK\n')
4498 s.write(b'HASCERT')
4499 self.assertEqual(s.recv(1024), b'TRUE\n')
4500
4501 def test_pha_optional_nocert(self):
4502 if support.verbose:
4503 sys.stdout.write("\n")
4504
4505 client_context, server_context, hostname = testing_context()
4506 server_context.post_handshake_auth = True
4507 server_context.verify_mode = ssl.CERT_OPTIONAL
4508 client_context.post_handshake_auth = True
4509
4510 server = ThreadedEchoServer(context=server_context, chatty=False)
4511 with server:
4512 with client_context.wrap_socket(socket.socket(),
4513 server_hostname=hostname) as s:
4514 s.connect((HOST, server.port))
4515 s.write(b'HASCERT')
4516 self.assertEqual(s.recv(1024), b'FALSE\n')
4517 s.write(b'PHA')
4518 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004519 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004520 s.write(b'HASCERT')
4521 self.assertEqual(s.recv(1024), b'FALSE\n')
4522
4523 def test_pha_no_pha_client(self):
4524 client_context, server_context, hostname = testing_context()
4525 server_context.post_handshake_auth = True
4526 server_context.verify_mode = ssl.CERT_REQUIRED
4527 client_context.load_cert_chain(SIGNED_CERTFILE)
4528
4529 server = ThreadedEchoServer(context=server_context, chatty=False)
4530 with server:
4531 with client_context.wrap_socket(socket.socket(),
4532 server_hostname=hostname) as s:
4533 s.connect((HOST, server.port))
4534 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4535 s.verify_client_post_handshake()
4536 s.write(b'PHA')
4537 self.assertIn(b'extension not received', s.recv(1024))
4538
4539 def test_pha_no_pha_server(self):
4540 # server doesn't have PHA enabled, cert is requested in handshake
4541 client_context, server_context, hostname = testing_context()
4542 server_context.verify_mode = ssl.CERT_REQUIRED
4543 client_context.post_handshake_auth = True
4544 client_context.load_cert_chain(SIGNED_CERTFILE)
4545
4546 server = ThreadedEchoServer(context=server_context, chatty=False)
4547 with server:
4548 with client_context.wrap_socket(socket.socket(),
4549 server_hostname=hostname) as s:
4550 s.connect((HOST, server.port))
4551 s.write(b'HASCERT')
4552 self.assertEqual(s.recv(1024), b'TRUE\n')
4553 # PHA doesn't fail if there is already a cert
4554 s.write(b'PHA')
4555 self.assertEqual(s.recv(1024), b'OK\n')
4556 s.write(b'HASCERT')
4557 self.assertEqual(s.recv(1024), b'TRUE\n')
4558
4559 def test_pha_not_tls13(self):
4560 # TLS 1.2
4561 client_context, server_context, hostname = testing_context()
4562 server_context.verify_mode = ssl.CERT_REQUIRED
4563 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4564 client_context.post_handshake_auth = True
4565 client_context.load_cert_chain(SIGNED_CERTFILE)
4566
4567 server = ThreadedEchoServer(context=server_context, chatty=False)
4568 with server:
4569 with client_context.wrap_socket(socket.socket(),
4570 server_hostname=hostname) as s:
4571 s.connect((HOST, server.port))
4572 # PHA fails for TLS != 1.3
4573 s.write(b'PHA')
4574 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4575
Christian Heimesf0f59302019-07-01 08:29:17 +02004576 def test_bpo37428_pha_cert_none(self):
4577 # verify that post_handshake_auth does not implicitly enable cert
4578 # validation.
4579 hostname = SIGNED_CERTFILE_HOSTNAME
4580 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4581 client_context.post_handshake_auth = True
4582 client_context.load_cert_chain(SIGNED_CERTFILE)
4583 # no cert validation and CA on client side
4584 client_context.check_hostname = False
4585 client_context.verify_mode = ssl.CERT_NONE
4586
4587 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4588 server_context.load_cert_chain(SIGNED_CERTFILE)
4589 server_context.load_verify_locations(SIGNING_CA)
4590 server_context.post_handshake_auth = True
4591 server_context.verify_mode = ssl.CERT_REQUIRED
4592
4593 server = ThreadedEchoServer(context=server_context, chatty=False)
4594 with server:
4595 with client_context.wrap_socket(socket.socket(),
4596 server_hostname=hostname) as s:
4597 s.connect((HOST, server.port))
4598 s.write(b'HASCERT')
4599 self.assertEqual(s.recv(1024), b'FALSE\n')
4600 s.write(b'PHA')
4601 self.assertEqual(s.recv(1024), b'OK\n')
4602 s.write(b'HASCERT')
4603 self.assertEqual(s.recv(1024), b'TRUE\n')
4604 # server cert has not been validated
4605 self.assertEqual(s.getpeercert(), {})
4606
Christian Heimes9fb051f2018-09-23 08:32:31 +02004607
Christian Heimesc7f70692019-05-31 11:44:05 +02004608HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4609requires_keylog = unittest.skipUnless(
4610 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4611
4612class TestSSLDebug(unittest.TestCase):
4613
Hai Shia7f5d932020-08-04 00:41:24 +08004614 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004615 with open(fname) as f:
4616 return len(list(f))
4617
4618 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004619 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004620 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004621 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004622 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4623 self.assertEqual(ctx.keylog_filename, None)
4624
Hai Shia7f5d932020-08-04 00:41:24 +08004625 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4626 ctx.keylog_filename = os_helper.TESTFN
4627 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4628 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004629 self.assertEqual(self.keylog_lines(), 1)
4630
4631 ctx.keylog_filename = None
4632 self.assertEqual(ctx.keylog_filename, None)
4633
4634 with self.assertRaises((IsADirectoryError, PermissionError)):
4635 # Windows raises PermissionError
4636 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004637 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004638
4639 with self.assertRaises(TypeError):
4640 ctx.keylog_filename = 1
4641
4642 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004643 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004644 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004645 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004646 client_context, server_context, hostname = testing_context()
4647
Hai Shia7f5d932020-08-04 00:41:24 +08004648 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004649 server = ThreadedEchoServer(context=server_context, chatty=False)
4650 with server:
4651 with client_context.wrap_socket(socket.socket(),
4652 server_hostname=hostname) as s:
4653 s.connect((HOST, server.port))
4654 # header, 5 lines for TLS 1.3
4655 self.assertEqual(self.keylog_lines(), 6)
4656
4657 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004658 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004659 server = ThreadedEchoServer(context=server_context, chatty=False)
4660 with server:
4661 with client_context.wrap_socket(socket.socket(),
4662 server_hostname=hostname) as s:
4663 s.connect((HOST, server.port))
4664 self.assertGreaterEqual(self.keylog_lines(), 11)
4665
Hai Shia7f5d932020-08-04 00:41:24 +08004666 client_context.keylog_filename = os_helper.TESTFN
4667 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004668 server = ThreadedEchoServer(context=server_context, chatty=False)
4669 with server:
4670 with client_context.wrap_socket(socket.socket(),
4671 server_hostname=hostname) as s:
4672 s.connect((HOST, server.port))
4673 self.assertGreaterEqual(self.keylog_lines(), 21)
4674
4675 client_context.keylog_filename = None
4676 server_context.keylog_filename = None
4677
4678 @requires_keylog
4679 @unittest.skipIf(sys.flags.ignore_environment,
4680 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004681 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004682 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004683 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004684 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004685 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4686 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004687
4688 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4689 self.assertEqual(ctx.keylog_filename, None)
4690
4691 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004692 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004693
4694 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004695 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004696
4697 def test_msg_callback(self):
4698 client_context, server_context, hostname = testing_context()
4699
4700 def msg_cb(conn, direction, version, content_type, msg_type, data):
4701 pass
4702
4703 self.assertIs(client_context._msg_callback, None)
4704 client_context._msg_callback = msg_cb
4705 self.assertIs(client_context._msg_callback, msg_cb)
4706 with self.assertRaises(TypeError):
4707 client_context._msg_callback = object()
4708
4709 def test_msg_callback_tls12(self):
4710 client_context, server_context, hostname = testing_context()
4711 client_context.options |= ssl.OP_NO_TLSv1_3
4712
4713 msg = []
4714
4715 def msg_cb(conn, direction, version, content_type, msg_type, data):
4716 self.assertIsInstance(conn, ssl.SSLSocket)
4717 self.assertIsInstance(data, bytes)
4718 self.assertIn(direction, {'read', 'write'})
4719 msg.append((direction, version, content_type, msg_type))
4720
4721 client_context._msg_callback = msg_cb
4722
4723 server = ThreadedEchoServer(context=server_context, chatty=False)
4724 with server:
4725 with client_context.wrap_socket(socket.socket(),
4726 server_hostname=hostname) as s:
4727 s.connect((HOST, server.port))
4728
Christian Heimese35d1ba2019-06-03 20:40:15 +02004729 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004730 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4731 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004732 msg
4733 )
4734 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004735 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4736 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004737 msg
4738 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004739
Christian Heimes77cde502021-03-21 16:13:09 +01004740 def test_msg_callback_deadlock_bpo43577(self):
4741 client_context, server_context, hostname = testing_context()
4742 server_context2 = testing_context()[1]
4743
4744 def msg_cb(conn, direction, version, content_type, msg_type, data):
4745 pass
4746
4747 def sni_cb(sock, servername, ctx):
4748 sock.context = server_context2
4749
4750 server_context._msg_callback = msg_cb
4751 server_context.sni_callback = sni_cb
4752
4753 server = ThreadedEchoServer(context=server_context, chatty=False)
4754 with server:
4755 with client_context.wrap_socket(socket.socket(),
4756 server_hostname=hostname) as s:
4757 s.connect((HOST, server.port))
4758 with client_context.wrap_socket(socket.socket(),
4759 server_hostname=hostname) as s:
4760 s.connect((HOST, server.port))
4761
Christian Heimesc7f70692019-05-31 11:44:05 +02004762
Thomas Woutersed03b412007-08-28 21:37:11 +00004763def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004764 if support.verbose:
4765 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004766 'Mac': platform.mac_ver,
4767 'Windows': platform.win32_ver,
4768 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004769 for name, func in plats.items():
4770 plat = func()
4771 if plat and plat[0]:
4772 plat = '%s %r' % (name, plat)
4773 break
4774 else:
4775 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004776 print("test_ssl: testing with %r %r" %
4777 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4778 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004779 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004780 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4781 try:
4782 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4783 except AttributeError:
4784 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004785
Antoine Pitrou152efa22010-05-16 18:19:27 +00004786 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004787 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004788 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004789 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004790 BADCERT, BADKEY, EMPTYCERT]:
4791 if not os.path.exists(filename):
4792 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004793
Martin Panter3840b2a2016-03-27 01:53:46 +00004794 tests = [
4795 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004796 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004797 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004798 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004799
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004800 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004801 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004802
Hai Shie80697d2020-05-28 06:10:27 +08004803 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004804 try:
4805 support.run_unittest(*tests)
4806 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004807 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004808
4809if __name__ == "__main__":
4810 test_main()