blob: a89768f24b2b0aaca6c0f9836c7cc8a56a3aff74 [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
Ethan Furmana02cb472021-04-21 10:20:44 -070015import datetime
16import enum
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000017import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000018import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000019import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000020import pprint
Antoine Pitrou803e6d62010-10-13 10:36:15 +000021import urllib.request
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020022import threading
Thomas Woutersed03b412007-08-28 21:37:11 +000023import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000024import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000025import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000026import platform
Christian Heimes892d66e2018-01-29 14:10:18 +010027import sysconfig
Christian Heimesdf6ac7e2019-09-26 17:02:59 +020028import functools
Christian Heimes888bbdc2017-09-07 14:18:21 -070029try:
30 import ctypes
31except ImportError:
32 ctypes = None
Thomas Woutersed03b412007-08-28 21:37:11 +000033
Hai Shia7f5d932020-08-04 00:41:24 +080034ssl = import_helper.import_module("ssl")
Christian Heimes666991f2021-04-26 15:01:40 +020035import _ssl
Antoine Pitrou05d936d2010-10-13 11:38:36 +000036
Ethan Furmana02cb472021-04-21 10:20:44 -070037from ssl import TLSVersion, _TLSContentType, _TLSMessageType, _TLSAlertType
Martin Panter3840b2a2016-03-27 01:53:46 +000038
Paul Monsonf3550692019-06-19 13:09:54 -070039Py_DEBUG = hasattr(sys, 'gettotalrefcount')
40Py_DEBUG_WIN32 = Py_DEBUG and sys.platform == 'win32'
41
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010042PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Serhiy Storchaka16994912020-04-25 10:06:29 +030043HOST = socket_helper.HOST
Christian Heimesd37b74f2021-04-19 08:31:29 +020044IS_OPENSSL_3_0_0 = ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
Christian Heimes892d66e2018-01-29 14:10:18 +010045PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
Antoine Pitrou152efa22010-05-16 18:19:27 +000046
Victor Stinner3ef63442019-02-19 18:06:03 +010047PROTOCOL_TO_TLS_VERSION = {}
48for proto, ver in (
49 ("PROTOCOL_SSLv23", "SSLv3"),
50 ("PROTOCOL_TLSv1", "TLSv1"),
51 ("PROTOCOL_TLSv1_1", "TLSv1_1"),
52):
53 try:
54 proto = getattr(ssl, proto)
55 ver = getattr(ssl.TLSVersion, ver)
56 except AttributeError:
57 continue
58 PROTOCOL_TO_TLS_VERSION[proto] = ver
59
Christian Heimesefff7062013-11-21 03:35:02 +010060def data_file(*name):
61 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000062
Antoine Pitrou81564092010-10-08 23:06:24 +000063# The custom key and certificate files used in test_ssl are generated
64# using Lib/test/make_ssl_certs.py.
65# Other certificates are simply fetched from the Internet servers they
66# are meant to authenticate.
67
Antoine Pitrou152efa22010-05-16 18:19:27 +000068CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000069BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000070ONLYCERT = data_file("ssl_cert.pem")
71ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000072BYTES_ONLYCERT = os.fsencode(ONLYCERT)
73BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020074CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
75ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
76KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000077CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000078BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010079CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
80CAFILE_CACERT = data_file("capath", "5ed36f99.0")
81
Christian Heimesbd5c7d22018-01-20 15:16:30 +010082CERTFILE_INFO = {
83 'issuer': ((('countryName', 'XY'),),
84 (('localityName', 'Castle Anthrax'),),
85 (('organizationName', 'Python Software Foundation'),),
86 (('commonName', 'localhost'),)),
Christian Heimese6dac002018-08-30 07:25:49 +020087 'notAfter': 'Aug 26 14:23:15 2028 GMT',
88 'notBefore': 'Aug 29 14:23:15 2018 GMT',
89 'serialNumber': '98A7CF88C74A32ED',
Christian Heimesbd5c7d22018-01-20 15:16:30 +010090 'subject': ((('countryName', 'XY'),),
91 (('localityName', 'Castle Anthrax'),),
92 (('organizationName', 'Python Software Foundation'),),
93 (('commonName', 'localhost'),)),
94 'subjectAltName': (('DNS', 'localhost'),),
95 'version': 3
96}
Antoine Pitrou152efa22010-05-16 18:19:27 +000097
Christian Heimes22587792013-11-21 23:56:13 +010098# empty CRL
99CRLFILE = data_file("revocation.crl")
100
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100101# Two keys and certs signed by the same CA (for SNI tests)
102SIGNED_CERTFILE = data_file("keycert3.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200103SIGNED_CERTFILE_HOSTNAME = 'localhost'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100104
105SIGNED_CERTFILE_INFO = {
106 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
107 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
108 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
109 'issuer': ((('countryName', 'XY'),),
110 (('organizationName', 'Python Software Foundation CA'),),
111 (('commonName', 'our-ca-server'),)),
Christian Heimesb467d9a2021-04-17 10:07:19 +0200112 'notAfter': 'Oct 28 14:23:16 2037 GMT',
Christian Heimese6dac002018-08-30 07:25:49 +0200113 'notBefore': 'Aug 29 14:23:16 2018 GMT',
114 'serialNumber': 'CB2D80995A69525C',
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100115 'subject': ((('countryName', 'XY'),),
116 (('localityName', 'Castle Anthrax'),),
117 (('organizationName', 'Python Software Foundation'),),
118 (('commonName', 'localhost'),)),
119 'subjectAltName': (('DNS', 'localhost'),),
120 'version': 3
121}
122
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100123SIGNED_CERTFILE2 = data_file("keycert4.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200124SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100125SIGNED_CERTFILE_ECC = data_file("keycertecc.pem")
126SIGNED_CERTFILE_ECC_HOSTNAME = 'localhost-ecc'
127
Martin Panter3840b2a2016-03-27 01:53:46 +0000128# Same certificate as pycacert.pem, but without extra text in file
129SIGNING_CA = data_file("capath", "ceff1710.0")
Christian Heimes1c03abd2016-09-06 23:25:35 +0200130# cert with all kinds of subject alt names
131ALLSANFILE = data_file("allsans.pem")
Christian Heimes66e57422018-01-29 14:25:13 +0100132IDNSANSFILE = data_file("idnsans.pem")
Christian Heimesb467d9a2021-04-17 10:07:19 +0200133NOSANFILE = data_file("nosan.pem")
134NOSAN_HOSTNAME = 'localhost'
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100135
Martin Panter3d81d932016-01-14 09:36:00 +0000136REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +0000137
138EMPTYCERT = data_file("nullcert.pem")
139BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +0000140NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000141BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200142NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +0200143NULLBYTECERT = data_file("nullbytecert.pem")
Christian Heimesa37f5242019-01-15 23:47:42 +0100144TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000145
Christian Heimes88bfd0b2018-08-14 12:54:19 +0200146DHFILE = data_file("ffdh3072.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100147BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +0000148
Christian Heimes358cfd42016-09-10 22:43:48 +0200149# Not defined in all versions of OpenSSL
150OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
151OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
152OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
153OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
Christian Heimes05d9fe32018-02-27 08:55:39 +0100154OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
Christian Heimes6f37ebc2021-04-09 17:59:21 +0200155OP_IGNORE_UNEXPECTED_EOF = getattr(ssl, "OP_IGNORE_UNEXPECTED_EOF", 0)
Christian Heimes358cfd42016-09-10 22:43:48 +0200156
Christian Heimesf6c6b582021-03-18 23:06:50 +0100157# Ubuntu has patched OpenSSL and changed behavior of security level 2
158# see https://bugs.python.org/issue41561#msg389003
159def is_ubuntu():
160 try:
161 # Assume that any references of "ubuntu" implies Ubuntu-like distro
162 # The workaround is not required for 18.04, but doesn't hurt either.
163 with open("/etc/os-release", encoding="utf-8") as f:
164 return "ubuntu" in f.read()
165 except FileNotFoundError:
166 return False
167
168if is_ubuntu():
169 def seclevel_workaround(*ctxs):
170 """"Lower security level to '1' and allow all ciphers for TLS 1.0/1"""
171 for ctx in ctxs:
Christian Heimes34477502021-04-12 12:00:38 +0200172 if (
173 hasattr(ctx, "minimum_version") and
174 ctx.minimum_version <= ssl.TLSVersion.TLSv1_1
175 ):
Christian Heimesf6c6b582021-03-18 23:06:50 +0100176 ctx.set_ciphers("@SECLEVEL=1:ALL")
177else:
178 def seclevel_workaround(*ctxs):
179 pass
180
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100181
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200182def has_tls_protocol(protocol):
183 """Check if a TLS protocol is available and enabled
184
185 :param protocol: enum ssl._SSLMethod member or name
186 :return: bool
187 """
188 if isinstance(protocol, str):
189 assert protocol.startswith('PROTOCOL_')
190 protocol = getattr(ssl, protocol, None)
191 if protocol is None:
192 return False
193 if protocol in {
194 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
195 ssl.PROTOCOL_TLS_CLIENT
196 }:
197 # auto-negotiate protocols are always available
198 return True
199 name = protocol.name
200 return has_tls_version(name[len('PROTOCOL_'):])
201
202
203@functools.lru_cache
204def has_tls_version(version):
205 """Check if a TLS/SSL version is enabled
206
207 :param version: TLS version name or ssl.TLSVersion member
208 :return: bool
209 """
210 if version == "SSLv2":
211 # never supported and not even in TLSVersion enum
212 return False
213
214 if isinstance(version, str):
215 version = ssl.TLSVersion.__members__[version]
216
217 # check compile time flags like ssl.HAS_TLSv1_2
218 if not getattr(ssl, f'HAS_{version.name}'):
219 return False
220
Christian Heimes5151d642021-04-09 15:43:06 +0200221 if IS_OPENSSL_3_0_0 and version < ssl.TLSVersion.TLSv1_2:
222 # bpo43791: 3.0.0-alpha14 fails with TLSV1_ALERT_INTERNAL_ERROR
223 return False
224
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200225 # check runtime and dynamic crypto policy settings. A TLS version may
226 # be compiled in but disabled by a policy or config option.
Christian Heimes2875c602021-04-19 07:27:10 +0200227 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200228 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200229 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200230 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
231 version < ctx.minimum_version
232 ):
233 return False
234 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200235 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200236 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
237 version > ctx.maximum_version
238 ):
239 return False
240
241 return True
242
243
244def requires_tls_version(version):
245 """Decorator to skip tests when a required TLS version is not available
246
247 :param version: TLS version name or ssl.TLSVersion member
248 :return:
249 """
250 def decorator(func):
251 @functools.wraps(func)
252 def wrapper(*args, **kw):
253 if not has_tls_version(version):
254 raise unittest.SkipTest(f"{version} is not available.")
255 else:
256 return func(*args, **kw)
257 return wrapper
258 return decorator
259
260
Thomas Woutersed03b412007-08-28 21:37:11 +0000261def handle_error(prefix):
262 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000263 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000264 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000265
Christian Heimesb7b92252018-02-25 09:49:31 +0100266
Antoine Pitrouc695c952014-04-28 20:57:36 +0200267def utc_offset(): #NOTE: ignore issues like #1647654
268 # local time = utc time + utc offset
269 if time.daylight and time.localtime().tm_isdst > 0:
270 return -time.altzone # seconds
271 return -time.timezone
272
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100273
Christian Heimes2875c602021-04-19 07:27:10 +0200274ignore_deprecation = warnings_helper.ignore_warnings(
275 category=DeprecationWarning
276)
Antoine Pitrou23df4832010-08-04 17:14:06 +0000277
Christian Heimes2875c602021-04-19 07:27:10 +0200278
279def test_wrap_socket(sock, *,
Christian Heimesd0486372016-09-10 23:23:33 +0200280 cert_reqs=ssl.CERT_NONE, ca_certs=None,
281 ciphers=None, certfile=None, keyfile=None,
282 **kwargs):
Christian Heimes2875c602021-04-19 07:27:10 +0200283 if not kwargs.get("server_side"):
284 kwargs["server_hostname"] = SIGNED_CERTFILE_HOSTNAME
285 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
286 else:
287 context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimesd0486372016-09-10 23:23:33 +0200288 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200289 if cert_reqs == ssl.CERT_NONE:
290 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200291 context.verify_mode = cert_reqs
292 if ca_certs is not None:
293 context.load_verify_locations(ca_certs)
294 if certfile is not None or keyfile is not None:
295 context.load_cert_chain(certfile, keyfile)
296 if ciphers is not None:
297 context.set_ciphers(ciphers)
298 return context.wrap_socket(sock, **kwargs)
299
Christian Heimesa170fa12017-09-15 20:27:30 +0200300
Christian Heimes666991f2021-04-26 15:01:40 +0200301def testing_context(server_cert=SIGNED_CERTFILE, *, server_chain=True):
Christian Heimesa170fa12017-09-15 20:27:30 +0200302 """Create context
303
304 client_context, server_context, hostname = testing_context()
305 """
306 if server_cert == SIGNED_CERTFILE:
307 hostname = SIGNED_CERTFILE_HOSTNAME
308 elif server_cert == SIGNED_CERTFILE2:
309 hostname = SIGNED_CERTFILE2_HOSTNAME
Christian Heimesb467d9a2021-04-17 10:07:19 +0200310 elif server_cert == NOSANFILE:
311 hostname = NOSAN_HOSTNAME
Christian Heimesa170fa12017-09-15 20:27:30 +0200312 else:
313 raise ValueError(server_cert)
314
315 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
316 client_context.load_verify_locations(SIGNING_CA)
317
318 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
319 server_context.load_cert_chain(server_cert)
Christian Heimes666991f2021-04-26 15:01:40 +0200320 if server_chain:
321 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200322
323 return client_context, server_context, hostname
324
325
Antoine Pitrou152efa22010-05-16 18:19:27 +0000326class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000327
Antoine Pitrou480a1242010-04-28 21:37:09 +0000328 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000329 ssl.CERT_NONE
330 ssl.CERT_OPTIONAL
331 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100332 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100333 ssl.OP_SINGLE_DH_USE
Christian Heimesd37b74f2021-04-19 08:31:29 +0200334 ssl.OP_SINGLE_ECDH_USE
Christian Heimes39258d32021-04-17 11:36:35 +0200335 ssl.OP_NO_COMPRESSION
Christian Heimesd37b74f2021-04-19 08:31:29 +0200336 self.assertEqual(ssl.HAS_SNI, True)
337 self.assertEqual(ssl.HAS_ECDH, True)
338 self.assertEqual(ssl.HAS_TLSv1_2, True)
339 self.assertEqual(ssl.HAS_TLSv1_3, True)
Christian Heimescb5b68a2017-09-07 18:07:00 -0700340 ssl.OP_NO_SSLv2
341 ssl.OP_NO_SSLv3
342 ssl.OP_NO_TLSv1
343 ssl.OP_NO_TLSv1_3
Christian Heimes39258d32021-04-17 11:36:35 +0200344 ssl.OP_NO_TLSv1_1
345 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200346 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000347
Christian Heimes91554e42021-05-02 09:47:45 +0200348 def test_ssl_types(self):
349 ssl_types = [
350 _ssl._SSLContext,
351 _ssl._SSLSocket,
352 _ssl.MemoryBIO,
353 _ssl.Certificate,
354 _ssl.SSLSession,
355 _ssl.SSLError,
356 ]
357 for ssl_type in ssl_types:
358 with self.subTest(ssl_type=ssl_type):
359 with self.assertRaisesRegex(TypeError, "immutable type"):
360 ssl_type.value = None
Erlend Egeberg Aasland0a3452e2021-06-24 01:46:25 +0200361 support.check_disallow_instantiation(self, _ssl.Certificate)
Christian Heimes91554e42021-05-02 09:47:45 +0200362
Christian Heimes9d50ab52018-02-27 10:17:30 +0100363 def test_private_init(self):
364 with self.assertRaisesRegex(TypeError, "public constructor"):
365 with socket.socket() as s:
366 ssl.SSLSocket(s)
367
Antoine Pitrou172f0252014-04-18 20:33:08 +0200368 def test_str_for_enums(self):
369 # Make sure that the PROTOCOL_* constants have enum-like string
370 # reprs.
Christian Heimes2875c602021-04-19 07:27:10 +0200371 proto = ssl.PROTOCOL_TLS_CLIENT
372 self.assertEqual(str(proto), 'PROTOCOL_TLS_CLIENT')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200373 ctx = ssl.SSLContext(proto)
374 self.assertIs(ctx.protocol, proto)
375
Antoine Pitrou480a1242010-04-28 21:37:09 +0000376 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000377 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000378 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000379 sys.stdout.write("\n RAND_status is %d (%s)\n"
380 % (v, (v and "sufficient randomness") or
381 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200382
Christian Heimes2875c602021-04-19 07:27:10 +0200383 with warnings_helper.check_warnings():
384 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200385 self.assertEqual(len(data), 16)
386 self.assertEqual(is_cryptographic, v == 1)
387 if v:
388 data = ssl.RAND_bytes(16)
389 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200390 else:
391 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200392
Victor Stinner1e81a392013-12-19 16:47:04 +0100393 # negative num is invalid
394 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
Christian Heimes2875c602021-04-19 07:27:10 +0200395 with warnings_helper.check_warnings():
396 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
Victor Stinner1e81a392013-12-19 16:47:04 +0100397
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000398 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200399 ssl.RAND_add(b"this is a random bytes object", 75.0)
400 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000401
Antoine Pitrou480a1242010-04-28 21:37:09 +0000402 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000403 # note that this uses an 'unofficial' function in _ssl.c,
404 # provided solely for this test, to exercise the certificate
405 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100406 self.assertEqual(
407 ssl._ssl._test_decode_cert(CERTFILE),
408 CERTFILE_INFO
409 )
410 self.assertEqual(
411 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
412 SIGNED_CERTFILE_INFO
413 )
414
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200415 # Issue #13034: the subjectAltName in some certificates
416 # (notably projects.developer.nokia.com:443) wasn't parsed
417 p = ssl._ssl._test_decode_cert(NOKIACERT)
418 if support.verbose:
419 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
420 self.assertEqual(p['subjectAltName'],
421 (('DNS', 'projects.developer.nokia.com'),
422 ('DNS', 'projects.forum.nokia.com'))
423 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100424 # extra OCSP and AIA fields
425 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
426 self.assertEqual(p['caIssuers'],
427 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
428 self.assertEqual(p['crlDistributionPoints'],
429 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000430
Christian Heimesa37f5242019-01-15 23:47:42 +0100431 def test_parse_cert_CVE_2019_5010(self):
432 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
433 if support.verbose:
434 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
435 self.assertEqual(
436 p,
437 {
438 'issuer': (
439 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
440 'notAfter': 'Jun 14 18:00:58 2028 GMT',
441 'notBefore': 'Jun 18 18:00:58 2018 GMT',
442 'serialNumber': '02',
443 'subject': ((('countryName', 'UK'),),
444 (('commonName',
445 'codenomicon-vm-2.test.lal.cisco.com'),)),
446 'subjectAltName': (
447 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
448 'version': 3
449 }
450 )
451
Christian Heimes824f7f32013-08-17 00:54:47 +0200452 def test_parse_cert_CVE_2013_4238(self):
453 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
454 if support.verbose:
455 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
456 subject = ((('countryName', 'US'),),
457 (('stateOrProvinceName', 'Oregon'),),
458 (('localityName', 'Beaverton'),),
459 (('organizationName', 'Python Software Foundation'),),
460 (('organizationalUnitName', 'Python Core Development'),),
461 (('commonName', 'null.python.org\x00example.org'),),
462 (('emailAddress', 'python-dev@python.org'),))
463 self.assertEqual(p['subject'], subject)
464 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200465 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
466 san = (('DNS', 'altnull.python.org\x00example.com'),
467 ('email', 'null@python.org\x00user@example.org'),
468 ('URI', 'http://null.python.org\x00http://example.org'),
469 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100470 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200471 else:
472 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
473 san = (('DNS', 'altnull.python.org\x00example.com'),
474 ('email', 'null@python.org\x00user@example.org'),
475 ('URI', 'http://null.python.org\x00http://example.org'),
476 ('IP Address', '192.0.2.1'),
477 ('IP Address', '<invalid>'))
478
479 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200480
Christian Heimes1c03abd2016-09-06 23:25:35 +0200481 def test_parse_all_sans(self):
482 p = ssl._ssl._test_decode_cert(ALLSANFILE)
483 self.assertEqual(p['subjectAltName'],
484 (
485 ('DNS', 'allsans'),
486 ('othername', '<unsupported>'),
487 ('othername', '<unsupported>'),
488 ('email', 'user@example.org'),
489 ('DNS', 'www.example.org'),
490 ('DirName',
491 ((('countryName', 'XY'),),
492 (('localityName', 'Castle Anthrax'),),
493 (('organizationName', 'Python Software Foundation'),),
494 (('commonName', 'dirname example'),))),
495 ('URI', 'https://www.python.org/'),
496 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100497 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200498 ('Registered ID', '1.2.3.4.5')
499 )
500 )
501
Antoine Pitrou480a1242010-04-28 21:37:09 +0000502 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000503 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000504 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000505 d1 = ssl.PEM_cert_to_DER_cert(pem)
506 p2 = ssl.DER_cert_to_PEM_cert(d1)
507 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000508 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000509 if not p2.startswith(ssl.PEM_HEADER + '\n'):
510 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
511 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
512 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000513
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000514 def test_openssl_version(self):
515 n = ssl.OPENSSL_VERSION_NUMBER
516 t = ssl.OPENSSL_VERSION_INFO
517 s = ssl.OPENSSL_VERSION
518 self.assertIsInstance(n, int)
519 self.assertIsInstance(t, tuple)
520 self.assertIsInstance(s, str)
521 # Some sanity checks follow
Christian Heimesd37b74f2021-04-19 08:31:29 +0200522 # >= 1.1.1
523 self.assertGreaterEqual(n, 0x10101000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100524 # < 4.0
525 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000526 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100527 self.assertGreaterEqual(major, 1)
528 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000529 self.assertGreaterEqual(minor, 0)
530 self.assertLess(minor, 256)
531 self.assertGreaterEqual(fix, 0)
532 self.assertLess(fix, 256)
533 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100534 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000535 self.assertGreaterEqual(status, 0)
536 self.assertLessEqual(status, 15)
Christian Heimesd37b74f2021-04-19 08:31:29 +0200537
538 libressl_ver = f"LibreSSL {major:d}"
539 openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}"
540 self.assertTrue(
541 s.startswith((openssl_ver, libressl_ver)),
542 (s, t, hex(n))
543 )
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000544
Antoine Pitrou9d543662010-04-23 23:10:32 +0000545 @support.cpython_only
546 def test_refcycle(self):
547 # Issue #7943: an SSL object doesn't create reference cycles with
548 # itself.
549 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200550 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000551 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800552 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100553 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100554 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000555
Antoine Pitroua468adc2010-09-14 14:43:44 +0000556 def test_wrapped_unconnected(self):
557 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200558 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000559 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200560 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100561 self.assertRaises(OSError, ss.recv, 1)
562 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
563 self.assertRaises(OSError, ss.recvfrom, 1)
564 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
565 self.assertRaises(OSError, ss.send, b'x')
566 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200567 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100568 self.assertRaises(NotImplementedError, ss.sendmsg,
569 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200570 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
571 self.assertRaises(NotImplementedError, ss.recvmsg_into,
572 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000573
Antoine Pitrou40f08742010-04-24 22:04:40 +0000574 def test_timeout(self):
575 # Issue #8524: when creating an SSL socket, the timeout of the
576 # original socket should be retained.
577 for timeout in (None, 0.0, 5.0):
578 s = socket.socket(socket.AF_INET)
579 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200580 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100581 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000582
Miss Islington (bot)4becc562021-06-13 05:07:00 -0700583 def test_openssl111_deprecations(self):
584 options = [
585 ssl.OP_NO_TLSv1,
586 ssl.OP_NO_TLSv1_1,
587 ssl.OP_NO_TLSv1_2,
588 ssl.OP_NO_TLSv1_3
589 ]
590 protocols = [
591 ssl.PROTOCOL_TLSv1,
592 ssl.PROTOCOL_TLSv1_1,
593 ssl.PROTOCOL_TLSv1_2,
594 ssl.PROTOCOL_TLS
595 ]
596 versions = [
597 ssl.TLSVersion.SSLv3,
598 ssl.TLSVersion.TLSv1,
599 ssl.TLSVersion.TLSv1_1,
600 ]
601
602 for option in options:
603 with self.subTest(option=option):
604 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
605 with self.assertWarns(DeprecationWarning) as cm:
606 ctx.options |= option
607 self.assertEqual(
Miss Islington (bot)08f2b9d2021-06-17 03:00:56 -0700608 'ssl.OP_NO_SSL*/ssl.OP_NO_TLS* options are deprecated',
Miss Islington (bot)4becc562021-06-13 05:07:00 -0700609 str(cm.warning)
610 )
611
612 for protocol in protocols:
613 with self.subTest(protocol=protocol):
614 with self.assertWarns(DeprecationWarning) as cm:
615 ssl.SSLContext(protocol)
616 self.assertEqual(
617 f'{protocol!r} is deprecated',
618 str(cm.warning)
619 )
620
621 for version in versions:
622 with self.subTest(version=version):
623 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
624 with self.assertWarns(DeprecationWarning) as cm:
625 ctx.minimum_version = version
626 self.assertEqual(
627 f'ssl.{version!r} is deprecated',
628 str(cm.warning)
629 )
630
Christian Heimes2875c602021-04-19 07:27:10 +0200631 @ignore_deprecation
Christian Heimesd0486372016-09-10 23:23:33 +0200632 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000633 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000634 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000635 "certfile must be specified",
636 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000637 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000638 "certfile must be specified for server-side operations",
639 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000640 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000641 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200642 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100643 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
644 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200645 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200646 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000647 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000648 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +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=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000654 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200655 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000656 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000657 ssl.wrap_socket(sock,
658 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000659 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000660
Martin Panter3464ea22016-02-01 21:58:11 +0000661 def bad_cert_test(self, certfile):
662 """Check that trying to use the given client certificate fails"""
663 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
664 certfile)
665 sock = socket.socket()
666 self.addCleanup(sock.close)
667 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200668 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200669 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000670
671 def test_empty_cert(self):
672 """Wrapping with an empty cert file"""
673 self.bad_cert_test("nullcert.pem")
674
675 def test_malformed_cert(self):
676 """Wrapping with a badly formatted certificate (syntax error)"""
677 self.bad_cert_test("badcert.pem")
678
679 def test_malformed_key(self):
680 """Wrapping with a badly formatted key (syntax error)"""
681 self.bad_cert_test("badkey.pem")
682
Christian Heimes2875c602021-04-19 07:27:10 +0200683 @ignore_deprecation
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000684 def test_match_hostname(self):
685 def ok(cert, hostname):
686 ssl.match_hostname(cert, hostname)
687 def fail(cert, hostname):
688 self.assertRaises(ssl.CertificateError,
689 ssl.match_hostname, cert, hostname)
690
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100691 # -- Hostname matching --
692
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000693 cert = {'subject': ((('commonName', 'example.com'),),)}
694 ok(cert, 'example.com')
695 ok(cert, 'ExAmple.cOm')
696 fail(cert, 'www.example.com')
697 fail(cert, '.example.com')
698 fail(cert, 'example.org')
699 fail(cert, 'exampleXcom')
700
701 cert = {'subject': ((('commonName', '*.a.com'),),)}
702 ok(cert, 'foo.a.com')
703 fail(cert, 'bar.foo.a.com')
704 fail(cert, 'a.com')
705 fail(cert, 'Xa.com')
706 fail(cert, '.a.com')
707
Mandeep Singhede2ac92017-11-27 04:01:27 +0530708 # only match wildcards when they are the only thing
709 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000710 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530711 fail(cert, 'foo.com')
712 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000713 fail(cert, 'bar.com')
714 fail(cert, 'foo.a.com')
715 fail(cert, 'bar.foo.com')
716
Christian Heimes824f7f32013-08-17 00:54:47 +0200717 # NULL bytes are bad, CVE-2013-4073
718 cert = {'subject': ((('commonName',
719 'null.python.org\x00example.org'),),)}
720 ok(cert, 'null.python.org\x00example.org') # or raise an error?
721 fail(cert, 'example.org')
722 fail(cert, 'null.python.org')
723
Georg Brandl72c98d32013-10-27 07:16:53 +0100724 # error cases with wildcards
725 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
726 fail(cert, 'bar.foo.a.com')
727 fail(cert, 'a.com')
728 fail(cert, 'Xa.com')
729 fail(cert, '.a.com')
730
731 cert = {'subject': ((('commonName', 'a.*.com'),),)}
732 fail(cert, 'a.foo.com')
733 fail(cert, 'a..com')
734 fail(cert, 'a.com')
735
736 # wildcard doesn't match IDNA prefix 'xn--'
737 idna = 'püthon.python.org'.encode("idna").decode("ascii")
738 cert = {'subject': ((('commonName', idna),),)}
739 ok(cert, idna)
740 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
741 fail(cert, idna)
742 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
743 fail(cert, idna)
744
745 # wildcard in first fragment and IDNA A-labels in sequent fragments
746 # are supported.
747 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
748 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530749 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
750 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100751 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
752 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
753
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000754 # Slightly fake real-world example
755 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
756 'subject': ((('commonName', 'linuxfrz.org'),),),
757 'subjectAltName': (('DNS', 'linuxfr.org'),
758 ('DNS', 'linuxfr.com'),
759 ('othername', '<unsupported>'))}
760 ok(cert, 'linuxfr.org')
761 ok(cert, 'linuxfr.com')
762 # Not a "DNS" entry
763 fail(cert, '<unsupported>')
764 # When there is a subjectAltName, commonName isn't used
765 fail(cert, 'linuxfrz.org')
766
767 # A pristine real-world example
768 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
769 'subject': ((('countryName', 'US'),),
770 (('stateOrProvinceName', 'California'),),
771 (('localityName', 'Mountain View'),),
772 (('organizationName', 'Google Inc'),),
773 (('commonName', 'mail.google.com'),))}
774 ok(cert, 'mail.google.com')
775 fail(cert, 'gmail.com')
776 # Only commonName is considered
777 fail(cert, 'California')
778
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100779 # -- IPv4 matching --
780 cert = {'subject': ((('commonName', 'example.com'),),),
781 'subjectAltName': (('DNS', 'example.com'),
782 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200783 ('IP Address', '14.15.16.17'),
784 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100785 ok(cert, '10.11.12.13')
786 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200787 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
788 fail(cert, '127.1')
789 fail(cert, '14.15.16.17 ')
790 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100791 fail(cert, '14.15.16.18')
792 fail(cert, 'example.net')
793
794 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300795 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100796 cert = {'subject': ((('commonName', 'example.com'),),),
797 'subjectAltName': (
798 ('DNS', 'example.com'),
799 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
800 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
801 ok(cert, '2001::cafe')
802 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200803 fail(cert, '2003::baba ')
804 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100805 fail(cert, '2003::bebe')
806 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100807
808 # -- Miscellaneous --
809
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000810 # Neither commonName nor subjectAltName
811 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
812 'subject': ((('countryName', 'US'),),
813 (('stateOrProvinceName', 'California'),),
814 (('localityName', 'Mountain View'),),
815 (('organizationName', 'Google Inc'),))}
816 fail(cert, 'mail.google.com')
817
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200818 # No DNS entry in subjectAltName but a commonName
819 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
820 'subject': ((('countryName', 'US'),),
821 (('stateOrProvinceName', 'California'),),
822 (('localityName', 'Mountain View'),),
823 (('commonName', 'mail.google.com'),)),
824 'subjectAltName': (('othername', 'blabla'), )}
825 ok(cert, 'mail.google.com')
826
827 # No DNS entry subjectAltName and no commonName
828 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
829 'subject': ((('countryName', 'US'),),
830 (('stateOrProvinceName', 'California'),),
831 (('localityName', 'Mountain View'),),
832 (('organizationName', 'Google Inc'),)),
833 'subjectAltName': (('othername', 'blabla'),)}
834 fail(cert, 'google.com')
835
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000836 # Empty cert / no cert
837 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
838 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
839
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200840 # Issue #17980: avoid denials of service by refusing more than one
841 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100842 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
843 with self.assertRaisesRegex(
844 ssl.CertificateError,
845 "partial wildcards in leftmost label are not supported"):
846 ssl.match_hostname(cert, 'axxb.example.com')
847
848 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
849 with self.assertRaisesRegex(
850 ssl.CertificateError,
851 "wildcard can only be present in the leftmost label"):
852 ssl.match_hostname(cert, 'www.sub.example.com')
853
854 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
855 with self.assertRaisesRegex(
856 ssl.CertificateError,
857 "too many wildcards"):
858 ssl.match_hostname(cert, 'axxbxxc.example.com')
859
860 cert = {'subject': ((('commonName', '*'),),)}
861 with self.assertRaisesRegex(
862 ssl.CertificateError,
863 "sole wildcard without additional labels are not support"):
864 ssl.match_hostname(cert, 'host')
865
866 cert = {'subject': ((('commonName', '*.com'),),)}
867 with self.assertRaisesRegex(
868 ssl.CertificateError,
869 r"hostname 'com' doesn't match '\*.com'"):
870 ssl.match_hostname(cert, 'com')
871
872 # extra checks for _inet_paton()
873 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
874 with self.assertRaises(ValueError):
875 ssl._inet_paton(invalid)
876 for ipaddr in ['127.0.0.1', '192.168.0.1']:
877 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300878 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100879 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
880 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200881
Antoine Pitroud5323212010-10-22 18:19:07 +0000882 def test_server_side(self):
883 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200884 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000885 with socket.socket() as sock:
886 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
887 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000888
Antoine Pitroud6494802011-07-21 01:11:30 +0200889 def test_unknown_channel_binding(self):
890 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200891 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200892 c = socket.socket(socket.AF_INET)
893 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200894 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100895 with self.assertRaises(ValueError):
896 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200897 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200898
899 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
900 "'tls-unique' channel binding not available")
901 def test_tls_unique_channel_binding(self):
902 # unconnected should return None for known type
903 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200904 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100905 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200906 # the same for server-side
907 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200908 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100909 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200910
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600911 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200912 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600913 r = repr(ss)
914 with self.assertWarns(ResourceWarning) as cm:
915 ss = None
916 support.gc_collect()
917 self.assertIn(r, str(cm.warning.args[0]))
918
Christian Heimes6d7ad132013-06-09 18:02:55 +0200919 def test_get_default_verify_paths(self):
920 paths = ssl.get_default_verify_paths()
921 self.assertEqual(len(paths), 6)
922 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
923
Hai Shia7f5d932020-08-04 00:41:24 +0800924 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200925 env["SSL_CERT_DIR"] = CAPATH
926 env["SSL_CERT_FILE"] = CERTFILE
927 paths = ssl.get_default_verify_paths()
928 self.assertEqual(paths.cafile, CERTFILE)
929 self.assertEqual(paths.capath, CAPATH)
930
Christian Heimes44109d72013-11-22 01:51:30 +0100931 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
932 def test_enum_certificates(self):
933 self.assertTrue(ssl.enum_certificates("CA"))
934 self.assertTrue(ssl.enum_certificates("ROOT"))
935
936 self.assertRaises(TypeError, ssl.enum_certificates)
937 self.assertRaises(WindowsError, ssl.enum_certificates, "")
938
Christian Heimesc2d65e12013-11-22 16:13:55 +0100939 trust_oids = set()
940 for storename in ("CA", "ROOT"):
941 store = ssl.enum_certificates(storename)
942 self.assertIsInstance(store, list)
943 for element in store:
944 self.assertIsInstance(element, tuple)
945 self.assertEqual(len(element), 3)
946 cert, enc, trust = element
947 self.assertIsInstance(cert, bytes)
948 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200949 self.assertIsInstance(trust, (frozenset, set, bool))
950 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100951 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100952
953 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100954 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200955
Christian Heimes46bebee2013-06-09 19:03:31 +0200956 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100957 def test_enum_crls(self):
958 self.assertTrue(ssl.enum_crls("CA"))
959 self.assertRaises(TypeError, ssl.enum_crls)
960 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200961
Christian Heimes44109d72013-11-22 01:51:30 +0100962 crls = ssl.enum_crls("CA")
963 self.assertIsInstance(crls, list)
964 for element in crls:
965 self.assertIsInstance(element, tuple)
966 self.assertEqual(len(element), 2)
967 self.assertIsInstance(element[0], bytes)
968 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200969
Christian Heimes46bebee2013-06-09 19:03:31 +0200970
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100971 def test_asn1object(self):
972 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
973 '1.3.6.1.5.5.7.3.1')
974
975 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
976 self.assertEqual(val, expected)
977 self.assertEqual(val.nid, 129)
978 self.assertEqual(val.shortname, 'serverAuth')
979 self.assertEqual(val.longname, 'TLS Web Server Authentication')
980 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
981 self.assertIsInstance(val, ssl._ASN1Object)
982 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
983
984 val = ssl._ASN1Object.fromnid(129)
985 self.assertEqual(val, expected)
986 self.assertIsInstance(val, ssl._ASN1Object)
987 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100988 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
989 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100990 for i in range(1000):
991 try:
992 obj = ssl._ASN1Object.fromnid(i)
993 except ValueError:
994 pass
995 else:
996 self.assertIsInstance(obj.nid, int)
997 self.assertIsInstance(obj.shortname, str)
998 self.assertIsInstance(obj.longname, str)
999 self.assertIsInstance(obj.oid, (str, type(None)))
1000
1001 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
1002 self.assertEqual(val, expected)
1003 self.assertIsInstance(val, ssl._ASN1Object)
1004 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
1005 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
1006 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +01001007 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
1008 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001009
Christian Heimes72d28502013-11-23 13:56:58 +01001010 def test_purpose_enum(self):
1011 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
1012 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
1013 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
1014 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
1015 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
1016 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
1017 '1.3.6.1.5.5.7.3.1')
1018
1019 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
1020 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
1021 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
1022 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
1023 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
1024 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
1025 '1.3.6.1.5.5.7.3.2')
1026
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001027 def test_unsupported_dtls(self):
1028 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1029 self.addCleanup(s.close)
1030 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +02001031 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001032 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +02001033 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001034 with self.assertRaises(NotImplementedError) as cx:
1035 ctx.wrap_socket(s)
1036 self.assertEqual(str(cx.exception), "only stream sockets are supported")
1037
Antoine Pitrouc695c952014-04-28 20:57:36 +02001038 def cert_time_ok(self, timestring, timestamp):
1039 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
1040
1041 def cert_time_fail(self, timestring):
1042 with self.assertRaises(ValueError):
1043 ssl.cert_time_to_seconds(timestring)
1044
1045 @unittest.skipUnless(utc_offset(),
1046 'local time needs to be different from UTC')
1047 def test_cert_time_to_seconds_timezone(self):
1048 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
1049 # results if local timezone is not UTC
1050 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
1051 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
1052
1053 def test_cert_time_to_seconds(self):
1054 timestring = "Jan 5 09:34:43 2018 GMT"
1055 ts = 1515144883.0
1056 self.cert_time_ok(timestring, ts)
1057 # accept keyword parameter, assert its name
1058 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
1059 # accept both %e and %d (space or zero generated by strftime)
1060 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
1061 # case-insensitive
1062 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
1063 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
1064 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1065 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1066 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1067 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1068 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1069 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1070
1071 newyear_ts = 1230768000.0
1072 # leap seconds
1073 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1074 # same timestamp
1075 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1076
1077 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1078 # allow 60th second (even if it is not a leap second)
1079 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1080 # allow 2nd leap second for compatibility with time.strptime()
1081 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1082 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1083
Mike53f7a7c2017-12-14 14:04:53 +03001084 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001085 # 99991231235959Z (rfc 5280)
1086 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1087
1088 @support.run_with_locale('LC_ALL', '')
1089 def test_cert_time_to_seconds_locale(self):
1090 # `cert_time_to_seconds()` should be locale independent
1091
1092 def local_february_name():
1093 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1094
1095 if local_february_name().lower() == 'feb':
1096 self.skipTest("locale-specific month name needs to be "
1097 "different from C locale")
1098
1099 # locale-independent
1100 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1101 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1102
Martin Panter3840b2a2016-03-27 01:53:46 +00001103 def test_connect_ex_error(self):
1104 server = socket.socket(socket.AF_INET)
1105 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001106 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001107 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001108 cert_reqs=ssl.CERT_REQUIRED)
1109 self.addCleanup(s.close)
1110 rc = s.connect_ex((HOST, port))
1111 # Issue #19919: Windows machines or VMs hosted on Windows
1112 # machines sometimes return EWOULDBLOCK.
1113 errors = (
1114 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1115 errno.EWOULDBLOCK,
1116 )
1117 self.assertIn(rc, errors)
1118
Christian Heimes89d15502021-04-19 06:55:30 +02001119 def test_read_write_zero(self):
1120 # empty reads and writes now work, bpo-42854, bpo-31711
1121 client_context, server_context, hostname = testing_context()
1122 server = ThreadedEchoServer(context=server_context)
1123 with server:
1124 with client_context.wrap_socket(socket.socket(),
1125 server_hostname=hostname) as s:
1126 s.connect((HOST, server.port))
1127 self.assertEqual(s.recv(0), b"")
1128 self.assertEqual(s.send(b""), 0)
1129
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001130
Antoine Pitrou152efa22010-05-16 18:19:27 +00001131class ContextTests(unittest.TestCase):
1132
1133 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001134 for protocol in PROTOCOLS:
Christian Heimes2875c602021-04-19 07:27:10 +02001135 with warnings_helper.check_warnings():
1136 ctx = ssl.SSLContext(protocol)
1137 self.assertEqual(ctx.protocol, protocol)
1138 with warnings_helper.check_warnings():
1139 ctx = ssl.SSLContext()
Christian Heimes598894f2016-09-05 23:19:05 +02001140 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001141 self.assertRaises(ValueError, ssl.SSLContext, -1)
1142 self.assertRaises(ValueError, ssl.SSLContext, 42)
1143
Antoine Pitrou152efa22010-05-16 18:19:27 +00001144 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001145 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001146 ctx.set_ciphers("ALL")
1147 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001148 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001149 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001150
Christian Heimes892d66e2018-01-29 14:10:18 +01001151 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1152 "Test applies only to Python default ciphers")
1153 def test_python_ciphers(self):
1154 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1155 ciphers = ctx.get_ciphers()
1156 for suite in ciphers:
1157 name = suite['name']
1158 self.assertNotIn("PSK", name)
1159 self.assertNotIn("SRP", name)
1160 self.assertNotIn("MD5", name)
1161 self.assertNotIn("RC4", name)
1162 self.assertNotIn("3DES", name)
1163
Christian Heimes25bfcd52016-09-06 00:04:45 +02001164 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001165 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001166 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001167 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001168 self.assertIn('AES256-GCM-SHA384', names)
1169 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001170
Antoine Pitroub5218772010-05-21 09:56:06 +00001171 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001172 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001173 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001174 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001175 # SSLContext also enables these by default
1176 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001177 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001178 OP_ENABLE_MIDDLEBOX_COMPAT |
1179 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001180 self.assertEqual(default, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001181 with warnings_helper.check_warnings():
1182 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001183 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001184 with warnings_helper.check_warnings():
1185 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
Christian Heimes39258d32021-04-17 11:36:35 +02001186 self.assertEqual(default, ctx.options)
1187 ctx.options = 0
1188 # Ubuntu has OP_NO_SSLv3 forced on by default
1189 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001190
Christian Heimesa170fa12017-09-15 20:27:30 +02001191 def test_verify_mode_protocol(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001192 with warnings_helper.check_warnings():
1193 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001194 # Default value
1195 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1196 ctx.verify_mode = ssl.CERT_OPTIONAL
1197 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1198 ctx.verify_mode = ssl.CERT_REQUIRED
1199 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1200 ctx.verify_mode = ssl.CERT_NONE
1201 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1202 with self.assertRaises(TypeError):
1203 ctx.verify_mode = None
1204 with self.assertRaises(ValueError):
1205 ctx.verify_mode = 42
1206
Christian Heimesa170fa12017-09-15 20:27:30 +02001207 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1208 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1209 self.assertFalse(ctx.check_hostname)
1210
1211 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1212 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1213 self.assertTrue(ctx.check_hostname)
1214
Christian Heimes61d478c2018-01-27 15:51:38 +01001215 def test_hostname_checks_common_name(self):
1216 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1217 self.assertTrue(ctx.hostname_checks_common_name)
1218 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1219 ctx.hostname_checks_common_name = True
1220 self.assertTrue(ctx.hostname_checks_common_name)
1221 ctx.hostname_checks_common_name = False
1222 self.assertFalse(ctx.hostname_checks_common_name)
1223 ctx.hostname_checks_common_name = True
1224 self.assertTrue(ctx.hostname_checks_common_name)
1225 else:
1226 with self.assertRaises(AttributeError):
1227 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001228
Christian Heimes2875c602021-04-19 07:27:10 +02001229 @ignore_deprecation
Christian Heimes698dde12018-02-27 11:54:43 +01001230 def test_min_max_version(self):
1231 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001232 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1233 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001234 minimum_range = {
1235 # stock OpenSSL
1236 ssl.TLSVersion.MINIMUM_SUPPORTED,
1237 # Fedora 29 uses TLS 1.0 by default
1238 ssl.TLSVersion.TLSv1,
1239 # RHEL 8 uses TLS 1.2 by default
1240 ssl.TLSVersion.TLSv1_2
1241 }
torsava34864d12019-12-02 17:15:42 +01001242 maximum_range = {
1243 # stock OpenSSL
1244 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1245 # Fedora 32 uses TLS 1.3 by default
1246 ssl.TLSVersion.TLSv1_3
1247 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001248
Christian Heimes34de2d32019-01-18 16:09:30 +01001249 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001250 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001251 )
torsava34864d12019-12-02 17:15:42 +01001252 self.assertIn(
1253 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001254 )
1255
1256 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1257 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1258 self.assertEqual(
1259 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1260 )
1261 self.assertEqual(
1262 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1263 )
1264
1265 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1266 ctx.maximum_version = ssl.TLSVersion.TLSv1
1267 self.assertEqual(
1268 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1269 )
1270 self.assertEqual(
1271 ctx.maximum_version, ssl.TLSVersion.TLSv1
1272 )
1273
1274 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1275 self.assertEqual(
1276 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1277 )
1278
1279 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1280 self.assertIn(
1281 ctx.maximum_version,
1282 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1283 )
1284
1285 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1286 self.assertIn(
1287 ctx.minimum_version,
1288 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1289 )
1290
1291 with self.assertRaises(ValueError):
1292 ctx.minimum_version = 42
1293
1294 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1295
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001296 self.assertIn(
1297 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001298 )
1299 self.assertEqual(
1300 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1301 )
1302 with self.assertRaises(ValueError):
1303 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1304 with self.assertRaises(ValueError):
1305 ctx.maximum_version = ssl.TLSVersion.TLSv1
1306
1307
matthewhughes9348e836bb2020-07-17 09:59:15 +01001308 @unittest.skipUnless(
1309 hasattr(ssl.SSLContext, 'security_level'),
1310 "requires OpenSSL >= 1.1.0"
1311 )
1312 def test_security_level(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001313 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
matthewhughes9348e836bb2020-07-17 09:59:15 +01001314 # The default security callback allows for levels between 0-5
1315 # with OpenSSL defaulting to 1, however some vendors override the
1316 # default value (e.g. Debian defaults to 2)
1317 security_level_range = {
1318 0,
1319 1, # OpenSSL default
1320 2, # Debian
1321 3,
1322 4,
1323 5,
1324 }
1325 self.assertIn(ctx.security_level, security_level_range)
1326
Christian Heimes22587792013-11-21 23:56:13 +01001327 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001328 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001329 # default value
1330 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1331 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001332 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1333 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1334 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1335 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1336 ctx.verify_flags = ssl.VERIFY_DEFAULT
1337 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001338 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1339 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001340 # supports any value
1341 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1342 self.assertEqual(ctx.verify_flags,
1343 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1344 with self.assertRaises(TypeError):
1345 ctx.verify_flags = None
1346
Antoine Pitrou152efa22010-05-16 18:19:27 +00001347 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001348 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001349 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001350 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001351 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1352 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001353 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001354 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001355 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001356 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001357 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001358 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001359 ctx.load_cert_chain(EMPTYCERT)
1360 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001361 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001362 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1363 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1364 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001365 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001366 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001367 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001368 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001369 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001370 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1371 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001372 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001373 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001374 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001375 # Password protected key and cert
1376 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1377 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1378 ctx.load_cert_chain(CERTFILE_PROTECTED,
1379 password=bytearray(KEY_PASSWORD.encode()))
1380 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1381 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1382 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1383 bytearray(KEY_PASSWORD.encode()))
1384 with self.assertRaisesRegex(TypeError, "should be a string"):
1385 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1386 with self.assertRaises(ssl.SSLError):
1387 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1388 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1389 # openssl has a fixed limit on the password buffer.
1390 # PEM_BUFSIZE is generally set to 1kb.
1391 # Return a string larger than this.
1392 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1393 # Password callback
1394 def getpass_unicode():
1395 return KEY_PASSWORD
1396 def getpass_bytes():
1397 return KEY_PASSWORD.encode()
1398 def getpass_bytearray():
1399 return bytearray(KEY_PASSWORD.encode())
1400 def getpass_badpass():
1401 return "badpass"
1402 def getpass_huge():
1403 return b'a' * (1024 * 1024)
1404 def getpass_bad_type():
1405 return 9
1406 def getpass_exception():
1407 raise Exception('getpass error')
1408 class GetPassCallable:
1409 def __call__(self):
1410 return KEY_PASSWORD
1411 def getpass(self):
1412 return KEY_PASSWORD
1413 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1414 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1415 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1416 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1417 ctx.load_cert_chain(CERTFILE_PROTECTED,
1418 password=GetPassCallable().getpass)
1419 with self.assertRaises(ssl.SSLError):
1420 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1421 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1422 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1423 with self.assertRaisesRegex(TypeError, "must return a string"):
1424 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1425 with self.assertRaisesRegex(Exception, "getpass error"):
1426 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1427 # Make sure the password function isn't called if it isn't needed
1428 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001429
1430 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001431 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001432 ctx.load_verify_locations(CERTFILE)
1433 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1434 ctx.load_verify_locations(BYTES_CERTFILE)
1435 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1436 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001437 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001438 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001439 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001440 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001441 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001442 ctx.load_verify_locations(BADCERT)
1443 ctx.load_verify_locations(CERTFILE, CAPATH)
1444 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1445
Victor Stinner80f75e62011-01-29 11:31:20 +00001446 # Issue #10989: crash if the second argument type is invalid
1447 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1448
Christian Heimesefff7062013-11-21 03:35:02 +01001449 def test_load_verify_cadata(self):
1450 # test cadata
1451 with open(CAFILE_CACERT) as f:
1452 cacert_pem = f.read()
1453 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1454 with open(CAFILE_NEURONIO) as f:
1455 neuronio_pem = f.read()
1456 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1457
1458 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001459 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001460 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1461 ctx.load_verify_locations(cadata=cacert_pem)
1462 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1463 ctx.load_verify_locations(cadata=neuronio_pem)
1464 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1465 # cert already in hash table
1466 ctx.load_verify_locations(cadata=neuronio_pem)
1467 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1468
1469 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001470 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001471 combined = "\n".join((cacert_pem, neuronio_pem))
1472 ctx.load_verify_locations(cadata=combined)
1473 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1474
1475 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001476 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001477 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1478 neuronio_pem, "tail"]
1479 ctx.load_verify_locations(cadata="\n".join(combined))
1480 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1481
1482 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001483 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001484 ctx.load_verify_locations(cadata=cacert_der)
1485 ctx.load_verify_locations(cadata=neuronio_der)
1486 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1487 # cert already in hash table
1488 ctx.load_verify_locations(cadata=cacert_der)
1489 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1490
1491 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001492 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001493 combined = b"".join((cacert_der, neuronio_der))
1494 ctx.load_verify_locations(cadata=combined)
1495 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1496
1497 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001498 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001499 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1500
Christian Heimesb9ad88b2021-04-23 13:51:40 +02001501 with self.assertRaisesRegex(
1502 ssl.SSLError,
1503 "no start line: cadata does not contain a certificate"
1504 ):
Christian Heimesefff7062013-11-21 03:35:02 +01001505 ctx.load_verify_locations(cadata="broken")
Christian Heimesb9ad88b2021-04-23 13:51:40 +02001506 with self.assertRaisesRegex(
1507 ssl.SSLError,
1508 "not enough data: cadata does not contain a certificate"
1509 ):
Christian Heimesefff7062013-11-21 03:35:02 +01001510 ctx.load_verify_locations(cadata=b"broken")
1511
Paul Monsonf3550692019-06-19 13:09:54 -07001512 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001513 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001514 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001515 ctx.load_dh_params(DHFILE)
1516 if os.name != 'nt':
1517 ctx.load_dh_params(BYTES_DHFILE)
1518 self.assertRaises(TypeError, ctx.load_dh_params)
1519 self.assertRaises(TypeError, ctx.load_dh_params, None)
1520 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001521 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001522 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001523 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001524 ctx.load_dh_params(CERTFILE)
1525
Antoine Pitroub0182c82010-10-12 20:09:02 +00001526 def test_session_stats(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001527 for proto in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
Antoine Pitroub0182c82010-10-12 20:09:02 +00001528 ctx = ssl.SSLContext(proto)
1529 self.assertEqual(ctx.session_stats(), {
1530 'number': 0,
1531 'connect': 0,
1532 'connect_good': 0,
1533 'connect_renegotiate': 0,
1534 'accept': 0,
1535 'accept_good': 0,
1536 'accept_renegotiate': 0,
1537 'hits': 0,
1538 'misses': 0,
1539 'timeouts': 0,
1540 'cache_full': 0,
1541 })
1542
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001543 def test_set_default_verify_paths(self):
1544 # There's not much we can do to test that it acts as expected,
1545 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001546 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001547 ctx.set_default_verify_paths()
1548
Antoine Pitrou501da612011-12-21 09:27:41 +01001549 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001550 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001551 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001552 ctx.set_ecdh_curve("prime256v1")
1553 ctx.set_ecdh_curve(b"prime256v1")
1554 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1555 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1556 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1557 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1558
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001559 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001560 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001561
1562 # set_servername_callback expects a callable, or None
1563 self.assertRaises(TypeError, ctx.set_servername_callback)
1564 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1565 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1566 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1567
1568 def dummycallback(sock, servername, ctx):
1569 pass
1570 ctx.set_servername_callback(None)
1571 ctx.set_servername_callback(dummycallback)
1572
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001573 def test_sni_callback_refcycle(self):
1574 # Reference cycles through the servername callback are detected
1575 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001576 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001577 def dummycallback(sock, servername, ctx, cycle=ctx):
1578 pass
1579 ctx.set_servername_callback(dummycallback)
1580 wr = weakref.ref(ctx)
1581 del ctx, dummycallback
1582 gc.collect()
1583 self.assertIs(wr(), None)
1584
Christian Heimes9a5395a2013-06-17 15:44:12 +02001585 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001586 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001587 self.assertEqual(ctx.cert_store_stats(),
1588 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1589 ctx.load_cert_chain(CERTFILE)
1590 self.assertEqual(ctx.cert_store_stats(),
1591 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1592 ctx.load_verify_locations(CERTFILE)
1593 self.assertEqual(ctx.cert_store_stats(),
1594 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001595 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001596 self.assertEqual(ctx.cert_store_stats(),
1597 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1598
1599 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001600 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001601 self.assertEqual(ctx.get_ca_certs(), [])
1602 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1603 ctx.load_verify_locations(CERTFILE)
1604 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001605 # but CAFILE_CACERT is a CA cert
1606 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001607 self.assertEqual(ctx.get_ca_certs(),
1608 [{'issuer': ((('organizationName', 'Root CA'),),
1609 (('organizationalUnitName', 'http://www.cacert.org'),),
1610 (('commonName', 'CA Cert Signing Authority'),),
1611 (('emailAddress', 'support@cacert.org'),)),
Christian Heimesd37b74f2021-04-19 08:31:29 +02001612 'notAfter': 'Mar 29 12:29:49 2033 GMT',
1613 'notBefore': 'Mar 30 12:29:49 2003 GMT',
Christian Heimes9a5395a2013-06-17 15:44:12 +02001614 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001615 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001616 'subject': ((('organizationName', 'Root CA'),),
1617 (('organizationalUnitName', 'http://www.cacert.org'),),
1618 (('commonName', 'CA Cert Signing Authority'),),
1619 (('emailAddress', 'support@cacert.org'),)),
1620 'version': 3}])
1621
Martin Panterb55f8b72016-01-14 12:53:56 +00001622 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001623 pem = f.read()
1624 der = ssl.PEM_cert_to_DER_cert(pem)
1625 self.assertEqual(ctx.get_ca_certs(True), [der])
1626
Christian Heimes72d28502013-11-23 13:56:58 +01001627 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001628 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001629 ctx.load_default_certs()
1630
Christian Heimesa170fa12017-09-15 20:27:30 +02001631 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001632 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1633 ctx.load_default_certs()
1634
Christian Heimesa170fa12017-09-15 20:27:30 +02001635 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001636 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1637
Christian Heimesa170fa12017-09-15 20:27:30 +02001638 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001639 self.assertRaises(TypeError, ctx.load_default_certs, None)
1640 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1641
Benjamin Peterson91244e02014-10-03 18:17:15 -04001642 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001643 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001644 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001645 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001646 env["SSL_CERT_DIR"] = CAPATH
1647 env["SSL_CERT_FILE"] = CERTFILE
1648 ctx.load_default_certs()
1649 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1650
Benjamin Peterson91244e02014-10-03 18:17:15 -04001651 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001652 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001653 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001654 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001655 ctx.load_default_certs()
1656 stats = ctx.cert_store_stats()
1657
Christian Heimesa170fa12017-09-15 20:27:30 +02001658 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001659 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001660 env["SSL_CERT_DIR"] = CAPATH
1661 env["SSL_CERT_FILE"] = CERTFILE
1662 ctx.load_default_certs()
1663 stats["x509"] += 1
1664 self.assertEqual(ctx.cert_store_stats(), stats)
1665
Christian Heimes358cfd42016-09-10 22:43:48 +02001666 def _assert_context_options(self, ctx):
1667 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1668 if OP_NO_COMPRESSION != 0:
1669 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1670 OP_NO_COMPRESSION)
1671 if OP_SINGLE_DH_USE != 0:
1672 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1673 OP_SINGLE_DH_USE)
1674 if OP_SINGLE_ECDH_USE != 0:
1675 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1676 OP_SINGLE_ECDH_USE)
1677 if OP_CIPHER_SERVER_PREFERENCE != 0:
1678 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1679 OP_CIPHER_SERVER_PREFERENCE)
1680
Christian Heimes4c05b472013-11-23 15:58:30 +01001681 def test_create_default_context(self):
1682 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001683
Christian Heimes2875c602021-04-19 07:27:10 +02001684 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001685 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001686 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001687 self._assert_context_options(ctx)
1688
Christian Heimes4c05b472013-11-23 15:58:30 +01001689 with open(SIGNING_CA) as f:
1690 cadata = f.read()
1691 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1692 cadata=cadata)
Christian Heimes2875c602021-04-19 07:27:10 +02001693 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001694 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001695 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001696
1697 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001698 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes4c05b472013-11-23 15:58:30 +01001699 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001700 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001701
Christian Heimes2875c602021-04-19 07:27:10 +02001702
1703
Christian Heimes67986f92013-11-23 22:43:47 +01001704 def test__create_stdlib_context(self):
1705 ctx = ssl._create_stdlib_context()
Christian Heimes2875c602021-04-19 07:27:10 +02001706 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes67986f92013-11-23 22:43:47 +01001707 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001708 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001709 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001710
Christian Heimes2875c602021-04-19 07:27:10 +02001711 with warnings_helper.check_warnings():
1712 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
Christian Heimes67986f92013-11-23 22:43:47 +01001713 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1714 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001715 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001716
Christian Heimes2875c602021-04-19 07:27:10 +02001717 with warnings_helper.check_warnings():
1718 ctx = ssl._create_stdlib_context(
1719 ssl.PROTOCOL_TLSv1_2,
1720 cert_reqs=ssl.CERT_REQUIRED,
1721 check_hostname=True
1722 )
1723 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
Christian Heimes67986f92013-11-23 22:43:47 +01001724 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001725 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001726 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001727
1728 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001729 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes67986f92013-11-23 22:43:47 +01001730 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001731 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001732
Christian Heimes1aa9a752013-12-02 02:41:19 +01001733 def test_check_hostname(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001734 with warnings_helper.check_warnings():
1735 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001736 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001737 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001738
Christian Heimese82c0342017-09-15 20:29:57 +02001739 # Auto set CERT_REQUIRED
1740 ctx.check_hostname = True
1741 self.assertTrue(ctx.check_hostname)
1742 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1743 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001744 ctx.verify_mode = ssl.CERT_REQUIRED
1745 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001746 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001747
Christian Heimese82c0342017-09-15 20:29:57 +02001748 # Changing verify_mode does not affect check_hostname
1749 ctx.check_hostname = False
1750 ctx.verify_mode = ssl.CERT_NONE
1751 ctx.check_hostname = False
1752 self.assertFalse(ctx.check_hostname)
1753 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1754 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001755 ctx.check_hostname = True
1756 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001757 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1758
1759 ctx.check_hostname = False
1760 ctx.verify_mode = ssl.CERT_OPTIONAL
1761 ctx.check_hostname = False
1762 self.assertFalse(ctx.check_hostname)
1763 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1764 # keep CERT_OPTIONAL
1765 ctx.check_hostname = True
1766 self.assertTrue(ctx.check_hostname)
1767 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001768
1769 # Cannot set CERT_NONE with check_hostname enabled
1770 with self.assertRaises(ValueError):
1771 ctx.verify_mode = ssl.CERT_NONE
1772 ctx.check_hostname = False
1773 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001774 ctx.verify_mode = ssl.CERT_NONE
1775 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001776
Christian Heimes5fe668c2016-09-12 00:01:11 +02001777 def test_context_client_server(self):
1778 # PROTOCOL_TLS_CLIENT has sane defaults
1779 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1780 self.assertTrue(ctx.check_hostname)
1781 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1782
1783 # PROTOCOL_TLS_SERVER has different but also sane defaults
1784 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1785 self.assertFalse(ctx.check_hostname)
1786 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1787
Christian Heimes4df60f12017-09-15 20:26:05 +02001788 def test_context_custom_class(self):
1789 class MySSLSocket(ssl.SSLSocket):
1790 pass
1791
1792 class MySSLObject(ssl.SSLObject):
1793 pass
1794
1795 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1796 ctx.sslsocket_class = MySSLSocket
1797 ctx.sslobject_class = MySSLObject
1798
1799 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1800 self.assertIsInstance(sock, MySSLSocket)
Miss Islington (bot)d7930fb2021-06-11 00:36:17 -07001801 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(), server_side=True)
Christian Heimes4df60f12017-09-15 20:26:05 +02001802 self.assertIsInstance(obj, MySSLObject)
1803
Christian Heimes78c7d522019-06-03 21:00:10 +02001804 def test_num_tickest(self):
1805 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1806 self.assertEqual(ctx.num_tickets, 2)
1807 ctx.num_tickets = 1
1808 self.assertEqual(ctx.num_tickets, 1)
1809 ctx.num_tickets = 0
1810 self.assertEqual(ctx.num_tickets, 0)
1811 with self.assertRaises(ValueError):
1812 ctx.num_tickets = -1
1813 with self.assertRaises(TypeError):
1814 ctx.num_tickets = None
1815
1816 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1817 self.assertEqual(ctx.num_tickets, 2)
1818 with self.assertRaises(ValueError):
1819 ctx.num_tickets = 1
1820
Antoine Pitrou152efa22010-05-16 18:19:27 +00001821
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001822class SSLErrorTests(unittest.TestCase):
1823
1824 def test_str(self):
1825 # The str() of a SSLError doesn't include the errno
1826 e = ssl.SSLError(1, "foo")
1827 self.assertEqual(str(e), "foo")
1828 self.assertEqual(e.errno, 1)
1829 # Same for a subclass
1830 e = ssl.SSLZeroReturnError(1, "foo")
1831 self.assertEqual(str(e), "foo")
1832 self.assertEqual(e.errno, 1)
1833
Paul Monsonf3550692019-06-19 13:09:54 -07001834 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001835 def test_lib_reason(self):
1836 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001837 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001838 with self.assertRaises(ssl.SSLError) as cm:
1839 ctx.load_dh_params(CERTFILE)
1840 self.assertEqual(cm.exception.library, 'PEM')
1841 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1842 s = str(cm.exception)
1843 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1844
1845 def test_subclass(self):
1846 # Check that the appropriate SSLError subclass is raised
1847 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001848 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1849 ctx.check_hostname = False
1850 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001851 with socket.create_server(("127.0.0.1", 0)) as s:
1852 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001853 c.setblocking(False)
1854 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001855 with self.assertRaises(ssl.SSLWantReadError) as cm:
1856 c.do_handshake()
1857 s = str(cm.exception)
1858 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1859 # For compatibility
1860 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1861
1862
Christian Heimes61d478c2018-01-27 15:51:38 +01001863 def test_bad_server_hostname(self):
1864 ctx = ssl.create_default_context()
1865 with self.assertRaises(ValueError):
1866 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1867 server_hostname="")
1868 with self.assertRaises(ValueError):
1869 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1870 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001871 with self.assertRaises(TypeError):
1872 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1873 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001874
1875
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001876class MemoryBIOTests(unittest.TestCase):
1877
1878 def test_read_write(self):
1879 bio = ssl.MemoryBIO()
1880 bio.write(b'foo')
1881 self.assertEqual(bio.read(), b'foo')
1882 self.assertEqual(bio.read(), b'')
1883 bio.write(b'foo')
1884 bio.write(b'bar')
1885 self.assertEqual(bio.read(), b'foobar')
1886 self.assertEqual(bio.read(), b'')
1887 bio.write(b'baz')
1888 self.assertEqual(bio.read(2), b'ba')
1889 self.assertEqual(bio.read(1), b'z')
1890 self.assertEqual(bio.read(1), b'')
1891
1892 def test_eof(self):
1893 bio = ssl.MemoryBIO()
1894 self.assertFalse(bio.eof)
1895 self.assertEqual(bio.read(), b'')
1896 self.assertFalse(bio.eof)
1897 bio.write(b'foo')
1898 self.assertFalse(bio.eof)
1899 bio.write_eof()
1900 self.assertFalse(bio.eof)
1901 self.assertEqual(bio.read(2), b'fo')
1902 self.assertFalse(bio.eof)
1903 self.assertEqual(bio.read(1), b'o')
1904 self.assertTrue(bio.eof)
1905 self.assertEqual(bio.read(), b'')
1906 self.assertTrue(bio.eof)
1907
1908 def test_pending(self):
1909 bio = ssl.MemoryBIO()
1910 self.assertEqual(bio.pending, 0)
1911 bio.write(b'foo')
1912 self.assertEqual(bio.pending, 3)
1913 for i in range(3):
1914 bio.read(1)
1915 self.assertEqual(bio.pending, 3-i-1)
1916 for i in range(3):
1917 bio.write(b'x')
1918 self.assertEqual(bio.pending, i+1)
1919 bio.read()
1920 self.assertEqual(bio.pending, 0)
1921
1922 def test_buffer_types(self):
1923 bio = ssl.MemoryBIO()
1924 bio.write(b'foo')
1925 self.assertEqual(bio.read(), b'foo')
1926 bio.write(bytearray(b'bar'))
1927 self.assertEqual(bio.read(), b'bar')
1928 bio.write(memoryview(b'baz'))
1929 self.assertEqual(bio.read(), b'baz')
1930
1931 def test_error_types(self):
1932 bio = ssl.MemoryBIO()
1933 self.assertRaises(TypeError, bio.write, 'foo')
1934 self.assertRaises(TypeError, bio.write, None)
1935 self.assertRaises(TypeError, bio.write, True)
1936 self.assertRaises(TypeError, bio.write, 1)
1937
1938
Christian Heimes9d50ab52018-02-27 10:17:30 +01001939class SSLObjectTests(unittest.TestCase):
1940 def test_private_init(self):
1941 bio = ssl.MemoryBIO()
1942 with self.assertRaisesRegex(TypeError, "public constructor"):
1943 ssl.SSLObject(bio, bio)
1944
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001945 def test_unwrap(self):
1946 client_ctx, server_ctx, hostname = testing_context()
1947 c_in = ssl.MemoryBIO()
1948 c_out = ssl.MemoryBIO()
1949 s_in = ssl.MemoryBIO()
1950 s_out = ssl.MemoryBIO()
1951 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1952 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1953
1954 # Loop on the handshake for a bit to get it settled
1955 for _ in range(5):
1956 try:
1957 client.do_handshake()
1958 except ssl.SSLWantReadError:
1959 pass
1960 if c_out.pending:
1961 s_in.write(c_out.read())
1962 try:
1963 server.do_handshake()
1964 except ssl.SSLWantReadError:
1965 pass
1966 if s_out.pending:
1967 c_in.write(s_out.read())
1968 # Now the handshakes should be complete (don't raise WantReadError)
1969 client.do_handshake()
1970 server.do_handshake()
1971
1972 # Now if we unwrap one side unilaterally, it should send close-notify
1973 # and raise WantReadError:
1974 with self.assertRaises(ssl.SSLWantReadError):
1975 client.unwrap()
1976
1977 # But server.unwrap() does not raise, because it reads the client's
1978 # close-notify:
1979 s_in.write(c_out.read())
1980 server.unwrap()
1981
1982 # And now that the client gets the server's close-notify, it doesn't
1983 # raise either.
1984 c_in.write(s_out.read())
1985 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001986
Martin Panter3840b2a2016-03-27 01:53:46 +00001987class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001988 """Tests that connect to a simple server running in the background"""
1989
1990 def setUp(self):
juhovh49fdf112021-04-18 21:11:48 +10001991 self.server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1992 self.server_context.load_cert_chain(SIGNED_CERTFILE)
1993 server = ThreadedEchoServer(context=self.server_context)
Martin Panter3840b2a2016-03-27 01:53:46 +00001994 self.server_addr = (HOST, server.port)
1995 server.__enter__()
1996 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001997
Antoine Pitrou480a1242010-04-28 21:37:09 +00001998 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001999 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002000 cert_reqs=ssl.CERT_NONE) as s:
2001 s.connect(self.server_addr)
2002 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02002003 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00002004
Martin Panter3840b2a2016-03-27 01:53:46 +00002005 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02002006 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002007 cert_reqs=ssl.CERT_REQUIRED,
2008 ca_certs=SIGNING_CA) as s:
2009 s.connect(self.server_addr)
2010 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02002011 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002012
Martin Panter3840b2a2016-03-27 01:53:46 +00002013 def test_connect_fail(self):
2014 # This should fail because we have no verification certs. Connection
2015 # failure crashes ThreadedEchoServer, so run this in an independent
2016 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02002017 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002018 cert_reqs=ssl.CERT_REQUIRED)
2019 self.addCleanup(s.close)
2020 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2021 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002022
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002023 def test_connect_ex(self):
2024 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02002025 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002026 cert_reqs=ssl.CERT_REQUIRED,
2027 ca_certs=SIGNING_CA)
2028 self.addCleanup(s.close)
2029 self.assertEqual(0, s.connect_ex(self.server_addr))
2030 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002031
2032 def test_non_blocking_connect_ex(self):
2033 # Issue #11326: non-blocking connect_ex() should allow handshake
2034 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02002035 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002036 cert_reqs=ssl.CERT_REQUIRED,
2037 ca_certs=SIGNING_CA,
2038 do_handshake_on_connect=False)
2039 self.addCleanup(s.close)
2040 s.setblocking(False)
2041 rc = s.connect_ex(self.server_addr)
2042 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2043 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2044 # Wait for connect to finish
2045 select.select([], [s], [], 5.0)
2046 # Non-blocking handshake
2047 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002048 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002049 s.do_handshake()
2050 break
2051 except ssl.SSLWantReadError:
2052 select.select([s], [], [], 5.0)
2053 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002054 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002055 # SSL established
2056 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002057
Antoine Pitrou152efa22010-05-16 18:19:27 +00002058 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002059 # Same as test_connect, but with a separately created context
Christian Heimes2875c602021-04-19 07:27:10 +02002060 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2061 ctx.check_hostname = False
2062 ctx.verify_mode = ssl.CERT_NONE
Martin Panter3840b2a2016-03-27 01:53:46 +00002063 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2064 s.connect(self.server_addr)
2065 self.assertEqual({}, s.getpeercert())
2066 # Same with a server hostname
2067 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2068 server_hostname="dummy") as s:
2069 s.connect(self.server_addr)
2070 ctx.verify_mode = ssl.CERT_REQUIRED
2071 # This should succeed because we specify the root cert
2072 ctx.load_verify_locations(SIGNING_CA)
2073 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2074 s.connect(self.server_addr)
2075 cert = s.getpeercert()
2076 self.assertTrue(cert)
2077
2078 def test_connect_with_context_fail(self):
2079 # This should fail because we have no verification certs. Connection
2080 # failure crashes ThreadedEchoServer, so run this in an independent
2081 # test method.
Christian Heimes2875c602021-04-19 07:27:10 +02002082 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2083 s = ctx.wrap_socket(
2084 socket.socket(socket.AF_INET),
2085 server_hostname=SIGNED_CERTFILE_HOSTNAME
2086 )
Martin Panter3840b2a2016-03-27 01:53:46 +00002087 self.addCleanup(s.close)
2088 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2089 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002090
2091 def test_connect_capath(self):
2092 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002093 # NOTE: the subject hashing algorithm has been changed between
2094 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2095 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002096 # filename) for this test to be portable across OpenSSL releases.
Christian Heimes2875c602021-04-19 07:27:10 +02002097 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002098 ctx.load_verify_locations(capath=CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002099 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2100 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002101 s.connect(self.server_addr)
2102 cert = s.getpeercert()
2103 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002104
Martin Panter3840b2a2016-03-27 01:53:46 +00002105 # Same with a bytes `capath` argument
Christian Heimes2875c602021-04-19 07:27:10 +02002106 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002107 ctx.load_verify_locations(capath=BYTES_CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002108 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2109 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002110 s.connect(self.server_addr)
2111 cert = s.getpeercert()
2112 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002113
Christian Heimesefff7062013-11-21 03:35:02 +01002114 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002115 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002116 pem = f.read()
2117 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002118 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002119 ctx.load_verify_locations(cadata=pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002120 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2121 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002122 s.connect(self.server_addr)
2123 cert = s.getpeercert()
2124 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002125
Martin Panter3840b2a2016-03-27 01:53:46 +00002126 # same with DER
Christian Heimes2875c602021-04-19 07:27:10 +02002127 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002128 ctx.load_verify_locations(cadata=der)
Christian Heimes2875c602021-04-19 07:27:10 +02002129 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2130 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002131 s.connect(self.server_addr)
2132 cert = s.getpeercert()
2133 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002134
Antoine Pitroue3220242010-04-24 11:13:53 +00002135 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2136 def test_makefile_close(self):
2137 # Issue #5238: creating a file-like object with makefile() shouldn't
2138 # delay closing the underlying "real socket" (here tested with its
2139 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002140 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002141 ss.connect(self.server_addr)
2142 fd = ss.fileno()
2143 f = ss.makefile()
2144 f.close()
2145 # The fd is still open
2146 os.read(fd, 0)
2147 # Closing the SSL socket should close the fd too
2148 ss.close()
2149 gc.collect()
2150 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002151 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002152 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002153
Antoine Pitrou480a1242010-04-28 21:37:09 +00002154 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002155 s = socket.socket(socket.AF_INET)
2156 s.connect(self.server_addr)
2157 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002158 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002159 cert_reqs=ssl.CERT_NONE,
2160 do_handshake_on_connect=False)
2161 self.addCleanup(s.close)
2162 count = 0
2163 while True:
2164 try:
2165 count += 1
2166 s.do_handshake()
2167 break
2168 except ssl.SSLWantReadError:
2169 select.select([s], [], [])
2170 except ssl.SSLWantWriteError:
2171 select.select([], [s], [])
2172 if support.verbose:
2173 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002174
Antoine Pitrou480a1242010-04-28 21:37:09 +00002175 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002176 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002177
juhovh49fdf112021-04-18 21:11:48 +10002178 def test_get_server_certificate_sni(self):
2179 host, port = self.server_addr
2180 server_names = []
2181
2182 # We store servername_cb arguments to make sure they match the host
2183 def servername_cb(ssl_sock, server_name, initial_context):
2184 server_names.append(server_name)
2185 self.server_context.set_servername_callback(servername_cb)
2186
2187 pem = ssl.get_server_certificate((host, port))
2188 if not pem:
2189 self.fail("No server certificate on %s:%s!" % (host, port))
2190
2191 pem = ssl.get_server_certificate((host, port), ca_certs=SIGNING_CA)
2192 if not pem:
2193 self.fail("No server certificate on %s:%s!" % (host, port))
2194 if support.verbose:
2195 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port, pem))
2196
2197 self.assertEqual(server_names, [host, host])
2198
Martin Panter3840b2a2016-03-27 01:53:46 +00002199 def test_get_server_certificate_fail(self):
2200 # Connection failure crashes ThreadedEchoServer, so run this in an
2201 # independent test method
2202 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002203
Zackery Spytzb2fac1a2021-04-23 22:46:01 -06002204 def test_get_server_certificate_timeout(self):
Christian Heimesf05c2ae2021-04-24 07:54:08 +02002205 def servername_cb(ssl_sock, server_name, initial_context):
2206 time.sleep(0.2)
2207 self.server_context.set_servername_callback(servername_cb)
2208
Zackery Spytzb2fac1a2021-04-23 22:46:01 -06002209 with self.assertRaises(socket.timeout):
2210 ssl.get_server_certificate(self.server_addr, ca_certs=SIGNING_CA,
Christian Heimesf05c2ae2021-04-24 07:54:08 +02002211 timeout=0.1)
Zackery Spytzb2fac1a2021-04-23 22:46:01 -06002212
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002213 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002214 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002215 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2216 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002217 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002218 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2219 s.connect(self.server_addr)
2220 # Error checking can happen at instantiation or when connecting
2221 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2222 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002223 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002224 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2225 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002226
Christian Heimes9a5395a2013-06-17 15:44:12 +02002227 def test_get_ca_certs_capath(self):
2228 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002229 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002230 ctx.load_verify_locations(capath=CAPATH)
2231 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002232 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2233 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002234 s.connect(self.server_addr)
2235 cert = s.getpeercert()
2236 self.assertTrue(cert)
2237 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002238
Christian Heimes8e7f3942013-12-05 07:41:08 +01002239 def test_context_setget(self):
2240 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002241 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2242 ctx1.load_verify_locations(capath=CAPATH)
2243 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2244 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002245 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002246 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002247 ss.connect(self.server_addr)
2248 self.assertIs(ss.context, ctx1)
2249 self.assertIs(ss._sslobj.context, ctx1)
2250 ss.context = ctx2
2251 self.assertIs(ss.context, ctx2)
2252 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002253
2254 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2255 # A simple IO loop. Call func(*args) depending on the error we get
2256 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002257 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002258 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002259 count = 0
2260 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002261 if time.monotonic() > deadline:
2262 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002263 errno = None
2264 count += 1
2265 try:
2266 ret = func(*args)
2267 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002268 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002269 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002270 raise
2271 errno = e.errno
2272 # Get any data from the outgoing BIO irrespective of any error, and
2273 # send it to the socket.
2274 buf = outgoing.read()
2275 sock.sendall(buf)
2276 # If there's no error, we're done. For WANT_READ, we need to get
2277 # data from the socket and put it in the incoming BIO.
2278 if errno is None:
2279 break
2280 elif errno == ssl.SSL_ERROR_WANT_READ:
2281 buf = sock.recv(32768)
2282 if buf:
2283 incoming.write(buf)
2284 else:
2285 incoming.write_eof()
2286 if support.verbose:
2287 sys.stdout.write("Needed %d calls to complete %s().\n"
2288 % (count, func.__name__))
2289 return ret
2290
Martin Panter3840b2a2016-03-27 01:53:46 +00002291 def test_bio_handshake(self):
2292 sock = socket.socket(socket.AF_INET)
2293 self.addCleanup(sock.close)
2294 sock.connect(self.server_addr)
2295 incoming = ssl.MemoryBIO()
2296 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002297 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2298 self.assertTrue(ctx.check_hostname)
2299 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002300 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002301 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2302 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002303 self.assertIs(sslobj._sslobj.owner, sslobj)
2304 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002305 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002306 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002307 self.assertRaises(ValueError, sslobj.getpeercert)
2308 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2309 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2310 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2311 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002312 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002313 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002314 self.assertTrue(sslobj.getpeercert())
2315 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2316 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2317 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002318 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002319 except ssl.SSLSyscallError:
2320 # If the server shuts down the TCP connection without sending a
2321 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2322 pass
2323 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2324
2325 def test_bio_read_write_data(self):
2326 sock = socket.socket(socket.AF_INET)
2327 self.addCleanup(sock.close)
2328 sock.connect(self.server_addr)
2329 incoming = ssl.MemoryBIO()
2330 outgoing = ssl.MemoryBIO()
Christian Heimes2875c602021-04-19 07:27:10 +02002331 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2332 ctx.check_hostname = False
Martin Panter3840b2a2016-03-27 01:53:46 +00002333 ctx.verify_mode = ssl.CERT_NONE
2334 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2335 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2336 req = b'FOO\n'
2337 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2338 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2339 self.assertEqual(buf, b'foo\n')
2340 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002341
2342
Martin Panter3840b2a2016-03-27 01:53:46 +00002343class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002344
Martin Panter3840b2a2016-03-27 01:53:46 +00002345 def test_timeout_connect_ex(self):
2346 # Issue #12065: on a timeout, connect_ex() should return the original
2347 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002348 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002349 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002350 cert_reqs=ssl.CERT_REQUIRED,
2351 do_handshake_on_connect=False)
2352 self.addCleanup(s.close)
2353 s.settimeout(0.0000001)
2354 rc = s.connect_ex((REMOTE_HOST, 443))
2355 if rc == 0:
2356 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002357 elif rc == errno.ENETUNREACH:
2358 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002359 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2360
Serhiy Storchaka16994912020-04-25 10:06:29 +03002361 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002362 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002363 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002364 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2365 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2366
Martin Panter3840b2a2016-03-27 01:53:46 +00002367
2368def _test_get_server_certificate(test, host, port, cert=None):
2369 pem = ssl.get_server_certificate((host, port))
2370 if not pem:
2371 test.fail("No server certificate on %s:%s!" % (host, port))
2372
2373 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2374 if not pem:
2375 test.fail("No server certificate on %s:%s!" % (host, port))
2376 if support.verbose:
2377 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2378
2379def _test_get_server_certificate_fail(test, host, port):
2380 try:
2381 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2382 except ssl.SSLError as x:
2383 #should fail
2384 if support.verbose:
2385 sys.stdout.write("%s\n" % x)
2386 else:
2387 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2388
2389
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002390from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002391
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002392class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002393
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002394 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002395
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002396 """A mildly complicated class, because we want it to work both
2397 with and without the SSL wrapper around the socket connection, so
2398 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002399
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002400 def __init__(self, server, connsock, addr):
2401 self.server = server
2402 self.running = False
2403 self.sock = connsock
2404 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002405 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002406 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002407 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002408 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002409
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002410 def wrap_conn(self):
2411 try:
2412 self.sslconn = self.server.context.wrap_socket(
2413 self.sock, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002414 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002415 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002416 # We treat ConnectionResetError as though it were an
2417 # SSLError - OpenSSL on Ubuntu abruptly closes the
2418 # connection when asked to use an unsupported protocol.
2419 #
Christian Heimes529525f2018-05-23 22:24:45 +02002420 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2421 # tries to send session tickets after handshake.
2422 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002423 #
2424 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2425 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002426 self.server.conn_errors.append(str(e))
2427 if self.server.chatty:
2428 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2429 self.running = False
2430 self.close()
2431 return False
2432 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002433 # OSError may occur with wrong protocols, e.g. both
2434 # sides use PROTOCOL_TLS_SERVER.
2435 #
2436 # XXX Various errors can have happened here, for example
2437 # a mismatching protocol version, an invalid certificate,
2438 # or a low-level bug. This should be made more discriminating.
2439 #
2440 # bpo-31323: Store the exception as string to prevent
2441 # a reference leak: server -> conn_errors -> exception
2442 # -> traceback -> self (ConnectionHandler) -> server
2443 self.server.conn_errors.append(str(e))
2444 if self.server.chatty:
2445 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Miss Islington (bot)b3fac2922021-06-24 05:27:35 -07002446
2447 # bpo-44229, bpo-43855, bpo-44237, and bpo-33450:
2448 # Ignore spurious EPROTOTYPE returned by write() on macOS.
2449 # See also http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/
2450 if e.errno != errno.EPROTOTYPE and sys.platform != "darwin":
2451 self.running = False
2452 self.server.stop()
2453 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002454 return False
2455 else:
2456 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2457 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2458 cert = self.sslconn.getpeercert()
2459 if support.verbose and self.server.chatty:
2460 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2461 cert_binary = self.sslconn.getpeercert(True)
2462 if support.verbose and self.server.chatty:
Christian Heimesc8666cf2021-04-24 09:17:54 +02002463 if cert_binary is None:
2464 sys.stdout.write(" client did not provide a cert\n")
2465 else:
2466 sys.stdout.write(f" cert binary is {len(cert_binary)}b\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002467 cipher = self.sslconn.cipher()
2468 if support.verbose and self.server.chatty:
2469 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002470 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002471
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002472 def read(self):
2473 if self.sslconn:
2474 return self.sslconn.read()
2475 else:
2476 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002477
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002478 def write(self, bytes):
2479 if self.sslconn:
2480 return self.sslconn.write(bytes)
2481 else:
2482 return self.sock.send(bytes)
2483
2484 def close(self):
2485 if self.sslconn:
2486 self.sslconn.close()
2487 else:
2488 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002489
Antoine Pitrou480a1242010-04-28 21:37:09 +00002490 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002491 self.running = True
2492 if not self.server.starttls_server:
2493 if not self.wrap_conn():
2494 return
2495 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002496 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002497 msg = self.read()
2498 stripped = msg.strip()
2499 if not stripped:
2500 # eof, so quit this handler
2501 self.running = False
2502 try:
2503 self.sock = self.sslconn.unwrap()
2504 except OSError:
2505 # Many tests shut the TCP connection down
2506 # without an SSL shutdown. This causes
2507 # unwrap() to raise OSError with errno=0!
2508 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002509 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002510 self.sslconn = None
2511 self.close()
2512 elif stripped == b'over':
2513 if support.verbose and self.server.connectionchatty:
2514 sys.stdout.write(" server: client closed connection\n")
2515 self.close()
2516 return
2517 elif (self.server.starttls_server and
2518 stripped == b'STARTTLS'):
2519 if support.verbose and self.server.connectionchatty:
2520 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2521 self.write(b"OK\n")
2522 if not self.wrap_conn():
2523 return
2524 elif (self.server.starttls_server and self.sslconn
2525 and stripped == b'ENDTLS'):
2526 if support.verbose and self.server.connectionchatty:
2527 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2528 self.write(b"OK\n")
2529 self.sock = self.sslconn.unwrap()
2530 self.sslconn = None
2531 if support.verbose and self.server.connectionchatty:
2532 sys.stdout.write(" server: connection is now unencrypted...\n")
2533 elif stripped == b'CB tls-unique':
2534 if support.verbose and self.server.connectionchatty:
2535 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2536 data = self.sslconn.get_channel_binding("tls-unique")
2537 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002538 elif stripped == b'PHA':
2539 if support.verbose and self.server.connectionchatty:
2540 sys.stdout.write(" server: initiating post handshake auth\n")
2541 try:
2542 self.sslconn.verify_client_post_handshake()
2543 except ssl.SSLError as e:
2544 self.write(repr(e).encode("us-ascii") + b"\n")
2545 else:
2546 self.write(b"OK\n")
2547 elif stripped == b'HASCERT':
2548 if self.sslconn.getpeercert() is not None:
2549 self.write(b'TRUE\n')
2550 else:
2551 self.write(b'FALSE\n')
2552 elif stripped == b'GETCERT':
2553 cert = self.sslconn.getpeercert()
2554 self.write(repr(cert).encode("us-ascii") + b"\n")
Christian Heimes666991f2021-04-26 15:01:40 +02002555 elif stripped == b'VERIFIEDCHAIN':
2556 certs = self.sslconn._sslobj.get_verified_chain()
2557 self.write(len(certs).to_bytes(1, "big") + b"\n")
2558 elif stripped == b'UNVERIFIEDCHAIN':
2559 certs = self.sslconn._sslobj.get_unverified_chain()
2560 self.write(len(certs).to_bytes(1, "big") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002561 else:
2562 if (support.verbose and
2563 self.server.connectionchatty):
2564 ctype = (self.sslconn and "encrypted") or "unencrypted"
2565 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2566 % (msg, ctype, msg.lower(), ctype))
2567 self.write(msg.lower())
Christian Heimesc8666cf2021-04-24 09:17:54 +02002568 except OSError as e:
2569 # handles SSLError and socket errors
Christian Heimes529525f2018-05-23 22:24:45 +02002570 if self.server.chatty and support.verbose:
Christian Heimesc8666cf2021-04-24 09:17:54 +02002571 if isinstance(e, ConnectionError):
2572 # OpenSSL 1.1.1 sometimes raises
2573 # ConnectionResetError when connection is not
2574 # shut down gracefully.
2575 print(
2576 f" Connection reset by peer: {self.addr}"
2577 )
2578 else:
2579 handle_error("Test server failure:\n")
2580 try:
2581 self.write(b"ERROR\n")
2582 except OSError:
2583 pass
Bill Janssen2f5799b2008-06-29 00:08:12 +00002584 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002585 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002586
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002587 # normally, we'd just stop here, but for the test
2588 # harness, we want to stop the server
2589 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002590
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002591 def __init__(self, certificate=None, ssl_version=None,
2592 certreqs=None, cacerts=None,
2593 chatty=True, connectionchatty=False, starttls_server=False,
Christian Heimes2875c602021-04-19 07:27:10 +02002594 alpn_protocols=None,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002595 ciphers=None, context=None):
2596 if context:
2597 self.context = context
2598 else:
2599 self.context = ssl.SSLContext(ssl_version
2600 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002601 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002602 self.context.verify_mode = (certreqs if certreqs is not None
2603 else ssl.CERT_NONE)
2604 if cacerts:
2605 self.context.load_verify_locations(cacerts)
2606 if certificate:
2607 self.context.load_cert_chain(certificate)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002608 if alpn_protocols:
2609 self.context.set_alpn_protocols(alpn_protocols)
2610 if ciphers:
2611 self.context.set_ciphers(ciphers)
2612 self.chatty = chatty
2613 self.connectionchatty = connectionchatty
2614 self.starttls_server = starttls_server
2615 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002616 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002617 self.flag = None
2618 self.active = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002619 self.selected_alpn_protocols = []
2620 self.shared_ciphers = []
2621 self.conn_errors = []
2622 threading.Thread.__init__(self)
2623 self.daemon = True
2624
2625 def __enter__(self):
2626 self.start(threading.Event())
2627 self.flag.wait()
2628 return self
2629
2630 def __exit__(self, *args):
2631 self.stop()
2632 self.join()
2633
2634 def start(self, flag=None):
2635 self.flag = flag
2636 threading.Thread.start(self)
2637
2638 def run(self):
Christian Heimesc715b522021-05-03 17:45:02 +02002639 self.sock.settimeout(1.0)
2640 self.sock.listen(5)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002641 self.active = True
2642 if self.flag:
2643 # signal an event
2644 self.flag.set()
2645 while self.active:
2646 try:
2647 newconn, connaddr = self.sock.accept()
2648 if support.verbose and self.chatty:
2649 sys.stdout.write(' server: new connection from '
2650 + repr(connaddr) + '\n')
2651 handler = self.ConnectionHandler(self, newconn, connaddr)
2652 handler.start()
2653 handler.join()
Christian Heimesc715b522021-05-03 17:45:02 +02002654 except TimeoutError as e:
2655 if support.verbose:
2656 sys.stdout.write(f' connection timeout {e!r}\n')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002657 except KeyboardInterrupt:
2658 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002659 except BaseException as e:
2660 if support.verbose and self.chatty:
2661 sys.stdout.write(
2662 ' connection handling failed: ' + repr(e) + '\n')
2663
Christian Heimesc715b522021-05-03 17:45:02 +02002664 self.close()
2665
2666 def close(self):
2667 if self.sock is not None:
2668 self.sock.close()
2669 self.sock = None
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002670
2671 def stop(self):
2672 self.active = False
2673
2674class AsyncoreEchoServer(threading.Thread):
2675
2676 # this one's based on asyncore.dispatcher
2677
2678 class EchoServer (asyncore.dispatcher):
2679
2680 class ConnectionHandler(asyncore.dispatcher_with_send):
2681
2682 def __init__(self, conn, certfile):
2683 self.socket = test_wrap_socket(conn, server_side=True,
2684 certfile=certfile,
2685 do_handshake_on_connect=False)
2686 asyncore.dispatcher_with_send.__init__(self, self.socket)
2687 self._ssl_accepting = True
2688 self._do_ssl_handshake()
2689
2690 def readable(self):
2691 if isinstance(self.socket, ssl.SSLSocket):
2692 while self.socket.pending() > 0:
2693 self.handle_read_event()
2694 return True
2695
2696 def _do_ssl_handshake(self):
2697 try:
2698 self.socket.do_handshake()
2699 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2700 return
2701 except ssl.SSLEOFError:
2702 return self.handle_close()
2703 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002704 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002705 except OSError as err:
2706 if err.args[0] == errno.ECONNABORTED:
2707 return self.handle_close()
2708 else:
2709 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002710
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002711 def handle_read(self):
2712 if self._ssl_accepting:
2713 self._do_ssl_handshake()
2714 else:
2715 data = self.recv(1024)
2716 if support.verbose:
2717 sys.stdout.write(" server: read %s from client\n" % repr(data))
2718 if not data:
2719 self.close()
2720 else:
2721 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002722
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002723 def handle_close(self):
2724 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002725 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002726 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002727
2728 def handle_error(self):
2729 raise
2730
Trent Nelson78520002008-04-10 20:54:35 +00002731 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002732 self.certfile = certfile
2733 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002734 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002735 asyncore.dispatcher.__init__(self, sock)
2736 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002737
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002738 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002739 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002740 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2741 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002742
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002743 def handle_error(self):
2744 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002745
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002746 def __init__(self, certfile):
2747 self.flag = None
2748 self.active = False
2749 self.server = self.EchoServer(certfile)
2750 self.port = self.server.port
2751 threading.Thread.__init__(self)
2752 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002753
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002754 def __str__(self):
2755 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002756
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002757 def __enter__(self):
2758 self.start(threading.Event())
2759 self.flag.wait()
2760 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002761
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002762 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002763 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002764 sys.stdout.write(" cleanup: stopping server.\n")
2765 self.stop()
2766 if support.verbose:
2767 sys.stdout.write(" cleanup: joining server thread.\n")
2768 self.join()
2769 if support.verbose:
2770 sys.stdout.write(" cleanup: successfully joined.\n")
2771 # make sure that ConnectionHandler is removed from socket_map
2772 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002773
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002774 def start (self, flag=None):
2775 self.flag = flag
2776 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002777
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002778 def run(self):
2779 self.active = True
2780 if self.flag:
2781 self.flag.set()
2782 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002783 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002784 asyncore.loop(1)
2785 except:
2786 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002787
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002788 def stop(self):
2789 self.active = False
2790 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002791
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002792def server_params_test(client_context, server_context, indata=b"FOO\n",
2793 chatty=True, connectionchatty=False, sni_name=None,
2794 session=None):
2795 """
2796 Launch a server, connect a client to it and try various reads
2797 and writes.
2798 """
2799 stats = {}
2800 server = ThreadedEchoServer(context=server_context,
2801 chatty=chatty,
2802 connectionchatty=False)
2803 with server:
2804 with client_context.wrap_socket(socket.socket(),
2805 server_hostname=sni_name, session=session) as s:
2806 s.connect((HOST, server.port))
2807 for arg in [indata, bytearray(indata), memoryview(indata)]:
2808 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002809 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002810 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002811 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002812 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002813 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002814 if connectionchatty:
2815 if support.verbose:
2816 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002817 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002818 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002819 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2820 % (outdata[:20], len(outdata),
2821 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002822 s.write(b"over\n")
2823 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002824 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002825 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002826 stats.update({
2827 'compression': s.compression(),
2828 'cipher': s.cipher(),
2829 'peercert': s.getpeercert(),
2830 'client_alpn_protocol': s.selected_alpn_protocol(),
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002831 'version': s.version(),
2832 'session_reused': s.session_reused,
2833 'session': s.session,
2834 })
2835 s.close()
2836 stats['server_alpn_protocols'] = server.selected_alpn_protocols
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002837 stats['server_shared_ciphers'] = server.shared_ciphers
2838 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002839
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002840def try_protocol_combo(server_protocol, client_protocol, expect_success,
2841 certsreqs=None, server_options=0, client_options=0):
2842 """
2843 Try to SSL-connect using *client_protocol* to *server_protocol*.
2844 If *expect_success* is true, assert that the connection succeeds,
2845 if it's false, assert that the connection fails.
2846 Also, if *expect_success* is a string, assert that it is the protocol
2847 version actually used by the connection.
2848 """
2849 if certsreqs is None:
2850 certsreqs = ssl.CERT_NONE
2851 certtype = {
2852 ssl.CERT_NONE: "CERT_NONE",
2853 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2854 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2855 }[certsreqs]
2856 if support.verbose:
2857 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2858 sys.stdout.write(formatstr %
2859 (ssl.get_protocol_name(client_protocol),
2860 ssl.get_protocol_name(server_protocol),
2861 certtype))
Christian Heimes2875c602021-04-19 07:27:10 +02002862
2863 with warnings_helper.check_warnings():
2864 # ignore Deprecation warnings
2865 client_context = ssl.SSLContext(client_protocol)
2866 client_context.options |= client_options
2867 server_context = ssl.SSLContext(server_protocol)
2868 server_context.options |= server_options
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002869
Victor Stinner3ef63442019-02-19 18:06:03 +01002870 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2871 if (min_version is not None
Christian Heimes2875c602021-04-19 07:27:10 +02002872 # SSLContext.minimum_version is only available on recent OpenSSL
2873 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2874 and hasattr(server_context, 'minimum_version')
2875 and server_protocol == ssl.PROTOCOL_TLS
2876 and server_context.minimum_version > min_version
2877 ):
Victor Stinner3ef63442019-02-19 18:06:03 +01002878 # If OpenSSL configuration is strict and requires more recent TLS
2879 # version, we have to change the minimum to test old TLS versions.
Christian Heimes2875c602021-04-19 07:27:10 +02002880 with warnings_helper.check_warnings():
2881 server_context.minimum_version = min_version
Victor Stinner3ef63442019-02-19 18:06:03 +01002882
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002883 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2884 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2885 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002886 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002887 client_context.set_ciphers("ALL")
2888
Christian Heimesf6c6b582021-03-18 23:06:50 +01002889 seclevel_workaround(server_context, client_context)
2890
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002891 for ctx in (client_context, server_context):
2892 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002893 ctx.load_cert_chain(SIGNED_CERTFILE)
2894 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002895 try:
2896 stats = server_params_test(client_context, server_context,
2897 chatty=False, connectionchatty=False)
2898 # Protocol mismatch can result in either an SSLError, or a
2899 # "Connection reset by peer" error.
2900 except ssl.SSLError:
2901 if expect_success:
2902 raise
2903 except OSError as e:
2904 if expect_success or e.errno != errno.ECONNRESET:
2905 raise
2906 else:
2907 if not expect_success:
2908 raise AssertionError(
2909 "Client protocol %s succeeded with server protocol %s!"
2910 % (ssl.get_protocol_name(client_protocol),
2911 ssl.get_protocol_name(server_protocol)))
2912 elif (expect_success is not True
2913 and expect_success != stats['version']):
2914 raise AssertionError("version mismatch: expected %r, got %r"
2915 % (expect_success, stats['version']))
2916
2917
2918class ThreadedTests(unittest.TestCase):
2919
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002920 def test_echo(self):
2921 """Basic test of an SSL client connecting to a server"""
2922 if support.verbose:
2923 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002924
Christian Heimesa170fa12017-09-15 20:27:30 +02002925 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002926
2927 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2928 server_params_test(client_context=client_context,
2929 server_context=server_context,
2930 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002931 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002932
2933 client_context.check_hostname = False
2934 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2935 with self.assertRaises(ssl.SSLError) as e:
2936 server_params_test(client_context=server_context,
2937 server_context=client_context,
2938 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002939 sni_name=hostname)
Miss Islington (bot)d7930fb2021-06-11 00:36:17 -07002940 self.assertIn(
2941 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
2942 str(e.exception)
2943 )
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002944
2945 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2946 with self.assertRaises(ssl.SSLError) as e:
2947 server_params_test(client_context=server_context,
2948 server_context=server_context,
2949 chatty=True, connectionchatty=True)
Miss Islington (bot)d7930fb2021-06-11 00:36:17 -07002950 self.assertIn(
2951 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
2952 str(e.exception)
2953 )
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002954
2955 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2956 with self.assertRaises(ssl.SSLError) as e:
2957 server_params_test(client_context=server_context,
2958 server_context=client_context,
2959 chatty=True, connectionchatty=True)
Miss Islington (bot)d7930fb2021-06-11 00:36:17 -07002960 self.assertIn(
2961 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
2962 str(e.exception))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002963
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002964 def test_getpeercert(self):
2965 if support.verbose:
2966 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002967
2968 client_context, server_context, hostname = testing_context()
2969 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002970 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002971 with client_context.wrap_socket(socket.socket(),
2972 do_handshake_on_connect=False,
2973 server_hostname=hostname) as s:
2974 s.connect((HOST, server.port))
2975 # getpeercert() raise ValueError while the handshake isn't
2976 # done.
2977 with self.assertRaises(ValueError):
2978 s.getpeercert()
2979 s.do_handshake()
2980 cert = s.getpeercert()
2981 self.assertTrue(cert, "Can't get peer certificate.")
2982 cipher = s.cipher()
2983 if support.verbose:
2984 sys.stdout.write(pprint.pformat(cert) + '\n')
2985 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2986 if 'subject' not in cert:
2987 self.fail("No subject field in certificate: %s." %
2988 pprint.pformat(cert))
2989 if ((('organizationName', 'Python Software Foundation'),)
2990 not in cert['subject']):
2991 self.fail(
2992 "Missing or invalid 'organizationName' field in certificate subject; "
2993 "should be 'Python Software Foundation'.")
2994 self.assertIn('notBefore', cert)
2995 self.assertIn('notAfter', cert)
2996 before = ssl.cert_time_to_seconds(cert['notBefore'])
2997 after = ssl.cert_time_to_seconds(cert['notAfter'])
2998 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002999
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003000 def test_crl_check(self):
3001 if support.verbose:
3002 sys.stdout.write("\n")
3003
Christian Heimesa170fa12017-09-15 20:27:30 +02003004 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003005
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003006 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02003007 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003008
3009 # VERIFY_DEFAULT should pass
3010 server = ThreadedEchoServer(context=server_context, chatty=True)
3011 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003012 with client_context.wrap_socket(socket.socket(),
3013 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01003014 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003015 cert = s.getpeercert()
3016 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00003017
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003018 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02003019 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00003020
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003021 server = ThreadedEchoServer(context=server_context, chatty=True)
3022 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003023 with client_context.wrap_socket(socket.socket(),
3024 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003025 with self.assertRaisesRegex(ssl.SSLError,
3026 "certificate verify failed"):
3027 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00003028
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003029 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02003030 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00003031
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003032 server = ThreadedEchoServer(context=server_context, chatty=True)
3033 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003034 with client_context.wrap_socket(socket.socket(),
3035 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02003036 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003037 cert = s.getpeercert()
3038 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02003039
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003040 def test_check_hostname(self):
3041 if support.verbose:
3042 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02003043
Christian Heimesa170fa12017-09-15 20:27:30 +02003044 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003045
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003046 # correct hostname should verify
3047 server = ThreadedEchoServer(context=server_context, chatty=True)
3048 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003049 with client_context.wrap_socket(socket.socket(),
3050 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003051 s.connect((HOST, server.port))
3052 cert = s.getpeercert()
3053 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003054
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003055 # incorrect hostname should raise an exception
3056 server = ThreadedEchoServer(context=server_context, chatty=True)
3057 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003058 with client_context.wrap_socket(socket.socket(),
3059 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01003060 with self.assertRaisesRegex(
3061 ssl.CertificateError,
3062 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003063 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003064
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003065 # missing server_hostname arg should cause an exception, too
3066 server = ThreadedEchoServer(context=server_context, chatty=True)
3067 with server:
3068 with socket.socket() as s:
3069 with self.assertRaisesRegex(ValueError,
3070 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02003071 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003072
Christian Heimesb467d9a2021-04-17 10:07:19 +02003073 @unittest.skipUnless(
3074 ssl.HAS_NEVER_CHECK_COMMON_NAME, "test requires hostname_checks_common_name"
3075 )
3076 def test_hostname_checks_common_name(self):
3077 client_context, server_context, hostname = testing_context()
3078 assert client_context.hostname_checks_common_name
3079 client_context.hostname_checks_common_name = False
3080
3081 # default cert has a SAN
3082 server = ThreadedEchoServer(context=server_context, chatty=True)
3083 with server:
3084 with client_context.wrap_socket(socket.socket(),
3085 server_hostname=hostname) as s:
3086 s.connect((HOST, server.port))
3087
3088 client_context, server_context, hostname = testing_context(NOSANFILE)
3089 client_context.hostname_checks_common_name = False
3090 server = ThreadedEchoServer(context=server_context, chatty=True)
3091 with server:
3092 with client_context.wrap_socket(socket.socket(),
3093 server_hostname=hostname) as s:
3094 with self.assertRaises(ssl.SSLCertVerificationError):
3095 s.connect((HOST, server.port))
3096
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003097 def test_ecc_cert(self):
3098 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3099 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003100 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003101 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3102
3103 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3104 # load ECC cert
3105 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3106
3107 # correct hostname should verify
3108 server = ThreadedEchoServer(context=server_context, chatty=True)
3109 with server:
3110 with client_context.wrap_socket(socket.socket(),
3111 server_hostname=hostname) as s:
3112 s.connect((HOST, server.port))
3113 cert = s.getpeercert()
3114 self.assertTrue(cert, "Can't get peer certificate.")
3115 cipher = s.cipher()[0].split('-')
3116 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3117
3118 def test_dual_rsa_ecc(self):
3119 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3120 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003121 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3122 # algorithms.
Miss Islington (bot)4becc562021-06-13 05:07:00 -07003123 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003124 # only ECDSA certs
3125 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3126 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3127
3128 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3129 # load ECC and RSA key/cert pairs
3130 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3131 server_context.load_cert_chain(SIGNED_CERTFILE)
3132
3133 # correct hostname should verify
3134 server = ThreadedEchoServer(context=server_context, chatty=True)
3135 with server:
3136 with client_context.wrap_socket(socket.socket(),
3137 server_hostname=hostname) as s:
3138 s.connect((HOST, server.port))
3139 cert = s.getpeercert()
3140 self.assertTrue(cert, "Can't get peer certificate.")
3141 cipher = s.cipher()[0].split('-')
3142 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3143
Christian Heimes66e57422018-01-29 14:25:13 +01003144 def test_check_hostname_idn(self):
3145 if support.verbose:
3146 sys.stdout.write("\n")
3147
Christian Heimes11a14932018-02-24 02:35:08 +01003148 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003149 server_context.load_cert_chain(IDNSANSFILE)
3150
Christian Heimes11a14932018-02-24 02:35:08 +01003151 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003152 context.verify_mode = ssl.CERT_REQUIRED
3153 context.check_hostname = True
3154 context.load_verify_locations(SIGNING_CA)
3155
3156 # correct hostname should verify, when specified in several
3157 # different ways
3158 idn_hostnames = [
3159 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003160 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003161 ('xn--knig-5qa.idn.pythontest.net',
3162 'xn--knig-5qa.idn.pythontest.net'),
3163 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003164 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003165
3166 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003167 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003168 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3169 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3170 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003171 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3172
3173 # ('königsgäßchen.idna2008.pythontest.net',
3174 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3175 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3176 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3177 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3178 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3179
Christian Heimes66e57422018-01-29 14:25:13 +01003180 ]
3181 for server_hostname, expected_hostname in idn_hostnames:
3182 server = ThreadedEchoServer(context=server_context, chatty=True)
3183 with server:
3184 with context.wrap_socket(socket.socket(),
3185 server_hostname=server_hostname) as s:
3186 self.assertEqual(s.server_hostname, expected_hostname)
3187 s.connect((HOST, server.port))
3188 cert = s.getpeercert()
3189 self.assertEqual(s.server_hostname, expected_hostname)
3190 self.assertTrue(cert, "Can't get peer certificate.")
3191
Christian Heimes66e57422018-01-29 14:25:13 +01003192 # incorrect hostname should raise an exception
3193 server = ThreadedEchoServer(context=server_context, chatty=True)
3194 with server:
3195 with context.wrap_socket(socket.socket(),
3196 server_hostname="python.example.org") as s:
3197 with self.assertRaises(ssl.CertificateError):
3198 s.connect((HOST, server.port))
3199
Christian Heimes529525f2018-05-23 22:24:45 +02003200 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003201 """Connecting when the server rejects the client's certificate
3202
3203 Launch a server with CERT_REQUIRED, and check that trying to
3204 connect to it with a wrong client certificate fails.
3205 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003206 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003207 # load client cert that is not signed by trusted CA
3208 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003209 # require TLS client authentication
3210 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003211 # TLS 1.3 has different handshake
3212 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003213
3214 server = ThreadedEchoServer(
3215 context=server_context, chatty=True, connectionchatty=True,
3216 )
3217
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003218 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003219 client_context.wrap_socket(socket.socket(),
3220 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003221 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003222 # Expect either an SSL error about the server rejecting
3223 # the connection, or a low-level connection reset (which
3224 # sometimes happens on Windows)
3225 s.connect((HOST, server.port))
3226 except ssl.SSLError as e:
3227 if support.verbose:
3228 sys.stdout.write("\nSSLError is %r\n" % e)
3229 except OSError as e:
3230 if e.errno != errno.ECONNRESET:
3231 raise
3232 if support.verbose:
3233 sys.stdout.write("\nsocket.error is %r\n" % e)
3234 else:
3235 self.fail("Use of invalid cert should have failed!")
3236
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003237 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003238 def test_wrong_cert_tls13(self):
3239 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003240 # load client cert that is not signed by trusted CA
3241 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003242 server_context.verify_mode = ssl.CERT_REQUIRED
3243 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3244 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3245
3246 server = ThreadedEchoServer(
3247 context=server_context, chatty=True, connectionchatty=True,
3248 )
3249 with server, \
3250 client_context.wrap_socket(socket.socket(),
Miss Islington (bot)d2ab15f2021-06-03 13:15:15 -07003251 server_hostname=hostname,
3252 suppress_ragged_eofs=False) as s:
Christian Heimes529525f2018-05-23 22:24:45 +02003253 # TLS 1.3 perform client cert exchange after handshake
3254 s.connect((HOST, server.port))
3255 try:
3256 s.write(b'data')
Christian Heimese0472392021-04-23 20:03:25 +02003257 s.read(1000)
3258 s.write(b'should have failed already')
3259 s.read(1000)
Christian Heimes529525f2018-05-23 22:24:45 +02003260 except ssl.SSLError as e:
3261 if support.verbose:
3262 sys.stdout.write("\nSSLError is %r\n" % e)
3263 except OSError as e:
3264 if e.errno != errno.ECONNRESET:
3265 raise
3266 if support.verbose:
3267 sys.stdout.write("\nsocket.error is %r\n" % e)
3268 else:
Miss Islington (bot)d2ab15f2021-06-03 13:15:15 -07003269 self.fail("Use of invalid cert should have failed!")
Christian Heimes529525f2018-05-23 22:24:45 +02003270
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003271 def test_rude_shutdown(self):
3272 """A brutal shutdown of an SSL server should raise an OSError
3273 in the client when attempting handshake.
3274 """
3275 listener_ready = threading.Event()
3276 listener_gone = threading.Event()
3277
3278 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003279 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003280
3281 # `listener` runs in a thread. It sits in an accept() until
3282 # the main thread connects. Then it rudely closes the socket,
3283 # and sets Event `listener_gone` to let the main thread know
3284 # the socket is gone.
3285 def listener():
3286 s.listen()
3287 listener_ready.set()
3288 newsock, addr = s.accept()
3289 newsock.close()
3290 s.close()
3291 listener_gone.set()
3292
3293 def connector():
3294 listener_ready.wait()
3295 with socket.socket() as c:
3296 c.connect((HOST, port))
3297 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003298 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003299 ssl_sock = test_wrap_socket(c)
3300 except OSError:
3301 pass
3302 else:
3303 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003304
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003305 t = threading.Thread(target=listener)
3306 t.start()
3307 try:
3308 connector()
3309 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003310 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003311
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003312 def test_ssl_cert_verify_error(self):
3313 if support.verbose:
3314 sys.stdout.write("\n")
3315
3316 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3317 server_context.load_cert_chain(SIGNED_CERTFILE)
3318
3319 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3320
3321 server = ThreadedEchoServer(context=server_context, chatty=True)
3322 with server:
3323 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003324 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003325 try:
3326 s.connect((HOST, server.port))
3327 except ssl.SSLError as e:
3328 msg = 'unable to get local issuer certificate'
3329 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3330 self.assertEqual(e.verify_code, 20)
3331 self.assertEqual(e.verify_message, msg)
3332 self.assertIn(msg, repr(e))
3333 self.assertIn('certificate verify failed', repr(e))
3334
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003335 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003336 def test_protocol_sslv2(self):
3337 """Connecting to an SSLv2 server with various client options"""
3338 if support.verbose:
3339 sys.stdout.write("\n")
3340 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3341 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3342 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003343 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003344 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003345 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3346 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3347 # SSLv23 client with specific SSL options
Christian Heimesa170fa12017-09-15 20:27:30 +02003348 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003349 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003350 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003351 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003352
Christian Heimesa170fa12017-09-15 20:27:30 +02003353 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003354 """Connecting to an SSLv23 server with various client options"""
3355 if support.verbose:
3356 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003357 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003358 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003359 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003360 except OSError as x:
3361 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3362 if support.verbose:
3363 sys.stdout.write(
3364 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3365 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003366 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003367 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3368 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003369 if has_tls_version('TLSv1'):
3370 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003371
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003372 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003373 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3374 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003375 if has_tls_version('TLSv1'):
3376 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003377
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003378 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003379 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3380 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003381 if has_tls_version('TLSv1'):
3382 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003383
3384 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003385 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003386 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003387 server_options=ssl.OP_NO_SSLv3)
3388 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003389 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003390 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003391 if has_tls_version('TLSv1'):
3392 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3393 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003394
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003395 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003396 def test_protocol_sslv3(self):
3397 """Connecting to an SSLv3 server with various client options"""
3398 if support.verbose:
3399 sys.stdout.write("\n")
3400 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3401 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3402 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003403 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003404 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003405 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003406 client_options=ssl.OP_NO_SSLv3)
3407 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003408
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003409 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003410 def test_protocol_tlsv1(self):
3411 """Connecting to a TLSv1 server with various client options"""
3412 if support.verbose:
3413 sys.stdout.write("\n")
3414 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3415 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3416 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003417 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003418 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003419 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003420 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003421 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003422 client_options=ssl.OP_NO_TLSv1)
3423
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003424 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003425 def test_protocol_tlsv1_1(self):
3426 """Connecting to a TLSv1.1 server with various client options.
3427 Testing against older TLS versions."""
3428 if support.verbose:
3429 sys.stdout.write("\n")
3430 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003431 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003432 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003433 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003434 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003435 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003436 client_options=ssl.OP_NO_TLSv1_1)
3437
Christian Heimesa170fa12017-09-15 20:27:30 +02003438 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003439 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3440 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003441
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003442 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003443 def test_protocol_tlsv1_2(self):
3444 """Connecting to a TLSv1.2 server with various client options.
3445 Testing against older TLS versions."""
3446 if support.verbose:
3447 sys.stdout.write("\n")
3448 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3449 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3450 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003451 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003452 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003453 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003454 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003455 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003456 client_options=ssl.OP_NO_TLSv1_2)
3457
Christian Heimesa170fa12017-09-15 20:27:30 +02003458 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003459 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3460 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3461 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3462 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3463
3464 def test_starttls(self):
3465 """Switching from clear text to encrypted and back again."""
3466 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3467
3468 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003469 starttls_server=True,
3470 chatty=True,
3471 connectionchatty=True)
3472 wrapped = False
3473 with server:
3474 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003475 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003476 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003477 if support.verbose:
3478 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003479 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003480 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003481 sys.stdout.write(
3482 " client: sending %r...\n" % indata)
3483 if wrapped:
3484 conn.write(indata)
3485 outdata = conn.read()
3486 else:
3487 s.send(indata)
3488 outdata = s.recv(1024)
3489 msg = outdata.strip().lower()
3490 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3491 # STARTTLS ok, switch to secure mode
3492 if support.verbose:
3493 sys.stdout.write(
3494 " client: read %r from server, starting TLS...\n"
3495 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003496 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003497 wrapped = True
3498 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3499 # ENDTLS ok, switch back to clear text
3500 if support.verbose:
3501 sys.stdout.write(
3502 " client: read %r from server, ending TLS...\n"
3503 % msg)
3504 s = conn.unwrap()
3505 wrapped = False
3506 else:
3507 if support.verbose:
3508 sys.stdout.write(
3509 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003510 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003511 sys.stdout.write(" client: closing connection.\n")
3512 if wrapped:
3513 conn.write(b"over\n")
3514 else:
3515 s.send(b"over\n")
3516 if wrapped:
3517 conn.close()
3518 else:
3519 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003520
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003521 def test_socketserver(self):
3522 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003523 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003524 # try to connect
3525 if support.verbose:
3526 sys.stdout.write('\n')
3527 with open(CERTFILE, 'rb') as f:
3528 d1 = f.read()
3529 d2 = ''
3530 # now fetch the same data from the HTTPS server
3531 url = 'https://localhost:%d/%s' % (
3532 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003533 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003534 f = urllib.request.urlopen(url, context=context)
3535 try:
3536 dlen = f.info().get("content-length")
3537 if dlen and (int(dlen) > 0):
3538 d2 = f.read(int(dlen))
3539 if support.verbose:
3540 sys.stdout.write(
3541 " client: read %d bytes from remote server '%s'\n"
3542 % (len(d2), server))
3543 finally:
3544 f.close()
3545 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003546
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003547 def test_asyncore_server(self):
3548 """Check the example asyncore integration."""
3549 if support.verbose:
3550 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003551
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003552 indata = b"FOO\n"
3553 server = AsyncoreEchoServer(CERTFILE)
3554 with server:
3555 s = test_wrap_socket(socket.socket())
3556 s.connect(('127.0.0.1', server.port))
3557 if support.verbose:
3558 sys.stdout.write(
3559 " client: sending %r...\n" % indata)
3560 s.write(indata)
3561 outdata = s.read()
3562 if support.verbose:
3563 sys.stdout.write(" client: read %r\n" % outdata)
3564 if outdata != indata.lower():
3565 self.fail(
3566 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3567 % (outdata[:20], len(outdata),
3568 indata[:20].lower(), len(indata)))
3569 s.write(b"over\n")
3570 if support.verbose:
3571 sys.stdout.write(" client: closing connection.\n")
3572 s.close()
3573 if support.verbose:
3574 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003575
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003576 def test_recv_send(self):
3577 """Test recv(), send() and friends."""
3578 if support.verbose:
3579 sys.stdout.write("\n")
3580
3581 server = ThreadedEchoServer(CERTFILE,
3582 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003583 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003584 cacerts=CERTFILE,
3585 chatty=True,
3586 connectionchatty=False)
3587 with server:
3588 s = test_wrap_socket(socket.socket(),
3589 server_side=False,
3590 certfile=CERTFILE,
3591 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003592 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003593 s.connect((HOST, server.port))
3594 # helper methods for standardising recv* method signatures
3595 def _recv_into():
3596 b = bytearray(b"\0"*100)
3597 count = s.recv_into(b)
3598 return b[:count]
3599
3600 def _recvfrom_into():
3601 b = bytearray(b"\0"*100)
3602 count, addr = s.recvfrom_into(b)
3603 return b[:count]
3604
3605 # (name, method, expect success?, *args, return value func)
3606 send_methods = [
3607 ('send', s.send, True, [], len),
3608 ('sendto', s.sendto, False, ["some.address"], len),
3609 ('sendall', s.sendall, True, [], lambda x: None),
3610 ]
3611 # (name, method, whether to expect success, *args)
3612 recv_methods = [
3613 ('recv', s.recv, True, []),
3614 ('recvfrom', s.recvfrom, False, ["some.address"]),
3615 ('recv_into', _recv_into, True, []),
3616 ('recvfrom_into', _recvfrom_into, False, []),
3617 ]
3618 data_prefix = "PREFIX_"
3619
3620 for (meth_name, send_meth, expect_success, args,
3621 ret_val_meth) in send_methods:
3622 indata = (data_prefix + meth_name).encode('ascii')
3623 try:
3624 ret = send_meth(indata, *args)
3625 msg = "sending with {}".format(meth_name)
3626 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3627 outdata = s.read()
3628 if outdata != indata.lower():
3629 self.fail(
3630 "While sending with <<{name:s}>> bad data "
3631 "<<{outdata:r}>> ({nout:d}) received; "
3632 "expected <<{indata:r}>> ({nin:d})\n".format(
3633 name=meth_name, outdata=outdata[:20],
3634 nout=len(outdata),
3635 indata=indata[:20], nin=len(indata)
3636 )
3637 )
3638 except ValueError as e:
3639 if expect_success:
3640 self.fail(
3641 "Failed to send with method <<{name:s}>>; "
3642 "expected to succeed.\n".format(name=meth_name)
3643 )
3644 if not str(e).startswith(meth_name):
3645 self.fail(
3646 "Method <<{name:s}>> failed with unexpected "
3647 "exception message: {exp:s}\n".format(
3648 name=meth_name, exp=e
3649 )
3650 )
3651
3652 for meth_name, recv_meth, expect_success, args in recv_methods:
3653 indata = (data_prefix + meth_name).encode('ascii')
3654 try:
3655 s.send(indata)
3656 outdata = recv_meth(*args)
3657 if outdata != indata.lower():
3658 self.fail(
3659 "While receiving with <<{name:s}>> bad data "
3660 "<<{outdata:r}>> ({nout:d}) received; "
3661 "expected <<{indata:r}>> ({nin:d})\n".format(
3662 name=meth_name, outdata=outdata[:20],
3663 nout=len(outdata),
3664 indata=indata[:20], nin=len(indata)
3665 )
3666 )
3667 except ValueError as e:
3668 if expect_success:
3669 self.fail(
3670 "Failed to receive with method <<{name:s}>>; "
3671 "expected to succeed.\n".format(name=meth_name)
3672 )
3673 if not str(e).startswith(meth_name):
3674 self.fail(
3675 "Method <<{name:s}>> failed with unexpected "
3676 "exception message: {exp:s}\n".format(
3677 name=meth_name, exp=e
3678 )
3679 )
3680 # consume data
3681 s.read()
3682
3683 # read(-1, buffer) is supported, even though read(-1) is not
3684 data = b"data"
3685 s.send(data)
3686 buffer = bytearray(len(data))
3687 self.assertEqual(s.read(-1, buffer), len(data))
3688 self.assertEqual(buffer, data)
3689
Christian Heimes888bbdc2017-09-07 14:18:21 -07003690 # sendall accepts bytes-like objects
3691 if ctypes is not None:
3692 ubyte = ctypes.c_ubyte * len(data)
3693 byteslike = ubyte.from_buffer_copy(data)
3694 s.sendall(byteslike)
3695 self.assertEqual(s.read(), data)
3696
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003697 # Make sure sendmsg et al are disallowed to avoid
3698 # inadvertent disclosure of data and/or corruption
3699 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003700 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003701 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3702 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3703 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003704 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003705 s.write(b"over\n")
3706
3707 self.assertRaises(ValueError, s.recv, -1)
3708 self.assertRaises(ValueError, s.read, -1)
3709
3710 s.close()
3711
3712 def test_recv_zero(self):
3713 server = ThreadedEchoServer(CERTFILE)
3714 server.__enter__()
3715 self.addCleanup(server.__exit__, None, None)
3716 s = socket.create_connection((HOST, server.port))
3717 self.addCleanup(s.close)
3718 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3719 self.addCleanup(s.close)
3720
3721 # recv/read(0) should return no data
3722 s.send(b"data")
3723 self.assertEqual(s.recv(0), b"")
3724 self.assertEqual(s.read(0), b"")
3725 self.assertEqual(s.read(), b"data")
3726
3727 # Should not block if the other end sends no data
3728 s.setblocking(False)
3729 self.assertEqual(s.recv(0), b"")
3730 self.assertEqual(s.recv_into(bytearray()), 0)
3731
3732 def test_nonblocking_send(self):
3733 server = ThreadedEchoServer(CERTFILE,
3734 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003735 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003736 cacerts=CERTFILE,
3737 chatty=True,
3738 connectionchatty=False)
3739 with server:
3740 s = test_wrap_socket(socket.socket(),
3741 server_side=False,
3742 certfile=CERTFILE,
3743 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003744 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003745 s.connect((HOST, server.port))
3746 s.setblocking(False)
3747
3748 # If we keep sending data, at some point the buffers
3749 # will be full and the call will block
3750 buf = bytearray(8192)
3751 def fill_buffer():
3752 while True:
3753 s.send(buf)
3754 self.assertRaises((ssl.SSLWantWriteError,
3755 ssl.SSLWantReadError), fill_buffer)
3756
3757 # Now read all the output and discard it
3758 s.setblocking(True)
3759 s.close()
3760
3761 def test_handshake_timeout(self):
3762 # Issue #5103: SSL handshake must respect the socket timeout
3763 server = socket.socket(socket.AF_INET)
3764 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003765 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003766 started = threading.Event()
3767 finish = False
3768
3769 def serve():
3770 server.listen()
3771 started.set()
3772 conns = []
3773 while not finish:
3774 r, w, e = select.select([server], [], [], 0.1)
3775 if server in r:
3776 # Let the socket hang around rather than having
3777 # it closed by garbage collection.
3778 conns.append(server.accept()[0])
3779 for sock in conns:
3780 sock.close()
3781
3782 t = threading.Thread(target=serve)
3783 t.start()
3784 started.wait()
3785
3786 try:
3787 try:
3788 c = socket.socket(socket.AF_INET)
3789 c.settimeout(0.2)
3790 c.connect((host, port))
3791 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003792 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003793 test_wrap_socket, c)
3794 finally:
3795 c.close()
3796 try:
3797 c = socket.socket(socket.AF_INET)
3798 c = test_wrap_socket(c)
3799 c.settimeout(0.2)
3800 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003801 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003802 c.connect, (host, port))
3803 finally:
3804 c.close()
3805 finally:
3806 finish = True
3807 t.join()
3808 server.close()
3809
3810 def test_server_accept(self):
3811 # Issue #16357: accept() on a SSLSocket created through
3812 # SSLContext.wrap_socket().
Christian Heimes2875c602021-04-19 07:27:10 +02003813 client_ctx, server_ctx, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003814 server = socket.socket(socket.AF_INET)
3815 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003816 port = socket_helper.bind_port(server)
Christian Heimes2875c602021-04-19 07:27:10 +02003817 server = server_ctx.wrap_socket(server, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003818 self.assertTrue(server.server_side)
3819
3820 evt = threading.Event()
3821 remote = None
3822 peer = None
3823 def serve():
3824 nonlocal remote, peer
3825 server.listen()
3826 # Block on the accept and wait on the connection to close.
3827 evt.set()
3828 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003829 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003830
3831 t = threading.Thread(target=serve)
3832 t.start()
3833 # Client wait until server setup and perform a connect.
3834 evt.wait()
Christian Heimes2875c602021-04-19 07:27:10 +02003835 client = client_ctx.wrap_socket(
3836 socket.socket(), server_hostname=hostname
3837 )
3838 client.connect((hostname, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003839 client.send(b'data')
3840 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003841 client_addr = client.getsockname()
3842 client.close()
3843 t.join()
3844 remote.close()
3845 server.close()
3846 # Sanity checks.
3847 self.assertIsInstance(remote, ssl.SSLSocket)
3848 self.assertEqual(peer, client_addr)
3849
3850 def test_getpeercert_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003851 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3852 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003853 with context.wrap_socket(socket.socket()) as sock:
3854 with self.assertRaises(OSError) as cm:
3855 sock.getpeercert()
3856 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3857
3858 def test_do_handshake_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003859 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3860 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003861 with context.wrap_socket(socket.socket()) as sock:
3862 with self.assertRaises(OSError) as cm:
3863 sock.do_handshake()
3864 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3865
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003866 def test_no_shared_ciphers(self):
3867 client_context, server_context, hostname = testing_context()
3868 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
Miss Islington (bot)4becc562021-06-13 05:07:00 -07003869 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Victor Stinner5e922652018-09-07 17:30:33 +02003870 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003871 client_context.set_ciphers("AES128")
3872 server_context.set_ciphers("AES256")
3873 with ThreadedEchoServer(context=server_context) as server:
3874 with client_context.wrap_socket(socket.socket(),
3875 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003876 with self.assertRaises(OSError):
3877 s.connect((HOST, server.port))
3878 self.assertIn("no shared cipher", server.conn_errors[0])
3879
3880 def test_version_basic(self):
3881 """
3882 Basic tests for SSLSocket.version().
3883 More tests are done in the test_protocol_*() methods.
3884 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003885 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3886 context.check_hostname = False
3887 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003888 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003889 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003890 chatty=False) as server:
3891 with context.wrap_socket(socket.socket()) as s:
3892 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003893 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003894 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003895 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003896 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003897 self.assertIs(s.version(), None)
3898
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003899 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003900 def test_tls1_3(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003901 client_context, server_context, hostname = testing_context()
3902 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3903 with ThreadedEchoServer(context=server_context) as server:
3904 with client_context.wrap_socket(socket.socket(),
3905 server_hostname=hostname) as s:
Christian Heimescb5b68a2017-09-07 18:07:00 -07003906 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003907 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003908 'TLS_AES_256_GCM_SHA384',
3909 'TLS_CHACHA20_POLY1305_SHA256',
3910 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003911 })
3912 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003913
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003914 @requires_tls_version('TLSv1_2')
Christian Heimes2875c602021-04-19 07:27:10 +02003915 @requires_tls_version('TLSv1')
3916 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003917 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003918 client_context, server_context, hostname = testing_context()
3919 # client TLSv1.0 to 1.2
3920 client_context.minimum_version = ssl.TLSVersion.TLSv1
3921 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3922 # server only TLSv1.2
3923 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3924 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3925
3926 with ThreadedEchoServer(context=server_context) as server:
3927 with client_context.wrap_socket(socket.socket(),
3928 server_hostname=hostname) as s:
3929 s.connect((HOST, server.port))
3930 self.assertEqual(s.version(), 'TLSv1.2')
3931
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003932 @requires_tls_version('TLSv1_1')
Christian Heimes2875c602021-04-19 07:27:10 +02003933 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003934 def test_min_max_version_tlsv1_1(self):
3935 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003936 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003937 client_context.minimum_version = ssl.TLSVersion.TLSv1
3938 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003939 server_context.minimum_version = ssl.TLSVersion.TLSv1
3940 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003941 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003942
3943 with ThreadedEchoServer(context=server_context) as server:
3944 with client_context.wrap_socket(socket.socket(),
3945 server_hostname=hostname) as s:
3946 s.connect((HOST, server.port))
3947 self.assertEqual(s.version(), 'TLSv1.1')
3948
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003949 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003950 @requires_tls_version('TLSv1')
Christian Heimes2875c602021-04-19 07:27:10 +02003951 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003952 def test_min_max_version_mismatch(self):
3953 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003954 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003955 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003956 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003957 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003958 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003959 seclevel_workaround(client_context, server_context)
3960
Christian Heimes698dde12018-02-27 11:54:43 +01003961 with ThreadedEchoServer(context=server_context) as server:
3962 with client_context.wrap_socket(socket.socket(),
3963 server_hostname=hostname) as s:
3964 with self.assertRaises(ssl.SSLError) as e:
3965 s.connect((HOST, server.port))
3966 self.assertIn("alert", str(e.exception))
3967
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003968 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003969 def test_min_max_version_sslv3(self):
3970 client_context, server_context, hostname = testing_context()
3971 server_context.minimum_version = ssl.TLSVersion.SSLv3
3972 client_context.minimum_version = ssl.TLSVersion.SSLv3
3973 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003974 seclevel_workaround(client_context, server_context)
3975
Christian Heimes698dde12018-02-27 11:54:43 +01003976 with ThreadedEchoServer(context=server_context) as server:
3977 with client_context.wrap_socket(socket.socket(),
3978 server_hostname=hostname) as s:
3979 s.connect((HOST, server.port))
3980 self.assertEqual(s.version(), 'SSLv3')
3981
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003982 def test_default_ecdh_curve(self):
3983 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3984 # should be enabled by default on SSL contexts.
Christian Heimes2875c602021-04-19 07:27:10 +02003985 client_context, server_context, hostname = testing_context()
Christian Heimescb5b68a2017-09-07 18:07:00 -07003986 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3987 # cipher name.
Christian Heimes2875c602021-04-19 07:27:10 +02003988 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003989 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3990 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3991 # our default cipher list should prefer ECDH-based ciphers
3992 # automatically.
Christian Heimes2875c602021-04-19 07:27:10 +02003993 with ThreadedEchoServer(context=server_context) as server:
3994 with client_context.wrap_socket(socket.socket(),
3995 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003996 s.connect((HOST, server.port))
3997 self.assertIn("ECDH", s.cipher()[0])
3998
3999 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
4000 "'tls-unique' channel binding not available")
4001 def test_tls_unique_channel_binding(self):
4002 """Test tls-unique channel binding."""
4003 if support.verbose:
4004 sys.stdout.write("\n")
4005
Christian Heimes05d9fe32018-02-27 08:55:39 +01004006 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004007
4008 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004009 chatty=True,
4010 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01004011
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004012 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01004013 with client_context.wrap_socket(
4014 socket.socket(),
4015 server_hostname=hostname) as s:
4016 s.connect((HOST, server.port))
4017 # get the data
4018 cb_data = s.get_channel_binding("tls-unique")
4019 if support.verbose:
4020 sys.stdout.write(
4021 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004022
Christian Heimes05d9fe32018-02-27 08:55:39 +01004023 # check if it is sane
4024 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02004025 if s.version() == 'TLSv1.3':
4026 self.assertEqual(len(cb_data), 48)
4027 else:
4028 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004029
Christian Heimes05d9fe32018-02-27 08:55:39 +01004030 # and compare with the peers version
4031 s.write(b"CB tls-unique\n")
4032 peer_data_repr = s.read().strip()
4033 self.assertEqual(peer_data_repr,
4034 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004035
4036 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01004037 with client_context.wrap_socket(
4038 socket.socket(),
4039 server_hostname=hostname) as s:
4040 s.connect((HOST, server.port))
4041 new_cb_data = s.get_channel_binding("tls-unique")
4042 if support.verbose:
4043 sys.stdout.write(
4044 "got another channel binding data: {0!r}\n".format(
4045 new_cb_data)
4046 )
4047 # is it really unique
4048 self.assertNotEqual(cb_data, new_cb_data)
4049 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02004050 if s.version() == 'TLSv1.3':
4051 self.assertEqual(len(cb_data), 48)
4052 else:
4053 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01004054 s.write(b"CB tls-unique\n")
4055 peer_data_repr = s.read().strip()
4056 self.assertEqual(peer_data_repr,
4057 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004058
4059 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004060 client_context, server_context, hostname = testing_context()
4061 stats = server_params_test(client_context, server_context,
4062 chatty=True, connectionchatty=True,
4063 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004064 if support.verbose:
4065 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
4066 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
4067
4068 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
4069 "ssl.OP_NO_COMPRESSION needed for this test")
4070 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004071 client_context, server_context, hostname = testing_context()
4072 client_context.options |= ssl.OP_NO_COMPRESSION
4073 server_context.options |= ssl.OP_NO_COMPRESSION
4074 stats = server_params_test(client_context, server_context,
4075 chatty=True, connectionchatty=True,
4076 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004077 self.assertIs(stats['compression'], None)
4078
Paul Monsonf3550692019-06-19 13:09:54 -07004079 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004080 def test_dh_params(self):
4081 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004082 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004083 # test scenario needs TLS <= 1.2
Miss Islington (bot)4becc562021-06-13 05:07:00 -07004084 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +02004085 server_context.load_dh_params(DHFILE)
4086 server_context.set_ciphers("kEDH")
Miss Islington (bot)4becc562021-06-13 05:07:00 -07004087 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +02004088 stats = server_params_test(client_context, server_context,
4089 chatty=True, connectionchatty=True,
4090 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004091 cipher = stats["cipher"][0]
4092 parts = cipher.split("-")
4093 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4094 self.fail("Non-DH cipher: " + cipher[0])
4095
Christian Heimesb7b92252018-02-25 09:49:31 +01004096 def test_ecdh_curve(self):
4097 # server secp384r1, client auto
4098 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004099
Christian Heimesb7b92252018-02-25 09:49:31 +01004100 server_context.set_ecdh_curve("secp384r1")
4101 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004102 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004103 stats = server_params_test(client_context, server_context,
4104 chatty=True, connectionchatty=True,
4105 sni_name=hostname)
4106
4107 # server auto, client secp384r1
4108 client_context, server_context, hostname = testing_context()
4109 client_context.set_ecdh_curve("secp384r1")
4110 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004111 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004112 stats = server_params_test(client_context, server_context,
4113 chatty=True, connectionchatty=True,
4114 sni_name=hostname)
4115
4116 # server / client curve mismatch
4117 client_context, server_context, hostname = testing_context()
4118 client_context.set_ecdh_curve("prime256v1")
4119 server_context.set_ecdh_curve("secp384r1")
4120 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004121 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
4122 with self.assertRaises(ssl.SSLError):
Christian Heimes39258d32021-04-17 11:36:35 +02004123 server_params_test(client_context, server_context,
4124 chatty=True, connectionchatty=True,
4125 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004126
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004127 def test_selected_alpn_protocol(self):
4128 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004129 client_context, server_context, hostname = testing_context()
4130 stats = server_params_test(client_context, server_context,
4131 chatty=True, connectionchatty=True,
4132 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004133 self.assertIs(stats['client_alpn_protocol'], None)
4134
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004135 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4136 # selected_alpn_protocol() is None unless ALPN is used by the client.
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(['foo', 'bar'])
4139 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004140 chatty=True, connectionchatty=True,
4141 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004142 self.assertIs(stats['client_alpn_protocol'], None)
4143
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004144 def test_alpn_protocols(self):
4145 server_protocols = ['foo', 'bar', 'milkshake']
4146 protocol_tests = [
4147 (['foo', 'bar'], 'foo'),
4148 (['bar', 'foo'], 'foo'),
4149 (['milkshake'], 'milkshake'),
4150 (['http/3.0', 'http/4.0'], None)
4151 ]
4152 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004153 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004154 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004155 client_context.set_alpn_protocols(client_protocols)
4156
4157 try:
4158 stats = server_params_test(client_context,
4159 server_context,
4160 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004161 connectionchatty=True,
4162 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004163 except ssl.SSLError as e:
4164 stats = e
4165
Christian Heimes39258d32021-04-17 11:36:35 +02004166 msg = "failed trying %s (s) and %s (c).\n" \
4167 "was expecting %s, but got %%s from the %%s" \
4168 % (str(server_protocols), str(client_protocols),
4169 str(expected))
4170 client_result = stats['client_alpn_protocol']
4171 self.assertEqual(client_result, expected,
4172 msg % (client_result, "client"))
4173 server_result = stats['server_alpn_protocols'][-1] \
4174 if len(stats['server_alpn_protocols']) else 'nothing'
4175 self.assertEqual(server_result, expected,
4176 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004177
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004178 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004179 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004180
4181 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004182 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004183 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004184 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004185 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004186 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004187 client_context.load_verify_locations(SIGNING_CA)
4188 return server_context, other_context, client_context
4189
4190 def check_common_name(self, stats, name):
4191 cert = stats['peercert']
4192 self.assertIn((('commonName', name),), cert['subject'])
4193
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004194 def test_sni_callback(self):
4195 calls = []
4196 server_context, other_context, client_context = self.sni_contexts()
4197
Christian Heimesa170fa12017-09-15 20:27:30 +02004198 client_context.check_hostname = False
4199
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004200 def servername_cb(ssl_sock, server_name, initial_context):
4201 calls.append((server_name, initial_context))
4202 if server_name is not None:
4203 ssl_sock.context = other_context
4204 server_context.set_servername_callback(servername_cb)
4205
4206 stats = server_params_test(client_context, server_context,
4207 chatty=True,
4208 sni_name='supermessage')
4209 # The hostname was fetched properly, and the certificate was
4210 # changed for the connection.
4211 self.assertEqual(calls, [("supermessage", server_context)])
4212 # CERTFILE4 was selected
4213 self.check_common_name(stats, 'fakehostname')
4214
4215 calls = []
4216 # The callback is called with server_name=None
4217 stats = server_params_test(client_context, server_context,
4218 chatty=True,
4219 sni_name=None)
4220 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004221 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004222
4223 # Check disabling the callback
4224 calls = []
4225 server_context.set_servername_callback(None)
4226
4227 stats = server_params_test(client_context, server_context,
4228 chatty=True,
4229 sni_name='notfunny')
4230 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004231 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004232 self.assertEqual(calls, [])
4233
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004234 def test_sni_callback_alert(self):
4235 # Returning a TLS alert is reflected to the connecting client
4236 server_context, other_context, client_context = self.sni_contexts()
4237
4238 def cb_returning_alert(ssl_sock, server_name, initial_context):
4239 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4240 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004241 with self.assertRaises(ssl.SSLError) as cm:
4242 stats = server_params_test(client_context, server_context,
4243 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004244 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004245 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004246
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004247 def test_sni_callback_raising(self):
4248 # Raising fails the connection with a TLS handshake failure alert.
4249 server_context, other_context, client_context = self.sni_contexts()
4250
4251 def cb_raising(ssl_sock, server_name, initial_context):
4252 1/0
4253 server_context.set_servername_callback(cb_raising)
4254
Victor Stinner00253502019-06-03 03:51:43 +02004255 with support.catch_unraisable_exception() as catch:
4256 with self.assertRaises(ssl.SSLError) as cm:
4257 stats = server_params_test(client_context, server_context,
4258 chatty=False,
4259 sni_name='supermessage')
4260
4261 self.assertEqual(cm.exception.reason,
4262 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4263 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004264
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004265 def test_sni_callback_wrong_return_type(self):
4266 # Returning the wrong return type terminates the TLS connection
4267 # with an internal error alert.
4268 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004269
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004270 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4271 return "foo"
4272 server_context.set_servername_callback(cb_wrong_return_type)
4273
Victor Stinner00253502019-06-03 03:51:43 +02004274 with support.catch_unraisable_exception() as catch:
4275 with self.assertRaises(ssl.SSLError) as cm:
4276 stats = server_params_test(client_context, server_context,
4277 chatty=False,
4278 sni_name='supermessage')
4279
4280
4281 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4282 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004283
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004284 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004285 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004286 client_context.set_ciphers("AES128:AES256")
4287 server_context.set_ciphers("AES256")
4288 expected_algs = [
4289 "AES256", "AES-256",
4290 # TLS 1.3 ciphers are always enabled
4291 "TLS_CHACHA20", "TLS_AES",
4292 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004293
Christian Heimesa170fa12017-09-15 20:27:30 +02004294 stats = server_params_test(client_context, server_context,
4295 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004296 ciphers = stats['server_shared_ciphers'][0]
4297 self.assertGreater(len(ciphers), 0)
4298 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004299 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004300 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004301
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004302 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004303 client_context, server_context, hostname = testing_context()
4304 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004305
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004306 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004307 s = client_context.wrap_socket(socket.socket(),
4308 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004309 s.connect((HOST, server.port))
4310 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004311
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004312 self.assertRaises(ValueError, s.read, 1024)
4313 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004314
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004315 def test_sendfile(self):
4316 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004317 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004318 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004319 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimes2875c602021-04-19 07:27:10 +02004320 client_context, server_context, hostname = testing_context()
4321 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004322 with server:
Christian Heimes2875c602021-04-19 07:27:10 +02004323 with client_context.wrap_socket(socket.socket(),
4324 server_hostname=hostname) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004325 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004326 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004327 s.sendfile(file)
4328 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004329
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004330 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004331 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004332 # TODO: sessions aren't compatible with TLSv1.3 yet
Miss Islington (bot)4becc562021-06-13 05:07:00 -07004333 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004334
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004335 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004336 stats = server_params_test(client_context, server_context,
4337 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004338 session = stats['session']
4339 self.assertTrue(session.id)
4340 self.assertGreater(session.time, 0)
4341 self.assertGreater(session.timeout, 0)
4342 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004343 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004344 self.assertFalse(stats['session_reused'])
4345 sess_stat = server_context.session_stats()
4346 self.assertEqual(sess_stat['accept'], 1)
4347 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004348
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004349 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004350 stats = server_params_test(client_context, server_context,
4351 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004352 sess_stat = server_context.session_stats()
4353 self.assertEqual(sess_stat['accept'], 2)
4354 self.assertEqual(sess_stat['hits'], 1)
4355 self.assertTrue(stats['session_reused'])
4356 session2 = stats['session']
4357 self.assertEqual(session2.id, session.id)
4358 self.assertEqual(session2, session)
4359 self.assertIsNot(session2, session)
4360 self.assertGreaterEqual(session2.time, session.time)
4361 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004362
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004363 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004364 stats = server_params_test(client_context, server_context,
4365 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004366 self.assertFalse(stats['session_reused'])
4367 session3 = stats['session']
4368 self.assertNotEqual(session3.id, session.id)
4369 self.assertNotEqual(session3, session)
4370 sess_stat = server_context.session_stats()
4371 self.assertEqual(sess_stat['accept'], 3)
4372 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004373
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004374 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004375 stats = server_params_test(client_context, server_context,
4376 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004377 self.assertTrue(stats['session_reused'])
4378 session4 = stats['session']
4379 self.assertEqual(session4.id, session.id)
4380 self.assertEqual(session4, session)
4381 self.assertGreaterEqual(session4.time, session.time)
4382 self.assertGreaterEqual(session4.timeout, session.timeout)
4383 sess_stat = server_context.session_stats()
4384 self.assertEqual(sess_stat['accept'], 4)
4385 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004386
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004387 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004388 client_context, server_context, hostname = testing_context()
4389 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004390
Christian Heimes05d9fe32018-02-27 08:55:39 +01004391 # TODO: session reuse does not work with TLSv1.3
Miss Islington (bot)4becc562021-06-13 05:07:00 -07004392 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4393 client_context2.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimescb5b68a2017-09-07 18:07:00 -07004394
Christian Heimesa170fa12017-09-15 20:27:30 +02004395 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004396 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004397 with client_context.wrap_socket(socket.socket(),
4398 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004399 # session is None before handshake
4400 self.assertEqual(s.session, None)
4401 self.assertEqual(s.session_reused, None)
4402 s.connect((HOST, server.port))
4403 session = s.session
4404 self.assertTrue(session)
4405 with self.assertRaises(TypeError) as e:
4406 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004407 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004408
Christian Heimesa170fa12017-09-15 20:27:30 +02004409 with client_context.wrap_socket(socket.socket(),
4410 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004411 s.connect((HOST, server.port))
4412 # cannot set session after handshake
4413 with self.assertRaises(ValueError) as e:
4414 s.session = session
4415 self.assertEqual(str(e.exception),
4416 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004417
Christian Heimesa170fa12017-09-15 20:27:30 +02004418 with client_context.wrap_socket(socket.socket(),
4419 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004420 # can set session before handshake and before the
4421 # connection was established
4422 s.session = session
4423 s.connect((HOST, server.port))
4424 self.assertEqual(s.session.id, session.id)
4425 self.assertEqual(s.session, session)
4426 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004427
Christian Heimesa170fa12017-09-15 20:27:30 +02004428 with client_context2.wrap_socket(socket.socket(),
4429 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004430 # cannot re-use session with a different SSLContext
4431 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004432 s.session = session
4433 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004434 self.assertEqual(str(e.exception),
4435 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004436
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004437
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004438@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004439class TestPostHandshakeAuth(unittest.TestCase):
4440 def test_pha_setter(self):
4441 protocols = [
Christian Heimes2875c602021-04-19 07:27:10 +02004442 ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
Christian Heimes9fb051f2018-09-23 08:32:31 +02004443 ]
4444 for protocol in protocols:
4445 ctx = ssl.SSLContext(protocol)
4446 self.assertEqual(ctx.post_handshake_auth, False)
4447
4448 ctx.post_handshake_auth = True
4449 self.assertEqual(ctx.post_handshake_auth, True)
4450
4451 ctx.verify_mode = ssl.CERT_REQUIRED
4452 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4453 self.assertEqual(ctx.post_handshake_auth, True)
4454
4455 ctx.post_handshake_auth = False
4456 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4457 self.assertEqual(ctx.post_handshake_auth, False)
4458
4459 ctx.verify_mode = ssl.CERT_OPTIONAL
4460 ctx.post_handshake_auth = True
4461 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4462 self.assertEqual(ctx.post_handshake_auth, True)
4463
4464 def test_pha_required(self):
4465 client_context, server_context, hostname = testing_context()
4466 server_context.post_handshake_auth = True
4467 server_context.verify_mode = ssl.CERT_REQUIRED
4468 client_context.post_handshake_auth = True
4469 client_context.load_cert_chain(SIGNED_CERTFILE)
4470
4471 server = ThreadedEchoServer(context=server_context, chatty=False)
4472 with server:
4473 with client_context.wrap_socket(socket.socket(),
4474 server_hostname=hostname) as s:
4475 s.connect((HOST, server.port))
4476 s.write(b'HASCERT')
4477 self.assertEqual(s.recv(1024), b'FALSE\n')
4478 s.write(b'PHA')
4479 self.assertEqual(s.recv(1024), b'OK\n')
4480 s.write(b'HASCERT')
4481 self.assertEqual(s.recv(1024), b'TRUE\n')
4482 # PHA method just returns true when cert is already available
4483 s.write(b'PHA')
4484 self.assertEqual(s.recv(1024), b'OK\n')
4485 s.write(b'GETCERT')
4486 cert_text = s.recv(4096).decode('us-ascii')
4487 self.assertIn('Python Software Foundation CA', cert_text)
4488
4489 def test_pha_required_nocert(self):
4490 client_context, server_context, hostname = testing_context()
4491 server_context.post_handshake_auth = True
4492 server_context.verify_mode = ssl.CERT_REQUIRED
4493 client_context.post_handshake_auth = True
4494
Christian Heimesc8666cf2021-04-24 09:17:54 +02004495 def msg_cb(conn, direction, version, content_type, msg_type, data):
4496 if support.verbose and content_type == _TLSContentType.ALERT:
4497 info = (conn, direction, version, content_type, msg_type, data)
4498 sys.stdout.write(f"TLS: {info!r}\n")
4499
4500 server_context._msg_callback = msg_cb
4501 client_context._msg_callback = msg_cb
4502
4503 server = ThreadedEchoServer(context=server_context, chatty=True)
4504 with server:
4505 with client_context.wrap_socket(socket.socket(),
Miss Islington (bot)d2ab15f2021-06-03 13:15:15 -07004506 server_hostname=hostname,
4507 suppress_ragged_eofs=False) as s:
Christian Heimesc8666cf2021-04-24 09:17:54 +02004508 s.connect((HOST, server.port))
4509 s.write(b'PHA')
Christian Heimesce9a0642021-04-24 15:08:13 +02004510 # test sometimes fails with EOF error. Test passes as long as
4511 # server aborts connection with an error.
Christian Heimesc8666cf2021-04-24 09:17:54 +02004512 with self.assertRaisesRegex(
4513 ssl.SSLError,
Christian Heimesce9a0642021-04-24 15:08:13 +02004514 '(certificate required|EOF occurred)'
Christian Heimesc8666cf2021-04-24 09:17:54 +02004515 ):
Victor Stinner73ea5462019-07-09 14:33:49 +02004516 # receive CertificateRequest
Miss Islington (bot)e5e93e62021-06-02 16:48:40 -07004517 data = s.recv(1024)
Miss Islington (bot)e5e93e62021-06-02 16:48:40 -07004518 self.assertEqual(data, b'OK\n')
4519
Victor Stinner73ea5462019-07-09 14:33:49 +02004520 # send empty Certificate + Finish
4521 s.write(b'HASCERT')
Miss Islington (bot)e5e93e62021-06-02 16:48:40 -07004522
Victor Stinner73ea5462019-07-09 14:33:49 +02004523 # receive alert
Miss Islington (bot)d2ab15f2021-06-03 13:15:15 -07004524 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004525
4526 def test_pha_optional(self):
4527 if support.verbose:
4528 sys.stdout.write("\n")
4529
4530 client_context, server_context, hostname = testing_context()
4531 server_context.post_handshake_auth = True
4532 server_context.verify_mode = ssl.CERT_REQUIRED
4533 client_context.post_handshake_auth = True
4534 client_context.load_cert_chain(SIGNED_CERTFILE)
4535
4536 # check CERT_OPTIONAL
4537 server_context.verify_mode = ssl.CERT_OPTIONAL
4538 server = ThreadedEchoServer(context=server_context, chatty=False)
4539 with server:
4540 with client_context.wrap_socket(socket.socket(),
4541 server_hostname=hostname) as s:
4542 s.connect((HOST, server.port))
4543 s.write(b'HASCERT')
4544 self.assertEqual(s.recv(1024), b'FALSE\n')
4545 s.write(b'PHA')
4546 self.assertEqual(s.recv(1024), b'OK\n')
4547 s.write(b'HASCERT')
4548 self.assertEqual(s.recv(1024), b'TRUE\n')
4549
4550 def test_pha_optional_nocert(self):
4551 if support.verbose:
4552 sys.stdout.write("\n")
4553
4554 client_context, server_context, hostname = testing_context()
4555 server_context.post_handshake_auth = True
4556 server_context.verify_mode = ssl.CERT_OPTIONAL
4557 client_context.post_handshake_auth = True
4558
4559 server = ThreadedEchoServer(context=server_context, chatty=False)
4560 with server:
4561 with client_context.wrap_socket(socket.socket(),
4562 server_hostname=hostname) as s:
4563 s.connect((HOST, server.port))
4564 s.write(b'HASCERT')
4565 self.assertEqual(s.recv(1024), b'FALSE\n')
4566 s.write(b'PHA')
4567 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004568 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004569 s.write(b'HASCERT')
4570 self.assertEqual(s.recv(1024), b'FALSE\n')
4571
4572 def test_pha_no_pha_client(self):
4573 client_context, server_context, hostname = testing_context()
4574 server_context.post_handshake_auth = True
4575 server_context.verify_mode = ssl.CERT_REQUIRED
4576 client_context.load_cert_chain(SIGNED_CERTFILE)
4577
4578 server = ThreadedEchoServer(context=server_context, chatty=False)
4579 with server:
4580 with client_context.wrap_socket(socket.socket(),
4581 server_hostname=hostname) as s:
4582 s.connect((HOST, server.port))
4583 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4584 s.verify_client_post_handshake()
4585 s.write(b'PHA')
4586 self.assertIn(b'extension not received', s.recv(1024))
4587
4588 def test_pha_no_pha_server(self):
4589 # server doesn't have PHA enabled, cert is requested in handshake
4590 client_context, server_context, hostname = testing_context()
4591 server_context.verify_mode = ssl.CERT_REQUIRED
4592 client_context.post_handshake_auth = True
4593 client_context.load_cert_chain(SIGNED_CERTFILE)
4594
4595 server = ThreadedEchoServer(context=server_context, chatty=False)
4596 with server:
4597 with client_context.wrap_socket(socket.socket(),
4598 server_hostname=hostname) as s:
4599 s.connect((HOST, server.port))
4600 s.write(b'HASCERT')
4601 self.assertEqual(s.recv(1024), b'TRUE\n')
4602 # PHA doesn't fail if there is already a cert
4603 s.write(b'PHA')
4604 self.assertEqual(s.recv(1024), b'OK\n')
4605 s.write(b'HASCERT')
4606 self.assertEqual(s.recv(1024), b'TRUE\n')
4607
4608 def test_pha_not_tls13(self):
4609 # TLS 1.2
4610 client_context, server_context, hostname = testing_context()
4611 server_context.verify_mode = ssl.CERT_REQUIRED
4612 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4613 client_context.post_handshake_auth = True
4614 client_context.load_cert_chain(SIGNED_CERTFILE)
4615
4616 server = ThreadedEchoServer(context=server_context, chatty=False)
4617 with server:
4618 with client_context.wrap_socket(socket.socket(),
4619 server_hostname=hostname) as s:
4620 s.connect((HOST, server.port))
4621 # PHA fails for TLS != 1.3
4622 s.write(b'PHA')
4623 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4624
Christian Heimesf0f59302019-07-01 08:29:17 +02004625 def test_bpo37428_pha_cert_none(self):
4626 # verify that post_handshake_auth does not implicitly enable cert
4627 # validation.
4628 hostname = SIGNED_CERTFILE_HOSTNAME
4629 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4630 client_context.post_handshake_auth = True
4631 client_context.load_cert_chain(SIGNED_CERTFILE)
4632 # no cert validation and CA on client side
4633 client_context.check_hostname = False
4634 client_context.verify_mode = ssl.CERT_NONE
4635
4636 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4637 server_context.load_cert_chain(SIGNED_CERTFILE)
4638 server_context.load_verify_locations(SIGNING_CA)
4639 server_context.post_handshake_auth = True
4640 server_context.verify_mode = ssl.CERT_REQUIRED
4641
4642 server = ThreadedEchoServer(context=server_context, chatty=False)
4643 with server:
4644 with client_context.wrap_socket(socket.socket(),
4645 server_hostname=hostname) as s:
4646 s.connect((HOST, server.port))
4647 s.write(b'HASCERT')
4648 self.assertEqual(s.recv(1024), b'FALSE\n')
4649 s.write(b'PHA')
4650 self.assertEqual(s.recv(1024), b'OK\n')
4651 s.write(b'HASCERT')
4652 self.assertEqual(s.recv(1024), b'TRUE\n')
4653 # server cert has not been validated
4654 self.assertEqual(s.getpeercert(), {})
4655
Christian Heimes666991f2021-04-26 15:01:40 +02004656 def test_internal_chain_client(self):
4657 client_context, server_context, hostname = testing_context(
4658 server_chain=False
4659 )
4660 server = ThreadedEchoServer(context=server_context, chatty=False)
4661 with server:
4662 with client_context.wrap_socket(
4663 socket.socket(),
4664 server_hostname=hostname
4665 ) as s:
4666 s.connect((HOST, server.port))
4667 vc = s._sslobj.get_verified_chain()
4668 self.assertEqual(len(vc), 2)
4669 ee, ca = vc
4670 uvc = s._sslobj.get_unverified_chain()
4671 self.assertEqual(len(uvc), 1)
4672
4673 self.assertEqual(ee, uvc[0])
4674 self.assertEqual(hash(ee), hash(uvc[0]))
4675 self.assertEqual(repr(ee), repr(uvc[0]))
4676
4677 self.assertNotEqual(ee, ca)
4678 self.assertNotEqual(hash(ee), hash(ca))
4679 self.assertNotEqual(repr(ee), repr(ca))
4680 self.assertNotEqual(ee.get_info(), ca.get_info())
4681 self.assertIn("CN=localhost", repr(ee))
4682 self.assertIn("CN=our-ca-server", repr(ca))
4683
4684 pem = ee.public_bytes(_ssl.ENCODING_PEM)
4685 der = ee.public_bytes(_ssl.ENCODING_DER)
4686 self.assertIsInstance(pem, str)
4687 self.assertIn("-----BEGIN CERTIFICATE-----", pem)
4688 self.assertIsInstance(der, bytes)
4689 self.assertEqual(
4690 ssl.PEM_cert_to_DER_cert(pem), der
4691 )
4692
4693 def test_internal_chain_server(self):
4694 client_context, server_context, hostname = testing_context()
4695 client_context.load_cert_chain(SIGNED_CERTFILE)
4696 server_context.verify_mode = ssl.CERT_REQUIRED
4697 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
4698
4699 server = ThreadedEchoServer(context=server_context, chatty=False)
4700 with server:
4701 with client_context.wrap_socket(
4702 socket.socket(),
4703 server_hostname=hostname
4704 ) as s:
4705 s.connect((HOST, server.port))
4706 s.write(b'VERIFIEDCHAIN\n')
4707 res = s.recv(1024)
4708 self.assertEqual(res, b'\x02\n')
4709 s.write(b'UNVERIFIEDCHAIN\n')
4710 res = s.recv(1024)
4711 self.assertEqual(res, b'\x02\n')
4712
Christian Heimes9fb051f2018-09-23 08:32:31 +02004713
Christian Heimesc7f70692019-05-31 11:44:05 +02004714HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4715requires_keylog = unittest.skipUnless(
4716 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4717
4718class TestSSLDebug(unittest.TestCase):
4719
Hai Shia7f5d932020-08-04 00:41:24 +08004720 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004721 with open(fname) as f:
4722 return len(list(f))
4723
4724 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004725 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004726 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004727 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004728 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4729 self.assertEqual(ctx.keylog_filename, None)
4730
Hai Shia7f5d932020-08-04 00:41:24 +08004731 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4732 ctx.keylog_filename = os_helper.TESTFN
4733 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4734 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004735 self.assertEqual(self.keylog_lines(), 1)
4736
4737 ctx.keylog_filename = None
4738 self.assertEqual(ctx.keylog_filename, None)
4739
4740 with self.assertRaises((IsADirectoryError, PermissionError)):
4741 # Windows raises PermissionError
4742 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004743 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004744
4745 with self.assertRaises(TypeError):
4746 ctx.keylog_filename = 1
4747
4748 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004749 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004750 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004751 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004752 client_context, server_context, hostname = testing_context()
4753
Hai Shia7f5d932020-08-04 00:41:24 +08004754 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004755 server = ThreadedEchoServer(context=server_context, chatty=False)
4756 with server:
4757 with client_context.wrap_socket(socket.socket(),
4758 server_hostname=hostname) as s:
4759 s.connect((HOST, server.port))
4760 # header, 5 lines for TLS 1.3
4761 self.assertEqual(self.keylog_lines(), 6)
4762
4763 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004764 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004765 server = ThreadedEchoServer(context=server_context, chatty=False)
4766 with server:
4767 with client_context.wrap_socket(socket.socket(),
4768 server_hostname=hostname) as s:
4769 s.connect((HOST, server.port))
4770 self.assertGreaterEqual(self.keylog_lines(), 11)
4771
Hai Shia7f5d932020-08-04 00:41:24 +08004772 client_context.keylog_filename = os_helper.TESTFN
4773 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004774 server = ThreadedEchoServer(context=server_context, chatty=False)
4775 with server:
4776 with client_context.wrap_socket(socket.socket(),
4777 server_hostname=hostname) as s:
4778 s.connect((HOST, server.port))
4779 self.assertGreaterEqual(self.keylog_lines(), 21)
4780
4781 client_context.keylog_filename = None
4782 server_context.keylog_filename = None
4783
4784 @requires_keylog
4785 @unittest.skipIf(sys.flags.ignore_environment,
4786 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004787 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004788 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004789 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004790 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004791 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4792 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004793
4794 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4795 self.assertEqual(ctx.keylog_filename, None)
4796
4797 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004798 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004799
4800 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004801 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004802
4803 def test_msg_callback(self):
4804 client_context, server_context, hostname = testing_context()
4805
4806 def msg_cb(conn, direction, version, content_type, msg_type, data):
4807 pass
4808
4809 self.assertIs(client_context._msg_callback, None)
4810 client_context._msg_callback = msg_cb
4811 self.assertIs(client_context._msg_callback, msg_cb)
4812 with self.assertRaises(TypeError):
4813 client_context._msg_callback = object()
4814
4815 def test_msg_callback_tls12(self):
4816 client_context, server_context, hostname = testing_context()
Miss Islington (bot)4becc562021-06-13 05:07:00 -07004817 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc7f70692019-05-31 11:44:05 +02004818
4819 msg = []
4820
4821 def msg_cb(conn, direction, version, content_type, msg_type, data):
4822 self.assertIsInstance(conn, ssl.SSLSocket)
4823 self.assertIsInstance(data, bytes)
4824 self.assertIn(direction, {'read', 'write'})
4825 msg.append((direction, version, content_type, msg_type))
4826
4827 client_context._msg_callback = msg_cb
4828
4829 server = ThreadedEchoServer(context=server_context, chatty=False)
4830 with server:
4831 with client_context.wrap_socket(socket.socket(),
4832 server_hostname=hostname) as s:
4833 s.connect((HOST, server.port))
4834
Christian Heimese35d1ba2019-06-03 20:40:15 +02004835 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004836 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4837 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004838 msg
4839 )
4840 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004841 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4842 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004843 msg
4844 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004845
Christian Heimes77cde502021-03-21 16:13:09 +01004846 def test_msg_callback_deadlock_bpo43577(self):
4847 client_context, server_context, hostname = testing_context()
4848 server_context2 = testing_context()[1]
4849
4850 def msg_cb(conn, direction, version, content_type, msg_type, data):
4851 pass
4852
4853 def sni_cb(sock, servername, ctx):
4854 sock.context = server_context2
4855
4856 server_context._msg_callback = msg_cb
4857 server_context.sni_callback = sni_cb
4858
4859 server = ThreadedEchoServer(context=server_context, chatty=False)
4860 with server:
4861 with client_context.wrap_socket(socket.socket(),
4862 server_hostname=hostname) as s:
4863 s.connect((HOST, server.port))
4864 with client_context.wrap_socket(socket.socket(),
4865 server_hostname=hostname) as s:
4866 s.connect((HOST, server.port))
4867
Christian Heimesc7f70692019-05-31 11:44:05 +02004868
Ethan Furmana02cb472021-04-21 10:20:44 -07004869class TestEnumerations(unittest.TestCase):
4870
4871 def test_tlsversion(self):
4872 class CheckedTLSVersion(enum.IntEnum):
4873 MINIMUM_SUPPORTED = _ssl.PROTO_MINIMUM_SUPPORTED
4874 SSLv3 = _ssl.PROTO_SSLv3
4875 TLSv1 = _ssl.PROTO_TLSv1
4876 TLSv1_1 = _ssl.PROTO_TLSv1_1
4877 TLSv1_2 = _ssl.PROTO_TLSv1_2
4878 TLSv1_3 = _ssl.PROTO_TLSv1_3
4879 MAXIMUM_SUPPORTED = _ssl.PROTO_MAXIMUM_SUPPORTED
4880 enum._test_simple_enum(CheckedTLSVersion, TLSVersion)
4881
4882 def test_tlscontenttype(self):
4883 class Checked_TLSContentType(enum.IntEnum):
4884 """Content types (record layer)
4885
4886 See RFC 8446, section B.1
4887 """
4888 CHANGE_CIPHER_SPEC = 20
4889 ALERT = 21
4890 HANDSHAKE = 22
4891 APPLICATION_DATA = 23
4892 # pseudo content types
4893 HEADER = 0x100
4894 INNER_CONTENT_TYPE = 0x101
4895 enum._test_simple_enum(Checked_TLSContentType, _TLSContentType)
4896
4897 def test_tlsalerttype(self):
4898 class Checked_TLSAlertType(enum.IntEnum):
4899 """Alert types for TLSContentType.ALERT messages
4900
4901 See RFC 8466, section B.2
4902 """
4903 CLOSE_NOTIFY = 0
4904 UNEXPECTED_MESSAGE = 10
4905 BAD_RECORD_MAC = 20
4906 DECRYPTION_FAILED = 21
4907 RECORD_OVERFLOW = 22
4908 DECOMPRESSION_FAILURE = 30
4909 HANDSHAKE_FAILURE = 40
4910 NO_CERTIFICATE = 41
4911 BAD_CERTIFICATE = 42
4912 UNSUPPORTED_CERTIFICATE = 43
4913 CERTIFICATE_REVOKED = 44
4914 CERTIFICATE_EXPIRED = 45
4915 CERTIFICATE_UNKNOWN = 46
4916 ILLEGAL_PARAMETER = 47
4917 UNKNOWN_CA = 48
4918 ACCESS_DENIED = 49
4919 DECODE_ERROR = 50
4920 DECRYPT_ERROR = 51
4921 EXPORT_RESTRICTION = 60
4922 PROTOCOL_VERSION = 70
4923 INSUFFICIENT_SECURITY = 71
4924 INTERNAL_ERROR = 80
4925 INAPPROPRIATE_FALLBACK = 86
4926 USER_CANCELED = 90
4927 NO_RENEGOTIATION = 100
4928 MISSING_EXTENSION = 109
4929 UNSUPPORTED_EXTENSION = 110
4930 CERTIFICATE_UNOBTAINABLE = 111
4931 UNRECOGNIZED_NAME = 112
4932 BAD_CERTIFICATE_STATUS_RESPONSE = 113
4933 BAD_CERTIFICATE_HASH_VALUE = 114
4934 UNKNOWN_PSK_IDENTITY = 115
4935 CERTIFICATE_REQUIRED = 116
4936 NO_APPLICATION_PROTOCOL = 120
4937 enum._test_simple_enum(Checked_TLSAlertType, _TLSAlertType)
4938
4939 def test_tlsmessagetype(self):
4940 class Checked_TLSMessageType(enum.IntEnum):
4941 """Message types (handshake protocol)
4942
4943 See RFC 8446, section B.3
4944 """
4945 HELLO_REQUEST = 0
4946 CLIENT_HELLO = 1
4947 SERVER_HELLO = 2
4948 HELLO_VERIFY_REQUEST = 3
4949 NEWSESSION_TICKET = 4
4950 END_OF_EARLY_DATA = 5
4951 HELLO_RETRY_REQUEST = 6
4952 ENCRYPTED_EXTENSIONS = 8
4953 CERTIFICATE = 11
4954 SERVER_KEY_EXCHANGE = 12
4955 CERTIFICATE_REQUEST = 13
4956 SERVER_DONE = 14
4957 CERTIFICATE_VERIFY = 15
4958 CLIENT_KEY_EXCHANGE = 16
4959 FINISHED = 20
4960 CERTIFICATE_URL = 21
4961 CERTIFICATE_STATUS = 22
4962 SUPPLEMENTAL_DATA = 23
4963 KEY_UPDATE = 24
4964 NEXT_PROTO = 67
4965 MESSAGE_HASH = 254
4966 CHANGE_CIPHER_SPEC = 0x0101
4967 enum._test_simple_enum(Checked_TLSMessageType, _TLSMessageType)
4968
4969 def test_sslmethod(self):
4970 Checked_SSLMethod = enum._old_convert_(
4971 enum.IntEnum, '_SSLMethod', 'ssl',
4972 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4973 source=ssl._ssl,
4974 )
4975 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
4976
4977 def test_options(self):
4978 CheckedOptions = enum._old_convert_(
4979 enum.FlagEnum, 'Options', 'ssl',
4980 lambda name: name.startswith('OP_'),
4981 source=ssl._ssl,
4982 )
4983 enum._test_simple_enum(CheckedOptions, ssl.Options)
4984
4985
4986 def test_alertdescription(self):
4987 CheckedAlertDescription = enum._old_convert_(
4988 enum.IntEnum, 'AlertDescription', 'ssl',
4989 lambda name: name.startswith('ALERT_DESCRIPTION_'),
4990 source=ssl._ssl,
4991 )
4992 enum._test_simple_enum(CheckedAlertDescription, ssl.AlertDescription)
4993
4994 def test_sslerrornumber(self):
4995 Checked_SSLMethod = enum._old_convert_(
4996 enum.IntEnum, '_SSLMethod', 'ssl',
4997 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4998 source=ssl._ssl,
4999 )
5000 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
5001
5002 def test_verifyflags(self):
5003 CheckedVerifyFlags = enum._old_convert_(
5004 enum.FlagEnum, 'VerifyFlags', 'ssl',
5005 lambda name: name.startswith('VERIFY_'),
5006 source=ssl._ssl,
5007 )
5008 enum._test_simple_enum(CheckedVerifyFlags, ssl.VerifyFlags)
5009
5010 def test_verifymode(self):
5011 CheckedVerifyMode = enum._old_convert_(
5012 enum.IntEnum, 'VerifyMode', 'ssl',
5013 lambda name: name.startswith('CERT_'),
5014 source=ssl._ssl,
5015 )
5016 enum._test_simple_enum(CheckedVerifyMode, ssl.VerifyMode)
5017
Thomas Woutersed03b412007-08-28 21:37:11 +00005018def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00005019 if support.verbose:
5020 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00005021 'Mac': platform.mac_ver,
5022 'Windows': platform.win32_ver,
5023 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04005024 for name, func in plats.items():
5025 plat = func()
5026 if plat and plat[0]:
5027 plat = '%s %r' % (name, plat)
5028 break
5029 else:
5030 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00005031 print("test_ssl: testing with %r %r" %
5032 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
5033 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00005034 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01005035 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
5036 try:
5037 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
5038 except AttributeError:
5039 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00005040
Antoine Pitrou152efa22010-05-16 18:19:27 +00005041 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00005042 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00005043 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01005044 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00005045 BADCERT, BADKEY, EMPTYCERT]:
5046 if not os.path.exists(filename):
5047 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005048
Martin Panter3840b2a2016-03-27 01:53:46 +00005049 tests = [
5050 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01005051 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02005052 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00005053 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00005054
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005055 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00005056 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00005057
Hai Shie80697d2020-05-28 06:10:27 +08005058 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00005059 try:
5060 support.run_unittest(*tests)
5061 finally:
Hai Shie80697d2020-05-28 06:10:27 +08005062 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00005063
5064if __name__ == "__main__":
5065 test_main()