blob: 06e501e3967849cfd11b484cd524a55df9d58717 [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
361 with self.assertRaisesRegex(
362 TypeError,
363 "cannot create '_ssl.Certificate' instances"
364 ):
365 _ssl.Certificate()
366
Christian Heimes9d50ab52018-02-27 10:17:30 +0100367 def test_private_init(self):
368 with self.assertRaisesRegex(TypeError, "public constructor"):
369 with socket.socket() as s:
370 ssl.SSLSocket(s)
371
Antoine Pitrou172f0252014-04-18 20:33:08 +0200372 def test_str_for_enums(self):
373 # Make sure that the PROTOCOL_* constants have enum-like string
374 # reprs.
Christian Heimes2875c602021-04-19 07:27:10 +0200375 proto = ssl.PROTOCOL_TLS_CLIENT
376 self.assertEqual(str(proto), 'PROTOCOL_TLS_CLIENT')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200377 ctx = ssl.SSLContext(proto)
378 self.assertIs(ctx.protocol, proto)
379
Antoine Pitrou480a1242010-04-28 21:37:09 +0000380 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000381 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000382 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000383 sys.stdout.write("\n RAND_status is %d (%s)\n"
384 % (v, (v and "sufficient randomness") or
385 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200386
Christian Heimes2875c602021-04-19 07:27:10 +0200387 with warnings_helper.check_warnings():
388 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200389 self.assertEqual(len(data), 16)
390 self.assertEqual(is_cryptographic, v == 1)
391 if v:
392 data = ssl.RAND_bytes(16)
393 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200394 else:
395 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200396
Victor Stinner1e81a392013-12-19 16:47:04 +0100397 # negative num is invalid
398 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
Christian Heimes2875c602021-04-19 07:27:10 +0200399 with warnings_helper.check_warnings():
400 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
Victor Stinner1e81a392013-12-19 16:47:04 +0100401
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000402 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200403 ssl.RAND_add(b"this is a random bytes object", 75.0)
404 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000405
Antoine Pitrou480a1242010-04-28 21:37:09 +0000406 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000407 # note that this uses an 'unofficial' function in _ssl.c,
408 # provided solely for this test, to exercise the certificate
409 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100410 self.assertEqual(
411 ssl._ssl._test_decode_cert(CERTFILE),
412 CERTFILE_INFO
413 )
414 self.assertEqual(
415 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
416 SIGNED_CERTFILE_INFO
417 )
418
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200419 # Issue #13034: the subjectAltName in some certificates
420 # (notably projects.developer.nokia.com:443) wasn't parsed
421 p = ssl._ssl._test_decode_cert(NOKIACERT)
422 if support.verbose:
423 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
424 self.assertEqual(p['subjectAltName'],
425 (('DNS', 'projects.developer.nokia.com'),
426 ('DNS', 'projects.forum.nokia.com'))
427 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100428 # extra OCSP and AIA fields
429 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
430 self.assertEqual(p['caIssuers'],
431 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
432 self.assertEqual(p['crlDistributionPoints'],
433 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000434
Christian Heimesa37f5242019-01-15 23:47:42 +0100435 def test_parse_cert_CVE_2019_5010(self):
436 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
437 if support.verbose:
438 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
439 self.assertEqual(
440 p,
441 {
442 'issuer': (
443 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
444 'notAfter': 'Jun 14 18:00:58 2028 GMT',
445 'notBefore': 'Jun 18 18:00:58 2018 GMT',
446 'serialNumber': '02',
447 'subject': ((('countryName', 'UK'),),
448 (('commonName',
449 'codenomicon-vm-2.test.lal.cisco.com'),)),
450 'subjectAltName': (
451 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
452 'version': 3
453 }
454 )
455
Christian Heimes824f7f32013-08-17 00:54:47 +0200456 def test_parse_cert_CVE_2013_4238(self):
457 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
458 if support.verbose:
459 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
460 subject = ((('countryName', 'US'),),
461 (('stateOrProvinceName', 'Oregon'),),
462 (('localityName', 'Beaverton'),),
463 (('organizationName', 'Python Software Foundation'),),
464 (('organizationalUnitName', 'Python Core Development'),),
465 (('commonName', 'null.python.org\x00example.org'),),
466 (('emailAddress', 'python-dev@python.org'),))
467 self.assertEqual(p['subject'], subject)
468 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200469 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
470 san = (('DNS', 'altnull.python.org\x00example.com'),
471 ('email', 'null@python.org\x00user@example.org'),
472 ('URI', 'http://null.python.org\x00http://example.org'),
473 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100474 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200475 else:
476 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
477 san = (('DNS', 'altnull.python.org\x00example.com'),
478 ('email', 'null@python.org\x00user@example.org'),
479 ('URI', 'http://null.python.org\x00http://example.org'),
480 ('IP Address', '192.0.2.1'),
481 ('IP Address', '<invalid>'))
482
483 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200484
Christian Heimes1c03abd2016-09-06 23:25:35 +0200485 def test_parse_all_sans(self):
486 p = ssl._ssl._test_decode_cert(ALLSANFILE)
487 self.assertEqual(p['subjectAltName'],
488 (
489 ('DNS', 'allsans'),
490 ('othername', '<unsupported>'),
491 ('othername', '<unsupported>'),
492 ('email', 'user@example.org'),
493 ('DNS', 'www.example.org'),
494 ('DirName',
495 ((('countryName', 'XY'),),
496 (('localityName', 'Castle Anthrax'),),
497 (('organizationName', 'Python Software Foundation'),),
498 (('commonName', 'dirname example'),))),
499 ('URI', 'https://www.python.org/'),
500 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100501 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200502 ('Registered ID', '1.2.3.4.5')
503 )
504 )
505
Antoine Pitrou480a1242010-04-28 21:37:09 +0000506 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000507 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000508 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000509 d1 = ssl.PEM_cert_to_DER_cert(pem)
510 p2 = ssl.DER_cert_to_PEM_cert(d1)
511 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000512 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000513 if not p2.startswith(ssl.PEM_HEADER + '\n'):
514 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
515 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
516 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000517
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000518 def test_openssl_version(self):
519 n = ssl.OPENSSL_VERSION_NUMBER
520 t = ssl.OPENSSL_VERSION_INFO
521 s = ssl.OPENSSL_VERSION
522 self.assertIsInstance(n, int)
523 self.assertIsInstance(t, tuple)
524 self.assertIsInstance(s, str)
525 # Some sanity checks follow
Christian Heimesd37b74f2021-04-19 08:31:29 +0200526 # >= 1.1.1
527 self.assertGreaterEqual(n, 0x10101000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100528 # < 4.0
529 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000530 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100531 self.assertGreaterEqual(major, 1)
532 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000533 self.assertGreaterEqual(minor, 0)
534 self.assertLess(minor, 256)
535 self.assertGreaterEqual(fix, 0)
536 self.assertLess(fix, 256)
537 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100538 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000539 self.assertGreaterEqual(status, 0)
540 self.assertLessEqual(status, 15)
Christian Heimesd37b74f2021-04-19 08:31:29 +0200541
542 libressl_ver = f"LibreSSL {major:d}"
543 openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}"
544 self.assertTrue(
545 s.startswith((openssl_ver, libressl_ver)),
546 (s, t, hex(n))
547 )
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000548
Antoine Pitrou9d543662010-04-23 23:10:32 +0000549 @support.cpython_only
550 def test_refcycle(self):
551 # Issue #7943: an SSL object doesn't create reference cycles with
552 # itself.
553 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200554 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000555 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800556 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100557 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100558 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000559
Antoine Pitroua468adc2010-09-14 14:43:44 +0000560 def test_wrapped_unconnected(self):
561 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200562 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000563 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200564 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100565 self.assertRaises(OSError, ss.recv, 1)
566 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
567 self.assertRaises(OSError, ss.recvfrom, 1)
568 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
569 self.assertRaises(OSError, ss.send, b'x')
570 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200571 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100572 self.assertRaises(NotImplementedError, ss.sendmsg,
573 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200574 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
575 self.assertRaises(NotImplementedError, ss.recvmsg_into,
576 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000577
Antoine Pitrou40f08742010-04-24 22:04:40 +0000578 def test_timeout(self):
579 # Issue #8524: when creating an SSL socket, the timeout of the
580 # original socket should be retained.
581 for timeout in (None, 0.0, 5.0):
582 s = socket.socket(socket.AF_INET)
583 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200584 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100585 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000586
Miss Islington (bot)4becc562021-06-13 05:07:00 -0700587 def test_openssl111_deprecations(self):
588 options = [
589 ssl.OP_NO_TLSv1,
590 ssl.OP_NO_TLSv1_1,
591 ssl.OP_NO_TLSv1_2,
592 ssl.OP_NO_TLSv1_3
593 ]
594 protocols = [
595 ssl.PROTOCOL_TLSv1,
596 ssl.PROTOCOL_TLSv1_1,
597 ssl.PROTOCOL_TLSv1_2,
598 ssl.PROTOCOL_TLS
599 ]
600 versions = [
601 ssl.TLSVersion.SSLv3,
602 ssl.TLSVersion.TLSv1,
603 ssl.TLSVersion.TLSv1_1,
604 ]
605
606 for option in options:
607 with self.subTest(option=option):
608 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
609 with self.assertWarns(DeprecationWarning) as cm:
610 ctx.options |= option
611 self.assertEqual(
Miss Islington (bot)08f2b9d2021-06-17 03:00:56 -0700612 'ssl.OP_NO_SSL*/ssl.OP_NO_TLS* options are deprecated',
Miss Islington (bot)4becc562021-06-13 05:07:00 -0700613 str(cm.warning)
614 )
615
616 for protocol in protocols:
617 with self.subTest(protocol=protocol):
618 with self.assertWarns(DeprecationWarning) as cm:
619 ssl.SSLContext(protocol)
620 self.assertEqual(
621 f'{protocol!r} is deprecated',
622 str(cm.warning)
623 )
624
625 for version in versions:
626 with self.subTest(version=version):
627 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
628 with self.assertWarns(DeprecationWarning) as cm:
629 ctx.minimum_version = version
630 self.assertEqual(
631 f'ssl.{version!r} is deprecated',
632 str(cm.warning)
633 )
634
Christian Heimes2875c602021-04-19 07:27:10 +0200635 @ignore_deprecation
Christian Heimesd0486372016-09-10 23:23:33 +0200636 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000637 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000638 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000639 "certfile must be specified",
640 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000641 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000642 "certfile must be specified for server-side operations",
643 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000644 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000645 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200646 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100647 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
648 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200649 s.connect, (HOST, 8080))
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, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000653 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200654 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000655 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000656 ssl.wrap_socket(sock,
657 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000658 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200659 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000660 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000661 ssl.wrap_socket(sock,
662 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000663 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000664
Martin Panter3464ea22016-02-01 21:58:11 +0000665 def bad_cert_test(self, certfile):
666 """Check that trying to use the given client certificate fails"""
667 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
668 certfile)
669 sock = socket.socket()
670 self.addCleanup(sock.close)
671 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200672 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200673 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000674
675 def test_empty_cert(self):
676 """Wrapping with an empty cert file"""
677 self.bad_cert_test("nullcert.pem")
678
679 def test_malformed_cert(self):
680 """Wrapping with a badly formatted certificate (syntax error)"""
681 self.bad_cert_test("badcert.pem")
682
683 def test_malformed_key(self):
684 """Wrapping with a badly formatted key (syntax error)"""
685 self.bad_cert_test("badkey.pem")
686
Christian Heimes2875c602021-04-19 07:27:10 +0200687 @ignore_deprecation
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000688 def test_match_hostname(self):
689 def ok(cert, hostname):
690 ssl.match_hostname(cert, hostname)
691 def fail(cert, hostname):
692 self.assertRaises(ssl.CertificateError,
693 ssl.match_hostname, cert, hostname)
694
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100695 # -- Hostname matching --
696
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000697 cert = {'subject': ((('commonName', 'example.com'),),)}
698 ok(cert, 'example.com')
699 ok(cert, 'ExAmple.cOm')
700 fail(cert, 'www.example.com')
701 fail(cert, '.example.com')
702 fail(cert, 'example.org')
703 fail(cert, 'exampleXcom')
704
705 cert = {'subject': ((('commonName', '*.a.com'),),)}
706 ok(cert, 'foo.a.com')
707 fail(cert, 'bar.foo.a.com')
708 fail(cert, 'a.com')
709 fail(cert, 'Xa.com')
710 fail(cert, '.a.com')
711
Mandeep Singhede2ac92017-11-27 04:01:27 +0530712 # only match wildcards when they are the only thing
713 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000714 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530715 fail(cert, 'foo.com')
716 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000717 fail(cert, 'bar.com')
718 fail(cert, 'foo.a.com')
719 fail(cert, 'bar.foo.com')
720
Christian Heimes824f7f32013-08-17 00:54:47 +0200721 # NULL bytes are bad, CVE-2013-4073
722 cert = {'subject': ((('commonName',
723 'null.python.org\x00example.org'),),)}
724 ok(cert, 'null.python.org\x00example.org') # or raise an error?
725 fail(cert, 'example.org')
726 fail(cert, 'null.python.org')
727
Georg Brandl72c98d32013-10-27 07:16:53 +0100728 # error cases with wildcards
729 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
730 fail(cert, 'bar.foo.a.com')
731 fail(cert, 'a.com')
732 fail(cert, 'Xa.com')
733 fail(cert, '.a.com')
734
735 cert = {'subject': ((('commonName', 'a.*.com'),),)}
736 fail(cert, 'a.foo.com')
737 fail(cert, 'a..com')
738 fail(cert, 'a.com')
739
740 # wildcard doesn't match IDNA prefix 'xn--'
741 idna = 'püthon.python.org'.encode("idna").decode("ascii")
742 cert = {'subject': ((('commonName', idna),),)}
743 ok(cert, idna)
744 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
745 fail(cert, idna)
746 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
747 fail(cert, idna)
748
749 # wildcard in first fragment and IDNA A-labels in sequent fragments
750 # are supported.
751 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
752 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530753 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
754 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100755 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
756 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
757
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000758 # Slightly fake real-world example
759 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
760 'subject': ((('commonName', 'linuxfrz.org'),),),
761 'subjectAltName': (('DNS', 'linuxfr.org'),
762 ('DNS', 'linuxfr.com'),
763 ('othername', '<unsupported>'))}
764 ok(cert, 'linuxfr.org')
765 ok(cert, 'linuxfr.com')
766 # Not a "DNS" entry
767 fail(cert, '<unsupported>')
768 # When there is a subjectAltName, commonName isn't used
769 fail(cert, 'linuxfrz.org')
770
771 # A pristine real-world example
772 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
773 'subject': ((('countryName', 'US'),),
774 (('stateOrProvinceName', 'California'),),
775 (('localityName', 'Mountain View'),),
776 (('organizationName', 'Google Inc'),),
777 (('commonName', 'mail.google.com'),))}
778 ok(cert, 'mail.google.com')
779 fail(cert, 'gmail.com')
780 # Only commonName is considered
781 fail(cert, 'California')
782
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100783 # -- IPv4 matching --
784 cert = {'subject': ((('commonName', 'example.com'),),),
785 'subjectAltName': (('DNS', 'example.com'),
786 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200787 ('IP Address', '14.15.16.17'),
788 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100789 ok(cert, '10.11.12.13')
790 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200791 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
792 fail(cert, '127.1')
793 fail(cert, '14.15.16.17 ')
794 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100795 fail(cert, '14.15.16.18')
796 fail(cert, 'example.net')
797
798 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300799 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100800 cert = {'subject': ((('commonName', 'example.com'),),),
801 'subjectAltName': (
802 ('DNS', 'example.com'),
803 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
804 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
805 ok(cert, '2001::cafe')
806 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200807 fail(cert, '2003::baba ')
808 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100809 fail(cert, '2003::bebe')
810 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100811
812 # -- Miscellaneous --
813
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000814 # Neither commonName nor subjectAltName
815 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
816 'subject': ((('countryName', 'US'),),
817 (('stateOrProvinceName', 'California'),),
818 (('localityName', 'Mountain View'),),
819 (('organizationName', 'Google Inc'),))}
820 fail(cert, 'mail.google.com')
821
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200822 # No DNS entry in subjectAltName but a commonName
823 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
824 'subject': ((('countryName', 'US'),),
825 (('stateOrProvinceName', 'California'),),
826 (('localityName', 'Mountain View'),),
827 (('commonName', 'mail.google.com'),)),
828 'subjectAltName': (('othername', 'blabla'), )}
829 ok(cert, 'mail.google.com')
830
831 # No DNS entry subjectAltName and no commonName
832 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
833 'subject': ((('countryName', 'US'),),
834 (('stateOrProvinceName', 'California'),),
835 (('localityName', 'Mountain View'),),
836 (('organizationName', 'Google Inc'),)),
837 'subjectAltName': (('othername', 'blabla'),)}
838 fail(cert, 'google.com')
839
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000840 # Empty cert / no cert
841 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
842 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
843
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200844 # Issue #17980: avoid denials of service by refusing more than one
845 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100846 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
847 with self.assertRaisesRegex(
848 ssl.CertificateError,
849 "partial wildcards in leftmost label are not supported"):
850 ssl.match_hostname(cert, 'axxb.example.com')
851
852 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
853 with self.assertRaisesRegex(
854 ssl.CertificateError,
855 "wildcard can only be present in the leftmost label"):
856 ssl.match_hostname(cert, 'www.sub.example.com')
857
858 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
859 with self.assertRaisesRegex(
860 ssl.CertificateError,
861 "too many wildcards"):
862 ssl.match_hostname(cert, 'axxbxxc.example.com')
863
864 cert = {'subject': ((('commonName', '*'),),)}
865 with self.assertRaisesRegex(
866 ssl.CertificateError,
867 "sole wildcard without additional labels are not support"):
868 ssl.match_hostname(cert, 'host')
869
870 cert = {'subject': ((('commonName', '*.com'),),)}
871 with self.assertRaisesRegex(
872 ssl.CertificateError,
873 r"hostname 'com' doesn't match '\*.com'"):
874 ssl.match_hostname(cert, 'com')
875
876 # extra checks for _inet_paton()
877 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
878 with self.assertRaises(ValueError):
879 ssl._inet_paton(invalid)
880 for ipaddr in ['127.0.0.1', '192.168.0.1']:
881 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300882 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100883 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
884 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200885
Antoine Pitroud5323212010-10-22 18:19:07 +0000886 def test_server_side(self):
887 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200888 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000889 with socket.socket() as sock:
890 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
891 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000892
Antoine Pitroud6494802011-07-21 01:11:30 +0200893 def test_unknown_channel_binding(self):
894 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200895 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200896 c = socket.socket(socket.AF_INET)
897 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200898 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100899 with self.assertRaises(ValueError):
900 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200901 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200902
903 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
904 "'tls-unique' channel binding not available")
905 def test_tls_unique_channel_binding(self):
906 # unconnected should return None for known type
907 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200908 with test_wrap_socket(s) 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 # the same for server-side
911 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200912 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100913 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200914
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600915 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200916 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600917 r = repr(ss)
918 with self.assertWarns(ResourceWarning) as cm:
919 ss = None
920 support.gc_collect()
921 self.assertIn(r, str(cm.warning.args[0]))
922
Christian Heimes6d7ad132013-06-09 18:02:55 +0200923 def test_get_default_verify_paths(self):
924 paths = ssl.get_default_verify_paths()
925 self.assertEqual(len(paths), 6)
926 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
927
Hai Shia7f5d932020-08-04 00:41:24 +0800928 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200929 env["SSL_CERT_DIR"] = CAPATH
930 env["SSL_CERT_FILE"] = CERTFILE
931 paths = ssl.get_default_verify_paths()
932 self.assertEqual(paths.cafile, CERTFILE)
933 self.assertEqual(paths.capath, CAPATH)
934
Christian Heimes44109d72013-11-22 01:51:30 +0100935 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
936 def test_enum_certificates(self):
937 self.assertTrue(ssl.enum_certificates("CA"))
938 self.assertTrue(ssl.enum_certificates("ROOT"))
939
940 self.assertRaises(TypeError, ssl.enum_certificates)
941 self.assertRaises(WindowsError, ssl.enum_certificates, "")
942
Christian Heimesc2d65e12013-11-22 16:13:55 +0100943 trust_oids = set()
944 for storename in ("CA", "ROOT"):
945 store = ssl.enum_certificates(storename)
946 self.assertIsInstance(store, list)
947 for element in store:
948 self.assertIsInstance(element, tuple)
949 self.assertEqual(len(element), 3)
950 cert, enc, trust = element
951 self.assertIsInstance(cert, bytes)
952 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200953 self.assertIsInstance(trust, (frozenset, set, bool))
954 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100955 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100956
957 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100958 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200959
Christian Heimes46bebee2013-06-09 19:03:31 +0200960 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100961 def test_enum_crls(self):
962 self.assertTrue(ssl.enum_crls("CA"))
963 self.assertRaises(TypeError, ssl.enum_crls)
964 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200965
Christian Heimes44109d72013-11-22 01:51:30 +0100966 crls = ssl.enum_crls("CA")
967 self.assertIsInstance(crls, list)
968 for element in crls:
969 self.assertIsInstance(element, tuple)
970 self.assertEqual(len(element), 2)
971 self.assertIsInstance(element[0], bytes)
972 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200973
Christian Heimes46bebee2013-06-09 19:03:31 +0200974
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100975 def test_asn1object(self):
976 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
977 '1.3.6.1.5.5.7.3.1')
978
979 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
980 self.assertEqual(val, expected)
981 self.assertEqual(val.nid, 129)
982 self.assertEqual(val.shortname, 'serverAuth')
983 self.assertEqual(val.longname, 'TLS Web Server Authentication')
984 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
985 self.assertIsInstance(val, ssl._ASN1Object)
986 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
987
988 val = ssl._ASN1Object.fromnid(129)
989 self.assertEqual(val, expected)
990 self.assertIsInstance(val, ssl._ASN1Object)
991 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100992 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
993 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100994 for i in range(1000):
995 try:
996 obj = ssl._ASN1Object.fromnid(i)
997 except ValueError:
998 pass
999 else:
1000 self.assertIsInstance(obj.nid, int)
1001 self.assertIsInstance(obj.shortname, str)
1002 self.assertIsInstance(obj.longname, str)
1003 self.assertIsInstance(obj.oid, (str, type(None)))
1004
1005 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
1006 self.assertEqual(val, expected)
1007 self.assertIsInstance(val, ssl._ASN1Object)
1008 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
1009 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
1010 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +01001011 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
1012 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001013
Christian Heimes72d28502013-11-23 13:56:58 +01001014 def test_purpose_enum(self):
1015 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
1016 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
1017 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
1018 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
1019 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
1020 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
1021 '1.3.6.1.5.5.7.3.1')
1022
1023 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
1024 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
1025 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
1026 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
1027 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
1028 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
1029 '1.3.6.1.5.5.7.3.2')
1030
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001031 def test_unsupported_dtls(self):
1032 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1033 self.addCleanup(s.close)
1034 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +02001035 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001036 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +02001037 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001038 with self.assertRaises(NotImplementedError) as cx:
1039 ctx.wrap_socket(s)
1040 self.assertEqual(str(cx.exception), "only stream sockets are supported")
1041
Antoine Pitrouc695c952014-04-28 20:57:36 +02001042 def cert_time_ok(self, timestring, timestamp):
1043 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
1044
1045 def cert_time_fail(self, timestring):
1046 with self.assertRaises(ValueError):
1047 ssl.cert_time_to_seconds(timestring)
1048
1049 @unittest.skipUnless(utc_offset(),
1050 'local time needs to be different from UTC')
1051 def test_cert_time_to_seconds_timezone(self):
1052 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
1053 # results if local timezone is not UTC
1054 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
1055 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
1056
1057 def test_cert_time_to_seconds(self):
1058 timestring = "Jan 5 09:34:43 2018 GMT"
1059 ts = 1515144883.0
1060 self.cert_time_ok(timestring, ts)
1061 # accept keyword parameter, assert its name
1062 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
1063 # accept both %e and %d (space or zero generated by strftime)
1064 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
1065 # case-insensitive
1066 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
1067 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
1068 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1069 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1070 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1071 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1072 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1073 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1074
1075 newyear_ts = 1230768000.0
1076 # leap seconds
1077 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1078 # same timestamp
1079 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1080
1081 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1082 # allow 60th second (even if it is not a leap second)
1083 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1084 # allow 2nd leap second for compatibility with time.strptime()
1085 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1086 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1087
Mike53f7a7c2017-12-14 14:04:53 +03001088 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001089 # 99991231235959Z (rfc 5280)
1090 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1091
1092 @support.run_with_locale('LC_ALL', '')
1093 def test_cert_time_to_seconds_locale(self):
1094 # `cert_time_to_seconds()` should be locale independent
1095
1096 def local_february_name():
1097 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1098
1099 if local_february_name().lower() == 'feb':
1100 self.skipTest("locale-specific month name needs to be "
1101 "different from C locale")
1102
1103 # locale-independent
1104 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1105 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1106
Martin Panter3840b2a2016-03-27 01:53:46 +00001107 def test_connect_ex_error(self):
1108 server = socket.socket(socket.AF_INET)
1109 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001110 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001111 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001112 cert_reqs=ssl.CERT_REQUIRED)
1113 self.addCleanup(s.close)
1114 rc = s.connect_ex((HOST, port))
1115 # Issue #19919: Windows machines or VMs hosted on Windows
1116 # machines sometimes return EWOULDBLOCK.
1117 errors = (
1118 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1119 errno.EWOULDBLOCK,
1120 )
1121 self.assertIn(rc, errors)
1122
Christian Heimes89d15502021-04-19 06:55:30 +02001123 def test_read_write_zero(self):
1124 # empty reads and writes now work, bpo-42854, bpo-31711
1125 client_context, server_context, hostname = testing_context()
1126 server = ThreadedEchoServer(context=server_context)
1127 with server:
1128 with client_context.wrap_socket(socket.socket(),
1129 server_hostname=hostname) as s:
1130 s.connect((HOST, server.port))
1131 self.assertEqual(s.recv(0), b"")
1132 self.assertEqual(s.send(b""), 0)
1133
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001134
Antoine Pitrou152efa22010-05-16 18:19:27 +00001135class ContextTests(unittest.TestCase):
1136
1137 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001138 for protocol in PROTOCOLS:
Christian Heimes2875c602021-04-19 07:27:10 +02001139 with warnings_helper.check_warnings():
1140 ctx = ssl.SSLContext(protocol)
1141 self.assertEqual(ctx.protocol, protocol)
1142 with warnings_helper.check_warnings():
1143 ctx = ssl.SSLContext()
Christian Heimes598894f2016-09-05 23:19:05 +02001144 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001145 self.assertRaises(ValueError, ssl.SSLContext, -1)
1146 self.assertRaises(ValueError, ssl.SSLContext, 42)
1147
Antoine Pitrou152efa22010-05-16 18:19:27 +00001148 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001149 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001150 ctx.set_ciphers("ALL")
1151 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001152 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001153 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001154
Christian Heimes892d66e2018-01-29 14:10:18 +01001155 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1156 "Test applies only to Python default ciphers")
1157 def test_python_ciphers(self):
1158 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1159 ciphers = ctx.get_ciphers()
1160 for suite in ciphers:
1161 name = suite['name']
1162 self.assertNotIn("PSK", name)
1163 self.assertNotIn("SRP", name)
1164 self.assertNotIn("MD5", name)
1165 self.assertNotIn("RC4", name)
1166 self.assertNotIn("3DES", name)
1167
Christian Heimes25bfcd52016-09-06 00:04:45 +02001168 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001169 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001170 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001171 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001172 self.assertIn('AES256-GCM-SHA384', names)
1173 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001174
Antoine Pitroub5218772010-05-21 09:56:06 +00001175 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001176 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001177 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001178 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001179 # SSLContext also enables these by default
1180 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001181 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001182 OP_ENABLE_MIDDLEBOX_COMPAT |
1183 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001184 self.assertEqual(default, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001185 with warnings_helper.check_warnings():
1186 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001187 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001188 with warnings_helper.check_warnings():
1189 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
Christian Heimes39258d32021-04-17 11:36:35 +02001190 self.assertEqual(default, ctx.options)
1191 ctx.options = 0
1192 # Ubuntu has OP_NO_SSLv3 forced on by default
1193 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001194
Christian Heimesa170fa12017-09-15 20:27:30 +02001195 def test_verify_mode_protocol(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001196 with warnings_helper.check_warnings():
1197 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001198 # Default value
1199 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1200 ctx.verify_mode = ssl.CERT_OPTIONAL
1201 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1202 ctx.verify_mode = ssl.CERT_REQUIRED
1203 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1204 ctx.verify_mode = ssl.CERT_NONE
1205 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1206 with self.assertRaises(TypeError):
1207 ctx.verify_mode = None
1208 with self.assertRaises(ValueError):
1209 ctx.verify_mode = 42
1210
Christian Heimesa170fa12017-09-15 20:27:30 +02001211 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1212 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1213 self.assertFalse(ctx.check_hostname)
1214
1215 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1216 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1217 self.assertTrue(ctx.check_hostname)
1218
Christian Heimes61d478c2018-01-27 15:51:38 +01001219 def test_hostname_checks_common_name(self):
1220 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1221 self.assertTrue(ctx.hostname_checks_common_name)
1222 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1223 ctx.hostname_checks_common_name = True
1224 self.assertTrue(ctx.hostname_checks_common_name)
1225 ctx.hostname_checks_common_name = False
1226 self.assertFalse(ctx.hostname_checks_common_name)
1227 ctx.hostname_checks_common_name = True
1228 self.assertTrue(ctx.hostname_checks_common_name)
1229 else:
1230 with self.assertRaises(AttributeError):
1231 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001232
Christian Heimes2875c602021-04-19 07:27:10 +02001233 @ignore_deprecation
Christian Heimes698dde12018-02-27 11:54:43 +01001234 def test_min_max_version(self):
1235 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001236 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1237 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001238 minimum_range = {
1239 # stock OpenSSL
1240 ssl.TLSVersion.MINIMUM_SUPPORTED,
1241 # Fedora 29 uses TLS 1.0 by default
1242 ssl.TLSVersion.TLSv1,
1243 # RHEL 8 uses TLS 1.2 by default
1244 ssl.TLSVersion.TLSv1_2
1245 }
torsava34864d12019-12-02 17:15:42 +01001246 maximum_range = {
1247 # stock OpenSSL
1248 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1249 # Fedora 32 uses TLS 1.3 by default
1250 ssl.TLSVersion.TLSv1_3
1251 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001252
Christian Heimes34de2d32019-01-18 16:09:30 +01001253 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001254 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001255 )
torsava34864d12019-12-02 17:15:42 +01001256 self.assertIn(
1257 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001258 )
1259
1260 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1261 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1262 self.assertEqual(
1263 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1264 )
1265 self.assertEqual(
1266 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1267 )
1268
1269 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1270 ctx.maximum_version = ssl.TLSVersion.TLSv1
1271 self.assertEqual(
1272 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1273 )
1274 self.assertEqual(
1275 ctx.maximum_version, ssl.TLSVersion.TLSv1
1276 )
1277
1278 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1279 self.assertEqual(
1280 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1281 )
1282
1283 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1284 self.assertIn(
1285 ctx.maximum_version,
1286 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1287 )
1288
1289 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1290 self.assertIn(
1291 ctx.minimum_version,
1292 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1293 )
1294
1295 with self.assertRaises(ValueError):
1296 ctx.minimum_version = 42
1297
1298 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1299
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001300 self.assertIn(
1301 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001302 )
1303 self.assertEqual(
1304 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1305 )
1306 with self.assertRaises(ValueError):
1307 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1308 with self.assertRaises(ValueError):
1309 ctx.maximum_version = ssl.TLSVersion.TLSv1
1310
1311
matthewhughes9348e836bb2020-07-17 09:59:15 +01001312 @unittest.skipUnless(
1313 hasattr(ssl.SSLContext, 'security_level'),
1314 "requires OpenSSL >= 1.1.0"
1315 )
1316 def test_security_level(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001317 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
matthewhughes9348e836bb2020-07-17 09:59:15 +01001318 # The default security callback allows for levels between 0-5
1319 # with OpenSSL defaulting to 1, however some vendors override the
1320 # default value (e.g. Debian defaults to 2)
1321 security_level_range = {
1322 0,
1323 1, # OpenSSL default
1324 2, # Debian
1325 3,
1326 4,
1327 5,
1328 }
1329 self.assertIn(ctx.security_level, security_level_range)
1330
Christian Heimes22587792013-11-21 23:56:13 +01001331 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001332 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001333 # default value
1334 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1335 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001336 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1337 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1338 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1339 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1340 ctx.verify_flags = ssl.VERIFY_DEFAULT
1341 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001342 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1343 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001344 # supports any value
1345 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1346 self.assertEqual(ctx.verify_flags,
1347 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1348 with self.assertRaises(TypeError):
1349 ctx.verify_flags = None
1350
Antoine Pitrou152efa22010-05-16 18:19:27 +00001351 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001352 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001353 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001354 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001355 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1356 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001357 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001358 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001359 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001360 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001361 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001362 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001363 ctx.load_cert_chain(EMPTYCERT)
1364 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001365 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001366 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1367 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1368 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_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(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001371 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001372 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001373 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001374 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1375 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001376 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001377 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001378 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001379 # Password protected key and cert
1380 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1381 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1382 ctx.load_cert_chain(CERTFILE_PROTECTED,
1383 password=bytearray(KEY_PASSWORD.encode()))
1384 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1385 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1386 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1387 bytearray(KEY_PASSWORD.encode()))
1388 with self.assertRaisesRegex(TypeError, "should be a string"):
1389 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1390 with self.assertRaises(ssl.SSLError):
1391 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1392 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1393 # openssl has a fixed limit on the password buffer.
1394 # PEM_BUFSIZE is generally set to 1kb.
1395 # Return a string larger than this.
1396 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1397 # Password callback
1398 def getpass_unicode():
1399 return KEY_PASSWORD
1400 def getpass_bytes():
1401 return KEY_PASSWORD.encode()
1402 def getpass_bytearray():
1403 return bytearray(KEY_PASSWORD.encode())
1404 def getpass_badpass():
1405 return "badpass"
1406 def getpass_huge():
1407 return b'a' * (1024 * 1024)
1408 def getpass_bad_type():
1409 return 9
1410 def getpass_exception():
1411 raise Exception('getpass error')
1412 class GetPassCallable:
1413 def __call__(self):
1414 return KEY_PASSWORD
1415 def getpass(self):
1416 return KEY_PASSWORD
1417 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1418 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1419 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1420 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1421 ctx.load_cert_chain(CERTFILE_PROTECTED,
1422 password=GetPassCallable().getpass)
1423 with self.assertRaises(ssl.SSLError):
1424 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1425 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1426 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1427 with self.assertRaisesRegex(TypeError, "must return a string"):
1428 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1429 with self.assertRaisesRegex(Exception, "getpass error"):
1430 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1431 # Make sure the password function isn't called if it isn't needed
1432 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001433
1434 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001435 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001436 ctx.load_verify_locations(CERTFILE)
1437 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1438 ctx.load_verify_locations(BYTES_CERTFILE)
1439 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1440 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001441 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001442 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001443 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001444 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001445 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001446 ctx.load_verify_locations(BADCERT)
1447 ctx.load_verify_locations(CERTFILE, CAPATH)
1448 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1449
Victor Stinner80f75e62011-01-29 11:31:20 +00001450 # Issue #10989: crash if the second argument type is invalid
1451 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1452
Christian Heimesefff7062013-11-21 03:35:02 +01001453 def test_load_verify_cadata(self):
1454 # test cadata
1455 with open(CAFILE_CACERT) as f:
1456 cacert_pem = f.read()
1457 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1458 with open(CAFILE_NEURONIO) as f:
1459 neuronio_pem = f.read()
1460 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1461
1462 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001463 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001464 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1465 ctx.load_verify_locations(cadata=cacert_pem)
1466 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1467 ctx.load_verify_locations(cadata=neuronio_pem)
1468 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1469 # cert already in hash table
1470 ctx.load_verify_locations(cadata=neuronio_pem)
1471 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1472
1473 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001474 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001475 combined = "\n".join((cacert_pem, neuronio_pem))
1476 ctx.load_verify_locations(cadata=combined)
1477 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1478
1479 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001480 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001481 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1482 neuronio_pem, "tail"]
1483 ctx.load_verify_locations(cadata="\n".join(combined))
1484 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1485
1486 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001487 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001488 ctx.load_verify_locations(cadata=cacert_der)
1489 ctx.load_verify_locations(cadata=neuronio_der)
1490 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1491 # cert already in hash table
1492 ctx.load_verify_locations(cadata=cacert_der)
1493 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1494
1495 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001496 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001497 combined = b"".join((cacert_der, neuronio_der))
1498 ctx.load_verify_locations(cadata=combined)
1499 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1500
1501 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001502 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001503 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1504
Christian Heimesb9ad88b2021-04-23 13:51:40 +02001505 with self.assertRaisesRegex(
1506 ssl.SSLError,
1507 "no start line: cadata does not contain a certificate"
1508 ):
Christian Heimesefff7062013-11-21 03:35:02 +01001509 ctx.load_verify_locations(cadata="broken")
Christian Heimesb9ad88b2021-04-23 13:51:40 +02001510 with self.assertRaisesRegex(
1511 ssl.SSLError,
1512 "not enough data: cadata does not contain a certificate"
1513 ):
Christian Heimesefff7062013-11-21 03:35:02 +01001514 ctx.load_verify_locations(cadata=b"broken")
1515
Paul Monsonf3550692019-06-19 13:09:54 -07001516 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001517 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001518 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001519 ctx.load_dh_params(DHFILE)
1520 if os.name != 'nt':
1521 ctx.load_dh_params(BYTES_DHFILE)
1522 self.assertRaises(TypeError, ctx.load_dh_params)
1523 self.assertRaises(TypeError, ctx.load_dh_params, None)
1524 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001525 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001526 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001527 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001528 ctx.load_dh_params(CERTFILE)
1529
Antoine Pitroub0182c82010-10-12 20:09:02 +00001530 def test_session_stats(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001531 for proto in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
Antoine Pitroub0182c82010-10-12 20:09:02 +00001532 ctx = ssl.SSLContext(proto)
1533 self.assertEqual(ctx.session_stats(), {
1534 'number': 0,
1535 'connect': 0,
1536 'connect_good': 0,
1537 'connect_renegotiate': 0,
1538 'accept': 0,
1539 'accept_good': 0,
1540 'accept_renegotiate': 0,
1541 'hits': 0,
1542 'misses': 0,
1543 'timeouts': 0,
1544 'cache_full': 0,
1545 })
1546
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001547 def test_set_default_verify_paths(self):
1548 # There's not much we can do to test that it acts as expected,
1549 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001550 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001551 ctx.set_default_verify_paths()
1552
Antoine Pitrou501da612011-12-21 09:27:41 +01001553 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001554 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001555 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001556 ctx.set_ecdh_curve("prime256v1")
1557 ctx.set_ecdh_curve(b"prime256v1")
1558 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1559 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1560 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1561 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1562
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001563 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001564 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001565
1566 # set_servername_callback expects a callable, or None
1567 self.assertRaises(TypeError, ctx.set_servername_callback)
1568 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1569 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1570 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1571
1572 def dummycallback(sock, servername, ctx):
1573 pass
1574 ctx.set_servername_callback(None)
1575 ctx.set_servername_callback(dummycallback)
1576
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001577 def test_sni_callback_refcycle(self):
1578 # Reference cycles through the servername callback are detected
1579 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001580 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001581 def dummycallback(sock, servername, ctx, cycle=ctx):
1582 pass
1583 ctx.set_servername_callback(dummycallback)
1584 wr = weakref.ref(ctx)
1585 del ctx, dummycallback
1586 gc.collect()
1587 self.assertIs(wr(), None)
1588
Christian Heimes9a5395a2013-06-17 15:44:12 +02001589 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001590 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001591 self.assertEqual(ctx.cert_store_stats(),
1592 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1593 ctx.load_cert_chain(CERTFILE)
1594 self.assertEqual(ctx.cert_store_stats(),
1595 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1596 ctx.load_verify_locations(CERTFILE)
1597 self.assertEqual(ctx.cert_store_stats(),
1598 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001599 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001600 self.assertEqual(ctx.cert_store_stats(),
1601 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1602
1603 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001604 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001605 self.assertEqual(ctx.get_ca_certs(), [])
1606 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1607 ctx.load_verify_locations(CERTFILE)
1608 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001609 # but CAFILE_CACERT is a CA cert
1610 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001611 self.assertEqual(ctx.get_ca_certs(),
1612 [{'issuer': ((('organizationName', 'Root CA'),),
1613 (('organizationalUnitName', 'http://www.cacert.org'),),
1614 (('commonName', 'CA Cert Signing Authority'),),
1615 (('emailAddress', 'support@cacert.org'),)),
Christian Heimesd37b74f2021-04-19 08:31:29 +02001616 'notAfter': 'Mar 29 12:29:49 2033 GMT',
1617 'notBefore': 'Mar 30 12:29:49 2003 GMT',
Christian Heimes9a5395a2013-06-17 15:44:12 +02001618 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001619 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001620 'subject': ((('organizationName', 'Root CA'),),
1621 (('organizationalUnitName', 'http://www.cacert.org'),),
1622 (('commonName', 'CA Cert Signing Authority'),),
1623 (('emailAddress', 'support@cacert.org'),)),
1624 'version': 3}])
1625
Martin Panterb55f8b72016-01-14 12:53:56 +00001626 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001627 pem = f.read()
1628 der = ssl.PEM_cert_to_DER_cert(pem)
1629 self.assertEqual(ctx.get_ca_certs(True), [der])
1630
Christian Heimes72d28502013-11-23 13:56:58 +01001631 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001632 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001633 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.SERVER_AUTH)
1637 ctx.load_default_certs()
1638
Christian Heimesa170fa12017-09-15 20:27:30 +02001639 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001640 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1641
Christian Heimesa170fa12017-09-15 20:27:30 +02001642 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001643 self.assertRaises(TypeError, ctx.load_default_certs, None)
1644 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1645
Benjamin Peterson91244e02014-10-03 18:17:15 -04001646 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001647 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001648 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001649 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001650 env["SSL_CERT_DIR"] = CAPATH
1651 env["SSL_CERT_FILE"] = CERTFILE
1652 ctx.load_default_certs()
1653 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1654
Benjamin Peterson91244e02014-10-03 18:17:15 -04001655 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001656 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001657 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001658 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001659 ctx.load_default_certs()
1660 stats = ctx.cert_store_stats()
1661
Christian Heimesa170fa12017-09-15 20:27:30 +02001662 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001663 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001664 env["SSL_CERT_DIR"] = CAPATH
1665 env["SSL_CERT_FILE"] = CERTFILE
1666 ctx.load_default_certs()
1667 stats["x509"] += 1
1668 self.assertEqual(ctx.cert_store_stats(), stats)
1669
Christian Heimes358cfd42016-09-10 22:43:48 +02001670 def _assert_context_options(self, ctx):
1671 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1672 if OP_NO_COMPRESSION != 0:
1673 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1674 OP_NO_COMPRESSION)
1675 if OP_SINGLE_DH_USE != 0:
1676 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1677 OP_SINGLE_DH_USE)
1678 if OP_SINGLE_ECDH_USE != 0:
1679 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1680 OP_SINGLE_ECDH_USE)
1681 if OP_CIPHER_SERVER_PREFERENCE != 0:
1682 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1683 OP_CIPHER_SERVER_PREFERENCE)
1684
Christian Heimes4c05b472013-11-23 15:58:30 +01001685 def test_create_default_context(self):
1686 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001687
Christian Heimes2875c602021-04-19 07:27:10 +02001688 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001689 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001690 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001691 self._assert_context_options(ctx)
1692
Christian Heimes4c05b472013-11-23 15:58:30 +01001693 with open(SIGNING_CA) as f:
1694 cadata = f.read()
1695 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1696 cadata=cadata)
Christian Heimes2875c602021-04-19 07:27:10 +02001697 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001698 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001699 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001700
1701 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001702 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes4c05b472013-11-23 15:58:30 +01001703 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001704 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001705
Christian Heimes2875c602021-04-19 07:27:10 +02001706
1707
Christian Heimes67986f92013-11-23 22:43:47 +01001708 def test__create_stdlib_context(self):
1709 ctx = ssl._create_stdlib_context()
Christian Heimes2875c602021-04-19 07:27:10 +02001710 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes67986f92013-11-23 22:43:47 +01001711 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001712 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001713 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001714
Christian Heimes2875c602021-04-19 07:27:10 +02001715 with warnings_helper.check_warnings():
1716 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
Christian Heimes67986f92013-11-23 22:43:47 +01001717 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1718 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001719 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001720
Christian Heimes2875c602021-04-19 07:27:10 +02001721 with warnings_helper.check_warnings():
1722 ctx = ssl._create_stdlib_context(
1723 ssl.PROTOCOL_TLSv1_2,
1724 cert_reqs=ssl.CERT_REQUIRED,
1725 check_hostname=True
1726 )
1727 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
Christian Heimes67986f92013-11-23 22:43:47 +01001728 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001729 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001730 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001731
1732 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001733 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes67986f92013-11-23 22:43:47 +01001734 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001735 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001736
Christian Heimes1aa9a752013-12-02 02:41:19 +01001737 def test_check_hostname(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001738 with warnings_helper.check_warnings():
1739 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001740 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001741 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001742
Christian Heimese82c0342017-09-15 20:29:57 +02001743 # Auto set CERT_REQUIRED
1744 ctx.check_hostname = True
1745 self.assertTrue(ctx.check_hostname)
1746 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1747 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001748 ctx.verify_mode = ssl.CERT_REQUIRED
1749 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001750 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001751
Christian Heimese82c0342017-09-15 20:29:57 +02001752 # Changing verify_mode does not affect check_hostname
1753 ctx.check_hostname = False
1754 ctx.verify_mode = ssl.CERT_NONE
1755 ctx.check_hostname = False
1756 self.assertFalse(ctx.check_hostname)
1757 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1758 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001759 ctx.check_hostname = True
1760 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001761 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1762
1763 ctx.check_hostname = False
1764 ctx.verify_mode = ssl.CERT_OPTIONAL
1765 ctx.check_hostname = False
1766 self.assertFalse(ctx.check_hostname)
1767 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1768 # keep CERT_OPTIONAL
1769 ctx.check_hostname = True
1770 self.assertTrue(ctx.check_hostname)
1771 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001772
1773 # Cannot set CERT_NONE with check_hostname enabled
1774 with self.assertRaises(ValueError):
1775 ctx.verify_mode = ssl.CERT_NONE
1776 ctx.check_hostname = False
1777 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001778 ctx.verify_mode = ssl.CERT_NONE
1779 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001780
Christian Heimes5fe668c2016-09-12 00:01:11 +02001781 def test_context_client_server(self):
1782 # PROTOCOL_TLS_CLIENT has sane defaults
1783 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1784 self.assertTrue(ctx.check_hostname)
1785 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1786
1787 # PROTOCOL_TLS_SERVER has different but also sane defaults
1788 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1789 self.assertFalse(ctx.check_hostname)
1790 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1791
Christian Heimes4df60f12017-09-15 20:26:05 +02001792 def test_context_custom_class(self):
1793 class MySSLSocket(ssl.SSLSocket):
1794 pass
1795
1796 class MySSLObject(ssl.SSLObject):
1797 pass
1798
1799 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1800 ctx.sslsocket_class = MySSLSocket
1801 ctx.sslobject_class = MySSLObject
1802
1803 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1804 self.assertIsInstance(sock, MySSLSocket)
Miss Islington (bot)d7930fb2021-06-11 00:36:17 -07001805 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(), server_side=True)
Christian Heimes4df60f12017-09-15 20:26:05 +02001806 self.assertIsInstance(obj, MySSLObject)
1807
Christian Heimes78c7d522019-06-03 21:00:10 +02001808 def test_num_tickest(self):
1809 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1810 self.assertEqual(ctx.num_tickets, 2)
1811 ctx.num_tickets = 1
1812 self.assertEqual(ctx.num_tickets, 1)
1813 ctx.num_tickets = 0
1814 self.assertEqual(ctx.num_tickets, 0)
1815 with self.assertRaises(ValueError):
1816 ctx.num_tickets = -1
1817 with self.assertRaises(TypeError):
1818 ctx.num_tickets = None
1819
1820 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1821 self.assertEqual(ctx.num_tickets, 2)
1822 with self.assertRaises(ValueError):
1823 ctx.num_tickets = 1
1824
Antoine Pitrou152efa22010-05-16 18:19:27 +00001825
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001826class SSLErrorTests(unittest.TestCase):
1827
1828 def test_str(self):
1829 # The str() of a SSLError doesn't include the errno
1830 e = ssl.SSLError(1, "foo")
1831 self.assertEqual(str(e), "foo")
1832 self.assertEqual(e.errno, 1)
1833 # Same for a subclass
1834 e = ssl.SSLZeroReturnError(1, "foo")
1835 self.assertEqual(str(e), "foo")
1836 self.assertEqual(e.errno, 1)
1837
Paul Monsonf3550692019-06-19 13:09:54 -07001838 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001839 def test_lib_reason(self):
1840 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001841 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001842 with self.assertRaises(ssl.SSLError) as cm:
1843 ctx.load_dh_params(CERTFILE)
1844 self.assertEqual(cm.exception.library, 'PEM')
1845 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1846 s = str(cm.exception)
1847 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1848
1849 def test_subclass(self):
1850 # Check that the appropriate SSLError subclass is raised
1851 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001852 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1853 ctx.check_hostname = False
1854 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001855 with socket.create_server(("127.0.0.1", 0)) as s:
1856 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001857 c.setblocking(False)
1858 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001859 with self.assertRaises(ssl.SSLWantReadError) as cm:
1860 c.do_handshake()
1861 s = str(cm.exception)
1862 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1863 # For compatibility
1864 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1865
1866
Christian Heimes61d478c2018-01-27 15:51:38 +01001867 def test_bad_server_hostname(self):
1868 ctx = ssl.create_default_context()
1869 with self.assertRaises(ValueError):
1870 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1871 server_hostname="")
1872 with self.assertRaises(ValueError):
1873 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1874 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001875 with self.assertRaises(TypeError):
1876 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1877 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001878
1879
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001880class MemoryBIOTests(unittest.TestCase):
1881
1882 def test_read_write(self):
1883 bio = ssl.MemoryBIO()
1884 bio.write(b'foo')
1885 self.assertEqual(bio.read(), b'foo')
1886 self.assertEqual(bio.read(), b'')
1887 bio.write(b'foo')
1888 bio.write(b'bar')
1889 self.assertEqual(bio.read(), b'foobar')
1890 self.assertEqual(bio.read(), b'')
1891 bio.write(b'baz')
1892 self.assertEqual(bio.read(2), b'ba')
1893 self.assertEqual(bio.read(1), b'z')
1894 self.assertEqual(bio.read(1), b'')
1895
1896 def test_eof(self):
1897 bio = ssl.MemoryBIO()
1898 self.assertFalse(bio.eof)
1899 self.assertEqual(bio.read(), b'')
1900 self.assertFalse(bio.eof)
1901 bio.write(b'foo')
1902 self.assertFalse(bio.eof)
1903 bio.write_eof()
1904 self.assertFalse(bio.eof)
1905 self.assertEqual(bio.read(2), b'fo')
1906 self.assertFalse(bio.eof)
1907 self.assertEqual(bio.read(1), b'o')
1908 self.assertTrue(bio.eof)
1909 self.assertEqual(bio.read(), b'')
1910 self.assertTrue(bio.eof)
1911
1912 def test_pending(self):
1913 bio = ssl.MemoryBIO()
1914 self.assertEqual(bio.pending, 0)
1915 bio.write(b'foo')
1916 self.assertEqual(bio.pending, 3)
1917 for i in range(3):
1918 bio.read(1)
1919 self.assertEqual(bio.pending, 3-i-1)
1920 for i in range(3):
1921 bio.write(b'x')
1922 self.assertEqual(bio.pending, i+1)
1923 bio.read()
1924 self.assertEqual(bio.pending, 0)
1925
1926 def test_buffer_types(self):
1927 bio = ssl.MemoryBIO()
1928 bio.write(b'foo')
1929 self.assertEqual(bio.read(), b'foo')
1930 bio.write(bytearray(b'bar'))
1931 self.assertEqual(bio.read(), b'bar')
1932 bio.write(memoryview(b'baz'))
1933 self.assertEqual(bio.read(), b'baz')
1934
1935 def test_error_types(self):
1936 bio = ssl.MemoryBIO()
1937 self.assertRaises(TypeError, bio.write, 'foo')
1938 self.assertRaises(TypeError, bio.write, None)
1939 self.assertRaises(TypeError, bio.write, True)
1940 self.assertRaises(TypeError, bio.write, 1)
1941
1942
Christian Heimes9d50ab52018-02-27 10:17:30 +01001943class SSLObjectTests(unittest.TestCase):
1944 def test_private_init(self):
1945 bio = ssl.MemoryBIO()
1946 with self.assertRaisesRegex(TypeError, "public constructor"):
1947 ssl.SSLObject(bio, bio)
1948
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001949 def test_unwrap(self):
1950 client_ctx, server_ctx, hostname = testing_context()
1951 c_in = ssl.MemoryBIO()
1952 c_out = ssl.MemoryBIO()
1953 s_in = ssl.MemoryBIO()
1954 s_out = ssl.MemoryBIO()
1955 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1956 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1957
1958 # Loop on the handshake for a bit to get it settled
1959 for _ in range(5):
1960 try:
1961 client.do_handshake()
1962 except ssl.SSLWantReadError:
1963 pass
1964 if c_out.pending:
1965 s_in.write(c_out.read())
1966 try:
1967 server.do_handshake()
1968 except ssl.SSLWantReadError:
1969 pass
1970 if s_out.pending:
1971 c_in.write(s_out.read())
1972 # Now the handshakes should be complete (don't raise WantReadError)
1973 client.do_handshake()
1974 server.do_handshake()
1975
1976 # Now if we unwrap one side unilaterally, it should send close-notify
1977 # and raise WantReadError:
1978 with self.assertRaises(ssl.SSLWantReadError):
1979 client.unwrap()
1980
1981 # But server.unwrap() does not raise, because it reads the client's
1982 # close-notify:
1983 s_in.write(c_out.read())
1984 server.unwrap()
1985
1986 # And now that the client gets the server's close-notify, it doesn't
1987 # raise either.
1988 c_in.write(s_out.read())
1989 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001990
Martin Panter3840b2a2016-03-27 01:53:46 +00001991class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001992 """Tests that connect to a simple server running in the background"""
1993
1994 def setUp(self):
juhovh49fdf112021-04-18 21:11:48 +10001995 self.server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1996 self.server_context.load_cert_chain(SIGNED_CERTFILE)
1997 server = ThreadedEchoServer(context=self.server_context)
Martin Panter3840b2a2016-03-27 01:53:46 +00001998 self.server_addr = (HOST, server.port)
1999 server.__enter__()
2000 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002001
Antoine Pitrou480a1242010-04-28 21:37:09 +00002002 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002003 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002004 cert_reqs=ssl.CERT_NONE) as s:
2005 s.connect(self.server_addr)
2006 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02002007 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00002008
Martin Panter3840b2a2016-03-27 01:53:46 +00002009 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02002010 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002011 cert_reqs=ssl.CERT_REQUIRED,
2012 ca_certs=SIGNING_CA) as s:
2013 s.connect(self.server_addr)
2014 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02002015 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002016
Martin Panter3840b2a2016-03-27 01:53:46 +00002017 def test_connect_fail(self):
2018 # This should fail because we have no verification certs. Connection
2019 # failure crashes ThreadedEchoServer, so run this in an independent
2020 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02002021 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002022 cert_reqs=ssl.CERT_REQUIRED)
2023 self.addCleanup(s.close)
2024 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2025 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002026
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002027 def test_connect_ex(self):
2028 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02002029 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002030 cert_reqs=ssl.CERT_REQUIRED,
2031 ca_certs=SIGNING_CA)
2032 self.addCleanup(s.close)
2033 self.assertEqual(0, s.connect_ex(self.server_addr))
2034 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002035
2036 def test_non_blocking_connect_ex(self):
2037 # Issue #11326: non-blocking connect_ex() should allow handshake
2038 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02002039 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002040 cert_reqs=ssl.CERT_REQUIRED,
2041 ca_certs=SIGNING_CA,
2042 do_handshake_on_connect=False)
2043 self.addCleanup(s.close)
2044 s.setblocking(False)
2045 rc = s.connect_ex(self.server_addr)
2046 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2047 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2048 # Wait for connect to finish
2049 select.select([], [s], [], 5.0)
2050 # Non-blocking handshake
2051 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002052 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002053 s.do_handshake()
2054 break
2055 except ssl.SSLWantReadError:
2056 select.select([s], [], [], 5.0)
2057 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002058 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002059 # SSL established
2060 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002061
Antoine Pitrou152efa22010-05-16 18:19:27 +00002062 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002063 # Same as test_connect, but with a separately created context
Christian Heimes2875c602021-04-19 07:27:10 +02002064 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2065 ctx.check_hostname = False
2066 ctx.verify_mode = ssl.CERT_NONE
Martin Panter3840b2a2016-03-27 01:53:46 +00002067 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2068 s.connect(self.server_addr)
2069 self.assertEqual({}, s.getpeercert())
2070 # Same with a server hostname
2071 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2072 server_hostname="dummy") as s:
2073 s.connect(self.server_addr)
2074 ctx.verify_mode = ssl.CERT_REQUIRED
2075 # This should succeed because we specify the root cert
2076 ctx.load_verify_locations(SIGNING_CA)
2077 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2078 s.connect(self.server_addr)
2079 cert = s.getpeercert()
2080 self.assertTrue(cert)
2081
2082 def test_connect_with_context_fail(self):
2083 # This should fail because we have no verification certs. Connection
2084 # failure crashes ThreadedEchoServer, so run this in an independent
2085 # test method.
Christian Heimes2875c602021-04-19 07:27:10 +02002086 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2087 s = ctx.wrap_socket(
2088 socket.socket(socket.AF_INET),
2089 server_hostname=SIGNED_CERTFILE_HOSTNAME
2090 )
Martin Panter3840b2a2016-03-27 01:53:46 +00002091 self.addCleanup(s.close)
2092 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2093 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002094
2095 def test_connect_capath(self):
2096 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002097 # NOTE: the subject hashing algorithm has been changed between
2098 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2099 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002100 # filename) for this test to be portable across OpenSSL releases.
Christian Heimes2875c602021-04-19 07:27:10 +02002101 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002102 ctx.load_verify_locations(capath=CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002103 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2104 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002105 s.connect(self.server_addr)
2106 cert = s.getpeercert()
2107 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002108
Martin Panter3840b2a2016-03-27 01:53:46 +00002109 # Same with a bytes `capath` argument
Christian Heimes2875c602021-04-19 07:27:10 +02002110 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002111 ctx.load_verify_locations(capath=BYTES_CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002112 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2113 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002114 s.connect(self.server_addr)
2115 cert = s.getpeercert()
2116 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002117
Christian Heimesefff7062013-11-21 03:35:02 +01002118 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002119 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002120 pem = f.read()
2121 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002122 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002123 ctx.load_verify_locations(cadata=pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002124 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2125 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002126 s.connect(self.server_addr)
2127 cert = s.getpeercert()
2128 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002129
Martin Panter3840b2a2016-03-27 01:53:46 +00002130 # same with DER
Christian Heimes2875c602021-04-19 07:27:10 +02002131 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002132 ctx.load_verify_locations(cadata=der)
Christian Heimes2875c602021-04-19 07:27:10 +02002133 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2134 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002135 s.connect(self.server_addr)
2136 cert = s.getpeercert()
2137 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002138
Antoine Pitroue3220242010-04-24 11:13:53 +00002139 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2140 def test_makefile_close(self):
2141 # Issue #5238: creating a file-like object with makefile() shouldn't
2142 # delay closing the underlying "real socket" (here tested with its
2143 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002144 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002145 ss.connect(self.server_addr)
2146 fd = ss.fileno()
2147 f = ss.makefile()
2148 f.close()
2149 # The fd is still open
2150 os.read(fd, 0)
2151 # Closing the SSL socket should close the fd too
2152 ss.close()
2153 gc.collect()
2154 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002155 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002156 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002157
Antoine Pitrou480a1242010-04-28 21:37:09 +00002158 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002159 s = socket.socket(socket.AF_INET)
2160 s.connect(self.server_addr)
2161 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002162 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002163 cert_reqs=ssl.CERT_NONE,
2164 do_handshake_on_connect=False)
2165 self.addCleanup(s.close)
2166 count = 0
2167 while True:
2168 try:
2169 count += 1
2170 s.do_handshake()
2171 break
2172 except ssl.SSLWantReadError:
2173 select.select([s], [], [])
2174 except ssl.SSLWantWriteError:
2175 select.select([], [s], [])
2176 if support.verbose:
2177 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002178
Antoine Pitrou480a1242010-04-28 21:37:09 +00002179 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002180 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002181
juhovh49fdf112021-04-18 21:11:48 +10002182 def test_get_server_certificate_sni(self):
2183 host, port = self.server_addr
2184 server_names = []
2185
2186 # We store servername_cb arguments to make sure they match the host
2187 def servername_cb(ssl_sock, server_name, initial_context):
2188 server_names.append(server_name)
2189 self.server_context.set_servername_callback(servername_cb)
2190
2191 pem = ssl.get_server_certificate((host, port))
2192 if not pem:
2193 self.fail("No server certificate on %s:%s!" % (host, port))
2194
2195 pem = ssl.get_server_certificate((host, port), ca_certs=SIGNING_CA)
2196 if not pem:
2197 self.fail("No server certificate on %s:%s!" % (host, port))
2198 if support.verbose:
2199 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port, pem))
2200
2201 self.assertEqual(server_names, [host, host])
2202
Martin Panter3840b2a2016-03-27 01:53:46 +00002203 def test_get_server_certificate_fail(self):
2204 # Connection failure crashes ThreadedEchoServer, so run this in an
2205 # independent test method
2206 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002207
Zackery Spytzb2fac1a2021-04-23 22:46:01 -06002208 def test_get_server_certificate_timeout(self):
Christian Heimesf05c2ae2021-04-24 07:54:08 +02002209 def servername_cb(ssl_sock, server_name, initial_context):
2210 time.sleep(0.2)
2211 self.server_context.set_servername_callback(servername_cb)
2212
Zackery Spytzb2fac1a2021-04-23 22:46:01 -06002213 with self.assertRaises(socket.timeout):
2214 ssl.get_server_certificate(self.server_addr, ca_certs=SIGNING_CA,
Christian Heimesf05c2ae2021-04-24 07:54:08 +02002215 timeout=0.1)
Zackery Spytzb2fac1a2021-04-23 22:46:01 -06002216
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002217 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002218 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002219 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2220 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002221 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002222 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2223 s.connect(self.server_addr)
2224 # Error checking can happen at instantiation or when connecting
2225 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2226 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002227 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002228 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2229 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002230
Christian Heimes9a5395a2013-06-17 15:44:12 +02002231 def test_get_ca_certs_capath(self):
2232 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002233 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002234 ctx.load_verify_locations(capath=CAPATH)
2235 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002236 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2237 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002238 s.connect(self.server_addr)
2239 cert = s.getpeercert()
2240 self.assertTrue(cert)
2241 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002242
Christian Heimes8e7f3942013-12-05 07:41:08 +01002243 def test_context_setget(self):
2244 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002245 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2246 ctx1.load_verify_locations(capath=CAPATH)
2247 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2248 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002249 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002250 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002251 ss.connect(self.server_addr)
2252 self.assertIs(ss.context, ctx1)
2253 self.assertIs(ss._sslobj.context, ctx1)
2254 ss.context = ctx2
2255 self.assertIs(ss.context, ctx2)
2256 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002257
2258 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2259 # A simple IO loop. Call func(*args) depending on the error we get
2260 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002261 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002262 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002263 count = 0
2264 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002265 if time.monotonic() > deadline:
2266 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002267 errno = None
2268 count += 1
2269 try:
2270 ret = func(*args)
2271 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002272 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002273 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002274 raise
2275 errno = e.errno
2276 # Get any data from the outgoing BIO irrespective of any error, and
2277 # send it to the socket.
2278 buf = outgoing.read()
2279 sock.sendall(buf)
2280 # If there's no error, we're done. For WANT_READ, we need to get
2281 # data from the socket and put it in the incoming BIO.
2282 if errno is None:
2283 break
2284 elif errno == ssl.SSL_ERROR_WANT_READ:
2285 buf = sock.recv(32768)
2286 if buf:
2287 incoming.write(buf)
2288 else:
2289 incoming.write_eof()
2290 if support.verbose:
2291 sys.stdout.write("Needed %d calls to complete %s().\n"
2292 % (count, func.__name__))
2293 return ret
2294
Martin Panter3840b2a2016-03-27 01:53:46 +00002295 def test_bio_handshake(self):
2296 sock = socket.socket(socket.AF_INET)
2297 self.addCleanup(sock.close)
2298 sock.connect(self.server_addr)
2299 incoming = ssl.MemoryBIO()
2300 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002301 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2302 self.assertTrue(ctx.check_hostname)
2303 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002304 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002305 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2306 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002307 self.assertIs(sslobj._sslobj.owner, sslobj)
2308 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002309 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002310 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002311 self.assertRaises(ValueError, sslobj.getpeercert)
2312 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2313 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2314 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2315 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002316 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002317 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002318 self.assertTrue(sslobj.getpeercert())
2319 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2320 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2321 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002322 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002323 except ssl.SSLSyscallError:
2324 # If the server shuts down the TCP connection without sending a
2325 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2326 pass
2327 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2328
2329 def test_bio_read_write_data(self):
2330 sock = socket.socket(socket.AF_INET)
2331 self.addCleanup(sock.close)
2332 sock.connect(self.server_addr)
2333 incoming = ssl.MemoryBIO()
2334 outgoing = ssl.MemoryBIO()
Christian Heimes2875c602021-04-19 07:27:10 +02002335 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2336 ctx.check_hostname = False
Martin Panter3840b2a2016-03-27 01:53:46 +00002337 ctx.verify_mode = ssl.CERT_NONE
2338 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2339 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2340 req = b'FOO\n'
2341 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2342 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2343 self.assertEqual(buf, b'foo\n')
2344 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002345
2346
Martin Panter3840b2a2016-03-27 01:53:46 +00002347class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002348
Martin Panter3840b2a2016-03-27 01:53:46 +00002349 def test_timeout_connect_ex(self):
2350 # Issue #12065: on a timeout, connect_ex() should return the original
2351 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002352 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002353 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002354 cert_reqs=ssl.CERT_REQUIRED,
2355 do_handshake_on_connect=False)
2356 self.addCleanup(s.close)
2357 s.settimeout(0.0000001)
2358 rc = s.connect_ex((REMOTE_HOST, 443))
2359 if rc == 0:
2360 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002361 elif rc == errno.ENETUNREACH:
2362 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002363 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2364
Serhiy Storchaka16994912020-04-25 10:06:29 +03002365 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002366 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002367 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002368 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2369 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2370
Martin Panter3840b2a2016-03-27 01:53:46 +00002371
2372def _test_get_server_certificate(test, host, port, cert=None):
2373 pem = ssl.get_server_certificate((host, port))
2374 if not pem:
2375 test.fail("No server certificate on %s:%s!" % (host, port))
2376
2377 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2378 if not pem:
2379 test.fail("No server certificate on %s:%s!" % (host, port))
2380 if support.verbose:
2381 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2382
2383def _test_get_server_certificate_fail(test, host, port):
2384 try:
2385 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2386 except ssl.SSLError as x:
2387 #should fail
2388 if support.verbose:
2389 sys.stdout.write("%s\n" % x)
2390 else:
2391 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2392
2393
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002394from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002395
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002396class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002397
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002398 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002399
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002400 """A mildly complicated class, because we want it to work both
2401 with and without the SSL wrapper around the socket connection, so
2402 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002403
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002404 def __init__(self, server, connsock, addr):
2405 self.server = server
2406 self.running = False
2407 self.sock = connsock
2408 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002409 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002410 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002411 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002412 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002413
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002414 def wrap_conn(self):
2415 try:
2416 self.sslconn = self.server.context.wrap_socket(
2417 self.sock, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002418 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002419 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002420 # We treat ConnectionResetError as though it were an
2421 # SSLError - OpenSSL on Ubuntu abruptly closes the
2422 # connection when asked to use an unsupported protocol.
2423 #
Christian Heimes529525f2018-05-23 22:24:45 +02002424 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2425 # tries to send session tickets after handshake.
2426 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002427 #
2428 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2429 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002430 self.server.conn_errors.append(str(e))
2431 if self.server.chatty:
2432 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2433 self.running = False
2434 self.close()
2435 return False
2436 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002437 # OSError may occur with wrong protocols, e.g. both
2438 # sides use PROTOCOL_TLS_SERVER.
2439 #
2440 # XXX Various errors can have happened here, for example
2441 # a mismatching protocol version, an invalid certificate,
2442 # or a low-level bug. This should be made more discriminating.
2443 #
2444 # bpo-31323: Store the exception as string to prevent
2445 # a reference leak: server -> conn_errors -> exception
2446 # -> traceback -> self (ConnectionHandler) -> server
2447 self.server.conn_errors.append(str(e))
2448 if self.server.chatty:
2449 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2450 self.running = False
2451 self.server.stop()
2452 self.close()
2453 return False
2454 else:
2455 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2456 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2457 cert = self.sslconn.getpeercert()
2458 if support.verbose and self.server.chatty:
2459 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2460 cert_binary = self.sslconn.getpeercert(True)
2461 if support.verbose and self.server.chatty:
Christian Heimesc8666cf2021-04-24 09:17:54 +02002462 if cert_binary is None:
2463 sys.stdout.write(" client did not provide a cert\n")
2464 else:
2465 sys.stdout.write(f" cert binary is {len(cert_binary)}b\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002466 cipher = self.sslconn.cipher()
2467 if support.verbose and self.server.chatty:
2468 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002469 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002470
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002471 def read(self):
2472 if self.sslconn:
2473 return self.sslconn.read()
2474 else:
2475 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002476
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002477 def write(self, bytes):
2478 if self.sslconn:
2479 return self.sslconn.write(bytes)
2480 else:
2481 return self.sock.send(bytes)
2482
2483 def close(self):
2484 if self.sslconn:
2485 self.sslconn.close()
2486 else:
2487 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002488
Antoine Pitrou480a1242010-04-28 21:37:09 +00002489 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002490 self.running = True
2491 if not self.server.starttls_server:
2492 if not self.wrap_conn():
2493 return
2494 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002495 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002496 msg = self.read()
2497 stripped = msg.strip()
2498 if not stripped:
2499 # eof, so quit this handler
2500 self.running = False
2501 try:
2502 self.sock = self.sslconn.unwrap()
2503 except OSError:
2504 # Many tests shut the TCP connection down
2505 # without an SSL shutdown. This causes
2506 # unwrap() to raise OSError with errno=0!
2507 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002508 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002509 self.sslconn = None
2510 self.close()
2511 elif stripped == b'over':
2512 if support.verbose and self.server.connectionchatty:
2513 sys.stdout.write(" server: client closed connection\n")
2514 self.close()
2515 return
2516 elif (self.server.starttls_server and
2517 stripped == b'STARTTLS'):
2518 if support.verbose and self.server.connectionchatty:
2519 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2520 self.write(b"OK\n")
2521 if not self.wrap_conn():
2522 return
2523 elif (self.server.starttls_server and self.sslconn
2524 and stripped == b'ENDTLS'):
2525 if support.verbose and self.server.connectionchatty:
2526 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2527 self.write(b"OK\n")
2528 self.sock = self.sslconn.unwrap()
2529 self.sslconn = None
2530 if support.verbose and self.server.connectionchatty:
2531 sys.stdout.write(" server: connection is now unencrypted...\n")
2532 elif stripped == b'CB tls-unique':
2533 if support.verbose and self.server.connectionchatty:
2534 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2535 data = self.sslconn.get_channel_binding("tls-unique")
2536 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002537 elif stripped == b'PHA':
2538 if support.verbose and self.server.connectionchatty:
2539 sys.stdout.write(" server: initiating post handshake auth\n")
2540 try:
2541 self.sslconn.verify_client_post_handshake()
2542 except ssl.SSLError as e:
2543 self.write(repr(e).encode("us-ascii") + b"\n")
2544 else:
2545 self.write(b"OK\n")
2546 elif stripped == b'HASCERT':
2547 if self.sslconn.getpeercert() is not None:
2548 self.write(b'TRUE\n')
2549 else:
2550 self.write(b'FALSE\n')
2551 elif stripped == b'GETCERT':
2552 cert = self.sslconn.getpeercert()
2553 self.write(repr(cert).encode("us-ascii") + b"\n")
Christian Heimes666991f2021-04-26 15:01:40 +02002554 elif stripped == b'VERIFIEDCHAIN':
2555 certs = self.sslconn._sslobj.get_verified_chain()
2556 self.write(len(certs).to_bytes(1, "big") + b"\n")
2557 elif stripped == b'UNVERIFIEDCHAIN':
2558 certs = self.sslconn._sslobj.get_unverified_chain()
2559 self.write(len(certs).to_bytes(1, "big") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002560 else:
2561 if (support.verbose and
2562 self.server.connectionchatty):
2563 ctype = (self.sslconn and "encrypted") or "unencrypted"
2564 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2565 % (msg, ctype, msg.lower(), ctype))
2566 self.write(msg.lower())
Christian Heimesc8666cf2021-04-24 09:17:54 +02002567 except OSError as e:
2568 # handles SSLError and socket errors
Christian Heimes529525f2018-05-23 22:24:45 +02002569 if self.server.chatty and support.verbose:
Christian Heimesc8666cf2021-04-24 09:17:54 +02002570 if isinstance(e, ConnectionError):
2571 # OpenSSL 1.1.1 sometimes raises
2572 # ConnectionResetError when connection is not
2573 # shut down gracefully.
2574 print(
2575 f" Connection reset by peer: {self.addr}"
2576 )
2577 else:
2578 handle_error("Test server failure:\n")
2579 try:
2580 self.write(b"ERROR\n")
2581 except OSError:
2582 pass
Bill Janssen2f5799b2008-06-29 00:08:12 +00002583 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002584 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002585
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002586 # normally, we'd just stop here, but for the test
2587 # harness, we want to stop the server
2588 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002589
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002590 def __init__(self, certificate=None, ssl_version=None,
2591 certreqs=None, cacerts=None,
2592 chatty=True, connectionchatty=False, starttls_server=False,
Christian Heimes2875c602021-04-19 07:27:10 +02002593 alpn_protocols=None,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002594 ciphers=None, context=None):
2595 if context:
2596 self.context = context
2597 else:
2598 self.context = ssl.SSLContext(ssl_version
2599 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002600 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002601 self.context.verify_mode = (certreqs if certreqs is not None
2602 else ssl.CERT_NONE)
2603 if cacerts:
2604 self.context.load_verify_locations(cacerts)
2605 if certificate:
2606 self.context.load_cert_chain(certificate)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002607 if alpn_protocols:
2608 self.context.set_alpn_protocols(alpn_protocols)
2609 if ciphers:
2610 self.context.set_ciphers(ciphers)
2611 self.chatty = chatty
2612 self.connectionchatty = connectionchatty
2613 self.starttls_server = starttls_server
2614 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002615 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002616 self.flag = None
2617 self.active = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002618 self.selected_alpn_protocols = []
2619 self.shared_ciphers = []
2620 self.conn_errors = []
2621 threading.Thread.__init__(self)
2622 self.daemon = True
2623
2624 def __enter__(self):
2625 self.start(threading.Event())
2626 self.flag.wait()
2627 return self
2628
2629 def __exit__(self, *args):
2630 self.stop()
2631 self.join()
2632
2633 def start(self, flag=None):
2634 self.flag = flag
2635 threading.Thread.start(self)
2636
2637 def run(self):
Christian Heimesc715b522021-05-03 17:45:02 +02002638 self.sock.settimeout(1.0)
2639 self.sock.listen(5)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002640 self.active = True
2641 if self.flag:
2642 # signal an event
2643 self.flag.set()
2644 while self.active:
2645 try:
2646 newconn, connaddr = self.sock.accept()
2647 if support.verbose and self.chatty:
2648 sys.stdout.write(' server: new connection from '
2649 + repr(connaddr) + '\n')
2650 handler = self.ConnectionHandler(self, newconn, connaddr)
2651 handler.start()
2652 handler.join()
Christian Heimesc715b522021-05-03 17:45:02 +02002653 except TimeoutError as e:
2654 if support.verbose:
2655 sys.stdout.write(f' connection timeout {e!r}\n')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002656 except KeyboardInterrupt:
2657 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002658 except BaseException as e:
2659 if support.verbose and self.chatty:
2660 sys.stdout.write(
2661 ' connection handling failed: ' + repr(e) + '\n')
2662
Christian Heimesc715b522021-05-03 17:45:02 +02002663 self.close()
2664
2665 def close(self):
2666 if self.sock is not None:
2667 self.sock.close()
2668 self.sock = None
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002669
2670 def stop(self):
2671 self.active = False
2672
2673class AsyncoreEchoServer(threading.Thread):
2674
2675 # this one's based on asyncore.dispatcher
2676
2677 class EchoServer (asyncore.dispatcher):
2678
2679 class ConnectionHandler(asyncore.dispatcher_with_send):
2680
2681 def __init__(self, conn, certfile):
2682 self.socket = test_wrap_socket(conn, server_side=True,
2683 certfile=certfile,
2684 do_handshake_on_connect=False)
2685 asyncore.dispatcher_with_send.__init__(self, self.socket)
2686 self._ssl_accepting = True
2687 self._do_ssl_handshake()
2688
2689 def readable(self):
2690 if isinstance(self.socket, ssl.SSLSocket):
2691 while self.socket.pending() > 0:
2692 self.handle_read_event()
2693 return True
2694
2695 def _do_ssl_handshake(self):
2696 try:
2697 self.socket.do_handshake()
2698 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2699 return
2700 except ssl.SSLEOFError:
2701 return self.handle_close()
2702 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002703 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002704 except OSError as err:
2705 if err.args[0] == errno.ECONNABORTED:
2706 return self.handle_close()
2707 else:
2708 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002709
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002710 def handle_read(self):
2711 if self._ssl_accepting:
2712 self._do_ssl_handshake()
2713 else:
2714 data = self.recv(1024)
2715 if support.verbose:
2716 sys.stdout.write(" server: read %s from client\n" % repr(data))
2717 if not data:
2718 self.close()
2719 else:
2720 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002721
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002722 def handle_close(self):
2723 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002724 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002725 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002726
2727 def handle_error(self):
2728 raise
2729
Trent Nelson78520002008-04-10 20:54:35 +00002730 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002731 self.certfile = certfile
2732 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002733 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002734 asyncore.dispatcher.__init__(self, sock)
2735 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002736
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002737 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002738 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002739 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2740 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002741
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002742 def handle_error(self):
2743 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002744
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002745 def __init__(self, certfile):
2746 self.flag = None
2747 self.active = False
2748 self.server = self.EchoServer(certfile)
2749 self.port = self.server.port
2750 threading.Thread.__init__(self)
2751 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002752
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002753 def __str__(self):
2754 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002755
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002756 def __enter__(self):
2757 self.start(threading.Event())
2758 self.flag.wait()
2759 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002760
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002761 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002762 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002763 sys.stdout.write(" cleanup: stopping server.\n")
2764 self.stop()
2765 if support.verbose:
2766 sys.stdout.write(" cleanup: joining server thread.\n")
2767 self.join()
2768 if support.verbose:
2769 sys.stdout.write(" cleanup: successfully joined.\n")
2770 # make sure that ConnectionHandler is removed from socket_map
2771 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002772
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002773 def start (self, flag=None):
2774 self.flag = flag
2775 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002776
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002777 def run(self):
2778 self.active = True
2779 if self.flag:
2780 self.flag.set()
2781 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002782 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002783 asyncore.loop(1)
2784 except:
2785 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002786
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002787 def stop(self):
2788 self.active = False
2789 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002790
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002791def server_params_test(client_context, server_context, indata=b"FOO\n",
2792 chatty=True, connectionchatty=False, sni_name=None,
2793 session=None):
2794 """
2795 Launch a server, connect a client to it and try various reads
2796 and writes.
2797 """
2798 stats = {}
2799 server = ThreadedEchoServer(context=server_context,
2800 chatty=chatty,
2801 connectionchatty=False)
2802 with server:
2803 with client_context.wrap_socket(socket.socket(),
2804 server_hostname=sni_name, session=session) as s:
2805 s.connect((HOST, server.port))
2806 for arg in [indata, bytearray(indata), memoryview(indata)]:
2807 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002808 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002809 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002810 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002811 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002812 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002813 if connectionchatty:
2814 if support.verbose:
2815 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002816 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002817 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002818 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2819 % (outdata[:20], len(outdata),
2820 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002821 s.write(b"over\n")
2822 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002823 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002824 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002825 stats.update({
2826 'compression': s.compression(),
2827 'cipher': s.cipher(),
2828 'peercert': s.getpeercert(),
2829 'client_alpn_protocol': s.selected_alpn_protocol(),
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002830 'version': s.version(),
2831 'session_reused': s.session_reused,
2832 'session': s.session,
2833 })
2834 s.close()
2835 stats['server_alpn_protocols'] = server.selected_alpn_protocols
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002836 stats['server_shared_ciphers'] = server.shared_ciphers
2837 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002838
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002839def try_protocol_combo(server_protocol, client_protocol, expect_success,
2840 certsreqs=None, server_options=0, client_options=0):
2841 """
2842 Try to SSL-connect using *client_protocol* to *server_protocol*.
2843 If *expect_success* is true, assert that the connection succeeds,
2844 if it's false, assert that the connection fails.
2845 Also, if *expect_success* is a string, assert that it is the protocol
2846 version actually used by the connection.
2847 """
2848 if certsreqs is None:
2849 certsreqs = ssl.CERT_NONE
2850 certtype = {
2851 ssl.CERT_NONE: "CERT_NONE",
2852 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2853 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2854 }[certsreqs]
2855 if support.verbose:
2856 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2857 sys.stdout.write(formatstr %
2858 (ssl.get_protocol_name(client_protocol),
2859 ssl.get_protocol_name(server_protocol),
2860 certtype))
Christian Heimes2875c602021-04-19 07:27:10 +02002861
2862 with warnings_helper.check_warnings():
2863 # ignore Deprecation warnings
2864 client_context = ssl.SSLContext(client_protocol)
2865 client_context.options |= client_options
2866 server_context = ssl.SSLContext(server_protocol)
2867 server_context.options |= server_options
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002868
Victor Stinner3ef63442019-02-19 18:06:03 +01002869 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2870 if (min_version is not None
Christian Heimes2875c602021-04-19 07:27:10 +02002871 # SSLContext.minimum_version is only available on recent OpenSSL
2872 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2873 and hasattr(server_context, 'minimum_version')
2874 and server_protocol == ssl.PROTOCOL_TLS
2875 and server_context.minimum_version > min_version
2876 ):
Victor Stinner3ef63442019-02-19 18:06:03 +01002877 # If OpenSSL configuration is strict and requires more recent TLS
2878 # version, we have to change the minimum to test old TLS versions.
Christian Heimes2875c602021-04-19 07:27:10 +02002879 with warnings_helper.check_warnings():
2880 server_context.minimum_version = min_version
Victor Stinner3ef63442019-02-19 18:06:03 +01002881
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002882 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2883 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2884 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002885 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002886 client_context.set_ciphers("ALL")
2887
Christian Heimesf6c6b582021-03-18 23:06:50 +01002888 seclevel_workaround(server_context, client_context)
2889
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002890 for ctx in (client_context, server_context):
2891 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002892 ctx.load_cert_chain(SIGNED_CERTFILE)
2893 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002894 try:
2895 stats = server_params_test(client_context, server_context,
2896 chatty=False, connectionchatty=False)
2897 # Protocol mismatch can result in either an SSLError, or a
2898 # "Connection reset by peer" error.
2899 except ssl.SSLError:
2900 if expect_success:
2901 raise
2902 except OSError as e:
2903 if expect_success or e.errno != errno.ECONNRESET:
2904 raise
2905 else:
2906 if not expect_success:
2907 raise AssertionError(
2908 "Client protocol %s succeeded with server protocol %s!"
2909 % (ssl.get_protocol_name(client_protocol),
2910 ssl.get_protocol_name(server_protocol)))
2911 elif (expect_success is not True
2912 and expect_success != stats['version']):
2913 raise AssertionError("version mismatch: expected %r, got %r"
2914 % (expect_success, stats['version']))
2915
2916
2917class ThreadedTests(unittest.TestCase):
2918
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002919 def test_echo(self):
2920 """Basic test of an SSL client connecting to a server"""
2921 if support.verbose:
2922 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002923
Christian Heimesa170fa12017-09-15 20:27:30 +02002924 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002925
2926 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2927 server_params_test(client_context=client_context,
2928 server_context=server_context,
2929 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002930 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002931
2932 client_context.check_hostname = False
2933 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2934 with self.assertRaises(ssl.SSLError) as e:
2935 server_params_test(client_context=server_context,
2936 server_context=client_context,
2937 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002938 sni_name=hostname)
Miss Islington (bot)d7930fb2021-06-11 00:36:17 -07002939 self.assertIn(
2940 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
2941 str(e.exception)
2942 )
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002943
2944 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2945 with self.assertRaises(ssl.SSLError) as e:
2946 server_params_test(client_context=server_context,
2947 server_context=server_context,
2948 chatty=True, connectionchatty=True)
Miss Islington (bot)d7930fb2021-06-11 00:36:17 -07002949 self.assertIn(
2950 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
2951 str(e.exception)
2952 )
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002953
2954 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2955 with self.assertRaises(ssl.SSLError) as e:
2956 server_params_test(client_context=server_context,
2957 server_context=client_context,
2958 chatty=True, connectionchatty=True)
Miss Islington (bot)d7930fb2021-06-11 00:36:17 -07002959 self.assertIn(
2960 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context',
2961 str(e.exception))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002962
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002963 def test_getpeercert(self):
2964 if support.verbose:
2965 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002966
2967 client_context, server_context, hostname = testing_context()
2968 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002969 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002970 with client_context.wrap_socket(socket.socket(),
2971 do_handshake_on_connect=False,
2972 server_hostname=hostname) as s:
2973 s.connect((HOST, server.port))
2974 # getpeercert() raise ValueError while the handshake isn't
2975 # done.
2976 with self.assertRaises(ValueError):
2977 s.getpeercert()
2978 s.do_handshake()
2979 cert = s.getpeercert()
2980 self.assertTrue(cert, "Can't get peer certificate.")
2981 cipher = s.cipher()
2982 if support.verbose:
2983 sys.stdout.write(pprint.pformat(cert) + '\n')
2984 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2985 if 'subject' not in cert:
2986 self.fail("No subject field in certificate: %s." %
2987 pprint.pformat(cert))
2988 if ((('organizationName', 'Python Software Foundation'),)
2989 not in cert['subject']):
2990 self.fail(
2991 "Missing or invalid 'organizationName' field in certificate subject; "
2992 "should be 'Python Software Foundation'.")
2993 self.assertIn('notBefore', cert)
2994 self.assertIn('notAfter', cert)
2995 before = ssl.cert_time_to_seconds(cert['notBefore'])
2996 after = ssl.cert_time_to_seconds(cert['notAfter'])
2997 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002998
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002999 def test_crl_check(self):
3000 if support.verbose:
3001 sys.stdout.write("\n")
3002
Christian Heimesa170fa12017-09-15 20:27:30 +02003003 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003004
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003005 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02003006 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003007
3008 # VERIFY_DEFAULT should pass
3009 server = ThreadedEchoServer(context=server_context, chatty=True)
3010 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003011 with client_context.wrap_socket(socket.socket(),
3012 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01003013 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003014 cert = s.getpeercert()
3015 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00003016
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003017 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02003018 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00003019
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003020 server = ThreadedEchoServer(context=server_context, chatty=True)
3021 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003022 with client_context.wrap_socket(socket.socket(),
3023 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003024 with self.assertRaisesRegex(ssl.SSLError,
3025 "certificate verify failed"):
3026 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00003027
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003028 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02003029 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00003030
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003031 server = ThreadedEchoServer(context=server_context, chatty=True)
3032 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003033 with client_context.wrap_socket(socket.socket(),
3034 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02003035 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003036 cert = s.getpeercert()
3037 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02003038
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003039 def test_check_hostname(self):
3040 if support.verbose:
3041 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02003042
Christian Heimesa170fa12017-09-15 20:27:30 +02003043 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003044
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003045 # correct hostname should verify
3046 server = ThreadedEchoServer(context=server_context, chatty=True)
3047 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003048 with client_context.wrap_socket(socket.socket(),
3049 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003050 s.connect((HOST, server.port))
3051 cert = s.getpeercert()
3052 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003053
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003054 # incorrect hostname should raise an exception
3055 server = ThreadedEchoServer(context=server_context, chatty=True)
3056 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003057 with client_context.wrap_socket(socket.socket(),
3058 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01003059 with self.assertRaisesRegex(
3060 ssl.CertificateError,
3061 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003062 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003063
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003064 # missing server_hostname arg should cause an exception, too
3065 server = ThreadedEchoServer(context=server_context, chatty=True)
3066 with server:
3067 with socket.socket() as s:
3068 with self.assertRaisesRegex(ValueError,
3069 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02003070 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003071
Christian Heimesb467d9a2021-04-17 10:07:19 +02003072 @unittest.skipUnless(
3073 ssl.HAS_NEVER_CHECK_COMMON_NAME, "test requires hostname_checks_common_name"
3074 )
3075 def test_hostname_checks_common_name(self):
3076 client_context, server_context, hostname = testing_context()
3077 assert client_context.hostname_checks_common_name
3078 client_context.hostname_checks_common_name = False
3079
3080 # default cert has a SAN
3081 server = ThreadedEchoServer(context=server_context, chatty=True)
3082 with server:
3083 with client_context.wrap_socket(socket.socket(),
3084 server_hostname=hostname) as s:
3085 s.connect((HOST, server.port))
3086
3087 client_context, server_context, hostname = testing_context(NOSANFILE)
3088 client_context.hostname_checks_common_name = False
3089 server = ThreadedEchoServer(context=server_context, chatty=True)
3090 with server:
3091 with client_context.wrap_socket(socket.socket(),
3092 server_hostname=hostname) as s:
3093 with self.assertRaises(ssl.SSLCertVerificationError):
3094 s.connect((HOST, server.port))
3095
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003096 def test_ecc_cert(self):
3097 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3098 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003099 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003100 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3101
3102 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3103 # load ECC cert
3104 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3105
3106 # correct hostname should verify
3107 server = ThreadedEchoServer(context=server_context, chatty=True)
3108 with server:
3109 with client_context.wrap_socket(socket.socket(),
3110 server_hostname=hostname) as s:
3111 s.connect((HOST, server.port))
3112 cert = s.getpeercert()
3113 self.assertTrue(cert, "Can't get peer certificate.")
3114 cipher = s.cipher()[0].split('-')
3115 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3116
3117 def test_dual_rsa_ecc(self):
3118 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3119 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003120 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3121 # algorithms.
Miss Islington (bot)4becc562021-06-13 05:07:00 -07003122 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003123 # only ECDSA certs
3124 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3125 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3126
3127 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3128 # load ECC and RSA key/cert pairs
3129 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3130 server_context.load_cert_chain(SIGNED_CERTFILE)
3131
3132 # correct hostname should verify
3133 server = ThreadedEchoServer(context=server_context, chatty=True)
3134 with server:
3135 with client_context.wrap_socket(socket.socket(),
3136 server_hostname=hostname) as s:
3137 s.connect((HOST, server.port))
3138 cert = s.getpeercert()
3139 self.assertTrue(cert, "Can't get peer certificate.")
3140 cipher = s.cipher()[0].split('-')
3141 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3142
Christian Heimes66e57422018-01-29 14:25:13 +01003143 def test_check_hostname_idn(self):
3144 if support.verbose:
3145 sys.stdout.write("\n")
3146
Christian Heimes11a14932018-02-24 02:35:08 +01003147 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003148 server_context.load_cert_chain(IDNSANSFILE)
3149
Christian Heimes11a14932018-02-24 02:35:08 +01003150 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003151 context.verify_mode = ssl.CERT_REQUIRED
3152 context.check_hostname = True
3153 context.load_verify_locations(SIGNING_CA)
3154
3155 # correct hostname should verify, when specified in several
3156 # different ways
3157 idn_hostnames = [
3158 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003159 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003160 ('xn--knig-5qa.idn.pythontest.net',
3161 'xn--knig-5qa.idn.pythontest.net'),
3162 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003163 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003164
3165 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003166 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003167 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3168 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3169 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003170 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3171
3172 # ('königsgäßchen.idna2008.pythontest.net',
3173 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3174 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3175 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3176 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3177 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3178
Christian Heimes66e57422018-01-29 14:25:13 +01003179 ]
3180 for server_hostname, expected_hostname in idn_hostnames:
3181 server = ThreadedEchoServer(context=server_context, chatty=True)
3182 with server:
3183 with context.wrap_socket(socket.socket(),
3184 server_hostname=server_hostname) as s:
3185 self.assertEqual(s.server_hostname, expected_hostname)
3186 s.connect((HOST, server.port))
3187 cert = s.getpeercert()
3188 self.assertEqual(s.server_hostname, expected_hostname)
3189 self.assertTrue(cert, "Can't get peer certificate.")
3190
Christian Heimes66e57422018-01-29 14:25:13 +01003191 # incorrect hostname should raise an exception
3192 server = ThreadedEchoServer(context=server_context, chatty=True)
3193 with server:
3194 with context.wrap_socket(socket.socket(),
3195 server_hostname="python.example.org") as s:
3196 with self.assertRaises(ssl.CertificateError):
3197 s.connect((HOST, server.port))
3198
Christian Heimes529525f2018-05-23 22:24:45 +02003199 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003200 """Connecting when the server rejects the client's certificate
3201
3202 Launch a server with CERT_REQUIRED, and check that trying to
3203 connect to it with a wrong client certificate fails.
3204 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003205 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003206 # load client cert that is not signed by trusted CA
3207 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003208 # require TLS client authentication
3209 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003210 # TLS 1.3 has different handshake
3211 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003212
3213 server = ThreadedEchoServer(
3214 context=server_context, chatty=True, connectionchatty=True,
3215 )
3216
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003217 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003218 client_context.wrap_socket(socket.socket(),
3219 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003220 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003221 # Expect either an SSL error about the server rejecting
3222 # the connection, or a low-level connection reset (which
3223 # sometimes happens on Windows)
3224 s.connect((HOST, server.port))
3225 except ssl.SSLError as e:
3226 if support.verbose:
3227 sys.stdout.write("\nSSLError is %r\n" % e)
3228 except OSError as e:
3229 if e.errno != errno.ECONNRESET:
3230 raise
3231 if support.verbose:
3232 sys.stdout.write("\nsocket.error is %r\n" % e)
3233 else:
3234 self.fail("Use of invalid cert should have failed!")
3235
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003236 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003237 def test_wrong_cert_tls13(self):
3238 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003239 # load client cert that is not signed by trusted CA
3240 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003241 server_context.verify_mode = ssl.CERT_REQUIRED
3242 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3243 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3244
3245 server = ThreadedEchoServer(
3246 context=server_context, chatty=True, connectionchatty=True,
3247 )
3248 with server, \
3249 client_context.wrap_socket(socket.socket(),
Miss Islington (bot)d2ab15f2021-06-03 13:15:15 -07003250 server_hostname=hostname,
3251 suppress_ragged_eofs=False) as s:
Christian Heimes529525f2018-05-23 22:24:45 +02003252 # TLS 1.3 perform client cert exchange after handshake
3253 s.connect((HOST, server.port))
3254 try:
3255 s.write(b'data')
Christian Heimese0472392021-04-23 20:03:25 +02003256 s.read(1000)
3257 s.write(b'should have failed already')
3258 s.read(1000)
Christian Heimes529525f2018-05-23 22:24:45 +02003259 except ssl.SSLError as e:
3260 if support.verbose:
3261 sys.stdout.write("\nSSLError is %r\n" % e)
3262 except OSError as e:
3263 if e.errno != errno.ECONNRESET:
3264 raise
3265 if support.verbose:
3266 sys.stdout.write("\nsocket.error is %r\n" % e)
3267 else:
Miss Islington (bot)d2ab15f2021-06-03 13:15:15 -07003268 self.fail("Use of invalid cert should have failed!")
Christian Heimes529525f2018-05-23 22:24:45 +02003269
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003270 def test_rude_shutdown(self):
3271 """A brutal shutdown of an SSL server should raise an OSError
3272 in the client when attempting handshake.
3273 """
3274 listener_ready = threading.Event()
3275 listener_gone = threading.Event()
3276
3277 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003278 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003279
3280 # `listener` runs in a thread. It sits in an accept() until
3281 # the main thread connects. Then it rudely closes the socket,
3282 # and sets Event `listener_gone` to let the main thread know
3283 # the socket is gone.
3284 def listener():
3285 s.listen()
3286 listener_ready.set()
3287 newsock, addr = s.accept()
3288 newsock.close()
3289 s.close()
3290 listener_gone.set()
3291
3292 def connector():
3293 listener_ready.wait()
3294 with socket.socket() as c:
3295 c.connect((HOST, port))
3296 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003297 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003298 ssl_sock = test_wrap_socket(c)
3299 except OSError:
3300 pass
3301 else:
3302 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003303
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003304 t = threading.Thread(target=listener)
3305 t.start()
3306 try:
3307 connector()
3308 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003309 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003310
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003311 def test_ssl_cert_verify_error(self):
3312 if support.verbose:
3313 sys.stdout.write("\n")
3314
3315 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3316 server_context.load_cert_chain(SIGNED_CERTFILE)
3317
3318 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3319
3320 server = ThreadedEchoServer(context=server_context, chatty=True)
3321 with server:
3322 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003323 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003324 try:
3325 s.connect((HOST, server.port))
3326 except ssl.SSLError as e:
3327 msg = 'unable to get local issuer certificate'
3328 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3329 self.assertEqual(e.verify_code, 20)
3330 self.assertEqual(e.verify_message, msg)
3331 self.assertIn(msg, repr(e))
3332 self.assertIn('certificate verify failed', repr(e))
3333
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003334 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003335 def test_protocol_sslv2(self):
3336 """Connecting to an SSLv2 server with various client options"""
3337 if support.verbose:
3338 sys.stdout.write("\n")
3339 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3340 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3341 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003342 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003343 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003344 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3345 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3346 # SSLv23 client with specific SSL options
Christian Heimesa170fa12017-09-15 20:27:30 +02003347 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003348 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003349 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003350 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003351
Christian Heimesa170fa12017-09-15 20:27:30 +02003352 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003353 """Connecting to an SSLv23 server with various client options"""
3354 if support.verbose:
3355 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003356 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003357 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003358 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003359 except OSError as x:
3360 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3361 if support.verbose:
3362 sys.stdout.write(
3363 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3364 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003365 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003366 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3367 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003368 if has_tls_version('TLSv1'):
3369 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003370
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003371 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003372 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3373 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003374 if has_tls_version('TLSv1'):
3375 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003376
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003377 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003378 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3379 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003380 if has_tls_version('TLSv1'):
3381 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003382
3383 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003384 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003385 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003386 server_options=ssl.OP_NO_SSLv3)
3387 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003388 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003389 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003390 if has_tls_version('TLSv1'):
3391 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3392 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003393
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003394 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003395 def test_protocol_sslv3(self):
3396 """Connecting to an SSLv3 server with various client options"""
3397 if support.verbose:
3398 sys.stdout.write("\n")
3399 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3400 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3401 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003402 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003403 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003404 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003405 client_options=ssl.OP_NO_SSLv3)
3406 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003407
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003408 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003409 def test_protocol_tlsv1(self):
3410 """Connecting to a TLSv1 server with various client options"""
3411 if support.verbose:
3412 sys.stdout.write("\n")
3413 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3414 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3415 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003416 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003417 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003418 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003419 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003420 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003421 client_options=ssl.OP_NO_TLSv1)
3422
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003423 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003424 def test_protocol_tlsv1_1(self):
3425 """Connecting to a TLSv1.1 server with various client options.
3426 Testing against older TLS versions."""
3427 if support.verbose:
3428 sys.stdout.write("\n")
3429 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003430 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003431 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003432 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003433 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003434 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003435 client_options=ssl.OP_NO_TLSv1_1)
3436
Christian Heimesa170fa12017-09-15 20:27:30 +02003437 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003438 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3439 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003440
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003441 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003442 def test_protocol_tlsv1_2(self):
3443 """Connecting to a TLSv1.2 server with various client options.
3444 Testing against older TLS versions."""
3445 if support.verbose:
3446 sys.stdout.write("\n")
3447 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3448 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3449 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003450 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003451 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003452 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003453 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003454 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003455 client_options=ssl.OP_NO_TLSv1_2)
3456
Christian Heimesa170fa12017-09-15 20:27:30 +02003457 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003458 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3459 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3460 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3461 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3462
3463 def test_starttls(self):
3464 """Switching from clear text to encrypted and back again."""
3465 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3466
3467 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003468 starttls_server=True,
3469 chatty=True,
3470 connectionchatty=True)
3471 wrapped = False
3472 with server:
3473 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003474 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003475 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003476 if support.verbose:
3477 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003478 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003479 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003480 sys.stdout.write(
3481 " client: sending %r...\n" % indata)
3482 if wrapped:
3483 conn.write(indata)
3484 outdata = conn.read()
3485 else:
3486 s.send(indata)
3487 outdata = s.recv(1024)
3488 msg = outdata.strip().lower()
3489 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3490 # STARTTLS ok, switch to secure mode
3491 if support.verbose:
3492 sys.stdout.write(
3493 " client: read %r from server, starting TLS...\n"
3494 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003495 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003496 wrapped = True
3497 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3498 # ENDTLS ok, switch back to clear text
3499 if support.verbose:
3500 sys.stdout.write(
3501 " client: read %r from server, ending TLS...\n"
3502 % msg)
3503 s = conn.unwrap()
3504 wrapped = False
3505 else:
3506 if support.verbose:
3507 sys.stdout.write(
3508 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003509 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003510 sys.stdout.write(" client: closing connection.\n")
3511 if wrapped:
3512 conn.write(b"over\n")
3513 else:
3514 s.send(b"over\n")
3515 if wrapped:
3516 conn.close()
3517 else:
3518 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003519
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003520 def test_socketserver(self):
3521 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003522 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003523 # try to connect
3524 if support.verbose:
3525 sys.stdout.write('\n')
3526 with open(CERTFILE, 'rb') as f:
3527 d1 = f.read()
3528 d2 = ''
3529 # now fetch the same data from the HTTPS server
3530 url = 'https://localhost:%d/%s' % (
3531 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003532 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003533 f = urllib.request.urlopen(url, context=context)
3534 try:
3535 dlen = f.info().get("content-length")
3536 if dlen and (int(dlen) > 0):
3537 d2 = f.read(int(dlen))
3538 if support.verbose:
3539 sys.stdout.write(
3540 " client: read %d bytes from remote server '%s'\n"
3541 % (len(d2), server))
3542 finally:
3543 f.close()
3544 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003545
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003546 def test_asyncore_server(self):
3547 """Check the example asyncore integration."""
3548 if support.verbose:
3549 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003550
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003551 indata = b"FOO\n"
3552 server = AsyncoreEchoServer(CERTFILE)
3553 with server:
3554 s = test_wrap_socket(socket.socket())
3555 s.connect(('127.0.0.1', server.port))
3556 if support.verbose:
3557 sys.stdout.write(
3558 " client: sending %r...\n" % indata)
3559 s.write(indata)
3560 outdata = s.read()
3561 if support.verbose:
3562 sys.stdout.write(" client: read %r\n" % outdata)
3563 if outdata != indata.lower():
3564 self.fail(
3565 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3566 % (outdata[:20], len(outdata),
3567 indata[:20].lower(), len(indata)))
3568 s.write(b"over\n")
3569 if support.verbose:
3570 sys.stdout.write(" client: closing connection.\n")
3571 s.close()
3572 if support.verbose:
3573 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003574
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003575 def test_recv_send(self):
3576 """Test recv(), send() and friends."""
3577 if support.verbose:
3578 sys.stdout.write("\n")
3579
3580 server = ThreadedEchoServer(CERTFILE,
3581 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003582 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003583 cacerts=CERTFILE,
3584 chatty=True,
3585 connectionchatty=False)
3586 with server:
3587 s = test_wrap_socket(socket.socket(),
3588 server_side=False,
3589 certfile=CERTFILE,
3590 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003591 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003592 s.connect((HOST, server.port))
3593 # helper methods for standardising recv* method signatures
3594 def _recv_into():
3595 b = bytearray(b"\0"*100)
3596 count = s.recv_into(b)
3597 return b[:count]
3598
3599 def _recvfrom_into():
3600 b = bytearray(b"\0"*100)
3601 count, addr = s.recvfrom_into(b)
3602 return b[:count]
3603
3604 # (name, method, expect success?, *args, return value func)
3605 send_methods = [
3606 ('send', s.send, True, [], len),
3607 ('sendto', s.sendto, False, ["some.address"], len),
3608 ('sendall', s.sendall, True, [], lambda x: None),
3609 ]
3610 # (name, method, whether to expect success, *args)
3611 recv_methods = [
3612 ('recv', s.recv, True, []),
3613 ('recvfrom', s.recvfrom, False, ["some.address"]),
3614 ('recv_into', _recv_into, True, []),
3615 ('recvfrom_into', _recvfrom_into, False, []),
3616 ]
3617 data_prefix = "PREFIX_"
3618
3619 for (meth_name, send_meth, expect_success, args,
3620 ret_val_meth) in send_methods:
3621 indata = (data_prefix + meth_name).encode('ascii')
3622 try:
3623 ret = send_meth(indata, *args)
3624 msg = "sending with {}".format(meth_name)
3625 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3626 outdata = s.read()
3627 if outdata != indata.lower():
3628 self.fail(
3629 "While sending with <<{name:s}>> bad data "
3630 "<<{outdata:r}>> ({nout:d}) received; "
3631 "expected <<{indata:r}>> ({nin:d})\n".format(
3632 name=meth_name, outdata=outdata[:20],
3633 nout=len(outdata),
3634 indata=indata[:20], nin=len(indata)
3635 )
3636 )
3637 except ValueError as e:
3638 if expect_success:
3639 self.fail(
3640 "Failed to send with method <<{name:s}>>; "
3641 "expected to succeed.\n".format(name=meth_name)
3642 )
3643 if not str(e).startswith(meth_name):
3644 self.fail(
3645 "Method <<{name:s}>> failed with unexpected "
3646 "exception message: {exp:s}\n".format(
3647 name=meth_name, exp=e
3648 )
3649 )
3650
3651 for meth_name, recv_meth, expect_success, args in recv_methods:
3652 indata = (data_prefix + meth_name).encode('ascii')
3653 try:
3654 s.send(indata)
3655 outdata = recv_meth(*args)
3656 if outdata != indata.lower():
3657 self.fail(
3658 "While receiving with <<{name:s}>> bad data "
3659 "<<{outdata:r}>> ({nout:d}) received; "
3660 "expected <<{indata:r}>> ({nin:d})\n".format(
3661 name=meth_name, outdata=outdata[:20],
3662 nout=len(outdata),
3663 indata=indata[:20], nin=len(indata)
3664 )
3665 )
3666 except ValueError as e:
3667 if expect_success:
3668 self.fail(
3669 "Failed to receive with method <<{name:s}>>; "
3670 "expected to succeed.\n".format(name=meth_name)
3671 )
3672 if not str(e).startswith(meth_name):
3673 self.fail(
3674 "Method <<{name:s}>> failed with unexpected "
3675 "exception message: {exp:s}\n".format(
3676 name=meth_name, exp=e
3677 )
3678 )
3679 # consume data
3680 s.read()
3681
3682 # read(-1, buffer) is supported, even though read(-1) is not
3683 data = b"data"
3684 s.send(data)
3685 buffer = bytearray(len(data))
3686 self.assertEqual(s.read(-1, buffer), len(data))
3687 self.assertEqual(buffer, data)
3688
Christian Heimes888bbdc2017-09-07 14:18:21 -07003689 # sendall accepts bytes-like objects
3690 if ctypes is not None:
3691 ubyte = ctypes.c_ubyte * len(data)
3692 byteslike = ubyte.from_buffer_copy(data)
3693 s.sendall(byteslike)
3694 self.assertEqual(s.read(), data)
3695
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003696 # Make sure sendmsg et al are disallowed to avoid
3697 # inadvertent disclosure of data and/or corruption
3698 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003699 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003700 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3701 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3702 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003703 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003704 s.write(b"over\n")
3705
3706 self.assertRaises(ValueError, s.recv, -1)
3707 self.assertRaises(ValueError, s.read, -1)
3708
3709 s.close()
3710
3711 def test_recv_zero(self):
3712 server = ThreadedEchoServer(CERTFILE)
3713 server.__enter__()
3714 self.addCleanup(server.__exit__, None, None)
3715 s = socket.create_connection((HOST, server.port))
3716 self.addCleanup(s.close)
3717 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3718 self.addCleanup(s.close)
3719
3720 # recv/read(0) should return no data
3721 s.send(b"data")
3722 self.assertEqual(s.recv(0), b"")
3723 self.assertEqual(s.read(0), b"")
3724 self.assertEqual(s.read(), b"data")
3725
3726 # Should not block if the other end sends no data
3727 s.setblocking(False)
3728 self.assertEqual(s.recv(0), b"")
3729 self.assertEqual(s.recv_into(bytearray()), 0)
3730
3731 def test_nonblocking_send(self):
3732 server = ThreadedEchoServer(CERTFILE,
3733 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003734 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003735 cacerts=CERTFILE,
3736 chatty=True,
3737 connectionchatty=False)
3738 with server:
3739 s = test_wrap_socket(socket.socket(),
3740 server_side=False,
3741 certfile=CERTFILE,
3742 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003743 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003744 s.connect((HOST, server.port))
3745 s.setblocking(False)
3746
3747 # If we keep sending data, at some point the buffers
3748 # will be full and the call will block
3749 buf = bytearray(8192)
3750 def fill_buffer():
3751 while True:
3752 s.send(buf)
3753 self.assertRaises((ssl.SSLWantWriteError,
3754 ssl.SSLWantReadError), fill_buffer)
3755
3756 # Now read all the output and discard it
3757 s.setblocking(True)
3758 s.close()
3759
3760 def test_handshake_timeout(self):
3761 # Issue #5103: SSL handshake must respect the socket timeout
3762 server = socket.socket(socket.AF_INET)
3763 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003764 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003765 started = threading.Event()
3766 finish = False
3767
3768 def serve():
3769 server.listen()
3770 started.set()
3771 conns = []
3772 while not finish:
3773 r, w, e = select.select([server], [], [], 0.1)
3774 if server in r:
3775 # Let the socket hang around rather than having
3776 # it closed by garbage collection.
3777 conns.append(server.accept()[0])
3778 for sock in conns:
3779 sock.close()
3780
3781 t = threading.Thread(target=serve)
3782 t.start()
3783 started.wait()
3784
3785 try:
3786 try:
3787 c = socket.socket(socket.AF_INET)
3788 c.settimeout(0.2)
3789 c.connect((host, port))
3790 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003791 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003792 test_wrap_socket, c)
3793 finally:
3794 c.close()
3795 try:
3796 c = socket.socket(socket.AF_INET)
3797 c = test_wrap_socket(c)
3798 c.settimeout(0.2)
3799 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003800 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003801 c.connect, (host, port))
3802 finally:
3803 c.close()
3804 finally:
3805 finish = True
3806 t.join()
3807 server.close()
3808
3809 def test_server_accept(self):
3810 # Issue #16357: accept() on a SSLSocket created through
3811 # SSLContext.wrap_socket().
Christian Heimes2875c602021-04-19 07:27:10 +02003812 client_ctx, server_ctx, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003813 server = socket.socket(socket.AF_INET)
3814 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003815 port = socket_helper.bind_port(server)
Christian Heimes2875c602021-04-19 07:27:10 +02003816 server = server_ctx.wrap_socket(server, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003817 self.assertTrue(server.server_side)
3818
3819 evt = threading.Event()
3820 remote = None
3821 peer = None
3822 def serve():
3823 nonlocal remote, peer
3824 server.listen()
3825 # Block on the accept and wait on the connection to close.
3826 evt.set()
3827 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003828 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003829
3830 t = threading.Thread(target=serve)
3831 t.start()
3832 # Client wait until server setup and perform a connect.
3833 evt.wait()
Christian Heimes2875c602021-04-19 07:27:10 +02003834 client = client_ctx.wrap_socket(
3835 socket.socket(), server_hostname=hostname
3836 )
3837 client.connect((hostname, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003838 client.send(b'data')
3839 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003840 client_addr = client.getsockname()
3841 client.close()
3842 t.join()
3843 remote.close()
3844 server.close()
3845 # Sanity checks.
3846 self.assertIsInstance(remote, ssl.SSLSocket)
3847 self.assertEqual(peer, client_addr)
3848
3849 def test_getpeercert_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003850 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3851 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003852 with context.wrap_socket(socket.socket()) as sock:
3853 with self.assertRaises(OSError) as cm:
3854 sock.getpeercert()
3855 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3856
3857 def test_do_handshake_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003858 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3859 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003860 with context.wrap_socket(socket.socket()) as sock:
3861 with self.assertRaises(OSError) as cm:
3862 sock.do_handshake()
3863 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3864
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003865 def test_no_shared_ciphers(self):
3866 client_context, server_context, hostname = testing_context()
3867 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
Miss Islington (bot)4becc562021-06-13 05:07:00 -07003868 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Victor Stinner5e922652018-09-07 17:30:33 +02003869 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003870 client_context.set_ciphers("AES128")
3871 server_context.set_ciphers("AES256")
3872 with ThreadedEchoServer(context=server_context) as server:
3873 with client_context.wrap_socket(socket.socket(),
3874 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003875 with self.assertRaises(OSError):
3876 s.connect((HOST, server.port))
3877 self.assertIn("no shared cipher", server.conn_errors[0])
3878
3879 def test_version_basic(self):
3880 """
3881 Basic tests for SSLSocket.version().
3882 More tests are done in the test_protocol_*() methods.
3883 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003884 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3885 context.check_hostname = False
3886 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003887 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003888 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003889 chatty=False) as server:
3890 with context.wrap_socket(socket.socket()) as s:
3891 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003892 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003893 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003894 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003895 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003896 self.assertIs(s.version(), None)
3897
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003898 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003899 def test_tls1_3(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003900 client_context, server_context, hostname = testing_context()
3901 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3902 with ThreadedEchoServer(context=server_context) as server:
3903 with client_context.wrap_socket(socket.socket(),
3904 server_hostname=hostname) as s:
Christian Heimescb5b68a2017-09-07 18:07:00 -07003905 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003906 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003907 'TLS_AES_256_GCM_SHA384',
3908 'TLS_CHACHA20_POLY1305_SHA256',
3909 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003910 })
3911 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003912
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003913 @requires_tls_version('TLSv1_2')
Christian Heimes2875c602021-04-19 07:27:10 +02003914 @requires_tls_version('TLSv1')
3915 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003916 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003917 client_context, server_context, hostname = testing_context()
3918 # client TLSv1.0 to 1.2
3919 client_context.minimum_version = ssl.TLSVersion.TLSv1
3920 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3921 # server only TLSv1.2
3922 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3923 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3924
3925 with ThreadedEchoServer(context=server_context) as server:
3926 with client_context.wrap_socket(socket.socket(),
3927 server_hostname=hostname) as s:
3928 s.connect((HOST, server.port))
3929 self.assertEqual(s.version(), 'TLSv1.2')
3930
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003931 @requires_tls_version('TLSv1_1')
Christian Heimes2875c602021-04-19 07:27:10 +02003932 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003933 def test_min_max_version_tlsv1_1(self):
3934 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003935 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003936 client_context.minimum_version = ssl.TLSVersion.TLSv1
3937 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003938 server_context.minimum_version = ssl.TLSVersion.TLSv1
3939 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003940 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003941
3942 with ThreadedEchoServer(context=server_context) as server:
3943 with client_context.wrap_socket(socket.socket(),
3944 server_hostname=hostname) as s:
3945 s.connect((HOST, server.port))
3946 self.assertEqual(s.version(), 'TLSv1.1')
3947
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003948 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003949 @requires_tls_version('TLSv1')
Christian Heimes2875c602021-04-19 07:27:10 +02003950 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003951 def test_min_max_version_mismatch(self):
3952 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003953 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003954 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003955 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003956 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003957 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003958 seclevel_workaround(client_context, server_context)
3959
Christian Heimes698dde12018-02-27 11:54:43 +01003960 with ThreadedEchoServer(context=server_context) as server:
3961 with client_context.wrap_socket(socket.socket(),
3962 server_hostname=hostname) as s:
3963 with self.assertRaises(ssl.SSLError) as e:
3964 s.connect((HOST, server.port))
3965 self.assertIn("alert", str(e.exception))
3966
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003967 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003968 def test_min_max_version_sslv3(self):
3969 client_context, server_context, hostname = testing_context()
3970 server_context.minimum_version = ssl.TLSVersion.SSLv3
3971 client_context.minimum_version = ssl.TLSVersion.SSLv3
3972 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003973 seclevel_workaround(client_context, server_context)
3974
Christian Heimes698dde12018-02-27 11:54:43 +01003975 with ThreadedEchoServer(context=server_context) as server:
3976 with client_context.wrap_socket(socket.socket(),
3977 server_hostname=hostname) as s:
3978 s.connect((HOST, server.port))
3979 self.assertEqual(s.version(), 'SSLv3')
3980
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003981 def test_default_ecdh_curve(self):
3982 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3983 # should be enabled by default on SSL contexts.
Christian Heimes2875c602021-04-19 07:27:10 +02003984 client_context, server_context, hostname = testing_context()
Christian Heimescb5b68a2017-09-07 18:07:00 -07003985 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3986 # cipher name.
Christian Heimes2875c602021-04-19 07:27:10 +02003987 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003988 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3989 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3990 # our default cipher list should prefer ECDH-based ciphers
3991 # automatically.
Christian Heimes2875c602021-04-19 07:27:10 +02003992 with ThreadedEchoServer(context=server_context) as server:
3993 with client_context.wrap_socket(socket.socket(),
3994 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003995 s.connect((HOST, server.port))
3996 self.assertIn("ECDH", s.cipher()[0])
3997
3998 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3999 "'tls-unique' channel binding not available")
4000 def test_tls_unique_channel_binding(self):
4001 """Test tls-unique channel binding."""
4002 if support.verbose:
4003 sys.stdout.write("\n")
4004
Christian Heimes05d9fe32018-02-27 08:55:39 +01004005 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004006
4007 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004008 chatty=True,
4009 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01004010
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004011 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01004012 with client_context.wrap_socket(
4013 socket.socket(),
4014 server_hostname=hostname) as s:
4015 s.connect((HOST, server.port))
4016 # get the data
4017 cb_data = s.get_channel_binding("tls-unique")
4018 if support.verbose:
4019 sys.stdout.write(
4020 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004021
Christian Heimes05d9fe32018-02-27 08:55:39 +01004022 # check if it is sane
4023 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02004024 if s.version() == 'TLSv1.3':
4025 self.assertEqual(len(cb_data), 48)
4026 else:
4027 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004028
Christian Heimes05d9fe32018-02-27 08:55:39 +01004029 # and compare with the peers version
4030 s.write(b"CB tls-unique\n")
4031 peer_data_repr = s.read().strip()
4032 self.assertEqual(peer_data_repr,
4033 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004034
4035 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01004036 with client_context.wrap_socket(
4037 socket.socket(),
4038 server_hostname=hostname) as s:
4039 s.connect((HOST, server.port))
4040 new_cb_data = s.get_channel_binding("tls-unique")
4041 if support.verbose:
4042 sys.stdout.write(
4043 "got another channel binding data: {0!r}\n".format(
4044 new_cb_data)
4045 )
4046 # is it really unique
4047 self.assertNotEqual(cb_data, new_cb_data)
4048 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02004049 if s.version() == 'TLSv1.3':
4050 self.assertEqual(len(cb_data), 48)
4051 else:
4052 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01004053 s.write(b"CB tls-unique\n")
4054 peer_data_repr = s.read().strip()
4055 self.assertEqual(peer_data_repr,
4056 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004057
4058 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004059 client_context, server_context, hostname = testing_context()
4060 stats = server_params_test(client_context, server_context,
4061 chatty=True, connectionchatty=True,
4062 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004063 if support.verbose:
4064 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
4065 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
4066
4067 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
4068 "ssl.OP_NO_COMPRESSION needed for this test")
4069 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004070 client_context, server_context, hostname = testing_context()
4071 client_context.options |= ssl.OP_NO_COMPRESSION
4072 server_context.options |= ssl.OP_NO_COMPRESSION
4073 stats = server_params_test(client_context, server_context,
4074 chatty=True, connectionchatty=True,
4075 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004076 self.assertIs(stats['compression'], None)
4077
Paul Monsonf3550692019-06-19 13:09:54 -07004078 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004079 def test_dh_params(self):
4080 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004081 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004082 # test scenario needs TLS <= 1.2
Miss Islington (bot)4becc562021-06-13 05:07:00 -07004083 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +02004084 server_context.load_dh_params(DHFILE)
4085 server_context.set_ciphers("kEDH")
Miss Islington (bot)4becc562021-06-13 05:07:00 -07004086 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +02004087 stats = server_params_test(client_context, server_context,
4088 chatty=True, connectionchatty=True,
4089 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004090 cipher = stats["cipher"][0]
4091 parts = cipher.split("-")
4092 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4093 self.fail("Non-DH cipher: " + cipher[0])
4094
Christian Heimesb7b92252018-02-25 09:49:31 +01004095 def test_ecdh_curve(self):
4096 # server secp384r1, client auto
4097 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004098
Christian Heimesb7b92252018-02-25 09:49:31 +01004099 server_context.set_ecdh_curve("secp384r1")
4100 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004101 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004102 stats = server_params_test(client_context, server_context,
4103 chatty=True, connectionchatty=True,
4104 sni_name=hostname)
4105
4106 # server auto, client secp384r1
4107 client_context, server_context, hostname = testing_context()
4108 client_context.set_ecdh_curve("secp384r1")
4109 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004110 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004111 stats = server_params_test(client_context, server_context,
4112 chatty=True, connectionchatty=True,
4113 sni_name=hostname)
4114
4115 # server / client curve mismatch
4116 client_context, server_context, hostname = testing_context()
4117 client_context.set_ecdh_curve("prime256v1")
4118 server_context.set_ecdh_curve("secp384r1")
4119 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004120 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
4121 with self.assertRaises(ssl.SSLError):
Christian Heimes39258d32021-04-17 11:36:35 +02004122 server_params_test(client_context, server_context,
4123 chatty=True, connectionchatty=True,
4124 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004125
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004126 def test_selected_alpn_protocol(self):
4127 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004128 client_context, server_context, hostname = testing_context()
4129 stats = server_params_test(client_context, server_context,
4130 chatty=True, connectionchatty=True,
4131 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004132 self.assertIs(stats['client_alpn_protocol'], None)
4133
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004134 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4135 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004136 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004137 server_context.set_alpn_protocols(['foo', 'bar'])
4138 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004139 chatty=True, connectionchatty=True,
4140 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004141 self.assertIs(stats['client_alpn_protocol'], None)
4142
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004143 def test_alpn_protocols(self):
4144 server_protocols = ['foo', 'bar', 'milkshake']
4145 protocol_tests = [
4146 (['foo', 'bar'], 'foo'),
4147 (['bar', 'foo'], 'foo'),
4148 (['milkshake'], 'milkshake'),
4149 (['http/3.0', 'http/4.0'], None)
4150 ]
4151 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004152 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004153 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004154 client_context.set_alpn_protocols(client_protocols)
4155
4156 try:
4157 stats = server_params_test(client_context,
4158 server_context,
4159 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004160 connectionchatty=True,
4161 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004162 except ssl.SSLError as e:
4163 stats = e
4164
Christian Heimes39258d32021-04-17 11:36:35 +02004165 msg = "failed trying %s (s) and %s (c).\n" \
4166 "was expecting %s, but got %%s from the %%s" \
4167 % (str(server_protocols), str(client_protocols),
4168 str(expected))
4169 client_result = stats['client_alpn_protocol']
4170 self.assertEqual(client_result, expected,
4171 msg % (client_result, "client"))
4172 server_result = stats['server_alpn_protocols'][-1] \
4173 if len(stats['server_alpn_protocols']) else 'nothing'
4174 self.assertEqual(server_result, expected,
4175 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004176
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004177 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004178 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004179
4180 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004181 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004182 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004183 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004184 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004185 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004186 client_context.load_verify_locations(SIGNING_CA)
4187 return server_context, other_context, client_context
4188
4189 def check_common_name(self, stats, name):
4190 cert = stats['peercert']
4191 self.assertIn((('commonName', name),), cert['subject'])
4192
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004193 def test_sni_callback(self):
4194 calls = []
4195 server_context, other_context, client_context = self.sni_contexts()
4196
Christian Heimesa170fa12017-09-15 20:27:30 +02004197 client_context.check_hostname = False
4198
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004199 def servername_cb(ssl_sock, server_name, initial_context):
4200 calls.append((server_name, initial_context))
4201 if server_name is not None:
4202 ssl_sock.context = other_context
4203 server_context.set_servername_callback(servername_cb)
4204
4205 stats = server_params_test(client_context, server_context,
4206 chatty=True,
4207 sni_name='supermessage')
4208 # The hostname was fetched properly, and the certificate was
4209 # changed for the connection.
4210 self.assertEqual(calls, [("supermessage", server_context)])
4211 # CERTFILE4 was selected
4212 self.check_common_name(stats, 'fakehostname')
4213
4214 calls = []
4215 # The callback is called with server_name=None
4216 stats = server_params_test(client_context, server_context,
4217 chatty=True,
4218 sni_name=None)
4219 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004220 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004221
4222 # Check disabling the callback
4223 calls = []
4224 server_context.set_servername_callback(None)
4225
4226 stats = server_params_test(client_context, server_context,
4227 chatty=True,
4228 sni_name='notfunny')
4229 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004230 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004231 self.assertEqual(calls, [])
4232
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004233 def test_sni_callback_alert(self):
4234 # Returning a TLS alert is reflected to the connecting client
4235 server_context, other_context, client_context = self.sni_contexts()
4236
4237 def cb_returning_alert(ssl_sock, server_name, initial_context):
4238 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4239 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004240 with self.assertRaises(ssl.SSLError) as cm:
4241 stats = server_params_test(client_context, server_context,
4242 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004243 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004244 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004245
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004246 def test_sni_callback_raising(self):
4247 # Raising fails the connection with a TLS handshake failure alert.
4248 server_context, other_context, client_context = self.sni_contexts()
4249
4250 def cb_raising(ssl_sock, server_name, initial_context):
4251 1/0
4252 server_context.set_servername_callback(cb_raising)
4253
Victor Stinner00253502019-06-03 03:51:43 +02004254 with support.catch_unraisable_exception() as catch:
4255 with self.assertRaises(ssl.SSLError) as cm:
4256 stats = server_params_test(client_context, server_context,
4257 chatty=False,
4258 sni_name='supermessage')
4259
4260 self.assertEqual(cm.exception.reason,
4261 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4262 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004263
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004264 def test_sni_callback_wrong_return_type(self):
4265 # Returning the wrong return type terminates the TLS connection
4266 # with an internal error alert.
4267 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004268
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004269 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4270 return "foo"
4271 server_context.set_servername_callback(cb_wrong_return_type)
4272
Victor Stinner00253502019-06-03 03:51:43 +02004273 with support.catch_unraisable_exception() as catch:
4274 with self.assertRaises(ssl.SSLError) as cm:
4275 stats = server_params_test(client_context, server_context,
4276 chatty=False,
4277 sni_name='supermessage')
4278
4279
4280 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4281 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004282
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004283 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004284 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004285 client_context.set_ciphers("AES128:AES256")
4286 server_context.set_ciphers("AES256")
4287 expected_algs = [
4288 "AES256", "AES-256",
4289 # TLS 1.3 ciphers are always enabled
4290 "TLS_CHACHA20", "TLS_AES",
4291 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004292
Christian Heimesa170fa12017-09-15 20:27:30 +02004293 stats = server_params_test(client_context, server_context,
4294 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004295 ciphers = stats['server_shared_ciphers'][0]
4296 self.assertGreater(len(ciphers), 0)
4297 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004298 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004299 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004300
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004301 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004302 client_context, server_context, hostname = testing_context()
4303 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004304
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004305 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004306 s = client_context.wrap_socket(socket.socket(),
4307 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004308 s.connect((HOST, server.port))
4309 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004310
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004311 self.assertRaises(ValueError, s.read, 1024)
4312 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004313
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004314 def test_sendfile(self):
4315 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004316 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004317 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004318 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimes2875c602021-04-19 07:27:10 +02004319 client_context, server_context, hostname = testing_context()
4320 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004321 with server:
Christian Heimes2875c602021-04-19 07:27:10 +02004322 with client_context.wrap_socket(socket.socket(),
4323 server_hostname=hostname) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004324 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004325 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004326 s.sendfile(file)
4327 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004328
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004329 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004330 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004331 # TODO: sessions aren't compatible with TLSv1.3 yet
Miss Islington (bot)4becc562021-06-13 05:07:00 -07004332 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004333
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004334 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004335 stats = server_params_test(client_context, server_context,
4336 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004337 session = stats['session']
4338 self.assertTrue(session.id)
4339 self.assertGreater(session.time, 0)
4340 self.assertGreater(session.timeout, 0)
4341 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004342 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004343 self.assertFalse(stats['session_reused'])
4344 sess_stat = server_context.session_stats()
4345 self.assertEqual(sess_stat['accept'], 1)
4346 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004347
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004348 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004349 stats = server_params_test(client_context, server_context,
4350 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004351 sess_stat = server_context.session_stats()
4352 self.assertEqual(sess_stat['accept'], 2)
4353 self.assertEqual(sess_stat['hits'], 1)
4354 self.assertTrue(stats['session_reused'])
4355 session2 = stats['session']
4356 self.assertEqual(session2.id, session.id)
4357 self.assertEqual(session2, session)
4358 self.assertIsNot(session2, session)
4359 self.assertGreaterEqual(session2.time, session.time)
4360 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004361
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004362 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004363 stats = server_params_test(client_context, server_context,
4364 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004365 self.assertFalse(stats['session_reused'])
4366 session3 = stats['session']
4367 self.assertNotEqual(session3.id, session.id)
4368 self.assertNotEqual(session3, session)
4369 sess_stat = server_context.session_stats()
4370 self.assertEqual(sess_stat['accept'], 3)
4371 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004372
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004373 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004374 stats = server_params_test(client_context, server_context,
4375 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004376 self.assertTrue(stats['session_reused'])
4377 session4 = stats['session']
4378 self.assertEqual(session4.id, session.id)
4379 self.assertEqual(session4, session)
4380 self.assertGreaterEqual(session4.time, session.time)
4381 self.assertGreaterEqual(session4.timeout, session.timeout)
4382 sess_stat = server_context.session_stats()
4383 self.assertEqual(sess_stat['accept'], 4)
4384 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004385
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004386 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004387 client_context, server_context, hostname = testing_context()
4388 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004389
Christian Heimes05d9fe32018-02-27 08:55:39 +01004390 # TODO: session reuse does not work with TLSv1.3
Miss Islington (bot)4becc562021-06-13 05:07:00 -07004391 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4392 client_context2.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimescb5b68a2017-09-07 18:07:00 -07004393
Christian Heimesa170fa12017-09-15 20:27:30 +02004394 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004395 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004396 with client_context.wrap_socket(socket.socket(),
4397 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004398 # session is None before handshake
4399 self.assertEqual(s.session, None)
4400 self.assertEqual(s.session_reused, None)
4401 s.connect((HOST, server.port))
4402 session = s.session
4403 self.assertTrue(session)
4404 with self.assertRaises(TypeError) as e:
4405 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004406 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004407
Christian Heimesa170fa12017-09-15 20:27:30 +02004408 with client_context.wrap_socket(socket.socket(),
4409 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004410 s.connect((HOST, server.port))
4411 # cannot set session after handshake
4412 with self.assertRaises(ValueError) as e:
4413 s.session = session
4414 self.assertEqual(str(e.exception),
4415 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004416
Christian Heimesa170fa12017-09-15 20:27:30 +02004417 with client_context.wrap_socket(socket.socket(),
4418 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004419 # can set session before handshake and before the
4420 # connection was established
4421 s.session = session
4422 s.connect((HOST, server.port))
4423 self.assertEqual(s.session.id, session.id)
4424 self.assertEqual(s.session, session)
4425 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004426
Christian Heimesa170fa12017-09-15 20:27:30 +02004427 with client_context2.wrap_socket(socket.socket(),
4428 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004429 # cannot re-use session with a different SSLContext
4430 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004431 s.session = session
4432 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004433 self.assertEqual(str(e.exception),
4434 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004435
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004436
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004437@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004438class TestPostHandshakeAuth(unittest.TestCase):
4439 def test_pha_setter(self):
4440 protocols = [
Christian Heimes2875c602021-04-19 07:27:10 +02004441 ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
Christian Heimes9fb051f2018-09-23 08:32:31 +02004442 ]
4443 for protocol in protocols:
4444 ctx = ssl.SSLContext(protocol)
4445 self.assertEqual(ctx.post_handshake_auth, False)
4446
4447 ctx.post_handshake_auth = True
4448 self.assertEqual(ctx.post_handshake_auth, True)
4449
4450 ctx.verify_mode = ssl.CERT_REQUIRED
4451 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4452 self.assertEqual(ctx.post_handshake_auth, True)
4453
4454 ctx.post_handshake_auth = False
4455 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4456 self.assertEqual(ctx.post_handshake_auth, False)
4457
4458 ctx.verify_mode = ssl.CERT_OPTIONAL
4459 ctx.post_handshake_auth = True
4460 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4461 self.assertEqual(ctx.post_handshake_auth, True)
4462
4463 def test_pha_required(self):
4464 client_context, server_context, hostname = testing_context()
4465 server_context.post_handshake_auth = True
4466 server_context.verify_mode = ssl.CERT_REQUIRED
4467 client_context.post_handshake_auth = True
4468 client_context.load_cert_chain(SIGNED_CERTFILE)
4469
4470 server = ThreadedEchoServer(context=server_context, chatty=False)
4471 with server:
4472 with client_context.wrap_socket(socket.socket(),
4473 server_hostname=hostname) as s:
4474 s.connect((HOST, server.port))
4475 s.write(b'HASCERT')
4476 self.assertEqual(s.recv(1024), b'FALSE\n')
4477 s.write(b'PHA')
4478 self.assertEqual(s.recv(1024), b'OK\n')
4479 s.write(b'HASCERT')
4480 self.assertEqual(s.recv(1024), b'TRUE\n')
4481 # PHA method just returns true when cert is already available
4482 s.write(b'PHA')
4483 self.assertEqual(s.recv(1024), b'OK\n')
4484 s.write(b'GETCERT')
4485 cert_text = s.recv(4096).decode('us-ascii')
4486 self.assertIn('Python Software Foundation CA', cert_text)
4487
4488 def test_pha_required_nocert(self):
4489 client_context, server_context, hostname = testing_context()
4490 server_context.post_handshake_auth = True
4491 server_context.verify_mode = ssl.CERT_REQUIRED
4492 client_context.post_handshake_auth = True
4493
Christian Heimesc8666cf2021-04-24 09:17:54 +02004494 def msg_cb(conn, direction, version, content_type, msg_type, data):
4495 if support.verbose and content_type == _TLSContentType.ALERT:
4496 info = (conn, direction, version, content_type, msg_type, data)
4497 sys.stdout.write(f"TLS: {info!r}\n")
4498
4499 server_context._msg_callback = msg_cb
4500 client_context._msg_callback = msg_cb
4501
4502 server = ThreadedEchoServer(context=server_context, chatty=True)
4503 with server:
4504 with client_context.wrap_socket(socket.socket(),
Miss Islington (bot)d2ab15f2021-06-03 13:15:15 -07004505 server_hostname=hostname,
4506 suppress_ragged_eofs=False) as s:
Christian Heimesc8666cf2021-04-24 09:17:54 +02004507 s.connect((HOST, server.port))
4508 s.write(b'PHA')
Christian Heimesce9a0642021-04-24 15:08:13 +02004509 # test sometimes fails with EOF error. Test passes as long as
4510 # server aborts connection with an error.
Christian Heimesc8666cf2021-04-24 09:17:54 +02004511 with self.assertRaisesRegex(
4512 ssl.SSLError,
Christian Heimesce9a0642021-04-24 15:08:13 +02004513 '(certificate required|EOF occurred)'
Christian Heimesc8666cf2021-04-24 09:17:54 +02004514 ):
Victor Stinner73ea5462019-07-09 14:33:49 +02004515 # receive CertificateRequest
Miss Islington (bot)e5e93e62021-06-02 16:48:40 -07004516 data = s.recv(1024)
Miss Islington (bot)e5e93e62021-06-02 16:48:40 -07004517 self.assertEqual(data, b'OK\n')
4518
Victor Stinner73ea5462019-07-09 14:33:49 +02004519 # send empty Certificate + Finish
4520 s.write(b'HASCERT')
Miss Islington (bot)e5e93e62021-06-02 16:48:40 -07004521
Victor Stinner73ea5462019-07-09 14:33:49 +02004522 # receive alert
Miss Islington (bot)d2ab15f2021-06-03 13:15:15 -07004523 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004524
4525 def test_pha_optional(self):
4526 if support.verbose:
4527 sys.stdout.write("\n")
4528
4529 client_context, server_context, hostname = testing_context()
4530 server_context.post_handshake_auth = True
4531 server_context.verify_mode = ssl.CERT_REQUIRED
4532 client_context.post_handshake_auth = True
4533 client_context.load_cert_chain(SIGNED_CERTFILE)
4534
4535 # check CERT_OPTIONAL
4536 server_context.verify_mode = ssl.CERT_OPTIONAL
4537 server = ThreadedEchoServer(context=server_context, chatty=False)
4538 with server:
4539 with client_context.wrap_socket(socket.socket(),
4540 server_hostname=hostname) as s:
4541 s.connect((HOST, server.port))
4542 s.write(b'HASCERT')
4543 self.assertEqual(s.recv(1024), b'FALSE\n')
4544 s.write(b'PHA')
4545 self.assertEqual(s.recv(1024), b'OK\n')
4546 s.write(b'HASCERT')
4547 self.assertEqual(s.recv(1024), b'TRUE\n')
4548
4549 def test_pha_optional_nocert(self):
4550 if support.verbose:
4551 sys.stdout.write("\n")
4552
4553 client_context, server_context, hostname = testing_context()
4554 server_context.post_handshake_auth = True
4555 server_context.verify_mode = ssl.CERT_OPTIONAL
4556 client_context.post_handshake_auth = True
4557
4558 server = ThreadedEchoServer(context=server_context, chatty=False)
4559 with server:
4560 with client_context.wrap_socket(socket.socket(),
4561 server_hostname=hostname) as s:
4562 s.connect((HOST, server.port))
4563 s.write(b'HASCERT')
4564 self.assertEqual(s.recv(1024), b'FALSE\n')
4565 s.write(b'PHA')
4566 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004567 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004568 s.write(b'HASCERT')
4569 self.assertEqual(s.recv(1024), b'FALSE\n')
4570
4571 def test_pha_no_pha_client(self):
4572 client_context, server_context, hostname = testing_context()
4573 server_context.post_handshake_auth = True
4574 server_context.verify_mode = ssl.CERT_REQUIRED
4575 client_context.load_cert_chain(SIGNED_CERTFILE)
4576
4577 server = ThreadedEchoServer(context=server_context, chatty=False)
4578 with server:
4579 with client_context.wrap_socket(socket.socket(),
4580 server_hostname=hostname) as s:
4581 s.connect((HOST, server.port))
4582 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4583 s.verify_client_post_handshake()
4584 s.write(b'PHA')
4585 self.assertIn(b'extension not received', s.recv(1024))
4586
4587 def test_pha_no_pha_server(self):
4588 # server doesn't have PHA enabled, cert is requested in handshake
4589 client_context, server_context, hostname = testing_context()
4590 server_context.verify_mode = ssl.CERT_REQUIRED
4591 client_context.post_handshake_auth = True
4592 client_context.load_cert_chain(SIGNED_CERTFILE)
4593
4594 server = ThreadedEchoServer(context=server_context, chatty=False)
4595 with server:
4596 with client_context.wrap_socket(socket.socket(),
4597 server_hostname=hostname) as s:
4598 s.connect((HOST, server.port))
4599 s.write(b'HASCERT')
4600 self.assertEqual(s.recv(1024), b'TRUE\n')
4601 # PHA doesn't fail if there is already a cert
4602 s.write(b'PHA')
4603 self.assertEqual(s.recv(1024), b'OK\n')
4604 s.write(b'HASCERT')
4605 self.assertEqual(s.recv(1024), b'TRUE\n')
4606
4607 def test_pha_not_tls13(self):
4608 # TLS 1.2
4609 client_context, server_context, hostname = testing_context()
4610 server_context.verify_mode = ssl.CERT_REQUIRED
4611 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4612 client_context.post_handshake_auth = True
4613 client_context.load_cert_chain(SIGNED_CERTFILE)
4614
4615 server = ThreadedEchoServer(context=server_context, chatty=False)
4616 with server:
4617 with client_context.wrap_socket(socket.socket(),
4618 server_hostname=hostname) as s:
4619 s.connect((HOST, server.port))
4620 # PHA fails for TLS != 1.3
4621 s.write(b'PHA')
4622 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4623
Christian Heimesf0f59302019-07-01 08:29:17 +02004624 def test_bpo37428_pha_cert_none(self):
4625 # verify that post_handshake_auth does not implicitly enable cert
4626 # validation.
4627 hostname = SIGNED_CERTFILE_HOSTNAME
4628 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4629 client_context.post_handshake_auth = True
4630 client_context.load_cert_chain(SIGNED_CERTFILE)
4631 # no cert validation and CA on client side
4632 client_context.check_hostname = False
4633 client_context.verify_mode = ssl.CERT_NONE
4634
4635 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4636 server_context.load_cert_chain(SIGNED_CERTFILE)
4637 server_context.load_verify_locations(SIGNING_CA)
4638 server_context.post_handshake_auth = True
4639 server_context.verify_mode = ssl.CERT_REQUIRED
4640
4641 server = ThreadedEchoServer(context=server_context, chatty=False)
4642 with server:
4643 with client_context.wrap_socket(socket.socket(),
4644 server_hostname=hostname) as s:
4645 s.connect((HOST, server.port))
4646 s.write(b'HASCERT')
4647 self.assertEqual(s.recv(1024), b'FALSE\n')
4648 s.write(b'PHA')
4649 self.assertEqual(s.recv(1024), b'OK\n')
4650 s.write(b'HASCERT')
4651 self.assertEqual(s.recv(1024), b'TRUE\n')
4652 # server cert has not been validated
4653 self.assertEqual(s.getpeercert(), {})
4654
Christian Heimes666991f2021-04-26 15:01:40 +02004655 def test_internal_chain_client(self):
4656 client_context, server_context, hostname = testing_context(
4657 server_chain=False
4658 )
4659 server = ThreadedEchoServer(context=server_context, chatty=False)
4660 with server:
4661 with client_context.wrap_socket(
4662 socket.socket(),
4663 server_hostname=hostname
4664 ) as s:
4665 s.connect((HOST, server.port))
4666 vc = s._sslobj.get_verified_chain()
4667 self.assertEqual(len(vc), 2)
4668 ee, ca = vc
4669 uvc = s._sslobj.get_unverified_chain()
4670 self.assertEqual(len(uvc), 1)
4671
4672 self.assertEqual(ee, uvc[0])
4673 self.assertEqual(hash(ee), hash(uvc[0]))
4674 self.assertEqual(repr(ee), repr(uvc[0]))
4675
4676 self.assertNotEqual(ee, ca)
4677 self.assertNotEqual(hash(ee), hash(ca))
4678 self.assertNotEqual(repr(ee), repr(ca))
4679 self.assertNotEqual(ee.get_info(), ca.get_info())
4680 self.assertIn("CN=localhost", repr(ee))
4681 self.assertIn("CN=our-ca-server", repr(ca))
4682
4683 pem = ee.public_bytes(_ssl.ENCODING_PEM)
4684 der = ee.public_bytes(_ssl.ENCODING_DER)
4685 self.assertIsInstance(pem, str)
4686 self.assertIn("-----BEGIN CERTIFICATE-----", pem)
4687 self.assertIsInstance(der, bytes)
4688 self.assertEqual(
4689 ssl.PEM_cert_to_DER_cert(pem), der
4690 )
4691
4692 def test_internal_chain_server(self):
4693 client_context, server_context, hostname = testing_context()
4694 client_context.load_cert_chain(SIGNED_CERTFILE)
4695 server_context.verify_mode = ssl.CERT_REQUIRED
4696 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
4697
4698 server = ThreadedEchoServer(context=server_context, chatty=False)
4699 with server:
4700 with client_context.wrap_socket(
4701 socket.socket(),
4702 server_hostname=hostname
4703 ) as s:
4704 s.connect((HOST, server.port))
4705 s.write(b'VERIFIEDCHAIN\n')
4706 res = s.recv(1024)
4707 self.assertEqual(res, b'\x02\n')
4708 s.write(b'UNVERIFIEDCHAIN\n')
4709 res = s.recv(1024)
4710 self.assertEqual(res, b'\x02\n')
4711
Christian Heimes9fb051f2018-09-23 08:32:31 +02004712
Christian Heimesc7f70692019-05-31 11:44:05 +02004713HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4714requires_keylog = unittest.skipUnless(
4715 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4716
4717class TestSSLDebug(unittest.TestCase):
4718
Hai Shia7f5d932020-08-04 00:41:24 +08004719 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004720 with open(fname) as f:
4721 return len(list(f))
4722
4723 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004724 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004725 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004726 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004727 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4728 self.assertEqual(ctx.keylog_filename, None)
4729
Hai Shia7f5d932020-08-04 00:41:24 +08004730 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4731 ctx.keylog_filename = os_helper.TESTFN
4732 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4733 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004734 self.assertEqual(self.keylog_lines(), 1)
4735
4736 ctx.keylog_filename = None
4737 self.assertEqual(ctx.keylog_filename, None)
4738
4739 with self.assertRaises((IsADirectoryError, PermissionError)):
4740 # Windows raises PermissionError
4741 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004742 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004743
4744 with self.assertRaises(TypeError):
4745 ctx.keylog_filename = 1
4746
4747 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004748 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004749 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004750 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004751 client_context, server_context, hostname = testing_context()
4752
Hai Shia7f5d932020-08-04 00:41:24 +08004753 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004754 server = ThreadedEchoServer(context=server_context, chatty=False)
4755 with server:
4756 with client_context.wrap_socket(socket.socket(),
4757 server_hostname=hostname) as s:
4758 s.connect((HOST, server.port))
4759 # header, 5 lines for TLS 1.3
4760 self.assertEqual(self.keylog_lines(), 6)
4761
4762 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004763 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004764 server = ThreadedEchoServer(context=server_context, chatty=False)
4765 with server:
4766 with client_context.wrap_socket(socket.socket(),
4767 server_hostname=hostname) as s:
4768 s.connect((HOST, server.port))
4769 self.assertGreaterEqual(self.keylog_lines(), 11)
4770
Hai Shia7f5d932020-08-04 00:41:24 +08004771 client_context.keylog_filename = os_helper.TESTFN
4772 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004773 server = ThreadedEchoServer(context=server_context, chatty=False)
4774 with server:
4775 with client_context.wrap_socket(socket.socket(),
4776 server_hostname=hostname) as s:
4777 s.connect((HOST, server.port))
4778 self.assertGreaterEqual(self.keylog_lines(), 21)
4779
4780 client_context.keylog_filename = None
4781 server_context.keylog_filename = None
4782
4783 @requires_keylog
4784 @unittest.skipIf(sys.flags.ignore_environment,
4785 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004786 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004787 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004788 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004789 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004790 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4791 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004792
4793 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4794 self.assertEqual(ctx.keylog_filename, None)
4795
4796 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004797 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004798
4799 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004800 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004801
4802 def test_msg_callback(self):
4803 client_context, server_context, hostname = testing_context()
4804
4805 def msg_cb(conn, direction, version, content_type, msg_type, data):
4806 pass
4807
4808 self.assertIs(client_context._msg_callback, None)
4809 client_context._msg_callback = msg_cb
4810 self.assertIs(client_context._msg_callback, msg_cb)
4811 with self.assertRaises(TypeError):
4812 client_context._msg_callback = object()
4813
4814 def test_msg_callback_tls12(self):
4815 client_context, server_context, hostname = testing_context()
Miss Islington (bot)4becc562021-06-13 05:07:00 -07004816 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc7f70692019-05-31 11:44:05 +02004817
4818 msg = []
4819
4820 def msg_cb(conn, direction, version, content_type, msg_type, data):
4821 self.assertIsInstance(conn, ssl.SSLSocket)
4822 self.assertIsInstance(data, bytes)
4823 self.assertIn(direction, {'read', 'write'})
4824 msg.append((direction, version, content_type, msg_type))
4825
4826 client_context._msg_callback = msg_cb
4827
4828 server = ThreadedEchoServer(context=server_context, chatty=False)
4829 with server:
4830 with client_context.wrap_socket(socket.socket(),
4831 server_hostname=hostname) as s:
4832 s.connect((HOST, server.port))
4833
Christian Heimese35d1ba2019-06-03 20:40:15 +02004834 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004835 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4836 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004837 msg
4838 )
4839 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004840 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4841 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004842 msg
4843 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004844
Christian Heimes77cde502021-03-21 16:13:09 +01004845 def test_msg_callback_deadlock_bpo43577(self):
4846 client_context, server_context, hostname = testing_context()
4847 server_context2 = testing_context()[1]
4848
4849 def msg_cb(conn, direction, version, content_type, msg_type, data):
4850 pass
4851
4852 def sni_cb(sock, servername, ctx):
4853 sock.context = server_context2
4854
4855 server_context._msg_callback = msg_cb
4856 server_context.sni_callback = sni_cb
4857
4858 server = ThreadedEchoServer(context=server_context, chatty=False)
4859 with server:
4860 with client_context.wrap_socket(socket.socket(),
4861 server_hostname=hostname) as s:
4862 s.connect((HOST, server.port))
4863 with client_context.wrap_socket(socket.socket(),
4864 server_hostname=hostname) as s:
4865 s.connect((HOST, server.port))
4866
Christian Heimesc7f70692019-05-31 11:44:05 +02004867
Ethan Furmana02cb472021-04-21 10:20:44 -07004868class TestEnumerations(unittest.TestCase):
4869
4870 def test_tlsversion(self):
4871 class CheckedTLSVersion(enum.IntEnum):
4872 MINIMUM_SUPPORTED = _ssl.PROTO_MINIMUM_SUPPORTED
4873 SSLv3 = _ssl.PROTO_SSLv3
4874 TLSv1 = _ssl.PROTO_TLSv1
4875 TLSv1_1 = _ssl.PROTO_TLSv1_1
4876 TLSv1_2 = _ssl.PROTO_TLSv1_2
4877 TLSv1_3 = _ssl.PROTO_TLSv1_3
4878 MAXIMUM_SUPPORTED = _ssl.PROTO_MAXIMUM_SUPPORTED
4879 enum._test_simple_enum(CheckedTLSVersion, TLSVersion)
4880
4881 def test_tlscontenttype(self):
4882 class Checked_TLSContentType(enum.IntEnum):
4883 """Content types (record layer)
4884
4885 See RFC 8446, section B.1
4886 """
4887 CHANGE_CIPHER_SPEC = 20
4888 ALERT = 21
4889 HANDSHAKE = 22
4890 APPLICATION_DATA = 23
4891 # pseudo content types
4892 HEADER = 0x100
4893 INNER_CONTENT_TYPE = 0x101
4894 enum._test_simple_enum(Checked_TLSContentType, _TLSContentType)
4895
4896 def test_tlsalerttype(self):
4897 class Checked_TLSAlertType(enum.IntEnum):
4898 """Alert types for TLSContentType.ALERT messages
4899
4900 See RFC 8466, section B.2
4901 """
4902 CLOSE_NOTIFY = 0
4903 UNEXPECTED_MESSAGE = 10
4904 BAD_RECORD_MAC = 20
4905 DECRYPTION_FAILED = 21
4906 RECORD_OVERFLOW = 22
4907 DECOMPRESSION_FAILURE = 30
4908 HANDSHAKE_FAILURE = 40
4909 NO_CERTIFICATE = 41
4910 BAD_CERTIFICATE = 42
4911 UNSUPPORTED_CERTIFICATE = 43
4912 CERTIFICATE_REVOKED = 44
4913 CERTIFICATE_EXPIRED = 45
4914 CERTIFICATE_UNKNOWN = 46
4915 ILLEGAL_PARAMETER = 47
4916 UNKNOWN_CA = 48
4917 ACCESS_DENIED = 49
4918 DECODE_ERROR = 50
4919 DECRYPT_ERROR = 51
4920 EXPORT_RESTRICTION = 60
4921 PROTOCOL_VERSION = 70
4922 INSUFFICIENT_SECURITY = 71
4923 INTERNAL_ERROR = 80
4924 INAPPROPRIATE_FALLBACK = 86
4925 USER_CANCELED = 90
4926 NO_RENEGOTIATION = 100
4927 MISSING_EXTENSION = 109
4928 UNSUPPORTED_EXTENSION = 110
4929 CERTIFICATE_UNOBTAINABLE = 111
4930 UNRECOGNIZED_NAME = 112
4931 BAD_CERTIFICATE_STATUS_RESPONSE = 113
4932 BAD_CERTIFICATE_HASH_VALUE = 114
4933 UNKNOWN_PSK_IDENTITY = 115
4934 CERTIFICATE_REQUIRED = 116
4935 NO_APPLICATION_PROTOCOL = 120
4936 enum._test_simple_enum(Checked_TLSAlertType, _TLSAlertType)
4937
4938 def test_tlsmessagetype(self):
4939 class Checked_TLSMessageType(enum.IntEnum):
4940 """Message types (handshake protocol)
4941
4942 See RFC 8446, section B.3
4943 """
4944 HELLO_REQUEST = 0
4945 CLIENT_HELLO = 1
4946 SERVER_HELLO = 2
4947 HELLO_VERIFY_REQUEST = 3
4948 NEWSESSION_TICKET = 4
4949 END_OF_EARLY_DATA = 5
4950 HELLO_RETRY_REQUEST = 6
4951 ENCRYPTED_EXTENSIONS = 8
4952 CERTIFICATE = 11
4953 SERVER_KEY_EXCHANGE = 12
4954 CERTIFICATE_REQUEST = 13
4955 SERVER_DONE = 14
4956 CERTIFICATE_VERIFY = 15
4957 CLIENT_KEY_EXCHANGE = 16
4958 FINISHED = 20
4959 CERTIFICATE_URL = 21
4960 CERTIFICATE_STATUS = 22
4961 SUPPLEMENTAL_DATA = 23
4962 KEY_UPDATE = 24
4963 NEXT_PROTO = 67
4964 MESSAGE_HASH = 254
4965 CHANGE_CIPHER_SPEC = 0x0101
4966 enum._test_simple_enum(Checked_TLSMessageType, _TLSMessageType)
4967
4968 def test_sslmethod(self):
4969 Checked_SSLMethod = enum._old_convert_(
4970 enum.IntEnum, '_SSLMethod', 'ssl',
4971 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4972 source=ssl._ssl,
4973 )
4974 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
4975
4976 def test_options(self):
4977 CheckedOptions = enum._old_convert_(
4978 enum.FlagEnum, 'Options', 'ssl',
4979 lambda name: name.startswith('OP_'),
4980 source=ssl._ssl,
4981 )
4982 enum._test_simple_enum(CheckedOptions, ssl.Options)
4983
4984
4985 def test_alertdescription(self):
4986 CheckedAlertDescription = enum._old_convert_(
4987 enum.IntEnum, 'AlertDescription', 'ssl',
4988 lambda name: name.startswith('ALERT_DESCRIPTION_'),
4989 source=ssl._ssl,
4990 )
4991 enum._test_simple_enum(CheckedAlertDescription, ssl.AlertDescription)
4992
4993 def test_sslerrornumber(self):
4994 Checked_SSLMethod = enum._old_convert_(
4995 enum.IntEnum, '_SSLMethod', 'ssl',
4996 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4997 source=ssl._ssl,
4998 )
4999 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
5000
5001 def test_verifyflags(self):
5002 CheckedVerifyFlags = enum._old_convert_(
5003 enum.FlagEnum, 'VerifyFlags', 'ssl',
5004 lambda name: name.startswith('VERIFY_'),
5005 source=ssl._ssl,
5006 )
5007 enum._test_simple_enum(CheckedVerifyFlags, ssl.VerifyFlags)
5008
5009 def test_verifymode(self):
5010 CheckedVerifyMode = enum._old_convert_(
5011 enum.IntEnum, 'VerifyMode', 'ssl',
5012 lambda name: name.startswith('CERT_'),
5013 source=ssl._ssl,
5014 )
5015 enum._test_simple_enum(CheckedVerifyMode, ssl.VerifyMode)
5016
Thomas Woutersed03b412007-08-28 21:37:11 +00005017def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00005018 if support.verbose:
5019 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00005020 'Mac': platform.mac_ver,
5021 'Windows': platform.win32_ver,
5022 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04005023 for name, func in plats.items():
5024 plat = func()
5025 if plat and plat[0]:
5026 plat = '%s %r' % (name, plat)
5027 break
5028 else:
5029 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00005030 print("test_ssl: testing with %r %r" %
5031 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
5032 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00005033 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01005034 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
5035 try:
5036 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
5037 except AttributeError:
5038 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00005039
Antoine Pitrou152efa22010-05-16 18:19:27 +00005040 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00005041 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00005042 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01005043 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00005044 BADCERT, BADKEY, EMPTYCERT]:
5045 if not os.path.exists(filename):
5046 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005047
Martin Panter3840b2a2016-03-27 01:53:46 +00005048 tests = [
5049 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01005050 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02005051 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00005052 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00005053
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005054 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00005055 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00005056
Hai Shie80697d2020-05-28 06:10:27 +08005057 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00005058 try:
5059 support.run_unittest(*tests)
5060 finally:
Hai Shie80697d2020-05-28 06:10:27 +08005061 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00005062
5063if __name__ == "__main__":
5064 test_main()