blob: 7b70979026dcf130d2fb3a64f21764350a636432 [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 Heimes89d15502021-04-19 06:55:30 +02001113 def test_read_write_zero(self):
1114 # empty reads and writes now work, bpo-42854, bpo-31711
1115 client_context, server_context, hostname = testing_context()
1116 server = ThreadedEchoServer(context=server_context)
1117 with server:
1118 with client_context.wrap_socket(socket.socket(),
1119 server_hostname=hostname) as s:
1120 s.connect((HOST, server.port))
1121 self.assertEqual(s.recv(0), b"")
1122 self.assertEqual(s.send(b""), 0)
1123
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001124
Antoine Pitrou152efa22010-05-16 18:19:27 +00001125class ContextTests(unittest.TestCase):
1126
1127 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001128 for protocol in PROTOCOLS:
1129 ssl.SSLContext(protocol)
Christian Heimes598894f2016-09-05 23:19:05 +02001130 ctx = ssl.SSLContext()
1131 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001132 self.assertRaises(ValueError, ssl.SSLContext, -1)
1133 self.assertRaises(ValueError, ssl.SSLContext, 42)
1134
1135 def test_protocol(self):
1136 for proto in PROTOCOLS:
1137 ctx = ssl.SSLContext(proto)
1138 self.assertEqual(ctx.protocol, proto)
1139
1140 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001141 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001142 ctx.set_ciphers("ALL")
1143 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001144 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001145 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001146
Christian Heimes892d66e2018-01-29 14:10:18 +01001147 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1148 "Test applies only to Python default ciphers")
1149 def test_python_ciphers(self):
1150 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1151 ciphers = ctx.get_ciphers()
1152 for suite in ciphers:
1153 name = suite['name']
1154 self.assertNotIn("PSK", name)
1155 self.assertNotIn("SRP", name)
1156 self.assertNotIn("MD5", name)
1157 self.assertNotIn("RC4", name)
1158 self.assertNotIn("3DES", name)
1159
Christian Heimes25bfcd52016-09-06 00:04:45 +02001160 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001161 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001162 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001163 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001164 self.assertIn('AES256-GCM-SHA384', names)
1165 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001166
Antoine Pitroub5218772010-05-21 09:56:06 +00001167 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001168 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001169 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001170 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001171 # SSLContext also enables these by default
1172 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001173 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001174 OP_ENABLE_MIDDLEBOX_COMPAT |
1175 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001176 self.assertEqual(default, ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001177 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001178 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Christian Heimes39258d32021-04-17 11:36:35 +02001179 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
1180 self.assertEqual(default, ctx.options)
1181 ctx.options = 0
1182 # Ubuntu has OP_NO_SSLv3 forced on by default
1183 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001184
Christian Heimesa170fa12017-09-15 20:27:30 +02001185 def test_verify_mode_protocol(self):
1186 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001187 # Default value
1188 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1189 ctx.verify_mode = ssl.CERT_OPTIONAL
1190 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1191 ctx.verify_mode = ssl.CERT_REQUIRED
1192 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1193 ctx.verify_mode = ssl.CERT_NONE
1194 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1195 with self.assertRaises(TypeError):
1196 ctx.verify_mode = None
1197 with self.assertRaises(ValueError):
1198 ctx.verify_mode = 42
1199
Christian Heimesa170fa12017-09-15 20:27:30 +02001200 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1201 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1202 self.assertFalse(ctx.check_hostname)
1203
1204 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1205 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1206 self.assertTrue(ctx.check_hostname)
1207
Christian Heimes61d478c2018-01-27 15:51:38 +01001208 def test_hostname_checks_common_name(self):
1209 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1210 self.assertTrue(ctx.hostname_checks_common_name)
1211 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1212 ctx.hostname_checks_common_name = True
1213 self.assertTrue(ctx.hostname_checks_common_name)
1214 ctx.hostname_checks_common_name = False
1215 self.assertFalse(ctx.hostname_checks_common_name)
1216 ctx.hostname_checks_common_name = True
1217 self.assertTrue(ctx.hostname_checks_common_name)
1218 else:
1219 with self.assertRaises(AttributeError):
1220 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001221
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001222 @requires_minimum_version
Christian Heimesc9bc49c2019-09-11 19:24:47 +02001223 @unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
Christian Heimes698dde12018-02-27 11:54:43 +01001224 def test_min_max_version(self):
1225 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001226 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1227 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001228 minimum_range = {
1229 # stock OpenSSL
1230 ssl.TLSVersion.MINIMUM_SUPPORTED,
1231 # Fedora 29 uses TLS 1.0 by default
1232 ssl.TLSVersion.TLSv1,
1233 # RHEL 8 uses TLS 1.2 by default
1234 ssl.TLSVersion.TLSv1_2
1235 }
torsava34864d12019-12-02 17:15:42 +01001236 maximum_range = {
1237 # stock OpenSSL
1238 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1239 # Fedora 32 uses TLS 1.3 by default
1240 ssl.TLSVersion.TLSv1_3
1241 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001242
Christian Heimes34de2d32019-01-18 16:09:30 +01001243 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001244 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001245 )
torsava34864d12019-12-02 17:15:42 +01001246 self.assertIn(
1247 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001248 )
1249
1250 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1251 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1252 self.assertEqual(
1253 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1254 )
1255 self.assertEqual(
1256 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1257 )
1258
1259 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1260 ctx.maximum_version = ssl.TLSVersion.TLSv1
1261 self.assertEqual(
1262 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1263 )
1264 self.assertEqual(
1265 ctx.maximum_version, ssl.TLSVersion.TLSv1
1266 )
1267
1268 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1269 self.assertEqual(
1270 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1271 )
1272
1273 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1274 self.assertIn(
1275 ctx.maximum_version,
1276 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1277 )
1278
1279 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1280 self.assertIn(
1281 ctx.minimum_version,
1282 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1283 )
1284
1285 with self.assertRaises(ValueError):
1286 ctx.minimum_version = 42
1287
1288 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1289
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001290 self.assertIn(
1291 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001292 )
1293 self.assertEqual(
1294 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1295 )
1296 with self.assertRaises(ValueError):
1297 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1298 with self.assertRaises(ValueError):
1299 ctx.maximum_version = ssl.TLSVersion.TLSv1
1300
1301
matthewhughes9348e836bb2020-07-17 09:59:15 +01001302 @unittest.skipUnless(
1303 hasattr(ssl.SSLContext, 'security_level'),
1304 "requires OpenSSL >= 1.1.0"
1305 )
1306 def test_security_level(self):
1307 ctx = ssl.SSLContext()
1308 # The default security callback allows for levels between 0-5
1309 # with OpenSSL defaulting to 1, however some vendors override the
1310 # default value (e.g. Debian defaults to 2)
1311 security_level_range = {
1312 0,
1313 1, # OpenSSL default
1314 2, # Debian
1315 3,
1316 4,
1317 5,
1318 }
1319 self.assertIn(ctx.security_level, security_level_range)
1320
Christian Heimes22587792013-11-21 23:56:13 +01001321 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001322 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001323 # default value
1324 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1325 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001326 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1327 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1328 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1329 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1330 ctx.verify_flags = ssl.VERIFY_DEFAULT
1331 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001332 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1333 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001334 # supports any value
1335 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1336 self.assertEqual(ctx.verify_flags,
1337 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1338 with self.assertRaises(TypeError):
1339 ctx.verify_flags = None
1340
Antoine Pitrou152efa22010-05-16 18:19:27 +00001341 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001342 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001343 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001344 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001345 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1346 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001347 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001348 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001349 self.assertEqual(cm.exception.errno, errno.ENOENT)
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(BADCERT)
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(EMPTYCERT)
1354 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001355 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001356 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1357 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1358 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001359 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001360 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001361 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001362 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001363 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001364 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1365 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001366 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001367 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001368 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001369 # Password protected key and cert
1370 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1371 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1372 ctx.load_cert_chain(CERTFILE_PROTECTED,
1373 password=bytearray(KEY_PASSWORD.encode()))
1374 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1375 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1376 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1377 bytearray(KEY_PASSWORD.encode()))
1378 with self.assertRaisesRegex(TypeError, "should be a string"):
1379 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1380 with self.assertRaises(ssl.SSLError):
1381 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1382 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1383 # openssl has a fixed limit on the password buffer.
1384 # PEM_BUFSIZE is generally set to 1kb.
1385 # Return a string larger than this.
1386 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1387 # Password callback
1388 def getpass_unicode():
1389 return KEY_PASSWORD
1390 def getpass_bytes():
1391 return KEY_PASSWORD.encode()
1392 def getpass_bytearray():
1393 return bytearray(KEY_PASSWORD.encode())
1394 def getpass_badpass():
1395 return "badpass"
1396 def getpass_huge():
1397 return b'a' * (1024 * 1024)
1398 def getpass_bad_type():
1399 return 9
1400 def getpass_exception():
1401 raise Exception('getpass error')
1402 class GetPassCallable:
1403 def __call__(self):
1404 return KEY_PASSWORD
1405 def getpass(self):
1406 return KEY_PASSWORD
1407 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1408 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1409 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1410 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1411 ctx.load_cert_chain(CERTFILE_PROTECTED,
1412 password=GetPassCallable().getpass)
1413 with self.assertRaises(ssl.SSLError):
1414 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1415 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1416 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1417 with self.assertRaisesRegex(TypeError, "must return a string"):
1418 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1419 with self.assertRaisesRegex(Exception, "getpass error"):
1420 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1421 # Make sure the password function isn't called if it isn't needed
1422 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001423
1424 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001425 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001426 ctx.load_verify_locations(CERTFILE)
1427 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1428 ctx.load_verify_locations(BYTES_CERTFILE)
1429 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1430 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001431 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001432 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001433 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001434 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001435 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001436 ctx.load_verify_locations(BADCERT)
1437 ctx.load_verify_locations(CERTFILE, CAPATH)
1438 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1439
Victor Stinner80f75e62011-01-29 11:31:20 +00001440 # Issue #10989: crash if the second argument type is invalid
1441 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1442
Christian Heimesefff7062013-11-21 03:35:02 +01001443 def test_load_verify_cadata(self):
1444 # test cadata
1445 with open(CAFILE_CACERT) as f:
1446 cacert_pem = f.read()
1447 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1448 with open(CAFILE_NEURONIO) as f:
1449 neuronio_pem = f.read()
1450 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1451
1452 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001453 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001454 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1455 ctx.load_verify_locations(cadata=cacert_pem)
1456 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1457 ctx.load_verify_locations(cadata=neuronio_pem)
1458 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1459 # cert already in hash table
1460 ctx.load_verify_locations(cadata=neuronio_pem)
1461 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1462
1463 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001464 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001465 combined = "\n".join((cacert_pem, neuronio_pem))
1466 ctx.load_verify_locations(cadata=combined)
1467 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1468
1469 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001470 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001471 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1472 neuronio_pem, "tail"]
1473 ctx.load_verify_locations(cadata="\n".join(combined))
1474 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1475
1476 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001477 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001478 ctx.load_verify_locations(cadata=cacert_der)
1479 ctx.load_verify_locations(cadata=neuronio_der)
1480 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1481 # cert already in hash table
1482 ctx.load_verify_locations(cadata=cacert_der)
1483 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1484
1485 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001486 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001487 combined = b"".join((cacert_der, neuronio_der))
1488 ctx.load_verify_locations(cadata=combined)
1489 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1490
1491 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001492 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001493 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1494
1495 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1496 ctx.load_verify_locations(cadata="broken")
1497 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1498 ctx.load_verify_locations(cadata=b"broken")
1499
1500
Paul Monsonf3550692019-06-19 13:09:54 -07001501 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001502 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001503 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001504 ctx.load_dh_params(DHFILE)
1505 if os.name != 'nt':
1506 ctx.load_dh_params(BYTES_DHFILE)
1507 self.assertRaises(TypeError, ctx.load_dh_params)
1508 self.assertRaises(TypeError, ctx.load_dh_params, None)
1509 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001510 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001511 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001512 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001513 ctx.load_dh_params(CERTFILE)
1514
Antoine Pitroub0182c82010-10-12 20:09:02 +00001515 def test_session_stats(self):
1516 for proto in PROTOCOLS:
1517 ctx = ssl.SSLContext(proto)
1518 self.assertEqual(ctx.session_stats(), {
1519 'number': 0,
1520 'connect': 0,
1521 'connect_good': 0,
1522 'connect_renegotiate': 0,
1523 'accept': 0,
1524 'accept_good': 0,
1525 'accept_renegotiate': 0,
1526 'hits': 0,
1527 'misses': 0,
1528 'timeouts': 0,
1529 'cache_full': 0,
1530 })
1531
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001532 def test_set_default_verify_paths(self):
1533 # There's not much we can do to test that it acts as expected,
1534 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001535 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001536 ctx.set_default_verify_paths()
1537
Antoine Pitrou501da612011-12-21 09:27:41 +01001538 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001539 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001540 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001541 ctx.set_ecdh_curve("prime256v1")
1542 ctx.set_ecdh_curve(b"prime256v1")
1543 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1544 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1545 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1546 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1547
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001548 @needs_sni
1549 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001550 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001551
1552 # set_servername_callback expects a callable, or None
1553 self.assertRaises(TypeError, ctx.set_servername_callback)
1554 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1555 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1556 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1557
1558 def dummycallback(sock, servername, ctx):
1559 pass
1560 ctx.set_servername_callback(None)
1561 ctx.set_servername_callback(dummycallback)
1562
1563 @needs_sni
1564 def test_sni_callback_refcycle(self):
1565 # Reference cycles through the servername callback are detected
1566 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001567 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001568 def dummycallback(sock, servername, ctx, cycle=ctx):
1569 pass
1570 ctx.set_servername_callback(dummycallback)
1571 wr = weakref.ref(ctx)
1572 del ctx, dummycallback
1573 gc.collect()
1574 self.assertIs(wr(), None)
1575
Christian Heimes9a5395a2013-06-17 15:44:12 +02001576 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001577 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001578 self.assertEqual(ctx.cert_store_stats(),
1579 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1580 ctx.load_cert_chain(CERTFILE)
1581 self.assertEqual(ctx.cert_store_stats(),
1582 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1583 ctx.load_verify_locations(CERTFILE)
1584 self.assertEqual(ctx.cert_store_stats(),
1585 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001586 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001587 self.assertEqual(ctx.cert_store_stats(),
1588 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1589
1590 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001591 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001592 self.assertEqual(ctx.get_ca_certs(), [])
1593 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1594 ctx.load_verify_locations(CERTFILE)
1595 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001596 # but CAFILE_CACERT is a CA cert
1597 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001598 self.assertEqual(ctx.get_ca_certs(),
1599 [{'issuer': ((('organizationName', 'Root CA'),),
1600 (('organizationalUnitName', 'http://www.cacert.org'),),
1601 (('commonName', 'CA Cert Signing Authority'),),
1602 (('emailAddress', 'support@cacert.org'),)),
1603 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1604 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1605 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001606 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001607 'subject': ((('organizationName', 'Root CA'),),
1608 (('organizationalUnitName', 'http://www.cacert.org'),),
1609 (('commonName', 'CA Cert Signing Authority'),),
1610 (('emailAddress', 'support@cacert.org'),)),
1611 'version': 3}])
1612
Martin Panterb55f8b72016-01-14 12:53:56 +00001613 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001614 pem = f.read()
1615 der = ssl.PEM_cert_to_DER_cert(pem)
1616 self.assertEqual(ctx.get_ca_certs(True), [der])
1617
Christian Heimes72d28502013-11-23 13:56:58 +01001618 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001619 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001620 ctx.load_default_certs()
1621
Christian Heimesa170fa12017-09-15 20:27:30 +02001622 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001623 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1624 ctx.load_default_certs()
1625
Christian Heimesa170fa12017-09-15 20:27:30 +02001626 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001627 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1628
Christian Heimesa170fa12017-09-15 20:27:30 +02001629 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001630 self.assertRaises(TypeError, ctx.load_default_certs, None)
1631 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1632
Benjamin Peterson91244e02014-10-03 18:17:15 -04001633 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimes598894f2016-09-05 23:19:05 +02001634 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001635 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001636 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001637 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001638 env["SSL_CERT_DIR"] = CAPATH
1639 env["SSL_CERT_FILE"] = CERTFILE
1640 ctx.load_default_certs()
1641 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1642
Benjamin Peterson91244e02014-10-03 18:17:15 -04001643 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001644 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001645 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001646 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001647 ctx.load_default_certs()
1648 stats = ctx.cert_store_stats()
1649
Christian Heimesa170fa12017-09-15 20:27:30 +02001650 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001651 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001652 env["SSL_CERT_DIR"] = CAPATH
1653 env["SSL_CERT_FILE"] = CERTFILE
1654 ctx.load_default_certs()
1655 stats["x509"] += 1
1656 self.assertEqual(ctx.cert_store_stats(), stats)
1657
Christian Heimes358cfd42016-09-10 22:43:48 +02001658 def _assert_context_options(self, ctx):
1659 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1660 if OP_NO_COMPRESSION != 0:
1661 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1662 OP_NO_COMPRESSION)
1663 if OP_SINGLE_DH_USE != 0:
1664 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1665 OP_SINGLE_DH_USE)
1666 if OP_SINGLE_ECDH_USE != 0:
1667 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1668 OP_SINGLE_ECDH_USE)
1669 if OP_CIPHER_SERVER_PREFERENCE != 0:
1670 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1671 OP_CIPHER_SERVER_PREFERENCE)
1672
Christian Heimes4c05b472013-11-23 15:58:30 +01001673 def test_create_default_context(self):
1674 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001675
Christian Heimesa170fa12017-09-15 20:27:30 +02001676 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001677 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001678 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001679 self._assert_context_options(ctx)
1680
Christian Heimes4c05b472013-11-23 15:58:30 +01001681 with open(SIGNING_CA) as f:
1682 cadata = f.read()
1683 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1684 cadata=cadata)
Christian Heimesa170fa12017-09-15 20:27:30 +02001685 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001686 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001687 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001688
1689 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001690 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001691 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001692 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001693
Christian Heimes67986f92013-11-23 22:43:47 +01001694 def test__create_stdlib_context(self):
1695 ctx = ssl._create_stdlib_context()
Christian Heimesa170fa12017-09-15 20:27:30 +02001696 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001697 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001698 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001699 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001700
1701 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1702 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1703 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001704 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001705
1706 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001707 cert_reqs=ssl.CERT_REQUIRED,
1708 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001709 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1710 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001711 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001712 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001713
1714 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001715 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001716 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001717 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001718
Christian Heimes1aa9a752013-12-02 02:41:19 +01001719 def test_check_hostname(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001720 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001721 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001722 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001723
Christian Heimese82c0342017-09-15 20:29:57 +02001724 # Auto set CERT_REQUIRED
1725 ctx.check_hostname = True
1726 self.assertTrue(ctx.check_hostname)
1727 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1728 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001729 ctx.verify_mode = ssl.CERT_REQUIRED
1730 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001731 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001732
Christian Heimese82c0342017-09-15 20:29:57 +02001733 # Changing verify_mode does not affect check_hostname
1734 ctx.check_hostname = False
1735 ctx.verify_mode = ssl.CERT_NONE
1736 ctx.check_hostname = False
1737 self.assertFalse(ctx.check_hostname)
1738 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1739 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001740 ctx.check_hostname = True
1741 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001742 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1743
1744 ctx.check_hostname = False
1745 ctx.verify_mode = ssl.CERT_OPTIONAL
1746 ctx.check_hostname = False
1747 self.assertFalse(ctx.check_hostname)
1748 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1749 # keep CERT_OPTIONAL
1750 ctx.check_hostname = True
1751 self.assertTrue(ctx.check_hostname)
1752 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001753
1754 # Cannot set CERT_NONE with check_hostname enabled
1755 with self.assertRaises(ValueError):
1756 ctx.verify_mode = ssl.CERT_NONE
1757 ctx.check_hostname = False
1758 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001759 ctx.verify_mode = ssl.CERT_NONE
1760 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001761
Christian Heimes5fe668c2016-09-12 00:01:11 +02001762 def test_context_client_server(self):
1763 # PROTOCOL_TLS_CLIENT has sane defaults
1764 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1765 self.assertTrue(ctx.check_hostname)
1766 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1767
1768 # PROTOCOL_TLS_SERVER has different but also sane defaults
1769 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1770 self.assertFalse(ctx.check_hostname)
1771 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1772
Christian Heimes4df60f12017-09-15 20:26:05 +02001773 def test_context_custom_class(self):
1774 class MySSLSocket(ssl.SSLSocket):
1775 pass
1776
1777 class MySSLObject(ssl.SSLObject):
1778 pass
1779
1780 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1781 ctx.sslsocket_class = MySSLSocket
1782 ctx.sslobject_class = MySSLObject
1783
1784 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1785 self.assertIsInstance(sock, MySSLSocket)
1786 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1787 self.assertIsInstance(obj, MySSLObject)
1788
Christian Heimes78c7d522019-06-03 21:00:10 +02001789 def test_num_tickest(self):
1790 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1791 self.assertEqual(ctx.num_tickets, 2)
1792 ctx.num_tickets = 1
1793 self.assertEqual(ctx.num_tickets, 1)
1794 ctx.num_tickets = 0
1795 self.assertEqual(ctx.num_tickets, 0)
1796 with self.assertRaises(ValueError):
1797 ctx.num_tickets = -1
1798 with self.assertRaises(TypeError):
1799 ctx.num_tickets = None
1800
1801 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1802 self.assertEqual(ctx.num_tickets, 2)
1803 with self.assertRaises(ValueError):
1804 ctx.num_tickets = 1
1805
Antoine Pitrou152efa22010-05-16 18:19:27 +00001806
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001807class SSLErrorTests(unittest.TestCase):
1808
1809 def test_str(self):
1810 # The str() of a SSLError doesn't include the errno
1811 e = ssl.SSLError(1, "foo")
1812 self.assertEqual(str(e), "foo")
1813 self.assertEqual(e.errno, 1)
1814 # Same for a subclass
1815 e = ssl.SSLZeroReturnError(1, "foo")
1816 self.assertEqual(str(e), "foo")
1817 self.assertEqual(e.errno, 1)
1818
Paul Monsonf3550692019-06-19 13:09:54 -07001819 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001820 def test_lib_reason(self):
1821 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001822 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001823 with self.assertRaises(ssl.SSLError) as cm:
1824 ctx.load_dh_params(CERTFILE)
1825 self.assertEqual(cm.exception.library, 'PEM')
1826 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1827 s = str(cm.exception)
1828 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1829
1830 def test_subclass(self):
1831 # Check that the appropriate SSLError subclass is raised
1832 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001833 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1834 ctx.check_hostname = False
1835 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001836 with socket.create_server(("127.0.0.1", 0)) as s:
1837 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001838 c.setblocking(False)
1839 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001840 with self.assertRaises(ssl.SSLWantReadError) as cm:
1841 c.do_handshake()
1842 s = str(cm.exception)
1843 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1844 # For compatibility
1845 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1846
1847
Christian Heimes61d478c2018-01-27 15:51:38 +01001848 def test_bad_server_hostname(self):
1849 ctx = ssl.create_default_context()
1850 with self.assertRaises(ValueError):
1851 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1852 server_hostname="")
1853 with self.assertRaises(ValueError):
1854 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1855 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001856 with self.assertRaises(TypeError):
1857 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1858 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001859
1860
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001861class MemoryBIOTests(unittest.TestCase):
1862
1863 def test_read_write(self):
1864 bio = ssl.MemoryBIO()
1865 bio.write(b'foo')
1866 self.assertEqual(bio.read(), b'foo')
1867 self.assertEqual(bio.read(), b'')
1868 bio.write(b'foo')
1869 bio.write(b'bar')
1870 self.assertEqual(bio.read(), b'foobar')
1871 self.assertEqual(bio.read(), b'')
1872 bio.write(b'baz')
1873 self.assertEqual(bio.read(2), b'ba')
1874 self.assertEqual(bio.read(1), b'z')
1875 self.assertEqual(bio.read(1), b'')
1876
1877 def test_eof(self):
1878 bio = ssl.MemoryBIO()
1879 self.assertFalse(bio.eof)
1880 self.assertEqual(bio.read(), b'')
1881 self.assertFalse(bio.eof)
1882 bio.write(b'foo')
1883 self.assertFalse(bio.eof)
1884 bio.write_eof()
1885 self.assertFalse(bio.eof)
1886 self.assertEqual(bio.read(2), b'fo')
1887 self.assertFalse(bio.eof)
1888 self.assertEqual(bio.read(1), b'o')
1889 self.assertTrue(bio.eof)
1890 self.assertEqual(bio.read(), b'')
1891 self.assertTrue(bio.eof)
1892
1893 def test_pending(self):
1894 bio = ssl.MemoryBIO()
1895 self.assertEqual(bio.pending, 0)
1896 bio.write(b'foo')
1897 self.assertEqual(bio.pending, 3)
1898 for i in range(3):
1899 bio.read(1)
1900 self.assertEqual(bio.pending, 3-i-1)
1901 for i in range(3):
1902 bio.write(b'x')
1903 self.assertEqual(bio.pending, i+1)
1904 bio.read()
1905 self.assertEqual(bio.pending, 0)
1906
1907 def test_buffer_types(self):
1908 bio = ssl.MemoryBIO()
1909 bio.write(b'foo')
1910 self.assertEqual(bio.read(), b'foo')
1911 bio.write(bytearray(b'bar'))
1912 self.assertEqual(bio.read(), b'bar')
1913 bio.write(memoryview(b'baz'))
1914 self.assertEqual(bio.read(), b'baz')
1915
1916 def test_error_types(self):
1917 bio = ssl.MemoryBIO()
1918 self.assertRaises(TypeError, bio.write, 'foo')
1919 self.assertRaises(TypeError, bio.write, None)
1920 self.assertRaises(TypeError, bio.write, True)
1921 self.assertRaises(TypeError, bio.write, 1)
1922
1923
Christian Heimes9d50ab52018-02-27 10:17:30 +01001924class SSLObjectTests(unittest.TestCase):
1925 def test_private_init(self):
1926 bio = ssl.MemoryBIO()
1927 with self.assertRaisesRegex(TypeError, "public constructor"):
1928 ssl.SSLObject(bio, bio)
1929
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001930 def test_unwrap(self):
1931 client_ctx, server_ctx, hostname = testing_context()
1932 c_in = ssl.MemoryBIO()
1933 c_out = ssl.MemoryBIO()
1934 s_in = ssl.MemoryBIO()
1935 s_out = ssl.MemoryBIO()
1936 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1937 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1938
1939 # Loop on the handshake for a bit to get it settled
1940 for _ in range(5):
1941 try:
1942 client.do_handshake()
1943 except ssl.SSLWantReadError:
1944 pass
1945 if c_out.pending:
1946 s_in.write(c_out.read())
1947 try:
1948 server.do_handshake()
1949 except ssl.SSLWantReadError:
1950 pass
1951 if s_out.pending:
1952 c_in.write(s_out.read())
1953 # Now the handshakes should be complete (don't raise WantReadError)
1954 client.do_handshake()
1955 server.do_handshake()
1956
1957 # Now if we unwrap one side unilaterally, it should send close-notify
1958 # and raise WantReadError:
1959 with self.assertRaises(ssl.SSLWantReadError):
1960 client.unwrap()
1961
1962 # But server.unwrap() does not raise, because it reads the client's
1963 # close-notify:
1964 s_in.write(c_out.read())
1965 server.unwrap()
1966
1967 # And now that the client gets the server's close-notify, it doesn't
1968 # raise either.
1969 c_in.write(s_out.read())
1970 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001971
Martin Panter3840b2a2016-03-27 01:53:46 +00001972class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001973 """Tests that connect to a simple server running in the background"""
1974
1975 def setUp(self):
juhovh49fdf112021-04-18 21:11:48 +10001976 self.server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1977 self.server_context.load_cert_chain(SIGNED_CERTFILE)
1978 server = ThreadedEchoServer(context=self.server_context)
Martin Panter3840b2a2016-03-27 01:53:46 +00001979 self.server_addr = (HOST, server.port)
1980 server.__enter__()
1981 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001982
Antoine Pitrou480a1242010-04-28 21:37:09 +00001983 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001984 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001985 cert_reqs=ssl.CERT_NONE) as s:
1986 s.connect(self.server_addr)
1987 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001988 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001989
Martin Panter3840b2a2016-03-27 01:53:46 +00001990 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001991 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001992 cert_reqs=ssl.CERT_REQUIRED,
1993 ca_certs=SIGNING_CA) as s:
1994 s.connect(self.server_addr)
1995 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001996 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001997
Martin Panter3840b2a2016-03-27 01:53:46 +00001998 def test_connect_fail(self):
1999 # This should fail because we have no verification certs. Connection
2000 # failure crashes ThreadedEchoServer, so run this in an independent
2001 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02002002 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002003 cert_reqs=ssl.CERT_REQUIRED)
2004 self.addCleanup(s.close)
2005 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2006 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002007
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002008 def test_connect_ex(self):
2009 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02002010 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002011 cert_reqs=ssl.CERT_REQUIRED,
2012 ca_certs=SIGNING_CA)
2013 self.addCleanup(s.close)
2014 self.assertEqual(0, s.connect_ex(self.server_addr))
2015 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002016
2017 def test_non_blocking_connect_ex(self):
2018 # Issue #11326: non-blocking connect_ex() should allow handshake
2019 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02002020 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002021 cert_reqs=ssl.CERT_REQUIRED,
2022 ca_certs=SIGNING_CA,
2023 do_handshake_on_connect=False)
2024 self.addCleanup(s.close)
2025 s.setblocking(False)
2026 rc = s.connect_ex(self.server_addr)
2027 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2028 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2029 # Wait for connect to finish
2030 select.select([], [s], [], 5.0)
2031 # Non-blocking handshake
2032 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002033 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002034 s.do_handshake()
2035 break
2036 except ssl.SSLWantReadError:
2037 select.select([s], [], [], 5.0)
2038 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002039 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002040 # SSL established
2041 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002042
Antoine Pitrou152efa22010-05-16 18:19:27 +00002043 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002044 # Same as test_connect, but with a separately created context
Christian Heimesa170fa12017-09-15 20:27:30 +02002045 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002046 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2047 s.connect(self.server_addr)
2048 self.assertEqual({}, s.getpeercert())
2049 # Same with a server hostname
2050 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2051 server_hostname="dummy") as s:
2052 s.connect(self.server_addr)
2053 ctx.verify_mode = ssl.CERT_REQUIRED
2054 # This should succeed because we specify the root cert
2055 ctx.load_verify_locations(SIGNING_CA)
2056 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2057 s.connect(self.server_addr)
2058 cert = s.getpeercert()
2059 self.assertTrue(cert)
2060
2061 def test_connect_with_context_fail(self):
2062 # This should fail because we have no verification certs. Connection
2063 # failure crashes ThreadedEchoServer, so run this in an independent
2064 # test method.
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 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
2068 self.addCleanup(s.close)
2069 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2070 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002071
2072 def test_connect_capath(self):
2073 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002074 # NOTE: the subject hashing algorithm has been changed between
2075 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2076 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002077 # filename) for this test to be portable across OpenSSL releases.
Christian Heimesa170fa12017-09-15 20:27:30 +02002078 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002079 ctx.verify_mode = ssl.CERT_REQUIRED
2080 ctx.load_verify_locations(capath=CAPATH)
2081 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2082 s.connect(self.server_addr)
2083 cert = s.getpeercert()
2084 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002085
Martin Panter3840b2a2016-03-27 01:53:46 +00002086 # Same with a bytes `capath` argument
Christian Heimesa170fa12017-09-15 20:27:30 +02002087 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002088 ctx.verify_mode = ssl.CERT_REQUIRED
2089 ctx.load_verify_locations(capath=BYTES_CAPATH)
2090 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2091 s.connect(self.server_addr)
2092 cert = s.getpeercert()
2093 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002094
Christian Heimesefff7062013-11-21 03:35:02 +01002095 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002096 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002097 pem = f.read()
2098 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimesa170fa12017-09-15 20:27:30 +02002099 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002100 ctx.verify_mode = ssl.CERT_REQUIRED
2101 ctx.load_verify_locations(cadata=pem)
2102 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2103 s.connect(self.server_addr)
2104 cert = s.getpeercert()
2105 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002106
Martin Panter3840b2a2016-03-27 01:53:46 +00002107 # same with DER
Christian Heimesa170fa12017-09-15 20:27:30 +02002108 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002109 ctx.verify_mode = ssl.CERT_REQUIRED
2110 ctx.load_verify_locations(cadata=der)
2111 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2112 s.connect(self.server_addr)
2113 cert = s.getpeercert()
2114 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002115
Antoine Pitroue3220242010-04-24 11:13:53 +00002116 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2117 def test_makefile_close(self):
2118 # Issue #5238: creating a file-like object with makefile() shouldn't
2119 # delay closing the underlying "real socket" (here tested with its
2120 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002121 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002122 ss.connect(self.server_addr)
2123 fd = ss.fileno()
2124 f = ss.makefile()
2125 f.close()
2126 # The fd is still open
2127 os.read(fd, 0)
2128 # Closing the SSL socket should close the fd too
2129 ss.close()
2130 gc.collect()
2131 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002132 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002133 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002134
Antoine Pitrou480a1242010-04-28 21:37:09 +00002135 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002136 s = socket.socket(socket.AF_INET)
2137 s.connect(self.server_addr)
2138 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002139 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002140 cert_reqs=ssl.CERT_NONE,
2141 do_handshake_on_connect=False)
2142 self.addCleanup(s.close)
2143 count = 0
2144 while True:
2145 try:
2146 count += 1
2147 s.do_handshake()
2148 break
2149 except ssl.SSLWantReadError:
2150 select.select([s], [], [])
2151 except ssl.SSLWantWriteError:
2152 select.select([], [s], [])
2153 if support.verbose:
2154 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002155
Antoine Pitrou480a1242010-04-28 21:37:09 +00002156 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002157 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002158
juhovh49fdf112021-04-18 21:11:48 +10002159 @needs_sni
2160 def test_get_server_certificate_sni(self):
2161 host, port = self.server_addr
2162 server_names = []
2163
2164 # We store servername_cb arguments to make sure they match the host
2165 def servername_cb(ssl_sock, server_name, initial_context):
2166 server_names.append(server_name)
2167 self.server_context.set_servername_callback(servername_cb)
2168
2169 pem = ssl.get_server_certificate((host, port))
2170 if not pem:
2171 self.fail("No server certificate on %s:%s!" % (host, port))
2172
2173 pem = ssl.get_server_certificate((host, port), ca_certs=SIGNING_CA)
2174 if not pem:
2175 self.fail("No server certificate on %s:%s!" % (host, port))
2176 if support.verbose:
2177 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port, pem))
2178
2179 self.assertEqual(server_names, [host, host])
2180
Martin Panter3840b2a2016-03-27 01:53:46 +00002181 def test_get_server_certificate_fail(self):
2182 # Connection failure crashes ThreadedEchoServer, so run this in an
2183 # independent test method
2184 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002185
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002186 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002187 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002188 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2189 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002190 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002191 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2192 s.connect(self.server_addr)
2193 # Error checking can happen at instantiation or when connecting
2194 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2195 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002196 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002197 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2198 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002199
Christian Heimes9a5395a2013-06-17 15:44:12 +02002200 def test_get_ca_certs_capath(self):
2201 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002202 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002203 ctx.load_verify_locations(capath=CAPATH)
2204 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002205 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2206 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002207 s.connect(self.server_addr)
2208 cert = s.getpeercert()
2209 self.assertTrue(cert)
2210 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002211
Christian Heimes575596e2013-12-15 21:49:17 +01002212 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01002213 def test_context_setget(self):
2214 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002215 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2216 ctx1.load_verify_locations(capath=CAPATH)
2217 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2218 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002219 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002220 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002221 ss.connect(self.server_addr)
2222 self.assertIs(ss.context, ctx1)
2223 self.assertIs(ss._sslobj.context, ctx1)
2224 ss.context = ctx2
2225 self.assertIs(ss.context, ctx2)
2226 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002227
2228 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2229 # A simple IO loop. Call func(*args) depending on the error we get
2230 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002231 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002232 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002233 count = 0
2234 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002235 if time.monotonic() > deadline:
2236 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002237 errno = None
2238 count += 1
2239 try:
2240 ret = func(*args)
2241 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002242 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002243 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002244 raise
2245 errno = e.errno
2246 # Get any data from the outgoing BIO irrespective of any error, and
2247 # send it to the socket.
2248 buf = outgoing.read()
2249 sock.sendall(buf)
2250 # If there's no error, we're done. For WANT_READ, we need to get
2251 # data from the socket and put it in the incoming BIO.
2252 if errno is None:
2253 break
2254 elif errno == ssl.SSL_ERROR_WANT_READ:
2255 buf = sock.recv(32768)
2256 if buf:
2257 incoming.write(buf)
2258 else:
2259 incoming.write_eof()
2260 if support.verbose:
2261 sys.stdout.write("Needed %d calls to complete %s().\n"
2262 % (count, func.__name__))
2263 return ret
2264
Martin Panter3840b2a2016-03-27 01:53:46 +00002265 def test_bio_handshake(self):
2266 sock = socket.socket(socket.AF_INET)
2267 self.addCleanup(sock.close)
2268 sock.connect(self.server_addr)
2269 incoming = ssl.MemoryBIO()
2270 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002271 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2272 self.assertTrue(ctx.check_hostname)
2273 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002274 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002275 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2276 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002277 self.assertIs(sslobj._sslobj.owner, sslobj)
2278 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002279 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002280 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002281 self.assertRaises(ValueError, sslobj.getpeercert)
2282 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2283 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2284 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2285 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002286 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002287 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002288 self.assertTrue(sslobj.getpeercert())
2289 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2290 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2291 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002292 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002293 except ssl.SSLSyscallError:
2294 # If the server shuts down the TCP connection without sending a
2295 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2296 pass
2297 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2298
2299 def test_bio_read_write_data(self):
2300 sock = socket.socket(socket.AF_INET)
2301 self.addCleanup(sock.close)
2302 sock.connect(self.server_addr)
2303 incoming = ssl.MemoryBIO()
2304 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002305 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002306 ctx.verify_mode = ssl.CERT_NONE
2307 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2308 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2309 req = b'FOO\n'
2310 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2311 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2312 self.assertEqual(buf, b'foo\n')
2313 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002314
2315
Martin Panter3840b2a2016-03-27 01:53:46 +00002316class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002317
Martin Panter3840b2a2016-03-27 01:53:46 +00002318 def test_timeout_connect_ex(self):
2319 # Issue #12065: on a timeout, connect_ex() should return the original
2320 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002321 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002322 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002323 cert_reqs=ssl.CERT_REQUIRED,
2324 do_handshake_on_connect=False)
2325 self.addCleanup(s.close)
2326 s.settimeout(0.0000001)
2327 rc = s.connect_ex((REMOTE_HOST, 443))
2328 if rc == 0:
2329 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002330 elif rc == errno.ENETUNREACH:
2331 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002332 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2333
Serhiy Storchaka16994912020-04-25 10:06:29 +03002334 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002335 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002336 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002337 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2338 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2339
Martin Panter3840b2a2016-03-27 01:53:46 +00002340
2341def _test_get_server_certificate(test, host, port, cert=None):
2342 pem = ssl.get_server_certificate((host, port))
2343 if not pem:
2344 test.fail("No server certificate on %s:%s!" % (host, port))
2345
2346 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2347 if not pem:
2348 test.fail("No server certificate on %s:%s!" % (host, port))
2349 if support.verbose:
2350 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2351
2352def _test_get_server_certificate_fail(test, host, port):
2353 try:
2354 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2355 except ssl.SSLError as x:
2356 #should fail
2357 if support.verbose:
2358 sys.stdout.write("%s\n" % x)
2359 else:
2360 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2361
2362
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002363from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002364
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002365class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002366
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002367 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002368
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002369 """A mildly complicated class, because we want it to work both
2370 with and without the SSL wrapper around the socket connection, so
2371 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002372
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002373 def __init__(self, server, connsock, addr):
2374 self.server = server
2375 self.running = False
2376 self.sock = connsock
2377 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002378 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002379 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002380 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002381 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002382
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002383 def wrap_conn(self):
2384 try:
2385 self.sslconn = self.server.context.wrap_socket(
2386 self.sock, server_side=True)
2387 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
2388 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002389 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002390 # We treat ConnectionResetError as though it were an
2391 # SSLError - OpenSSL on Ubuntu abruptly closes the
2392 # connection when asked to use an unsupported protocol.
2393 #
Christian Heimes529525f2018-05-23 22:24:45 +02002394 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2395 # tries to send session tickets after handshake.
2396 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002397 #
2398 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2399 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002400 self.server.conn_errors.append(str(e))
2401 if self.server.chatty:
2402 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2403 self.running = False
2404 self.close()
2405 return False
2406 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002407 # OSError may occur with wrong protocols, e.g. both
2408 # sides use PROTOCOL_TLS_SERVER.
2409 #
2410 # XXX Various errors can have happened here, for example
2411 # a mismatching protocol version, an invalid certificate,
2412 # or a low-level bug. This should be made more discriminating.
2413 #
2414 # bpo-31323: Store the exception as string to prevent
2415 # a reference leak: server -> conn_errors -> exception
2416 # -> traceback -> self (ConnectionHandler) -> server
2417 self.server.conn_errors.append(str(e))
2418 if self.server.chatty:
2419 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2420 self.running = False
2421 self.server.stop()
2422 self.close()
2423 return False
2424 else:
2425 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2426 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2427 cert = self.sslconn.getpeercert()
2428 if support.verbose and self.server.chatty:
2429 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2430 cert_binary = self.sslconn.getpeercert(True)
2431 if support.verbose and self.server.chatty:
2432 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2433 cipher = self.sslconn.cipher()
2434 if support.verbose and self.server.chatty:
2435 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
2436 sys.stdout.write(" server: selected protocol is now "
2437 + str(self.sslconn.selected_npn_protocol()) + "\n")
2438 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002439
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002440 def read(self):
2441 if self.sslconn:
2442 return self.sslconn.read()
2443 else:
2444 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002445
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002446 def write(self, bytes):
2447 if self.sslconn:
2448 return self.sslconn.write(bytes)
2449 else:
2450 return self.sock.send(bytes)
2451
2452 def close(self):
2453 if self.sslconn:
2454 self.sslconn.close()
2455 else:
2456 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002457
Antoine Pitrou480a1242010-04-28 21:37:09 +00002458 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002459 self.running = True
2460 if not self.server.starttls_server:
2461 if not self.wrap_conn():
2462 return
2463 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002464 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002465 msg = self.read()
2466 stripped = msg.strip()
2467 if not stripped:
2468 # eof, so quit this handler
2469 self.running = False
2470 try:
2471 self.sock = self.sslconn.unwrap()
2472 except OSError:
2473 # Many tests shut the TCP connection down
2474 # without an SSL shutdown. This causes
2475 # unwrap() to raise OSError with errno=0!
2476 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002477 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002478 self.sslconn = None
2479 self.close()
2480 elif stripped == b'over':
2481 if support.verbose and self.server.connectionchatty:
2482 sys.stdout.write(" server: client closed connection\n")
2483 self.close()
2484 return
2485 elif (self.server.starttls_server and
2486 stripped == b'STARTTLS'):
2487 if support.verbose and self.server.connectionchatty:
2488 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2489 self.write(b"OK\n")
2490 if not self.wrap_conn():
2491 return
2492 elif (self.server.starttls_server and self.sslconn
2493 and stripped == b'ENDTLS'):
2494 if support.verbose and self.server.connectionchatty:
2495 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2496 self.write(b"OK\n")
2497 self.sock = self.sslconn.unwrap()
2498 self.sslconn = None
2499 if support.verbose and self.server.connectionchatty:
2500 sys.stdout.write(" server: connection is now unencrypted...\n")
2501 elif stripped == b'CB tls-unique':
2502 if support.verbose and self.server.connectionchatty:
2503 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2504 data = self.sslconn.get_channel_binding("tls-unique")
2505 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002506 elif stripped == b'PHA':
2507 if support.verbose and self.server.connectionchatty:
2508 sys.stdout.write(" server: initiating post handshake auth\n")
2509 try:
2510 self.sslconn.verify_client_post_handshake()
2511 except ssl.SSLError as e:
2512 self.write(repr(e).encode("us-ascii") + b"\n")
2513 else:
2514 self.write(b"OK\n")
2515 elif stripped == b'HASCERT':
2516 if self.sslconn.getpeercert() is not None:
2517 self.write(b'TRUE\n')
2518 else:
2519 self.write(b'FALSE\n')
2520 elif stripped == b'GETCERT':
2521 cert = self.sslconn.getpeercert()
2522 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002523 else:
2524 if (support.verbose and
2525 self.server.connectionchatty):
2526 ctype = (self.sslconn and "encrypted") or "unencrypted"
2527 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2528 % (msg, ctype, msg.lower(), ctype))
2529 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002530 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002531 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2532 # when connection is not shut down gracefully.
2533 if self.server.chatty and support.verbose:
2534 sys.stdout.write(
2535 " Connection reset by peer: {}\n".format(
2536 self.addr)
2537 )
2538 self.close()
2539 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002540 except ssl.SSLError as err:
2541 # On Windows sometimes test_pha_required_nocert receives the
2542 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2543 # before the 'tlsv13 alert certificate required' exception.
2544 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2545 # is received test_pha_required_nocert fails with ConnectionResetError
2546 # because the underlying socket is closed
2547 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2548 if self.server.chatty and support.verbose:
2549 sys.stdout.write(err.args[1])
2550 # test_pha_required_nocert is expecting this exception
2551 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002552 except OSError:
2553 if self.server.chatty:
2554 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002555 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002556 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002557
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002558 # normally, we'd just stop here, but for the test
2559 # harness, we want to stop the server
2560 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002561
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002562 def __init__(self, certificate=None, ssl_version=None,
2563 certreqs=None, cacerts=None,
2564 chatty=True, connectionchatty=False, starttls_server=False,
2565 npn_protocols=None, alpn_protocols=None,
2566 ciphers=None, context=None):
2567 if context:
2568 self.context = context
2569 else:
2570 self.context = ssl.SSLContext(ssl_version
2571 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002572 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002573 self.context.verify_mode = (certreqs if certreqs is not None
2574 else ssl.CERT_NONE)
2575 if cacerts:
2576 self.context.load_verify_locations(cacerts)
2577 if certificate:
2578 self.context.load_cert_chain(certificate)
2579 if npn_protocols:
2580 self.context.set_npn_protocols(npn_protocols)
2581 if alpn_protocols:
2582 self.context.set_alpn_protocols(alpn_protocols)
2583 if ciphers:
2584 self.context.set_ciphers(ciphers)
2585 self.chatty = chatty
2586 self.connectionchatty = connectionchatty
2587 self.starttls_server = starttls_server
2588 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002589 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002590 self.flag = None
2591 self.active = False
2592 self.selected_npn_protocols = []
2593 self.selected_alpn_protocols = []
2594 self.shared_ciphers = []
2595 self.conn_errors = []
2596 threading.Thread.__init__(self)
2597 self.daemon = True
2598
2599 def __enter__(self):
2600 self.start(threading.Event())
2601 self.flag.wait()
2602 return self
2603
2604 def __exit__(self, *args):
2605 self.stop()
2606 self.join()
2607
2608 def start(self, flag=None):
2609 self.flag = flag
2610 threading.Thread.start(self)
2611
2612 def run(self):
2613 self.sock.settimeout(0.05)
2614 self.sock.listen()
2615 self.active = True
2616 if self.flag:
2617 # signal an event
2618 self.flag.set()
2619 while self.active:
2620 try:
2621 newconn, connaddr = self.sock.accept()
2622 if support.verbose and self.chatty:
2623 sys.stdout.write(' server: new connection from '
2624 + repr(connaddr) + '\n')
2625 handler = self.ConnectionHandler(self, newconn, connaddr)
2626 handler.start()
2627 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002628 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002629 pass
2630 except KeyboardInterrupt:
2631 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002632 except BaseException as e:
2633 if support.verbose and self.chatty:
2634 sys.stdout.write(
2635 ' connection handling failed: ' + repr(e) + '\n')
2636
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002637 self.sock.close()
2638
2639 def stop(self):
2640 self.active = False
2641
2642class AsyncoreEchoServer(threading.Thread):
2643
2644 # this one's based on asyncore.dispatcher
2645
2646 class EchoServer (asyncore.dispatcher):
2647
2648 class ConnectionHandler(asyncore.dispatcher_with_send):
2649
2650 def __init__(self, conn, certfile):
2651 self.socket = test_wrap_socket(conn, server_side=True,
2652 certfile=certfile,
2653 do_handshake_on_connect=False)
2654 asyncore.dispatcher_with_send.__init__(self, self.socket)
2655 self._ssl_accepting = True
2656 self._do_ssl_handshake()
2657
2658 def readable(self):
2659 if isinstance(self.socket, ssl.SSLSocket):
2660 while self.socket.pending() > 0:
2661 self.handle_read_event()
2662 return True
2663
2664 def _do_ssl_handshake(self):
2665 try:
2666 self.socket.do_handshake()
2667 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2668 return
2669 except ssl.SSLEOFError:
2670 return self.handle_close()
2671 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002672 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002673 except OSError as err:
2674 if err.args[0] == errno.ECONNABORTED:
2675 return self.handle_close()
2676 else:
2677 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002678
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002679 def handle_read(self):
2680 if self._ssl_accepting:
2681 self._do_ssl_handshake()
2682 else:
2683 data = self.recv(1024)
2684 if support.verbose:
2685 sys.stdout.write(" server: read %s from client\n" % repr(data))
2686 if not data:
2687 self.close()
2688 else:
2689 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002690
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002691 def handle_close(self):
2692 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002693 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002694 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002695
2696 def handle_error(self):
2697 raise
2698
Trent Nelson78520002008-04-10 20:54:35 +00002699 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002700 self.certfile = certfile
2701 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002702 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002703 asyncore.dispatcher.__init__(self, sock)
2704 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002705
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002706 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002707 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002708 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2709 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002710
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002711 def handle_error(self):
2712 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002713
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002714 def __init__(self, certfile):
2715 self.flag = None
2716 self.active = False
2717 self.server = self.EchoServer(certfile)
2718 self.port = self.server.port
2719 threading.Thread.__init__(self)
2720 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002721
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002722 def __str__(self):
2723 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002724
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002725 def __enter__(self):
2726 self.start(threading.Event())
2727 self.flag.wait()
2728 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002729
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002730 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002731 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002732 sys.stdout.write(" cleanup: stopping server.\n")
2733 self.stop()
2734 if support.verbose:
2735 sys.stdout.write(" cleanup: joining server thread.\n")
2736 self.join()
2737 if support.verbose:
2738 sys.stdout.write(" cleanup: successfully joined.\n")
2739 # make sure that ConnectionHandler is removed from socket_map
2740 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002741
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002742 def start (self, flag=None):
2743 self.flag = flag
2744 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002745
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002746 def run(self):
2747 self.active = True
2748 if self.flag:
2749 self.flag.set()
2750 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002751 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002752 asyncore.loop(1)
2753 except:
2754 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002755
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002756 def stop(self):
2757 self.active = False
2758 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002759
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002760def server_params_test(client_context, server_context, indata=b"FOO\n",
2761 chatty=True, connectionchatty=False, sni_name=None,
2762 session=None):
2763 """
2764 Launch a server, connect a client to it and try various reads
2765 and writes.
2766 """
2767 stats = {}
2768 server = ThreadedEchoServer(context=server_context,
2769 chatty=chatty,
2770 connectionchatty=False)
2771 with server:
2772 with client_context.wrap_socket(socket.socket(),
2773 server_hostname=sni_name, session=session) as s:
2774 s.connect((HOST, server.port))
2775 for arg in [indata, bytearray(indata), memoryview(indata)]:
2776 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002777 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002778 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002779 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002780 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002781 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002782 if connectionchatty:
2783 if support.verbose:
2784 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002785 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002786 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002787 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2788 % (outdata[:20], len(outdata),
2789 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002790 s.write(b"over\n")
2791 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002792 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002793 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002794 stats.update({
2795 'compression': s.compression(),
2796 'cipher': s.cipher(),
2797 'peercert': s.getpeercert(),
2798 'client_alpn_protocol': s.selected_alpn_protocol(),
2799 'client_npn_protocol': s.selected_npn_protocol(),
2800 'version': s.version(),
2801 'session_reused': s.session_reused,
2802 'session': s.session,
2803 })
2804 s.close()
2805 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2806 stats['server_npn_protocols'] = server.selected_npn_protocols
2807 stats['server_shared_ciphers'] = server.shared_ciphers
2808 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002809
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002810def try_protocol_combo(server_protocol, client_protocol, expect_success,
2811 certsreqs=None, server_options=0, client_options=0):
2812 """
2813 Try to SSL-connect using *client_protocol* to *server_protocol*.
2814 If *expect_success* is true, assert that the connection succeeds,
2815 if it's false, assert that the connection fails.
2816 Also, if *expect_success* is a string, assert that it is the protocol
2817 version actually used by the connection.
2818 """
2819 if certsreqs is None:
2820 certsreqs = ssl.CERT_NONE
2821 certtype = {
2822 ssl.CERT_NONE: "CERT_NONE",
2823 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2824 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2825 }[certsreqs]
2826 if support.verbose:
2827 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2828 sys.stdout.write(formatstr %
2829 (ssl.get_protocol_name(client_protocol),
2830 ssl.get_protocol_name(server_protocol),
2831 certtype))
2832 client_context = ssl.SSLContext(client_protocol)
2833 client_context.options |= client_options
2834 server_context = ssl.SSLContext(server_protocol)
2835 server_context.options |= server_options
2836
Victor Stinner3ef63442019-02-19 18:06:03 +01002837 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2838 if (min_version is not None
2839 # SSLContext.minimum_version is only available on recent OpenSSL
2840 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2841 and hasattr(server_context, 'minimum_version')
2842 and server_protocol == ssl.PROTOCOL_TLS
2843 and server_context.minimum_version > min_version):
2844 # If OpenSSL configuration is strict and requires more recent TLS
2845 # version, we have to change the minimum to test old TLS versions.
2846 server_context.minimum_version = min_version
2847
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002848 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2849 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2850 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002851 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002852 client_context.set_ciphers("ALL")
2853
Christian Heimesf6c6b582021-03-18 23:06:50 +01002854 seclevel_workaround(server_context, client_context)
2855
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002856 for ctx in (client_context, server_context):
2857 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002858 ctx.load_cert_chain(SIGNED_CERTFILE)
2859 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002860 try:
2861 stats = server_params_test(client_context, server_context,
2862 chatty=False, connectionchatty=False)
2863 # Protocol mismatch can result in either an SSLError, or a
2864 # "Connection reset by peer" error.
2865 except ssl.SSLError:
2866 if expect_success:
2867 raise
2868 except OSError as e:
2869 if expect_success or e.errno != errno.ECONNRESET:
2870 raise
2871 else:
2872 if not expect_success:
2873 raise AssertionError(
2874 "Client protocol %s succeeded with server protocol %s!"
2875 % (ssl.get_protocol_name(client_protocol),
2876 ssl.get_protocol_name(server_protocol)))
2877 elif (expect_success is not True
2878 and expect_success != stats['version']):
2879 raise AssertionError("version mismatch: expected %r, got %r"
2880 % (expect_success, stats['version']))
2881
2882
2883class ThreadedTests(unittest.TestCase):
2884
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002885 def test_echo(self):
2886 """Basic test of an SSL client connecting to a server"""
2887 if support.verbose:
2888 sys.stdout.write("\n")
2889 for protocol in PROTOCOLS:
2890 if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
2891 continue
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02002892 if not has_tls_protocol(protocol):
2893 continue
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002894 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2895 context = ssl.SSLContext(protocol)
2896 context.load_cert_chain(CERTFILE)
Christian Heimesf6c6b582021-03-18 23:06:50 +01002897 seclevel_workaround(context)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002898 server_params_test(context, context,
2899 chatty=True, connectionchatty=True)
2900
Christian Heimesa170fa12017-09-15 20:27:30 +02002901 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002902
2903 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2904 server_params_test(client_context=client_context,
2905 server_context=server_context,
2906 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002907 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002908
2909 client_context.check_hostname = False
2910 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2911 with self.assertRaises(ssl.SSLError) as e:
2912 server_params_test(client_context=server_context,
2913 server_context=client_context,
2914 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002915 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002916 self.assertIn('called a function you should not call',
2917 str(e.exception))
2918
2919 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2920 with self.assertRaises(ssl.SSLError) as e:
2921 server_params_test(client_context=server_context,
2922 server_context=server_context,
2923 chatty=True, connectionchatty=True)
2924 self.assertIn('called a function you should not call',
2925 str(e.exception))
2926
2927 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2928 with self.assertRaises(ssl.SSLError) as e:
2929 server_params_test(client_context=server_context,
2930 server_context=client_context,
2931 chatty=True, connectionchatty=True)
2932 self.assertIn('called a function you should not call',
2933 str(e.exception))
2934
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002935 def test_getpeercert(self):
2936 if support.verbose:
2937 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002938
2939 client_context, server_context, hostname = testing_context()
2940 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002941 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002942 with client_context.wrap_socket(socket.socket(),
2943 do_handshake_on_connect=False,
2944 server_hostname=hostname) as s:
2945 s.connect((HOST, server.port))
2946 # getpeercert() raise ValueError while the handshake isn't
2947 # done.
2948 with self.assertRaises(ValueError):
2949 s.getpeercert()
2950 s.do_handshake()
2951 cert = s.getpeercert()
2952 self.assertTrue(cert, "Can't get peer certificate.")
2953 cipher = s.cipher()
2954 if support.verbose:
2955 sys.stdout.write(pprint.pformat(cert) + '\n')
2956 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2957 if 'subject' not in cert:
2958 self.fail("No subject field in certificate: %s." %
2959 pprint.pformat(cert))
2960 if ((('organizationName', 'Python Software Foundation'),)
2961 not in cert['subject']):
2962 self.fail(
2963 "Missing or invalid 'organizationName' field in certificate subject; "
2964 "should be 'Python Software Foundation'.")
2965 self.assertIn('notBefore', cert)
2966 self.assertIn('notAfter', cert)
2967 before = ssl.cert_time_to_seconds(cert['notBefore'])
2968 after = ssl.cert_time_to_seconds(cert['notAfter'])
2969 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002970
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002971 def test_crl_check(self):
2972 if support.verbose:
2973 sys.stdout.write("\n")
2974
Christian Heimesa170fa12017-09-15 20:27:30 +02002975 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002976
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002977 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002978 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002979
2980 # VERIFY_DEFAULT should pass
2981 server = ThreadedEchoServer(context=server_context, chatty=True)
2982 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002983 with client_context.wrap_socket(socket.socket(),
2984 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002985 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002986 cert = s.getpeercert()
2987 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002988
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002989 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002990 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002991
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002992 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=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002996 with self.assertRaisesRegex(ssl.SSLError,
2997 "certificate verify failed"):
2998 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002999
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003000 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02003001 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00003002
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003003 server = ThreadedEchoServer(context=server_context, chatty=True)
3004 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003005 with client_context.wrap_socket(socket.socket(),
3006 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02003007 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003008 cert = s.getpeercert()
3009 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02003010
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003011 def test_check_hostname(self):
3012 if support.verbose:
3013 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02003014
Christian Heimesa170fa12017-09-15 20:27:30 +02003015 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003016
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003017 # correct hostname should verify
3018 server = ThreadedEchoServer(context=server_context, chatty=True)
3019 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003020 with client_context.wrap_socket(socket.socket(),
3021 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003022 s.connect((HOST, server.port))
3023 cert = s.getpeercert()
3024 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003025
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003026 # incorrect hostname should raise an exception
3027 server = ThreadedEchoServer(context=server_context, chatty=True)
3028 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003029 with client_context.wrap_socket(socket.socket(),
3030 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01003031 with self.assertRaisesRegex(
3032 ssl.CertificateError,
3033 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003034 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003035
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003036 # missing server_hostname arg should cause an exception, too
3037 server = ThreadedEchoServer(context=server_context, chatty=True)
3038 with server:
3039 with socket.socket() as s:
3040 with self.assertRaisesRegex(ValueError,
3041 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02003042 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003043
Christian Heimesb467d9a2021-04-17 10:07:19 +02003044 @unittest.skipUnless(
3045 ssl.HAS_NEVER_CHECK_COMMON_NAME, "test requires hostname_checks_common_name"
3046 )
3047 def test_hostname_checks_common_name(self):
3048 client_context, server_context, hostname = testing_context()
3049 assert client_context.hostname_checks_common_name
3050 client_context.hostname_checks_common_name = False
3051
3052 # default cert has a SAN
3053 server = ThreadedEchoServer(context=server_context, chatty=True)
3054 with server:
3055 with client_context.wrap_socket(socket.socket(),
3056 server_hostname=hostname) as s:
3057 s.connect((HOST, server.port))
3058
3059 client_context, server_context, hostname = testing_context(NOSANFILE)
3060 client_context.hostname_checks_common_name = False
3061 server = ThreadedEchoServer(context=server_context, chatty=True)
3062 with server:
3063 with client_context.wrap_socket(socket.socket(),
3064 server_hostname=hostname) as s:
3065 with self.assertRaises(ssl.SSLCertVerificationError):
3066 s.connect((HOST, server.port))
3067
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003068 def test_ecc_cert(self):
3069 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3070 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003071 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003072 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3073
3074 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3075 # load ECC cert
3076 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3077
3078 # correct hostname should verify
3079 server = ThreadedEchoServer(context=server_context, chatty=True)
3080 with server:
3081 with client_context.wrap_socket(socket.socket(),
3082 server_hostname=hostname) as s:
3083 s.connect((HOST, server.port))
3084 cert = s.getpeercert()
3085 self.assertTrue(cert, "Can't get peer certificate.")
3086 cipher = s.cipher()[0].split('-')
3087 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3088
3089 def test_dual_rsa_ecc(self):
3090 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3091 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003092 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3093 # algorithms.
3094 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003095 # only ECDSA certs
3096 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3097 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3098
3099 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3100 # load ECC and RSA key/cert pairs
3101 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3102 server_context.load_cert_chain(SIGNED_CERTFILE)
3103
3104 # correct hostname should verify
3105 server = ThreadedEchoServer(context=server_context, chatty=True)
3106 with server:
3107 with client_context.wrap_socket(socket.socket(),
3108 server_hostname=hostname) as s:
3109 s.connect((HOST, server.port))
3110 cert = s.getpeercert()
3111 self.assertTrue(cert, "Can't get peer certificate.")
3112 cipher = s.cipher()[0].split('-')
3113 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3114
Christian Heimes66e57422018-01-29 14:25:13 +01003115 def test_check_hostname_idn(self):
3116 if support.verbose:
3117 sys.stdout.write("\n")
3118
Christian Heimes11a14932018-02-24 02:35:08 +01003119 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003120 server_context.load_cert_chain(IDNSANSFILE)
3121
Christian Heimes11a14932018-02-24 02:35:08 +01003122 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003123 context.verify_mode = ssl.CERT_REQUIRED
3124 context.check_hostname = True
3125 context.load_verify_locations(SIGNING_CA)
3126
3127 # correct hostname should verify, when specified in several
3128 # different ways
3129 idn_hostnames = [
3130 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003131 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003132 ('xn--knig-5qa.idn.pythontest.net',
3133 'xn--knig-5qa.idn.pythontest.net'),
3134 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003135 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003136
3137 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003138 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003139 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3140 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3141 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003142 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3143
3144 # ('königsgäßchen.idna2008.pythontest.net',
3145 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3146 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3147 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3148 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3149 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3150
Christian Heimes66e57422018-01-29 14:25:13 +01003151 ]
3152 for server_hostname, expected_hostname in idn_hostnames:
3153 server = ThreadedEchoServer(context=server_context, chatty=True)
3154 with server:
3155 with context.wrap_socket(socket.socket(),
3156 server_hostname=server_hostname) as s:
3157 self.assertEqual(s.server_hostname, expected_hostname)
3158 s.connect((HOST, server.port))
3159 cert = s.getpeercert()
3160 self.assertEqual(s.server_hostname, expected_hostname)
3161 self.assertTrue(cert, "Can't get peer certificate.")
3162
Christian Heimes66e57422018-01-29 14:25:13 +01003163 # incorrect hostname should raise an exception
3164 server = ThreadedEchoServer(context=server_context, chatty=True)
3165 with server:
3166 with context.wrap_socket(socket.socket(),
3167 server_hostname="python.example.org") as s:
3168 with self.assertRaises(ssl.CertificateError):
3169 s.connect((HOST, server.port))
3170
Christian Heimes529525f2018-05-23 22:24:45 +02003171 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003172 """Connecting when the server rejects the client's certificate
3173
3174 Launch a server with CERT_REQUIRED, and check that trying to
3175 connect to it with a wrong client certificate fails.
3176 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003177 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003178 # load client cert that is not signed by trusted CA
3179 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003180 # require TLS client authentication
3181 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003182 # TLS 1.3 has different handshake
3183 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003184
3185 server = ThreadedEchoServer(
3186 context=server_context, chatty=True, connectionchatty=True,
3187 )
3188
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003189 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003190 client_context.wrap_socket(socket.socket(),
3191 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003192 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003193 # Expect either an SSL error about the server rejecting
3194 # the connection, or a low-level connection reset (which
3195 # sometimes happens on Windows)
3196 s.connect((HOST, server.port))
3197 except ssl.SSLError as e:
3198 if support.verbose:
3199 sys.stdout.write("\nSSLError is %r\n" % e)
3200 except OSError as e:
3201 if e.errno != errno.ECONNRESET:
3202 raise
3203 if support.verbose:
3204 sys.stdout.write("\nsocket.error is %r\n" % e)
3205 else:
3206 self.fail("Use of invalid cert should have failed!")
3207
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003208 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003209 def test_wrong_cert_tls13(self):
3210 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003211 # load client cert that is not signed by trusted CA
3212 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003213 server_context.verify_mode = ssl.CERT_REQUIRED
3214 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3215 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3216
3217 server = ThreadedEchoServer(
3218 context=server_context, chatty=True, connectionchatty=True,
3219 )
3220 with server, \
3221 client_context.wrap_socket(socket.socket(),
3222 server_hostname=hostname) as s:
3223 # TLS 1.3 perform client cert exchange after handshake
3224 s.connect((HOST, server.port))
3225 try:
3226 s.write(b'data')
3227 s.read(4)
3228 except ssl.SSLError as e:
3229 if support.verbose:
3230 sys.stdout.write("\nSSLError is %r\n" % e)
3231 except OSError as e:
3232 if e.errno != errno.ECONNRESET:
3233 raise
3234 if support.verbose:
3235 sys.stdout.write("\nsocket.error is %r\n" % e)
3236 else:
3237 self.fail("Use of invalid cert should have failed!")
3238
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003239 def test_rude_shutdown(self):
3240 """A brutal shutdown of an SSL server should raise an OSError
3241 in the client when attempting handshake.
3242 """
3243 listener_ready = threading.Event()
3244 listener_gone = threading.Event()
3245
3246 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003247 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003248
3249 # `listener` runs in a thread. It sits in an accept() until
3250 # the main thread connects. Then it rudely closes the socket,
3251 # and sets Event `listener_gone` to let the main thread know
3252 # the socket is gone.
3253 def listener():
3254 s.listen()
3255 listener_ready.set()
3256 newsock, addr = s.accept()
3257 newsock.close()
3258 s.close()
3259 listener_gone.set()
3260
3261 def connector():
3262 listener_ready.wait()
3263 with socket.socket() as c:
3264 c.connect((HOST, port))
3265 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003266 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003267 ssl_sock = test_wrap_socket(c)
3268 except OSError:
3269 pass
3270 else:
3271 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003272
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003273 t = threading.Thread(target=listener)
3274 t.start()
3275 try:
3276 connector()
3277 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003278 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003279
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003280 def test_ssl_cert_verify_error(self):
3281 if support.verbose:
3282 sys.stdout.write("\n")
3283
3284 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3285 server_context.load_cert_chain(SIGNED_CERTFILE)
3286
3287 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3288
3289 server = ThreadedEchoServer(context=server_context, chatty=True)
3290 with server:
3291 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003292 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003293 try:
3294 s.connect((HOST, server.port))
3295 except ssl.SSLError as e:
3296 msg = 'unable to get local issuer certificate'
3297 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3298 self.assertEqual(e.verify_code, 20)
3299 self.assertEqual(e.verify_message, msg)
3300 self.assertIn(msg, repr(e))
3301 self.assertIn('certificate verify failed', repr(e))
3302
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003303 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003304 def test_protocol_sslv2(self):
3305 """Connecting to an SSLv2 server with various client options"""
3306 if support.verbose:
3307 sys.stdout.write("\n")
3308 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3309 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3310 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003311 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003312 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003313 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3314 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3315 # SSLv23 client with specific SSL options
3316 if no_sslv2_implies_sslv3_hello():
3317 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003318 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003319 client_options=ssl.OP_NO_SSLv2)
Christian Heimesa170fa12017-09-15 20:27:30 +02003320 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003321 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003322 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003323 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003324
Christian Heimesa170fa12017-09-15 20:27:30 +02003325 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003326 """Connecting to an SSLv23 server with various client options"""
3327 if support.verbose:
3328 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003329 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003330 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003331 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003332 except OSError as x:
3333 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3334 if support.verbose:
3335 sys.stdout.write(
3336 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3337 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003338 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003339 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3340 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003341 if has_tls_version('TLSv1'):
3342 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003343
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003344 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003345 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3346 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003347 if has_tls_version('TLSv1'):
3348 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003349
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003350 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003351 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3352 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003353 if has_tls_version('TLSv1'):
3354 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003355
3356 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003357 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003358 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003359 server_options=ssl.OP_NO_SSLv3)
3360 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003361 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003362 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003363 if has_tls_version('TLSv1'):
3364 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3365 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003366
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003367 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003368 def test_protocol_sslv3(self):
3369 """Connecting to an SSLv3 server with various client options"""
3370 if support.verbose:
3371 sys.stdout.write("\n")
3372 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3373 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3374 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003375 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003376 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003377 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003378 client_options=ssl.OP_NO_SSLv3)
3379 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3380 if no_sslv2_implies_sslv3_hello():
3381 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003382 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003383 False, client_options=ssl.OP_NO_SSLv2)
3384
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003385 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003386 def test_protocol_tlsv1(self):
3387 """Connecting to a TLSv1 server with various client options"""
3388 if support.verbose:
3389 sys.stdout.write("\n")
3390 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3391 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3392 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003393 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003394 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003395 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003396 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003397 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003398 client_options=ssl.OP_NO_TLSv1)
3399
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003400 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003401 def test_protocol_tlsv1_1(self):
3402 """Connecting to a TLSv1.1 server with various client options.
3403 Testing against older TLS versions."""
3404 if support.verbose:
3405 sys.stdout.write("\n")
3406 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003407 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003408 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003409 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003410 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003411 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003412 client_options=ssl.OP_NO_TLSv1_1)
3413
Christian Heimesa170fa12017-09-15 20:27:30 +02003414 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003415 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3416 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003417
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003418 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003419 def test_protocol_tlsv1_2(self):
3420 """Connecting to a TLSv1.2 server with various client options.
3421 Testing against older TLS versions."""
3422 if support.verbose:
3423 sys.stdout.write("\n")
3424 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3425 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3426 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003427 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003428 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003429 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003430 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003431 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003432 client_options=ssl.OP_NO_TLSv1_2)
3433
Christian Heimesa170fa12017-09-15 20:27:30 +02003434 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003435 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3436 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3437 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3438 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3439
3440 def test_starttls(self):
3441 """Switching from clear text to encrypted and back again."""
3442 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3443
3444 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003445 starttls_server=True,
3446 chatty=True,
3447 connectionchatty=True)
3448 wrapped = False
3449 with server:
3450 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003451 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003452 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003453 if support.verbose:
3454 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003455 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003456 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003457 sys.stdout.write(
3458 " client: sending %r...\n" % indata)
3459 if wrapped:
3460 conn.write(indata)
3461 outdata = conn.read()
3462 else:
3463 s.send(indata)
3464 outdata = s.recv(1024)
3465 msg = outdata.strip().lower()
3466 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3467 # STARTTLS ok, switch to secure mode
3468 if support.verbose:
3469 sys.stdout.write(
3470 " client: read %r from server, starting TLS...\n"
3471 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003472 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003473 wrapped = True
3474 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3475 # ENDTLS ok, switch back to clear text
3476 if support.verbose:
3477 sys.stdout.write(
3478 " client: read %r from server, ending TLS...\n"
3479 % msg)
3480 s = conn.unwrap()
3481 wrapped = False
3482 else:
3483 if support.verbose:
3484 sys.stdout.write(
3485 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003486 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003487 sys.stdout.write(" client: closing connection.\n")
3488 if wrapped:
3489 conn.write(b"over\n")
3490 else:
3491 s.send(b"over\n")
3492 if wrapped:
3493 conn.close()
3494 else:
3495 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003496
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003497 def test_socketserver(self):
3498 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003499 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003500 # try to connect
3501 if support.verbose:
3502 sys.stdout.write('\n')
3503 with open(CERTFILE, 'rb') as f:
3504 d1 = f.read()
3505 d2 = ''
3506 # now fetch the same data from the HTTPS server
3507 url = 'https://localhost:%d/%s' % (
3508 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003509 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003510 f = urllib.request.urlopen(url, context=context)
3511 try:
3512 dlen = f.info().get("content-length")
3513 if dlen and (int(dlen) > 0):
3514 d2 = f.read(int(dlen))
3515 if support.verbose:
3516 sys.stdout.write(
3517 " client: read %d bytes from remote server '%s'\n"
3518 % (len(d2), server))
3519 finally:
3520 f.close()
3521 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003522
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003523 def test_asyncore_server(self):
3524 """Check the example asyncore integration."""
3525 if support.verbose:
3526 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003527
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003528 indata = b"FOO\n"
3529 server = AsyncoreEchoServer(CERTFILE)
3530 with server:
3531 s = test_wrap_socket(socket.socket())
3532 s.connect(('127.0.0.1', server.port))
3533 if support.verbose:
3534 sys.stdout.write(
3535 " client: sending %r...\n" % indata)
3536 s.write(indata)
3537 outdata = s.read()
3538 if support.verbose:
3539 sys.stdout.write(" client: read %r\n" % outdata)
3540 if outdata != indata.lower():
3541 self.fail(
3542 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3543 % (outdata[:20], len(outdata),
3544 indata[:20].lower(), len(indata)))
3545 s.write(b"over\n")
3546 if support.verbose:
3547 sys.stdout.write(" client: closing connection.\n")
3548 s.close()
3549 if support.verbose:
3550 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003551
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003552 def test_recv_send(self):
3553 """Test recv(), send() and friends."""
3554 if support.verbose:
3555 sys.stdout.write("\n")
3556
3557 server = ThreadedEchoServer(CERTFILE,
3558 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003559 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003560 cacerts=CERTFILE,
3561 chatty=True,
3562 connectionchatty=False)
3563 with server:
3564 s = test_wrap_socket(socket.socket(),
3565 server_side=False,
3566 certfile=CERTFILE,
3567 ca_certs=CERTFILE,
3568 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003569 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003570 s.connect((HOST, server.port))
3571 # helper methods for standardising recv* method signatures
3572 def _recv_into():
3573 b = bytearray(b"\0"*100)
3574 count = s.recv_into(b)
3575 return b[:count]
3576
3577 def _recvfrom_into():
3578 b = bytearray(b"\0"*100)
3579 count, addr = s.recvfrom_into(b)
3580 return b[:count]
3581
3582 # (name, method, expect success?, *args, return value func)
3583 send_methods = [
3584 ('send', s.send, True, [], len),
3585 ('sendto', s.sendto, False, ["some.address"], len),
3586 ('sendall', s.sendall, True, [], lambda x: None),
3587 ]
3588 # (name, method, whether to expect success, *args)
3589 recv_methods = [
3590 ('recv', s.recv, True, []),
3591 ('recvfrom', s.recvfrom, False, ["some.address"]),
3592 ('recv_into', _recv_into, True, []),
3593 ('recvfrom_into', _recvfrom_into, False, []),
3594 ]
3595 data_prefix = "PREFIX_"
3596
3597 for (meth_name, send_meth, expect_success, args,
3598 ret_val_meth) in send_methods:
3599 indata = (data_prefix + meth_name).encode('ascii')
3600 try:
3601 ret = send_meth(indata, *args)
3602 msg = "sending with {}".format(meth_name)
3603 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3604 outdata = s.read()
3605 if outdata != indata.lower():
3606 self.fail(
3607 "While sending with <<{name:s}>> bad data "
3608 "<<{outdata:r}>> ({nout:d}) received; "
3609 "expected <<{indata:r}>> ({nin:d})\n".format(
3610 name=meth_name, outdata=outdata[:20],
3611 nout=len(outdata),
3612 indata=indata[:20], nin=len(indata)
3613 )
3614 )
3615 except ValueError as e:
3616 if expect_success:
3617 self.fail(
3618 "Failed to send with method <<{name:s}>>; "
3619 "expected to succeed.\n".format(name=meth_name)
3620 )
3621 if not str(e).startswith(meth_name):
3622 self.fail(
3623 "Method <<{name:s}>> failed with unexpected "
3624 "exception message: {exp:s}\n".format(
3625 name=meth_name, exp=e
3626 )
3627 )
3628
3629 for meth_name, recv_meth, expect_success, args in recv_methods:
3630 indata = (data_prefix + meth_name).encode('ascii')
3631 try:
3632 s.send(indata)
3633 outdata = recv_meth(*args)
3634 if outdata != indata.lower():
3635 self.fail(
3636 "While receiving with <<{name:s}>> bad data "
3637 "<<{outdata:r}>> ({nout:d}) received; "
3638 "expected <<{indata:r}>> ({nin:d})\n".format(
3639 name=meth_name, outdata=outdata[:20],
3640 nout=len(outdata),
3641 indata=indata[:20], nin=len(indata)
3642 )
3643 )
3644 except ValueError as e:
3645 if expect_success:
3646 self.fail(
3647 "Failed to receive with method <<{name:s}>>; "
3648 "expected to succeed.\n".format(name=meth_name)
3649 )
3650 if not str(e).startswith(meth_name):
3651 self.fail(
3652 "Method <<{name:s}>> failed with unexpected "
3653 "exception message: {exp:s}\n".format(
3654 name=meth_name, exp=e
3655 )
3656 )
3657 # consume data
3658 s.read()
3659
3660 # read(-1, buffer) is supported, even though read(-1) is not
3661 data = b"data"
3662 s.send(data)
3663 buffer = bytearray(len(data))
3664 self.assertEqual(s.read(-1, buffer), len(data))
3665 self.assertEqual(buffer, data)
3666
Christian Heimes888bbdc2017-09-07 14:18:21 -07003667 # sendall accepts bytes-like objects
3668 if ctypes is not None:
3669 ubyte = ctypes.c_ubyte * len(data)
3670 byteslike = ubyte.from_buffer_copy(data)
3671 s.sendall(byteslike)
3672 self.assertEqual(s.read(), data)
3673
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003674 # Make sure sendmsg et al are disallowed to avoid
3675 # inadvertent disclosure of data and/or corruption
3676 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003677 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003678 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3679 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3680 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003681 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003682 s.write(b"over\n")
3683
3684 self.assertRaises(ValueError, s.recv, -1)
3685 self.assertRaises(ValueError, s.read, -1)
3686
3687 s.close()
3688
3689 def test_recv_zero(self):
3690 server = ThreadedEchoServer(CERTFILE)
3691 server.__enter__()
3692 self.addCleanup(server.__exit__, None, None)
3693 s = socket.create_connection((HOST, server.port))
3694 self.addCleanup(s.close)
3695 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3696 self.addCleanup(s.close)
3697
3698 # recv/read(0) should return no data
3699 s.send(b"data")
3700 self.assertEqual(s.recv(0), b"")
3701 self.assertEqual(s.read(0), b"")
3702 self.assertEqual(s.read(), b"data")
3703
3704 # Should not block if the other end sends no data
3705 s.setblocking(False)
3706 self.assertEqual(s.recv(0), b"")
3707 self.assertEqual(s.recv_into(bytearray()), 0)
3708
3709 def test_nonblocking_send(self):
3710 server = ThreadedEchoServer(CERTFILE,
3711 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003712 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003713 cacerts=CERTFILE,
3714 chatty=True,
3715 connectionchatty=False)
3716 with server:
3717 s = test_wrap_socket(socket.socket(),
3718 server_side=False,
3719 certfile=CERTFILE,
3720 ca_certs=CERTFILE,
3721 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003722 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003723 s.connect((HOST, server.port))
3724 s.setblocking(False)
3725
3726 # If we keep sending data, at some point the buffers
3727 # will be full and the call will block
3728 buf = bytearray(8192)
3729 def fill_buffer():
3730 while True:
3731 s.send(buf)
3732 self.assertRaises((ssl.SSLWantWriteError,
3733 ssl.SSLWantReadError), fill_buffer)
3734
3735 # Now read all the output and discard it
3736 s.setblocking(True)
3737 s.close()
3738
3739 def test_handshake_timeout(self):
3740 # Issue #5103: SSL handshake must respect the socket timeout
3741 server = socket.socket(socket.AF_INET)
3742 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003743 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003744 started = threading.Event()
3745 finish = False
3746
3747 def serve():
3748 server.listen()
3749 started.set()
3750 conns = []
3751 while not finish:
3752 r, w, e = select.select([server], [], [], 0.1)
3753 if server in r:
3754 # Let the socket hang around rather than having
3755 # it closed by garbage collection.
3756 conns.append(server.accept()[0])
3757 for sock in conns:
3758 sock.close()
3759
3760 t = threading.Thread(target=serve)
3761 t.start()
3762 started.wait()
3763
3764 try:
3765 try:
3766 c = socket.socket(socket.AF_INET)
3767 c.settimeout(0.2)
3768 c.connect((host, port))
3769 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003770 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003771 test_wrap_socket, c)
3772 finally:
3773 c.close()
3774 try:
3775 c = socket.socket(socket.AF_INET)
3776 c = test_wrap_socket(c)
3777 c.settimeout(0.2)
3778 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003779 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003780 c.connect, (host, port))
3781 finally:
3782 c.close()
3783 finally:
3784 finish = True
3785 t.join()
3786 server.close()
3787
3788 def test_server_accept(self):
3789 # Issue #16357: accept() on a SSLSocket created through
3790 # SSLContext.wrap_socket().
Christian Heimesa170fa12017-09-15 20:27:30 +02003791 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003792 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003793 context.load_verify_locations(SIGNING_CA)
3794 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003795 server = socket.socket(socket.AF_INET)
3796 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003797 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003798 server = context.wrap_socket(server, server_side=True)
3799 self.assertTrue(server.server_side)
3800
3801 evt = threading.Event()
3802 remote = None
3803 peer = None
3804 def serve():
3805 nonlocal remote, peer
3806 server.listen()
3807 # Block on the accept and wait on the connection to close.
3808 evt.set()
3809 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003810 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003811
3812 t = threading.Thread(target=serve)
3813 t.start()
3814 # Client wait until server setup and perform a connect.
3815 evt.wait()
3816 client = context.wrap_socket(socket.socket())
3817 client.connect((host, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003818 client.send(b'data')
3819 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003820 client_addr = client.getsockname()
3821 client.close()
3822 t.join()
3823 remote.close()
3824 server.close()
3825 # Sanity checks.
3826 self.assertIsInstance(remote, ssl.SSLSocket)
3827 self.assertEqual(peer, client_addr)
3828
3829 def test_getpeercert_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003830 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003831 with context.wrap_socket(socket.socket()) as sock:
3832 with self.assertRaises(OSError) as cm:
3833 sock.getpeercert()
3834 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3835
3836 def test_do_handshake_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003837 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003838 with context.wrap_socket(socket.socket()) as sock:
3839 with self.assertRaises(OSError) as cm:
3840 sock.do_handshake()
3841 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3842
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003843 def test_no_shared_ciphers(self):
3844 client_context, server_context, hostname = testing_context()
3845 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3846 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003847 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003848 client_context.set_ciphers("AES128")
3849 server_context.set_ciphers("AES256")
3850 with ThreadedEchoServer(context=server_context) as server:
3851 with client_context.wrap_socket(socket.socket(),
3852 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003853 with self.assertRaises(OSError):
3854 s.connect((HOST, server.port))
3855 self.assertIn("no shared cipher", server.conn_errors[0])
3856
3857 def test_version_basic(self):
3858 """
3859 Basic tests for SSLSocket.version().
3860 More tests are done in the test_protocol_*() methods.
3861 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003862 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3863 context.check_hostname = False
3864 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003865 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003866 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003867 chatty=False) as server:
3868 with context.wrap_socket(socket.socket()) as s:
3869 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003870 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003871 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003872 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003873 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003874 self.assertIs(s.version(), None)
3875
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003876 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003877 def test_tls1_3(self):
3878 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
3879 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003880 context.options |= (
3881 ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2
3882 )
3883 with ThreadedEchoServer(context=context) as server:
3884 with context.wrap_socket(socket.socket()) as s:
3885 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003886 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003887 'TLS_AES_256_GCM_SHA384',
3888 'TLS_CHACHA20_POLY1305_SHA256',
3889 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003890 })
3891 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003892
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003893 @requires_minimum_version
3894 @requires_tls_version('TLSv1_2')
3895 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003896 client_context, server_context, hostname = testing_context()
3897 # client TLSv1.0 to 1.2
3898 client_context.minimum_version = ssl.TLSVersion.TLSv1
3899 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3900 # server only TLSv1.2
3901 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3902 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3903
3904 with ThreadedEchoServer(context=server_context) as server:
3905 with client_context.wrap_socket(socket.socket(),
3906 server_hostname=hostname) as s:
3907 s.connect((HOST, server.port))
3908 self.assertEqual(s.version(), 'TLSv1.2')
3909
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003910 @requires_minimum_version
3911 @requires_tls_version('TLSv1_1')
3912 def test_min_max_version_tlsv1_1(self):
3913 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003914 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003915 client_context.minimum_version = ssl.TLSVersion.TLSv1
3916 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003917 server_context.minimum_version = ssl.TLSVersion.TLSv1
3918 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003919 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003920
3921 with ThreadedEchoServer(context=server_context) as server:
3922 with client_context.wrap_socket(socket.socket(),
3923 server_hostname=hostname) as s:
3924 s.connect((HOST, server.port))
3925 self.assertEqual(s.version(), 'TLSv1.1')
3926
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003927 @requires_minimum_version
3928 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003929 @requires_tls_version('TLSv1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003930 def test_min_max_version_mismatch(self):
3931 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003932 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003933 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003934 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003935 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003936 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003937 seclevel_workaround(client_context, server_context)
3938
Christian Heimes698dde12018-02-27 11:54:43 +01003939 with ThreadedEchoServer(context=server_context) as server:
3940 with client_context.wrap_socket(socket.socket(),
3941 server_hostname=hostname) as s:
3942 with self.assertRaises(ssl.SSLError) as e:
3943 s.connect((HOST, server.port))
3944 self.assertIn("alert", str(e.exception))
3945
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003946 @requires_minimum_version
3947 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003948 def test_min_max_version_sslv3(self):
3949 client_context, server_context, hostname = testing_context()
3950 server_context.minimum_version = ssl.TLSVersion.SSLv3
3951 client_context.minimum_version = ssl.TLSVersion.SSLv3
3952 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003953 seclevel_workaround(client_context, server_context)
3954
Christian Heimes698dde12018-02-27 11:54:43 +01003955 with ThreadedEchoServer(context=server_context) as server:
3956 with client_context.wrap_socket(socket.socket(),
3957 server_hostname=hostname) as s:
3958 s.connect((HOST, server.port))
3959 self.assertEqual(s.version(), 'SSLv3')
3960
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003961 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3962 def test_default_ecdh_curve(self):
3963 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3964 # should be enabled by default on SSL contexts.
Christian Heimesa170fa12017-09-15 20:27:30 +02003965 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003966 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003967 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3968 # cipher name.
3969 context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003970 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3971 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3972 # our default cipher list should prefer ECDH-based ciphers
3973 # automatically.
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003974 with ThreadedEchoServer(context=context) as server:
3975 with context.wrap_socket(socket.socket()) as s:
3976 s.connect((HOST, server.port))
3977 self.assertIn("ECDH", s.cipher()[0])
3978
3979 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3980 "'tls-unique' channel binding not available")
3981 def test_tls_unique_channel_binding(self):
3982 """Test tls-unique channel binding."""
3983 if support.verbose:
3984 sys.stdout.write("\n")
3985
Christian Heimes05d9fe32018-02-27 08:55:39 +01003986 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003987
3988 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003989 chatty=True,
3990 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003991
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003992 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003993 with client_context.wrap_socket(
3994 socket.socket(),
3995 server_hostname=hostname) as s:
3996 s.connect((HOST, server.port))
3997 # get the data
3998 cb_data = s.get_channel_binding("tls-unique")
3999 if support.verbose:
4000 sys.stdout.write(
4001 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004002
Christian Heimes05d9fe32018-02-27 08:55:39 +01004003 # check if it is sane
4004 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02004005 if s.version() == 'TLSv1.3':
4006 self.assertEqual(len(cb_data), 48)
4007 else:
4008 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004009
Christian Heimes05d9fe32018-02-27 08:55:39 +01004010 # and compare with the peers version
4011 s.write(b"CB tls-unique\n")
4012 peer_data_repr = s.read().strip()
4013 self.assertEqual(peer_data_repr,
4014 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004015
4016 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01004017 with client_context.wrap_socket(
4018 socket.socket(),
4019 server_hostname=hostname) as s:
4020 s.connect((HOST, server.port))
4021 new_cb_data = s.get_channel_binding("tls-unique")
4022 if support.verbose:
4023 sys.stdout.write(
4024 "got another channel binding data: {0!r}\n".format(
4025 new_cb_data)
4026 )
4027 # is it really unique
4028 self.assertNotEqual(cb_data, new_cb_data)
4029 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02004030 if s.version() == 'TLSv1.3':
4031 self.assertEqual(len(cb_data), 48)
4032 else:
4033 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01004034 s.write(b"CB tls-unique\n")
4035 peer_data_repr = s.read().strip()
4036 self.assertEqual(peer_data_repr,
4037 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004038
4039 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004040 client_context, server_context, hostname = testing_context()
4041 stats = server_params_test(client_context, server_context,
4042 chatty=True, connectionchatty=True,
4043 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004044 if support.verbose:
4045 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
4046 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
4047
4048 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
4049 "ssl.OP_NO_COMPRESSION needed for this test")
4050 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004051 client_context, server_context, hostname = testing_context()
4052 client_context.options |= ssl.OP_NO_COMPRESSION
4053 server_context.options |= ssl.OP_NO_COMPRESSION
4054 stats = server_params_test(client_context, server_context,
4055 chatty=True, connectionchatty=True,
4056 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004057 self.assertIs(stats['compression'], None)
4058
Paul Monsonf3550692019-06-19 13:09:54 -07004059 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004060 def test_dh_params(self):
4061 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004062 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004063 # test scenario needs TLS <= 1.2
4064 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004065 server_context.load_dh_params(DHFILE)
4066 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004067 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004068 stats = server_params_test(client_context, server_context,
4069 chatty=True, connectionchatty=True,
4070 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004071 cipher = stats["cipher"][0]
4072 parts = cipher.split("-")
4073 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4074 self.fail("Non-DH cipher: " + cipher[0])
4075
Christian Heimesb7b92252018-02-25 09:49:31 +01004076 @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004077 @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
Christian Heimesb7b92252018-02-25 09:49:31 +01004078 def test_ecdh_curve(self):
4079 # server secp384r1, client auto
4080 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004081
Christian Heimesb7b92252018-02-25 09:49:31 +01004082 server_context.set_ecdh_curve("secp384r1")
4083 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4084 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4085 stats = server_params_test(client_context, server_context,
4086 chatty=True, connectionchatty=True,
4087 sni_name=hostname)
4088
4089 # server auto, client secp384r1
4090 client_context, server_context, hostname = testing_context()
4091 client_context.set_ecdh_curve("secp384r1")
4092 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4093 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4094 stats = server_params_test(client_context, server_context,
4095 chatty=True, connectionchatty=True,
4096 sni_name=hostname)
4097
4098 # server / client curve mismatch
4099 client_context, server_context, hostname = testing_context()
4100 client_context.set_ecdh_curve("prime256v1")
4101 server_context.set_ecdh_curve("secp384r1")
4102 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4103 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4104 try:
Christian Heimes39258d32021-04-17 11:36:35 +02004105 server_params_test(client_context, server_context,
4106 chatty=True, connectionchatty=True,
4107 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004108 except ssl.SSLError:
Christian Heimes39258d32021-04-17 11:36:35 +02004109 self.fail("mismatch curve did not fail")
Christian Heimesb7b92252018-02-25 09:49:31 +01004110
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004111 def test_selected_alpn_protocol(self):
4112 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004113 client_context, server_context, hostname = testing_context()
4114 stats = server_params_test(client_context, server_context,
4115 chatty=True, connectionchatty=True,
4116 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004117 self.assertIs(stats['client_alpn_protocol'], None)
4118
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004119 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4120 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004121 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004122 server_context.set_alpn_protocols(['foo', 'bar'])
4123 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004124 chatty=True, connectionchatty=True,
4125 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004126 self.assertIs(stats['client_alpn_protocol'], None)
4127
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004128 def test_alpn_protocols(self):
4129 server_protocols = ['foo', 'bar', 'milkshake']
4130 protocol_tests = [
4131 (['foo', 'bar'], 'foo'),
4132 (['bar', 'foo'], 'foo'),
4133 (['milkshake'], 'milkshake'),
4134 (['http/3.0', 'http/4.0'], None)
4135 ]
4136 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004137 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004138 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004139 client_context.set_alpn_protocols(client_protocols)
4140
4141 try:
4142 stats = server_params_test(client_context,
4143 server_context,
4144 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004145 connectionchatty=True,
4146 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004147 except ssl.SSLError as e:
4148 stats = e
4149
Christian Heimes39258d32021-04-17 11:36:35 +02004150 msg = "failed trying %s (s) and %s (c).\n" \
4151 "was expecting %s, but got %%s from the %%s" \
4152 % (str(server_protocols), str(client_protocols),
4153 str(expected))
4154 client_result = stats['client_alpn_protocol']
4155 self.assertEqual(client_result, expected,
4156 msg % (client_result, "client"))
4157 server_result = stats['server_alpn_protocols'][-1] \
4158 if len(stats['server_alpn_protocols']) else 'nothing'
4159 self.assertEqual(server_result, expected,
4160 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004161
4162 def test_selected_npn_protocol(self):
4163 # selected_npn_protocol() is None unless NPN is used
Christian Heimesa170fa12017-09-15 20:27:30 +02004164 client_context, server_context, hostname = testing_context()
4165 stats = server_params_test(client_context, server_context,
4166 chatty=True, connectionchatty=True,
4167 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004168 self.assertIs(stats['client_npn_protocol'], None)
4169
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004170 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004171 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004172
4173 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004174 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004175 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004176 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004177 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004178 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004179 client_context.load_verify_locations(SIGNING_CA)
4180 return server_context, other_context, client_context
4181
4182 def check_common_name(self, stats, name):
4183 cert = stats['peercert']
4184 self.assertIn((('commonName', name),), cert['subject'])
4185
4186 @needs_sni
4187 def test_sni_callback(self):
4188 calls = []
4189 server_context, other_context, client_context = self.sni_contexts()
4190
Christian Heimesa170fa12017-09-15 20:27:30 +02004191 client_context.check_hostname = False
4192
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004193 def servername_cb(ssl_sock, server_name, initial_context):
4194 calls.append((server_name, initial_context))
4195 if server_name is not None:
4196 ssl_sock.context = other_context
4197 server_context.set_servername_callback(servername_cb)
4198
4199 stats = server_params_test(client_context, server_context,
4200 chatty=True,
4201 sni_name='supermessage')
4202 # The hostname was fetched properly, and the certificate was
4203 # changed for the connection.
4204 self.assertEqual(calls, [("supermessage", server_context)])
4205 # CERTFILE4 was selected
4206 self.check_common_name(stats, 'fakehostname')
4207
4208 calls = []
4209 # The callback is called with server_name=None
4210 stats = server_params_test(client_context, server_context,
4211 chatty=True,
4212 sni_name=None)
4213 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004214 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004215
4216 # Check disabling the callback
4217 calls = []
4218 server_context.set_servername_callback(None)
4219
4220 stats = server_params_test(client_context, server_context,
4221 chatty=True,
4222 sni_name='notfunny')
4223 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004224 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004225 self.assertEqual(calls, [])
4226
4227 @needs_sni
4228 def test_sni_callback_alert(self):
4229 # Returning a TLS alert is reflected to the connecting client
4230 server_context, other_context, client_context = self.sni_contexts()
4231
4232 def cb_returning_alert(ssl_sock, server_name, initial_context):
4233 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4234 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004235 with self.assertRaises(ssl.SSLError) as cm:
4236 stats = server_params_test(client_context, server_context,
4237 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004238 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004239 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004240
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004241 @needs_sni
4242 def test_sni_callback_raising(self):
4243 # Raising fails the connection with a TLS handshake failure alert.
4244 server_context, other_context, client_context = self.sni_contexts()
4245
4246 def cb_raising(ssl_sock, server_name, initial_context):
4247 1/0
4248 server_context.set_servername_callback(cb_raising)
4249
Victor Stinner00253502019-06-03 03:51:43 +02004250 with support.catch_unraisable_exception() as catch:
4251 with self.assertRaises(ssl.SSLError) as cm:
4252 stats = server_params_test(client_context, server_context,
4253 chatty=False,
4254 sni_name='supermessage')
4255
4256 self.assertEqual(cm.exception.reason,
4257 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4258 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004259
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004260 @needs_sni
4261 def test_sni_callback_wrong_return_type(self):
4262 # Returning the wrong return type terminates the TLS connection
4263 # with an internal error alert.
4264 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004265
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004266 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4267 return "foo"
4268 server_context.set_servername_callback(cb_wrong_return_type)
4269
Victor Stinner00253502019-06-03 03:51:43 +02004270 with support.catch_unraisable_exception() as catch:
4271 with self.assertRaises(ssl.SSLError) as cm:
4272 stats = server_params_test(client_context, server_context,
4273 chatty=False,
4274 sni_name='supermessage')
4275
4276
4277 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4278 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004279
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004280 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004281 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004282 client_context.set_ciphers("AES128:AES256")
4283 server_context.set_ciphers("AES256")
4284 expected_algs = [
4285 "AES256", "AES-256",
4286 # TLS 1.3 ciphers are always enabled
4287 "TLS_CHACHA20", "TLS_AES",
4288 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004289
Christian Heimesa170fa12017-09-15 20:27:30 +02004290 stats = server_params_test(client_context, server_context,
4291 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004292 ciphers = stats['server_shared_ciphers'][0]
4293 self.assertGreater(len(ciphers), 0)
4294 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004295 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004296 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004297
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004298 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004299 client_context, server_context, hostname = testing_context()
4300 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004301
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004302 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004303 s = client_context.wrap_socket(socket.socket(),
4304 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004305 s.connect((HOST, server.port))
4306 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004307
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004308 self.assertRaises(ValueError, s.read, 1024)
4309 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004310
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004311 def test_sendfile(self):
4312 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004313 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004314 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004315 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesa170fa12017-09-15 20:27:30 +02004316 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004317 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01004318 context.load_verify_locations(SIGNING_CA)
4319 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004320 server = ThreadedEchoServer(context=context, chatty=False)
4321 with server:
4322 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004323 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004324 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004325 s.sendfile(file)
4326 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004327
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004328 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004329 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004330 # TODO: sessions aren't compatible with TLSv1.3 yet
4331 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004332
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004333 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004334 stats = server_params_test(client_context, server_context,
4335 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004336 session = stats['session']
4337 self.assertTrue(session.id)
4338 self.assertGreater(session.time, 0)
4339 self.assertGreater(session.timeout, 0)
4340 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004341 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004342 self.assertFalse(stats['session_reused'])
4343 sess_stat = server_context.session_stats()
4344 self.assertEqual(sess_stat['accept'], 1)
4345 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004346
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004347 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004348 stats = server_params_test(client_context, server_context,
4349 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004350 sess_stat = server_context.session_stats()
4351 self.assertEqual(sess_stat['accept'], 2)
4352 self.assertEqual(sess_stat['hits'], 1)
4353 self.assertTrue(stats['session_reused'])
4354 session2 = stats['session']
4355 self.assertEqual(session2.id, session.id)
4356 self.assertEqual(session2, session)
4357 self.assertIsNot(session2, session)
4358 self.assertGreaterEqual(session2.time, session.time)
4359 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004360
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004361 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004362 stats = server_params_test(client_context, server_context,
4363 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004364 self.assertFalse(stats['session_reused'])
4365 session3 = stats['session']
4366 self.assertNotEqual(session3.id, session.id)
4367 self.assertNotEqual(session3, session)
4368 sess_stat = server_context.session_stats()
4369 self.assertEqual(sess_stat['accept'], 3)
4370 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004371
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004372 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004373 stats = server_params_test(client_context, server_context,
4374 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004375 self.assertTrue(stats['session_reused'])
4376 session4 = stats['session']
4377 self.assertEqual(session4.id, session.id)
4378 self.assertEqual(session4, session)
4379 self.assertGreaterEqual(session4.time, session.time)
4380 self.assertGreaterEqual(session4.timeout, session.timeout)
4381 sess_stat = server_context.session_stats()
4382 self.assertEqual(sess_stat['accept'], 4)
4383 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004384
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004385 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004386 client_context, server_context, hostname = testing_context()
4387 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004388
Christian Heimes05d9fe32018-02-27 08:55:39 +01004389 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004390 client_context.options |= ssl.OP_NO_TLSv1_3
4391 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004392
Christian Heimesa170fa12017-09-15 20:27:30 +02004393 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004394 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004395 with client_context.wrap_socket(socket.socket(),
4396 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004397 # session is None before handshake
4398 self.assertEqual(s.session, None)
4399 self.assertEqual(s.session_reused, None)
4400 s.connect((HOST, server.port))
4401 session = s.session
4402 self.assertTrue(session)
4403 with self.assertRaises(TypeError) as e:
4404 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004405 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004406
Christian Heimesa170fa12017-09-15 20:27:30 +02004407 with client_context.wrap_socket(socket.socket(),
4408 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004409 s.connect((HOST, server.port))
4410 # cannot set session after handshake
4411 with self.assertRaises(ValueError) as e:
4412 s.session = session
4413 self.assertEqual(str(e.exception),
4414 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004415
Christian Heimesa170fa12017-09-15 20:27:30 +02004416 with client_context.wrap_socket(socket.socket(),
4417 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004418 # can set session before handshake and before the
4419 # connection was established
4420 s.session = session
4421 s.connect((HOST, server.port))
4422 self.assertEqual(s.session.id, session.id)
4423 self.assertEqual(s.session, session)
4424 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004425
Christian Heimesa170fa12017-09-15 20:27:30 +02004426 with client_context2.wrap_socket(socket.socket(),
4427 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004428 # cannot re-use session with a different SSLContext
4429 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004430 s.session = session
4431 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004432 self.assertEqual(str(e.exception),
4433 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004434
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004435
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004436@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004437class TestPostHandshakeAuth(unittest.TestCase):
4438 def test_pha_setter(self):
4439 protocols = [
4440 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
4441 ]
4442 for protocol in protocols:
4443 ctx = ssl.SSLContext(protocol)
4444 self.assertEqual(ctx.post_handshake_auth, False)
4445
4446 ctx.post_handshake_auth = True
4447 self.assertEqual(ctx.post_handshake_auth, True)
4448
4449 ctx.verify_mode = ssl.CERT_REQUIRED
4450 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4451 self.assertEqual(ctx.post_handshake_auth, True)
4452
4453 ctx.post_handshake_auth = False
4454 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4455 self.assertEqual(ctx.post_handshake_auth, False)
4456
4457 ctx.verify_mode = ssl.CERT_OPTIONAL
4458 ctx.post_handshake_auth = True
4459 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4460 self.assertEqual(ctx.post_handshake_auth, True)
4461
4462 def test_pha_required(self):
4463 client_context, server_context, hostname = testing_context()
4464 server_context.post_handshake_auth = True
4465 server_context.verify_mode = ssl.CERT_REQUIRED
4466 client_context.post_handshake_auth = True
4467 client_context.load_cert_chain(SIGNED_CERTFILE)
4468
4469 server = ThreadedEchoServer(context=server_context, chatty=False)
4470 with server:
4471 with client_context.wrap_socket(socket.socket(),
4472 server_hostname=hostname) as s:
4473 s.connect((HOST, server.port))
4474 s.write(b'HASCERT')
4475 self.assertEqual(s.recv(1024), b'FALSE\n')
4476 s.write(b'PHA')
4477 self.assertEqual(s.recv(1024), b'OK\n')
4478 s.write(b'HASCERT')
4479 self.assertEqual(s.recv(1024), b'TRUE\n')
4480 # PHA method just returns true when cert is already available
4481 s.write(b'PHA')
4482 self.assertEqual(s.recv(1024), b'OK\n')
4483 s.write(b'GETCERT')
4484 cert_text = s.recv(4096).decode('us-ascii')
4485 self.assertIn('Python Software Foundation CA', cert_text)
4486
4487 def test_pha_required_nocert(self):
4488 client_context, server_context, hostname = testing_context()
4489 server_context.post_handshake_auth = True
4490 server_context.verify_mode = ssl.CERT_REQUIRED
4491 client_context.post_handshake_auth = True
4492
Victor Stinner73ea5462019-07-09 14:33:49 +02004493 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4494 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004495 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004496 server = ThreadedEchoServer(context=server_context, chatty=False)
4497 with server:
4498 with client_context.wrap_socket(socket.socket(),
4499 server_hostname=hostname) as s:
4500 s.connect((HOST, server.port))
4501 s.write(b'PHA')
4502 # receive CertificateRequest
4503 self.assertEqual(s.recv(1024), b'OK\n')
4504 # send empty Certificate + Finish
4505 s.write(b'HASCERT')
4506 # receive alert
4507 with self.assertRaisesRegex(
4508 ssl.SSLError,
4509 'tlsv13 alert certificate required'):
4510 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004511
4512 def test_pha_optional(self):
4513 if support.verbose:
4514 sys.stdout.write("\n")
4515
4516 client_context, server_context, hostname = testing_context()
4517 server_context.post_handshake_auth = True
4518 server_context.verify_mode = ssl.CERT_REQUIRED
4519 client_context.post_handshake_auth = True
4520 client_context.load_cert_chain(SIGNED_CERTFILE)
4521
4522 # check CERT_OPTIONAL
4523 server_context.verify_mode = ssl.CERT_OPTIONAL
4524 server = ThreadedEchoServer(context=server_context, chatty=False)
4525 with server:
4526 with client_context.wrap_socket(socket.socket(),
4527 server_hostname=hostname) as s:
4528 s.connect((HOST, server.port))
4529 s.write(b'HASCERT')
4530 self.assertEqual(s.recv(1024), b'FALSE\n')
4531 s.write(b'PHA')
4532 self.assertEqual(s.recv(1024), b'OK\n')
4533 s.write(b'HASCERT')
4534 self.assertEqual(s.recv(1024), b'TRUE\n')
4535
4536 def test_pha_optional_nocert(self):
4537 if support.verbose:
4538 sys.stdout.write("\n")
4539
4540 client_context, server_context, hostname = testing_context()
4541 server_context.post_handshake_auth = True
4542 server_context.verify_mode = ssl.CERT_OPTIONAL
4543 client_context.post_handshake_auth = True
4544
4545 server = ThreadedEchoServer(context=server_context, chatty=False)
4546 with server:
4547 with client_context.wrap_socket(socket.socket(),
4548 server_hostname=hostname) as s:
4549 s.connect((HOST, server.port))
4550 s.write(b'HASCERT')
4551 self.assertEqual(s.recv(1024), b'FALSE\n')
4552 s.write(b'PHA')
4553 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004554 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004555 s.write(b'HASCERT')
4556 self.assertEqual(s.recv(1024), b'FALSE\n')
4557
4558 def test_pha_no_pha_client(self):
4559 client_context, server_context, hostname = testing_context()
4560 server_context.post_handshake_auth = True
4561 server_context.verify_mode = ssl.CERT_REQUIRED
4562 client_context.load_cert_chain(SIGNED_CERTFILE)
4563
4564 server = ThreadedEchoServer(context=server_context, chatty=False)
4565 with server:
4566 with client_context.wrap_socket(socket.socket(),
4567 server_hostname=hostname) as s:
4568 s.connect((HOST, server.port))
4569 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4570 s.verify_client_post_handshake()
4571 s.write(b'PHA')
4572 self.assertIn(b'extension not received', s.recv(1024))
4573
4574 def test_pha_no_pha_server(self):
4575 # server doesn't have PHA enabled, cert is requested in handshake
4576 client_context, server_context, hostname = testing_context()
4577 server_context.verify_mode = ssl.CERT_REQUIRED
4578 client_context.post_handshake_auth = True
4579 client_context.load_cert_chain(SIGNED_CERTFILE)
4580
4581 server = ThreadedEchoServer(context=server_context, chatty=False)
4582 with server:
4583 with client_context.wrap_socket(socket.socket(),
4584 server_hostname=hostname) as s:
4585 s.connect((HOST, server.port))
4586 s.write(b'HASCERT')
4587 self.assertEqual(s.recv(1024), b'TRUE\n')
4588 # PHA doesn't fail if there is already a cert
4589 s.write(b'PHA')
4590 self.assertEqual(s.recv(1024), b'OK\n')
4591 s.write(b'HASCERT')
4592 self.assertEqual(s.recv(1024), b'TRUE\n')
4593
4594 def test_pha_not_tls13(self):
4595 # TLS 1.2
4596 client_context, server_context, hostname = testing_context()
4597 server_context.verify_mode = ssl.CERT_REQUIRED
4598 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4599 client_context.post_handshake_auth = True
4600 client_context.load_cert_chain(SIGNED_CERTFILE)
4601
4602 server = ThreadedEchoServer(context=server_context, chatty=False)
4603 with server:
4604 with client_context.wrap_socket(socket.socket(),
4605 server_hostname=hostname) as s:
4606 s.connect((HOST, server.port))
4607 # PHA fails for TLS != 1.3
4608 s.write(b'PHA')
4609 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4610
Christian Heimesf0f59302019-07-01 08:29:17 +02004611 def test_bpo37428_pha_cert_none(self):
4612 # verify that post_handshake_auth does not implicitly enable cert
4613 # validation.
4614 hostname = SIGNED_CERTFILE_HOSTNAME
4615 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4616 client_context.post_handshake_auth = True
4617 client_context.load_cert_chain(SIGNED_CERTFILE)
4618 # no cert validation and CA on client side
4619 client_context.check_hostname = False
4620 client_context.verify_mode = ssl.CERT_NONE
4621
4622 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4623 server_context.load_cert_chain(SIGNED_CERTFILE)
4624 server_context.load_verify_locations(SIGNING_CA)
4625 server_context.post_handshake_auth = True
4626 server_context.verify_mode = ssl.CERT_REQUIRED
4627
4628 server = ThreadedEchoServer(context=server_context, chatty=False)
4629 with server:
4630 with client_context.wrap_socket(socket.socket(),
4631 server_hostname=hostname) as s:
4632 s.connect((HOST, server.port))
4633 s.write(b'HASCERT')
4634 self.assertEqual(s.recv(1024), b'FALSE\n')
4635 s.write(b'PHA')
4636 self.assertEqual(s.recv(1024), b'OK\n')
4637 s.write(b'HASCERT')
4638 self.assertEqual(s.recv(1024), b'TRUE\n')
4639 # server cert has not been validated
4640 self.assertEqual(s.getpeercert(), {})
4641
Christian Heimes9fb051f2018-09-23 08:32:31 +02004642
Christian Heimesc7f70692019-05-31 11:44:05 +02004643HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4644requires_keylog = unittest.skipUnless(
4645 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4646
4647class TestSSLDebug(unittest.TestCase):
4648
Hai Shia7f5d932020-08-04 00:41:24 +08004649 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004650 with open(fname) as f:
4651 return len(list(f))
4652
4653 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004654 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004655 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004656 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004657 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4658 self.assertEqual(ctx.keylog_filename, None)
4659
Hai Shia7f5d932020-08-04 00:41:24 +08004660 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4661 ctx.keylog_filename = os_helper.TESTFN
4662 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4663 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004664 self.assertEqual(self.keylog_lines(), 1)
4665
4666 ctx.keylog_filename = None
4667 self.assertEqual(ctx.keylog_filename, None)
4668
4669 with self.assertRaises((IsADirectoryError, PermissionError)):
4670 # Windows raises PermissionError
4671 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004672 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004673
4674 with self.assertRaises(TypeError):
4675 ctx.keylog_filename = 1
4676
4677 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004678 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004679 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004680 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004681 client_context, server_context, hostname = testing_context()
4682
Hai Shia7f5d932020-08-04 00:41:24 +08004683 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004684 server = ThreadedEchoServer(context=server_context, chatty=False)
4685 with server:
4686 with client_context.wrap_socket(socket.socket(),
4687 server_hostname=hostname) as s:
4688 s.connect((HOST, server.port))
4689 # header, 5 lines for TLS 1.3
4690 self.assertEqual(self.keylog_lines(), 6)
4691
4692 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004693 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004694 server = ThreadedEchoServer(context=server_context, chatty=False)
4695 with server:
4696 with client_context.wrap_socket(socket.socket(),
4697 server_hostname=hostname) as s:
4698 s.connect((HOST, server.port))
4699 self.assertGreaterEqual(self.keylog_lines(), 11)
4700
Hai Shia7f5d932020-08-04 00:41:24 +08004701 client_context.keylog_filename = os_helper.TESTFN
4702 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004703 server = ThreadedEchoServer(context=server_context, chatty=False)
4704 with server:
4705 with client_context.wrap_socket(socket.socket(),
4706 server_hostname=hostname) as s:
4707 s.connect((HOST, server.port))
4708 self.assertGreaterEqual(self.keylog_lines(), 21)
4709
4710 client_context.keylog_filename = None
4711 server_context.keylog_filename = None
4712
4713 @requires_keylog
4714 @unittest.skipIf(sys.flags.ignore_environment,
4715 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004716 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004717 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004718 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004719 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004720 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4721 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004722
4723 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4724 self.assertEqual(ctx.keylog_filename, None)
4725
4726 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004727 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004728
4729 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004730 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004731
4732 def test_msg_callback(self):
4733 client_context, server_context, hostname = testing_context()
4734
4735 def msg_cb(conn, direction, version, content_type, msg_type, data):
4736 pass
4737
4738 self.assertIs(client_context._msg_callback, None)
4739 client_context._msg_callback = msg_cb
4740 self.assertIs(client_context._msg_callback, msg_cb)
4741 with self.assertRaises(TypeError):
4742 client_context._msg_callback = object()
4743
4744 def test_msg_callback_tls12(self):
4745 client_context, server_context, hostname = testing_context()
4746 client_context.options |= ssl.OP_NO_TLSv1_3
4747
4748 msg = []
4749
4750 def msg_cb(conn, direction, version, content_type, msg_type, data):
4751 self.assertIsInstance(conn, ssl.SSLSocket)
4752 self.assertIsInstance(data, bytes)
4753 self.assertIn(direction, {'read', 'write'})
4754 msg.append((direction, version, content_type, msg_type))
4755
4756 client_context._msg_callback = msg_cb
4757
4758 server = ThreadedEchoServer(context=server_context, chatty=False)
4759 with server:
4760 with client_context.wrap_socket(socket.socket(),
4761 server_hostname=hostname) as s:
4762 s.connect((HOST, server.port))
4763
Christian Heimese35d1ba2019-06-03 20:40:15 +02004764 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004765 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4766 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004767 msg
4768 )
4769 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004770 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4771 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004772 msg
4773 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004774
Christian Heimes77cde502021-03-21 16:13:09 +01004775 def test_msg_callback_deadlock_bpo43577(self):
4776 client_context, server_context, hostname = testing_context()
4777 server_context2 = testing_context()[1]
4778
4779 def msg_cb(conn, direction, version, content_type, msg_type, data):
4780 pass
4781
4782 def sni_cb(sock, servername, ctx):
4783 sock.context = server_context2
4784
4785 server_context._msg_callback = msg_cb
4786 server_context.sni_callback = sni_cb
4787
4788 server = ThreadedEchoServer(context=server_context, chatty=False)
4789 with server:
4790 with client_context.wrap_socket(socket.socket(),
4791 server_hostname=hostname) as s:
4792 s.connect((HOST, server.port))
4793 with client_context.wrap_socket(socket.socket(),
4794 server_hostname=hostname) as s:
4795 s.connect((HOST, server.port))
4796
Christian Heimesc7f70692019-05-31 11:44:05 +02004797
Thomas Woutersed03b412007-08-28 21:37:11 +00004798def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004799 if support.verbose:
4800 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004801 'Mac': platform.mac_ver,
4802 'Windows': platform.win32_ver,
4803 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004804 for name, func in plats.items():
4805 plat = func()
4806 if plat and plat[0]:
4807 plat = '%s %r' % (name, plat)
4808 break
4809 else:
4810 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004811 print("test_ssl: testing with %r %r" %
4812 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4813 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004814 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004815 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4816 try:
4817 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4818 except AttributeError:
4819 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004820
Antoine Pitrou152efa22010-05-16 18:19:27 +00004821 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004822 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004823 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004824 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004825 BADCERT, BADKEY, EMPTYCERT]:
4826 if not os.path.exists(filename):
4827 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004828
Martin Panter3840b2a2016-03-27 01:53:46 +00004829 tests = [
4830 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004831 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004832 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004833 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004834
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004835 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004836 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004837
Hai Shie80697d2020-05-28 06:10:27 +08004838 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004839 try:
4840 support.run_unittest(*tests)
4841 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004842 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004843
4844if __name__ == "__main__":
4845 test_main()