blob: bed0d413a80b3689b086546bc92eaf353e2b9ff5 [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_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0)
44IS_OPENSSL_1_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1)
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 Heimese6dac002018-08-30 07:25:49 +0200112 'notAfter': 'Jul 7 14:23:16 2028 GMT',
113 '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")
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100133
Martin Panter3d81d932016-01-14 09:36:00 +0000134REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +0000135
136EMPTYCERT = data_file("nullcert.pem")
137BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +0000138NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000139BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200140NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +0200141NULLBYTECERT = data_file("nullbytecert.pem")
Christian Heimesa37f5242019-01-15 23:47:42 +0100142TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000143
Christian Heimes88bfd0b2018-08-14 12:54:19 +0200144DHFILE = data_file("ffdh3072.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100145BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +0000146
Christian Heimes358cfd42016-09-10 22:43:48 +0200147# Not defined in all versions of OpenSSL
148OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
149OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
150OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
151OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
Christian Heimes05d9fe32018-02-27 08:55:39 +0100152OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
Christian Heimes358cfd42016-09-10 22:43:48 +0200153
Christian Heimesf6c6b582021-03-18 23:06:50 +0100154# Ubuntu has patched OpenSSL and changed behavior of security level 2
155# see https://bugs.python.org/issue41561#msg389003
156def is_ubuntu():
157 try:
158 # Assume that any references of "ubuntu" implies Ubuntu-like distro
159 # The workaround is not required for 18.04, but doesn't hurt either.
160 with open("/etc/os-release", encoding="utf-8") as f:
161 return "ubuntu" in f.read()
162 except FileNotFoundError:
163 return False
164
165if is_ubuntu():
166 def seclevel_workaround(*ctxs):
167 """"Lower security level to '1' and allow all ciphers for TLS 1.0/1"""
168 for ctx in ctxs:
169 if ctx.minimum_version <= ssl.TLSVersion.TLSv1_1:
170 ctx.set_ciphers("@SECLEVEL=1:ALL")
171else:
172 def seclevel_workaround(*ctxs):
173 pass
174
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100175
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200176def has_tls_protocol(protocol):
177 """Check if a TLS protocol is available and enabled
178
179 :param protocol: enum ssl._SSLMethod member or name
180 :return: bool
181 """
182 if isinstance(protocol, str):
183 assert protocol.startswith('PROTOCOL_')
184 protocol = getattr(ssl, protocol, None)
185 if protocol is None:
186 return False
187 if protocol in {
188 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
189 ssl.PROTOCOL_TLS_CLIENT
190 }:
191 # auto-negotiate protocols are always available
192 return True
193 name = protocol.name
194 return has_tls_version(name[len('PROTOCOL_'):])
195
196
197@functools.lru_cache
198def has_tls_version(version):
199 """Check if a TLS/SSL version is enabled
200
201 :param version: TLS version name or ssl.TLSVersion member
202 :return: bool
203 """
204 if version == "SSLv2":
205 # never supported and not even in TLSVersion enum
206 return False
207
208 if isinstance(version, str):
209 version = ssl.TLSVersion.__members__[version]
210
211 # check compile time flags like ssl.HAS_TLSv1_2
212 if not getattr(ssl, f'HAS_{version.name}'):
213 return False
214
215 # check runtime and dynamic crypto policy settings. A TLS version may
216 # be compiled in but disabled by a policy or config option.
217 ctx = ssl.SSLContext()
218 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200219 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200220 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
221 version < ctx.minimum_version
222 ):
223 return False
224 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200225 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200226 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
227 version > ctx.maximum_version
228 ):
229 return False
230
231 return True
232
233
234def requires_tls_version(version):
235 """Decorator to skip tests when a required TLS version is not available
236
237 :param version: TLS version name or ssl.TLSVersion member
238 :return:
239 """
240 def decorator(func):
241 @functools.wraps(func)
242 def wrapper(*args, **kw):
243 if not has_tls_version(version):
244 raise unittest.SkipTest(f"{version} is not available.")
245 else:
246 return func(*args, **kw)
247 return wrapper
248 return decorator
249
250
251requires_minimum_version = unittest.skipUnless(
252 hasattr(ssl.SSLContext, 'minimum_version'),
253 "required OpenSSL >= 1.1.0g"
254)
255
256
Thomas Woutersed03b412007-08-28 21:37:11 +0000257def handle_error(prefix):
258 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000259 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000260 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000261
Antoine Pitroub5218772010-05-21 09:56:06 +0000262def can_clear_options():
263 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +0200264 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +0000265
266def no_sslv2_implies_sslv3_hello():
267 # 0.9.7h or higher
268 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
269
Christian Heimes2427b502013-11-23 11:24:32 +0100270def have_verify_flags():
271 # 0.9.8 or higher
272 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
273
Christian Heimesb7b92252018-02-25 09:49:31 +0100274def _have_secp_curves():
275 if not ssl.HAS_ECDH:
276 return False
277 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
278 try:
279 ctx.set_ecdh_curve("secp384r1")
280 except ValueError:
281 return False
282 else:
283 return True
284
285
286HAVE_SECP_CURVES = _have_secp_curves()
287
288
Antoine Pitrouc695c952014-04-28 20:57:36 +0200289def utc_offset(): #NOTE: ignore issues like #1647654
290 # local time = utc time + utc offset
291 if time.daylight and time.localtime().tm_isdst > 0:
292 return -time.altzone # seconds
293 return -time.timezone
294
Christian Heimes9424bb42013-06-17 15:32:57 +0200295def asn1time(cert_time):
296 # Some versions of OpenSSL ignore seconds, see #18207
297 # 0.9.8.i
298 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
299 fmt = "%b %d %H:%M:%S %Y GMT"
300 dt = datetime.datetime.strptime(cert_time, fmt)
301 dt = dt.replace(second=0)
302 cert_time = dt.strftime(fmt)
303 # %d adds leading zero but ASN1_TIME_print() uses leading space
304 if cert_time[4] == "0":
305 cert_time = cert_time[:4] + " " + cert_time[5:]
306
307 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000308
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100309needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
310
Antoine Pitrou23df4832010-08-04 17:14:06 +0000311
Christian Heimesd0486372016-09-10 23:23:33 +0200312def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLS, *,
313 cert_reqs=ssl.CERT_NONE, ca_certs=None,
314 ciphers=None, certfile=None, keyfile=None,
315 **kwargs):
316 context = ssl.SSLContext(ssl_version)
317 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200318 if cert_reqs == ssl.CERT_NONE:
319 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200320 context.verify_mode = cert_reqs
321 if ca_certs is not None:
322 context.load_verify_locations(ca_certs)
323 if certfile is not None or keyfile is not None:
324 context.load_cert_chain(certfile, keyfile)
325 if ciphers is not None:
326 context.set_ciphers(ciphers)
327 return context.wrap_socket(sock, **kwargs)
328
Christian Heimesa170fa12017-09-15 20:27:30 +0200329
330def testing_context(server_cert=SIGNED_CERTFILE):
331 """Create context
332
333 client_context, server_context, hostname = testing_context()
334 """
335 if server_cert == SIGNED_CERTFILE:
336 hostname = SIGNED_CERTFILE_HOSTNAME
337 elif server_cert == SIGNED_CERTFILE2:
338 hostname = SIGNED_CERTFILE2_HOSTNAME
339 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
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100362 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
363 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000364 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100365 self.assertIn(ssl.HAS_ECDH, {True, False})
Christian Heimescb5b68a2017-09-07 18:07:00 -0700366 ssl.OP_NO_SSLv2
367 ssl.OP_NO_SSLv3
368 ssl.OP_NO_TLSv1
369 ssl.OP_NO_TLSv1_3
370 if ssl.OPENSSL_VERSION_INFO >= (1, 0, 1):
371 ssl.OP_NO_TLSv1_1
372 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200373 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000374
Christian Heimes9d50ab52018-02-27 10:17:30 +0100375 def test_private_init(self):
376 with self.assertRaisesRegex(TypeError, "public constructor"):
377 with socket.socket() as s:
378 ssl.SSLSocket(s)
379
Antoine Pitrou172f0252014-04-18 20:33:08 +0200380 def test_str_for_enums(self):
381 # Make sure that the PROTOCOL_* constants have enum-like string
382 # reprs.
Christian Heimes598894f2016-09-05 23:19:05 +0200383 proto = ssl.PROTOCOL_TLS
384 self.assertEqual(str(proto), '_SSLMethod.PROTOCOL_TLS')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200385 ctx = ssl.SSLContext(proto)
386 self.assertIs(ctx.protocol, proto)
387
Antoine Pitrou480a1242010-04-28 21:37:09 +0000388 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000389 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000390 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000391 sys.stdout.write("\n RAND_status is %d (%s)\n"
392 % (v, (v and "sufficient randomness") or
393 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200394
395 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
396 self.assertEqual(len(data), 16)
397 self.assertEqual(is_cryptographic, v == 1)
398 if v:
399 data = ssl.RAND_bytes(16)
400 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200401 else:
402 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200403
Victor Stinner1e81a392013-12-19 16:47:04 +0100404 # negative num is invalid
405 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
406 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
407
Victor Stinnerbeeb5122014-11-28 13:28:25 +0100408 if hasattr(ssl, 'RAND_egd'):
409 self.assertRaises(TypeError, ssl.RAND_egd, 1)
410 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000411 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200412 ssl.RAND_add(b"this is a random bytes object", 75.0)
413 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000414
pxinwr98a54172020-12-09 07:20:19 +0800415 @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
Christian Heimesf77b4b22013-08-21 13:26:05 +0200416 def test_random_fork(self):
417 status = ssl.RAND_status()
418 if not status:
419 self.fail("OpenSSL's PRNG has insufficient randomness")
420
421 rfd, wfd = os.pipe()
422 pid = os.fork()
423 if pid == 0:
424 try:
425 os.close(rfd)
426 child_random = ssl.RAND_pseudo_bytes(16)[0]
427 self.assertEqual(len(child_random), 16)
428 os.write(wfd, child_random)
429 os.close(wfd)
430 except BaseException:
431 os._exit(1)
432 else:
433 os._exit(0)
434 else:
435 os.close(wfd)
436 self.addCleanup(os.close, rfd)
Victor Stinner278c1e12020-03-31 20:08:12 +0200437 support.wait_process(pid, exitcode=0)
Christian Heimesf77b4b22013-08-21 13:26:05 +0200438
439 child_random = os.read(rfd, 16)
440 self.assertEqual(len(child_random), 16)
441 parent_random = ssl.RAND_pseudo_bytes(16)[0]
442 self.assertEqual(len(parent_random), 16)
443
444 self.assertNotEqual(child_random, parent_random)
445
Christian Heimese6dac002018-08-30 07:25:49 +0200446 maxDiff = None
447
Antoine Pitrou480a1242010-04-28 21:37:09 +0000448 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000449 # note that this uses an 'unofficial' function in _ssl.c,
450 # provided solely for this test, to exercise the certificate
451 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100452 self.assertEqual(
453 ssl._ssl._test_decode_cert(CERTFILE),
454 CERTFILE_INFO
455 )
456 self.assertEqual(
457 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
458 SIGNED_CERTFILE_INFO
459 )
460
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200461 # Issue #13034: the subjectAltName in some certificates
462 # (notably projects.developer.nokia.com:443) wasn't parsed
463 p = ssl._ssl._test_decode_cert(NOKIACERT)
464 if support.verbose:
465 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
466 self.assertEqual(p['subjectAltName'],
467 (('DNS', 'projects.developer.nokia.com'),
468 ('DNS', 'projects.forum.nokia.com'))
469 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100470 # extra OCSP and AIA fields
471 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
472 self.assertEqual(p['caIssuers'],
473 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
474 self.assertEqual(p['crlDistributionPoints'],
475 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000476
Christian Heimesa37f5242019-01-15 23:47:42 +0100477 def test_parse_cert_CVE_2019_5010(self):
478 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
479 if support.verbose:
480 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
481 self.assertEqual(
482 p,
483 {
484 'issuer': (
485 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
486 'notAfter': 'Jun 14 18:00:58 2028 GMT',
487 'notBefore': 'Jun 18 18:00:58 2018 GMT',
488 'serialNumber': '02',
489 'subject': ((('countryName', 'UK'),),
490 (('commonName',
491 'codenomicon-vm-2.test.lal.cisco.com'),)),
492 'subjectAltName': (
493 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
494 'version': 3
495 }
496 )
497
Christian Heimes824f7f32013-08-17 00:54:47 +0200498 def test_parse_cert_CVE_2013_4238(self):
499 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
500 if support.verbose:
501 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
502 subject = ((('countryName', 'US'),),
503 (('stateOrProvinceName', 'Oregon'),),
504 (('localityName', 'Beaverton'),),
505 (('organizationName', 'Python Software Foundation'),),
506 (('organizationalUnitName', 'Python Core Development'),),
507 (('commonName', 'null.python.org\x00example.org'),),
508 (('emailAddress', 'python-dev@python.org'),))
509 self.assertEqual(p['subject'], subject)
510 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200511 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
512 san = (('DNS', 'altnull.python.org\x00example.com'),
513 ('email', 'null@python.org\x00user@example.org'),
514 ('URI', 'http://null.python.org\x00http://example.org'),
515 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100516 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200517 else:
518 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
519 san = (('DNS', 'altnull.python.org\x00example.com'),
520 ('email', 'null@python.org\x00user@example.org'),
521 ('URI', 'http://null.python.org\x00http://example.org'),
522 ('IP Address', '192.0.2.1'),
523 ('IP Address', '<invalid>'))
524
525 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200526
Christian Heimes1c03abd2016-09-06 23:25:35 +0200527 def test_parse_all_sans(self):
528 p = ssl._ssl._test_decode_cert(ALLSANFILE)
529 self.assertEqual(p['subjectAltName'],
530 (
531 ('DNS', 'allsans'),
532 ('othername', '<unsupported>'),
533 ('othername', '<unsupported>'),
534 ('email', 'user@example.org'),
535 ('DNS', 'www.example.org'),
536 ('DirName',
537 ((('countryName', 'XY'),),
538 (('localityName', 'Castle Anthrax'),),
539 (('organizationName', 'Python Software Foundation'),),
540 (('commonName', 'dirname example'),))),
541 ('URI', 'https://www.python.org/'),
542 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100543 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200544 ('Registered ID', '1.2.3.4.5')
545 )
546 )
547
Antoine Pitrou480a1242010-04-28 21:37:09 +0000548 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000549 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000550 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000551 d1 = ssl.PEM_cert_to_DER_cert(pem)
552 p2 = ssl.DER_cert_to_PEM_cert(d1)
553 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000554 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000555 if not p2.startswith(ssl.PEM_HEADER + '\n'):
556 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
557 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
558 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000559
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000560 def test_openssl_version(self):
561 n = ssl.OPENSSL_VERSION_NUMBER
562 t = ssl.OPENSSL_VERSION_INFO
563 s = ssl.OPENSSL_VERSION
564 self.assertIsInstance(n, int)
565 self.assertIsInstance(t, tuple)
566 self.assertIsInstance(s, str)
567 # Some sanity checks follow
568 # >= 0.9
569 self.assertGreaterEqual(n, 0x900000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100570 # < 4.0
571 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000572 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100573 self.assertGreaterEqual(major, 1)
574 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000575 self.assertGreaterEqual(minor, 0)
576 self.assertLess(minor, 256)
577 self.assertGreaterEqual(fix, 0)
578 self.assertLess(fix, 256)
579 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100580 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000581 self.assertGreaterEqual(status, 0)
582 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400583 # Version string as returned by {Open,Libre}SSL, the format might change
Christian Heimes598894f2016-09-05 23:19:05 +0200584 if IS_LIBRESSL:
585 self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
Victor Stinner789b8052015-01-06 11:51:06 +0100586 (s, t, hex(n)))
Antoine Pitroudfab9352014-07-21 18:35:01 -0400587 else:
588 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
Victor Stinner789b8052015-01-06 11:51:06 +0100589 (s, t, hex(n)))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000590
Antoine Pitrou9d543662010-04-23 23:10:32 +0000591 @support.cpython_only
592 def test_refcycle(self):
593 # Issue #7943: an SSL object doesn't create reference cycles with
594 # itself.
595 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200596 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000597 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800598 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100599 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100600 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000601
Antoine Pitroua468adc2010-09-14 14:43:44 +0000602 def test_wrapped_unconnected(self):
603 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200604 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000605 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200606 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100607 self.assertRaises(OSError, ss.recv, 1)
608 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
609 self.assertRaises(OSError, ss.recvfrom, 1)
610 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
611 self.assertRaises(OSError, ss.send, b'x')
612 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200613 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100614 self.assertRaises(NotImplementedError, ss.sendmsg,
615 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200616 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
617 self.assertRaises(NotImplementedError, ss.recvmsg_into,
618 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000619
Antoine Pitrou40f08742010-04-24 22:04:40 +0000620 def test_timeout(self):
621 # Issue #8524: when creating an SSL socket, the timeout of the
622 # original socket should be retained.
623 for timeout in (None, 0.0, 5.0):
624 s = socket.socket(socket.AF_INET)
625 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200626 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100627 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000628
Christian Heimesd0486372016-09-10 23:23:33 +0200629 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000630 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000631 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000632 "certfile must be specified",
633 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000634 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000635 "certfile must be specified for server-side operations",
636 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000637 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000638 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200639 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100640 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
641 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200642 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200643 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000644 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000645 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000646 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200647 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000648 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000649 ssl.wrap_socket(sock,
650 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000651 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200652 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000653 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000654 ssl.wrap_socket(sock,
655 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000656 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000657
Martin Panter3464ea22016-02-01 21:58:11 +0000658 def bad_cert_test(self, certfile):
659 """Check that trying to use the given client certificate fails"""
660 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
661 certfile)
662 sock = socket.socket()
663 self.addCleanup(sock.close)
664 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200665 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200666 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000667
668 def test_empty_cert(self):
669 """Wrapping with an empty cert file"""
670 self.bad_cert_test("nullcert.pem")
671
672 def test_malformed_cert(self):
673 """Wrapping with a badly formatted certificate (syntax error)"""
674 self.bad_cert_test("badcert.pem")
675
676 def test_malformed_key(self):
677 """Wrapping with a badly formatted key (syntax error)"""
678 self.bad_cert_test("badkey.pem")
679
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000680 def test_match_hostname(self):
681 def ok(cert, hostname):
682 ssl.match_hostname(cert, hostname)
683 def fail(cert, hostname):
684 self.assertRaises(ssl.CertificateError,
685 ssl.match_hostname, cert, hostname)
686
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100687 # -- Hostname matching --
688
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000689 cert = {'subject': ((('commonName', 'example.com'),),)}
690 ok(cert, 'example.com')
691 ok(cert, 'ExAmple.cOm')
692 fail(cert, 'www.example.com')
693 fail(cert, '.example.com')
694 fail(cert, 'example.org')
695 fail(cert, 'exampleXcom')
696
697 cert = {'subject': ((('commonName', '*.a.com'),),)}
698 ok(cert, 'foo.a.com')
699 fail(cert, 'bar.foo.a.com')
700 fail(cert, 'a.com')
701 fail(cert, 'Xa.com')
702 fail(cert, '.a.com')
703
Mandeep Singhede2ac92017-11-27 04:01:27 +0530704 # only match wildcards when they are the only thing
705 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000706 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530707 fail(cert, 'foo.com')
708 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000709 fail(cert, 'bar.com')
710 fail(cert, 'foo.a.com')
711 fail(cert, 'bar.foo.com')
712
Christian Heimes824f7f32013-08-17 00:54:47 +0200713 # NULL bytes are bad, CVE-2013-4073
714 cert = {'subject': ((('commonName',
715 'null.python.org\x00example.org'),),)}
716 ok(cert, 'null.python.org\x00example.org') # or raise an error?
717 fail(cert, 'example.org')
718 fail(cert, 'null.python.org')
719
Georg Brandl72c98d32013-10-27 07:16:53 +0100720 # error cases with wildcards
721 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
722 fail(cert, 'bar.foo.a.com')
723 fail(cert, 'a.com')
724 fail(cert, 'Xa.com')
725 fail(cert, '.a.com')
726
727 cert = {'subject': ((('commonName', 'a.*.com'),),)}
728 fail(cert, 'a.foo.com')
729 fail(cert, 'a..com')
730 fail(cert, 'a.com')
731
732 # wildcard doesn't match IDNA prefix 'xn--'
733 idna = 'püthon.python.org'.encode("idna").decode("ascii")
734 cert = {'subject': ((('commonName', idna),),)}
735 ok(cert, idna)
736 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
737 fail(cert, idna)
738 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
739 fail(cert, idna)
740
741 # wildcard in first fragment and IDNA A-labels in sequent fragments
742 # are supported.
743 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
744 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530745 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
746 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100747 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
748 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
749
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000750 # Slightly fake real-world example
751 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
752 'subject': ((('commonName', 'linuxfrz.org'),),),
753 'subjectAltName': (('DNS', 'linuxfr.org'),
754 ('DNS', 'linuxfr.com'),
755 ('othername', '<unsupported>'))}
756 ok(cert, 'linuxfr.org')
757 ok(cert, 'linuxfr.com')
758 # Not a "DNS" entry
759 fail(cert, '<unsupported>')
760 # When there is a subjectAltName, commonName isn't used
761 fail(cert, 'linuxfrz.org')
762
763 # A pristine real-world example
764 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
765 'subject': ((('countryName', 'US'),),
766 (('stateOrProvinceName', 'California'),),
767 (('localityName', 'Mountain View'),),
768 (('organizationName', 'Google Inc'),),
769 (('commonName', 'mail.google.com'),))}
770 ok(cert, 'mail.google.com')
771 fail(cert, 'gmail.com')
772 # Only commonName is considered
773 fail(cert, 'California')
774
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100775 # -- IPv4 matching --
776 cert = {'subject': ((('commonName', 'example.com'),),),
777 'subjectAltName': (('DNS', 'example.com'),
778 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200779 ('IP Address', '14.15.16.17'),
780 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100781 ok(cert, '10.11.12.13')
782 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200783 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
784 fail(cert, '127.1')
785 fail(cert, '14.15.16.17 ')
786 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100787 fail(cert, '14.15.16.18')
788 fail(cert, 'example.net')
789
790 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300791 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100792 cert = {'subject': ((('commonName', 'example.com'),),),
793 'subjectAltName': (
794 ('DNS', 'example.com'),
795 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
796 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
797 ok(cert, '2001::cafe')
798 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200799 fail(cert, '2003::baba ')
800 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100801 fail(cert, '2003::bebe')
802 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100803
804 # -- Miscellaneous --
805
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000806 # Neither commonName nor subjectAltName
807 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
808 'subject': ((('countryName', 'US'),),
809 (('stateOrProvinceName', 'California'),),
810 (('localityName', 'Mountain View'),),
811 (('organizationName', 'Google Inc'),))}
812 fail(cert, 'mail.google.com')
813
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200814 # No DNS entry in subjectAltName but a commonName
815 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
816 'subject': ((('countryName', 'US'),),
817 (('stateOrProvinceName', 'California'),),
818 (('localityName', 'Mountain View'),),
819 (('commonName', 'mail.google.com'),)),
820 'subjectAltName': (('othername', 'blabla'), )}
821 ok(cert, 'mail.google.com')
822
823 # No DNS entry subjectAltName and no commonName
824 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
825 'subject': ((('countryName', 'US'),),
826 (('stateOrProvinceName', 'California'),),
827 (('localityName', 'Mountain View'),),
828 (('organizationName', 'Google Inc'),)),
829 'subjectAltName': (('othername', 'blabla'),)}
830 fail(cert, 'google.com')
831
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000832 # Empty cert / no cert
833 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
834 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
835
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200836 # Issue #17980: avoid denials of service by refusing more than one
837 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100838 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
839 with self.assertRaisesRegex(
840 ssl.CertificateError,
841 "partial wildcards in leftmost label are not supported"):
842 ssl.match_hostname(cert, 'axxb.example.com')
843
844 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
845 with self.assertRaisesRegex(
846 ssl.CertificateError,
847 "wildcard can only be present in the leftmost label"):
848 ssl.match_hostname(cert, 'www.sub.example.com')
849
850 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
851 with self.assertRaisesRegex(
852 ssl.CertificateError,
853 "too many wildcards"):
854 ssl.match_hostname(cert, 'axxbxxc.example.com')
855
856 cert = {'subject': ((('commonName', '*'),),)}
857 with self.assertRaisesRegex(
858 ssl.CertificateError,
859 "sole wildcard without additional labels are not support"):
860 ssl.match_hostname(cert, 'host')
861
862 cert = {'subject': ((('commonName', '*.com'),),)}
863 with self.assertRaisesRegex(
864 ssl.CertificateError,
865 r"hostname 'com' doesn't match '\*.com'"):
866 ssl.match_hostname(cert, 'com')
867
868 # extra checks for _inet_paton()
869 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
870 with self.assertRaises(ValueError):
871 ssl._inet_paton(invalid)
872 for ipaddr in ['127.0.0.1', '192.168.0.1']:
873 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300874 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100875 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
876 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200877
Antoine Pitroud5323212010-10-22 18:19:07 +0000878 def test_server_side(self):
879 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200880 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000881 with socket.socket() as sock:
882 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
883 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000884
Antoine Pitroud6494802011-07-21 01:11:30 +0200885 def test_unknown_channel_binding(self):
886 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200887 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200888 c = socket.socket(socket.AF_INET)
889 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200890 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100891 with self.assertRaises(ValueError):
892 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200893 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200894
895 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
896 "'tls-unique' channel binding not available")
897 def test_tls_unique_channel_binding(self):
898 # unconnected should return None for known type
899 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200900 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100901 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200902 # the same for server-side
903 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200904 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100905 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200906
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600907 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200908 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600909 r = repr(ss)
910 with self.assertWarns(ResourceWarning) as cm:
911 ss = None
912 support.gc_collect()
913 self.assertIn(r, str(cm.warning.args[0]))
914
Christian Heimes6d7ad132013-06-09 18:02:55 +0200915 def test_get_default_verify_paths(self):
916 paths = ssl.get_default_verify_paths()
917 self.assertEqual(len(paths), 6)
918 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
919
Hai Shia7f5d932020-08-04 00:41:24 +0800920 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200921 env["SSL_CERT_DIR"] = CAPATH
922 env["SSL_CERT_FILE"] = CERTFILE
923 paths = ssl.get_default_verify_paths()
924 self.assertEqual(paths.cafile, CERTFILE)
925 self.assertEqual(paths.capath, CAPATH)
926
Christian Heimes44109d72013-11-22 01:51:30 +0100927 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
928 def test_enum_certificates(self):
929 self.assertTrue(ssl.enum_certificates("CA"))
930 self.assertTrue(ssl.enum_certificates("ROOT"))
931
932 self.assertRaises(TypeError, ssl.enum_certificates)
933 self.assertRaises(WindowsError, ssl.enum_certificates, "")
934
Christian Heimesc2d65e12013-11-22 16:13:55 +0100935 trust_oids = set()
936 for storename in ("CA", "ROOT"):
937 store = ssl.enum_certificates(storename)
938 self.assertIsInstance(store, list)
939 for element in store:
940 self.assertIsInstance(element, tuple)
941 self.assertEqual(len(element), 3)
942 cert, enc, trust = element
943 self.assertIsInstance(cert, bytes)
944 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200945 self.assertIsInstance(trust, (frozenset, set, bool))
946 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100947 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100948
949 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100950 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200951
Christian Heimes46bebee2013-06-09 19:03:31 +0200952 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100953 def test_enum_crls(self):
954 self.assertTrue(ssl.enum_crls("CA"))
955 self.assertRaises(TypeError, ssl.enum_crls)
956 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200957
Christian Heimes44109d72013-11-22 01:51:30 +0100958 crls = ssl.enum_crls("CA")
959 self.assertIsInstance(crls, list)
960 for element in crls:
961 self.assertIsInstance(element, tuple)
962 self.assertEqual(len(element), 2)
963 self.assertIsInstance(element[0], bytes)
964 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200965
Christian Heimes46bebee2013-06-09 19:03:31 +0200966
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100967 def test_asn1object(self):
968 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
969 '1.3.6.1.5.5.7.3.1')
970
971 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
972 self.assertEqual(val, expected)
973 self.assertEqual(val.nid, 129)
974 self.assertEqual(val.shortname, 'serverAuth')
975 self.assertEqual(val.longname, 'TLS Web Server Authentication')
976 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
977 self.assertIsInstance(val, ssl._ASN1Object)
978 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
979
980 val = ssl._ASN1Object.fromnid(129)
981 self.assertEqual(val, expected)
982 self.assertIsInstance(val, ssl._ASN1Object)
983 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100984 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
985 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100986 for i in range(1000):
987 try:
988 obj = ssl._ASN1Object.fromnid(i)
989 except ValueError:
990 pass
991 else:
992 self.assertIsInstance(obj.nid, int)
993 self.assertIsInstance(obj.shortname, str)
994 self.assertIsInstance(obj.longname, str)
995 self.assertIsInstance(obj.oid, (str, type(None)))
996
997 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
998 self.assertEqual(val, expected)
999 self.assertIsInstance(val, ssl._ASN1Object)
1000 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
1001 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
1002 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +01001003 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
1004 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001005
Christian Heimes72d28502013-11-23 13:56:58 +01001006 def test_purpose_enum(self):
1007 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
1008 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
1009 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
1010 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
1011 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
1012 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
1013 '1.3.6.1.5.5.7.3.1')
1014
1015 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
1016 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
1017 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
1018 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
1019 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
1020 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
1021 '1.3.6.1.5.5.7.3.2')
1022
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001023 def test_unsupported_dtls(self):
1024 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1025 self.addCleanup(s.close)
1026 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +02001027 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001028 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +02001029 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001030 with self.assertRaises(NotImplementedError) as cx:
1031 ctx.wrap_socket(s)
1032 self.assertEqual(str(cx.exception), "only stream sockets are supported")
1033
Antoine Pitrouc695c952014-04-28 20:57:36 +02001034 def cert_time_ok(self, timestring, timestamp):
1035 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
1036
1037 def cert_time_fail(self, timestring):
1038 with self.assertRaises(ValueError):
1039 ssl.cert_time_to_seconds(timestring)
1040
1041 @unittest.skipUnless(utc_offset(),
1042 'local time needs to be different from UTC')
1043 def test_cert_time_to_seconds_timezone(self):
1044 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
1045 # results if local timezone is not UTC
1046 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
1047 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
1048
1049 def test_cert_time_to_seconds(self):
1050 timestring = "Jan 5 09:34:43 2018 GMT"
1051 ts = 1515144883.0
1052 self.cert_time_ok(timestring, ts)
1053 # accept keyword parameter, assert its name
1054 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
1055 # accept both %e and %d (space or zero generated by strftime)
1056 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
1057 # case-insensitive
1058 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
1059 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
1060 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1061 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1062 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1063 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1064 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1065 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1066
1067 newyear_ts = 1230768000.0
1068 # leap seconds
1069 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1070 # same timestamp
1071 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1072
1073 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1074 # allow 60th second (even if it is not a leap second)
1075 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1076 # allow 2nd leap second for compatibility with time.strptime()
1077 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1078 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1079
Mike53f7a7c2017-12-14 14:04:53 +03001080 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001081 # 99991231235959Z (rfc 5280)
1082 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1083
1084 @support.run_with_locale('LC_ALL', '')
1085 def test_cert_time_to_seconds_locale(self):
1086 # `cert_time_to_seconds()` should be locale independent
1087
1088 def local_february_name():
1089 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1090
1091 if local_february_name().lower() == 'feb':
1092 self.skipTest("locale-specific month name needs to be "
1093 "different from C locale")
1094
1095 # locale-independent
1096 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1097 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1098
Martin Panter3840b2a2016-03-27 01:53:46 +00001099 def test_connect_ex_error(self):
1100 server = socket.socket(socket.AF_INET)
1101 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001102 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001103 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001104 cert_reqs=ssl.CERT_REQUIRED)
1105 self.addCleanup(s.close)
1106 rc = s.connect_ex((HOST, port))
1107 # Issue #19919: Windows machines or VMs hosted on Windows
1108 # machines sometimes return EWOULDBLOCK.
1109 errors = (
1110 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1111 errno.EWOULDBLOCK,
1112 )
1113 self.assertIn(rc, errors)
1114
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001115
Antoine Pitrou152efa22010-05-16 18:19:27 +00001116class ContextTests(unittest.TestCase):
1117
1118 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001119 for protocol in PROTOCOLS:
1120 ssl.SSLContext(protocol)
Christian Heimes598894f2016-09-05 23:19:05 +02001121 ctx = ssl.SSLContext()
1122 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001123 self.assertRaises(ValueError, ssl.SSLContext, -1)
1124 self.assertRaises(ValueError, ssl.SSLContext, 42)
1125
1126 def test_protocol(self):
1127 for proto in PROTOCOLS:
1128 ctx = ssl.SSLContext(proto)
1129 self.assertEqual(ctx.protocol, proto)
1130
1131 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001132 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001133 ctx.set_ciphers("ALL")
1134 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001135 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001136 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001137
Christian Heimes892d66e2018-01-29 14:10:18 +01001138 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1139 "Test applies only to Python default ciphers")
1140 def test_python_ciphers(self):
1141 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1142 ciphers = ctx.get_ciphers()
1143 for suite in ciphers:
1144 name = suite['name']
1145 self.assertNotIn("PSK", name)
1146 self.assertNotIn("SRP", name)
1147 self.assertNotIn("MD5", name)
1148 self.assertNotIn("RC4", name)
1149 self.assertNotIn("3DES", name)
1150
Christian Heimes25bfcd52016-09-06 00:04:45 +02001151 @unittest.skipIf(ssl.OPENSSL_VERSION_INFO < (1, 0, 2, 0, 0), 'OpenSSL too old')
1152 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001153 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001154 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001155 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001156 self.assertIn('AES256-GCM-SHA384', names)
1157 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001158
Antoine Pitroub5218772010-05-21 09:56:06 +00001159 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001160 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001161 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001162 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001163 # SSLContext also enables these by default
1164 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001165 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
1166 OP_ENABLE_MIDDLEBOX_COMPAT)
Christian Heimes598894f2016-09-05 23:19:05 +02001167 self.assertEqual(default, ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001168 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001169 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +00001170 if can_clear_options():
Christian Heimes598894f2016-09-05 23:19:05 +02001171 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
1172 self.assertEqual(default, ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +00001173 ctx.options = 0
Matthias Klosef7c56242016-06-12 23:40:00 -07001174 # Ubuntu has OP_NO_SSLv3 forced on by default
1175 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001176 else:
1177 with self.assertRaises(ValueError):
1178 ctx.options = 0
1179
Christian Heimesa170fa12017-09-15 20:27:30 +02001180 def test_verify_mode_protocol(self):
1181 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001182 # Default value
1183 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1184 ctx.verify_mode = ssl.CERT_OPTIONAL
1185 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1186 ctx.verify_mode = ssl.CERT_REQUIRED
1187 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1188 ctx.verify_mode = ssl.CERT_NONE
1189 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1190 with self.assertRaises(TypeError):
1191 ctx.verify_mode = None
1192 with self.assertRaises(ValueError):
1193 ctx.verify_mode = 42
1194
Christian Heimesa170fa12017-09-15 20:27:30 +02001195 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1196 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1197 self.assertFalse(ctx.check_hostname)
1198
1199 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1200 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1201 self.assertTrue(ctx.check_hostname)
1202
Christian Heimes61d478c2018-01-27 15:51:38 +01001203 def test_hostname_checks_common_name(self):
1204 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1205 self.assertTrue(ctx.hostname_checks_common_name)
1206 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1207 ctx.hostname_checks_common_name = True
1208 self.assertTrue(ctx.hostname_checks_common_name)
1209 ctx.hostname_checks_common_name = False
1210 self.assertFalse(ctx.hostname_checks_common_name)
1211 ctx.hostname_checks_common_name = True
1212 self.assertTrue(ctx.hostname_checks_common_name)
1213 else:
1214 with self.assertRaises(AttributeError):
1215 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001216
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001217 @requires_minimum_version
Christian Heimesc9bc49c2019-09-11 19:24:47 +02001218 @unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
Christian Heimes698dde12018-02-27 11:54:43 +01001219 def test_min_max_version(self):
1220 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001221 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1222 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001223 minimum_range = {
1224 # stock OpenSSL
1225 ssl.TLSVersion.MINIMUM_SUPPORTED,
1226 # Fedora 29 uses TLS 1.0 by default
1227 ssl.TLSVersion.TLSv1,
1228 # RHEL 8 uses TLS 1.2 by default
1229 ssl.TLSVersion.TLSv1_2
1230 }
torsava34864d12019-12-02 17:15:42 +01001231 maximum_range = {
1232 # stock OpenSSL
1233 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1234 # Fedora 32 uses TLS 1.3 by default
1235 ssl.TLSVersion.TLSv1_3
1236 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001237
Christian Heimes34de2d32019-01-18 16:09:30 +01001238 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001239 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001240 )
torsava34864d12019-12-02 17:15:42 +01001241 self.assertIn(
1242 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001243 )
1244
1245 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1246 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1247 self.assertEqual(
1248 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1249 )
1250 self.assertEqual(
1251 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1252 )
1253
1254 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1255 ctx.maximum_version = ssl.TLSVersion.TLSv1
1256 self.assertEqual(
1257 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1258 )
1259 self.assertEqual(
1260 ctx.maximum_version, ssl.TLSVersion.TLSv1
1261 )
1262
1263 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1264 self.assertEqual(
1265 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1266 )
1267
1268 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1269 self.assertIn(
1270 ctx.maximum_version,
1271 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1272 )
1273
1274 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1275 self.assertIn(
1276 ctx.minimum_version,
1277 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1278 )
1279
1280 with self.assertRaises(ValueError):
1281 ctx.minimum_version = 42
1282
1283 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1284
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001285 self.assertIn(
1286 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001287 )
1288 self.assertEqual(
1289 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1290 )
1291 with self.assertRaises(ValueError):
1292 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1293 with self.assertRaises(ValueError):
1294 ctx.maximum_version = ssl.TLSVersion.TLSv1
1295
1296
matthewhughes9348e836bb2020-07-17 09:59:15 +01001297 @unittest.skipUnless(
1298 hasattr(ssl.SSLContext, 'security_level'),
1299 "requires OpenSSL >= 1.1.0"
1300 )
1301 def test_security_level(self):
1302 ctx = ssl.SSLContext()
1303 # The default security callback allows for levels between 0-5
1304 # with OpenSSL defaulting to 1, however some vendors override the
1305 # default value (e.g. Debian defaults to 2)
1306 security_level_range = {
1307 0,
1308 1, # OpenSSL default
1309 2, # Debian
1310 3,
1311 4,
1312 5,
1313 }
1314 self.assertIn(ctx.security_level, security_level_range)
1315
Christian Heimes2427b502013-11-23 11:24:32 +01001316 @unittest.skipUnless(have_verify_flags(),
1317 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01001318 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001319 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001320 # default value
1321 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1322 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001323 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1324 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1325 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1326 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1327 ctx.verify_flags = ssl.VERIFY_DEFAULT
1328 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001329 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1330 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001331 # supports any value
1332 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1333 self.assertEqual(ctx.verify_flags,
1334 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1335 with self.assertRaises(TypeError):
1336 ctx.verify_flags = None
1337
Antoine Pitrou152efa22010-05-16 18:19:27 +00001338 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001339 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001340 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001341 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001342 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1343 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001344 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001345 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001346 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001347 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001348 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001349 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001350 ctx.load_cert_chain(EMPTYCERT)
1351 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001352 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001353 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1354 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1355 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001356 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001357 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001358 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001359 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001360 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001361 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1362 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001363 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001364 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001365 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001366 # Password protected key and cert
1367 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1368 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1369 ctx.load_cert_chain(CERTFILE_PROTECTED,
1370 password=bytearray(KEY_PASSWORD.encode()))
1371 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1372 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1373 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1374 bytearray(KEY_PASSWORD.encode()))
1375 with self.assertRaisesRegex(TypeError, "should be a string"):
1376 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1377 with self.assertRaises(ssl.SSLError):
1378 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1379 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1380 # openssl has a fixed limit on the password buffer.
1381 # PEM_BUFSIZE is generally set to 1kb.
1382 # Return a string larger than this.
1383 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1384 # Password callback
1385 def getpass_unicode():
1386 return KEY_PASSWORD
1387 def getpass_bytes():
1388 return KEY_PASSWORD.encode()
1389 def getpass_bytearray():
1390 return bytearray(KEY_PASSWORD.encode())
1391 def getpass_badpass():
1392 return "badpass"
1393 def getpass_huge():
1394 return b'a' * (1024 * 1024)
1395 def getpass_bad_type():
1396 return 9
1397 def getpass_exception():
1398 raise Exception('getpass error')
1399 class GetPassCallable:
1400 def __call__(self):
1401 return KEY_PASSWORD
1402 def getpass(self):
1403 return KEY_PASSWORD
1404 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1405 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1406 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1407 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1408 ctx.load_cert_chain(CERTFILE_PROTECTED,
1409 password=GetPassCallable().getpass)
1410 with self.assertRaises(ssl.SSLError):
1411 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1412 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1413 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1414 with self.assertRaisesRegex(TypeError, "must return a string"):
1415 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1416 with self.assertRaisesRegex(Exception, "getpass error"):
1417 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1418 # Make sure the password function isn't called if it isn't needed
1419 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001420
1421 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001422 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001423 ctx.load_verify_locations(CERTFILE)
1424 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1425 ctx.load_verify_locations(BYTES_CERTFILE)
1426 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1427 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001428 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001429 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001430 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001431 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001432 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001433 ctx.load_verify_locations(BADCERT)
1434 ctx.load_verify_locations(CERTFILE, CAPATH)
1435 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1436
Victor Stinner80f75e62011-01-29 11:31:20 +00001437 # Issue #10989: crash if the second argument type is invalid
1438 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1439
Christian Heimesefff7062013-11-21 03:35:02 +01001440 def test_load_verify_cadata(self):
1441 # test cadata
1442 with open(CAFILE_CACERT) as f:
1443 cacert_pem = f.read()
1444 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1445 with open(CAFILE_NEURONIO) as f:
1446 neuronio_pem = f.read()
1447 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1448
1449 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001450 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001451 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1452 ctx.load_verify_locations(cadata=cacert_pem)
1453 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1454 ctx.load_verify_locations(cadata=neuronio_pem)
1455 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1456 # cert already in hash table
1457 ctx.load_verify_locations(cadata=neuronio_pem)
1458 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1459
1460 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001461 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001462 combined = "\n".join((cacert_pem, neuronio_pem))
1463 ctx.load_verify_locations(cadata=combined)
1464 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1465
1466 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001467 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001468 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1469 neuronio_pem, "tail"]
1470 ctx.load_verify_locations(cadata="\n".join(combined))
1471 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1472
1473 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001474 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001475 ctx.load_verify_locations(cadata=cacert_der)
1476 ctx.load_verify_locations(cadata=neuronio_der)
1477 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1478 # cert already in hash table
1479 ctx.load_verify_locations(cadata=cacert_der)
1480 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1481
1482 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001483 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001484 combined = b"".join((cacert_der, neuronio_der))
1485 ctx.load_verify_locations(cadata=combined)
1486 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1487
1488 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001489 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001490 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1491
1492 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1493 ctx.load_verify_locations(cadata="broken")
1494 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1495 ctx.load_verify_locations(cadata=b"broken")
1496
1497
Paul Monsonf3550692019-06-19 13:09:54 -07001498 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001499 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001500 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001501 ctx.load_dh_params(DHFILE)
1502 if os.name != 'nt':
1503 ctx.load_dh_params(BYTES_DHFILE)
1504 self.assertRaises(TypeError, ctx.load_dh_params)
1505 self.assertRaises(TypeError, ctx.load_dh_params, None)
1506 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001507 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001508 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001509 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001510 ctx.load_dh_params(CERTFILE)
1511
Antoine Pitroub0182c82010-10-12 20:09:02 +00001512 def test_session_stats(self):
1513 for proto in PROTOCOLS:
1514 ctx = ssl.SSLContext(proto)
1515 self.assertEqual(ctx.session_stats(), {
1516 'number': 0,
1517 'connect': 0,
1518 'connect_good': 0,
1519 'connect_renegotiate': 0,
1520 'accept': 0,
1521 'accept_good': 0,
1522 'accept_renegotiate': 0,
1523 'hits': 0,
1524 'misses': 0,
1525 'timeouts': 0,
1526 'cache_full': 0,
1527 })
1528
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001529 def test_set_default_verify_paths(self):
1530 # There's not much we can do to test that it acts as expected,
1531 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001532 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001533 ctx.set_default_verify_paths()
1534
Antoine Pitrou501da612011-12-21 09:27:41 +01001535 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001536 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001537 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001538 ctx.set_ecdh_curve("prime256v1")
1539 ctx.set_ecdh_curve(b"prime256v1")
1540 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1541 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1542 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1543 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1544
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001545 @needs_sni
1546 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001547 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001548
1549 # set_servername_callback expects a callable, or None
1550 self.assertRaises(TypeError, ctx.set_servername_callback)
1551 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1552 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1553 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1554
1555 def dummycallback(sock, servername, ctx):
1556 pass
1557 ctx.set_servername_callback(None)
1558 ctx.set_servername_callback(dummycallback)
1559
1560 @needs_sni
1561 def test_sni_callback_refcycle(self):
1562 # Reference cycles through the servername callback are detected
1563 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001564 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001565 def dummycallback(sock, servername, ctx, cycle=ctx):
1566 pass
1567 ctx.set_servername_callback(dummycallback)
1568 wr = weakref.ref(ctx)
1569 del ctx, dummycallback
1570 gc.collect()
1571 self.assertIs(wr(), None)
1572
Christian Heimes9a5395a2013-06-17 15:44:12 +02001573 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001574 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001575 self.assertEqual(ctx.cert_store_stats(),
1576 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1577 ctx.load_cert_chain(CERTFILE)
1578 self.assertEqual(ctx.cert_store_stats(),
1579 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1580 ctx.load_verify_locations(CERTFILE)
1581 self.assertEqual(ctx.cert_store_stats(),
1582 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001583 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001584 self.assertEqual(ctx.cert_store_stats(),
1585 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1586
1587 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001588 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001589 self.assertEqual(ctx.get_ca_certs(), [])
1590 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1591 ctx.load_verify_locations(CERTFILE)
1592 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001593 # but CAFILE_CACERT is a CA cert
1594 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001595 self.assertEqual(ctx.get_ca_certs(),
1596 [{'issuer': ((('organizationName', 'Root CA'),),
1597 (('organizationalUnitName', 'http://www.cacert.org'),),
1598 (('commonName', 'CA Cert Signing Authority'),),
1599 (('emailAddress', 'support@cacert.org'),)),
1600 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1601 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1602 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001603 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001604 'subject': ((('organizationName', 'Root CA'),),
1605 (('organizationalUnitName', 'http://www.cacert.org'),),
1606 (('commonName', 'CA Cert Signing Authority'),),
1607 (('emailAddress', 'support@cacert.org'),)),
1608 'version': 3}])
1609
Martin Panterb55f8b72016-01-14 12:53:56 +00001610 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001611 pem = f.read()
1612 der = ssl.PEM_cert_to_DER_cert(pem)
1613 self.assertEqual(ctx.get_ca_certs(True), [der])
1614
Christian Heimes72d28502013-11-23 13:56:58 +01001615 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001616 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001617 ctx.load_default_certs()
1618
Christian Heimesa170fa12017-09-15 20:27:30 +02001619 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001620 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1621 ctx.load_default_certs()
1622
Christian Heimesa170fa12017-09-15 20:27:30 +02001623 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001624 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1625
Christian Heimesa170fa12017-09-15 20:27:30 +02001626 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001627 self.assertRaises(TypeError, ctx.load_default_certs, None)
1628 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1629
Benjamin Peterson91244e02014-10-03 18:17:15 -04001630 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimes598894f2016-09-05 23:19:05 +02001631 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001632 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001633 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001634 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001635 env["SSL_CERT_DIR"] = CAPATH
1636 env["SSL_CERT_FILE"] = CERTFILE
1637 ctx.load_default_certs()
1638 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1639
Benjamin Peterson91244e02014-10-03 18:17:15 -04001640 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001641 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001642 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001643 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001644 ctx.load_default_certs()
1645 stats = ctx.cert_store_stats()
1646
Christian Heimesa170fa12017-09-15 20:27:30 +02001647 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001648 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001649 env["SSL_CERT_DIR"] = CAPATH
1650 env["SSL_CERT_FILE"] = CERTFILE
1651 ctx.load_default_certs()
1652 stats["x509"] += 1
1653 self.assertEqual(ctx.cert_store_stats(), stats)
1654
Christian Heimes358cfd42016-09-10 22:43:48 +02001655 def _assert_context_options(self, ctx):
1656 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1657 if OP_NO_COMPRESSION != 0:
1658 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1659 OP_NO_COMPRESSION)
1660 if OP_SINGLE_DH_USE != 0:
1661 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1662 OP_SINGLE_DH_USE)
1663 if OP_SINGLE_ECDH_USE != 0:
1664 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1665 OP_SINGLE_ECDH_USE)
1666 if OP_CIPHER_SERVER_PREFERENCE != 0:
1667 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1668 OP_CIPHER_SERVER_PREFERENCE)
1669
Christian Heimes4c05b472013-11-23 15:58:30 +01001670 def test_create_default_context(self):
1671 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001672
Christian Heimesa170fa12017-09-15 20:27:30 +02001673 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001674 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001675 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001676 self._assert_context_options(ctx)
1677
Christian Heimes4c05b472013-11-23 15:58:30 +01001678 with open(SIGNING_CA) as f:
1679 cadata = f.read()
1680 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1681 cadata=cadata)
Christian Heimesa170fa12017-09-15 20:27:30 +02001682 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001683 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001684 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001685
1686 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001687 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001688 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001689 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001690
Christian Heimes67986f92013-11-23 22:43:47 +01001691 def test__create_stdlib_context(self):
1692 ctx = ssl._create_stdlib_context()
Christian Heimesa170fa12017-09-15 20:27:30 +02001693 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001694 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001695 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001696 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001697
1698 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1699 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1700 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
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(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001704 cert_reqs=ssl.CERT_REQUIRED,
1705 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001706 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1707 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001708 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001709 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001710
1711 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001712 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001713 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001714 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001715
Christian Heimes1aa9a752013-12-02 02:41:19 +01001716 def test_check_hostname(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001717 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001718 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001719 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001720
Christian Heimese82c0342017-09-15 20:29:57 +02001721 # Auto set CERT_REQUIRED
1722 ctx.check_hostname = True
1723 self.assertTrue(ctx.check_hostname)
1724 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1725 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001726 ctx.verify_mode = ssl.CERT_REQUIRED
1727 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001728 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001729
Christian Heimese82c0342017-09-15 20:29:57 +02001730 # Changing verify_mode does not affect check_hostname
1731 ctx.check_hostname = False
1732 ctx.verify_mode = ssl.CERT_NONE
1733 ctx.check_hostname = False
1734 self.assertFalse(ctx.check_hostname)
1735 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1736 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001737 ctx.check_hostname = True
1738 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001739 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1740
1741 ctx.check_hostname = False
1742 ctx.verify_mode = ssl.CERT_OPTIONAL
1743 ctx.check_hostname = False
1744 self.assertFalse(ctx.check_hostname)
1745 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1746 # keep CERT_OPTIONAL
1747 ctx.check_hostname = True
1748 self.assertTrue(ctx.check_hostname)
1749 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001750
1751 # Cannot set CERT_NONE with check_hostname enabled
1752 with self.assertRaises(ValueError):
1753 ctx.verify_mode = ssl.CERT_NONE
1754 ctx.check_hostname = False
1755 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001756 ctx.verify_mode = ssl.CERT_NONE
1757 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001758
Christian Heimes5fe668c2016-09-12 00:01:11 +02001759 def test_context_client_server(self):
1760 # PROTOCOL_TLS_CLIENT has sane defaults
1761 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1762 self.assertTrue(ctx.check_hostname)
1763 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1764
1765 # PROTOCOL_TLS_SERVER has different but also sane defaults
1766 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1767 self.assertFalse(ctx.check_hostname)
1768 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1769
Christian Heimes4df60f12017-09-15 20:26:05 +02001770 def test_context_custom_class(self):
1771 class MySSLSocket(ssl.SSLSocket):
1772 pass
1773
1774 class MySSLObject(ssl.SSLObject):
1775 pass
1776
1777 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1778 ctx.sslsocket_class = MySSLSocket
1779 ctx.sslobject_class = MySSLObject
1780
1781 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1782 self.assertIsInstance(sock, MySSLSocket)
1783 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1784 self.assertIsInstance(obj, MySSLObject)
1785
Christian Heimes78c7d522019-06-03 21:00:10 +02001786 @unittest.skipUnless(IS_OPENSSL_1_1_1, "Test requires OpenSSL 1.1.1")
1787 def test_num_tickest(self):
1788 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1789 self.assertEqual(ctx.num_tickets, 2)
1790 ctx.num_tickets = 1
1791 self.assertEqual(ctx.num_tickets, 1)
1792 ctx.num_tickets = 0
1793 self.assertEqual(ctx.num_tickets, 0)
1794 with self.assertRaises(ValueError):
1795 ctx.num_tickets = -1
1796 with self.assertRaises(TypeError):
1797 ctx.num_tickets = None
1798
1799 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1800 self.assertEqual(ctx.num_tickets, 2)
1801 with self.assertRaises(ValueError):
1802 ctx.num_tickets = 1
1803
Antoine Pitrou152efa22010-05-16 18:19:27 +00001804
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001805class SSLErrorTests(unittest.TestCase):
1806
1807 def test_str(self):
1808 # The str() of a SSLError doesn't include the errno
1809 e = ssl.SSLError(1, "foo")
1810 self.assertEqual(str(e), "foo")
1811 self.assertEqual(e.errno, 1)
1812 # Same for a subclass
1813 e = ssl.SSLZeroReturnError(1, "foo")
1814 self.assertEqual(str(e), "foo")
1815 self.assertEqual(e.errno, 1)
1816
Paul Monsonf3550692019-06-19 13:09:54 -07001817 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001818 def test_lib_reason(self):
1819 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001820 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001821 with self.assertRaises(ssl.SSLError) as cm:
1822 ctx.load_dh_params(CERTFILE)
1823 self.assertEqual(cm.exception.library, 'PEM')
1824 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1825 s = str(cm.exception)
1826 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1827
1828 def test_subclass(self):
1829 # Check that the appropriate SSLError subclass is raised
1830 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001831 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1832 ctx.check_hostname = False
1833 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001834 with socket.create_server(("127.0.0.1", 0)) as s:
1835 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001836 c.setblocking(False)
1837 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001838 with self.assertRaises(ssl.SSLWantReadError) as cm:
1839 c.do_handshake()
1840 s = str(cm.exception)
1841 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1842 # For compatibility
1843 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1844
1845
Christian Heimes61d478c2018-01-27 15:51:38 +01001846 def test_bad_server_hostname(self):
1847 ctx = ssl.create_default_context()
1848 with self.assertRaises(ValueError):
1849 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1850 server_hostname="")
1851 with self.assertRaises(ValueError):
1852 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1853 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001854 with self.assertRaises(TypeError):
1855 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1856 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001857
1858
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001859class MemoryBIOTests(unittest.TestCase):
1860
1861 def test_read_write(self):
1862 bio = ssl.MemoryBIO()
1863 bio.write(b'foo')
1864 self.assertEqual(bio.read(), b'foo')
1865 self.assertEqual(bio.read(), b'')
1866 bio.write(b'foo')
1867 bio.write(b'bar')
1868 self.assertEqual(bio.read(), b'foobar')
1869 self.assertEqual(bio.read(), b'')
1870 bio.write(b'baz')
1871 self.assertEqual(bio.read(2), b'ba')
1872 self.assertEqual(bio.read(1), b'z')
1873 self.assertEqual(bio.read(1), b'')
1874
1875 def test_eof(self):
1876 bio = ssl.MemoryBIO()
1877 self.assertFalse(bio.eof)
1878 self.assertEqual(bio.read(), b'')
1879 self.assertFalse(bio.eof)
1880 bio.write(b'foo')
1881 self.assertFalse(bio.eof)
1882 bio.write_eof()
1883 self.assertFalse(bio.eof)
1884 self.assertEqual(bio.read(2), b'fo')
1885 self.assertFalse(bio.eof)
1886 self.assertEqual(bio.read(1), b'o')
1887 self.assertTrue(bio.eof)
1888 self.assertEqual(bio.read(), b'')
1889 self.assertTrue(bio.eof)
1890
1891 def test_pending(self):
1892 bio = ssl.MemoryBIO()
1893 self.assertEqual(bio.pending, 0)
1894 bio.write(b'foo')
1895 self.assertEqual(bio.pending, 3)
1896 for i in range(3):
1897 bio.read(1)
1898 self.assertEqual(bio.pending, 3-i-1)
1899 for i in range(3):
1900 bio.write(b'x')
1901 self.assertEqual(bio.pending, i+1)
1902 bio.read()
1903 self.assertEqual(bio.pending, 0)
1904
1905 def test_buffer_types(self):
1906 bio = ssl.MemoryBIO()
1907 bio.write(b'foo')
1908 self.assertEqual(bio.read(), b'foo')
1909 bio.write(bytearray(b'bar'))
1910 self.assertEqual(bio.read(), b'bar')
1911 bio.write(memoryview(b'baz'))
1912 self.assertEqual(bio.read(), b'baz')
1913
1914 def test_error_types(self):
1915 bio = ssl.MemoryBIO()
1916 self.assertRaises(TypeError, bio.write, 'foo')
1917 self.assertRaises(TypeError, bio.write, None)
1918 self.assertRaises(TypeError, bio.write, True)
1919 self.assertRaises(TypeError, bio.write, 1)
1920
1921
Christian Heimes9d50ab52018-02-27 10:17:30 +01001922class SSLObjectTests(unittest.TestCase):
1923 def test_private_init(self):
1924 bio = ssl.MemoryBIO()
1925 with self.assertRaisesRegex(TypeError, "public constructor"):
1926 ssl.SSLObject(bio, bio)
1927
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001928 def test_unwrap(self):
1929 client_ctx, server_ctx, hostname = testing_context()
1930 c_in = ssl.MemoryBIO()
1931 c_out = ssl.MemoryBIO()
1932 s_in = ssl.MemoryBIO()
1933 s_out = ssl.MemoryBIO()
1934 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1935 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1936
1937 # Loop on the handshake for a bit to get it settled
1938 for _ in range(5):
1939 try:
1940 client.do_handshake()
1941 except ssl.SSLWantReadError:
1942 pass
1943 if c_out.pending:
1944 s_in.write(c_out.read())
1945 try:
1946 server.do_handshake()
1947 except ssl.SSLWantReadError:
1948 pass
1949 if s_out.pending:
1950 c_in.write(s_out.read())
1951 # Now the handshakes should be complete (don't raise WantReadError)
1952 client.do_handshake()
1953 server.do_handshake()
1954
1955 # Now if we unwrap one side unilaterally, it should send close-notify
1956 # and raise WantReadError:
1957 with self.assertRaises(ssl.SSLWantReadError):
1958 client.unwrap()
1959
1960 # But server.unwrap() does not raise, because it reads the client's
1961 # close-notify:
1962 s_in.write(c_out.read())
1963 server.unwrap()
1964
1965 # And now that the client gets the server's close-notify, it doesn't
1966 # raise either.
1967 c_in.write(s_out.read())
1968 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001969
Martin Panter3840b2a2016-03-27 01:53:46 +00001970class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001971 """Tests that connect to a simple server running in the background"""
1972
1973 def setUp(self):
1974 server = ThreadedEchoServer(SIGNED_CERTFILE)
1975 self.server_addr = (HOST, server.port)
1976 server.__enter__()
1977 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001978
Antoine Pitrou480a1242010-04-28 21:37:09 +00001979 def test_connect(self):
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_NONE) as s:
1982 s.connect(self.server_addr)
1983 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001984 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001985
Martin Panter3840b2a2016-03-27 01:53:46 +00001986 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001987 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001988 cert_reqs=ssl.CERT_REQUIRED,
1989 ca_certs=SIGNING_CA) as s:
1990 s.connect(self.server_addr)
1991 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001992 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001993
Martin Panter3840b2a2016-03-27 01:53:46 +00001994 def test_connect_fail(self):
1995 # This should fail because we have no verification certs. Connection
1996 # failure crashes ThreadedEchoServer, so run this in an independent
1997 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001998 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001999 cert_reqs=ssl.CERT_REQUIRED)
2000 self.addCleanup(s.close)
2001 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2002 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002003
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002004 def test_connect_ex(self):
2005 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02002006 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002007 cert_reqs=ssl.CERT_REQUIRED,
2008 ca_certs=SIGNING_CA)
2009 self.addCleanup(s.close)
2010 self.assertEqual(0, s.connect_ex(self.server_addr))
2011 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002012
2013 def test_non_blocking_connect_ex(self):
2014 # Issue #11326: non-blocking connect_ex() should allow handshake
2015 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02002016 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002017 cert_reqs=ssl.CERT_REQUIRED,
2018 ca_certs=SIGNING_CA,
2019 do_handshake_on_connect=False)
2020 self.addCleanup(s.close)
2021 s.setblocking(False)
2022 rc = s.connect_ex(self.server_addr)
2023 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2024 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2025 # Wait for connect to finish
2026 select.select([], [s], [], 5.0)
2027 # Non-blocking handshake
2028 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002029 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002030 s.do_handshake()
2031 break
2032 except ssl.SSLWantReadError:
2033 select.select([s], [], [], 5.0)
2034 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002035 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002036 # SSL established
2037 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002038
Antoine Pitrou152efa22010-05-16 18:19:27 +00002039 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002040 # Same as test_connect, but with a separately created context
Christian Heimesa170fa12017-09-15 20:27:30 +02002041 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002042 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2043 s.connect(self.server_addr)
2044 self.assertEqual({}, s.getpeercert())
2045 # Same with a server hostname
2046 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2047 server_hostname="dummy") as s:
2048 s.connect(self.server_addr)
2049 ctx.verify_mode = ssl.CERT_REQUIRED
2050 # This should succeed because we specify the root cert
2051 ctx.load_verify_locations(SIGNING_CA)
2052 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2053 s.connect(self.server_addr)
2054 cert = s.getpeercert()
2055 self.assertTrue(cert)
2056
2057 def test_connect_with_context_fail(self):
2058 # This should fail because we have no verification certs. Connection
2059 # failure crashes ThreadedEchoServer, so run this in an independent
2060 # test method.
Christian Heimesa170fa12017-09-15 20:27:30 +02002061 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002062 ctx.verify_mode = ssl.CERT_REQUIRED
2063 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
2064 self.addCleanup(s.close)
2065 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2066 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002067
2068 def test_connect_capath(self):
2069 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002070 # NOTE: the subject hashing algorithm has been changed between
2071 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2072 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002073 # filename) for this test to be portable across OpenSSL releases.
Christian Heimesa170fa12017-09-15 20:27:30 +02002074 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002075 ctx.verify_mode = ssl.CERT_REQUIRED
2076 ctx.load_verify_locations(capath=CAPATH)
2077 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2078 s.connect(self.server_addr)
2079 cert = s.getpeercert()
2080 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002081
Martin Panter3840b2a2016-03-27 01:53:46 +00002082 # Same with a bytes `capath` argument
Christian Heimesa170fa12017-09-15 20:27:30 +02002083 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002084 ctx.verify_mode = ssl.CERT_REQUIRED
2085 ctx.load_verify_locations(capath=BYTES_CAPATH)
2086 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2087 s.connect(self.server_addr)
2088 cert = s.getpeercert()
2089 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002090
Christian Heimesefff7062013-11-21 03:35:02 +01002091 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002092 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002093 pem = f.read()
2094 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimesa170fa12017-09-15 20:27:30 +02002095 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002096 ctx.verify_mode = ssl.CERT_REQUIRED
2097 ctx.load_verify_locations(cadata=pem)
2098 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2099 s.connect(self.server_addr)
2100 cert = s.getpeercert()
2101 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002102
Martin Panter3840b2a2016-03-27 01:53:46 +00002103 # same with DER
Christian Heimesa170fa12017-09-15 20:27:30 +02002104 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002105 ctx.verify_mode = ssl.CERT_REQUIRED
2106 ctx.load_verify_locations(cadata=der)
2107 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2108 s.connect(self.server_addr)
2109 cert = s.getpeercert()
2110 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002111
Antoine Pitroue3220242010-04-24 11:13:53 +00002112 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2113 def test_makefile_close(self):
2114 # Issue #5238: creating a file-like object with makefile() shouldn't
2115 # delay closing the underlying "real socket" (here tested with its
2116 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002117 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002118 ss.connect(self.server_addr)
2119 fd = ss.fileno()
2120 f = ss.makefile()
2121 f.close()
2122 # The fd is still open
2123 os.read(fd, 0)
2124 # Closing the SSL socket should close the fd too
2125 ss.close()
2126 gc.collect()
2127 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002128 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002129 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002130
Antoine Pitrou480a1242010-04-28 21:37:09 +00002131 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002132 s = socket.socket(socket.AF_INET)
2133 s.connect(self.server_addr)
2134 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002135 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002136 cert_reqs=ssl.CERT_NONE,
2137 do_handshake_on_connect=False)
2138 self.addCleanup(s.close)
2139 count = 0
2140 while True:
2141 try:
2142 count += 1
2143 s.do_handshake()
2144 break
2145 except ssl.SSLWantReadError:
2146 select.select([s], [], [])
2147 except ssl.SSLWantWriteError:
2148 select.select([], [s], [])
2149 if support.verbose:
2150 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002151
Antoine Pitrou480a1242010-04-28 21:37:09 +00002152 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002153 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002154
Martin Panter3840b2a2016-03-27 01:53:46 +00002155 def test_get_server_certificate_fail(self):
2156 # Connection failure crashes ThreadedEchoServer, so run this in an
2157 # independent test method
2158 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002159
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002160 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002161 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002162 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2163 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002164 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002165 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2166 s.connect(self.server_addr)
2167 # Error checking can happen at instantiation or when connecting
2168 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2169 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002170 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002171 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2172 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002173
Christian Heimes9a5395a2013-06-17 15:44:12 +02002174 def test_get_ca_certs_capath(self):
2175 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002176 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002177 ctx.load_verify_locations(capath=CAPATH)
2178 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002179 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2180 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002181 s.connect(self.server_addr)
2182 cert = s.getpeercert()
2183 self.assertTrue(cert)
2184 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002185
Christian Heimes575596e2013-12-15 21:49:17 +01002186 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01002187 def test_context_setget(self):
2188 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002189 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2190 ctx1.load_verify_locations(capath=CAPATH)
2191 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2192 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002193 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002194 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002195 ss.connect(self.server_addr)
2196 self.assertIs(ss.context, ctx1)
2197 self.assertIs(ss._sslobj.context, ctx1)
2198 ss.context = ctx2
2199 self.assertIs(ss.context, ctx2)
2200 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002201
2202 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2203 # A simple IO loop. Call func(*args) depending on the error we get
2204 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002205 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002206 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002207 count = 0
2208 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002209 if time.monotonic() > deadline:
2210 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002211 errno = None
2212 count += 1
2213 try:
2214 ret = func(*args)
2215 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002216 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002217 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002218 raise
2219 errno = e.errno
2220 # Get any data from the outgoing BIO irrespective of any error, and
2221 # send it to the socket.
2222 buf = outgoing.read()
2223 sock.sendall(buf)
2224 # If there's no error, we're done. For WANT_READ, we need to get
2225 # data from the socket and put it in the incoming BIO.
2226 if errno is None:
2227 break
2228 elif errno == ssl.SSL_ERROR_WANT_READ:
2229 buf = sock.recv(32768)
2230 if buf:
2231 incoming.write(buf)
2232 else:
2233 incoming.write_eof()
2234 if support.verbose:
2235 sys.stdout.write("Needed %d calls to complete %s().\n"
2236 % (count, func.__name__))
2237 return ret
2238
Martin Panter3840b2a2016-03-27 01:53:46 +00002239 def test_bio_handshake(self):
2240 sock = socket.socket(socket.AF_INET)
2241 self.addCleanup(sock.close)
2242 sock.connect(self.server_addr)
2243 incoming = ssl.MemoryBIO()
2244 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002245 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2246 self.assertTrue(ctx.check_hostname)
2247 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002248 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002249 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2250 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002251 self.assertIs(sslobj._sslobj.owner, sslobj)
2252 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002253 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002254 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002255 self.assertRaises(ValueError, sslobj.getpeercert)
2256 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2257 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2258 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2259 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002260 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002261 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002262 self.assertTrue(sslobj.getpeercert())
2263 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2264 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2265 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002266 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002267 except ssl.SSLSyscallError:
2268 # If the server shuts down the TCP connection without sending a
2269 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2270 pass
2271 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2272
2273 def test_bio_read_write_data(self):
2274 sock = socket.socket(socket.AF_INET)
2275 self.addCleanup(sock.close)
2276 sock.connect(self.server_addr)
2277 incoming = ssl.MemoryBIO()
2278 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002279 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002280 ctx.verify_mode = ssl.CERT_NONE
2281 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2282 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2283 req = b'FOO\n'
2284 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2285 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2286 self.assertEqual(buf, b'foo\n')
2287 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002288
2289
Martin Panter3840b2a2016-03-27 01:53:46 +00002290class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002291
Martin Panter3840b2a2016-03-27 01:53:46 +00002292 def test_timeout_connect_ex(self):
2293 # Issue #12065: on a timeout, connect_ex() should return the original
2294 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002295 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002296 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002297 cert_reqs=ssl.CERT_REQUIRED,
2298 do_handshake_on_connect=False)
2299 self.addCleanup(s.close)
2300 s.settimeout(0.0000001)
2301 rc = s.connect_ex((REMOTE_HOST, 443))
2302 if rc == 0:
2303 self.skipTest("REMOTE_HOST responded too quickly")
2304 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2305
Serhiy Storchaka16994912020-04-25 10:06:29 +03002306 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002307 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002308 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002309 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2310 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2311
Martin Panter3840b2a2016-03-27 01:53:46 +00002312
2313def _test_get_server_certificate(test, host, port, cert=None):
2314 pem = ssl.get_server_certificate((host, port))
2315 if not pem:
2316 test.fail("No server certificate on %s:%s!" % (host, port))
2317
2318 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2319 if not pem:
2320 test.fail("No server certificate on %s:%s!" % (host, port))
2321 if support.verbose:
2322 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2323
2324def _test_get_server_certificate_fail(test, host, port):
2325 try:
2326 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2327 except ssl.SSLError as x:
2328 #should fail
2329 if support.verbose:
2330 sys.stdout.write("%s\n" % x)
2331 else:
2332 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2333
2334
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002335from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002336
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002337class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002338
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002339 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002340
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002341 """A mildly complicated class, because we want it to work both
2342 with and without the SSL wrapper around the socket connection, so
2343 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002344
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002345 def __init__(self, server, connsock, addr):
2346 self.server = server
2347 self.running = False
2348 self.sock = connsock
2349 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002350 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002351 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002352 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002353 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002354
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002355 def wrap_conn(self):
2356 try:
2357 self.sslconn = self.server.context.wrap_socket(
2358 self.sock, server_side=True)
2359 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
2360 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002361 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002362 # We treat ConnectionResetError as though it were an
2363 # SSLError - OpenSSL on Ubuntu abruptly closes the
2364 # connection when asked to use an unsupported protocol.
2365 #
Christian Heimes529525f2018-05-23 22:24:45 +02002366 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2367 # tries to send session tickets after handshake.
2368 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002369 #
2370 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2371 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002372 self.server.conn_errors.append(str(e))
2373 if self.server.chatty:
2374 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2375 self.running = False
2376 self.close()
2377 return False
2378 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002379 # OSError may occur with wrong protocols, e.g. both
2380 # sides use PROTOCOL_TLS_SERVER.
2381 #
2382 # XXX Various errors can have happened here, for example
2383 # a mismatching protocol version, an invalid certificate,
2384 # or a low-level bug. This should be made more discriminating.
2385 #
2386 # bpo-31323: Store the exception as string to prevent
2387 # a reference leak: server -> conn_errors -> exception
2388 # -> traceback -> self (ConnectionHandler) -> server
2389 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.server.stop()
2394 self.close()
2395 return False
2396 else:
2397 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2398 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2399 cert = self.sslconn.getpeercert()
2400 if support.verbose and self.server.chatty:
2401 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2402 cert_binary = self.sslconn.getpeercert(True)
2403 if support.verbose and self.server.chatty:
2404 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2405 cipher = self.sslconn.cipher()
2406 if support.verbose and self.server.chatty:
2407 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
2408 sys.stdout.write(" server: selected protocol is now "
2409 + str(self.sslconn.selected_npn_protocol()) + "\n")
2410 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002411
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002412 def read(self):
2413 if self.sslconn:
2414 return self.sslconn.read()
2415 else:
2416 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002417
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002418 def write(self, bytes):
2419 if self.sslconn:
2420 return self.sslconn.write(bytes)
2421 else:
2422 return self.sock.send(bytes)
2423
2424 def close(self):
2425 if self.sslconn:
2426 self.sslconn.close()
2427 else:
2428 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002429
Antoine Pitrou480a1242010-04-28 21:37:09 +00002430 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002431 self.running = True
2432 if not self.server.starttls_server:
2433 if not self.wrap_conn():
2434 return
2435 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002436 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002437 msg = self.read()
2438 stripped = msg.strip()
2439 if not stripped:
2440 # eof, so quit this handler
2441 self.running = False
2442 try:
2443 self.sock = self.sslconn.unwrap()
2444 except OSError:
2445 # Many tests shut the TCP connection down
2446 # without an SSL shutdown. This causes
2447 # unwrap() to raise OSError with errno=0!
2448 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002449 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002450 self.sslconn = None
2451 self.close()
2452 elif stripped == b'over':
2453 if support.verbose and self.server.connectionchatty:
2454 sys.stdout.write(" server: client closed connection\n")
2455 self.close()
2456 return
2457 elif (self.server.starttls_server and
2458 stripped == b'STARTTLS'):
2459 if support.verbose and self.server.connectionchatty:
2460 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2461 self.write(b"OK\n")
2462 if not self.wrap_conn():
2463 return
2464 elif (self.server.starttls_server and self.sslconn
2465 and stripped == b'ENDTLS'):
2466 if support.verbose and self.server.connectionchatty:
2467 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2468 self.write(b"OK\n")
2469 self.sock = self.sslconn.unwrap()
2470 self.sslconn = None
2471 if support.verbose and self.server.connectionchatty:
2472 sys.stdout.write(" server: connection is now unencrypted...\n")
2473 elif stripped == b'CB tls-unique':
2474 if support.verbose and self.server.connectionchatty:
2475 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2476 data = self.sslconn.get_channel_binding("tls-unique")
2477 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002478 elif stripped == b'PHA':
2479 if support.verbose and self.server.connectionchatty:
2480 sys.stdout.write(" server: initiating post handshake auth\n")
2481 try:
2482 self.sslconn.verify_client_post_handshake()
2483 except ssl.SSLError as e:
2484 self.write(repr(e).encode("us-ascii") + b"\n")
2485 else:
2486 self.write(b"OK\n")
2487 elif stripped == b'HASCERT':
2488 if self.sslconn.getpeercert() is not None:
2489 self.write(b'TRUE\n')
2490 else:
2491 self.write(b'FALSE\n')
2492 elif stripped == b'GETCERT':
2493 cert = self.sslconn.getpeercert()
2494 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002495 else:
2496 if (support.verbose and
2497 self.server.connectionchatty):
2498 ctype = (self.sslconn and "encrypted") or "unencrypted"
2499 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2500 % (msg, ctype, msg.lower(), ctype))
2501 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002502 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002503 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2504 # when connection is not shut down gracefully.
2505 if self.server.chatty and support.verbose:
2506 sys.stdout.write(
2507 " Connection reset by peer: {}\n".format(
2508 self.addr)
2509 )
2510 self.close()
2511 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002512 except ssl.SSLError as err:
2513 # On Windows sometimes test_pha_required_nocert receives the
2514 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2515 # before the 'tlsv13 alert certificate required' exception.
2516 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2517 # is received test_pha_required_nocert fails with ConnectionResetError
2518 # because the underlying socket is closed
2519 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2520 if self.server.chatty and support.verbose:
2521 sys.stdout.write(err.args[1])
2522 # test_pha_required_nocert is expecting this exception
2523 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002524 except OSError:
2525 if self.server.chatty:
2526 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002527 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002528 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002529
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002530 # normally, we'd just stop here, but for the test
2531 # harness, we want to stop the server
2532 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002533
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002534 def __init__(self, certificate=None, ssl_version=None,
2535 certreqs=None, cacerts=None,
2536 chatty=True, connectionchatty=False, starttls_server=False,
2537 npn_protocols=None, alpn_protocols=None,
2538 ciphers=None, context=None):
2539 if context:
2540 self.context = context
2541 else:
2542 self.context = ssl.SSLContext(ssl_version
2543 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002544 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002545 self.context.verify_mode = (certreqs if certreqs is not None
2546 else ssl.CERT_NONE)
2547 if cacerts:
2548 self.context.load_verify_locations(cacerts)
2549 if certificate:
2550 self.context.load_cert_chain(certificate)
2551 if npn_protocols:
2552 self.context.set_npn_protocols(npn_protocols)
2553 if alpn_protocols:
2554 self.context.set_alpn_protocols(alpn_protocols)
2555 if ciphers:
2556 self.context.set_ciphers(ciphers)
2557 self.chatty = chatty
2558 self.connectionchatty = connectionchatty
2559 self.starttls_server = starttls_server
2560 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002561 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002562 self.flag = None
2563 self.active = False
2564 self.selected_npn_protocols = []
2565 self.selected_alpn_protocols = []
2566 self.shared_ciphers = []
2567 self.conn_errors = []
2568 threading.Thread.__init__(self)
2569 self.daemon = True
2570
2571 def __enter__(self):
2572 self.start(threading.Event())
2573 self.flag.wait()
2574 return self
2575
2576 def __exit__(self, *args):
2577 self.stop()
2578 self.join()
2579
2580 def start(self, flag=None):
2581 self.flag = flag
2582 threading.Thread.start(self)
2583
2584 def run(self):
2585 self.sock.settimeout(0.05)
2586 self.sock.listen()
2587 self.active = True
2588 if self.flag:
2589 # signal an event
2590 self.flag.set()
2591 while self.active:
2592 try:
2593 newconn, connaddr = self.sock.accept()
2594 if support.verbose and self.chatty:
2595 sys.stdout.write(' server: new connection from '
2596 + repr(connaddr) + '\n')
2597 handler = self.ConnectionHandler(self, newconn, connaddr)
2598 handler.start()
2599 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002600 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002601 pass
2602 except KeyboardInterrupt:
2603 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002604 except BaseException as e:
2605 if support.verbose and self.chatty:
2606 sys.stdout.write(
2607 ' connection handling failed: ' + repr(e) + '\n')
2608
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002609 self.sock.close()
2610
2611 def stop(self):
2612 self.active = False
2613
2614class AsyncoreEchoServer(threading.Thread):
2615
2616 # this one's based on asyncore.dispatcher
2617
2618 class EchoServer (asyncore.dispatcher):
2619
2620 class ConnectionHandler(asyncore.dispatcher_with_send):
2621
2622 def __init__(self, conn, certfile):
2623 self.socket = test_wrap_socket(conn, server_side=True,
2624 certfile=certfile,
2625 do_handshake_on_connect=False)
2626 asyncore.dispatcher_with_send.__init__(self, self.socket)
2627 self._ssl_accepting = True
2628 self._do_ssl_handshake()
2629
2630 def readable(self):
2631 if isinstance(self.socket, ssl.SSLSocket):
2632 while self.socket.pending() > 0:
2633 self.handle_read_event()
2634 return True
2635
2636 def _do_ssl_handshake(self):
2637 try:
2638 self.socket.do_handshake()
2639 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2640 return
2641 except ssl.SSLEOFError:
2642 return self.handle_close()
2643 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002644 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002645 except OSError as err:
2646 if err.args[0] == errno.ECONNABORTED:
2647 return self.handle_close()
2648 else:
2649 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002650
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002651 def handle_read(self):
2652 if self._ssl_accepting:
2653 self._do_ssl_handshake()
2654 else:
2655 data = self.recv(1024)
2656 if support.verbose:
2657 sys.stdout.write(" server: read %s from client\n" % repr(data))
2658 if not data:
2659 self.close()
2660 else:
2661 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002662
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002663 def handle_close(self):
2664 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002665 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002666 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002667
2668 def handle_error(self):
2669 raise
2670
Trent Nelson78520002008-04-10 20:54:35 +00002671 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002672 self.certfile = certfile
2673 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002674 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002675 asyncore.dispatcher.__init__(self, sock)
2676 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002677
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002678 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002679 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002680 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2681 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002682
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002683 def handle_error(self):
2684 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002685
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002686 def __init__(self, certfile):
2687 self.flag = None
2688 self.active = False
2689 self.server = self.EchoServer(certfile)
2690 self.port = self.server.port
2691 threading.Thread.__init__(self)
2692 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002693
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002694 def __str__(self):
2695 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002696
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002697 def __enter__(self):
2698 self.start(threading.Event())
2699 self.flag.wait()
2700 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002701
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002702 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002703 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002704 sys.stdout.write(" cleanup: stopping server.\n")
2705 self.stop()
2706 if support.verbose:
2707 sys.stdout.write(" cleanup: joining server thread.\n")
2708 self.join()
2709 if support.verbose:
2710 sys.stdout.write(" cleanup: successfully joined.\n")
2711 # make sure that ConnectionHandler is removed from socket_map
2712 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002713
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002714 def start (self, flag=None):
2715 self.flag = flag
2716 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002717
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002718 def run(self):
2719 self.active = True
2720 if self.flag:
2721 self.flag.set()
2722 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002723 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002724 asyncore.loop(1)
2725 except:
2726 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002727
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002728 def stop(self):
2729 self.active = False
2730 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002731
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002732def server_params_test(client_context, server_context, indata=b"FOO\n",
2733 chatty=True, connectionchatty=False, sni_name=None,
2734 session=None):
2735 """
2736 Launch a server, connect a client to it and try various reads
2737 and writes.
2738 """
2739 stats = {}
2740 server = ThreadedEchoServer(context=server_context,
2741 chatty=chatty,
2742 connectionchatty=False)
2743 with server:
2744 with client_context.wrap_socket(socket.socket(),
2745 server_hostname=sni_name, session=session) as s:
2746 s.connect((HOST, server.port))
2747 for arg in [indata, bytearray(indata), memoryview(indata)]:
2748 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002749 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002750 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002751 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002752 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002753 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002754 if connectionchatty:
2755 if support.verbose:
2756 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002757 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002758 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002759 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2760 % (outdata[:20], len(outdata),
2761 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002762 s.write(b"over\n")
2763 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002764 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002765 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002766 stats.update({
2767 'compression': s.compression(),
2768 'cipher': s.cipher(),
2769 'peercert': s.getpeercert(),
2770 'client_alpn_protocol': s.selected_alpn_protocol(),
2771 'client_npn_protocol': s.selected_npn_protocol(),
2772 'version': s.version(),
2773 'session_reused': s.session_reused,
2774 'session': s.session,
2775 })
2776 s.close()
2777 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2778 stats['server_npn_protocols'] = server.selected_npn_protocols
2779 stats['server_shared_ciphers'] = server.shared_ciphers
2780 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002781
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002782def try_protocol_combo(server_protocol, client_protocol, expect_success,
2783 certsreqs=None, server_options=0, client_options=0):
2784 """
2785 Try to SSL-connect using *client_protocol* to *server_protocol*.
2786 If *expect_success* is true, assert that the connection succeeds,
2787 if it's false, assert that the connection fails.
2788 Also, if *expect_success* is a string, assert that it is the protocol
2789 version actually used by the connection.
2790 """
2791 if certsreqs is None:
2792 certsreqs = ssl.CERT_NONE
2793 certtype = {
2794 ssl.CERT_NONE: "CERT_NONE",
2795 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2796 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2797 }[certsreqs]
2798 if support.verbose:
2799 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2800 sys.stdout.write(formatstr %
2801 (ssl.get_protocol_name(client_protocol),
2802 ssl.get_protocol_name(server_protocol),
2803 certtype))
2804 client_context = ssl.SSLContext(client_protocol)
2805 client_context.options |= client_options
2806 server_context = ssl.SSLContext(server_protocol)
2807 server_context.options |= server_options
2808
Victor Stinner3ef63442019-02-19 18:06:03 +01002809 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2810 if (min_version is not None
2811 # SSLContext.minimum_version is only available on recent OpenSSL
2812 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2813 and hasattr(server_context, 'minimum_version')
2814 and server_protocol == ssl.PROTOCOL_TLS
2815 and server_context.minimum_version > min_version):
2816 # If OpenSSL configuration is strict and requires more recent TLS
2817 # version, we have to change the minimum to test old TLS versions.
2818 server_context.minimum_version = min_version
2819
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002820 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2821 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2822 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002823 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002824 client_context.set_ciphers("ALL")
2825
Christian Heimesf6c6b582021-03-18 23:06:50 +01002826 seclevel_workaround(server_context, client_context)
2827
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002828 for ctx in (client_context, server_context):
2829 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002830 ctx.load_cert_chain(SIGNED_CERTFILE)
2831 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002832 try:
2833 stats = server_params_test(client_context, server_context,
2834 chatty=False, connectionchatty=False)
2835 # Protocol mismatch can result in either an SSLError, or a
2836 # "Connection reset by peer" error.
2837 except ssl.SSLError:
2838 if expect_success:
2839 raise
2840 except OSError as e:
2841 if expect_success or e.errno != errno.ECONNRESET:
2842 raise
2843 else:
2844 if not expect_success:
2845 raise AssertionError(
2846 "Client protocol %s succeeded with server protocol %s!"
2847 % (ssl.get_protocol_name(client_protocol),
2848 ssl.get_protocol_name(server_protocol)))
2849 elif (expect_success is not True
2850 and expect_success != stats['version']):
2851 raise AssertionError("version mismatch: expected %r, got %r"
2852 % (expect_success, stats['version']))
2853
2854
2855class ThreadedTests(unittest.TestCase):
2856
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002857 def test_echo(self):
2858 """Basic test of an SSL client connecting to a server"""
2859 if support.verbose:
2860 sys.stdout.write("\n")
2861 for protocol in PROTOCOLS:
2862 if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
2863 continue
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02002864 if not has_tls_protocol(protocol):
2865 continue
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002866 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2867 context = ssl.SSLContext(protocol)
2868 context.load_cert_chain(CERTFILE)
Christian Heimesf6c6b582021-03-18 23:06:50 +01002869 seclevel_workaround(context)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002870 server_params_test(context, context,
2871 chatty=True, connectionchatty=True)
2872
Christian Heimesa170fa12017-09-15 20:27:30 +02002873 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002874
2875 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2876 server_params_test(client_context=client_context,
2877 server_context=server_context,
2878 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002879 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002880
2881 client_context.check_hostname = False
2882 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2883 with self.assertRaises(ssl.SSLError) as e:
2884 server_params_test(client_context=server_context,
2885 server_context=client_context,
2886 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002887 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002888 self.assertIn('called a function you should not call',
2889 str(e.exception))
2890
2891 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2892 with self.assertRaises(ssl.SSLError) as e:
2893 server_params_test(client_context=server_context,
2894 server_context=server_context,
2895 chatty=True, connectionchatty=True)
2896 self.assertIn('called a function you should not call',
2897 str(e.exception))
2898
2899 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, 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)
2904 self.assertIn('called a function you should not call',
2905 str(e.exception))
2906
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002907 def test_getpeercert(self):
2908 if support.verbose:
2909 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002910
2911 client_context, server_context, hostname = testing_context()
2912 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002913 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002914 with client_context.wrap_socket(socket.socket(),
2915 do_handshake_on_connect=False,
2916 server_hostname=hostname) as s:
2917 s.connect((HOST, server.port))
2918 # getpeercert() raise ValueError while the handshake isn't
2919 # done.
2920 with self.assertRaises(ValueError):
2921 s.getpeercert()
2922 s.do_handshake()
2923 cert = s.getpeercert()
2924 self.assertTrue(cert, "Can't get peer certificate.")
2925 cipher = s.cipher()
2926 if support.verbose:
2927 sys.stdout.write(pprint.pformat(cert) + '\n')
2928 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2929 if 'subject' not in cert:
2930 self.fail("No subject field in certificate: %s." %
2931 pprint.pformat(cert))
2932 if ((('organizationName', 'Python Software Foundation'),)
2933 not in cert['subject']):
2934 self.fail(
2935 "Missing or invalid 'organizationName' field in certificate subject; "
2936 "should be 'Python Software Foundation'.")
2937 self.assertIn('notBefore', cert)
2938 self.assertIn('notAfter', cert)
2939 before = ssl.cert_time_to_seconds(cert['notBefore'])
2940 after = ssl.cert_time_to_seconds(cert['notAfter'])
2941 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002942
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002943 @unittest.skipUnless(have_verify_flags(),
2944 "verify_flags need OpenSSL > 0.9.8")
2945 def test_crl_check(self):
2946 if support.verbose:
2947 sys.stdout.write("\n")
2948
Christian Heimesa170fa12017-09-15 20:27:30 +02002949 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002950
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002951 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002952 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002953
2954 # VERIFY_DEFAULT should pass
2955 server = ThreadedEchoServer(context=server_context, chatty=True)
2956 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002957 with client_context.wrap_socket(socket.socket(),
2958 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002959 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002960 cert = s.getpeercert()
2961 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002962
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002963 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002964 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002965
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002966 server = ThreadedEchoServer(context=server_context, chatty=True)
2967 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002968 with client_context.wrap_socket(socket.socket(),
2969 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002970 with self.assertRaisesRegex(ssl.SSLError,
2971 "certificate verify failed"):
2972 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002973
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002974 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002975 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002976
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002977 server = ThreadedEchoServer(context=server_context, chatty=True)
2978 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002979 with client_context.wrap_socket(socket.socket(),
2980 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002981 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002982 cert = s.getpeercert()
2983 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002984
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002985 def test_check_hostname(self):
2986 if support.verbose:
2987 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002988
Christian Heimesa170fa12017-09-15 20:27:30 +02002989 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002990
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002991 # correct hostname should verify
2992 server = ThreadedEchoServer(context=server_context, chatty=True)
2993 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002994 with client_context.wrap_socket(socket.socket(),
2995 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002996 s.connect((HOST, server.port))
2997 cert = s.getpeercert()
2998 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002999
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003000 # incorrect hostname should raise an exception
3001 server = ThreadedEchoServer(context=server_context, chatty=True)
3002 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003003 with client_context.wrap_socket(socket.socket(),
3004 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01003005 with self.assertRaisesRegex(
3006 ssl.CertificateError,
3007 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003008 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003009
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003010 # missing server_hostname arg should cause an exception, too
3011 server = ThreadedEchoServer(context=server_context, chatty=True)
3012 with server:
3013 with socket.socket() as s:
3014 with self.assertRaisesRegex(ValueError,
3015 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02003016 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003017
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003018 def test_ecc_cert(self):
3019 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3020 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003021 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003022 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3023
3024 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3025 # load ECC cert
3026 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3027
3028 # correct hostname should verify
3029 server = ThreadedEchoServer(context=server_context, chatty=True)
3030 with server:
3031 with client_context.wrap_socket(socket.socket(),
3032 server_hostname=hostname) as s:
3033 s.connect((HOST, server.port))
3034 cert = s.getpeercert()
3035 self.assertTrue(cert, "Can't get peer certificate.")
3036 cipher = s.cipher()[0].split('-')
3037 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3038
3039 def test_dual_rsa_ecc(self):
3040 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3041 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003042 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3043 # algorithms.
3044 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003045 # only ECDSA certs
3046 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3047 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3048
3049 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3050 # load ECC and RSA key/cert pairs
3051 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3052 server_context.load_cert_chain(SIGNED_CERTFILE)
3053
3054 # correct hostname should verify
3055 server = ThreadedEchoServer(context=server_context, chatty=True)
3056 with server:
3057 with client_context.wrap_socket(socket.socket(),
3058 server_hostname=hostname) as s:
3059 s.connect((HOST, server.port))
3060 cert = s.getpeercert()
3061 self.assertTrue(cert, "Can't get peer certificate.")
3062 cipher = s.cipher()[0].split('-')
3063 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3064
Christian Heimes66e57422018-01-29 14:25:13 +01003065 def test_check_hostname_idn(self):
3066 if support.verbose:
3067 sys.stdout.write("\n")
3068
Christian Heimes11a14932018-02-24 02:35:08 +01003069 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003070 server_context.load_cert_chain(IDNSANSFILE)
3071
Christian Heimes11a14932018-02-24 02:35:08 +01003072 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003073 context.verify_mode = ssl.CERT_REQUIRED
3074 context.check_hostname = True
3075 context.load_verify_locations(SIGNING_CA)
3076
3077 # correct hostname should verify, when specified in several
3078 # different ways
3079 idn_hostnames = [
3080 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003081 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003082 ('xn--knig-5qa.idn.pythontest.net',
3083 'xn--knig-5qa.idn.pythontest.net'),
3084 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003085 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003086
3087 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003088 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003089 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3090 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3091 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003092 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3093
3094 # ('königsgäßchen.idna2008.pythontest.net',
3095 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3096 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3097 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3098 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3099 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3100
Christian Heimes66e57422018-01-29 14:25:13 +01003101 ]
3102 for server_hostname, expected_hostname in idn_hostnames:
3103 server = ThreadedEchoServer(context=server_context, chatty=True)
3104 with server:
3105 with context.wrap_socket(socket.socket(),
3106 server_hostname=server_hostname) as s:
3107 self.assertEqual(s.server_hostname, expected_hostname)
3108 s.connect((HOST, server.port))
3109 cert = s.getpeercert()
3110 self.assertEqual(s.server_hostname, expected_hostname)
3111 self.assertTrue(cert, "Can't get peer certificate.")
3112
Christian Heimes66e57422018-01-29 14:25:13 +01003113 # incorrect hostname should raise an exception
3114 server = ThreadedEchoServer(context=server_context, chatty=True)
3115 with server:
3116 with context.wrap_socket(socket.socket(),
3117 server_hostname="python.example.org") as s:
3118 with self.assertRaises(ssl.CertificateError):
3119 s.connect((HOST, server.port))
3120
Christian Heimes529525f2018-05-23 22:24:45 +02003121 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003122 """Connecting when the server rejects the client's certificate
3123
3124 Launch a server with CERT_REQUIRED, and check that trying to
3125 connect to it with a wrong client certificate fails.
3126 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003127 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003128 # load client cert that is not signed by trusted CA
3129 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003130 # require TLS client authentication
3131 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003132 # TLS 1.3 has different handshake
3133 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003134
3135 server = ThreadedEchoServer(
3136 context=server_context, chatty=True, connectionchatty=True,
3137 )
3138
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003139 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003140 client_context.wrap_socket(socket.socket(),
3141 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003142 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003143 # Expect either an SSL error about the server rejecting
3144 # the connection, or a low-level connection reset (which
3145 # sometimes happens on Windows)
3146 s.connect((HOST, server.port))
3147 except ssl.SSLError as e:
3148 if support.verbose:
3149 sys.stdout.write("\nSSLError is %r\n" % e)
3150 except OSError as e:
3151 if e.errno != errno.ECONNRESET:
3152 raise
3153 if support.verbose:
3154 sys.stdout.write("\nsocket.error is %r\n" % e)
3155 else:
3156 self.fail("Use of invalid cert should have failed!")
3157
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003158 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003159 def test_wrong_cert_tls13(self):
3160 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003161 # load client cert that is not signed by trusted CA
3162 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003163 server_context.verify_mode = ssl.CERT_REQUIRED
3164 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3165 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3166
3167 server = ThreadedEchoServer(
3168 context=server_context, chatty=True, connectionchatty=True,
3169 )
3170 with server, \
3171 client_context.wrap_socket(socket.socket(),
3172 server_hostname=hostname) as s:
3173 # TLS 1.3 perform client cert exchange after handshake
3174 s.connect((HOST, server.port))
3175 try:
3176 s.write(b'data')
3177 s.read(4)
3178 except ssl.SSLError as e:
3179 if support.verbose:
3180 sys.stdout.write("\nSSLError is %r\n" % e)
3181 except OSError as e:
3182 if e.errno != errno.ECONNRESET:
3183 raise
3184 if support.verbose:
3185 sys.stdout.write("\nsocket.error is %r\n" % e)
3186 else:
3187 self.fail("Use of invalid cert should have failed!")
3188
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003189 def test_rude_shutdown(self):
3190 """A brutal shutdown of an SSL server should raise an OSError
3191 in the client when attempting handshake.
3192 """
3193 listener_ready = threading.Event()
3194 listener_gone = threading.Event()
3195
3196 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003197 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003198
3199 # `listener` runs in a thread. It sits in an accept() until
3200 # the main thread connects. Then it rudely closes the socket,
3201 # and sets Event `listener_gone` to let the main thread know
3202 # the socket is gone.
3203 def listener():
3204 s.listen()
3205 listener_ready.set()
3206 newsock, addr = s.accept()
3207 newsock.close()
3208 s.close()
3209 listener_gone.set()
3210
3211 def connector():
3212 listener_ready.wait()
3213 with socket.socket() as c:
3214 c.connect((HOST, port))
3215 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003216 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003217 ssl_sock = test_wrap_socket(c)
3218 except OSError:
3219 pass
3220 else:
3221 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003222
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003223 t = threading.Thread(target=listener)
3224 t.start()
3225 try:
3226 connector()
3227 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003228 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003229
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003230 def test_ssl_cert_verify_error(self):
3231 if support.verbose:
3232 sys.stdout.write("\n")
3233
3234 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3235 server_context.load_cert_chain(SIGNED_CERTFILE)
3236
3237 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3238
3239 server = ThreadedEchoServer(context=server_context, chatty=True)
3240 with server:
3241 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003242 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003243 try:
3244 s.connect((HOST, server.port))
3245 except ssl.SSLError as e:
3246 msg = 'unable to get local issuer certificate'
3247 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3248 self.assertEqual(e.verify_code, 20)
3249 self.assertEqual(e.verify_message, msg)
3250 self.assertIn(msg, repr(e))
3251 self.assertIn('certificate verify failed', repr(e))
3252
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003253 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003254 def test_protocol_sslv2(self):
3255 """Connecting to an SSLv2 server with various client options"""
3256 if support.verbose:
3257 sys.stdout.write("\n")
3258 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3259 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3260 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003261 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003262 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003263 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3264 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3265 # SSLv23 client with specific SSL options
3266 if no_sslv2_implies_sslv3_hello():
3267 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003268 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003269 client_options=ssl.OP_NO_SSLv2)
Christian Heimesa170fa12017-09-15 20:27:30 +02003270 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003271 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003272 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003273 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003274
Christian Heimesa170fa12017-09-15 20:27:30 +02003275 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003276 """Connecting to an SSLv23 server with various client options"""
3277 if support.verbose:
3278 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003279 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003280 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003281 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003282 except OSError as x:
3283 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3284 if support.verbose:
3285 sys.stdout.write(
3286 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3287 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003288 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003289 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3290 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003291 if has_tls_version('TLSv1'):
3292 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003293
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003294 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003295 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3296 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003297 if has_tls_version('TLSv1'):
3298 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003299
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003300 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003301 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3302 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003303 if has_tls_version('TLSv1'):
3304 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003305
3306 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003307 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003308 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003309 server_options=ssl.OP_NO_SSLv3)
3310 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003311 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003312 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003313 if has_tls_version('TLSv1'):
3314 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3315 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003316
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003317 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003318 def test_protocol_sslv3(self):
3319 """Connecting to an SSLv3 server with various client options"""
3320 if support.verbose:
3321 sys.stdout.write("\n")
3322 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3323 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3324 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003325 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003326 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003327 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003328 client_options=ssl.OP_NO_SSLv3)
3329 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3330 if no_sslv2_implies_sslv3_hello():
3331 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003332 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003333 False, client_options=ssl.OP_NO_SSLv2)
3334
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003335 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003336 def test_protocol_tlsv1(self):
3337 """Connecting to a TLSv1 server with various client options"""
3338 if support.verbose:
3339 sys.stdout.write("\n")
3340 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3341 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3342 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003343 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003344 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003345 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003346 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003347 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003348 client_options=ssl.OP_NO_TLSv1)
3349
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003350 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003351 def test_protocol_tlsv1_1(self):
3352 """Connecting to a TLSv1.1 server with various client options.
3353 Testing against older TLS versions."""
3354 if support.verbose:
3355 sys.stdout.write("\n")
3356 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003357 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003358 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003359 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003360 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003361 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003362 client_options=ssl.OP_NO_TLSv1_1)
3363
Christian Heimesa170fa12017-09-15 20:27:30 +02003364 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003365 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3366 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003367
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003368 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003369 def test_protocol_tlsv1_2(self):
3370 """Connecting to a TLSv1.2 server with various client options.
3371 Testing against older TLS versions."""
3372 if support.verbose:
3373 sys.stdout.write("\n")
3374 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3375 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3376 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003377 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003378 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003379 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003380 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003381 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003382 client_options=ssl.OP_NO_TLSv1_2)
3383
Christian Heimesa170fa12017-09-15 20:27:30 +02003384 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003385 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3386 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3387 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3388 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3389
3390 def test_starttls(self):
3391 """Switching from clear text to encrypted and back again."""
3392 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3393
3394 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003395 starttls_server=True,
3396 chatty=True,
3397 connectionchatty=True)
3398 wrapped = False
3399 with server:
3400 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003401 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003402 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003403 if support.verbose:
3404 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003405 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003406 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003407 sys.stdout.write(
3408 " client: sending %r...\n" % indata)
3409 if wrapped:
3410 conn.write(indata)
3411 outdata = conn.read()
3412 else:
3413 s.send(indata)
3414 outdata = s.recv(1024)
3415 msg = outdata.strip().lower()
3416 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3417 # STARTTLS ok, switch to secure mode
3418 if support.verbose:
3419 sys.stdout.write(
3420 " client: read %r from server, starting TLS...\n"
3421 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003422 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003423 wrapped = True
3424 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3425 # ENDTLS ok, switch back to clear text
3426 if support.verbose:
3427 sys.stdout.write(
3428 " client: read %r from server, ending TLS...\n"
3429 % msg)
3430 s = conn.unwrap()
3431 wrapped = False
3432 else:
3433 if support.verbose:
3434 sys.stdout.write(
3435 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003436 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003437 sys.stdout.write(" client: closing connection.\n")
3438 if wrapped:
3439 conn.write(b"over\n")
3440 else:
3441 s.send(b"over\n")
3442 if wrapped:
3443 conn.close()
3444 else:
3445 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003446
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003447 def test_socketserver(self):
3448 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003449 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003450 # try to connect
3451 if support.verbose:
3452 sys.stdout.write('\n')
3453 with open(CERTFILE, 'rb') as f:
3454 d1 = f.read()
3455 d2 = ''
3456 # now fetch the same data from the HTTPS server
3457 url = 'https://localhost:%d/%s' % (
3458 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003459 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003460 f = urllib.request.urlopen(url, context=context)
3461 try:
3462 dlen = f.info().get("content-length")
3463 if dlen and (int(dlen) > 0):
3464 d2 = f.read(int(dlen))
3465 if support.verbose:
3466 sys.stdout.write(
3467 " client: read %d bytes from remote server '%s'\n"
3468 % (len(d2), server))
3469 finally:
3470 f.close()
3471 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003472
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003473 def test_asyncore_server(self):
3474 """Check the example asyncore integration."""
3475 if support.verbose:
3476 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003477
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003478 indata = b"FOO\n"
3479 server = AsyncoreEchoServer(CERTFILE)
3480 with server:
3481 s = test_wrap_socket(socket.socket())
3482 s.connect(('127.0.0.1', server.port))
3483 if support.verbose:
3484 sys.stdout.write(
3485 " client: sending %r...\n" % indata)
3486 s.write(indata)
3487 outdata = s.read()
3488 if support.verbose:
3489 sys.stdout.write(" client: read %r\n" % outdata)
3490 if outdata != indata.lower():
3491 self.fail(
3492 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3493 % (outdata[:20], len(outdata),
3494 indata[:20].lower(), len(indata)))
3495 s.write(b"over\n")
3496 if support.verbose:
3497 sys.stdout.write(" client: closing connection.\n")
3498 s.close()
3499 if support.verbose:
3500 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003501
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003502 def test_recv_send(self):
3503 """Test recv(), send() and friends."""
3504 if support.verbose:
3505 sys.stdout.write("\n")
3506
3507 server = ThreadedEchoServer(CERTFILE,
3508 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003509 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003510 cacerts=CERTFILE,
3511 chatty=True,
3512 connectionchatty=False)
3513 with server:
3514 s = test_wrap_socket(socket.socket(),
3515 server_side=False,
3516 certfile=CERTFILE,
3517 ca_certs=CERTFILE,
3518 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003519 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003520 s.connect((HOST, server.port))
3521 # helper methods for standardising recv* method signatures
3522 def _recv_into():
3523 b = bytearray(b"\0"*100)
3524 count = s.recv_into(b)
3525 return b[:count]
3526
3527 def _recvfrom_into():
3528 b = bytearray(b"\0"*100)
3529 count, addr = s.recvfrom_into(b)
3530 return b[:count]
3531
3532 # (name, method, expect success?, *args, return value func)
3533 send_methods = [
3534 ('send', s.send, True, [], len),
3535 ('sendto', s.sendto, False, ["some.address"], len),
3536 ('sendall', s.sendall, True, [], lambda x: None),
3537 ]
3538 # (name, method, whether to expect success, *args)
3539 recv_methods = [
3540 ('recv', s.recv, True, []),
3541 ('recvfrom', s.recvfrom, False, ["some.address"]),
3542 ('recv_into', _recv_into, True, []),
3543 ('recvfrom_into', _recvfrom_into, False, []),
3544 ]
3545 data_prefix = "PREFIX_"
3546
3547 for (meth_name, send_meth, expect_success, args,
3548 ret_val_meth) in send_methods:
3549 indata = (data_prefix + meth_name).encode('ascii')
3550 try:
3551 ret = send_meth(indata, *args)
3552 msg = "sending with {}".format(meth_name)
3553 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3554 outdata = s.read()
3555 if outdata != indata.lower():
3556 self.fail(
3557 "While sending with <<{name:s}>> bad data "
3558 "<<{outdata:r}>> ({nout:d}) received; "
3559 "expected <<{indata:r}>> ({nin:d})\n".format(
3560 name=meth_name, outdata=outdata[:20],
3561 nout=len(outdata),
3562 indata=indata[:20], nin=len(indata)
3563 )
3564 )
3565 except ValueError as e:
3566 if expect_success:
3567 self.fail(
3568 "Failed to send with method <<{name:s}>>; "
3569 "expected to succeed.\n".format(name=meth_name)
3570 )
3571 if not str(e).startswith(meth_name):
3572 self.fail(
3573 "Method <<{name:s}>> failed with unexpected "
3574 "exception message: {exp:s}\n".format(
3575 name=meth_name, exp=e
3576 )
3577 )
3578
3579 for meth_name, recv_meth, expect_success, args in recv_methods:
3580 indata = (data_prefix + meth_name).encode('ascii')
3581 try:
3582 s.send(indata)
3583 outdata = recv_meth(*args)
3584 if outdata != indata.lower():
3585 self.fail(
3586 "While receiving with <<{name:s}>> bad data "
3587 "<<{outdata:r}>> ({nout:d}) received; "
3588 "expected <<{indata:r}>> ({nin:d})\n".format(
3589 name=meth_name, outdata=outdata[:20],
3590 nout=len(outdata),
3591 indata=indata[:20], nin=len(indata)
3592 )
3593 )
3594 except ValueError as e:
3595 if expect_success:
3596 self.fail(
3597 "Failed to receive with method <<{name:s}>>; "
3598 "expected to succeed.\n".format(name=meth_name)
3599 )
3600 if not str(e).startswith(meth_name):
3601 self.fail(
3602 "Method <<{name:s}>> failed with unexpected "
3603 "exception message: {exp:s}\n".format(
3604 name=meth_name, exp=e
3605 )
3606 )
3607 # consume data
3608 s.read()
3609
3610 # read(-1, buffer) is supported, even though read(-1) is not
3611 data = b"data"
3612 s.send(data)
3613 buffer = bytearray(len(data))
3614 self.assertEqual(s.read(-1, buffer), len(data))
3615 self.assertEqual(buffer, data)
3616
Christian Heimes888bbdc2017-09-07 14:18:21 -07003617 # sendall accepts bytes-like objects
3618 if ctypes is not None:
3619 ubyte = ctypes.c_ubyte * len(data)
3620 byteslike = ubyte.from_buffer_copy(data)
3621 s.sendall(byteslike)
3622 self.assertEqual(s.read(), data)
3623
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003624 # Make sure sendmsg et al are disallowed to avoid
3625 # inadvertent disclosure of data and/or corruption
3626 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003627 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003628 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3629 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3630 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003631 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003632 s.write(b"over\n")
3633
3634 self.assertRaises(ValueError, s.recv, -1)
3635 self.assertRaises(ValueError, s.read, -1)
3636
3637 s.close()
3638
3639 def test_recv_zero(self):
3640 server = ThreadedEchoServer(CERTFILE)
3641 server.__enter__()
3642 self.addCleanup(server.__exit__, None, None)
3643 s = socket.create_connection((HOST, server.port))
3644 self.addCleanup(s.close)
3645 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3646 self.addCleanup(s.close)
3647
3648 # recv/read(0) should return no data
3649 s.send(b"data")
3650 self.assertEqual(s.recv(0), b"")
3651 self.assertEqual(s.read(0), b"")
3652 self.assertEqual(s.read(), b"data")
3653
3654 # Should not block if the other end sends no data
3655 s.setblocking(False)
3656 self.assertEqual(s.recv(0), b"")
3657 self.assertEqual(s.recv_into(bytearray()), 0)
3658
3659 def test_nonblocking_send(self):
3660 server = ThreadedEchoServer(CERTFILE,
3661 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003662 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003663 cacerts=CERTFILE,
3664 chatty=True,
3665 connectionchatty=False)
3666 with server:
3667 s = test_wrap_socket(socket.socket(),
3668 server_side=False,
3669 certfile=CERTFILE,
3670 ca_certs=CERTFILE,
3671 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003672 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003673 s.connect((HOST, server.port))
3674 s.setblocking(False)
3675
3676 # If we keep sending data, at some point the buffers
3677 # will be full and the call will block
3678 buf = bytearray(8192)
3679 def fill_buffer():
3680 while True:
3681 s.send(buf)
3682 self.assertRaises((ssl.SSLWantWriteError,
3683 ssl.SSLWantReadError), fill_buffer)
3684
3685 # Now read all the output and discard it
3686 s.setblocking(True)
3687 s.close()
3688
3689 def test_handshake_timeout(self):
3690 # Issue #5103: SSL handshake must respect the socket timeout
3691 server = socket.socket(socket.AF_INET)
3692 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003693 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003694 started = threading.Event()
3695 finish = False
3696
3697 def serve():
3698 server.listen()
3699 started.set()
3700 conns = []
3701 while not finish:
3702 r, w, e = select.select([server], [], [], 0.1)
3703 if server in r:
3704 # Let the socket hang around rather than having
3705 # it closed by garbage collection.
3706 conns.append(server.accept()[0])
3707 for sock in conns:
3708 sock.close()
3709
3710 t = threading.Thread(target=serve)
3711 t.start()
3712 started.wait()
3713
3714 try:
3715 try:
3716 c = socket.socket(socket.AF_INET)
3717 c.settimeout(0.2)
3718 c.connect((host, port))
3719 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003720 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003721 test_wrap_socket, c)
3722 finally:
3723 c.close()
3724 try:
3725 c = socket.socket(socket.AF_INET)
3726 c = test_wrap_socket(c)
3727 c.settimeout(0.2)
3728 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003729 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003730 c.connect, (host, port))
3731 finally:
3732 c.close()
3733 finally:
3734 finish = True
3735 t.join()
3736 server.close()
3737
3738 def test_server_accept(self):
3739 # Issue #16357: accept() on a SSLSocket created through
3740 # SSLContext.wrap_socket().
Christian Heimesa170fa12017-09-15 20:27:30 +02003741 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003742 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003743 context.load_verify_locations(SIGNING_CA)
3744 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003745 server = socket.socket(socket.AF_INET)
3746 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003747 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003748 server = context.wrap_socket(server, server_side=True)
3749 self.assertTrue(server.server_side)
3750
3751 evt = threading.Event()
3752 remote = None
3753 peer = None
3754 def serve():
3755 nonlocal remote, peer
3756 server.listen()
3757 # Block on the accept and wait on the connection to close.
3758 evt.set()
3759 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003760 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003761
3762 t = threading.Thread(target=serve)
3763 t.start()
3764 # Client wait until server setup and perform a connect.
3765 evt.wait()
3766 client = context.wrap_socket(socket.socket())
3767 client.connect((host, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003768 client.send(b'data')
3769 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003770 client_addr = client.getsockname()
3771 client.close()
3772 t.join()
3773 remote.close()
3774 server.close()
3775 # Sanity checks.
3776 self.assertIsInstance(remote, ssl.SSLSocket)
3777 self.assertEqual(peer, client_addr)
3778
3779 def test_getpeercert_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003780 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003781 with context.wrap_socket(socket.socket()) as sock:
3782 with self.assertRaises(OSError) as cm:
3783 sock.getpeercert()
3784 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3785
3786 def test_do_handshake_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003787 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003788 with context.wrap_socket(socket.socket()) as sock:
3789 with self.assertRaises(OSError) as cm:
3790 sock.do_handshake()
3791 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3792
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003793 def test_no_shared_ciphers(self):
3794 client_context, server_context, hostname = testing_context()
3795 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3796 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003797 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003798 client_context.set_ciphers("AES128")
3799 server_context.set_ciphers("AES256")
3800 with ThreadedEchoServer(context=server_context) as server:
3801 with client_context.wrap_socket(socket.socket(),
3802 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003803 with self.assertRaises(OSError):
3804 s.connect((HOST, server.port))
3805 self.assertIn("no shared cipher", server.conn_errors[0])
3806
3807 def test_version_basic(self):
3808 """
3809 Basic tests for SSLSocket.version().
3810 More tests are done in the test_protocol_*() methods.
3811 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003812 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3813 context.check_hostname = False
3814 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003815 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003816 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003817 chatty=False) as server:
3818 with context.wrap_socket(socket.socket()) as s:
3819 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003820 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003821 s.connect((HOST, server.port))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003822 if IS_OPENSSL_1_1_1 and has_tls_version('TLSv1_3'):
Christian Heimes05d9fe32018-02-27 08:55:39 +01003823 self.assertEqual(s.version(), 'TLSv1.3')
3824 elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
Christian Heimesa170fa12017-09-15 20:27:30 +02003825 self.assertEqual(s.version(), 'TLSv1.2')
3826 else: # 0.9.8 to 1.0.1
3827 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2'))
Christian Heimes141c5e82018-02-24 21:10:57 +01003828 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003829 self.assertIs(s.version(), None)
3830
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003831 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003832 def test_tls1_3(self):
3833 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
3834 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003835 context.options |= (
3836 ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2
3837 )
3838 with ThreadedEchoServer(context=context) as server:
3839 with context.wrap_socket(socket.socket()) as s:
3840 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003841 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003842 'TLS_AES_256_GCM_SHA384',
3843 'TLS_CHACHA20_POLY1305_SHA256',
3844 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003845 })
3846 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003847
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003848 @requires_minimum_version
3849 @requires_tls_version('TLSv1_2')
3850 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003851 client_context, server_context, hostname = testing_context()
3852 # client TLSv1.0 to 1.2
3853 client_context.minimum_version = ssl.TLSVersion.TLSv1
3854 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3855 # server only TLSv1.2
3856 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3857 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3858
3859 with ThreadedEchoServer(context=server_context) as server:
3860 with client_context.wrap_socket(socket.socket(),
3861 server_hostname=hostname) as s:
3862 s.connect((HOST, server.port))
3863 self.assertEqual(s.version(), 'TLSv1.2')
3864
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003865 @requires_minimum_version
3866 @requires_tls_version('TLSv1_1')
3867 def test_min_max_version_tlsv1_1(self):
3868 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003869 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003870 client_context.minimum_version = ssl.TLSVersion.TLSv1
3871 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003872 server_context.minimum_version = ssl.TLSVersion.TLSv1
3873 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003874 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003875
3876 with ThreadedEchoServer(context=server_context) as server:
3877 with client_context.wrap_socket(socket.socket(),
3878 server_hostname=hostname) as s:
3879 s.connect((HOST, server.port))
3880 self.assertEqual(s.version(), 'TLSv1.1')
3881
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003882 @requires_minimum_version
3883 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003884 @requires_tls_version('TLSv1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003885 def test_min_max_version_mismatch(self):
3886 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003887 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003888 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003889 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003890 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003891 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003892 seclevel_workaround(client_context, server_context)
3893
Christian Heimes698dde12018-02-27 11:54:43 +01003894 with ThreadedEchoServer(context=server_context) as server:
3895 with client_context.wrap_socket(socket.socket(),
3896 server_hostname=hostname) as s:
3897 with self.assertRaises(ssl.SSLError) as e:
3898 s.connect((HOST, server.port))
3899 self.assertIn("alert", str(e.exception))
3900
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003901 @requires_minimum_version
3902 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003903 def test_min_max_version_sslv3(self):
3904 client_context, server_context, hostname = testing_context()
3905 server_context.minimum_version = ssl.TLSVersion.SSLv3
3906 client_context.minimum_version = ssl.TLSVersion.SSLv3
3907 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003908 seclevel_workaround(client_context, server_context)
3909
Christian Heimes698dde12018-02-27 11:54:43 +01003910 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(), 'SSLv3')
3915
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003916 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3917 def test_default_ecdh_curve(self):
3918 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3919 # should be enabled by default on SSL contexts.
Christian Heimesa170fa12017-09-15 20:27:30 +02003920 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003921 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003922 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3923 # cipher name.
3924 context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003925 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3926 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3927 # our default cipher list should prefer ECDH-based ciphers
3928 # automatically.
3929 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
3930 context.set_ciphers("ECCdraft:ECDH")
3931 with ThreadedEchoServer(context=context) as server:
3932 with context.wrap_socket(socket.socket()) as s:
3933 s.connect((HOST, server.port))
3934 self.assertIn("ECDH", s.cipher()[0])
3935
3936 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3937 "'tls-unique' channel binding not available")
3938 def test_tls_unique_channel_binding(self):
3939 """Test tls-unique channel binding."""
3940 if support.verbose:
3941 sys.stdout.write("\n")
3942
Christian Heimes05d9fe32018-02-27 08:55:39 +01003943 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003944
3945 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003946 chatty=True,
3947 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003948
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003949 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003950 with client_context.wrap_socket(
3951 socket.socket(),
3952 server_hostname=hostname) as s:
3953 s.connect((HOST, server.port))
3954 # get the data
3955 cb_data = s.get_channel_binding("tls-unique")
3956 if support.verbose:
3957 sys.stdout.write(
3958 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003959
Christian Heimes05d9fe32018-02-27 08:55:39 +01003960 # check if it is sane
3961 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003962 if s.version() == 'TLSv1.3':
3963 self.assertEqual(len(cb_data), 48)
3964 else:
3965 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003966
Christian Heimes05d9fe32018-02-27 08:55:39 +01003967 # and compare with the peers version
3968 s.write(b"CB tls-unique\n")
3969 peer_data_repr = s.read().strip()
3970 self.assertEqual(peer_data_repr,
3971 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003972
3973 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003974 with client_context.wrap_socket(
3975 socket.socket(),
3976 server_hostname=hostname) as s:
3977 s.connect((HOST, server.port))
3978 new_cb_data = s.get_channel_binding("tls-unique")
3979 if support.verbose:
3980 sys.stdout.write(
3981 "got another channel binding data: {0!r}\n".format(
3982 new_cb_data)
3983 )
3984 # is it really unique
3985 self.assertNotEqual(cb_data, new_cb_data)
3986 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003987 if s.version() == 'TLSv1.3':
3988 self.assertEqual(len(cb_data), 48)
3989 else:
3990 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003991 s.write(b"CB tls-unique\n")
3992 peer_data_repr = s.read().strip()
3993 self.assertEqual(peer_data_repr,
3994 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003995
3996 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003997 client_context, server_context, hostname = testing_context()
3998 stats = server_params_test(client_context, server_context,
3999 chatty=True, connectionchatty=True,
4000 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004001 if support.verbose:
4002 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
4003 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
4004
4005 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
4006 "ssl.OP_NO_COMPRESSION needed for this test")
4007 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004008 client_context, server_context, hostname = testing_context()
4009 client_context.options |= ssl.OP_NO_COMPRESSION
4010 server_context.options |= ssl.OP_NO_COMPRESSION
4011 stats = server_params_test(client_context, server_context,
4012 chatty=True, connectionchatty=True,
4013 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004014 self.assertIs(stats['compression'], None)
4015
Paul Monsonf3550692019-06-19 13:09:54 -07004016 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004017 def test_dh_params(self):
4018 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004019 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004020 # test scenario needs TLS <= 1.2
4021 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004022 server_context.load_dh_params(DHFILE)
4023 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004024 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004025 stats = server_params_test(client_context, server_context,
4026 chatty=True, connectionchatty=True,
4027 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004028 cipher = stats["cipher"][0]
4029 parts = cipher.split("-")
4030 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4031 self.fail("Non-DH cipher: " + cipher[0])
4032
Christian Heimesb7b92252018-02-25 09:49:31 +01004033 @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004034 @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
Christian Heimesb7b92252018-02-25 09:49:31 +01004035 def test_ecdh_curve(self):
4036 # server secp384r1, client auto
4037 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004038
Christian Heimesb7b92252018-02-25 09:49:31 +01004039 server_context.set_ecdh_curve("secp384r1")
4040 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4041 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4042 stats = server_params_test(client_context, server_context,
4043 chatty=True, connectionchatty=True,
4044 sni_name=hostname)
4045
4046 # server auto, client secp384r1
4047 client_context, server_context, hostname = testing_context()
4048 client_context.set_ecdh_curve("secp384r1")
4049 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4050 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4051 stats = server_params_test(client_context, server_context,
4052 chatty=True, connectionchatty=True,
4053 sni_name=hostname)
4054
4055 # server / client curve mismatch
4056 client_context, server_context, hostname = testing_context()
4057 client_context.set_ecdh_curve("prime256v1")
4058 server_context.set_ecdh_curve("secp384r1")
4059 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4060 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4061 try:
4062 stats = server_params_test(client_context, server_context,
4063 chatty=True, connectionchatty=True,
4064 sni_name=hostname)
4065 except ssl.SSLError:
4066 pass
4067 else:
4068 # OpenSSL 1.0.2 does not fail although it should.
Christian Heimes05d9fe32018-02-27 08:55:39 +01004069 if IS_OPENSSL_1_1_0:
Christian Heimesb7b92252018-02-25 09:49:31 +01004070 self.fail("mismatch curve did not fail")
4071
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004072 def test_selected_alpn_protocol(self):
4073 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004074 client_context, server_context, hostname = testing_context()
4075 stats = server_params_test(client_context, server_context,
4076 chatty=True, connectionchatty=True,
4077 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004078 self.assertIs(stats['client_alpn_protocol'], None)
4079
4080 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
4081 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4082 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004083 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004084 server_context.set_alpn_protocols(['foo', 'bar'])
4085 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004086 chatty=True, connectionchatty=True,
4087 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004088 self.assertIs(stats['client_alpn_protocol'], None)
4089
4090 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
4091 def test_alpn_protocols(self):
4092 server_protocols = ['foo', 'bar', 'milkshake']
4093 protocol_tests = [
4094 (['foo', 'bar'], 'foo'),
4095 (['bar', 'foo'], 'foo'),
4096 (['milkshake'], 'milkshake'),
4097 (['http/3.0', 'http/4.0'], None)
4098 ]
4099 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004100 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004101 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004102 client_context.set_alpn_protocols(client_protocols)
4103
4104 try:
4105 stats = server_params_test(client_context,
4106 server_context,
4107 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004108 connectionchatty=True,
4109 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004110 except ssl.SSLError as e:
4111 stats = e
4112
Christian Heimes05d9fe32018-02-27 08:55:39 +01004113 if (expected is None and IS_OPENSSL_1_1_0
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004114 and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)):
4115 # OpenSSL 1.1.0 to 1.1.0e raises handshake error
4116 self.assertIsInstance(stats, ssl.SSLError)
4117 else:
4118 msg = "failed trying %s (s) and %s (c).\n" \
4119 "was expecting %s, but got %%s from the %%s" \
4120 % (str(server_protocols), str(client_protocols),
4121 str(expected))
4122 client_result = stats['client_alpn_protocol']
4123 self.assertEqual(client_result, expected,
4124 msg % (client_result, "client"))
4125 server_result = stats['server_alpn_protocols'][-1] \
4126 if len(stats['server_alpn_protocols']) else 'nothing'
4127 self.assertEqual(server_result, expected,
4128 msg % (server_result, "server"))
4129
4130 def test_selected_npn_protocol(self):
4131 # selected_npn_protocol() is None unless NPN is used
Christian Heimesa170fa12017-09-15 20:27:30 +02004132 client_context, server_context, hostname = testing_context()
4133 stats = server_params_test(client_context, server_context,
4134 chatty=True, connectionchatty=True,
4135 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004136 self.assertIs(stats['client_npn_protocol'], None)
4137
4138 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
4139 def test_npn_protocols(self):
4140 server_protocols = ['http/1.1', 'spdy/2']
4141 protocol_tests = [
4142 (['http/1.1', 'spdy/2'], 'http/1.1'),
4143 (['spdy/2', 'http/1.1'], 'http/1.1'),
4144 (['spdy/2', 'test'], 'spdy/2'),
4145 (['abc', 'def'], 'abc')
4146 ]
4147 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004148 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004149 server_context.set_npn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004150 client_context.set_npn_protocols(client_protocols)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004151 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004152 chatty=True, connectionchatty=True,
4153 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004154 msg = "failed trying %s (s) and %s (c).\n" \
4155 "was expecting %s, but got %%s from the %%s" \
4156 % (str(server_protocols), str(client_protocols),
4157 str(expected))
4158 client_result = stats['client_npn_protocol']
4159 self.assertEqual(client_result, expected, msg % (client_result, "client"))
4160 server_result = stats['server_npn_protocols'][-1] \
4161 if len(stats['server_npn_protocols']) else 'nothing'
4162 self.assertEqual(server_result, expected, msg % (server_result, "server"))
4163
4164 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004165 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004166 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004167 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004168 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004169 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004170 client_context.load_verify_locations(SIGNING_CA)
4171 return server_context, other_context, client_context
4172
4173 def check_common_name(self, stats, name):
4174 cert = stats['peercert']
4175 self.assertIn((('commonName', name),), cert['subject'])
4176
4177 @needs_sni
4178 def test_sni_callback(self):
4179 calls = []
4180 server_context, other_context, client_context = self.sni_contexts()
4181
Christian Heimesa170fa12017-09-15 20:27:30 +02004182 client_context.check_hostname = False
4183
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004184 def servername_cb(ssl_sock, server_name, initial_context):
4185 calls.append((server_name, initial_context))
4186 if server_name is not None:
4187 ssl_sock.context = other_context
4188 server_context.set_servername_callback(servername_cb)
4189
4190 stats = server_params_test(client_context, server_context,
4191 chatty=True,
4192 sni_name='supermessage')
4193 # The hostname was fetched properly, and the certificate was
4194 # changed for the connection.
4195 self.assertEqual(calls, [("supermessage", server_context)])
4196 # CERTFILE4 was selected
4197 self.check_common_name(stats, 'fakehostname')
4198
4199 calls = []
4200 # The callback is called with server_name=None
4201 stats = server_params_test(client_context, server_context,
4202 chatty=True,
4203 sni_name=None)
4204 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004205 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004206
4207 # Check disabling the callback
4208 calls = []
4209 server_context.set_servername_callback(None)
4210
4211 stats = server_params_test(client_context, server_context,
4212 chatty=True,
4213 sni_name='notfunny')
4214 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004215 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004216 self.assertEqual(calls, [])
4217
4218 @needs_sni
4219 def test_sni_callback_alert(self):
4220 # Returning a TLS alert is reflected to the connecting client
4221 server_context, other_context, client_context = self.sni_contexts()
4222
4223 def cb_returning_alert(ssl_sock, server_name, initial_context):
4224 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4225 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004226 with self.assertRaises(ssl.SSLError) as cm:
4227 stats = server_params_test(client_context, server_context,
4228 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004229 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004230 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004231
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004232 @needs_sni
4233 def test_sni_callback_raising(self):
4234 # Raising fails the connection with a TLS handshake failure alert.
4235 server_context, other_context, client_context = self.sni_contexts()
4236
4237 def cb_raising(ssl_sock, server_name, initial_context):
4238 1/0
4239 server_context.set_servername_callback(cb_raising)
4240
Victor Stinner00253502019-06-03 03:51:43 +02004241 with support.catch_unraisable_exception() as catch:
4242 with self.assertRaises(ssl.SSLError) as cm:
4243 stats = server_params_test(client_context, server_context,
4244 chatty=False,
4245 sni_name='supermessage')
4246
4247 self.assertEqual(cm.exception.reason,
4248 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4249 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004250
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004251 @needs_sni
4252 def test_sni_callback_wrong_return_type(self):
4253 # Returning the wrong return type terminates the TLS connection
4254 # with an internal error alert.
4255 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004256
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004257 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4258 return "foo"
4259 server_context.set_servername_callback(cb_wrong_return_type)
4260
Victor Stinner00253502019-06-03 03:51:43 +02004261 with support.catch_unraisable_exception() as catch:
4262 with self.assertRaises(ssl.SSLError) as cm:
4263 stats = server_params_test(client_context, server_context,
4264 chatty=False,
4265 sni_name='supermessage')
4266
4267
4268 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4269 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004270
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004271 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004272 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004273 client_context.set_ciphers("AES128:AES256")
4274 server_context.set_ciphers("AES256")
4275 expected_algs = [
4276 "AES256", "AES-256",
4277 # TLS 1.3 ciphers are always enabled
4278 "TLS_CHACHA20", "TLS_AES",
4279 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004280
Christian Heimesa170fa12017-09-15 20:27:30 +02004281 stats = server_params_test(client_context, server_context,
4282 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004283 ciphers = stats['server_shared_ciphers'][0]
4284 self.assertGreater(len(ciphers), 0)
4285 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004286 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004287 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004288
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004289 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004290 client_context, server_context, hostname = testing_context()
4291 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004292
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004293 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004294 s = client_context.wrap_socket(socket.socket(),
4295 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004296 s.connect((HOST, server.port))
4297 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004298
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004299 self.assertRaises(ValueError, s.read, 1024)
4300 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004301
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004302 def test_sendfile(self):
4303 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004304 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004305 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004306 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesa170fa12017-09-15 20:27:30 +02004307 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004308 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01004309 context.load_verify_locations(SIGNING_CA)
4310 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004311 server = ThreadedEchoServer(context=context, chatty=False)
4312 with server:
4313 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004314 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004315 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004316 s.sendfile(file)
4317 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004318
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004319 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004320 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004321 # TODO: sessions aren't compatible with TLSv1.3 yet
4322 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004323
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004324 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004325 stats = server_params_test(client_context, server_context,
4326 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004327 session = stats['session']
4328 self.assertTrue(session.id)
4329 self.assertGreater(session.time, 0)
4330 self.assertGreater(session.timeout, 0)
4331 self.assertTrue(session.has_ticket)
4332 if ssl.OPENSSL_VERSION_INFO > (1, 0, 1):
4333 self.assertGreater(session.ticket_lifetime_hint, 0)
4334 self.assertFalse(stats['session_reused'])
4335 sess_stat = server_context.session_stats()
4336 self.assertEqual(sess_stat['accept'], 1)
4337 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004338
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004339 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004340 stats = server_params_test(client_context, server_context,
4341 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004342 sess_stat = server_context.session_stats()
4343 self.assertEqual(sess_stat['accept'], 2)
4344 self.assertEqual(sess_stat['hits'], 1)
4345 self.assertTrue(stats['session_reused'])
4346 session2 = stats['session']
4347 self.assertEqual(session2.id, session.id)
4348 self.assertEqual(session2, session)
4349 self.assertIsNot(session2, session)
4350 self.assertGreaterEqual(session2.time, session.time)
4351 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004352
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004353 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004354 stats = server_params_test(client_context, server_context,
4355 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004356 self.assertFalse(stats['session_reused'])
4357 session3 = stats['session']
4358 self.assertNotEqual(session3.id, session.id)
4359 self.assertNotEqual(session3, session)
4360 sess_stat = server_context.session_stats()
4361 self.assertEqual(sess_stat['accept'], 3)
4362 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004363
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004364 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004365 stats = server_params_test(client_context, server_context,
4366 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004367 self.assertTrue(stats['session_reused'])
4368 session4 = stats['session']
4369 self.assertEqual(session4.id, session.id)
4370 self.assertEqual(session4, session)
4371 self.assertGreaterEqual(session4.time, session.time)
4372 self.assertGreaterEqual(session4.timeout, session.timeout)
4373 sess_stat = server_context.session_stats()
4374 self.assertEqual(sess_stat['accept'], 4)
4375 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004376
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004377 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004378 client_context, server_context, hostname = testing_context()
4379 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004380
Christian Heimes05d9fe32018-02-27 08:55:39 +01004381 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004382 client_context.options |= ssl.OP_NO_TLSv1_3
4383 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004384
Christian Heimesa170fa12017-09-15 20:27:30 +02004385 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004386 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004387 with client_context.wrap_socket(socket.socket(),
4388 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004389 # session is None before handshake
4390 self.assertEqual(s.session, None)
4391 self.assertEqual(s.session_reused, None)
4392 s.connect((HOST, server.port))
4393 session = s.session
4394 self.assertTrue(session)
4395 with self.assertRaises(TypeError) as e:
4396 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004397 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004398
Christian Heimesa170fa12017-09-15 20:27:30 +02004399 with client_context.wrap_socket(socket.socket(),
4400 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004401 s.connect((HOST, server.port))
4402 # cannot set session after handshake
4403 with self.assertRaises(ValueError) as e:
4404 s.session = session
4405 self.assertEqual(str(e.exception),
4406 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004407
Christian Heimesa170fa12017-09-15 20:27:30 +02004408 with client_context.wrap_socket(socket.socket(),
4409 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004410 # can set session before handshake and before the
4411 # connection was established
4412 s.session = session
4413 s.connect((HOST, server.port))
4414 self.assertEqual(s.session.id, session.id)
4415 self.assertEqual(s.session, session)
4416 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004417
Christian Heimesa170fa12017-09-15 20:27:30 +02004418 with client_context2.wrap_socket(socket.socket(),
4419 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004420 # cannot re-use session with a different SSLContext
4421 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004422 s.session = session
4423 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004424 self.assertEqual(str(e.exception),
4425 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004426
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004427
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004428@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004429class TestPostHandshakeAuth(unittest.TestCase):
4430 def test_pha_setter(self):
4431 protocols = [
4432 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
4433 ]
4434 for protocol in protocols:
4435 ctx = ssl.SSLContext(protocol)
4436 self.assertEqual(ctx.post_handshake_auth, False)
4437
4438 ctx.post_handshake_auth = True
4439 self.assertEqual(ctx.post_handshake_auth, True)
4440
4441 ctx.verify_mode = ssl.CERT_REQUIRED
4442 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4443 self.assertEqual(ctx.post_handshake_auth, True)
4444
4445 ctx.post_handshake_auth = False
4446 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4447 self.assertEqual(ctx.post_handshake_auth, False)
4448
4449 ctx.verify_mode = ssl.CERT_OPTIONAL
4450 ctx.post_handshake_auth = True
4451 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4452 self.assertEqual(ctx.post_handshake_auth, True)
4453
4454 def test_pha_required(self):
4455 client_context, server_context, hostname = testing_context()
4456 server_context.post_handshake_auth = True
4457 server_context.verify_mode = ssl.CERT_REQUIRED
4458 client_context.post_handshake_auth = True
4459 client_context.load_cert_chain(SIGNED_CERTFILE)
4460
4461 server = ThreadedEchoServer(context=server_context, chatty=False)
4462 with server:
4463 with client_context.wrap_socket(socket.socket(),
4464 server_hostname=hostname) as s:
4465 s.connect((HOST, server.port))
4466 s.write(b'HASCERT')
4467 self.assertEqual(s.recv(1024), b'FALSE\n')
4468 s.write(b'PHA')
4469 self.assertEqual(s.recv(1024), b'OK\n')
4470 s.write(b'HASCERT')
4471 self.assertEqual(s.recv(1024), b'TRUE\n')
4472 # PHA method just returns true when cert is already available
4473 s.write(b'PHA')
4474 self.assertEqual(s.recv(1024), b'OK\n')
4475 s.write(b'GETCERT')
4476 cert_text = s.recv(4096).decode('us-ascii')
4477 self.assertIn('Python Software Foundation CA', cert_text)
4478
4479 def test_pha_required_nocert(self):
4480 client_context, server_context, hostname = testing_context()
4481 server_context.post_handshake_auth = True
4482 server_context.verify_mode = ssl.CERT_REQUIRED
4483 client_context.post_handshake_auth = True
4484
Victor Stinner73ea5462019-07-09 14:33:49 +02004485 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4486 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004487 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004488 server = ThreadedEchoServer(context=server_context, chatty=False)
4489 with server:
4490 with client_context.wrap_socket(socket.socket(),
4491 server_hostname=hostname) as s:
4492 s.connect((HOST, server.port))
4493 s.write(b'PHA')
4494 # receive CertificateRequest
4495 self.assertEqual(s.recv(1024), b'OK\n')
4496 # send empty Certificate + Finish
4497 s.write(b'HASCERT')
4498 # receive alert
4499 with self.assertRaisesRegex(
4500 ssl.SSLError,
4501 'tlsv13 alert certificate required'):
4502 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004503
4504 def test_pha_optional(self):
4505 if support.verbose:
4506 sys.stdout.write("\n")
4507
4508 client_context, server_context, hostname = testing_context()
4509 server_context.post_handshake_auth = True
4510 server_context.verify_mode = ssl.CERT_REQUIRED
4511 client_context.post_handshake_auth = True
4512 client_context.load_cert_chain(SIGNED_CERTFILE)
4513
4514 # check CERT_OPTIONAL
4515 server_context.verify_mode = ssl.CERT_OPTIONAL
4516 server = ThreadedEchoServer(context=server_context, chatty=False)
4517 with server:
4518 with client_context.wrap_socket(socket.socket(),
4519 server_hostname=hostname) as s:
4520 s.connect((HOST, server.port))
4521 s.write(b'HASCERT')
4522 self.assertEqual(s.recv(1024), b'FALSE\n')
4523 s.write(b'PHA')
4524 self.assertEqual(s.recv(1024), b'OK\n')
4525 s.write(b'HASCERT')
4526 self.assertEqual(s.recv(1024), b'TRUE\n')
4527
4528 def test_pha_optional_nocert(self):
4529 if support.verbose:
4530 sys.stdout.write("\n")
4531
4532 client_context, server_context, hostname = testing_context()
4533 server_context.post_handshake_auth = True
4534 server_context.verify_mode = ssl.CERT_OPTIONAL
4535 client_context.post_handshake_auth = True
4536
4537 server = ThreadedEchoServer(context=server_context, chatty=False)
4538 with server:
4539 with client_context.wrap_socket(socket.socket(),
4540 server_hostname=hostname) as s:
4541 s.connect((HOST, server.port))
4542 s.write(b'HASCERT')
4543 self.assertEqual(s.recv(1024), b'FALSE\n')
4544 s.write(b'PHA')
4545 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004546 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004547 s.write(b'HASCERT')
4548 self.assertEqual(s.recv(1024), b'FALSE\n')
4549
4550 def test_pha_no_pha_client(self):
4551 client_context, server_context, hostname = testing_context()
4552 server_context.post_handshake_auth = True
4553 server_context.verify_mode = ssl.CERT_REQUIRED
4554 client_context.load_cert_chain(SIGNED_CERTFILE)
4555
4556 server = ThreadedEchoServer(context=server_context, chatty=False)
4557 with server:
4558 with client_context.wrap_socket(socket.socket(),
4559 server_hostname=hostname) as s:
4560 s.connect((HOST, server.port))
4561 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4562 s.verify_client_post_handshake()
4563 s.write(b'PHA')
4564 self.assertIn(b'extension not received', s.recv(1024))
4565
4566 def test_pha_no_pha_server(self):
4567 # server doesn't have PHA enabled, cert is requested in handshake
4568 client_context, server_context, hostname = testing_context()
4569 server_context.verify_mode = ssl.CERT_REQUIRED
4570 client_context.post_handshake_auth = True
4571 client_context.load_cert_chain(SIGNED_CERTFILE)
4572
4573 server = ThreadedEchoServer(context=server_context, chatty=False)
4574 with server:
4575 with client_context.wrap_socket(socket.socket(),
4576 server_hostname=hostname) as s:
4577 s.connect((HOST, server.port))
4578 s.write(b'HASCERT')
4579 self.assertEqual(s.recv(1024), b'TRUE\n')
4580 # PHA doesn't fail if there is already a cert
4581 s.write(b'PHA')
4582 self.assertEqual(s.recv(1024), b'OK\n')
4583 s.write(b'HASCERT')
4584 self.assertEqual(s.recv(1024), b'TRUE\n')
4585
4586 def test_pha_not_tls13(self):
4587 # TLS 1.2
4588 client_context, server_context, hostname = testing_context()
4589 server_context.verify_mode = ssl.CERT_REQUIRED
4590 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4591 client_context.post_handshake_auth = True
4592 client_context.load_cert_chain(SIGNED_CERTFILE)
4593
4594 server = ThreadedEchoServer(context=server_context, chatty=False)
4595 with server:
4596 with client_context.wrap_socket(socket.socket(),
4597 server_hostname=hostname) as s:
4598 s.connect((HOST, server.port))
4599 # PHA fails for TLS != 1.3
4600 s.write(b'PHA')
4601 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4602
Christian Heimesf0f59302019-07-01 08:29:17 +02004603 def test_bpo37428_pha_cert_none(self):
4604 # verify that post_handshake_auth does not implicitly enable cert
4605 # validation.
4606 hostname = SIGNED_CERTFILE_HOSTNAME
4607 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4608 client_context.post_handshake_auth = True
4609 client_context.load_cert_chain(SIGNED_CERTFILE)
4610 # no cert validation and CA on client side
4611 client_context.check_hostname = False
4612 client_context.verify_mode = ssl.CERT_NONE
4613
4614 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4615 server_context.load_cert_chain(SIGNED_CERTFILE)
4616 server_context.load_verify_locations(SIGNING_CA)
4617 server_context.post_handshake_auth = True
4618 server_context.verify_mode = ssl.CERT_REQUIRED
4619
4620 server = ThreadedEchoServer(context=server_context, chatty=False)
4621 with server:
4622 with client_context.wrap_socket(socket.socket(),
4623 server_hostname=hostname) as s:
4624 s.connect((HOST, server.port))
4625 s.write(b'HASCERT')
4626 self.assertEqual(s.recv(1024), b'FALSE\n')
4627 s.write(b'PHA')
4628 self.assertEqual(s.recv(1024), b'OK\n')
4629 s.write(b'HASCERT')
4630 self.assertEqual(s.recv(1024), b'TRUE\n')
4631 # server cert has not been validated
4632 self.assertEqual(s.getpeercert(), {})
4633
Christian Heimes9fb051f2018-09-23 08:32:31 +02004634
Christian Heimesc7f70692019-05-31 11:44:05 +02004635HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4636requires_keylog = unittest.skipUnless(
4637 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4638
4639class TestSSLDebug(unittest.TestCase):
4640
Hai Shia7f5d932020-08-04 00:41:24 +08004641 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004642 with open(fname) as f:
4643 return len(list(f))
4644
4645 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004646 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004647 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004648 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004649 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4650 self.assertEqual(ctx.keylog_filename, None)
4651
Hai Shia7f5d932020-08-04 00:41:24 +08004652 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4653 ctx.keylog_filename = os_helper.TESTFN
4654 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4655 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004656 self.assertEqual(self.keylog_lines(), 1)
4657
4658 ctx.keylog_filename = None
4659 self.assertEqual(ctx.keylog_filename, None)
4660
4661 with self.assertRaises((IsADirectoryError, PermissionError)):
4662 # Windows raises PermissionError
4663 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004664 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004665
4666 with self.assertRaises(TypeError):
4667 ctx.keylog_filename = 1
4668
4669 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004670 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004671 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004672 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004673 client_context, server_context, hostname = testing_context()
4674
Hai Shia7f5d932020-08-04 00:41:24 +08004675 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004676 server = ThreadedEchoServer(context=server_context, chatty=False)
4677 with server:
4678 with client_context.wrap_socket(socket.socket(),
4679 server_hostname=hostname) as s:
4680 s.connect((HOST, server.port))
4681 # header, 5 lines for TLS 1.3
4682 self.assertEqual(self.keylog_lines(), 6)
4683
4684 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004685 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004686 server = ThreadedEchoServer(context=server_context, chatty=False)
4687 with server:
4688 with client_context.wrap_socket(socket.socket(),
4689 server_hostname=hostname) as s:
4690 s.connect((HOST, server.port))
4691 self.assertGreaterEqual(self.keylog_lines(), 11)
4692
Hai Shia7f5d932020-08-04 00:41:24 +08004693 client_context.keylog_filename = os_helper.TESTFN
4694 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004695 server = ThreadedEchoServer(context=server_context, chatty=False)
4696 with server:
4697 with client_context.wrap_socket(socket.socket(),
4698 server_hostname=hostname) as s:
4699 s.connect((HOST, server.port))
4700 self.assertGreaterEqual(self.keylog_lines(), 21)
4701
4702 client_context.keylog_filename = None
4703 server_context.keylog_filename = None
4704
4705 @requires_keylog
4706 @unittest.skipIf(sys.flags.ignore_environment,
4707 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004708 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004709 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004710 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004711 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004712 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4713 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004714
4715 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4716 self.assertEqual(ctx.keylog_filename, None)
4717
4718 ctx = ssl.create_default_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 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004722 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004723
4724 def test_msg_callback(self):
4725 client_context, server_context, hostname = testing_context()
4726
4727 def msg_cb(conn, direction, version, content_type, msg_type, data):
4728 pass
4729
4730 self.assertIs(client_context._msg_callback, None)
4731 client_context._msg_callback = msg_cb
4732 self.assertIs(client_context._msg_callback, msg_cb)
4733 with self.assertRaises(TypeError):
4734 client_context._msg_callback = object()
4735
4736 def test_msg_callback_tls12(self):
4737 client_context, server_context, hostname = testing_context()
4738 client_context.options |= ssl.OP_NO_TLSv1_3
4739
4740 msg = []
4741
4742 def msg_cb(conn, direction, version, content_type, msg_type, data):
4743 self.assertIsInstance(conn, ssl.SSLSocket)
4744 self.assertIsInstance(data, bytes)
4745 self.assertIn(direction, {'read', 'write'})
4746 msg.append((direction, version, content_type, msg_type))
4747
4748 client_context._msg_callback = msg_cb
4749
4750 server = ThreadedEchoServer(context=server_context, chatty=False)
4751 with server:
4752 with client_context.wrap_socket(socket.socket(),
4753 server_hostname=hostname) as s:
4754 s.connect((HOST, server.port))
4755
Christian Heimese35d1ba2019-06-03 20:40:15 +02004756 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004757 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4758 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004759 msg
4760 )
4761 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004762 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4763 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004764 msg
4765 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004766
Christian Heimes77cde502021-03-21 16:13:09 +01004767 def test_msg_callback_deadlock_bpo43577(self):
4768 client_context, server_context, hostname = testing_context()
4769 server_context2 = testing_context()[1]
4770
4771 def msg_cb(conn, direction, version, content_type, msg_type, data):
4772 pass
4773
4774 def sni_cb(sock, servername, ctx):
4775 sock.context = server_context2
4776
4777 server_context._msg_callback = msg_cb
4778 server_context.sni_callback = sni_cb
4779
4780 server = ThreadedEchoServer(context=server_context, chatty=False)
4781 with server:
4782 with client_context.wrap_socket(socket.socket(),
4783 server_hostname=hostname) as s:
4784 s.connect((HOST, server.port))
4785 with client_context.wrap_socket(socket.socket(),
4786 server_hostname=hostname) as s:
4787 s.connect((HOST, server.port))
4788
Christian Heimesc7f70692019-05-31 11:44:05 +02004789
Thomas Woutersed03b412007-08-28 21:37:11 +00004790def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004791 if support.verbose:
4792 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004793 'Mac': platform.mac_ver,
4794 'Windows': platform.win32_ver,
4795 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004796 for name, func in plats.items():
4797 plat = func()
4798 if plat and plat[0]:
4799 plat = '%s %r' % (name, plat)
4800 break
4801 else:
4802 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004803 print("test_ssl: testing with %r %r" %
4804 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4805 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004806 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004807 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4808 try:
4809 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4810 except AttributeError:
4811 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004812
Antoine Pitrou152efa22010-05-16 18:19:27 +00004813 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004814 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004815 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004816 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004817 BADCERT, BADKEY, EMPTYCERT]:
4818 if not os.path.exists(filename):
4819 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004820
Martin Panter3840b2a2016-03-27 01:53:46 +00004821 tests = [
4822 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004823 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004824 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004825 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004826
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004827 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004828 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004829
Hai Shie80697d2020-05-28 06:10:27 +08004830 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004831 try:
4832 support.run_unittest(*tests)
4833 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004834 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004835
4836if __name__ == "__main__":
4837 test_main()