blob: 403261dda968092523e267d46417b77f5a2d5017 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Christian Heimesc7f70692019-05-31 11:44:05 +02005import unittest.mock
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Hai Shia7f5d932020-08-04 00:41:24 +08007from test.support import import_helper
8from test.support import os_helper
Serhiy Storchaka16994912020-04-25 10:06:29 +03009from test.support import socket_helper
Hai Shie80697d2020-05-28 06:10:27 +080010from test.support import threading_helper
Hai Shia7f5d932020-08-04 00:41:24 +080011from test.support import warnings_helper
Thomas Woutersed03b412007-08-28 21:37:11 +000012import socket
Bill Janssen6e027db2007-11-15 22:23:56 +000013import select
Thomas Woutersed03b412007-08-28 21:37:11 +000014import time
Christian Heimes9424bb42013-06-17 15:32:57 +020015import datetime
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000016import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000017import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000018import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000019import pprint
Antoine Pitrou803e6d62010-10-13 10:36:15 +000020import urllib.request
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020021import threading
Thomas Woutersed03b412007-08-28 21:37:11 +000022import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000023import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000024import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000025import platform
Christian Heimes892d66e2018-01-29 14:10:18 +010026import sysconfig
Christian Heimesdf6ac7e2019-09-26 17:02:59 +020027import functools
Christian Heimes888bbdc2017-09-07 14:18:21 -070028try:
29 import ctypes
30except ImportError:
31 ctypes = None
Thomas Woutersed03b412007-08-28 21:37:11 +000032
Hai Shia7f5d932020-08-04 00:41:24 +080033ssl = import_helper.import_module("ssl")
Antoine Pitrou05d936d2010-10-13 11:38:36 +000034
Victor Stinner8f4ef3b2019-07-01 18:28:25 +020035from ssl import TLSVersion, _TLSContentType, _TLSMessageType
Martin Panter3840b2a2016-03-27 01:53:46 +000036
Paul Monsonf3550692019-06-19 13:09:54 -070037Py_DEBUG = hasattr(sys, 'gettotalrefcount')
38Py_DEBUG_WIN32 = Py_DEBUG and sys.platform == 'win32'
39
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010040PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Serhiy Storchaka16994912020-04-25 10:06:29 +030041HOST = socket_helper.HOST
Christian Heimes598894f2016-09-05 23:19:05 +020042IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
Christian Heimes05d9fe32018-02-27 08:55:39 +010043IS_OPENSSL_1_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1)
Christian Heimes5151d642021-04-09 15:43:06 +020044IS_OPENSSL_3_0_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
Christian Heimes892d66e2018-01-29 14:10:18 +010045PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
Antoine Pitrou152efa22010-05-16 18:19:27 +000046
Victor Stinner3ef63442019-02-19 18:06:03 +010047PROTOCOL_TO_TLS_VERSION = {}
48for proto, ver in (
49 ("PROTOCOL_SSLv23", "SSLv3"),
50 ("PROTOCOL_TLSv1", "TLSv1"),
51 ("PROTOCOL_TLSv1_1", "TLSv1_1"),
52):
53 try:
54 proto = getattr(ssl, proto)
55 ver = getattr(ssl.TLSVersion, ver)
56 except AttributeError:
57 continue
58 PROTOCOL_TO_TLS_VERSION[proto] = ver
59
Christian Heimesefff7062013-11-21 03:35:02 +010060def data_file(*name):
61 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000062
Antoine Pitrou81564092010-10-08 23:06:24 +000063# The custom key and certificate files used in test_ssl are generated
64# using Lib/test/make_ssl_certs.py.
65# Other certificates are simply fetched from the Internet servers they
66# are meant to authenticate.
67
Antoine Pitrou152efa22010-05-16 18:19:27 +000068CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000069BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000070ONLYCERT = data_file("ssl_cert.pem")
71ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000072BYTES_ONLYCERT = os.fsencode(ONLYCERT)
73BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020074CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
75ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
76KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000077CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000078BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010079CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
80CAFILE_CACERT = data_file("capath", "5ed36f99.0")
81
Christian Heimesbd5c7d22018-01-20 15:16:30 +010082CERTFILE_INFO = {
83 'issuer': ((('countryName', 'XY'),),
84 (('localityName', 'Castle Anthrax'),),
85 (('organizationName', 'Python Software Foundation'),),
86 (('commonName', 'localhost'),)),
Christian Heimese6dac002018-08-30 07:25:49 +020087 'notAfter': 'Aug 26 14:23:15 2028 GMT',
88 'notBefore': 'Aug 29 14:23:15 2018 GMT',
89 'serialNumber': '98A7CF88C74A32ED',
Christian Heimesbd5c7d22018-01-20 15:16:30 +010090 'subject': ((('countryName', 'XY'),),
91 (('localityName', 'Castle Anthrax'),),
92 (('organizationName', 'Python Software Foundation'),),
93 (('commonName', 'localhost'),)),
94 'subjectAltName': (('DNS', 'localhost'),),
95 'version': 3
96}
Antoine Pitrou152efa22010-05-16 18:19:27 +000097
Christian Heimes22587792013-11-21 23:56:13 +010098# empty CRL
99CRLFILE = data_file("revocation.crl")
100
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100101# Two keys and certs signed by the same CA (for SNI tests)
102SIGNED_CERTFILE = data_file("keycert3.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200103SIGNED_CERTFILE_HOSTNAME = 'localhost'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100104
105SIGNED_CERTFILE_INFO = {
106 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
107 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
108 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
109 'issuer': ((('countryName', 'XY'),),
110 (('organizationName', 'Python Software Foundation CA'),),
111 (('commonName', 'our-ca-server'),)),
Christian Heimesb467d9a2021-04-17 10:07:19 +0200112 'notAfter': 'Oct 28 14:23:16 2037 GMT',
Christian Heimese6dac002018-08-30 07:25:49 +0200113 'notBefore': 'Aug 29 14:23:16 2018 GMT',
114 'serialNumber': 'CB2D80995A69525C',
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100115 'subject': ((('countryName', 'XY'),),
116 (('localityName', 'Castle Anthrax'),),
117 (('organizationName', 'Python Software Foundation'),),
118 (('commonName', 'localhost'),)),
119 'subjectAltName': (('DNS', 'localhost'),),
120 'version': 3
121}
122
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100123SIGNED_CERTFILE2 = data_file("keycert4.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200124SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100125SIGNED_CERTFILE_ECC = data_file("keycertecc.pem")
126SIGNED_CERTFILE_ECC_HOSTNAME = 'localhost-ecc'
127
Martin Panter3840b2a2016-03-27 01:53:46 +0000128# Same certificate as pycacert.pem, but without extra text in file
129SIGNING_CA = data_file("capath", "ceff1710.0")
Christian Heimes1c03abd2016-09-06 23:25:35 +0200130# cert with all kinds of subject alt names
131ALLSANFILE = data_file("allsans.pem")
Christian Heimes66e57422018-01-29 14:25:13 +0100132IDNSANSFILE = data_file("idnsans.pem")
Christian Heimesb467d9a2021-04-17 10:07:19 +0200133NOSANFILE = data_file("nosan.pem")
134NOSAN_HOSTNAME = 'localhost'
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100135
Martin Panter3d81d932016-01-14 09:36:00 +0000136REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +0000137
138EMPTYCERT = data_file("nullcert.pem")
139BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +0000140NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000141BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200142NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +0200143NULLBYTECERT = data_file("nullbytecert.pem")
Christian Heimesa37f5242019-01-15 23:47:42 +0100144TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000145
Christian Heimes88bfd0b2018-08-14 12:54:19 +0200146DHFILE = data_file("ffdh3072.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100147BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +0000148
Christian Heimes358cfd42016-09-10 22:43:48 +0200149# Not defined in all versions of OpenSSL
150OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
151OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
152OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
153OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
Christian Heimes05d9fe32018-02-27 08:55:39 +0100154OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
Christian Heimes6f37ebc2021-04-09 17:59:21 +0200155OP_IGNORE_UNEXPECTED_EOF = getattr(ssl, "OP_IGNORE_UNEXPECTED_EOF", 0)
Christian Heimes358cfd42016-09-10 22:43:48 +0200156
Christian Heimesf6c6b582021-03-18 23:06:50 +0100157# Ubuntu has patched OpenSSL and changed behavior of security level 2
158# see https://bugs.python.org/issue41561#msg389003
159def is_ubuntu():
160 try:
161 # Assume that any references of "ubuntu" implies Ubuntu-like distro
162 # The workaround is not required for 18.04, but doesn't hurt either.
163 with open("/etc/os-release", encoding="utf-8") as f:
164 return "ubuntu" in f.read()
165 except FileNotFoundError:
166 return False
167
168if is_ubuntu():
169 def seclevel_workaround(*ctxs):
170 """"Lower security level to '1' and allow all ciphers for TLS 1.0/1"""
171 for ctx in ctxs:
Christian Heimes34477502021-04-12 12:00:38 +0200172 if (
173 hasattr(ctx, "minimum_version") and
174 ctx.minimum_version <= ssl.TLSVersion.TLSv1_1
175 ):
Christian Heimesf6c6b582021-03-18 23:06:50 +0100176 ctx.set_ciphers("@SECLEVEL=1:ALL")
177else:
178 def seclevel_workaround(*ctxs):
179 pass
180
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100181
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200182def has_tls_protocol(protocol):
183 """Check if a TLS protocol is available and enabled
184
185 :param protocol: enum ssl._SSLMethod member or name
186 :return: bool
187 """
188 if isinstance(protocol, str):
189 assert protocol.startswith('PROTOCOL_')
190 protocol = getattr(ssl, protocol, None)
191 if protocol is None:
192 return False
193 if protocol in {
194 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
195 ssl.PROTOCOL_TLS_CLIENT
196 }:
197 # auto-negotiate protocols are always available
198 return True
199 name = protocol.name
200 return has_tls_version(name[len('PROTOCOL_'):])
201
202
203@functools.lru_cache
204def has_tls_version(version):
205 """Check if a TLS/SSL version is enabled
206
207 :param version: TLS version name or ssl.TLSVersion member
208 :return: bool
209 """
210 if version == "SSLv2":
211 # never supported and not even in TLSVersion enum
212 return False
213
214 if isinstance(version, str):
215 version = ssl.TLSVersion.__members__[version]
216
217 # check compile time flags like ssl.HAS_TLSv1_2
218 if not getattr(ssl, f'HAS_{version.name}'):
219 return False
220
Christian Heimes5151d642021-04-09 15:43:06 +0200221 if IS_OPENSSL_3_0_0 and version < ssl.TLSVersion.TLSv1_2:
222 # bpo43791: 3.0.0-alpha14 fails with TLSV1_ALERT_INTERNAL_ERROR
223 return False
224
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200225 # check runtime and dynamic crypto policy settings. A TLS version may
226 # be compiled in but disabled by a policy or config option.
227 ctx = ssl.SSLContext()
228 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200229 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200230 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
231 version < ctx.minimum_version
232 ):
233 return False
234 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200235 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200236 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
237 version > ctx.maximum_version
238 ):
239 return False
240
241 return True
242
243
244def requires_tls_version(version):
245 """Decorator to skip tests when a required TLS version is not available
246
247 :param version: TLS version name or ssl.TLSVersion member
248 :return:
249 """
250 def decorator(func):
251 @functools.wraps(func)
252 def wrapper(*args, **kw):
253 if not has_tls_version(version):
254 raise unittest.SkipTest(f"{version} is not available.")
255 else:
256 return func(*args, **kw)
257 return wrapper
258 return decorator
259
260
261requires_minimum_version = unittest.skipUnless(
262 hasattr(ssl.SSLContext, 'minimum_version'),
263 "required OpenSSL >= 1.1.0g"
264)
265
266
Thomas Woutersed03b412007-08-28 21:37:11 +0000267def handle_error(prefix):
268 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000269 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000270 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000271
Christian Heimesb7b92252018-02-25 09:49:31 +0100272def _have_secp_curves():
273 if not ssl.HAS_ECDH:
274 return False
275 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
276 try:
277 ctx.set_ecdh_curve("secp384r1")
278 except ValueError:
279 return False
280 else:
281 return True
282
283
284HAVE_SECP_CURVES = _have_secp_curves()
285
286
Antoine Pitrouc695c952014-04-28 20:57:36 +0200287def utc_offset(): #NOTE: ignore issues like #1647654
288 # local time = utc time + utc offset
289 if time.daylight and time.localtime().tm_isdst > 0:
290 return -time.altzone # seconds
291 return -time.timezone
292
Christian Heimes9424bb42013-06-17 15:32:57 +0200293def asn1time(cert_time):
294 # Some versions of OpenSSL ignore seconds, see #18207
295 # 0.9.8.i
296 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
297 fmt = "%b %d %H:%M:%S %Y GMT"
298 dt = datetime.datetime.strptime(cert_time, fmt)
299 dt = dt.replace(second=0)
300 cert_time = dt.strftime(fmt)
301 # %d adds leading zero but ASN1_TIME_print() uses leading space
302 if cert_time[4] == "0":
303 cert_time = cert_time[:4] + " " + cert_time[5:]
304
305 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000306
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100307needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
308
Antoine Pitrou23df4832010-08-04 17:14:06 +0000309
Christian Heimesd0486372016-09-10 23:23:33 +0200310def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLS, *,
311 cert_reqs=ssl.CERT_NONE, ca_certs=None,
312 ciphers=None, certfile=None, keyfile=None,
313 **kwargs):
314 context = ssl.SSLContext(ssl_version)
315 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200316 if cert_reqs == ssl.CERT_NONE:
317 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200318 context.verify_mode = cert_reqs
319 if ca_certs is not None:
320 context.load_verify_locations(ca_certs)
321 if certfile is not None or keyfile is not None:
322 context.load_cert_chain(certfile, keyfile)
323 if ciphers is not None:
324 context.set_ciphers(ciphers)
325 return context.wrap_socket(sock, **kwargs)
326
Christian Heimesa170fa12017-09-15 20:27:30 +0200327
328def testing_context(server_cert=SIGNED_CERTFILE):
329 """Create context
330
331 client_context, server_context, hostname = testing_context()
332 """
333 if server_cert == SIGNED_CERTFILE:
334 hostname = SIGNED_CERTFILE_HOSTNAME
335 elif server_cert == SIGNED_CERTFILE2:
336 hostname = SIGNED_CERTFILE2_HOSTNAME
Christian Heimesb467d9a2021-04-17 10:07:19 +0200337 elif server_cert == NOSANFILE:
338 hostname = NOSAN_HOSTNAME
Christian Heimesa170fa12017-09-15 20:27:30 +0200339 else:
340 raise ValueError(server_cert)
341
342 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
343 client_context.load_verify_locations(SIGNING_CA)
344
345 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
346 server_context.load_cert_chain(server_cert)
Christian Heimes9fb051f2018-09-23 08:32:31 +0200347 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200348
349 return client_context, server_context, hostname
350
351
Antoine Pitrou152efa22010-05-16 18:19:27 +0000352class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000353
Antoine Pitrou480a1242010-04-28 21:37:09 +0000354 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000355 ssl.CERT_NONE
356 ssl.CERT_OPTIONAL
357 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100358 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100359 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100360 if ssl.HAS_ECDH:
361 ssl.OP_SINGLE_ECDH_USE
Christian Heimes39258d32021-04-17 11:36:35 +0200362 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000363 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100364 self.assertIn(ssl.HAS_ECDH, {True, False})
Christian Heimescb5b68a2017-09-07 18:07:00 -0700365 ssl.OP_NO_SSLv2
366 ssl.OP_NO_SSLv3
367 ssl.OP_NO_TLSv1
368 ssl.OP_NO_TLSv1_3
Christian Heimes39258d32021-04-17 11:36:35 +0200369 ssl.OP_NO_TLSv1_1
370 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200371 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000372
Christian Heimes9d50ab52018-02-27 10:17:30 +0100373 def test_private_init(self):
374 with self.assertRaisesRegex(TypeError, "public constructor"):
375 with socket.socket() as s:
376 ssl.SSLSocket(s)
377
Antoine Pitrou172f0252014-04-18 20:33:08 +0200378 def test_str_for_enums(self):
379 # Make sure that the PROTOCOL_* constants have enum-like string
380 # reprs.
Christian Heimes598894f2016-09-05 23:19:05 +0200381 proto = ssl.PROTOCOL_TLS
Ethan Furmanb7751062021-03-30 21:17:26 -0700382 self.assertEqual(str(proto), 'PROTOCOL_TLS')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200383 ctx = ssl.SSLContext(proto)
384 self.assertIs(ctx.protocol, proto)
385
Antoine Pitrou480a1242010-04-28 21:37:09 +0000386 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000387 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000388 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000389 sys.stdout.write("\n RAND_status is %d (%s)\n"
390 % (v, (v and "sufficient randomness") or
391 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200392
393 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
394 self.assertEqual(len(data), 16)
395 self.assertEqual(is_cryptographic, v == 1)
396 if v:
397 data = ssl.RAND_bytes(16)
398 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200399 else:
400 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200401
Victor Stinner1e81a392013-12-19 16:47:04 +0100402 # negative num is invalid
403 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
404 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
405
Victor Stinnerbeeb5122014-11-28 13:28:25 +0100406 if hasattr(ssl, 'RAND_egd'):
407 self.assertRaises(TypeError, ssl.RAND_egd, 1)
408 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000409 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200410 ssl.RAND_add(b"this is a random bytes object", 75.0)
411 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000412
pxinwr98a54172020-12-09 07:20:19 +0800413 @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
Christian Heimesf77b4b22013-08-21 13:26:05 +0200414 def test_random_fork(self):
415 status = ssl.RAND_status()
416 if not status:
417 self.fail("OpenSSL's PRNG has insufficient randomness")
418
419 rfd, wfd = os.pipe()
420 pid = os.fork()
421 if pid == 0:
422 try:
423 os.close(rfd)
424 child_random = ssl.RAND_pseudo_bytes(16)[0]
425 self.assertEqual(len(child_random), 16)
426 os.write(wfd, child_random)
427 os.close(wfd)
428 except BaseException:
429 os._exit(1)
430 else:
431 os._exit(0)
432 else:
433 os.close(wfd)
434 self.addCleanup(os.close, rfd)
Victor Stinner278c1e12020-03-31 20:08:12 +0200435 support.wait_process(pid, exitcode=0)
Christian Heimesf77b4b22013-08-21 13:26:05 +0200436
437 child_random = os.read(rfd, 16)
438 self.assertEqual(len(child_random), 16)
439 parent_random = ssl.RAND_pseudo_bytes(16)[0]
440 self.assertEqual(len(parent_random), 16)
441
442 self.assertNotEqual(child_random, parent_random)
443
Christian Heimese6dac002018-08-30 07:25:49 +0200444 maxDiff = None
445
Antoine Pitrou480a1242010-04-28 21:37:09 +0000446 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000447 # note that this uses an 'unofficial' function in _ssl.c,
448 # provided solely for this test, to exercise the certificate
449 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100450 self.assertEqual(
451 ssl._ssl._test_decode_cert(CERTFILE),
452 CERTFILE_INFO
453 )
454 self.assertEqual(
455 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
456 SIGNED_CERTFILE_INFO
457 )
458
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200459 # Issue #13034: the subjectAltName in some certificates
460 # (notably projects.developer.nokia.com:443) wasn't parsed
461 p = ssl._ssl._test_decode_cert(NOKIACERT)
462 if support.verbose:
463 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
464 self.assertEqual(p['subjectAltName'],
465 (('DNS', 'projects.developer.nokia.com'),
466 ('DNS', 'projects.forum.nokia.com'))
467 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100468 # extra OCSP and AIA fields
469 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
470 self.assertEqual(p['caIssuers'],
471 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
472 self.assertEqual(p['crlDistributionPoints'],
473 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000474
Christian Heimesa37f5242019-01-15 23:47:42 +0100475 def test_parse_cert_CVE_2019_5010(self):
476 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
477 if support.verbose:
478 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
479 self.assertEqual(
480 p,
481 {
482 'issuer': (
483 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
484 'notAfter': 'Jun 14 18:00:58 2028 GMT',
485 'notBefore': 'Jun 18 18:00:58 2018 GMT',
486 'serialNumber': '02',
487 'subject': ((('countryName', 'UK'),),
488 (('commonName',
489 'codenomicon-vm-2.test.lal.cisco.com'),)),
490 'subjectAltName': (
491 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
492 'version': 3
493 }
494 )
495
Christian Heimes824f7f32013-08-17 00:54:47 +0200496 def test_parse_cert_CVE_2013_4238(self):
497 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
498 if support.verbose:
499 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
500 subject = ((('countryName', 'US'),),
501 (('stateOrProvinceName', 'Oregon'),),
502 (('localityName', 'Beaverton'),),
503 (('organizationName', 'Python Software Foundation'),),
504 (('organizationalUnitName', 'Python Core Development'),),
505 (('commonName', 'null.python.org\x00example.org'),),
506 (('emailAddress', 'python-dev@python.org'),))
507 self.assertEqual(p['subject'], subject)
508 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200509 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
510 san = (('DNS', 'altnull.python.org\x00example.com'),
511 ('email', 'null@python.org\x00user@example.org'),
512 ('URI', 'http://null.python.org\x00http://example.org'),
513 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100514 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200515 else:
516 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
517 san = (('DNS', 'altnull.python.org\x00example.com'),
518 ('email', 'null@python.org\x00user@example.org'),
519 ('URI', 'http://null.python.org\x00http://example.org'),
520 ('IP Address', '192.0.2.1'),
521 ('IP Address', '<invalid>'))
522
523 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200524
Christian Heimes1c03abd2016-09-06 23:25:35 +0200525 def test_parse_all_sans(self):
526 p = ssl._ssl._test_decode_cert(ALLSANFILE)
527 self.assertEqual(p['subjectAltName'],
528 (
529 ('DNS', 'allsans'),
530 ('othername', '<unsupported>'),
531 ('othername', '<unsupported>'),
532 ('email', 'user@example.org'),
533 ('DNS', 'www.example.org'),
534 ('DirName',
535 ((('countryName', 'XY'),),
536 (('localityName', 'Castle Anthrax'),),
537 (('organizationName', 'Python Software Foundation'),),
538 (('commonName', 'dirname example'),))),
539 ('URI', 'https://www.python.org/'),
540 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100541 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200542 ('Registered ID', '1.2.3.4.5')
543 )
544 )
545
Antoine Pitrou480a1242010-04-28 21:37:09 +0000546 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000547 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000548 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000549 d1 = ssl.PEM_cert_to_DER_cert(pem)
550 p2 = ssl.DER_cert_to_PEM_cert(d1)
551 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000552 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000553 if not p2.startswith(ssl.PEM_HEADER + '\n'):
554 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
555 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
556 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000557
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000558 def test_openssl_version(self):
559 n = ssl.OPENSSL_VERSION_NUMBER
560 t = ssl.OPENSSL_VERSION_INFO
561 s = ssl.OPENSSL_VERSION
562 self.assertIsInstance(n, int)
563 self.assertIsInstance(t, tuple)
564 self.assertIsInstance(s, str)
565 # Some sanity checks follow
566 # >= 0.9
567 self.assertGreaterEqual(n, 0x900000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100568 # < 4.0
569 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000570 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100571 self.assertGreaterEqual(major, 1)
572 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000573 self.assertGreaterEqual(minor, 0)
574 self.assertLess(minor, 256)
575 self.assertGreaterEqual(fix, 0)
576 self.assertLess(fix, 256)
577 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100578 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000579 self.assertGreaterEqual(status, 0)
580 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400581 # Version string as returned by {Open,Libre}SSL, the format might change
Christian Heimes598894f2016-09-05 23:19:05 +0200582 if IS_LIBRESSL:
583 self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
Victor Stinner789b8052015-01-06 11:51:06 +0100584 (s, t, hex(n)))
Antoine Pitroudfab9352014-07-21 18:35:01 -0400585 else:
586 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
Victor Stinner789b8052015-01-06 11:51:06 +0100587 (s, t, hex(n)))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000588
Antoine Pitrou9d543662010-04-23 23:10:32 +0000589 @support.cpython_only
590 def test_refcycle(self):
591 # Issue #7943: an SSL object doesn't create reference cycles with
592 # itself.
593 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200594 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000595 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800596 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100597 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100598 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000599
Antoine Pitroua468adc2010-09-14 14:43:44 +0000600 def test_wrapped_unconnected(self):
601 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200602 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000603 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200604 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100605 self.assertRaises(OSError, ss.recv, 1)
606 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
607 self.assertRaises(OSError, ss.recvfrom, 1)
608 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
609 self.assertRaises(OSError, ss.send, b'x')
610 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200611 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100612 self.assertRaises(NotImplementedError, ss.sendmsg,
613 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200614 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
615 self.assertRaises(NotImplementedError, ss.recvmsg_into,
616 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000617
Antoine Pitrou40f08742010-04-24 22:04:40 +0000618 def test_timeout(self):
619 # Issue #8524: when creating an SSL socket, the timeout of the
620 # original socket should be retained.
621 for timeout in (None, 0.0, 5.0):
622 s = socket.socket(socket.AF_INET)
623 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200624 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100625 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000626
Christian Heimesd0486372016-09-10 23:23:33 +0200627 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000628 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000629 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000630 "certfile must be specified",
631 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000632 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000633 "certfile must be specified for server-side operations",
634 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000635 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000636 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200637 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100638 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
639 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200640 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200641 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000642 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000643 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000644 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200645 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000646 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000647 ssl.wrap_socket(sock,
648 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000649 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200650 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000651 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000652 ssl.wrap_socket(sock,
653 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000654 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000655
Martin Panter3464ea22016-02-01 21:58:11 +0000656 def bad_cert_test(self, certfile):
657 """Check that trying to use the given client certificate fails"""
658 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
659 certfile)
660 sock = socket.socket()
661 self.addCleanup(sock.close)
662 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200663 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200664 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000665
666 def test_empty_cert(self):
667 """Wrapping with an empty cert file"""
668 self.bad_cert_test("nullcert.pem")
669
670 def test_malformed_cert(self):
671 """Wrapping with a badly formatted certificate (syntax error)"""
672 self.bad_cert_test("badcert.pem")
673
674 def test_malformed_key(self):
675 """Wrapping with a badly formatted key (syntax error)"""
676 self.bad_cert_test("badkey.pem")
677
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000678 def test_match_hostname(self):
679 def ok(cert, hostname):
680 ssl.match_hostname(cert, hostname)
681 def fail(cert, hostname):
682 self.assertRaises(ssl.CertificateError,
683 ssl.match_hostname, cert, hostname)
684
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100685 # -- Hostname matching --
686
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000687 cert = {'subject': ((('commonName', 'example.com'),),)}
688 ok(cert, 'example.com')
689 ok(cert, 'ExAmple.cOm')
690 fail(cert, 'www.example.com')
691 fail(cert, '.example.com')
692 fail(cert, 'example.org')
693 fail(cert, 'exampleXcom')
694
695 cert = {'subject': ((('commonName', '*.a.com'),),)}
696 ok(cert, 'foo.a.com')
697 fail(cert, 'bar.foo.a.com')
698 fail(cert, 'a.com')
699 fail(cert, 'Xa.com')
700 fail(cert, '.a.com')
701
Mandeep Singhede2ac92017-11-27 04:01:27 +0530702 # only match wildcards when they are the only thing
703 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000704 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530705 fail(cert, 'foo.com')
706 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000707 fail(cert, 'bar.com')
708 fail(cert, 'foo.a.com')
709 fail(cert, 'bar.foo.com')
710
Christian Heimes824f7f32013-08-17 00:54:47 +0200711 # NULL bytes are bad, CVE-2013-4073
712 cert = {'subject': ((('commonName',
713 'null.python.org\x00example.org'),),)}
714 ok(cert, 'null.python.org\x00example.org') # or raise an error?
715 fail(cert, 'example.org')
716 fail(cert, 'null.python.org')
717
Georg Brandl72c98d32013-10-27 07:16:53 +0100718 # error cases with wildcards
719 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
720 fail(cert, 'bar.foo.a.com')
721 fail(cert, 'a.com')
722 fail(cert, 'Xa.com')
723 fail(cert, '.a.com')
724
725 cert = {'subject': ((('commonName', 'a.*.com'),),)}
726 fail(cert, 'a.foo.com')
727 fail(cert, 'a..com')
728 fail(cert, 'a.com')
729
730 # wildcard doesn't match IDNA prefix 'xn--'
731 idna = 'püthon.python.org'.encode("idna").decode("ascii")
732 cert = {'subject': ((('commonName', idna),),)}
733 ok(cert, idna)
734 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
735 fail(cert, idna)
736 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
737 fail(cert, idna)
738
739 # wildcard in first fragment and IDNA A-labels in sequent fragments
740 # are supported.
741 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
742 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530743 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
744 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100745 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
746 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
747
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000748 # Slightly fake real-world example
749 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
750 'subject': ((('commonName', 'linuxfrz.org'),),),
751 'subjectAltName': (('DNS', 'linuxfr.org'),
752 ('DNS', 'linuxfr.com'),
753 ('othername', '<unsupported>'))}
754 ok(cert, 'linuxfr.org')
755 ok(cert, 'linuxfr.com')
756 # Not a "DNS" entry
757 fail(cert, '<unsupported>')
758 # When there is a subjectAltName, commonName isn't used
759 fail(cert, 'linuxfrz.org')
760
761 # A pristine real-world example
762 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
763 'subject': ((('countryName', 'US'),),
764 (('stateOrProvinceName', 'California'),),
765 (('localityName', 'Mountain View'),),
766 (('organizationName', 'Google Inc'),),
767 (('commonName', 'mail.google.com'),))}
768 ok(cert, 'mail.google.com')
769 fail(cert, 'gmail.com')
770 # Only commonName is considered
771 fail(cert, 'California')
772
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100773 # -- IPv4 matching --
774 cert = {'subject': ((('commonName', 'example.com'),),),
775 'subjectAltName': (('DNS', 'example.com'),
776 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200777 ('IP Address', '14.15.16.17'),
778 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100779 ok(cert, '10.11.12.13')
780 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200781 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
782 fail(cert, '127.1')
783 fail(cert, '14.15.16.17 ')
784 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100785 fail(cert, '14.15.16.18')
786 fail(cert, 'example.net')
787
788 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300789 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100790 cert = {'subject': ((('commonName', 'example.com'),),),
791 'subjectAltName': (
792 ('DNS', 'example.com'),
793 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
794 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
795 ok(cert, '2001::cafe')
796 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200797 fail(cert, '2003::baba ')
798 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100799 fail(cert, '2003::bebe')
800 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100801
802 # -- Miscellaneous --
803
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000804 # Neither commonName nor subjectAltName
805 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
806 'subject': ((('countryName', 'US'),),
807 (('stateOrProvinceName', 'California'),),
808 (('localityName', 'Mountain View'),),
809 (('organizationName', 'Google Inc'),))}
810 fail(cert, 'mail.google.com')
811
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200812 # No DNS entry in subjectAltName but a commonName
813 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
814 'subject': ((('countryName', 'US'),),
815 (('stateOrProvinceName', 'California'),),
816 (('localityName', 'Mountain View'),),
817 (('commonName', 'mail.google.com'),)),
818 'subjectAltName': (('othername', 'blabla'), )}
819 ok(cert, 'mail.google.com')
820
821 # No DNS entry subjectAltName and no commonName
822 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
823 'subject': ((('countryName', 'US'),),
824 (('stateOrProvinceName', 'California'),),
825 (('localityName', 'Mountain View'),),
826 (('organizationName', 'Google Inc'),)),
827 'subjectAltName': (('othername', 'blabla'),)}
828 fail(cert, 'google.com')
829
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000830 # Empty cert / no cert
831 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
832 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
833
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200834 # Issue #17980: avoid denials of service by refusing more than one
835 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100836 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
837 with self.assertRaisesRegex(
838 ssl.CertificateError,
839 "partial wildcards in leftmost label are not supported"):
840 ssl.match_hostname(cert, 'axxb.example.com')
841
842 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
843 with self.assertRaisesRegex(
844 ssl.CertificateError,
845 "wildcard can only be present in the leftmost label"):
846 ssl.match_hostname(cert, 'www.sub.example.com')
847
848 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
849 with self.assertRaisesRegex(
850 ssl.CertificateError,
851 "too many wildcards"):
852 ssl.match_hostname(cert, 'axxbxxc.example.com')
853
854 cert = {'subject': ((('commonName', '*'),),)}
855 with self.assertRaisesRegex(
856 ssl.CertificateError,
857 "sole wildcard without additional labels are not support"):
858 ssl.match_hostname(cert, 'host')
859
860 cert = {'subject': ((('commonName', '*.com'),),)}
861 with self.assertRaisesRegex(
862 ssl.CertificateError,
863 r"hostname 'com' doesn't match '\*.com'"):
864 ssl.match_hostname(cert, 'com')
865
866 # extra checks for _inet_paton()
867 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
868 with self.assertRaises(ValueError):
869 ssl._inet_paton(invalid)
870 for ipaddr in ['127.0.0.1', '192.168.0.1']:
871 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300872 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100873 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
874 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200875
Antoine Pitroud5323212010-10-22 18:19:07 +0000876 def test_server_side(self):
877 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200878 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000879 with socket.socket() as sock:
880 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
881 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000882
Antoine Pitroud6494802011-07-21 01:11:30 +0200883 def test_unknown_channel_binding(self):
884 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200885 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200886 c = socket.socket(socket.AF_INET)
887 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200888 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100889 with self.assertRaises(ValueError):
890 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200891 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200892
893 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
894 "'tls-unique' channel binding not available")
895 def test_tls_unique_channel_binding(self):
896 # unconnected should return None for known type
897 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200898 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100899 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200900 # the same for server-side
901 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200902 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100903 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200904
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600905 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200906 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600907 r = repr(ss)
908 with self.assertWarns(ResourceWarning) as cm:
909 ss = None
910 support.gc_collect()
911 self.assertIn(r, str(cm.warning.args[0]))
912
Christian Heimes6d7ad132013-06-09 18:02:55 +0200913 def test_get_default_verify_paths(self):
914 paths = ssl.get_default_verify_paths()
915 self.assertEqual(len(paths), 6)
916 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
917
Hai Shia7f5d932020-08-04 00:41:24 +0800918 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200919 env["SSL_CERT_DIR"] = CAPATH
920 env["SSL_CERT_FILE"] = CERTFILE
921 paths = ssl.get_default_verify_paths()
922 self.assertEqual(paths.cafile, CERTFILE)
923 self.assertEqual(paths.capath, CAPATH)
924
Christian Heimes44109d72013-11-22 01:51:30 +0100925 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
926 def test_enum_certificates(self):
927 self.assertTrue(ssl.enum_certificates("CA"))
928 self.assertTrue(ssl.enum_certificates("ROOT"))
929
930 self.assertRaises(TypeError, ssl.enum_certificates)
931 self.assertRaises(WindowsError, ssl.enum_certificates, "")
932
Christian Heimesc2d65e12013-11-22 16:13:55 +0100933 trust_oids = set()
934 for storename in ("CA", "ROOT"):
935 store = ssl.enum_certificates(storename)
936 self.assertIsInstance(store, list)
937 for element in store:
938 self.assertIsInstance(element, tuple)
939 self.assertEqual(len(element), 3)
940 cert, enc, trust = element
941 self.assertIsInstance(cert, bytes)
942 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200943 self.assertIsInstance(trust, (frozenset, set, bool))
944 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100945 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100946
947 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100948 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200949
Christian Heimes46bebee2013-06-09 19:03:31 +0200950 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100951 def test_enum_crls(self):
952 self.assertTrue(ssl.enum_crls("CA"))
953 self.assertRaises(TypeError, ssl.enum_crls)
954 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200955
Christian Heimes44109d72013-11-22 01:51:30 +0100956 crls = ssl.enum_crls("CA")
957 self.assertIsInstance(crls, list)
958 for element in crls:
959 self.assertIsInstance(element, tuple)
960 self.assertEqual(len(element), 2)
961 self.assertIsInstance(element[0], bytes)
962 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200963
Christian Heimes46bebee2013-06-09 19:03:31 +0200964
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100965 def test_asn1object(self):
966 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
967 '1.3.6.1.5.5.7.3.1')
968
969 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
970 self.assertEqual(val, expected)
971 self.assertEqual(val.nid, 129)
972 self.assertEqual(val.shortname, 'serverAuth')
973 self.assertEqual(val.longname, 'TLS Web Server Authentication')
974 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
975 self.assertIsInstance(val, ssl._ASN1Object)
976 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
977
978 val = ssl._ASN1Object.fromnid(129)
979 self.assertEqual(val, expected)
980 self.assertIsInstance(val, ssl._ASN1Object)
981 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100982 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
983 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100984 for i in range(1000):
985 try:
986 obj = ssl._ASN1Object.fromnid(i)
987 except ValueError:
988 pass
989 else:
990 self.assertIsInstance(obj.nid, int)
991 self.assertIsInstance(obj.shortname, str)
992 self.assertIsInstance(obj.longname, str)
993 self.assertIsInstance(obj.oid, (str, type(None)))
994
995 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
996 self.assertEqual(val, expected)
997 self.assertIsInstance(val, ssl._ASN1Object)
998 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
999 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
1000 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +01001001 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
1002 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001003
Christian Heimes72d28502013-11-23 13:56:58 +01001004 def test_purpose_enum(self):
1005 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
1006 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
1007 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
1008 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
1009 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
1010 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
1011 '1.3.6.1.5.5.7.3.1')
1012
1013 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
1014 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
1015 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
1016 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
1017 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
1018 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
1019 '1.3.6.1.5.5.7.3.2')
1020
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001021 def test_unsupported_dtls(self):
1022 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1023 self.addCleanup(s.close)
1024 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +02001025 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001026 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +02001027 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001028 with self.assertRaises(NotImplementedError) as cx:
1029 ctx.wrap_socket(s)
1030 self.assertEqual(str(cx.exception), "only stream sockets are supported")
1031
Antoine Pitrouc695c952014-04-28 20:57:36 +02001032 def cert_time_ok(self, timestring, timestamp):
1033 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
1034
1035 def cert_time_fail(self, timestring):
1036 with self.assertRaises(ValueError):
1037 ssl.cert_time_to_seconds(timestring)
1038
1039 @unittest.skipUnless(utc_offset(),
1040 'local time needs to be different from UTC')
1041 def test_cert_time_to_seconds_timezone(self):
1042 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
1043 # results if local timezone is not UTC
1044 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
1045 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
1046
1047 def test_cert_time_to_seconds(self):
1048 timestring = "Jan 5 09:34:43 2018 GMT"
1049 ts = 1515144883.0
1050 self.cert_time_ok(timestring, ts)
1051 # accept keyword parameter, assert its name
1052 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
1053 # accept both %e and %d (space or zero generated by strftime)
1054 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
1055 # case-insensitive
1056 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
1057 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
1058 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1059 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1060 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1061 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1062 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1063 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1064
1065 newyear_ts = 1230768000.0
1066 # leap seconds
1067 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1068 # same timestamp
1069 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1070
1071 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1072 # allow 60th second (even if it is not a leap second)
1073 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1074 # allow 2nd leap second for compatibility with time.strptime()
1075 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1076 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1077
Mike53f7a7c2017-12-14 14:04:53 +03001078 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001079 # 99991231235959Z (rfc 5280)
1080 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1081
1082 @support.run_with_locale('LC_ALL', '')
1083 def test_cert_time_to_seconds_locale(self):
1084 # `cert_time_to_seconds()` should be locale independent
1085
1086 def local_february_name():
1087 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1088
1089 if local_february_name().lower() == 'feb':
1090 self.skipTest("locale-specific month name needs to be "
1091 "different from C locale")
1092
1093 # locale-independent
1094 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1095 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1096
Martin Panter3840b2a2016-03-27 01:53:46 +00001097 def test_connect_ex_error(self):
1098 server = socket.socket(socket.AF_INET)
1099 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001100 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001101 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001102 cert_reqs=ssl.CERT_REQUIRED)
1103 self.addCleanup(s.close)
1104 rc = s.connect_ex((HOST, port))
1105 # Issue #19919: Windows machines or VMs hosted on Windows
1106 # machines sometimes return EWOULDBLOCK.
1107 errors = (
1108 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1109 errno.EWOULDBLOCK,
1110 )
1111 self.assertIn(rc, errors)
1112
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001113
Antoine Pitrou152efa22010-05-16 18:19:27 +00001114class ContextTests(unittest.TestCase):
1115
1116 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001117 for protocol in PROTOCOLS:
1118 ssl.SSLContext(protocol)
Christian Heimes598894f2016-09-05 23:19:05 +02001119 ctx = ssl.SSLContext()
1120 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001121 self.assertRaises(ValueError, ssl.SSLContext, -1)
1122 self.assertRaises(ValueError, ssl.SSLContext, 42)
1123
1124 def test_protocol(self):
1125 for proto in PROTOCOLS:
1126 ctx = ssl.SSLContext(proto)
1127 self.assertEqual(ctx.protocol, proto)
1128
1129 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001130 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001131 ctx.set_ciphers("ALL")
1132 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001133 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001134 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001135
Christian Heimes892d66e2018-01-29 14:10:18 +01001136 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1137 "Test applies only to Python default ciphers")
1138 def test_python_ciphers(self):
1139 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1140 ciphers = ctx.get_ciphers()
1141 for suite in ciphers:
1142 name = suite['name']
1143 self.assertNotIn("PSK", name)
1144 self.assertNotIn("SRP", name)
1145 self.assertNotIn("MD5", name)
1146 self.assertNotIn("RC4", name)
1147 self.assertNotIn("3DES", name)
1148
Christian Heimes25bfcd52016-09-06 00:04:45 +02001149 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001150 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001151 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001152 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001153 self.assertIn('AES256-GCM-SHA384', names)
1154 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001155
Antoine Pitroub5218772010-05-21 09:56:06 +00001156 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001157 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001158 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001159 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001160 # SSLContext also enables these by default
1161 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001162 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001163 OP_ENABLE_MIDDLEBOX_COMPAT |
1164 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001165 self.assertEqual(default, ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001166 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001167 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Christian Heimes39258d32021-04-17 11:36:35 +02001168 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
1169 self.assertEqual(default, ctx.options)
1170 ctx.options = 0
1171 # Ubuntu has OP_NO_SSLv3 forced on by default
1172 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001173
Christian Heimesa170fa12017-09-15 20:27:30 +02001174 def test_verify_mode_protocol(self):
1175 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001176 # Default value
1177 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1178 ctx.verify_mode = ssl.CERT_OPTIONAL
1179 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1180 ctx.verify_mode = ssl.CERT_REQUIRED
1181 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1182 ctx.verify_mode = ssl.CERT_NONE
1183 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1184 with self.assertRaises(TypeError):
1185 ctx.verify_mode = None
1186 with self.assertRaises(ValueError):
1187 ctx.verify_mode = 42
1188
Christian Heimesa170fa12017-09-15 20:27:30 +02001189 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1190 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1191 self.assertFalse(ctx.check_hostname)
1192
1193 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1194 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1195 self.assertTrue(ctx.check_hostname)
1196
Christian Heimes61d478c2018-01-27 15:51:38 +01001197 def test_hostname_checks_common_name(self):
1198 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1199 self.assertTrue(ctx.hostname_checks_common_name)
1200 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1201 ctx.hostname_checks_common_name = True
1202 self.assertTrue(ctx.hostname_checks_common_name)
1203 ctx.hostname_checks_common_name = False
1204 self.assertFalse(ctx.hostname_checks_common_name)
1205 ctx.hostname_checks_common_name = True
1206 self.assertTrue(ctx.hostname_checks_common_name)
1207 else:
1208 with self.assertRaises(AttributeError):
1209 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001210
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001211 @requires_minimum_version
Christian Heimesc9bc49c2019-09-11 19:24:47 +02001212 @unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
Christian Heimes698dde12018-02-27 11:54:43 +01001213 def test_min_max_version(self):
1214 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001215 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1216 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001217 minimum_range = {
1218 # stock OpenSSL
1219 ssl.TLSVersion.MINIMUM_SUPPORTED,
1220 # Fedora 29 uses TLS 1.0 by default
1221 ssl.TLSVersion.TLSv1,
1222 # RHEL 8 uses TLS 1.2 by default
1223 ssl.TLSVersion.TLSv1_2
1224 }
torsava34864d12019-12-02 17:15:42 +01001225 maximum_range = {
1226 # stock OpenSSL
1227 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1228 # Fedora 32 uses TLS 1.3 by default
1229 ssl.TLSVersion.TLSv1_3
1230 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001231
Christian Heimes34de2d32019-01-18 16:09:30 +01001232 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001233 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001234 )
torsava34864d12019-12-02 17:15:42 +01001235 self.assertIn(
1236 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001237 )
1238
1239 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1240 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1241 self.assertEqual(
1242 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1243 )
1244 self.assertEqual(
1245 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1246 )
1247
1248 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1249 ctx.maximum_version = ssl.TLSVersion.TLSv1
1250 self.assertEqual(
1251 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1252 )
1253 self.assertEqual(
1254 ctx.maximum_version, ssl.TLSVersion.TLSv1
1255 )
1256
1257 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1258 self.assertEqual(
1259 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1260 )
1261
1262 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1263 self.assertIn(
1264 ctx.maximum_version,
1265 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1266 )
1267
1268 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1269 self.assertIn(
1270 ctx.minimum_version,
1271 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1272 )
1273
1274 with self.assertRaises(ValueError):
1275 ctx.minimum_version = 42
1276
1277 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1278
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001279 self.assertIn(
1280 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001281 )
1282 self.assertEqual(
1283 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1284 )
1285 with self.assertRaises(ValueError):
1286 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1287 with self.assertRaises(ValueError):
1288 ctx.maximum_version = ssl.TLSVersion.TLSv1
1289
1290
matthewhughes9348e836bb2020-07-17 09:59:15 +01001291 @unittest.skipUnless(
1292 hasattr(ssl.SSLContext, 'security_level'),
1293 "requires OpenSSL >= 1.1.0"
1294 )
1295 def test_security_level(self):
1296 ctx = ssl.SSLContext()
1297 # The default security callback allows for levels between 0-5
1298 # with OpenSSL defaulting to 1, however some vendors override the
1299 # default value (e.g. Debian defaults to 2)
1300 security_level_range = {
1301 0,
1302 1, # OpenSSL default
1303 2, # Debian
1304 3,
1305 4,
1306 5,
1307 }
1308 self.assertIn(ctx.security_level, security_level_range)
1309
Christian Heimes22587792013-11-21 23:56:13 +01001310 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001311 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001312 # default value
1313 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1314 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001315 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1316 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1317 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1318 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1319 ctx.verify_flags = ssl.VERIFY_DEFAULT
1320 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001321 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1322 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001323 # supports any value
1324 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1325 self.assertEqual(ctx.verify_flags,
1326 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1327 with self.assertRaises(TypeError):
1328 ctx.verify_flags = None
1329
Antoine Pitrou152efa22010-05-16 18:19:27 +00001330 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001331 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001332 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001333 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001334 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1335 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001336 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001337 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001338 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001339 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001340 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001341 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001342 ctx.load_cert_chain(EMPTYCERT)
1343 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001344 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001345 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1346 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1347 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001348 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001349 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001350 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001351 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001352 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001353 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1354 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001355 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001356 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001357 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001358 # Password protected key and cert
1359 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1360 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1361 ctx.load_cert_chain(CERTFILE_PROTECTED,
1362 password=bytearray(KEY_PASSWORD.encode()))
1363 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1364 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1365 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1366 bytearray(KEY_PASSWORD.encode()))
1367 with self.assertRaisesRegex(TypeError, "should be a string"):
1368 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1369 with self.assertRaises(ssl.SSLError):
1370 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1371 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1372 # openssl has a fixed limit on the password buffer.
1373 # PEM_BUFSIZE is generally set to 1kb.
1374 # Return a string larger than this.
1375 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1376 # Password callback
1377 def getpass_unicode():
1378 return KEY_PASSWORD
1379 def getpass_bytes():
1380 return KEY_PASSWORD.encode()
1381 def getpass_bytearray():
1382 return bytearray(KEY_PASSWORD.encode())
1383 def getpass_badpass():
1384 return "badpass"
1385 def getpass_huge():
1386 return b'a' * (1024 * 1024)
1387 def getpass_bad_type():
1388 return 9
1389 def getpass_exception():
1390 raise Exception('getpass error')
1391 class GetPassCallable:
1392 def __call__(self):
1393 return KEY_PASSWORD
1394 def getpass(self):
1395 return KEY_PASSWORD
1396 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1397 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1398 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1399 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1400 ctx.load_cert_chain(CERTFILE_PROTECTED,
1401 password=GetPassCallable().getpass)
1402 with self.assertRaises(ssl.SSLError):
1403 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1404 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1405 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1406 with self.assertRaisesRegex(TypeError, "must return a string"):
1407 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1408 with self.assertRaisesRegex(Exception, "getpass error"):
1409 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1410 # Make sure the password function isn't called if it isn't needed
1411 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001412
1413 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001414 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001415 ctx.load_verify_locations(CERTFILE)
1416 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1417 ctx.load_verify_locations(BYTES_CERTFILE)
1418 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1419 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001420 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001421 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001422 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001423 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001424 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001425 ctx.load_verify_locations(BADCERT)
1426 ctx.load_verify_locations(CERTFILE, CAPATH)
1427 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1428
Victor Stinner80f75e62011-01-29 11:31:20 +00001429 # Issue #10989: crash if the second argument type is invalid
1430 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1431
Christian Heimesefff7062013-11-21 03:35:02 +01001432 def test_load_verify_cadata(self):
1433 # test cadata
1434 with open(CAFILE_CACERT) as f:
1435 cacert_pem = f.read()
1436 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1437 with open(CAFILE_NEURONIO) as f:
1438 neuronio_pem = f.read()
1439 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1440
1441 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001442 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001443 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1444 ctx.load_verify_locations(cadata=cacert_pem)
1445 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1446 ctx.load_verify_locations(cadata=neuronio_pem)
1447 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1448 # cert already in hash table
1449 ctx.load_verify_locations(cadata=neuronio_pem)
1450 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1451
1452 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001453 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001454 combined = "\n".join((cacert_pem, neuronio_pem))
1455 ctx.load_verify_locations(cadata=combined)
1456 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1457
1458 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001459 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001460 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1461 neuronio_pem, "tail"]
1462 ctx.load_verify_locations(cadata="\n".join(combined))
1463 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1464
1465 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001466 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001467 ctx.load_verify_locations(cadata=cacert_der)
1468 ctx.load_verify_locations(cadata=neuronio_der)
1469 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1470 # cert already in hash table
1471 ctx.load_verify_locations(cadata=cacert_der)
1472 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1473
1474 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001475 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001476 combined = b"".join((cacert_der, neuronio_der))
1477 ctx.load_verify_locations(cadata=combined)
1478 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1479
1480 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001481 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001482 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1483
1484 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1485 ctx.load_verify_locations(cadata="broken")
1486 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1487 ctx.load_verify_locations(cadata=b"broken")
1488
1489
Paul Monsonf3550692019-06-19 13:09:54 -07001490 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001491 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001492 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001493 ctx.load_dh_params(DHFILE)
1494 if os.name != 'nt':
1495 ctx.load_dh_params(BYTES_DHFILE)
1496 self.assertRaises(TypeError, ctx.load_dh_params)
1497 self.assertRaises(TypeError, ctx.load_dh_params, None)
1498 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001499 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001500 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001501 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001502 ctx.load_dh_params(CERTFILE)
1503
Antoine Pitroub0182c82010-10-12 20:09:02 +00001504 def test_session_stats(self):
1505 for proto in PROTOCOLS:
1506 ctx = ssl.SSLContext(proto)
1507 self.assertEqual(ctx.session_stats(), {
1508 'number': 0,
1509 'connect': 0,
1510 'connect_good': 0,
1511 'connect_renegotiate': 0,
1512 'accept': 0,
1513 'accept_good': 0,
1514 'accept_renegotiate': 0,
1515 'hits': 0,
1516 'misses': 0,
1517 'timeouts': 0,
1518 'cache_full': 0,
1519 })
1520
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001521 def test_set_default_verify_paths(self):
1522 # There's not much we can do to test that it acts as expected,
1523 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001524 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001525 ctx.set_default_verify_paths()
1526
Antoine Pitrou501da612011-12-21 09:27:41 +01001527 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001528 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001529 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001530 ctx.set_ecdh_curve("prime256v1")
1531 ctx.set_ecdh_curve(b"prime256v1")
1532 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1533 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1534 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1535 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1536
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001537 @needs_sni
1538 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001539 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001540
1541 # set_servername_callback expects a callable, or None
1542 self.assertRaises(TypeError, ctx.set_servername_callback)
1543 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1544 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1545 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1546
1547 def dummycallback(sock, servername, ctx):
1548 pass
1549 ctx.set_servername_callback(None)
1550 ctx.set_servername_callback(dummycallback)
1551
1552 @needs_sni
1553 def test_sni_callback_refcycle(self):
1554 # Reference cycles through the servername callback are detected
1555 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001556 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001557 def dummycallback(sock, servername, ctx, cycle=ctx):
1558 pass
1559 ctx.set_servername_callback(dummycallback)
1560 wr = weakref.ref(ctx)
1561 del ctx, dummycallback
1562 gc.collect()
1563 self.assertIs(wr(), None)
1564
Christian Heimes9a5395a2013-06-17 15:44:12 +02001565 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001566 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001567 self.assertEqual(ctx.cert_store_stats(),
1568 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1569 ctx.load_cert_chain(CERTFILE)
1570 self.assertEqual(ctx.cert_store_stats(),
1571 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1572 ctx.load_verify_locations(CERTFILE)
1573 self.assertEqual(ctx.cert_store_stats(),
1574 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001575 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001576 self.assertEqual(ctx.cert_store_stats(),
1577 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1578
1579 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001580 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001581 self.assertEqual(ctx.get_ca_certs(), [])
1582 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1583 ctx.load_verify_locations(CERTFILE)
1584 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001585 # but CAFILE_CACERT is a CA cert
1586 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001587 self.assertEqual(ctx.get_ca_certs(),
1588 [{'issuer': ((('organizationName', 'Root CA'),),
1589 (('organizationalUnitName', 'http://www.cacert.org'),),
1590 (('commonName', 'CA Cert Signing Authority'),),
1591 (('emailAddress', 'support@cacert.org'),)),
1592 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1593 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1594 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001595 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001596 'subject': ((('organizationName', 'Root CA'),),
1597 (('organizationalUnitName', 'http://www.cacert.org'),),
1598 (('commonName', 'CA Cert Signing Authority'),),
1599 (('emailAddress', 'support@cacert.org'),)),
1600 'version': 3}])
1601
Martin Panterb55f8b72016-01-14 12:53:56 +00001602 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001603 pem = f.read()
1604 der = ssl.PEM_cert_to_DER_cert(pem)
1605 self.assertEqual(ctx.get_ca_certs(True), [der])
1606
Christian Heimes72d28502013-11-23 13:56:58 +01001607 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001608 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001609 ctx.load_default_certs()
1610
Christian Heimesa170fa12017-09-15 20:27:30 +02001611 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001612 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1613 ctx.load_default_certs()
1614
Christian Heimesa170fa12017-09-15 20:27:30 +02001615 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001616 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1617
Christian Heimesa170fa12017-09-15 20:27:30 +02001618 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001619 self.assertRaises(TypeError, ctx.load_default_certs, None)
1620 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1621
Benjamin Peterson91244e02014-10-03 18:17:15 -04001622 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimes598894f2016-09-05 23:19:05 +02001623 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001624 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001625 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001626 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001627 env["SSL_CERT_DIR"] = CAPATH
1628 env["SSL_CERT_FILE"] = CERTFILE
1629 ctx.load_default_certs()
1630 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1631
Benjamin Peterson91244e02014-10-03 18:17:15 -04001632 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001633 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001634 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001635 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001636 ctx.load_default_certs()
1637 stats = ctx.cert_store_stats()
1638
Christian Heimesa170fa12017-09-15 20:27:30 +02001639 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001640 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001641 env["SSL_CERT_DIR"] = CAPATH
1642 env["SSL_CERT_FILE"] = CERTFILE
1643 ctx.load_default_certs()
1644 stats["x509"] += 1
1645 self.assertEqual(ctx.cert_store_stats(), stats)
1646
Christian Heimes358cfd42016-09-10 22:43:48 +02001647 def _assert_context_options(self, ctx):
1648 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1649 if OP_NO_COMPRESSION != 0:
1650 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1651 OP_NO_COMPRESSION)
1652 if OP_SINGLE_DH_USE != 0:
1653 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1654 OP_SINGLE_DH_USE)
1655 if OP_SINGLE_ECDH_USE != 0:
1656 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1657 OP_SINGLE_ECDH_USE)
1658 if OP_CIPHER_SERVER_PREFERENCE != 0:
1659 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1660 OP_CIPHER_SERVER_PREFERENCE)
1661
Christian Heimes4c05b472013-11-23 15:58:30 +01001662 def test_create_default_context(self):
1663 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001664
Christian Heimesa170fa12017-09-15 20:27:30 +02001665 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001666 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001667 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001668 self._assert_context_options(ctx)
1669
Christian Heimes4c05b472013-11-23 15:58:30 +01001670 with open(SIGNING_CA) as f:
1671 cadata = f.read()
1672 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1673 cadata=cadata)
Christian Heimesa170fa12017-09-15 20:27:30 +02001674 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001675 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001676 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001677
1678 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001679 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001680 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001681 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001682
Christian Heimes67986f92013-11-23 22:43:47 +01001683 def test__create_stdlib_context(self):
1684 ctx = ssl._create_stdlib_context()
Christian Heimesa170fa12017-09-15 20:27:30 +02001685 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001686 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001687 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001688 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001689
1690 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1691 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1692 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001693 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001694
1695 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001696 cert_reqs=ssl.CERT_REQUIRED,
1697 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001698 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1699 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001700 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001701 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001702
1703 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001704 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001705 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001706 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001707
Christian Heimes1aa9a752013-12-02 02:41:19 +01001708 def test_check_hostname(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001709 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001710 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001711 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001712
Christian Heimese82c0342017-09-15 20:29:57 +02001713 # Auto set CERT_REQUIRED
1714 ctx.check_hostname = True
1715 self.assertTrue(ctx.check_hostname)
1716 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1717 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001718 ctx.verify_mode = ssl.CERT_REQUIRED
1719 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001720 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001721
Christian Heimese82c0342017-09-15 20:29:57 +02001722 # Changing verify_mode does not affect check_hostname
1723 ctx.check_hostname = False
1724 ctx.verify_mode = ssl.CERT_NONE
1725 ctx.check_hostname = False
1726 self.assertFalse(ctx.check_hostname)
1727 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1728 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001729 ctx.check_hostname = True
1730 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001731 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1732
1733 ctx.check_hostname = False
1734 ctx.verify_mode = ssl.CERT_OPTIONAL
1735 ctx.check_hostname = False
1736 self.assertFalse(ctx.check_hostname)
1737 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1738 # keep CERT_OPTIONAL
1739 ctx.check_hostname = True
1740 self.assertTrue(ctx.check_hostname)
1741 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001742
1743 # Cannot set CERT_NONE with check_hostname enabled
1744 with self.assertRaises(ValueError):
1745 ctx.verify_mode = ssl.CERT_NONE
1746 ctx.check_hostname = False
1747 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001748 ctx.verify_mode = ssl.CERT_NONE
1749 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001750
Christian Heimes5fe668c2016-09-12 00:01:11 +02001751 def test_context_client_server(self):
1752 # PROTOCOL_TLS_CLIENT has sane defaults
1753 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1754 self.assertTrue(ctx.check_hostname)
1755 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1756
1757 # PROTOCOL_TLS_SERVER has different but also sane defaults
1758 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1759 self.assertFalse(ctx.check_hostname)
1760 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1761
Christian Heimes4df60f12017-09-15 20:26:05 +02001762 def test_context_custom_class(self):
1763 class MySSLSocket(ssl.SSLSocket):
1764 pass
1765
1766 class MySSLObject(ssl.SSLObject):
1767 pass
1768
1769 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1770 ctx.sslsocket_class = MySSLSocket
1771 ctx.sslobject_class = MySSLObject
1772
1773 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1774 self.assertIsInstance(sock, MySSLSocket)
1775 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1776 self.assertIsInstance(obj, MySSLObject)
1777
Christian Heimes78c7d522019-06-03 21:00:10 +02001778 def test_num_tickest(self):
1779 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1780 self.assertEqual(ctx.num_tickets, 2)
1781 ctx.num_tickets = 1
1782 self.assertEqual(ctx.num_tickets, 1)
1783 ctx.num_tickets = 0
1784 self.assertEqual(ctx.num_tickets, 0)
1785 with self.assertRaises(ValueError):
1786 ctx.num_tickets = -1
1787 with self.assertRaises(TypeError):
1788 ctx.num_tickets = None
1789
1790 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1791 self.assertEqual(ctx.num_tickets, 2)
1792 with self.assertRaises(ValueError):
1793 ctx.num_tickets = 1
1794
Antoine Pitrou152efa22010-05-16 18:19:27 +00001795
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001796class SSLErrorTests(unittest.TestCase):
1797
1798 def test_str(self):
1799 # The str() of a SSLError doesn't include the errno
1800 e = ssl.SSLError(1, "foo")
1801 self.assertEqual(str(e), "foo")
1802 self.assertEqual(e.errno, 1)
1803 # Same for a subclass
1804 e = ssl.SSLZeroReturnError(1, "foo")
1805 self.assertEqual(str(e), "foo")
1806 self.assertEqual(e.errno, 1)
1807
Paul Monsonf3550692019-06-19 13:09:54 -07001808 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001809 def test_lib_reason(self):
1810 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001811 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001812 with self.assertRaises(ssl.SSLError) as cm:
1813 ctx.load_dh_params(CERTFILE)
1814 self.assertEqual(cm.exception.library, 'PEM')
1815 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1816 s = str(cm.exception)
1817 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1818
1819 def test_subclass(self):
1820 # Check that the appropriate SSLError subclass is raised
1821 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001822 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1823 ctx.check_hostname = False
1824 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001825 with socket.create_server(("127.0.0.1", 0)) as s:
1826 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001827 c.setblocking(False)
1828 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001829 with self.assertRaises(ssl.SSLWantReadError) as cm:
1830 c.do_handshake()
1831 s = str(cm.exception)
1832 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1833 # For compatibility
1834 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1835
1836
Christian Heimes61d478c2018-01-27 15:51:38 +01001837 def test_bad_server_hostname(self):
1838 ctx = ssl.create_default_context()
1839 with self.assertRaises(ValueError):
1840 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1841 server_hostname="")
1842 with self.assertRaises(ValueError):
1843 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1844 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001845 with self.assertRaises(TypeError):
1846 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1847 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001848
1849
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001850class MemoryBIOTests(unittest.TestCase):
1851
1852 def test_read_write(self):
1853 bio = ssl.MemoryBIO()
1854 bio.write(b'foo')
1855 self.assertEqual(bio.read(), b'foo')
1856 self.assertEqual(bio.read(), b'')
1857 bio.write(b'foo')
1858 bio.write(b'bar')
1859 self.assertEqual(bio.read(), b'foobar')
1860 self.assertEqual(bio.read(), b'')
1861 bio.write(b'baz')
1862 self.assertEqual(bio.read(2), b'ba')
1863 self.assertEqual(bio.read(1), b'z')
1864 self.assertEqual(bio.read(1), b'')
1865
1866 def test_eof(self):
1867 bio = ssl.MemoryBIO()
1868 self.assertFalse(bio.eof)
1869 self.assertEqual(bio.read(), b'')
1870 self.assertFalse(bio.eof)
1871 bio.write(b'foo')
1872 self.assertFalse(bio.eof)
1873 bio.write_eof()
1874 self.assertFalse(bio.eof)
1875 self.assertEqual(bio.read(2), b'fo')
1876 self.assertFalse(bio.eof)
1877 self.assertEqual(bio.read(1), b'o')
1878 self.assertTrue(bio.eof)
1879 self.assertEqual(bio.read(), b'')
1880 self.assertTrue(bio.eof)
1881
1882 def test_pending(self):
1883 bio = ssl.MemoryBIO()
1884 self.assertEqual(bio.pending, 0)
1885 bio.write(b'foo')
1886 self.assertEqual(bio.pending, 3)
1887 for i in range(3):
1888 bio.read(1)
1889 self.assertEqual(bio.pending, 3-i-1)
1890 for i in range(3):
1891 bio.write(b'x')
1892 self.assertEqual(bio.pending, i+1)
1893 bio.read()
1894 self.assertEqual(bio.pending, 0)
1895
1896 def test_buffer_types(self):
1897 bio = ssl.MemoryBIO()
1898 bio.write(b'foo')
1899 self.assertEqual(bio.read(), b'foo')
1900 bio.write(bytearray(b'bar'))
1901 self.assertEqual(bio.read(), b'bar')
1902 bio.write(memoryview(b'baz'))
1903 self.assertEqual(bio.read(), b'baz')
1904
1905 def test_error_types(self):
1906 bio = ssl.MemoryBIO()
1907 self.assertRaises(TypeError, bio.write, 'foo')
1908 self.assertRaises(TypeError, bio.write, None)
1909 self.assertRaises(TypeError, bio.write, True)
1910 self.assertRaises(TypeError, bio.write, 1)
1911
1912
Christian Heimes9d50ab52018-02-27 10:17:30 +01001913class SSLObjectTests(unittest.TestCase):
1914 def test_private_init(self):
1915 bio = ssl.MemoryBIO()
1916 with self.assertRaisesRegex(TypeError, "public constructor"):
1917 ssl.SSLObject(bio, bio)
1918
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001919 def test_unwrap(self):
1920 client_ctx, server_ctx, hostname = testing_context()
1921 c_in = ssl.MemoryBIO()
1922 c_out = ssl.MemoryBIO()
1923 s_in = ssl.MemoryBIO()
1924 s_out = ssl.MemoryBIO()
1925 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1926 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1927
1928 # Loop on the handshake for a bit to get it settled
1929 for _ in range(5):
1930 try:
1931 client.do_handshake()
1932 except ssl.SSLWantReadError:
1933 pass
1934 if c_out.pending:
1935 s_in.write(c_out.read())
1936 try:
1937 server.do_handshake()
1938 except ssl.SSLWantReadError:
1939 pass
1940 if s_out.pending:
1941 c_in.write(s_out.read())
1942 # Now the handshakes should be complete (don't raise WantReadError)
1943 client.do_handshake()
1944 server.do_handshake()
1945
1946 # Now if we unwrap one side unilaterally, it should send close-notify
1947 # and raise WantReadError:
1948 with self.assertRaises(ssl.SSLWantReadError):
1949 client.unwrap()
1950
1951 # But server.unwrap() does not raise, because it reads the client's
1952 # close-notify:
1953 s_in.write(c_out.read())
1954 server.unwrap()
1955
1956 # And now that the client gets the server's close-notify, it doesn't
1957 # raise either.
1958 c_in.write(s_out.read())
1959 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001960
Martin Panter3840b2a2016-03-27 01:53:46 +00001961class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001962 """Tests that connect to a simple server running in the background"""
1963
1964 def setUp(self):
juhovh49fdf112021-04-18 21:11:48 +10001965 self.server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1966 self.server_context.load_cert_chain(SIGNED_CERTFILE)
1967 server = ThreadedEchoServer(context=self.server_context)
Martin Panter3840b2a2016-03-27 01:53:46 +00001968 self.server_addr = (HOST, server.port)
1969 server.__enter__()
1970 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001971
Antoine Pitrou480a1242010-04-28 21:37:09 +00001972 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001973 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001974 cert_reqs=ssl.CERT_NONE) as s:
1975 s.connect(self.server_addr)
1976 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001977 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001978
Martin Panter3840b2a2016-03-27 01:53:46 +00001979 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001980 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001981 cert_reqs=ssl.CERT_REQUIRED,
1982 ca_certs=SIGNING_CA) as s:
1983 s.connect(self.server_addr)
1984 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001985 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001986
Martin Panter3840b2a2016-03-27 01:53:46 +00001987 def test_connect_fail(self):
1988 # This should fail because we have no verification certs. Connection
1989 # failure crashes ThreadedEchoServer, so run this in an independent
1990 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001991 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001992 cert_reqs=ssl.CERT_REQUIRED)
1993 self.addCleanup(s.close)
1994 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1995 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001996
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001997 def test_connect_ex(self):
1998 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02001999 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002000 cert_reqs=ssl.CERT_REQUIRED,
2001 ca_certs=SIGNING_CA)
2002 self.addCleanup(s.close)
2003 self.assertEqual(0, s.connect_ex(self.server_addr))
2004 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002005
2006 def test_non_blocking_connect_ex(self):
2007 # Issue #11326: non-blocking connect_ex() should allow handshake
2008 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02002009 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002010 cert_reqs=ssl.CERT_REQUIRED,
2011 ca_certs=SIGNING_CA,
2012 do_handshake_on_connect=False)
2013 self.addCleanup(s.close)
2014 s.setblocking(False)
2015 rc = s.connect_ex(self.server_addr)
2016 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2017 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2018 # Wait for connect to finish
2019 select.select([], [s], [], 5.0)
2020 # Non-blocking handshake
2021 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002022 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002023 s.do_handshake()
2024 break
2025 except ssl.SSLWantReadError:
2026 select.select([s], [], [], 5.0)
2027 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002028 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002029 # SSL established
2030 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002031
Antoine Pitrou152efa22010-05-16 18:19:27 +00002032 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002033 # Same as test_connect, but with a separately created context
Christian Heimesa170fa12017-09-15 20:27:30 +02002034 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002035 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2036 s.connect(self.server_addr)
2037 self.assertEqual({}, s.getpeercert())
2038 # Same with a server hostname
2039 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2040 server_hostname="dummy") as s:
2041 s.connect(self.server_addr)
2042 ctx.verify_mode = ssl.CERT_REQUIRED
2043 # This should succeed because we specify the root cert
2044 ctx.load_verify_locations(SIGNING_CA)
2045 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2046 s.connect(self.server_addr)
2047 cert = s.getpeercert()
2048 self.assertTrue(cert)
2049
2050 def test_connect_with_context_fail(self):
2051 # This should fail because we have no verification certs. Connection
2052 # failure crashes ThreadedEchoServer, so run this in an independent
2053 # test method.
Christian Heimesa170fa12017-09-15 20:27:30 +02002054 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002055 ctx.verify_mode = ssl.CERT_REQUIRED
2056 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
2057 self.addCleanup(s.close)
2058 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2059 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002060
2061 def test_connect_capath(self):
2062 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002063 # NOTE: the subject hashing algorithm has been changed between
2064 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2065 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002066 # filename) for this test to be portable across OpenSSL releases.
Christian Heimesa170fa12017-09-15 20:27:30 +02002067 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002068 ctx.verify_mode = ssl.CERT_REQUIRED
2069 ctx.load_verify_locations(capath=CAPATH)
2070 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2071 s.connect(self.server_addr)
2072 cert = s.getpeercert()
2073 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002074
Martin Panter3840b2a2016-03-27 01:53:46 +00002075 # Same with a bytes `capath` argument
Christian Heimesa170fa12017-09-15 20:27:30 +02002076 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002077 ctx.verify_mode = ssl.CERT_REQUIRED
2078 ctx.load_verify_locations(capath=BYTES_CAPATH)
2079 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2080 s.connect(self.server_addr)
2081 cert = s.getpeercert()
2082 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002083
Christian Heimesefff7062013-11-21 03:35:02 +01002084 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002085 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002086 pem = f.read()
2087 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimesa170fa12017-09-15 20:27:30 +02002088 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002089 ctx.verify_mode = ssl.CERT_REQUIRED
2090 ctx.load_verify_locations(cadata=pem)
2091 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2092 s.connect(self.server_addr)
2093 cert = s.getpeercert()
2094 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002095
Martin Panter3840b2a2016-03-27 01:53:46 +00002096 # same with DER
Christian Heimesa170fa12017-09-15 20:27:30 +02002097 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002098 ctx.verify_mode = ssl.CERT_REQUIRED
2099 ctx.load_verify_locations(cadata=der)
2100 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2101 s.connect(self.server_addr)
2102 cert = s.getpeercert()
2103 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002104
Antoine Pitroue3220242010-04-24 11:13:53 +00002105 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2106 def test_makefile_close(self):
2107 # Issue #5238: creating a file-like object with makefile() shouldn't
2108 # delay closing the underlying "real socket" (here tested with its
2109 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002110 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002111 ss.connect(self.server_addr)
2112 fd = ss.fileno()
2113 f = ss.makefile()
2114 f.close()
2115 # The fd is still open
2116 os.read(fd, 0)
2117 # Closing the SSL socket should close the fd too
2118 ss.close()
2119 gc.collect()
2120 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002121 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002122 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002123
Antoine Pitrou480a1242010-04-28 21:37:09 +00002124 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002125 s = socket.socket(socket.AF_INET)
2126 s.connect(self.server_addr)
2127 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002128 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002129 cert_reqs=ssl.CERT_NONE,
2130 do_handshake_on_connect=False)
2131 self.addCleanup(s.close)
2132 count = 0
2133 while True:
2134 try:
2135 count += 1
2136 s.do_handshake()
2137 break
2138 except ssl.SSLWantReadError:
2139 select.select([s], [], [])
2140 except ssl.SSLWantWriteError:
2141 select.select([], [s], [])
2142 if support.verbose:
2143 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002144
Antoine Pitrou480a1242010-04-28 21:37:09 +00002145 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002146 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002147
juhovh49fdf112021-04-18 21:11:48 +10002148 @needs_sni
2149 def test_get_server_certificate_sni(self):
2150 host, port = self.server_addr
2151 server_names = []
2152
2153 # We store servername_cb arguments to make sure they match the host
2154 def servername_cb(ssl_sock, server_name, initial_context):
2155 server_names.append(server_name)
2156 self.server_context.set_servername_callback(servername_cb)
2157
2158 pem = ssl.get_server_certificate((host, port))
2159 if not pem:
2160 self.fail("No server certificate on %s:%s!" % (host, port))
2161
2162 pem = ssl.get_server_certificate((host, port), ca_certs=SIGNING_CA)
2163 if not pem:
2164 self.fail("No server certificate on %s:%s!" % (host, port))
2165 if support.verbose:
2166 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port, pem))
2167
2168 self.assertEqual(server_names, [host, host])
2169
Martin Panter3840b2a2016-03-27 01:53:46 +00002170 def test_get_server_certificate_fail(self):
2171 # Connection failure crashes ThreadedEchoServer, so run this in an
2172 # independent test method
2173 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002174
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002175 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002176 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002177 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2178 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002179 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002180 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2181 s.connect(self.server_addr)
2182 # Error checking can happen at instantiation or when connecting
2183 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2184 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002185 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002186 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2187 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002188
Christian Heimes9a5395a2013-06-17 15:44:12 +02002189 def test_get_ca_certs_capath(self):
2190 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002191 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002192 ctx.load_verify_locations(capath=CAPATH)
2193 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002194 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2195 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002196 s.connect(self.server_addr)
2197 cert = s.getpeercert()
2198 self.assertTrue(cert)
2199 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002200
Christian Heimes575596e2013-12-15 21:49:17 +01002201 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01002202 def test_context_setget(self):
2203 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002204 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2205 ctx1.load_verify_locations(capath=CAPATH)
2206 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2207 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002208 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002209 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002210 ss.connect(self.server_addr)
2211 self.assertIs(ss.context, ctx1)
2212 self.assertIs(ss._sslobj.context, ctx1)
2213 ss.context = ctx2
2214 self.assertIs(ss.context, ctx2)
2215 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002216
2217 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2218 # A simple IO loop. Call func(*args) depending on the error we get
2219 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002220 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002221 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002222 count = 0
2223 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002224 if time.monotonic() > deadline:
2225 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002226 errno = None
2227 count += 1
2228 try:
2229 ret = func(*args)
2230 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002231 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002232 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002233 raise
2234 errno = e.errno
2235 # Get any data from the outgoing BIO irrespective of any error, and
2236 # send it to the socket.
2237 buf = outgoing.read()
2238 sock.sendall(buf)
2239 # If there's no error, we're done. For WANT_READ, we need to get
2240 # data from the socket and put it in the incoming BIO.
2241 if errno is None:
2242 break
2243 elif errno == ssl.SSL_ERROR_WANT_READ:
2244 buf = sock.recv(32768)
2245 if buf:
2246 incoming.write(buf)
2247 else:
2248 incoming.write_eof()
2249 if support.verbose:
2250 sys.stdout.write("Needed %d calls to complete %s().\n"
2251 % (count, func.__name__))
2252 return ret
2253
Martin Panter3840b2a2016-03-27 01:53:46 +00002254 def test_bio_handshake(self):
2255 sock = socket.socket(socket.AF_INET)
2256 self.addCleanup(sock.close)
2257 sock.connect(self.server_addr)
2258 incoming = ssl.MemoryBIO()
2259 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002260 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2261 self.assertTrue(ctx.check_hostname)
2262 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002263 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002264 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2265 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002266 self.assertIs(sslobj._sslobj.owner, sslobj)
2267 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002268 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002269 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002270 self.assertRaises(ValueError, sslobj.getpeercert)
2271 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2272 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2273 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2274 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002275 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002276 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002277 self.assertTrue(sslobj.getpeercert())
2278 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2279 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2280 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002281 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002282 except ssl.SSLSyscallError:
2283 # If the server shuts down the TCP connection without sending a
2284 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2285 pass
2286 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2287
2288 def test_bio_read_write_data(self):
2289 sock = socket.socket(socket.AF_INET)
2290 self.addCleanup(sock.close)
2291 sock.connect(self.server_addr)
2292 incoming = ssl.MemoryBIO()
2293 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002294 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002295 ctx.verify_mode = ssl.CERT_NONE
2296 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2297 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2298 req = b'FOO\n'
2299 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2300 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2301 self.assertEqual(buf, b'foo\n')
2302 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002303
2304
Martin Panter3840b2a2016-03-27 01:53:46 +00002305class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002306
Martin Panter3840b2a2016-03-27 01:53:46 +00002307 def test_timeout_connect_ex(self):
2308 # Issue #12065: on a timeout, connect_ex() should return the original
2309 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002310 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002311 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002312 cert_reqs=ssl.CERT_REQUIRED,
2313 do_handshake_on_connect=False)
2314 self.addCleanup(s.close)
2315 s.settimeout(0.0000001)
2316 rc = s.connect_ex((REMOTE_HOST, 443))
2317 if rc == 0:
2318 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002319 elif rc == errno.ENETUNREACH:
2320 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002321 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2322
Serhiy Storchaka16994912020-04-25 10:06:29 +03002323 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002324 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002325 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002326 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2327 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2328
Martin Panter3840b2a2016-03-27 01:53:46 +00002329
2330def _test_get_server_certificate(test, host, port, cert=None):
2331 pem = ssl.get_server_certificate((host, port))
2332 if not pem:
2333 test.fail("No server certificate on %s:%s!" % (host, port))
2334
2335 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2336 if not pem:
2337 test.fail("No server certificate on %s:%s!" % (host, port))
2338 if support.verbose:
2339 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2340
2341def _test_get_server_certificate_fail(test, host, port):
2342 try:
2343 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2344 except ssl.SSLError as x:
2345 #should fail
2346 if support.verbose:
2347 sys.stdout.write("%s\n" % x)
2348 else:
2349 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2350
2351
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002352from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002353
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002354class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002355
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002356 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002357
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002358 """A mildly complicated class, because we want it to work both
2359 with and without the SSL wrapper around the socket connection, so
2360 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002361
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002362 def __init__(self, server, connsock, addr):
2363 self.server = server
2364 self.running = False
2365 self.sock = connsock
2366 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002367 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002368 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002369 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002370 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002371
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002372 def wrap_conn(self):
2373 try:
2374 self.sslconn = self.server.context.wrap_socket(
2375 self.sock, server_side=True)
2376 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
2377 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002378 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002379 # We treat ConnectionResetError as though it were an
2380 # SSLError - OpenSSL on Ubuntu abruptly closes the
2381 # connection when asked to use an unsupported protocol.
2382 #
Christian Heimes529525f2018-05-23 22:24:45 +02002383 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2384 # tries to send session tickets after handshake.
2385 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002386 #
2387 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2388 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002389 self.server.conn_errors.append(str(e))
2390 if self.server.chatty:
2391 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2392 self.running = False
2393 self.close()
2394 return False
2395 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002396 # OSError may occur with wrong protocols, e.g. both
2397 # sides use PROTOCOL_TLS_SERVER.
2398 #
2399 # XXX Various errors can have happened here, for example
2400 # a mismatching protocol version, an invalid certificate,
2401 # or a low-level bug. This should be made more discriminating.
2402 #
2403 # bpo-31323: Store the exception as string to prevent
2404 # a reference leak: server -> conn_errors -> exception
2405 # -> traceback -> self (ConnectionHandler) -> server
2406 self.server.conn_errors.append(str(e))
2407 if self.server.chatty:
2408 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2409 self.running = False
2410 self.server.stop()
2411 self.close()
2412 return False
2413 else:
2414 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2415 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2416 cert = self.sslconn.getpeercert()
2417 if support.verbose and self.server.chatty:
2418 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2419 cert_binary = self.sslconn.getpeercert(True)
2420 if support.verbose and self.server.chatty:
2421 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2422 cipher = self.sslconn.cipher()
2423 if support.verbose and self.server.chatty:
2424 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
2425 sys.stdout.write(" server: selected protocol is now "
2426 + str(self.sslconn.selected_npn_protocol()) + "\n")
2427 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002428
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002429 def read(self):
2430 if self.sslconn:
2431 return self.sslconn.read()
2432 else:
2433 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002434
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002435 def write(self, bytes):
2436 if self.sslconn:
2437 return self.sslconn.write(bytes)
2438 else:
2439 return self.sock.send(bytes)
2440
2441 def close(self):
2442 if self.sslconn:
2443 self.sslconn.close()
2444 else:
2445 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002446
Antoine Pitrou480a1242010-04-28 21:37:09 +00002447 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002448 self.running = True
2449 if not self.server.starttls_server:
2450 if not self.wrap_conn():
2451 return
2452 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002453 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002454 msg = self.read()
2455 stripped = msg.strip()
2456 if not stripped:
2457 # eof, so quit this handler
2458 self.running = False
2459 try:
2460 self.sock = self.sslconn.unwrap()
2461 except OSError:
2462 # Many tests shut the TCP connection down
2463 # without an SSL shutdown. This causes
2464 # unwrap() to raise OSError with errno=0!
2465 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002466 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002467 self.sslconn = None
2468 self.close()
2469 elif stripped == b'over':
2470 if support.verbose and self.server.connectionchatty:
2471 sys.stdout.write(" server: client closed connection\n")
2472 self.close()
2473 return
2474 elif (self.server.starttls_server and
2475 stripped == b'STARTTLS'):
2476 if support.verbose and self.server.connectionchatty:
2477 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2478 self.write(b"OK\n")
2479 if not self.wrap_conn():
2480 return
2481 elif (self.server.starttls_server and self.sslconn
2482 and stripped == b'ENDTLS'):
2483 if support.verbose and self.server.connectionchatty:
2484 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2485 self.write(b"OK\n")
2486 self.sock = self.sslconn.unwrap()
2487 self.sslconn = None
2488 if support.verbose and self.server.connectionchatty:
2489 sys.stdout.write(" server: connection is now unencrypted...\n")
2490 elif stripped == b'CB tls-unique':
2491 if support.verbose and self.server.connectionchatty:
2492 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2493 data = self.sslconn.get_channel_binding("tls-unique")
2494 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002495 elif stripped == b'PHA':
2496 if support.verbose and self.server.connectionchatty:
2497 sys.stdout.write(" server: initiating post handshake auth\n")
2498 try:
2499 self.sslconn.verify_client_post_handshake()
2500 except ssl.SSLError as e:
2501 self.write(repr(e).encode("us-ascii") + b"\n")
2502 else:
2503 self.write(b"OK\n")
2504 elif stripped == b'HASCERT':
2505 if self.sslconn.getpeercert() is not None:
2506 self.write(b'TRUE\n')
2507 else:
2508 self.write(b'FALSE\n')
2509 elif stripped == b'GETCERT':
2510 cert = self.sslconn.getpeercert()
2511 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002512 else:
2513 if (support.verbose and
2514 self.server.connectionchatty):
2515 ctype = (self.sslconn and "encrypted") or "unencrypted"
2516 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2517 % (msg, ctype, msg.lower(), ctype))
2518 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002519 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002520 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2521 # when connection is not shut down gracefully.
2522 if self.server.chatty and support.verbose:
2523 sys.stdout.write(
2524 " Connection reset by peer: {}\n".format(
2525 self.addr)
2526 )
2527 self.close()
2528 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002529 except ssl.SSLError as err:
2530 # On Windows sometimes test_pha_required_nocert receives the
2531 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2532 # before the 'tlsv13 alert certificate required' exception.
2533 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2534 # is received test_pha_required_nocert fails with ConnectionResetError
2535 # because the underlying socket is closed
2536 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2537 if self.server.chatty and support.verbose:
2538 sys.stdout.write(err.args[1])
2539 # test_pha_required_nocert is expecting this exception
2540 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002541 except OSError:
2542 if self.server.chatty:
2543 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002544 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002545 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002546
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002547 # normally, we'd just stop here, but for the test
2548 # harness, we want to stop the server
2549 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002550
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002551 def __init__(self, certificate=None, ssl_version=None,
2552 certreqs=None, cacerts=None,
2553 chatty=True, connectionchatty=False, starttls_server=False,
2554 npn_protocols=None, alpn_protocols=None,
2555 ciphers=None, context=None):
2556 if context:
2557 self.context = context
2558 else:
2559 self.context = ssl.SSLContext(ssl_version
2560 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002561 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002562 self.context.verify_mode = (certreqs if certreqs is not None
2563 else ssl.CERT_NONE)
2564 if cacerts:
2565 self.context.load_verify_locations(cacerts)
2566 if certificate:
2567 self.context.load_cert_chain(certificate)
2568 if npn_protocols:
2569 self.context.set_npn_protocols(npn_protocols)
2570 if alpn_protocols:
2571 self.context.set_alpn_protocols(alpn_protocols)
2572 if ciphers:
2573 self.context.set_ciphers(ciphers)
2574 self.chatty = chatty
2575 self.connectionchatty = connectionchatty
2576 self.starttls_server = starttls_server
2577 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002578 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002579 self.flag = None
2580 self.active = False
2581 self.selected_npn_protocols = []
2582 self.selected_alpn_protocols = []
2583 self.shared_ciphers = []
2584 self.conn_errors = []
2585 threading.Thread.__init__(self)
2586 self.daemon = True
2587
2588 def __enter__(self):
2589 self.start(threading.Event())
2590 self.flag.wait()
2591 return self
2592
2593 def __exit__(self, *args):
2594 self.stop()
2595 self.join()
2596
2597 def start(self, flag=None):
2598 self.flag = flag
2599 threading.Thread.start(self)
2600
2601 def run(self):
2602 self.sock.settimeout(0.05)
2603 self.sock.listen()
2604 self.active = True
2605 if self.flag:
2606 # signal an event
2607 self.flag.set()
2608 while self.active:
2609 try:
2610 newconn, connaddr = self.sock.accept()
2611 if support.verbose and self.chatty:
2612 sys.stdout.write(' server: new connection from '
2613 + repr(connaddr) + '\n')
2614 handler = self.ConnectionHandler(self, newconn, connaddr)
2615 handler.start()
2616 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002617 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002618 pass
2619 except KeyboardInterrupt:
2620 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002621 except BaseException as e:
2622 if support.verbose and self.chatty:
2623 sys.stdout.write(
2624 ' connection handling failed: ' + repr(e) + '\n')
2625
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002626 self.sock.close()
2627
2628 def stop(self):
2629 self.active = False
2630
2631class AsyncoreEchoServer(threading.Thread):
2632
2633 # this one's based on asyncore.dispatcher
2634
2635 class EchoServer (asyncore.dispatcher):
2636
2637 class ConnectionHandler(asyncore.dispatcher_with_send):
2638
2639 def __init__(self, conn, certfile):
2640 self.socket = test_wrap_socket(conn, server_side=True,
2641 certfile=certfile,
2642 do_handshake_on_connect=False)
2643 asyncore.dispatcher_with_send.__init__(self, self.socket)
2644 self._ssl_accepting = True
2645 self._do_ssl_handshake()
2646
2647 def readable(self):
2648 if isinstance(self.socket, ssl.SSLSocket):
2649 while self.socket.pending() > 0:
2650 self.handle_read_event()
2651 return True
2652
2653 def _do_ssl_handshake(self):
2654 try:
2655 self.socket.do_handshake()
2656 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2657 return
2658 except ssl.SSLEOFError:
2659 return self.handle_close()
2660 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002661 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002662 except OSError as err:
2663 if err.args[0] == errno.ECONNABORTED:
2664 return self.handle_close()
2665 else:
2666 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002667
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002668 def handle_read(self):
2669 if self._ssl_accepting:
2670 self._do_ssl_handshake()
2671 else:
2672 data = self.recv(1024)
2673 if support.verbose:
2674 sys.stdout.write(" server: read %s from client\n" % repr(data))
2675 if not data:
2676 self.close()
2677 else:
2678 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002679
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002680 def handle_close(self):
2681 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002682 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002683 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002684
2685 def handle_error(self):
2686 raise
2687
Trent Nelson78520002008-04-10 20:54:35 +00002688 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002689 self.certfile = certfile
2690 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002691 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002692 asyncore.dispatcher.__init__(self, sock)
2693 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002694
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002695 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002696 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002697 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2698 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002699
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002700 def handle_error(self):
2701 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002702
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002703 def __init__(self, certfile):
2704 self.flag = None
2705 self.active = False
2706 self.server = self.EchoServer(certfile)
2707 self.port = self.server.port
2708 threading.Thread.__init__(self)
2709 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002710
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002711 def __str__(self):
2712 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002713
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002714 def __enter__(self):
2715 self.start(threading.Event())
2716 self.flag.wait()
2717 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002718
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002719 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002720 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002721 sys.stdout.write(" cleanup: stopping server.\n")
2722 self.stop()
2723 if support.verbose:
2724 sys.stdout.write(" cleanup: joining server thread.\n")
2725 self.join()
2726 if support.verbose:
2727 sys.stdout.write(" cleanup: successfully joined.\n")
2728 # make sure that ConnectionHandler is removed from socket_map
2729 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002730
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002731 def start (self, flag=None):
2732 self.flag = flag
2733 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002734
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002735 def run(self):
2736 self.active = True
2737 if self.flag:
2738 self.flag.set()
2739 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002740 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002741 asyncore.loop(1)
2742 except:
2743 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002744
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002745 def stop(self):
2746 self.active = False
2747 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002748
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002749def server_params_test(client_context, server_context, indata=b"FOO\n",
2750 chatty=True, connectionchatty=False, sni_name=None,
2751 session=None):
2752 """
2753 Launch a server, connect a client to it and try various reads
2754 and writes.
2755 """
2756 stats = {}
2757 server = ThreadedEchoServer(context=server_context,
2758 chatty=chatty,
2759 connectionchatty=False)
2760 with server:
2761 with client_context.wrap_socket(socket.socket(),
2762 server_hostname=sni_name, session=session) as s:
2763 s.connect((HOST, server.port))
2764 for arg in [indata, bytearray(indata), memoryview(indata)]:
2765 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002766 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002767 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002768 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002769 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002770 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002771 if connectionchatty:
2772 if support.verbose:
2773 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002774 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002775 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002776 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2777 % (outdata[:20], len(outdata),
2778 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002779 s.write(b"over\n")
2780 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002781 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002782 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002783 stats.update({
2784 'compression': s.compression(),
2785 'cipher': s.cipher(),
2786 'peercert': s.getpeercert(),
2787 'client_alpn_protocol': s.selected_alpn_protocol(),
2788 'client_npn_protocol': s.selected_npn_protocol(),
2789 'version': s.version(),
2790 'session_reused': s.session_reused,
2791 'session': s.session,
2792 })
2793 s.close()
2794 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2795 stats['server_npn_protocols'] = server.selected_npn_protocols
2796 stats['server_shared_ciphers'] = server.shared_ciphers
2797 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002798
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002799def try_protocol_combo(server_protocol, client_protocol, expect_success,
2800 certsreqs=None, server_options=0, client_options=0):
2801 """
2802 Try to SSL-connect using *client_protocol* to *server_protocol*.
2803 If *expect_success* is true, assert that the connection succeeds,
2804 if it's false, assert that the connection fails.
2805 Also, if *expect_success* is a string, assert that it is the protocol
2806 version actually used by the connection.
2807 """
2808 if certsreqs is None:
2809 certsreqs = ssl.CERT_NONE
2810 certtype = {
2811 ssl.CERT_NONE: "CERT_NONE",
2812 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2813 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2814 }[certsreqs]
2815 if support.verbose:
2816 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2817 sys.stdout.write(formatstr %
2818 (ssl.get_protocol_name(client_protocol),
2819 ssl.get_protocol_name(server_protocol),
2820 certtype))
2821 client_context = ssl.SSLContext(client_protocol)
2822 client_context.options |= client_options
2823 server_context = ssl.SSLContext(server_protocol)
2824 server_context.options |= server_options
2825
Victor Stinner3ef63442019-02-19 18:06:03 +01002826 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2827 if (min_version is not None
2828 # SSLContext.minimum_version is only available on recent OpenSSL
2829 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2830 and hasattr(server_context, 'minimum_version')
2831 and server_protocol == ssl.PROTOCOL_TLS
2832 and server_context.minimum_version > min_version):
2833 # If OpenSSL configuration is strict and requires more recent TLS
2834 # version, we have to change the minimum to test old TLS versions.
2835 server_context.minimum_version = min_version
2836
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002837 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2838 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2839 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002840 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002841 client_context.set_ciphers("ALL")
2842
Christian Heimesf6c6b582021-03-18 23:06:50 +01002843 seclevel_workaround(server_context, client_context)
2844
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002845 for ctx in (client_context, server_context):
2846 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002847 ctx.load_cert_chain(SIGNED_CERTFILE)
2848 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002849 try:
2850 stats = server_params_test(client_context, server_context,
2851 chatty=False, connectionchatty=False)
2852 # Protocol mismatch can result in either an SSLError, or a
2853 # "Connection reset by peer" error.
2854 except ssl.SSLError:
2855 if expect_success:
2856 raise
2857 except OSError as e:
2858 if expect_success or e.errno != errno.ECONNRESET:
2859 raise
2860 else:
2861 if not expect_success:
2862 raise AssertionError(
2863 "Client protocol %s succeeded with server protocol %s!"
2864 % (ssl.get_protocol_name(client_protocol),
2865 ssl.get_protocol_name(server_protocol)))
2866 elif (expect_success is not True
2867 and expect_success != stats['version']):
2868 raise AssertionError("version mismatch: expected %r, got %r"
2869 % (expect_success, stats['version']))
2870
2871
2872class ThreadedTests(unittest.TestCase):
2873
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002874 def test_echo(self):
2875 """Basic test of an SSL client connecting to a server"""
2876 if support.verbose:
2877 sys.stdout.write("\n")
2878 for protocol in PROTOCOLS:
2879 if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
2880 continue
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02002881 if not has_tls_protocol(protocol):
2882 continue
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002883 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2884 context = ssl.SSLContext(protocol)
2885 context.load_cert_chain(CERTFILE)
Christian Heimesf6c6b582021-03-18 23:06:50 +01002886 seclevel_workaround(context)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002887 server_params_test(context, context,
2888 chatty=True, connectionchatty=True)
2889
Christian Heimesa170fa12017-09-15 20:27:30 +02002890 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002891
2892 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2893 server_params_test(client_context=client_context,
2894 server_context=server_context,
2895 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002896 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002897
2898 client_context.check_hostname = False
2899 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2900 with self.assertRaises(ssl.SSLError) as e:
2901 server_params_test(client_context=server_context,
2902 server_context=client_context,
2903 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002904 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002905 self.assertIn('called a function you should not call',
2906 str(e.exception))
2907
2908 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2909 with self.assertRaises(ssl.SSLError) as e:
2910 server_params_test(client_context=server_context,
2911 server_context=server_context,
2912 chatty=True, connectionchatty=True)
2913 self.assertIn('called a function you should not call',
2914 str(e.exception))
2915
2916 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2917 with self.assertRaises(ssl.SSLError) as e:
2918 server_params_test(client_context=server_context,
2919 server_context=client_context,
2920 chatty=True, connectionchatty=True)
2921 self.assertIn('called a function you should not call',
2922 str(e.exception))
2923
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002924 def test_getpeercert(self):
2925 if support.verbose:
2926 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002927
2928 client_context, server_context, hostname = testing_context()
2929 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002930 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002931 with client_context.wrap_socket(socket.socket(),
2932 do_handshake_on_connect=False,
2933 server_hostname=hostname) as s:
2934 s.connect((HOST, server.port))
2935 # getpeercert() raise ValueError while the handshake isn't
2936 # done.
2937 with self.assertRaises(ValueError):
2938 s.getpeercert()
2939 s.do_handshake()
2940 cert = s.getpeercert()
2941 self.assertTrue(cert, "Can't get peer certificate.")
2942 cipher = s.cipher()
2943 if support.verbose:
2944 sys.stdout.write(pprint.pformat(cert) + '\n')
2945 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2946 if 'subject' not in cert:
2947 self.fail("No subject field in certificate: %s." %
2948 pprint.pformat(cert))
2949 if ((('organizationName', 'Python Software Foundation'),)
2950 not in cert['subject']):
2951 self.fail(
2952 "Missing or invalid 'organizationName' field in certificate subject; "
2953 "should be 'Python Software Foundation'.")
2954 self.assertIn('notBefore', cert)
2955 self.assertIn('notAfter', cert)
2956 before = ssl.cert_time_to_seconds(cert['notBefore'])
2957 after = ssl.cert_time_to_seconds(cert['notAfter'])
2958 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002959
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002960 def test_crl_check(self):
2961 if support.verbose:
2962 sys.stdout.write("\n")
2963
Christian Heimesa170fa12017-09-15 20:27:30 +02002964 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002965
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002966 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002967 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002968
2969 # VERIFY_DEFAULT should pass
2970 server = ThreadedEchoServer(context=server_context, chatty=True)
2971 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002972 with client_context.wrap_socket(socket.socket(),
2973 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002974 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002975 cert = s.getpeercert()
2976 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002977
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002978 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002979 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002980
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002981 server = ThreadedEchoServer(context=server_context, chatty=True)
2982 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002983 with client_context.wrap_socket(socket.socket(),
2984 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002985 with self.assertRaisesRegex(ssl.SSLError,
2986 "certificate verify failed"):
2987 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002988
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002989 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002990 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002991
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002992 server = ThreadedEchoServer(context=server_context, chatty=True)
2993 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002994 with client_context.wrap_socket(socket.socket(),
2995 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002996 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002997 cert = s.getpeercert()
2998 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002999
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003000 def test_check_hostname(self):
3001 if support.verbose:
3002 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02003003
Christian Heimesa170fa12017-09-15 20:27:30 +02003004 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003005
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003006 # correct hostname should verify
3007 server = ThreadedEchoServer(context=server_context, chatty=True)
3008 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003009 with client_context.wrap_socket(socket.socket(),
3010 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003011 s.connect((HOST, server.port))
3012 cert = s.getpeercert()
3013 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003014
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003015 # incorrect hostname should raise an exception
3016 server = ThreadedEchoServer(context=server_context, chatty=True)
3017 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003018 with client_context.wrap_socket(socket.socket(),
3019 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01003020 with self.assertRaisesRegex(
3021 ssl.CertificateError,
3022 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003023 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003024
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003025 # missing server_hostname arg should cause an exception, too
3026 server = ThreadedEchoServer(context=server_context, chatty=True)
3027 with server:
3028 with socket.socket() as s:
3029 with self.assertRaisesRegex(ValueError,
3030 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02003031 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003032
Christian Heimesb467d9a2021-04-17 10:07:19 +02003033 @unittest.skipUnless(
3034 ssl.HAS_NEVER_CHECK_COMMON_NAME, "test requires hostname_checks_common_name"
3035 )
3036 def test_hostname_checks_common_name(self):
3037 client_context, server_context, hostname = testing_context()
3038 assert client_context.hostname_checks_common_name
3039 client_context.hostname_checks_common_name = False
3040
3041 # default cert has a SAN
3042 server = ThreadedEchoServer(context=server_context, chatty=True)
3043 with server:
3044 with client_context.wrap_socket(socket.socket(),
3045 server_hostname=hostname) as s:
3046 s.connect((HOST, server.port))
3047
3048 client_context, server_context, hostname = testing_context(NOSANFILE)
3049 client_context.hostname_checks_common_name = False
3050 server = ThreadedEchoServer(context=server_context, chatty=True)
3051 with server:
3052 with client_context.wrap_socket(socket.socket(),
3053 server_hostname=hostname) as s:
3054 with self.assertRaises(ssl.SSLCertVerificationError):
3055 s.connect((HOST, server.port))
3056
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003057 def test_ecc_cert(self):
3058 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3059 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003060 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003061 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3062
3063 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3064 # load ECC cert
3065 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3066
3067 # correct hostname should verify
3068 server = ThreadedEchoServer(context=server_context, chatty=True)
3069 with server:
3070 with client_context.wrap_socket(socket.socket(),
3071 server_hostname=hostname) as s:
3072 s.connect((HOST, server.port))
3073 cert = s.getpeercert()
3074 self.assertTrue(cert, "Can't get peer certificate.")
3075 cipher = s.cipher()[0].split('-')
3076 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3077
3078 def test_dual_rsa_ecc(self):
3079 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3080 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003081 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3082 # algorithms.
3083 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003084 # only ECDSA certs
3085 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3086 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3087
3088 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3089 # load ECC and RSA key/cert pairs
3090 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3091 server_context.load_cert_chain(SIGNED_CERTFILE)
3092
3093 # correct hostname should verify
3094 server = ThreadedEchoServer(context=server_context, chatty=True)
3095 with server:
3096 with client_context.wrap_socket(socket.socket(),
3097 server_hostname=hostname) as s:
3098 s.connect((HOST, server.port))
3099 cert = s.getpeercert()
3100 self.assertTrue(cert, "Can't get peer certificate.")
3101 cipher = s.cipher()[0].split('-')
3102 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3103
Christian Heimes66e57422018-01-29 14:25:13 +01003104 def test_check_hostname_idn(self):
3105 if support.verbose:
3106 sys.stdout.write("\n")
3107
Christian Heimes11a14932018-02-24 02:35:08 +01003108 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003109 server_context.load_cert_chain(IDNSANSFILE)
3110
Christian Heimes11a14932018-02-24 02:35:08 +01003111 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003112 context.verify_mode = ssl.CERT_REQUIRED
3113 context.check_hostname = True
3114 context.load_verify_locations(SIGNING_CA)
3115
3116 # correct hostname should verify, when specified in several
3117 # different ways
3118 idn_hostnames = [
3119 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003120 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003121 ('xn--knig-5qa.idn.pythontest.net',
3122 'xn--knig-5qa.idn.pythontest.net'),
3123 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003124 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003125
3126 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003127 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003128 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3129 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3130 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003131 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3132
3133 # ('königsgäßchen.idna2008.pythontest.net',
3134 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3135 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3136 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3137 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3138 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3139
Christian Heimes66e57422018-01-29 14:25:13 +01003140 ]
3141 for server_hostname, expected_hostname in idn_hostnames:
3142 server = ThreadedEchoServer(context=server_context, chatty=True)
3143 with server:
3144 with context.wrap_socket(socket.socket(),
3145 server_hostname=server_hostname) as s:
3146 self.assertEqual(s.server_hostname, expected_hostname)
3147 s.connect((HOST, server.port))
3148 cert = s.getpeercert()
3149 self.assertEqual(s.server_hostname, expected_hostname)
3150 self.assertTrue(cert, "Can't get peer certificate.")
3151
Christian Heimes66e57422018-01-29 14:25:13 +01003152 # incorrect hostname should raise an exception
3153 server = ThreadedEchoServer(context=server_context, chatty=True)
3154 with server:
3155 with context.wrap_socket(socket.socket(),
3156 server_hostname="python.example.org") as s:
3157 with self.assertRaises(ssl.CertificateError):
3158 s.connect((HOST, server.port))
3159
Christian Heimes529525f2018-05-23 22:24:45 +02003160 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003161 """Connecting when the server rejects the client's certificate
3162
3163 Launch a server with CERT_REQUIRED, and check that trying to
3164 connect to it with a wrong client certificate fails.
3165 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003166 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003167 # load client cert that is not signed by trusted CA
3168 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003169 # require TLS client authentication
3170 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003171 # TLS 1.3 has different handshake
3172 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003173
3174 server = ThreadedEchoServer(
3175 context=server_context, chatty=True, connectionchatty=True,
3176 )
3177
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003178 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003179 client_context.wrap_socket(socket.socket(),
3180 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003181 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003182 # Expect either an SSL error about the server rejecting
3183 # the connection, or a low-level connection reset (which
3184 # sometimes happens on Windows)
3185 s.connect((HOST, server.port))
3186 except ssl.SSLError as e:
3187 if support.verbose:
3188 sys.stdout.write("\nSSLError is %r\n" % e)
3189 except OSError as e:
3190 if e.errno != errno.ECONNRESET:
3191 raise
3192 if support.verbose:
3193 sys.stdout.write("\nsocket.error is %r\n" % e)
3194 else:
3195 self.fail("Use of invalid cert should have failed!")
3196
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003197 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003198 def test_wrong_cert_tls13(self):
3199 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003200 # load client cert that is not signed by trusted CA
3201 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003202 server_context.verify_mode = ssl.CERT_REQUIRED
3203 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3204 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3205
3206 server = ThreadedEchoServer(
3207 context=server_context, chatty=True, connectionchatty=True,
3208 )
3209 with server, \
3210 client_context.wrap_socket(socket.socket(),
3211 server_hostname=hostname) as s:
3212 # TLS 1.3 perform client cert exchange after handshake
3213 s.connect((HOST, server.port))
3214 try:
3215 s.write(b'data')
3216 s.read(4)
3217 except ssl.SSLError as e:
3218 if support.verbose:
3219 sys.stdout.write("\nSSLError is %r\n" % e)
3220 except OSError as e:
3221 if e.errno != errno.ECONNRESET:
3222 raise
3223 if support.verbose:
3224 sys.stdout.write("\nsocket.error is %r\n" % e)
3225 else:
3226 self.fail("Use of invalid cert should have failed!")
3227
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003228 def test_rude_shutdown(self):
3229 """A brutal shutdown of an SSL server should raise an OSError
3230 in the client when attempting handshake.
3231 """
3232 listener_ready = threading.Event()
3233 listener_gone = threading.Event()
3234
3235 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003236 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003237
3238 # `listener` runs in a thread. It sits in an accept() until
3239 # the main thread connects. Then it rudely closes the socket,
3240 # and sets Event `listener_gone` to let the main thread know
3241 # the socket is gone.
3242 def listener():
3243 s.listen()
3244 listener_ready.set()
3245 newsock, addr = s.accept()
3246 newsock.close()
3247 s.close()
3248 listener_gone.set()
3249
3250 def connector():
3251 listener_ready.wait()
3252 with socket.socket() as c:
3253 c.connect((HOST, port))
3254 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003255 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003256 ssl_sock = test_wrap_socket(c)
3257 except OSError:
3258 pass
3259 else:
3260 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003261
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003262 t = threading.Thread(target=listener)
3263 t.start()
3264 try:
3265 connector()
3266 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003267 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003268
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003269 def test_ssl_cert_verify_error(self):
3270 if support.verbose:
3271 sys.stdout.write("\n")
3272
3273 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3274 server_context.load_cert_chain(SIGNED_CERTFILE)
3275
3276 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3277
3278 server = ThreadedEchoServer(context=server_context, chatty=True)
3279 with server:
3280 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003281 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003282 try:
3283 s.connect((HOST, server.port))
3284 except ssl.SSLError as e:
3285 msg = 'unable to get local issuer certificate'
3286 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3287 self.assertEqual(e.verify_code, 20)
3288 self.assertEqual(e.verify_message, msg)
3289 self.assertIn(msg, repr(e))
3290 self.assertIn('certificate verify failed', repr(e))
3291
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003292 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003293 def test_protocol_sslv2(self):
3294 """Connecting to an SSLv2 server with various client options"""
3295 if support.verbose:
3296 sys.stdout.write("\n")
3297 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3298 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3299 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003300 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003301 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003302 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3303 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3304 # SSLv23 client with specific SSL options
3305 if no_sslv2_implies_sslv3_hello():
3306 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003307 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003308 client_options=ssl.OP_NO_SSLv2)
Christian Heimesa170fa12017-09-15 20:27:30 +02003309 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003310 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003311 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003312 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003313
Christian Heimesa170fa12017-09-15 20:27:30 +02003314 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003315 """Connecting to an SSLv23 server with various client options"""
3316 if support.verbose:
3317 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003318 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003319 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003320 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003321 except OSError as x:
3322 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3323 if support.verbose:
3324 sys.stdout.write(
3325 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3326 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003327 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003328 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3329 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003330 if has_tls_version('TLSv1'):
3331 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003332
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003333 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003334 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3335 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003336 if has_tls_version('TLSv1'):
3337 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003338
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003339 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003340 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3341 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003342 if has_tls_version('TLSv1'):
3343 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003344
3345 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003346 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003347 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003348 server_options=ssl.OP_NO_SSLv3)
3349 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003350 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003351 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003352 if has_tls_version('TLSv1'):
3353 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3354 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003355
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003356 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003357 def test_protocol_sslv3(self):
3358 """Connecting to an SSLv3 server with various client options"""
3359 if support.verbose:
3360 sys.stdout.write("\n")
3361 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3362 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3363 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003364 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003365 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003366 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003367 client_options=ssl.OP_NO_SSLv3)
3368 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3369 if no_sslv2_implies_sslv3_hello():
3370 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003371 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003372 False, client_options=ssl.OP_NO_SSLv2)
3373
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003374 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003375 def test_protocol_tlsv1(self):
3376 """Connecting to a TLSv1 server with various client options"""
3377 if support.verbose:
3378 sys.stdout.write("\n")
3379 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3380 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3381 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003382 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003383 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003384 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003385 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003386 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003387 client_options=ssl.OP_NO_TLSv1)
3388
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003389 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003390 def test_protocol_tlsv1_1(self):
3391 """Connecting to a TLSv1.1 server with various client options.
3392 Testing against older TLS versions."""
3393 if support.verbose:
3394 sys.stdout.write("\n")
3395 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003396 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003397 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003398 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003399 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003400 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003401 client_options=ssl.OP_NO_TLSv1_1)
3402
Christian Heimesa170fa12017-09-15 20:27:30 +02003403 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003404 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3405 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003406
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003407 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003408 def test_protocol_tlsv1_2(self):
3409 """Connecting to a TLSv1.2 server with various client options.
3410 Testing against older TLS versions."""
3411 if support.verbose:
3412 sys.stdout.write("\n")
3413 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3414 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3415 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
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_2, 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_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003420 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003421 client_options=ssl.OP_NO_TLSv1_2)
3422
Christian Heimesa170fa12017-09-15 20:27:30 +02003423 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003424 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3425 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3426 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3427 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3428
3429 def test_starttls(self):
3430 """Switching from clear text to encrypted and back again."""
3431 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3432
3433 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003434 starttls_server=True,
3435 chatty=True,
3436 connectionchatty=True)
3437 wrapped = False
3438 with server:
3439 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003440 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003441 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003442 if support.verbose:
3443 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003444 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003445 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003446 sys.stdout.write(
3447 " client: sending %r...\n" % indata)
3448 if wrapped:
3449 conn.write(indata)
3450 outdata = conn.read()
3451 else:
3452 s.send(indata)
3453 outdata = s.recv(1024)
3454 msg = outdata.strip().lower()
3455 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3456 # STARTTLS ok, switch to secure mode
3457 if support.verbose:
3458 sys.stdout.write(
3459 " client: read %r from server, starting TLS...\n"
3460 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003461 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003462 wrapped = True
3463 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3464 # ENDTLS ok, switch back to clear text
3465 if support.verbose:
3466 sys.stdout.write(
3467 " client: read %r from server, ending TLS...\n"
3468 % msg)
3469 s = conn.unwrap()
3470 wrapped = False
3471 else:
3472 if support.verbose:
3473 sys.stdout.write(
3474 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003475 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003476 sys.stdout.write(" client: closing connection.\n")
3477 if wrapped:
3478 conn.write(b"over\n")
3479 else:
3480 s.send(b"over\n")
3481 if wrapped:
3482 conn.close()
3483 else:
3484 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003485
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003486 def test_socketserver(self):
3487 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003488 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003489 # try to connect
3490 if support.verbose:
3491 sys.stdout.write('\n')
3492 with open(CERTFILE, 'rb') as f:
3493 d1 = f.read()
3494 d2 = ''
3495 # now fetch the same data from the HTTPS server
3496 url = 'https://localhost:%d/%s' % (
3497 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003498 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003499 f = urllib.request.urlopen(url, context=context)
3500 try:
3501 dlen = f.info().get("content-length")
3502 if dlen and (int(dlen) > 0):
3503 d2 = f.read(int(dlen))
3504 if support.verbose:
3505 sys.stdout.write(
3506 " client: read %d bytes from remote server '%s'\n"
3507 % (len(d2), server))
3508 finally:
3509 f.close()
3510 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003511
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003512 def test_asyncore_server(self):
3513 """Check the example asyncore integration."""
3514 if support.verbose:
3515 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003516
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003517 indata = b"FOO\n"
3518 server = AsyncoreEchoServer(CERTFILE)
3519 with server:
3520 s = test_wrap_socket(socket.socket())
3521 s.connect(('127.0.0.1', server.port))
3522 if support.verbose:
3523 sys.stdout.write(
3524 " client: sending %r...\n" % indata)
3525 s.write(indata)
3526 outdata = s.read()
3527 if support.verbose:
3528 sys.stdout.write(" client: read %r\n" % outdata)
3529 if outdata != indata.lower():
3530 self.fail(
3531 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3532 % (outdata[:20], len(outdata),
3533 indata[:20].lower(), len(indata)))
3534 s.write(b"over\n")
3535 if support.verbose:
3536 sys.stdout.write(" client: closing connection.\n")
3537 s.close()
3538 if support.verbose:
3539 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003540
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003541 def test_recv_send(self):
3542 """Test recv(), send() and friends."""
3543 if support.verbose:
3544 sys.stdout.write("\n")
3545
3546 server = ThreadedEchoServer(CERTFILE,
3547 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003548 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003549 cacerts=CERTFILE,
3550 chatty=True,
3551 connectionchatty=False)
3552 with server:
3553 s = test_wrap_socket(socket.socket(),
3554 server_side=False,
3555 certfile=CERTFILE,
3556 ca_certs=CERTFILE,
3557 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003558 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003559 s.connect((HOST, server.port))
3560 # helper methods for standardising recv* method signatures
3561 def _recv_into():
3562 b = bytearray(b"\0"*100)
3563 count = s.recv_into(b)
3564 return b[:count]
3565
3566 def _recvfrom_into():
3567 b = bytearray(b"\0"*100)
3568 count, addr = s.recvfrom_into(b)
3569 return b[:count]
3570
3571 # (name, method, expect success?, *args, return value func)
3572 send_methods = [
3573 ('send', s.send, True, [], len),
3574 ('sendto', s.sendto, False, ["some.address"], len),
3575 ('sendall', s.sendall, True, [], lambda x: None),
3576 ]
3577 # (name, method, whether to expect success, *args)
3578 recv_methods = [
3579 ('recv', s.recv, True, []),
3580 ('recvfrom', s.recvfrom, False, ["some.address"]),
3581 ('recv_into', _recv_into, True, []),
3582 ('recvfrom_into', _recvfrom_into, False, []),
3583 ]
3584 data_prefix = "PREFIX_"
3585
3586 for (meth_name, send_meth, expect_success, args,
3587 ret_val_meth) in send_methods:
3588 indata = (data_prefix + meth_name).encode('ascii')
3589 try:
3590 ret = send_meth(indata, *args)
3591 msg = "sending with {}".format(meth_name)
3592 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3593 outdata = s.read()
3594 if outdata != indata.lower():
3595 self.fail(
3596 "While sending with <<{name:s}>> bad data "
3597 "<<{outdata:r}>> ({nout:d}) received; "
3598 "expected <<{indata:r}>> ({nin:d})\n".format(
3599 name=meth_name, outdata=outdata[:20],
3600 nout=len(outdata),
3601 indata=indata[:20], nin=len(indata)
3602 )
3603 )
3604 except ValueError as e:
3605 if expect_success:
3606 self.fail(
3607 "Failed to send with method <<{name:s}>>; "
3608 "expected to succeed.\n".format(name=meth_name)
3609 )
3610 if not str(e).startswith(meth_name):
3611 self.fail(
3612 "Method <<{name:s}>> failed with unexpected "
3613 "exception message: {exp:s}\n".format(
3614 name=meth_name, exp=e
3615 )
3616 )
3617
3618 for meth_name, recv_meth, expect_success, args in recv_methods:
3619 indata = (data_prefix + meth_name).encode('ascii')
3620 try:
3621 s.send(indata)
3622 outdata = recv_meth(*args)
3623 if outdata != indata.lower():
3624 self.fail(
3625 "While receiving with <<{name:s}>> bad data "
3626 "<<{outdata:r}>> ({nout:d}) received; "
3627 "expected <<{indata:r}>> ({nin:d})\n".format(
3628 name=meth_name, outdata=outdata[:20],
3629 nout=len(outdata),
3630 indata=indata[:20], nin=len(indata)
3631 )
3632 )
3633 except ValueError as e:
3634 if expect_success:
3635 self.fail(
3636 "Failed to receive with method <<{name:s}>>; "
3637 "expected to succeed.\n".format(name=meth_name)
3638 )
3639 if not str(e).startswith(meth_name):
3640 self.fail(
3641 "Method <<{name:s}>> failed with unexpected "
3642 "exception message: {exp:s}\n".format(
3643 name=meth_name, exp=e
3644 )
3645 )
3646 # consume data
3647 s.read()
3648
3649 # read(-1, buffer) is supported, even though read(-1) is not
3650 data = b"data"
3651 s.send(data)
3652 buffer = bytearray(len(data))
3653 self.assertEqual(s.read(-1, buffer), len(data))
3654 self.assertEqual(buffer, data)
3655
Christian Heimes888bbdc2017-09-07 14:18:21 -07003656 # sendall accepts bytes-like objects
3657 if ctypes is not None:
3658 ubyte = ctypes.c_ubyte * len(data)
3659 byteslike = ubyte.from_buffer_copy(data)
3660 s.sendall(byteslike)
3661 self.assertEqual(s.read(), data)
3662
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003663 # Make sure sendmsg et al are disallowed to avoid
3664 # inadvertent disclosure of data and/or corruption
3665 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003666 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003667 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3668 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3669 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003670 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003671 s.write(b"over\n")
3672
3673 self.assertRaises(ValueError, s.recv, -1)
3674 self.assertRaises(ValueError, s.read, -1)
3675
3676 s.close()
3677
3678 def test_recv_zero(self):
3679 server = ThreadedEchoServer(CERTFILE)
3680 server.__enter__()
3681 self.addCleanup(server.__exit__, None, None)
3682 s = socket.create_connection((HOST, server.port))
3683 self.addCleanup(s.close)
3684 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3685 self.addCleanup(s.close)
3686
3687 # recv/read(0) should return no data
3688 s.send(b"data")
3689 self.assertEqual(s.recv(0), b"")
3690 self.assertEqual(s.read(0), b"")
3691 self.assertEqual(s.read(), b"data")
3692
3693 # Should not block if the other end sends no data
3694 s.setblocking(False)
3695 self.assertEqual(s.recv(0), b"")
3696 self.assertEqual(s.recv_into(bytearray()), 0)
3697
3698 def test_nonblocking_send(self):
3699 server = ThreadedEchoServer(CERTFILE,
3700 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003701 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003702 cacerts=CERTFILE,
3703 chatty=True,
3704 connectionchatty=False)
3705 with server:
3706 s = test_wrap_socket(socket.socket(),
3707 server_side=False,
3708 certfile=CERTFILE,
3709 ca_certs=CERTFILE,
3710 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003711 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003712 s.connect((HOST, server.port))
3713 s.setblocking(False)
3714
3715 # If we keep sending data, at some point the buffers
3716 # will be full and the call will block
3717 buf = bytearray(8192)
3718 def fill_buffer():
3719 while True:
3720 s.send(buf)
3721 self.assertRaises((ssl.SSLWantWriteError,
3722 ssl.SSLWantReadError), fill_buffer)
3723
3724 # Now read all the output and discard it
3725 s.setblocking(True)
3726 s.close()
3727
3728 def test_handshake_timeout(self):
3729 # Issue #5103: SSL handshake must respect the socket timeout
3730 server = socket.socket(socket.AF_INET)
3731 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003732 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003733 started = threading.Event()
3734 finish = False
3735
3736 def serve():
3737 server.listen()
3738 started.set()
3739 conns = []
3740 while not finish:
3741 r, w, e = select.select([server], [], [], 0.1)
3742 if server in r:
3743 # Let the socket hang around rather than having
3744 # it closed by garbage collection.
3745 conns.append(server.accept()[0])
3746 for sock in conns:
3747 sock.close()
3748
3749 t = threading.Thread(target=serve)
3750 t.start()
3751 started.wait()
3752
3753 try:
3754 try:
3755 c = socket.socket(socket.AF_INET)
3756 c.settimeout(0.2)
3757 c.connect((host, port))
3758 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003759 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003760 test_wrap_socket, c)
3761 finally:
3762 c.close()
3763 try:
3764 c = socket.socket(socket.AF_INET)
3765 c = test_wrap_socket(c)
3766 c.settimeout(0.2)
3767 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003768 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003769 c.connect, (host, port))
3770 finally:
3771 c.close()
3772 finally:
3773 finish = True
3774 t.join()
3775 server.close()
3776
3777 def test_server_accept(self):
3778 # Issue #16357: accept() on a SSLSocket created through
3779 # SSLContext.wrap_socket().
Christian Heimesa170fa12017-09-15 20:27:30 +02003780 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003781 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003782 context.load_verify_locations(SIGNING_CA)
3783 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003784 server = socket.socket(socket.AF_INET)
3785 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003786 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003787 server = context.wrap_socket(server, server_side=True)
3788 self.assertTrue(server.server_side)
3789
3790 evt = threading.Event()
3791 remote = None
3792 peer = None
3793 def serve():
3794 nonlocal remote, peer
3795 server.listen()
3796 # Block on the accept and wait on the connection to close.
3797 evt.set()
3798 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003799 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003800
3801 t = threading.Thread(target=serve)
3802 t.start()
3803 # Client wait until server setup and perform a connect.
3804 evt.wait()
3805 client = context.wrap_socket(socket.socket())
3806 client.connect((host, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003807 client.send(b'data')
3808 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003809 client_addr = client.getsockname()
3810 client.close()
3811 t.join()
3812 remote.close()
3813 server.close()
3814 # Sanity checks.
3815 self.assertIsInstance(remote, ssl.SSLSocket)
3816 self.assertEqual(peer, client_addr)
3817
3818 def test_getpeercert_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003819 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003820 with context.wrap_socket(socket.socket()) as sock:
3821 with self.assertRaises(OSError) as cm:
3822 sock.getpeercert()
3823 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3824
3825 def test_do_handshake_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003826 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003827 with context.wrap_socket(socket.socket()) as sock:
3828 with self.assertRaises(OSError) as cm:
3829 sock.do_handshake()
3830 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3831
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003832 def test_no_shared_ciphers(self):
3833 client_context, server_context, hostname = testing_context()
3834 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3835 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003836 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003837 client_context.set_ciphers("AES128")
3838 server_context.set_ciphers("AES256")
3839 with ThreadedEchoServer(context=server_context) as server:
3840 with client_context.wrap_socket(socket.socket(),
3841 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003842 with self.assertRaises(OSError):
3843 s.connect((HOST, server.port))
3844 self.assertIn("no shared cipher", server.conn_errors[0])
3845
3846 def test_version_basic(self):
3847 """
3848 Basic tests for SSLSocket.version().
3849 More tests are done in the test_protocol_*() methods.
3850 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003851 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3852 context.check_hostname = False
3853 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003854 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003855 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003856 chatty=False) as server:
3857 with context.wrap_socket(socket.socket()) as s:
3858 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003859 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003860 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003861 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003862 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003863 self.assertIs(s.version(), None)
3864
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003865 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003866 def test_tls1_3(self):
3867 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
3868 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003869 context.options |= (
3870 ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2
3871 )
3872 with ThreadedEchoServer(context=context) as server:
3873 with context.wrap_socket(socket.socket()) as s:
3874 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003875 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003876 'TLS_AES_256_GCM_SHA384',
3877 'TLS_CHACHA20_POLY1305_SHA256',
3878 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003879 })
3880 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003881
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003882 @requires_minimum_version
3883 @requires_tls_version('TLSv1_2')
3884 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003885 client_context, server_context, hostname = testing_context()
3886 # client TLSv1.0 to 1.2
3887 client_context.minimum_version = ssl.TLSVersion.TLSv1
3888 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3889 # server only TLSv1.2
3890 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3891 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3892
3893 with ThreadedEchoServer(context=server_context) as server:
3894 with client_context.wrap_socket(socket.socket(),
3895 server_hostname=hostname) as s:
3896 s.connect((HOST, server.port))
3897 self.assertEqual(s.version(), 'TLSv1.2')
3898
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003899 @requires_minimum_version
3900 @requires_tls_version('TLSv1_1')
3901 def test_min_max_version_tlsv1_1(self):
3902 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003903 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003904 client_context.minimum_version = ssl.TLSVersion.TLSv1
3905 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003906 server_context.minimum_version = ssl.TLSVersion.TLSv1
3907 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003908 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003909
3910 with ThreadedEchoServer(context=server_context) as server:
3911 with client_context.wrap_socket(socket.socket(),
3912 server_hostname=hostname) as s:
3913 s.connect((HOST, server.port))
3914 self.assertEqual(s.version(), 'TLSv1.1')
3915
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003916 @requires_minimum_version
3917 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003918 @requires_tls_version('TLSv1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003919 def test_min_max_version_mismatch(self):
3920 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003921 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003922 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003923 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003924 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003925 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003926 seclevel_workaround(client_context, server_context)
3927
Christian Heimes698dde12018-02-27 11:54:43 +01003928 with ThreadedEchoServer(context=server_context) as server:
3929 with client_context.wrap_socket(socket.socket(),
3930 server_hostname=hostname) as s:
3931 with self.assertRaises(ssl.SSLError) as e:
3932 s.connect((HOST, server.port))
3933 self.assertIn("alert", str(e.exception))
3934
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003935 @requires_minimum_version
3936 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003937 def test_min_max_version_sslv3(self):
3938 client_context, server_context, hostname = testing_context()
3939 server_context.minimum_version = ssl.TLSVersion.SSLv3
3940 client_context.minimum_version = ssl.TLSVersion.SSLv3
3941 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003942 seclevel_workaround(client_context, server_context)
3943
Christian Heimes698dde12018-02-27 11:54:43 +01003944 with ThreadedEchoServer(context=server_context) as server:
3945 with client_context.wrap_socket(socket.socket(),
3946 server_hostname=hostname) as s:
3947 s.connect((HOST, server.port))
3948 self.assertEqual(s.version(), 'SSLv3')
3949
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003950 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3951 def test_default_ecdh_curve(self):
3952 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3953 # should be enabled by default on SSL contexts.
Christian Heimesa170fa12017-09-15 20:27:30 +02003954 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003955 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003956 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3957 # cipher name.
3958 context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003959 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3960 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3961 # our default cipher list should prefer ECDH-based ciphers
3962 # automatically.
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003963 with ThreadedEchoServer(context=context) as server:
3964 with context.wrap_socket(socket.socket()) as s:
3965 s.connect((HOST, server.port))
3966 self.assertIn("ECDH", s.cipher()[0])
3967
3968 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3969 "'tls-unique' channel binding not available")
3970 def test_tls_unique_channel_binding(self):
3971 """Test tls-unique channel binding."""
3972 if support.verbose:
3973 sys.stdout.write("\n")
3974
Christian Heimes05d9fe32018-02-27 08:55:39 +01003975 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003976
3977 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003978 chatty=True,
3979 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003980
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003981 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003982 with client_context.wrap_socket(
3983 socket.socket(),
3984 server_hostname=hostname) as s:
3985 s.connect((HOST, server.port))
3986 # get the data
3987 cb_data = s.get_channel_binding("tls-unique")
3988 if support.verbose:
3989 sys.stdout.write(
3990 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003991
Christian Heimes05d9fe32018-02-27 08:55:39 +01003992 # check if it is sane
3993 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003994 if s.version() == 'TLSv1.3':
3995 self.assertEqual(len(cb_data), 48)
3996 else:
3997 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003998
Christian Heimes05d9fe32018-02-27 08:55:39 +01003999 # and compare with the peers version
4000 s.write(b"CB tls-unique\n")
4001 peer_data_repr = s.read().strip()
4002 self.assertEqual(peer_data_repr,
4003 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004004
4005 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01004006 with client_context.wrap_socket(
4007 socket.socket(),
4008 server_hostname=hostname) as s:
4009 s.connect((HOST, server.port))
4010 new_cb_data = s.get_channel_binding("tls-unique")
4011 if support.verbose:
4012 sys.stdout.write(
4013 "got another channel binding data: {0!r}\n".format(
4014 new_cb_data)
4015 )
4016 # is it really unique
4017 self.assertNotEqual(cb_data, new_cb_data)
4018 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02004019 if s.version() == 'TLSv1.3':
4020 self.assertEqual(len(cb_data), 48)
4021 else:
4022 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01004023 s.write(b"CB tls-unique\n")
4024 peer_data_repr = s.read().strip()
4025 self.assertEqual(peer_data_repr,
4026 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004027
4028 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004029 client_context, server_context, hostname = testing_context()
4030 stats = server_params_test(client_context, server_context,
4031 chatty=True, connectionchatty=True,
4032 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004033 if support.verbose:
4034 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
4035 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
4036
4037 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
4038 "ssl.OP_NO_COMPRESSION needed for this test")
4039 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004040 client_context, server_context, hostname = testing_context()
4041 client_context.options |= ssl.OP_NO_COMPRESSION
4042 server_context.options |= ssl.OP_NO_COMPRESSION
4043 stats = server_params_test(client_context, server_context,
4044 chatty=True, connectionchatty=True,
4045 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004046 self.assertIs(stats['compression'], None)
4047
Paul Monsonf3550692019-06-19 13:09:54 -07004048 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004049 def test_dh_params(self):
4050 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004051 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004052 # test scenario needs TLS <= 1.2
4053 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004054 server_context.load_dh_params(DHFILE)
4055 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004056 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004057 stats = server_params_test(client_context, server_context,
4058 chatty=True, connectionchatty=True,
4059 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004060 cipher = stats["cipher"][0]
4061 parts = cipher.split("-")
4062 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4063 self.fail("Non-DH cipher: " + cipher[0])
4064
Christian Heimesb7b92252018-02-25 09:49:31 +01004065 @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004066 @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
Christian Heimesb7b92252018-02-25 09:49:31 +01004067 def test_ecdh_curve(self):
4068 # server secp384r1, client auto
4069 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004070
Christian Heimesb7b92252018-02-25 09:49:31 +01004071 server_context.set_ecdh_curve("secp384r1")
4072 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4073 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4074 stats = server_params_test(client_context, server_context,
4075 chatty=True, connectionchatty=True,
4076 sni_name=hostname)
4077
4078 # server auto, client secp384r1
4079 client_context, server_context, hostname = testing_context()
4080 client_context.set_ecdh_curve("secp384r1")
4081 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4082 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4083 stats = server_params_test(client_context, server_context,
4084 chatty=True, connectionchatty=True,
4085 sni_name=hostname)
4086
4087 # server / client curve mismatch
4088 client_context, server_context, hostname = testing_context()
4089 client_context.set_ecdh_curve("prime256v1")
4090 server_context.set_ecdh_curve("secp384r1")
4091 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4092 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4093 try:
Christian Heimes39258d32021-04-17 11:36:35 +02004094 server_params_test(client_context, server_context,
4095 chatty=True, connectionchatty=True,
4096 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004097 except ssl.SSLError:
Christian Heimes39258d32021-04-17 11:36:35 +02004098 self.fail("mismatch curve did not fail")
Christian Heimesb7b92252018-02-25 09:49:31 +01004099
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004100 def test_selected_alpn_protocol(self):
4101 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004102 client_context, server_context, hostname = testing_context()
4103 stats = server_params_test(client_context, server_context,
4104 chatty=True, connectionchatty=True,
4105 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004106 self.assertIs(stats['client_alpn_protocol'], None)
4107
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004108 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4109 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004110 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004111 server_context.set_alpn_protocols(['foo', 'bar'])
4112 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004113 chatty=True, connectionchatty=True,
4114 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004115 self.assertIs(stats['client_alpn_protocol'], None)
4116
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004117 def test_alpn_protocols(self):
4118 server_protocols = ['foo', 'bar', 'milkshake']
4119 protocol_tests = [
4120 (['foo', 'bar'], 'foo'),
4121 (['bar', 'foo'], 'foo'),
4122 (['milkshake'], 'milkshake'),
4123 (['http/3.0', 'http/4.0'], None)
4124 ]
4125 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004126 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004127 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004128 client_context.set_alpn_protocols(client_protocols)
4129
4130 try:
4131 stats = server_params_test(client_context,
4132 server_context,
4133 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004134 connectionchatty=True,
4135 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004136 except ssl.SSLError as e:
4137 stats = e
4138
Christian Heimes39258d32021-04-17 11:36:35 +02004139 msg = "failed trying %s (s) and %s (c).\n" \
4140 "was expecting %s, but got %%s from the %%s" \
4141 % (str(server_protocols), str(client_protocols),
4142 str(expected))
4143 client_result = stats['client_alpn_protocol']
4144 self.assertEqual(client_result, expected,
4145 msg % (client_result, "client"))
4146 server_result = stats['server_alpn_protocols'][-1] \
4147 if len(stats['server_alpn_protocols']) else 'nothing'
4148 self.assertEqual(server_result, expected,
4149 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004150
4151 def test_selected_npn_protocol(self):
4152 # selected_npn_protocol() is None unless NPN is used
Christian Heimesa170fa12017-09-15 20:27:30 +02004153 client_context, server_context, hostname = testing_context()
4154 stats = server_params_test(client_context, server_context,
4155 chatty=True, connectionchatty=True,
4156 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004157 self.assertIs(stats['client_npn_protocol'], None)
4158
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004159 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004160 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004161
4162 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004163 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004164 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004165 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004166 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004167 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004168 client_context.load_verify_locations(SIGNING_CA)
4169 return server_context, other_context, client_context
4170
4171 def check_common_name(self, stats, name):
4172 cert = stats['peercert']
4173 self.assertIn((('commonName', name),), cert['subject'])
4174
4175 @needs_sni
4176 def test_sni_callback(self):
4177 calls = []
4178 server_context, other_context, client_context = self.sni_contexts()
4179
Christian Heimesa170fa12017-09-15 20:27:30 +02004180 client_context.check_hostname = False
4181
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004182 def servername_cb(ssl_sock, server_name, initial_context):
4183 calls.append((server_name, initial_context))
4184 if server_name is not None:
4185 ssl_sock.context = other_context
4186 server_context.set_servername_callback(servername_cb)
4187
4188 stats = server_params_test(client_context, server_context,
4189 chatty=True,
4190 sni_name='supermessage')
4191 # The hostname was fetched properly, and the certificate was
4192 # changed for the connection.
4193 self.assertEqual(calls, [("supermessage", server_context)])
4194 # CERTFILE4 was selected
4195 self.check_common_name(stats, 'fakehostname')
4196
4197 calls = []
4198 # The callback is called with server_name=None
4199 stats = server_params_test(client_context, server_context,
4200 chatty=True,
4201 sni_name=None)
4202 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004203 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004204
4205 # Check disabling the callback
4206 calls = []
4207 server_context.set_servername_callback(None)
4208
4209 stats = server_params_test(client_context, server_context,
4210 chatty=True,
4211 sni_name='notfunny')
4212 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004213 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004214 self.assertEqual(calls, [])
4215
4216 @needs_sni
4217 def test_sni_callback_alert(self):
4218 # Returning a TLS alert is reflected to the connecting client
4219 server_context, other_context, client_context = self.sni_contexts()
4220
4221 def cb_returning_alert(ssl_sock, server_name, initial_context):
4222 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4223 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004224 with self.assertRaises(ssl.SSLError) as cm:
4225 stats = server_params_test(client_context, server_context,
4226 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004227 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004228 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004229
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004230 @needs_sni
4231 def test_sni_callback_raising(self):
4232 # Raising fails the connection with a TLS handshake failure alert.
4233 server_context, other_context, client_context = self.sni_contexts()
4234
4235 def cb_raising(ssl_sock, server_name, initial_context):
4236 1/0
4237 server_context.set_servername_callback(cb_raising)
4238
Victor Stinner00253502019-06-03 03:51:43 +02004239 with support.catch_unraisable_exception() as catch:
4240 with self.assertRaises(ssl.SSLError) as cm:
4241 stats = server_params_test(client_context, server_context,
4242 chatty=False,
4243 sni_name='supermessage')
4244
4245 self.assertEqual(cm.exception.reason,
4246 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4247 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004248
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004249 @needs_sni
4250 def test_sni_callback_wrong_return_type(self):
4251 # Returning the wrong return type terminates the TLS connection
4252 # with an internal error alert.
4253 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004254
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004255 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4256 return "foo"
4257 server_context.set_servername_callback(cb_wrong_return_type)
4258
Victor Stinner00253502019-06-03 03:51:43 +02004259 with support.catch_unraisable_exception() as catch:
4260 with self.assertRaises(ssl.SSLError) as cm:
4261 stats = server_params_test(client_context, server_context,
4262 chatty=False,
4263 sni_name='supermessage')
4264
4265
4266 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4267 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004268
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004269 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004270 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004271 client_context.set_ciphers("AES128:AES256")
4272 server_context.set_ciphers("AES256")
4273 expected_algs = [
4274 "AES256", "AES-256",
4275 # TLS 1.3 ciphers are always enabled
4276 "TLS_CHACHA20", "TLS_AES",
4277 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004278
Christian Heimesa170fa12017-09-15 20:27:30 +02004279 stats = server_params_test(client_context, server_context,
4280 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004281 ciphers = stats['server_shared_ciphers'][0]
4282 self.assertGreater(len(ciphers), 0)
4283 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004284 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004285 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004286
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004287 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004288 client_context, server_context, hostname = testing_context()
4289 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004290
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004291 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004292 s = client_context.wrap_socket(socket.socket(),
4293 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004294 s.connect((HOST, server.port))
4295 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004296
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004297 self.assertRaises(ValueError, s.read, 1024)
4298 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004299
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004300 def test_sendfile(self):
4301 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004302 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004303 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004304 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesa170fa12017-09-15 20:27:30 +02004305 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004306 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01004307 context.load_verify_locations(SIGNING_CA)
4308 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004309 server = ThreadedEchoServer(context=context, chatty=False)
4310 with server:
4311 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004312 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004313 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004314 s.sendfile(file)
4315 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004316
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004317 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004318 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004319 # TODO: sessions aren't compatible with TLSv1.3 yet
4320 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004321
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004322 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004323 stats = server_params_test(client_context, server_context,
4324 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004325 session = stats['session']
4326 self.assertTrue(session.id)
4327 self.assertGreater(session.time, 0)
4328 self.assertGreater(session.timeout, 0)
4329 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004330 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004331 self.assertFalse(stats['session_reused'])
4332 sess_stat = server_context.session_stats()
4333 self.assertEqual(sess_stat['accept'], 1)
4334 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004335
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004336 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004337 stats = server_params_test(client_context, server_context,
4338 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004339 sess_stat = server_context.session_stats()
4340 self.assertEqual(sess_stat['accept'], 2)
4341 self.assertEqual(sess_stat['hits'], 1)
4342 self.assertTrue(stats['session_reused'])
4343 session2 = stats['session']
4344 self.assertEqual(session2.id, session.id)
4345 self.assertEqual(session2, session)
4346 self.assertIsNot(session2, session)
4347 self.assertGreaterEqual(session2.time, session.time)
4348 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004349
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004350 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004351 stats = server_params_test(client_context, server_context,
4352 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004353 self.assertFalse(stats['session_reused'])
4354 session3 = stats['session']
4355 self.assertNotEqual(session3.id, session.id)
4356 self.assertNotEqual(session3, session)
4357 sess_stat = server_context.session_stats()
4358 self.assertEqual(sess_stat['accept'], 3)
4359 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004360
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004361 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004362 stats = server_params_test(client_context, server_context,
4363 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004364 self.assertTrue(stats['session_reused'])
4365 session4 = stats['session']
4366 self.assertEqual(session4.id, session.id)
4367 self.assertEqual(session4, session)
4368 self.assertGreaterEqual(session4.time, session.time)
4369 self.assertGreaterEqual(session4.timeout, session.timeout)
4370 sess_stat = server_context.session_stats()
4371 self.assertEqual(sess_stat['accept'], 4)
4372 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004373
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004374 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004375 client_context, server_context, hostname = testing_context()
4376 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004377
Christian Heimes05d9fe32018-02-27 08:55:39 +01004378 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004379 client_context.options |= ssl.OP_NO_TLSv1_3
4380 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004381
Christian Heimesa170fa12017-09-15 20:27:30 +02004382 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004383 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004384 with client_context.wrap_socket(socket.socket(),
4385 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004386 # session is None before handshake
4387 self.assertEqual(s.session, None)
4388 self.assertEqual(s.session_reused, None)
4389 s.connect((HOST, server.port))
4390 session = s.session
4391 self.assertTrue(session)
4392 with self.assertRaises(TypeError) as e:
4393 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004394 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004395
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 s.connect((HOST, server.port))
4399 # cannot set session after handshake
4400 with self.assertRaises(ValueError) as e:
4401 s.session = session
4402 self.assertEqual(str(e.exception),
4403 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004404
Christian Heimesa170fa12017-09-15 20:27:30 +02004405 with client_context.wrap_socket(socket.socket(),
4406 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004407 # can set session before handshake and before the
4408 # connection was established
4409 s.session = session
4410 s.connect((HOST, server.port))
4411 self.assertEqual(s.session.id, session.id)
4412 self.assertEqual(s.session, session)
4413 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004414
Christian Heimesa170fa12017-09-15 20:27:30 +02004415 with client_context2.wrap_socket(socket.socket(),
4416 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004417 # cannot re-use session with a different SSLContext
4418 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004419 s.session = session
4420 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004421 self.assertEqual(str(e.exception),
4422 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004423
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004424
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004425@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004426class TestPostHandshakeAuth(unittest.TestCase):
4427 def test_pha_setter(self):
4428 protocols = [
4429 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
4430 ]
4431 for protocol in protocols:
4432 ctx = ssl.SSLContext(protocol)
4433 self.assertEqual(ctx.post_handshake_auth, False)
4434
4435 ctx.post_handshake_auth = True
4436 self.assertEqual(ctx.post_handshake_auth, True)
4437
4438 ctx.verify_mode = ssl.CERT_REQUIRED
4439 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4440 self.assertEqual(ctx.post_handshake_auth, True)
4441
4442 ctx.post_handshake_auth = False
4443 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4444 self.assertEqual(ctx.post_handshake_auth, False)
4445
4446 ctx.verify_mode = ssl.CERT_OPTIONAL
4447 ctx.post_handshake_auth = True
4448 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4449 self.assertEqual(ctx.post_handshake_auth, True)
4450
4451 def test_pha_required(self):
4452 client_context, server_context, hostname = testing_context()
4453 server_context.post_handshake_auth = True
4454 server_context.verify_mode = ssl.CERT_REQUIRED
4455 client_context.post_handshake_auth = True
4456 client_context.load_cert_chain(SIGNED_CERTFILE)
4457
4458 server = ThreadedEchoServer(context=server_context, chatty=False)
4459 with server:
4460 with client_context.wrap_socket(socket.socket(),
4461 server_hostname=hostname) as s:
4462 s.connect((HOST, server.port))
4463 s.write(b'HASCERT')
4464 self.assertEqual(s.recv(1024), b'FALSE\n')
4465 s.write(b'PHA')
4466 self.assertEqual(s.recv(1024), b'OK\n')
4467 s.write(b'HASCERT')
4468 self.assertEqual(s.recv(1024), b'TRUE\n')
4469 # PHA method just returns true when cert is already available
4470 s.write(b'PHA')
4471 self.assertEqual(s.recv(1024), b'OK\n')
4472 s.write(b'GETCERT')
4473 cert_text = s.recv(4096).decode('us-ascii')
4474 self.assertIn('Python Software Foundation CA', cert_text)
4475
4476 def test_pha_required_nocert(self):
4477 client_context, server_context, hostname = testing_context()
4478 server_context.post_handshake_auth = True
4479 server_context.verify_mode = ssl.CERT_REQUIRED
4480 client_context.post_handshake_auth = True
4481
Victor Stinner73ea5462019-07-09 14:33:49 +02004482 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4483 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004484 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004485 server = ThreadedEchoServer(context=server_context, chatty=False)
4486 with server:
4487 with client_context.wrap_socket(socket.socket(),
4488 server_hostname=hostname) as s:
4489 s.connect((HOST, server.port))
4490 s.write(b'PHA')
4491 # receive CertificateRequest
4492 self.assertEqual(s.recv(1024), b'OK\n')
4493 # send empty Certificate + Finish
4494 s.write(b'HASCERT')
4495 # receive alert
4496 with self.assertRaisesRegex(
4497 ssl.SSLError,
4498 'tlsv13 alert certificate required'):
4499 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004500
4501 def test_pha_optional(self):
4502 if support.verbose:
4503 sys.stdout.write("\n")
4504
4505 client_context, server_context, hostname = testing_context()
4506 server_context.post_handshake_auth = True
4507 server_context.verify_mode = ssl.CERT_REQUIRED
4508 client_context.post_handshake_auth = True
4509 client_context.load_cert_chain(SIGNED_CERTFILE)
4510
4511 # check CERT_OPTIONAL
4512 server_context.verify_mode = ssl.CERT_OPTIONAL
4513 server = ThreadedEchoServer(context=server_context, chatty=False)
4514 with server:
4515 with client_context.wrap_socket(socket.socket(),
4516 server_hostname=hostname) as s:
4517 s.connect((HOST, server.port))
4518 s.write(b'HASCERT')
4519 self.assertEqual(s.recv(1024), b'FALSE\n')
4520 s.write(b'PHA')
4521 self.assertEqual(s.recv(1024), b'OK\n')
4522 s.write(b'HASCERT')
4523 self.assertEqual(s.recv(1024), b'TRUE\n')
4524
4525 def test_pha_optional_nocert(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_OPTIONAL
4532 client_context.post_handshake_auth = True
4533
4534 server = ThreadedEchoServer(context=server_context, chatty=False)
4535 with server:
4536 with client_context.wrap_socket(socket.socket(),
4537 server_hostname=hostname) as s:
4538 s.connect((HOST, server.port))
4539 s.write(b'HASCERT')
4540 self.assertEqual(s.recv(1024), b'FALSE\n')
4541 s.write(b'PHA')
4542 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004543 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004544 s.write(b'HASCERT')
4545 self.assertEqual(s.recv(1024), b'FALSE\n')
4546
4547 def test_pha_no_pha_client(self):
4548 client_context, server_context, hostname = testing_context()
4549 server_context.post_handshake_auth = True
4550 server_context.verify_mode = ssl.CERT_REQUIRED
4551 client_context.load_cert_chain(SIGNED_CERTFILE)
4552
4553 server = ThreadedEchoServer(context=server_context, chatty=False)
4554 with server:
4555 with client_context.wrap_socket(socket.socket(),
4556 server_hostname=hostname) as s:
4557 s.connect((HOST, server.port))
4558 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4559 s.verify_client_post_handshake()
4560 s.write(b'PHA')
4561 self.assertIn(b'extension not received', s.recv(1024))
4562
4563 def test_pha_no_pha_server(self):
4564 # server doesn't have PHA enabled, cert is requested in handshake
4565 client_context, server_context, hostname = testing_context()
4566 server_context.verify_mode = ssl.CERT_REQUIRED
4567 client_context.post_handshake_auth = True
4568 client_context.load_cert_chain(SIGNED_CERTFILE)
4569
4570 server = ThreadedEchoServer(context=server_context, chatty=False)
4571 with server:
4572 with client_context.wrap_socket(socket.socket(),
4573 server_hostname=hostname) as s:
4574 s.connect((HOST, server.port))
4575 s.write(b'HASCERT')
4576 self.assertEqual(s.recv(1024), b'TRUE\n')
4577 # PHA doesn't fail if there is already a cert
4578 s.write(b'PHA')
4579 self.assertEqual(s.recv(1024), b'OK\n')
4580 s.write(b'HASCERT')
4581 self.assertEqual(s.recv(1024), b'TRUE\n')
4582
4583 def test_pha_not_tls13(self):
4584 # TLS 1.2
4585 client_context, server_context, hostname = testing_context()
4586 server_context.verify_mode = ssl.CERT_REQUIRED
4587 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4588 client_context.post_handshake_auth = True
4589 client_context.load_cert_chain(SIGNED_CERTFILE)
4590
4591 server = ThreadedEchoServer(context=server_context, chatty=False)
4592 with server:
4593 with client_context.wrap_socket(socket.socket(),
4594 server_hostname=hostname) as s:
4595 s.connect((HOST, server.port))
4596 # PHA fails for TLS != 1.3
4597 s.write(b'PHA')
4598 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4599
Christian Heimesf0f59302019-07-01 08:29:17 +02004600 def test_bpo37428_pha_cert_none(self):
4601 # verify that post_handshake_auth does not implicitly enable cert
4602 # validation.
4603 hostname = SIGNED_CERTFILE_HOSTNAME
4604 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4605 client_context.post_handshake_auth = True
4606 client_context.load_cert_chain(SIGNED_CERTFILE)
4607 # no cert validation and CA on client side
4608 client_context.check_hostname = False
4609 client_context.verify_mode = ssl.CERT_NONE
4610
4611 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4612 server_context.load_cert_chain(SIGNED_CERTFILE)
4613 server_context.load_verify_locations(SIGNING_CA)
4614 server_context.post_handshake_auth = True
4615 server_context.verify_mode = ssl.CERT_REQUIRED
4616
4617 server = ThreadedEchoServer(context=server_context, chatty=False)
4618 with server:
4619 with client_context.wrap_socket(socket.socket(),
4620 server_hostname=hostname) as s:
4621 s.connect((HOST, server.port))
4622 s.write(b'HASCERT')
4623 self.assertEqual(s.recv(1024), b'FALSE\n')
4624 s.write(b'PHA')
4625 self.assertEqual(s.recv(1024), b'OK\n')
4626 s.write(b'HASCERT')
4627 self.assertEqual(s.recv(1024), b'TRUE\n')
4628 # server cert has not been validated
4629 self.assertEqual(s.getpeercert(), {})
4630
Christian Heimes9fb051f2018-09-23 08:32:31 +02004631
Christian Heimesc7f70692019-05-31 11:44:05 +02004632HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4633requires_keylog = unittest.skipUnless(
4634 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4635
4636class TestSSLDebug(unittest.TestCase):
4637
Hai Shia7f5d932020-08-04 00:41:24 +08004638 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004639 with open(fname) as f:
4640 return len(list(f))
4641
4642 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004643 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004644 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004645 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004646 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4647 self.assertEqual(ctx.keylog_filename, None)
4648
Hai Shia7f5d932020-08-04 00:41:24 +08004649 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4650 ctx.keylog_filename = os_helper.TESTFN
4651 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4652 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004653 self.assertEqual(self.keylog_lines(), 1)
4654
4655 ctx.keylog_filename = None
4656 self.assertEqual(ctx.keylog_filename, None)
4657
4658 with self.assertRaises((IsADirectoryError, PermissionError)):
4659 # Windows raises PermissionError
4660 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004661 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004662
4663 with self.assertRaises(TypeError):
4664 ctx.keylog_filename = 1
4665
4666 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004667 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004668 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004669 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004670 client_context, server_context, hostname = testing_context()
4671
Hai Shia7f5d932020-08-04 00:41:24 +08004672 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004673 server = ThreadedEchoServer(context=server_context, chatty=False)
4674 with server:
4675 with client_context.wrap_socket(socket.socket(),
4676 server_hostname=hostname) as s:
4677 s.connect((HOST, server.port))
4678 # header, 5 lines for TLS 1.3
4679 self.assertEqual(self.keylog_lines(), 6)
4680
4681 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004682 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004683 server = ThreadedEchoServer(context=server_context, chatty=False)
4684 with server:
4685 with client_context.wrap_socket(socket.socket(),
4686 server_hostname=hostname) as s:
4687 s.connect((HOST, server.port))
4688 self.assertGreaterEqual(self.keylog_lines(), 11)
4689
Hai Shia7f5d932020-08-04 00:41:24 +08004690 client_context.keylog_filename = os_helper.TESTFN
4691 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004692 server = ThreadedEchoServer(context=server_context, chatty=False)
4693 with server:
4694 with client_context.wrap_socket(socket.socket(),
4695 server_hostname=hostname) as s:
4696 s.connect((HOST, server.port))
4697 self.assertGreaterEqual(self.keylog_lines(), 21)
4698
4699 client_context.keylog_filename = None
4700 server_context.keylog_filename = None
4701
4702 @requires_keylog
4703 @unittest.skipIf(sys.flags.ignore_environment,
4704 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004705 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004706 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004707 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004708 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004709 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4710 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004711
4712 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4713 self.assertEqual(ctx.keylog_filename, None)
4714
4715 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004716 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004717
4718 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004719 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004720
4721 def test_msg_callback(self):
4722 client_context, server_context, hostname = testing_context()
4723
4724 def msg_cb(conn, direction, version, content_type, msg_type, data):
4725 pass
4726
4727 self.assertIs(client_context._msg_callback, None)
4728 client_context._msg_callback = msg_cb
4729 self.assertIs(client_context._msg_callback, msg_cb)
4730 with self.assertRaises(TypeError):
4731 client_context._msg_callback = object()
4732
4733 def test_msg_callback_tls12(self):
4734 client_context, server_context, hostname = testing_context()
4735 client_context.options |= ssl.OP_NO_TLSv1_3
4736
4737 msg = []
4738
4739 def msg_cb(conn, direction, version, content_type, msg_type, data):
4740 self.assertIsInstance(conn, ssl.SSLSocket)
4741 self.assertIsInstance(data, bytes)
4742 self.assertIn(direction, {'read', 'write'})
4743 msg.append((direction, version, content_type, msg_type))
4744
4745 client_context._msg_callback = msg_cb
4746
4747 server = ThreadedEchoServer(context=server_context, chatty=False)
4748 with server:
4749 with client_context.wrap_socket(socket.socket(),
4750 server_hostname=hostname) as s:
4751 s.connect((HOST, server.port))
4752
Christian Heimese35d1ba2019-06-03 20:40:15 +02004753 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004754 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4755 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004756 msg
4757 )
4758 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004759 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4760 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004761 msg
4762 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004763
Christian Heimes77cde502021-03-21 16:13:09 +01004764 def test_msg_callback_deadlock_bpo43577(self):
4765 client_context, server_context, hostname = testing_context()
4766 server_context2 = testing_context()[1]
4767
4768 def msg_cb(conn, direction, version, content_type, msg_type, data):
4769 pass
4770
4771 def sni_cb(sock, servername, ctx):
4772 sock.context = server_context2
4773
4774 server_context._msg_callback = msg_cb
4775 server_context.sni_callback = sni_cb
4776
4777 server = ThreadedEchoServer(context=server_context, chatty=False)
4778 with server:
4779 with client_context.wrap_socket(socket.socket(),
4780 server_hostname=hostname) as s:
4781 s.connect((HOST, server.port))
4782 with client_context.wrap_socket(socket.socket(),
4783 server_hostname=hostname) as s:
4784 s.connect((HOST, server.port))
4785
Christian Heimesc7f70692019-05-31 11:44:05 +02004786
Thomas Woutersed03b412007-08-28 21:37:11 +00004787def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004788 if support.verbose:
4789 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004790 'Mac': platform.mac_ver,
4791 'Windows': platform.win32_ver,
4792 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004793 for name, func in plats.items():
4794 plat = func()
4795 if plat and plat[0]:
4796 plat = '%s %r' % (name, plat)
4797 break
4798 else:
4799 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004800 print("test_ssl: testing with %r %r" %
4801 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4802 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004803 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004804 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4805 try:
4806 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4807 except AttributeError:
4808 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004809
Antoine Pitrou152efa22010-05-16 18:19:27 +00004810 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004811 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004812 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004813 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004814 BADCERT, BADKEY, EMPTYCERT]:
4815 if not os.path.exists(filename):
4816 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004817
Martin Panter3840b2a2016-03-27 01:53:46 +00004818 tests = [
4819 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004820 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004821 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004822 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004823
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004824 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004825 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004826
Hai Shie80697d2020-05-28 06:10:27 +08004827 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004828 try:
4829 support.run_unittest(*tests)
4830 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004831 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004832
4833if __name__ == "__main__":
4834 test_main()