blob: 4ef1fb8d63bb2ecc016476a69250c489edeaa49e [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
Ethan Furmanb7751062021-03-30 21:17:26 -0700384 self.assertEqual(str(proto), '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")
Carl Meyer29c451c2021-03-27 15:52:28 -06002304 elif rc == errno.ENETUNREACH:
2305 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002306 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2307
Serhiy Storchaka16994912020-04-25 10:06:29 +03002308 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002309 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002310 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002311 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2312 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2313
Martin Panter3840b2a2016-03-27 01:53:46 +00002314
2315def _test_get_server_certificate(test, host, port, cert=None):
2316 pem = ssl.get_server_certificate((host, port))
2317 if not pem:
2318 test.fail("No server certificate on %s:%s!" % (host, port))
2319
2320 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2321 if not pem:
2322 test.fail("No server certificate on %s:%s!" % (host, port))
2323 if support.verbose:
2324 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2325
2326def _test_get_server_certificate_fail(test, host, port):
2327 try:
2328 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2329 except ssl.SSLError as x:
2330 #should fail
2331 if support.verbose:
2332 sys.stdout.write("%s\n" % x)
2333 else:
2334 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2335
2336
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002337from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002338
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002339class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002340
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002341 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002342
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002343 """A mildly complicated class, because we want it to work both
2344 with and without the SSL wrapper around the socket connection, so
2345 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002346
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002347 def __init__(self, server, connsock, addr):
2348 self.server = server
2349 self.running = False
2350 self.sock = connsock
2351 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002352 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002353 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002354 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002355 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002356
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002357 def wrap_conn(self):
2358 try:
2359 self.sslconn = self.server.context.wrap_socket(
2360 self.sock, server_side=True)
2361 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
2362 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002363 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002364 # We treat ConnectionResetError as though it were an
2365 # SSLError - OpenSSL on Ubuntu abruptly closes the
2366 # connection when asked to use an unsupported protocol.
2367 #
Christian Heimes529525f2018-05-23 22:24:45 +02002368 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2369 # tries to send session tickets after handshake.
2370 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002371 #
2372 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2373 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002374 self.server.conn_errors.append(str(e))
2375 if self.server.chatty:
2376 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2377 self.running = False
2378 self.close()
2379 return False
2380 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002381 # OSError may occur with wrong protocols, e.g. both
2382 # sides use PROTOCOL_TLS_SERVER.
2383 #
2384 # XXX Various errors can have happened here, for example
2385 # a mismatching protocol version, an invalid certificate,
2386 # or a low-level bug. This should be made more discriminating.
2387 #
2388 # bpo-31323: Store the exception as string to prevent
2389 # a reference leak: server -> conn_errors -> exception
2390 # -> traceback -> self (ConnectionHandler) -> server
2391 self.server.conn_errors.append(str(e))
2392 if self.server.chatty:
2393 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2394 self.running = False
2395 self.server.stop()
2396 self.close()
2397 return False
2398 else:
2399 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2400 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2401 cert = self.sslconn.getpeercert()
2402 if support.verbose and self.server.chatty:
2403 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2404 cert_binary = self.sslconn.getpeercert(True)
2405 if support.verbose and self.server.chatty:
2406 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2407 cipher = self.sslconn.cipher()
2408 if support.verbose and self.server.chatty:
2409 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
2410 sys.stdout.write(" server: selected protocol is now "
2411 + str(self.sslconn.selected_npn_protocol()) + "\n")
2412 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002413
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002414 def read(self):
2415 if self.sslconn:
2416 return self.sslconn.read()
2417 else:
2418 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002419
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002420 def write(self, bytes):
2421 if self.sslconn:
2422 return self.sslconn.write(bytes)
2423 else:
2424 return self.sock.send(bytes)
2425
2426 def close(self):
2427 if self.sslconn:
2428 self.sslconn.close()
2429 else:
2430 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002431
Antoine Pitrou480a1242010-04-28 21:37:09 +00002432 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002433 self.running = True
2434 if not self.server.starttls_server:
2435 if not self.wrap_conn():
2436 return
2437 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002438 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002439 msg = self.read()
2440 stripped = msg.strip()
2441 if not stripped:
2442 # eof, so quit this handler
2443 self.running = False
2444 try:
2445 self.sock = self.sslconn.unwrap()
2446 except OSError:
2447 # Many tests shut the TCP connection down
2448 # without an SSL shutdown. This causes
2449 # unwrap() to raise OSError with errno=0!
2450 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002451 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002452 self.sslconn = None
2453 self.close()
2454 elif stripped == b'over':
2455 if support.verbose and self.server.connectionchatty:
2456 sys.stdout.write(" server: client closed connection\n")
2457 self.close()
2458 return
2459 elif (self.server.starttls_server and
2460 stripped == b'STARTTLS'):
2461 if support.verbose and self.server.connectionchatty:
2462 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2463 self.write(b"OK\n")
2464 if not self.wrap_conn():
2465 return
2466 elif (self.server.starttls_server and self.sslconn
2467 and stripped == b'ENDTLS'):
2468 if support.verbose and self.server.connectionchatty:
2469 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2470 self.write(b"OK\n")
2471 self.sock = self.sslconn.unwrap()
2472 self.sslconn = None
2473 if support.verbose and self.server.connectionchatty:
2474 sys.stdout.write(" server: connection is now unencrypted...\n")
2475 elif stripped == b'CB tls-unique':
2476 if support.verbose and self.server.connectionchatty:
2477 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2478 data = self.sslconn.get_channel_binding("tls-unique")
2479 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002480 elif stripped == b'PHA':
2481 if support.verbose and self.server.connectionchatty:
2482 sys.stdout.write(" server: initiating post handshake auth\n")
2483 try:
2484 self.sslconn.verify_client_post_handshake()
2485 except ssl.SSLError as e:
2486 self.write(repr(e).encode("us-ascii") + b"\n")
2487 else:
2488 self.write(b"OK\n")
2489 elif stripped == b'HASCERT':
2490 if self.sslconn.getpeercert() is not None:
2491 self.write(b'TRUE\n')
2492 else:
2493 self.write(b'FALSE\n')
2494 elif stripped == b'GETCERT':
2495 cert = self.sslconn.getpeercert()
2496 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002497 else:
2498 if (support.verbose and
2499 self.server.connectionchatty):
2500 ctype = (self.sslconn and "encrypted") or "unencrypted"
2501 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2502 % (msg, ctype, msg.lower(), ctype))
2503 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002504 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002505 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2506 # when connection is not shut down gracefully.
2507 if self.server.chatty and support.verbose:
2508 sys.stdout.write(
2509 " Connection reset by peer: {}\n".format(
2510 self.addr)
2511 )
2512 self.close()
2513 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002514 except ssl.SSLError as err:
2515 # On Windows sometimes test_pha_required_nocert receives the
2516 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2517 # before the 'tlsv13 alert certificate required' exception.
2518 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2519 # is received test_pha_required_nocert fails with ConnectionResetError
2520 # because the underlying socket is closed
2521 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2522 if self.server.chatty and support.verbose:
2523 sys.stdout.write(err.args[1])
2524 # test_pha_required_nocert is expecting this exception
2525 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002526 except OSError:
2527 if self.server.chatty:
2528 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002529 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002530 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002531
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002532 # normally, we'd just stop here, but for the test
2533 # harness, we want to stop the server
2534 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002535
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002536 def __init__(self, certificate=None, ssl_version=None,
2537 certreqs=None, cacerts=None,
2538 chatty=True, connectionchatty=False, starttls_server=False,
2539 npn_protocols=None, alpn_protocols=None,
2540 ciphers=None, context=None):
2541 if context:
2542 self.context = context
2543 else:
2544 self.context = ssl.SSLContext(ssl_version
2545 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002546 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002547 self.context.verify_mode = (certreqs if certreqs is not None
2548 else ssl.CERT_NONE)
2549 if cacerts:
2550 self.context.load_verify_locations(cacerts)
2551 if certificate:
2552 self.context.load_cert_chain(certificate)
2553 if npn_protocols:
2554 self.context.set_npn_protocols(npn_protocols)
2555 if alpn_protocols:
2556 self.context.set_alpn_protocols(alpn_protocols)
2557 if ciphers:
2558 self.context.set_ciphers(ciphers)
2559 self.chatty = chatty
2560 self.connectionchatty = connectionchatty
2561 self.starttls_server = starttls_server
2562 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002563 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002564 self.flag = None
2565 self.active = False
2566 self.selected_npn_protocols = []
2567 self.selected_alpn_protocols = []
2568 self.shared_ciphers = []
2569 self.conn_errors = []
2570 threading.Thread.__init__(self)
2571 self.daemon = True
2572
2573 def __enter__(self):
2574 self.start(threading.Event())
2575 self.flag.wait()
2576 return self
2577
2578 def __exit__(self, *args):
2579 self.stop()
2580 self.join()
2581
2582 def start(self, flag=None):
2583 self.flag = flag
2584 threading.Thread.start(self)
2585
2586 def run(self):
2587 self.sock.settimeout(0.05)
2588 self.sock.listen()
2589 self.active = True
2590 if self.flag:
2591 # signal an event
2592 self.flag.set()
2593 while self.active:
2594 try:
2595 newconn, connaddr = self.sock.accept()
2596 if support.verbose and self.chatty:
2597 sys.stdout.write(' server: new connection from '
2598 + repr(connaddr) + '\n')
2599 handler = self.ConnectionHandler(self, newconn, connaddr)
2600 handler.start()
2601 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002602 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002603 pass
2604 except KeyboardInterrupt:
2605 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002606 except BaseException as e:
2607 if support.verbose and self.chatty:
2608 sys.stdout.write(
2609 ' connection handling failed: ' + repr(e) + '\n')
2610
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002611 self.sock.close()
2612
2613 def stop(self):
2614 self.active = False
2615
2616class AsyncoreEchoServer(threading.Thread):
2617
2618 # this one's based on asyncore.dispatcher
2619
2620 class EchoServer (asyncore.dispatcher):
2621
2622 class ConnectionHandler(asyncore.dispatcher_with_send):
2623
2624 def __init__(self, conn, certfile):
2625 self.socket = test_wrap_socket(conn, server_side=True,
2626 certfile=certfile,
2627 do_handshake_on_connect=False)
2628 asyncore.dispatcher_with_send.__init__(self, self.socket)
2629 self._ssl_accepting = True
2630 self._do_ssl_handshake()
2631
2632 def readable(self):
2633 if isinstance(self.socket, ssl.SSLSocket):
2634 while self.socket.pending() > 0:
2635 self.handle_read_event()
2636 return True
2637
2638 def _do_ssl_handshake(self):
2639 try:
2640 self.socket.do_handshake()
2641 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2642 return
2643 except ssl.SSLEOFError:
2644 return self.handle_close()
2645 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002646 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002647 except OSError as err:
2648 if err.args[0] == errno.ECONNABORTED:
2649 return self.handle_close()
2650 else:
2651 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002652
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002653 def handle_read(self):
2654 if self._ssl_accepting:
2655 self._do_ssl_handshake()
2656 else:
2657 data = self.recv(1024)
2658 if support.verbose:
2659 sys.stdout.write(" server: read %s from client\n" % repr(data))
2660 if not data:
2661 self.close()
2662 else:
2663 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002664
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002665 def handle_close(self):
2666 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002667 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002668 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002669
2670 def handle_error(self):
2671 raise
2672
Trent Nelson78520002008-04-10 20:54:35 +00002673 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002674 self.certfile = certfile
2675 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002676 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002677 asyncore.dispatcher.__init__(self, sock)
2678 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002679
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002680 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002681 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002682 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2683 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002684
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002685 def handle_error(self):
2686 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002687
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002688 def __init__(self, certfile):
2689 self.flag = None
2690 self.active = False
2691 self.server = self.EchoServer(certfile)
2692 self.port = self.server.port
2693 threading.Thread.__init__(self)
2694 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002695
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002696 def __str__(self):
2697 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002698
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002699 def __enter__(self):
2700 self.start(threading.Event())
2701 self.flag.wait()
2702 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002703
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002704 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002705 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002706 sys.stdout.write(" cleanup: stopping server.\n")
2707 self.stop()
2708 if support.verbose:
2709 sys.stdout.write(" cleanup: joining server thread.\n")
2710 self.join()
2711 if support.verbose:
2712 sys.stdout.write(" cleanup: successfully joined.\n")
2713 # make sure that ConnectionHandler is removed from socket_map
2714 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002715
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002716 def start (self, flag=None):
2717 self.flag = flag
2718 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002719
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002720 def run(self):
2721 self.active = True
2722 if self.flag:
2723 self.flag.set()
2724 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002725 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002726 asyncore.loop(1)
2727 except:
2728 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002729
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002730 def stop(self):
2731 self.active = False
2732 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002733
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002734def server_params_test(client_context, server_context, indata=b"FOO\n",
2735 chatty=True, connectionchatty=False, sni_name=None,
2736 session=None):
2737 """
2738 Launch a server, connect a client to it and try various reads
2739 and writes.
2740 """
2741 stats = {}
2742 server = ThreadedEchoServer(context=server_context,
2743 chatty=chatty,
2744 connectionchatty=False)
2745 with server:
2746 with client_context.wrap_socket(socket.socket(),
2747 server_hostname=sni_name, session=session) as s:
2748 s.connect((HOST, server.port))
2749 for arg in [indata, bytearray(indata), memoryview(indata)]:
2750 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002751 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002752 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002753 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002754 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002755 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002756 if connectionchatty:
2757 if support.verbose:
2758 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002759 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002760 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002761 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2762 % (outdata[:20], len(outdata),
2763 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002764 s.write(b"over\n")
2765 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002766 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002767 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002768 stats.update({
2769 'compression': s.compression(),
2770 'cipher': s.cipher(),
2771 'peercert': s.getpeercert(),
2772 'client_alpn_protocol': s.selected_alpn_protocol(),
2773 'client_npn_protocol': s.selected_npn_protocol(),
2774 'version': s.version(),
2775 'session_reused': s.session_reused,
2776 'session': s.session,
2777 })
2778 s.close()
2779 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2780 stats['server_npn_protocols'] = server.selected_npn_protocols
2781 stats['server_shared_ciphers'] = server.shared_ciphers
2782 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002783
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002784def try_protocol_combo(server_protocol, client_protocol, expect_success,
2785 certsreqs=None, server_options=0, client_options=0):
2786 """
2787 Try to SSL-connect using *client_protocol* to *server_protocol*.
2788 If *expect_success* is true, assert that the connection succeeds,
2789 if it's false, assert that the connection fails.
2790 Also, if *expect_success* is a string, assert that it is the protocol
2791 version actually used by the connection.
2792 """
2793 if certsreqs is None:
2794 certsreqs = ssl.CERT_NONE
2795 certtype = {
2796 ssl.CERT_NONE: "CERT_NONE",
2797 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2798 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2799 }[certsreqs]
2800 if support.verbose:
2801 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2802 sys.stdout.write(formatstr %
2803 (ssl.get_protocol_name(client_protocol),
2804 ssl.get_protocol_name(server_protocol),
2805 certtype))
2806 client_context = ssl.SSLContext(client_protocol)
2807 client_context.options |= client_options
2808 server_context = ssl.SSLContext(server_protocol)
2809 server_context.options |= server_options
2810
Victor Stinner3ef63442019-02-19 18:06:03 +01002811 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2812 if (min_version is not None
2813 # SSLContext.minimum_version is only available on recent OpenSSL
2814 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2815 and hasattr(server_context, 'minimum_version')
2816 and server_protocol == ssl.PROTOCOL_TLS
2817 and server_context.minimum_version > min_version):
2818 # If OpenSSL configuration is strict and requires more recent TLS
2819 # version, we have to change the minimum to test old TLS versions.
2820 server_context.minimum_version = min_version
2821
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002822 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2823 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2824 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002825 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002826 client_context.set_ciphers("ALL")
2827
Christian Heimesf6c6b582021-03-18 23:06:50 +01002828 seclevel_workaround(server_context, client_context)
2829
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002830 for ctx in (client_context, server_context):
2831 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002832 ctx.load_cert_chain(SIGNED_CERTFILE)
2833 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002834 try:
2835 stats = server_params_test(client_context, server_context,
2836 chatty=False, connectionchatty=False)
2837 # Protocol mismatch can result in either an SSLError, or a
2838 # "Connection reset by peer" error.
2839 except ssl.SSLError:
2840 if expect_success:
2841 raise
2842 except OSError as e:
2843 if expect_success or e.errno != errno.ECONNRESET:
2844 raise
2845 else:
2846 if not expect_success:
2847 raise AssertionError(
2848 "Client protocol %s succeeded with server protocol %s!"
2849 % (ssl.get_protocol_name(client_protocol),
2850 ssl.get_protocol_name(server_protocol)))
2851 elif (expect_success is not True
2852 and expect_success != stats['version']):
2853 raise AssertionError("version mismatch: expected %r, got %r"
2854 % (expect_success, stats['version']))
2855
2856
2857class ThreadedTests(unittest.TestCase):
2858
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002859 def test_echo(self):
2860 """Basic test of an SSL client connecting to a server"""
2861 if support.verbose:
2862 sys.stdout.write("\n")
2863 for protocol in PROTOCOLS:
2864 if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
2865 continue
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02002866 if not has_tls_protocol(protocol):
2867 continue
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002868 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2869 context = ssl.SSLContext(protocol)
2870 context.load_cert_chain(CERTFILE)
Christian Heimesf6c6b582021-03-18 23:06:50 +01002871 seclevel_workaround(context)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002872 server_params_test(context, context,
2873 chatty=True, connectionchatty=True)
2874
Christian Heimesa170fa12017-09-15 20:27:30 +02002875 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002876
2877 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2878 server_params_test(client_context=client_context,
2879 server_context=server_context,
2880 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002881 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002882
2883 client_context.check_hostname = False
2884 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2885 with self.assertRaises(ssl.SSLError) as e:
2886 server_params_test(client_context=server_context,
2887 server_context=client_context,
2888 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002889 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002890 self.assertIn('called a function you should not call',
2891 str(e.exception))
2892
2893 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2894 with self.assertRaises(ssl.SSLError) as e:
2895 server_params_test(client_context=server_context,
2896 server_context=server_context,
2897 chatty=True, connectionchatty=True)
2898 self.assertIn('called a function you should not call',
2899 str(e.exception))
2900
2901 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2902 with self.assertRaises(ssl.SSLError) as e:
2903 server_params_test(client_context=server_context,
2904 server_context=client_context,
2905 chatty=True, connectionchatty=True)
2906 self.assertIn('called a function you should not call',
2907 str(e.exception))
2908
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002909 def test_getpeercert(self):
2910 if support.verbose:
2911 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002912
2913 client_context, server_context, hostname = testing_context()
2914 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002915 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002916 with client_context.wrap_socket(socket.socket(),
2917 do_handshake_on_connect=False,
2918 server_hostname=hostname) as s:
2919 s.connect((HOST, server.port))
2920 # getpeercert() raise ValueError while the handshake isn't
2921 # done.
2922 with self.assertRaises(ValueError):
2923 s.getpeercert()
2924 s.do_handshake()
2925 cert = s.getpeercert()
2926 self.assertTrue(cert, "Can't get peer certificate.")
2927 cipher = s.cipher()
2928 if support.verbose:
2929 sys.stdout.write(pprint.pformat(cert) + '\n')
2930 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2931 if 'subject' not in cert:
2932 self.fail("No subject field in certificate: %s." %
2933 pprint.pformat(cert))
2934 if ((('organizationName', 'Python Software Foundation'),)
2935 not in cert['subject']):
2936 self.fail(
2937 "Missing or invalid 'organizationName' field in certificate subject; "
2938 "should be 'Python Software Foundation'.")
2939 self.assertIn('notBefore', cert)
2940 self.assertIn('notAfter', cert)
2941 before = ssl.cert_time_to_seconds(cert['notBefore'])
2942 after = ssl.cert_time_to_seconds(cert['notAfter'])
2943 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002944
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002945 @unittest.skipUnless(have_verify_flags(),
2946 "verify_flags need OpenSSL > 0.9.8")
2947 def test_crl_check(self):
2948 if support.verbose:
2949 sys.stdout.write("\n")
2950
Christian Heimesa170fa12017-09-15 20:27:30 +02002951 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002952
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002953 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002954 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002955
2956 # VERIFY_DEFAULT should pass
2957 server = ThreadedEchoServer(context=server_context, chatty=True)
2958 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002959 with client_context.wrap_socket(socket.socket(),
2960 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002961 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002962 cert = s.getpeercert()
2963 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002964
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002965 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002966 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002967
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002968 server = ThreadedEchoServer(context=server_context, chatty=True)
2969 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002970 with client_context.wrap_socket(socket.socket(),
2971 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002972 with self.assertRaisesRegex(ssl.SSLError,
2973 "certificate verify failed"):
2974 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002975
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002976 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002977 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002978
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002979 server = ThreadedEchoServer(context=server_context, chatty=True)
2980 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002981 with client_context.wrap_socket(socket.socket(),
2982 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002983 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002984 cert = s.getpeercert()
2985 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002986
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002987 def test_check_hostname(self):
2988 if support.verbose:
2989 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002990
Christian Heimesa170fa12017-09-15 20:27:30 +02002991 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002992
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002993 # correct hostname should verify
2994 server = ThreadedEchoServer(context=server_context, chatty=True)
2995 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002996 with client_context.wrap_socket(socket.socket(),
2997 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002998 s.connect((HOST, server.port))
2999 cert = s.getpeercert()
3000 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003001
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003002 # incorrect hostname should raise an exception
3003 server = ThreadedEchoServer(context=server_context, chatty=True)
3004 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003005 with client_context.wrap_socket(socket.socket(),
3006 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01003007 with self.assertRaisesRegex(
3008 ssl.CertificateError,
3009 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003010 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003011
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003012 # missing server_hostname arg should cause an exception, too
3013 server = ThreadedEchoServer(context=server_context, chatty=True)
3014 with server:
3015 with socket.socket() as s:
3016 with self.assertRaisesRegex(ValueError,
3017 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02003018 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003019
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003020 def test_ecc_cert(self):
3021 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3022 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003023 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003024 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3025
3026 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3027 # load ECC cert
3028 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3029
3030 # correct hostname should verify
3031 server = ThreadedEchoServer(context=server_context, chatty=True)
3032 with server:
3033 with client_context.wrap_socket(socket.socket(),
3034 server_hostname=hostname) as s:
3035 s.connect((HOST, server.port))
3036 cert = s.getpeercert()
3037 self.assertTrue(cert, "Can't get peer certificate.")
3038 cipher = s.cipher()[0].split('-')
3039 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3040
3041 def test_dual_rsa_ecc(self):
3042 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3043 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003044 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3045 # algorithms.
3046 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003047 # only ECDSA certs
3048 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3049 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3050
3051 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3052 # load ECC and RSA key/cert pairs
3053 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3054 server_context.load_cert_chain(SIGNED_CERTFILE)
3055
3056 # correct hostname should verify
3057 server = ThreadedEchoServer(context=server_context, chatty=True)
3058 with server:
3059 with client_context.wrap_socket(socket.socket(),
3060 server_hostname=hostname) as s:
3061 s.connect((HOST, server.port))
3062 cert = s.getpeercert()
3063 self.assertTrue(cert, "Can't get peer certificate.")
3064 cipher = s.cipher()[0].split('-')
3065 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3066
Christian Heimes66e57422018-01-29 14:25:13 +01003067 def test_check_hostname_idn(self):
3068 if support.verbose:
3069 sys.stdout.write("\n")
3070
Christian Heimes11a14932018-02-24 02:35:08 +01003071 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003072 server_context.load_cert_chain(IDNSANSFILE)
3073
Christian Heimes11a14932018-02-24 02:35:08 +01003074 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003075 context.verify_mode = ssl.CERT_REQUIRED
3076 context.check_hostname = True
3077 context.load_verify_locations(SIGNING_CA)
3078
3079 # correct hostname should verify, when specified in several
3080 # different ways
3081 idn_hostnames = [
3082 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003083 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003084 ('xn--knig-5qa.idn.pythontest.net',
3085 'xn--knig-5qa.idn.pythontest.net'),
3086 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003087 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003088
3089 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003090 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003091 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3092 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3093 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003094 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3095
3096 # ('königsgäßchen.idna2008.pythontest.net',
3097 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3098 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3099 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3100 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3101 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3102
Christian Heimes66e57422018-01-29 14:25:13 +01003103 ]
3104 for server_hostname, expected_hostname in idn_hostnames:
3105 server = ThreadedEchoServer(context=server_context, chatty=True)
3106 with server:
3107 with context.wrap_socket(socket.socket(),
3108 server_hostname=server_hostname) as s:
3109 self.assertEqual(s.server_hostname, expected_hostname)
3110 s.connect((HOST, server.port))
3111 cert = s.getpeercert()
3112 self.assertEqual(s.server_hostname, expected_hostname)
3113 self.assertTrue(cert, "Can't get peer certificate.")
3114
Christian Heimes66e57422018-01-29 14:25:13 +01003115 # incorrect hostname should raise an exception
3116 server = ThreadedEchoServer(context=server_context, chatty=True)
3117 with server:
3118 with context.wrap_socket(socket.socket(),
3119 server_hostname="python.example.org") as s:
3120 with self.assertRaises(ssl.CertificateError):
3121 s.connect((HOST, server.port))
3122
Christian Heimes529525f2018-05-23 22:24:45 +02003123 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003124 """Connecting when the server rejects the client's certificate
3125
3126 Launch a server with CERT_REQUIRED, and check that trying to
3127 connect to it with a wrong client certificate fails.
3128 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003129 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003130 # load client cert that is not signed by trusted CA
3131 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003132 # require TLS client authentication
3133 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003134 # TLS 1.3 has different handshake
3135 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003136
3137 server = ThreadedEchoServer(
3138 context=server_context, chatty=True, connectionchatty=True,
3139 )
3140
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003141 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003142 client_context.wrap_socket(socket.socket(),
3143 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003144 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003145 # Expect either an SSL error about the server rejecting
3146 # the connection, or a low-level connection reset (which
3147 # sometimes happens on Windows)
3148 s.connect((HOST, server.port))
3149 except ssl.SSLError as e:
3150 if support.verbose:
3151 sys.stdout.write("\nSSLError is %r\n" % e)
3152 except OSError as e:
3153 if e.errno != errno.ECONNRESET:
3154 raise
3155 if support.verbose:
3156 sys.stdout.write("\nsocket.error is %r\n" % e)
3157 else:
3158 self.fail("Use of invalid cert should have failed!")
3159
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003160 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003161 def test_wrong_cert_tls13(self):
3162 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003163 # load client cert that is not signed by trusted CA
3164 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003165 server_context.verify_mode = ssl.CERT_REQUIRED
3166 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3167 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3168
3169 server = ThreadedEchoServer(
3170 context=server_context, chatty=True, connectionchatty=True,
3171 )
3172 with server, \
3173 client_context.wrap_socket(socket.socket(),
3174 server_hostname=hostname) as s:
3175 # TLS 1.3 perform client cert exchange after handshake
3176 s.connect((HOST, server.port))
3177 try:
3178 s.write(b'data')
3179 s.read(4)
3180 except ssl.SSLError as e:
3181 if support.verbose:
3182 sys.stdout.write("\nSSLError is %r\n" % e)
3183 except OSError as e:
3184 if e.errno != errno.ECONNRESET:
3185 raise
3186 if support.verbose:
3187 sys.stdout.write("\nsocket.error is %r\n" % e)
3188 else:
3189 self.fail("Use of invalid cert should have failed!")
3190
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003191 def test_rude_shutdown(self):
3192 """A brutal shutdown of an SSL server should raise an OSError
3193 in the client when attempting handshake.
3194 """
3195 listener_ready = threading.Event()
3196 listener_gone = threading.Event()
3197
3198 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003199 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003200
3201 # `listener` runs in a thread. It sits in an accept() until
3202 # the main thread connects. Then it rudely closes the socket,
3203 # and sets Event `listener_gone` to let the main thread know
3204 # the socket is gone.
3205 def listener():
3206 s.listen()
3207 listener_ready.set()
3208 newsock, addr = s.accept()
3209 newsock.close()
3210 s.close()
3211 listener_gone.set()
3212
3213 def connector():
3214 listener_ready.wait()
3215 with socket.socket() as c:
3216 c.connect((HOST, port))
3217 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003218 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003219 ssl_sock = test_wrap_socket(c)
3220 except OSError:
3221 pass
3222 else:
3223 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003224
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003225 t = threading.Thread(target=listener)
3226 t.start()
3227 try:
3228 connector()
3229 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003230 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003231
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003232 def test_ssl_cert_verify_error(self):
3233 if support.verbose:
3234 sys.stdout.write("\n")
3235
3236 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3237 server_context.load_cert_chain(SIGNED_CERTFILE)
3238
3239 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3240
3241 server = ThreadedEchoServer(context=server_context, chatty=True)
3242 with server:
3243 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003244 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003245 try:
3246 s.connect((HOST, server.port))
3247 except ssl.SSLError as e:
3248 msg = 'unable to get local issuer certificate'
3249 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3250 self.assertEqual(e.verify_code, 20)
3251 self.assertEqual(e.verify_message, msg)
3252 self.assertIn(msg, repr(e))
3253 self.assertIn('certificate verify failed', repr(e))
3254
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003255 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003256 def test_protocol_sslv2(self):
3257 """Connecting to an SSLv2 server with various client options"""
3258 if support.verbose:
3259 sys.stdout.write("\n")
3260 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3261 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3262 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003263 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003264 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003265 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3266 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3267 # SSLv23 client with specific SSL options
3268 if no_sslv2_implies_sslv3_hello():
3269 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
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_SSLv2)
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_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003274 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003275 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003276
Christian Heimesa170fa12017-09-15 20:27:30 +02003277 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003278 """Connecting to an SSLv23 server with various client options"""
3279 if support.verbose:
3280 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003281 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003282 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003283 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003284 except OSError as x:
3285 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3286 if support.verbose:
3287 sys.stdout.write(
3288 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3289 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003290 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003291 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3292 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003293 if has_tls_version('TLSv1'):
3294 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003295
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003296 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003297 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3298 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003299 if has_tls_version('TLSv1'):
3300 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003301
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003302 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003303 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3304 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003305 if has_tls_version('TLSv1'):
3306 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003307
3308 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003309 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003310 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003311 server_options=ssl.OP_NO_SSLv3)
3312 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003313 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003314 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003315 if has_tls_version('TLSv1'):
3316 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3317 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003318
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003319 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003320 def test_protocol_sslv3(self):
3321 """Connecting to an SSLv3 server with various client options"""
3322 if support.verbose:
3323 sys.stdout.write("\n")
3324 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3325 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3326 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003327 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003328 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003329 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003330 client_options=ssl.OP_NO_SSLv3)
3331 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3332 if no_sslv2_implies_sslv3_hello():
3333 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003334 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003335 False, client_options=ssl.OP_NO_SSLv2)
3336
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003337 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003338 def test_protocol_tlsv1(self):
3339 """Connecting to a TLSv1 server with various client options"""
3340 if support.verbose:
3341 sys.stdout.write("\n")
3342 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3343 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3344 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003345 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003346 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003347 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003348 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003349 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003350 client_options=ssl.OP_NO_TLSv1)
3351
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003352 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003353 def test_protocol_tlsv1_1(self):
3354 """Connecting to a TLSv1.1 server with various client options.
3355 Testing against older TLS versions."""
3356 if support.verbose:
3357 sys.stdout.write("\n")
3358 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003359 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003360 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003361 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003362 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003363 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003364 client_options=ssl.OP_NO_TLSv1_1)
3365
Christian Heimesa170fa12017-09-15 20:27:30 +02003366 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003367 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3368 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003369
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003370 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003371 def test_protocol_tlsv1_2(self):
3372 """Connecting to a TLSv1.2 server with various client options.
3373 Testing against older TLS versions."""
3374 if support.verbose:
3375 sys.stdout.write("\n")
3376 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3377 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3378 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003379 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003380 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003381 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003382 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003383 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003384 client_options=ssl.OP_NO_TLSv1_2)
3385
Christian Heimesa170fa12017-09-15 20:27:30 +02003386 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003387 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3388 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3389 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3390 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3391
3392 def test_starttls(self):
3393 """Switching from clear text to encrypted and back again."""
3394 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3395
3396 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003397 starttls_server=True,
3398 chatty=True,
3399 connectionchatty=True)
3400 wrapped = False
3401 with server:
3402 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003403 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003404 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003405 if support.verbose:
3406 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003407 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003408 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003409 sys.stdout.write(
3410 " client: sending %r...\n" % indata)
3411 if wrapped:
3412 conn.write(indata)
3413 outdata = conn.read()
3414 else:
3415 s.send(indata)
3416 outdata = s.recv(1024)
3417 msg = outdata.strip().lower()
3418 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3419 # STARTTLS ok, switch to secure mode
3420 if support.verbose:
3421 sys.stdout.write(
3422 " client: read %r from server, starting TLS...\n"
3423 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003424 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003425 wrapped = True
3426 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3427 # ENDTLS ok, switch back to clear text
3428 if support.verbose:
3429 sys.stdout.write(
3430 " client: read %r from server, ending TLS...\n"
3431 % msg)
3432 s = conn.unwrap()
3433 wrapped = False
3434 else:
3435 if support.verbose:
3436 sys.stdout.write(
3437 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003438 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003439 sys.stdout.write(" client: closing connection.\n")
3440 if wrapped:
3441 conn.write(b"over\n")
3442 else:
3443 s.send(b"over\n")
3444 if wrapped:
3445 conn.close()
3446 else:
3447 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003448
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003449 def test_socketserver(self):
3450 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003451 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003452 # try to connect
3453 if support.verbose:
3454 sys.stdout.write('\n')
3455 with open(CERTFILE, 'rb') as f:
3456 d1 = f.read()
3457 d2 = ''
3458 # now fetch the same data from the HTTPS server
3459 url = 'https://localhost:%d/%s' % (
3460 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003461 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003462 f = urllib.request.urlopen(url, context=context)
3463 try:
3464 dlen = f.info().get("content-length")
3465 if dlen and (int(dlen) > 0):
3466 d2 = f.read(int(dlen))
3467 if support.verbose:
3468 sys.stdout.write(
3469 " client: read %d bytes from remote server '%s'\n"
3470 % (len(d2), server))
3471 finally:
3472 f.close()
3473 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003474
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003475 def test_asyncore_server(self):
3476 """Check the example asyncore integration."""
3477 if support.verbose:
3478 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003479
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003480 indata = b"FOO\n"
3481 server = AsyncoreEchoServer(CERTFILE)
3482 with server:
3483 s = test_wrap_socket(socket.socket())
3484 s.connect(('127.0.0.1', server.port))
3485 if support.verbose:
3486 sys.stdout.write(
3487 " client: sending %r...\n" % indata)
3488 s.write(indata)
3489 outdata = s.read()
3490 if support.verbose:
3491 sys.stdout.write(" client: read %r\n" % outdata)
3492 if outdata != indata.lower():
3493 self.fail(
3494 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3495 % (outdata[:20], len(outdata),
3496 indata[:20].lower(), len(indata)))
3497 s.write(b"over\n")
3498 if support.verbose:
3499 sys.stdout.write(" client: closing connection.\n")
3500 s.close()
3501 if support.verbose:
3502 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003503
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003504 def test_recv_send(self):
3505 """Test recv(), send() and friends."""
3506 if support.verbose:
3507 sys.stdout.write("\n")
3508
3509 server = ThreadedEchoServer(CERTFILE,
3510 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003511 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003512 cacerts=CERTFILE,
3513 chatty=True,
3514 connectionchatty=False)
3515 with server:
3516 s = test_wrap_socket(socket.socket(),
3517 server_side=False,
3518 certfile=CERTFILE,
3519 ca_certs=CERTFILE,
3520 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003521 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003522 s.connect((HOST, server.port))
3523 # helper methods for standardising recv* method signatures
3524 def _recv_into():
3525 b = bytearray(b"\0"*100)
3526 count = s.recv_into(b)
3527 return b[:count]
3528
3529 def _recvfrom_into():
3530 b = bytearray(b"\0"*100)
3531 count, addr = s.recvfrom_into(b)
3532 return b[:count]
3533
3534 # (name, method, expect success?, *args, return value func)
3535 send_methods = [
3536 ('send', s.send, True, [], len),
3537 ('sendto', s.sendto, False, ["some.address"], len),
3538 ('sendall', s.sendall, True, [], lambda x: None),
3539 ]
3540 # (name, method, whether to expect success, *args)
3541 recv_methods = [
3542 ('recv', s.recv, True, []),
3543 ('recvfrom', s.recvfrom, False, ["some.address"]),
3544 ('recv_into', _recv_into, True, []),
3545 ('recvfrom_into', _recvfrom_into, False, []),
3546 ]
3547 data_prefix = "PREFIX_"
3548
3549 for (meth_name, send_meth, expect_success, args,
3550 ret_val_meth) in send_methods:
3551 indata = (data_prefix + meth_name).encode('ascii')
3552 try:
3553 ret = send_meth(indata, *args)
3554 msg = "sending with {}".format(meth_name)
3555 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3556 outdata = s.read()
3557 if outdata != indata.lower():
3558 self.fail(
3559 "While sending with <<{name:s}>> bad data "
3560 "<<{outdata:r}>> ({nout:d}) received; "
3561 "expected <<{indata:r}>> ({nin:d})\n".format(
3562 name=meth_name, outdata=outdata[:20],
3563 nout=len(outdata),
3564 indata=indata[:20], nin=len(indata)
3565 )
3566 )
3567 except ValueError as e:
3568 if expect_success:
3569 self.fail(
3570 "Failed to send with method <<{name:s}>>; "
3571 "expected to succeed.\n".format(name=meth_name)
3572 )
3573 if not str(e).startswith(meth_name):
3574 self.fail(
3575 "Method <<{name:s}>> failed with unexpected "
3576 "exception message: {exp:s}\n".format(
3577 name=meth_name, exp=e
3578 )
3579 )
3580
3581 for meth_name, recv_meth, expect_success, args in recv_methods:
3582 indata = (data_prefix + meth_name).encode('ascii')
3583 try:
3584 s.send(indata)
3585 outdata = recv_meth(*args)
3586 if outdata != indata.lower():
3587 self.fail(
3588 "While receiving with <<{name:s}>> bad data "
3589 "<<{outdata:r}>> ({nout:d}) received; "
3590 "expected <<{indata:r}>> ({nin:d})\n".format(
3591 name=meth_name, outdata=outdata[:20],
3592 nout=len(outdata),
3593 indata=indata[:20], nin=len(indata)
3594 )
3595 )
3596 except ValueError as e:
3597 if expect_success:
3598 self.fail(
3599 "Failed to receive with method <<{name:s}>>; "
3600 "expected to succeed.\n".format(name=meth_name)
3601 )
3602 if not str(e).startswith(meth_name):
3603 self.fail(
3604 "Method <<{name:s}>> failed with unexpected "
3605 "exception message: {exp:s}\n".format(
3606 name=meth_name, exp=e
3607 )
3608 )
3609 # consume data
3610 s.read()
3611
3612 # read(-1, buffer) is supported, even though read(-1) is not
3613 data = b"data"
3614 s.send(data)
3615 buffer = bytearray(len(data))
3616 self.assertEqual(s.read(-1, buffer), len(data))
3617 self.assertEqual(buffer, data)
3618
Christian Heimes888bbdc2017-09-07 14:18:21 -07003619 # sendall accepts bytes-like objects
3620 if ctypes is not None:
3621 ubyte = ctypes.c_ubyte * len(data)
3622 byteslike = ubyte.from_buffer_copy(data)
3623 s.sendall(byteslike)
3624 self.assertEqual(s.read(), data)
3625
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003626 # Make sure sendmsg et al are disallowed to avoid
3627 # inadvertent disclosure of data and/or corruption
3628 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003629 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003630 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3631 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3632 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003633 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003634 s.write(b"over\n")
3635
3636 self.assertRaises(ValueError, s.recv, -1)
3637 self.assertRaises(ValueError, s.read, -1)
3638
3639 s.close()
3640
3641 def test_recv_zero(self):
3642 server = ThreadedEchoServer(CERTFILE)
3643 server.__enter__()
3644 self.addCleanup(server.__exit__, None, None)
3645 s = socket.create_connection((HOST, server.port))
3646 self.addCleanup(s.close)
3647 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3648 self.addCleanup(s.close)
3649
3650 # recv/read(0) should return no data
3651 s.send(b"data")
3652 self.assertEqual(s.recv(0), b"")
3653 self.assertEqual(s.read(0), b"")
3654 self.assertEqual(s.read(), b"data")
3655
3656 # Should not block if the other end sends no data
3657 s.setblocking(False)
3658 self.assertEqual(s.recv(0), b"")
3659 self.assertEqual(s.recv_into(bytearray()), 0)
3660
3661 def test_nonblocking_send(self):
3662 server = ThreadedEchoServer(CERTFILE,
3663 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003664 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003665 cacerts=CERTFILE,
3666 chatty=True,
3667 connectionchatty=False)
3668 with server:
3669 s = test_wrap_socket(socket.socket(),
3670 server_side=False,
3671 certfile=CERTFILE,
3672 ca_certs=CERTFILE,
3673 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003674 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003675 s.connect((HOST, server.port))
3676 s.setblocking(False)
3677
3678 # If we keep sending data, at some point the buffers
3679 # will be full and the call will block
3680 buf = bytearray(8192)
3681 def fill_buffer():
3682 while True:
3683 s.send(buf)
3684 self.assertRaises((ssl.SSLWantWriteError,
3685 ssl.SSLWantReadError), fill_buffer)
3686
3687 # Now read all the output and discard it
3688 s.setblocking(True)
3689 s.close()
3690
3691 def test_handshake_timeout(self):
3692 # Issue #5103: SSL handshake must respect the socket timeout
3693 server = socket.socket(socket.AF_INET)
3694 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003695 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003696 started = threading.Event()
3697 finish = False
3698
3699 def serve():
3700 server.listen()
3701 started.set()
3702 conns = []
3703 while not finish:
3704 r, w, e = select.select([server], [], [], 0.1)
3705 if server in r:
3706 # Let the socket hang around rather than having
3707 # it closed by garbage collection.
3708 conns.append(server.accept()[0])
3709 for sock in conns:
3710 sock.close()
3711
3712 t = threading.Thread(target=serve)
3713 t.start()
3714 started.wait()
3715
3716 try:
3717 try:
3718 c = socket.socket(socket.AF_INET)
3719 c.settimeout(0.2)
3720 c.connect((host, port))
3721 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003722 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003723 test_wrap_socket, c)
3724 finally:
3725 c.close()
3726 try:
3727 c = socket.socket(socket.AF_INET)
3728 c = test_wrap_socket(c)
3729 c.settimeout(0.2)
3730 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003731 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003732 c.connect, (host, port))
3733 finally:
3734 c.close()
3735 finally:
3736 finish = True
3737 t.join()
3738 server.close()
3739
3740 def test_server_accept(self):
3741 # Issue #16357: accept() on a SSLSocket created through
3742 # SSLContext.wrap_socket().
Christian Heimesa170fa12017-09-15 20:27:30 +02003743 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003744 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003745 context.load_verify_locations(SIGNING_CA)
3746 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003747 server = socket.socket(socket.AF_INET)
3748 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003749 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003750 server = context.wrap_socket(server, server_side=True)
3751 self.assertTrue(server.server_side)
3752
3753 evt = threading.Event()
3754 remote = None
3755 peer = None
3756 def serve():
3757 nonlocal remote, peer
3758 server.listen()
3759 # Block on the accept and wait on the connection to close.
3760 evt.set()
3761 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003762 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003763
3764 t = threading.Thread(target=serve)
3765 t.start()
3766 # Client wait until server setup and perform a connect.
3767 evt.wait()
3768 client = context.wrap_socket(socket.socket())
3769 client.connect((host, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003770 client.send(b'data')
3771 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003772 client_addr = client.getsockname()
3773 client.close()
3774 t.join()
3775 remote.close()
3776 server.close()
3777 # Sanity checks.
3778 self.assertIsInstance(remote, ssl.SSLSocket)
3779 self.assertEqual(peer, client_addr)
3780
3781 def test_getpeercert_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003782 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003783 with context.wrap_socket(socket.socket()) as sock:
3784 with self.assertRaises(OSError) as cm:
3785 sock.getpeercert()
3786 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3787
3788 def test_do_handshake_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003789 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003790 with context.wrap_socket(socket.socket()) as sock:
3791 with self.assertRaises(OSError) as cm:
3792 sock.do_handshake()
3793 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3794
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003795 def test_no_shared_ciphers(self):
3796 client_context, server_context, hostname = testing_context()
3797 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3798 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003799 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003800 client_context.set_ciphers("AES128")
3801 server_context.set_ciphers("AES256")
3802 with ThreadedEchoServer(context=server_context) as server:
3803 with client_context.wrap_socket(socket.socket(),
3804 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003805 with self.assertRaises(OSError):
3806 s.connect((HOST, server.port))
3807 self.assertIn("no shared cipher", server.conn_errors[0])
3808
3809 def test_version_basic(self):
3810 """
3811 Basic tests for SSLSocket.version().
3812 More tests are done in the test_protocol_*() methods.
3813 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003814 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3815 context.check_hostname = False
3816 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003817 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003818 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003819 chatty=False) as server:
3820 with context.wrap_socket(socket.socket()) as s:
3821 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003822 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003823 s.connect((HOST, server.port))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003824 if IS_OPENSSL_1_1_1 and has_tls_version('TLSv1_3'):
Christian Heimes05d9fe32018-02-27 08:55:39 +01003825 self.assertEqual(s.version(), 'TLSv1.3')
3826 elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
Christian Heimesa170fa12017-09-15 20:27:30 +02003827 self.assertEqual(s.version(), 'TLSv1.2')
3828 else: # 0.9.8 to 1.0.1
3829 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2'))
Christian Heimes141c5e82018-02-24 21:10:57 +01003830 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003831 self.assertIs(s.version(), None)
3832
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003833 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003834 def test_tls1_3(self):
3835 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
3836 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003837 context.options |= (
3838 ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2
3839 )
3840 with ThreadedEchoServer(context=context) as server:
3841 with context.wrap_socket(socket.socket()) as s:
3842 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003843 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003844 'TLS_AES_256_GCM_SHA384',
3845 'TLS_CHACHA20_POLY1305_SHA256',
3846 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003847 })
3848 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003849
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003850 @requires_minimum_version
3851 @requires_tls_version('TLSv1_2')
3852 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003853 client_context, server_context, hostname = testing_context()
3854 # client TLSv1.0 to 1.2
3855 client_context.minimum_version = ssl.TLSVersion.TLSv1
3856 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3857 # server only TLSv1.2
3858 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3859 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3860
3861 with ThreadedEchoServer(context=server_context) as server:
3862 with client_context.wrap_socket(socket.socket(),
3863 server_hostname=hostname) as s:
3864 s.connect((HOST, server.port))
3865 self.assertEqual(s.version(), 'TLSv1.2')
3866
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003867 @requires_minimum_version
3868 @requires_tls_version('TLSv1_1')
3869 def test_min_max_version_tlsv1_1(self):
3870 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003871 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003872 client_context.minimum_version = ssl.TLSVersion.TLSv1
3873 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003874 server_context.minimum_version = ssl.TLSVersion.TLSv1
3875 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003876 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003877
3878 with ThreadedEchoServer(context=server_context) as server:
3879 with client_context.wrap_socket(socket.socket(),
3880 server_hostname=hostname) as s:
3881 s.connect((HOST, server.port))
3882 self.assertEqual(s.version(), 'TLSv1.1')
3883
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003884 @requires_minimum_version
3885 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003886 @requires_tls_version('TLSv1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003887 def test_min_max_version_mismatch(self):
3888 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003889 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003890 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003891 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003892 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003893 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003894 seclevel_workaround(client_context, server_context)
3895
Christian Heimes698dde12018-02-27 11:54:43 +01003896 with ThreadedEchoServer(context=server_context) as server:
3897 with client_context.wrap_socket(socket.socket(),
3898 server_hostname=hostname) as s:
3899 with self.assertRaises(ssl.SSLError) as e:
3900 s.connect((HOST, server.port))
3901 self.assertIn("alert", str(e.exception))
3902
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003903 @requires_minimum_version
3904 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003905 def test_min_max_version_sslv3(self):
3906 client_context, server_context, hostname = testing_context()
3907 server_context.minimum_version = ssl.TLSVersion.SSLv3
3908 client_context.minimum_version = ssl.TLSVersion.SSLv3
3909 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003910 seclevel_workaround(client_context, server_context)
3911
Christian Heimes698dde12018-02-27 11:54:43 +01003912 with ThreadedEchoServer(context=server_context) as server:
3913 with client_context.wrap_socket(socket.socket(),
3914 server_hostname=hostname) as s:
3915 s.connect((HOST, server.port))
3916 self.assertEqual(s.version(), 'SSLv3')
3917
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003918 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3919 def test_default_ecdh_curve(self):
3920 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3921 # should be enabled by default on SSL contexts.
Christian Heimesa170fa12017-09-15 20:27:30 +02003922 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003923 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003924 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3925 # cipher name.
3926 context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003927 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3928 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3929 # our default cipher list should prefer ECDH-based ciphers
3930 # automatically.
3931 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
3932 context.set_ciphers("ECCdraft:ECDH")
3933 with ThreadedEchoServer(context=context) as server:
3934 with context.wrap_socket(socket.socket()) as s:
3935 s.connect((HOST, server.port))
3936 self.assertIn("ECDH", s.cipher()[0])
3937
3938 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3939 "'tls-unique' channel binding not available")
3940 def test_tls_unique_channel_binding(self):
3941 """Test tls-unique channel binding."""
3942 if support.verbose:
3943 sys.stdout.write("\n")
3944
Christian Heimes05d9fe32018-02-27 08:55:39 +01003945 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003946
3947 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003948 chatty=True,
3949 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003950
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003951 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003952 with client_context.wrap_socket(
3953 socket.socket(),
3954 server_hostname=hostname) as s:
3955 s.connect((HOST, server.port))
3956 # get the data
3957 cb_data = s.get_channel_binding("tls-unique")
3958 if support.verbose:
3959 sys.stdout.write(
3960 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003961
Christian Heimes05d9fe32018-02-27 08:55:39 +01003962 # check if it is sane
3963 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003964 if s.version() == 'TLSv1.3':
3965 self.assertEqual(len(cb_data), 48)
3966 else:
3967 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003968
Christian Heimes05d9fe32018-02-27 08:55:39 +01003969 # and compare with the peers version
3970 s.write(b"CB tls-unique\n")
3971 peer_data_repr = s.read().strip()
3972 self.assertEqual(peer_data_repr,
3973 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003974
3975 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003976 with client_context.wrap_socket(
3977 socket.socket(),
3978 server_hostname=hostname) as s:
3979 s.connect((HOST, server.port))
3980 new_cb_data = s.get_channel_binding("tls-unique")
3981 if support.verbose:
3982 sys.stdout.write(
3983 "got another channel binding data: {0!r}\n".format(
3984 new_cb_data)
3985 )
3986 # is it really unique
3987 self.assertNotEqual(cb_data, new_cb_data)
3988 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003989 if s.version() == 'TLSv1.3':
3990 self.assertEqual(len(cb_data), 48)
3991 else:
3992 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003993 s.write(b"CB tls-unique\n")
3994 peer_data_repr = s.read().strip()
3995 self.assertEqual(peer_data_repr,
3996 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003997
3998 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003999 client_context, server_context, hostname = testing_context()
4000 stats = server_params_test(client_context, server_context,
4001 chatty=True, connectionchatty=True,
4002 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004003 if support.verbose:
4004 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
4005 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
4006
4007 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
4008 "ssl.OP_NO_COMPRESSION needed for this test")
4009 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004010 client_context, server_context, hostname = testing_context()
4011 client_context.options |= ssl.OP_NO_COMPRESSION
4012 server_context.options |= ssl.OP_NO_COMPRESSION
4013 stats = server_params_test(client_context, server_context,
4014 chatty=True, connectionchatty=True,
4015 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004016 self.assertIs(stats['compression'], None)
4017
Paul Monsonf3550692019-06-19 13:09:54 -07004018 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004019 def test_dh_params(self):
4020 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004021 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004022 # test scenario needs TLS <= 1.2
4023 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004024 server_context.load_dh_params(DHFILE)
4025 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004026 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004027 stats = server_params_test(client_context, server_context,
4028 chatty=True, connectionchatty=True,
4029 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004030 cipher = stats["cipher"][0]
4031 parts = cipher.split("-")
4032 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4033 self.fail("Non-DH cipher: " + cipher[0])
4034
Christian Heimesb7b92252018-02-25 09:49:31 +01004035 @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004036 @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
Christian Heimesb7b92252018-02-25 09:49:31 +01004037 def test_ecdh_curve(self):
4038 # server secp384r1, client auto
4039 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004040
Christian Heimesb7b92252018-02-25 09:49:31 +01004041 server_context.set_ecdh_curve("secp384r1")
4042 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4043 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4044 stats = server_params_test(client_context, server_context,
4045 chatty=True, connectionchatty=True,
4046 sni_name=hostname)
4047
4048 # server auto, client secp384r1
4049 client_context, server_context, hostname = testing_context()
4050 client_context.set_ecdh_curve("secp384r1")
4051 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4052 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4053 stats = server_params_test(client_context, server_context,
4054 chatty=True, connectionchatty=True,
4055 sni_name=hostname)
4056
4057 # server / client curve mismatch
4058 client_context, server_context, hostname = testing_context()
4059 client_context.set_ecdh_curve("prime256v1")
4060 server_context.set_ecdh_curve("secp384r1")
4061 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4062 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4063 try:
4064 stats = server_params_test(client_context, server_context,
4065 chatty=True, connectionchatty=True,
4066 sni_name=hostname)
4067 except ssl.SSLError:
4068 pass
4069 else:
4070 # OpenSSL 1.0.2 does not fail although it should.
Christian Heimes05d9fe32018-02-27 08:55:39 +01004071 if IS_OPENSSL_1_1_0:
Christian Heimesb7b92252018-02-25 09:49:31 +01004072 self.fail("mismatch curve did not fail")
4073
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004074 def test_selected_alpn_protocol(self):
4075 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004076 client_context, server_context, hostname = testing_context()
4077 stats = server_params_test(client_context, server_context,
4078 chatty=True, connectionchatty=True,
4079 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004080 self.assertIs(stats['client_alpn_protocol'], None)
4081
4082 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
4083 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4084 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004085 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004086 server_context.set_alpn_protocols(['foo', 'bar'])
4087 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004088 chatty=True, connectionchatty=True,
4089 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004090 self.assertIs(stats['client_alpn_protocol'], None)
4091
4092 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
4093 def test_alpn_protocols(self):
4094 server_protocols = ['foo', 'bar', 'milkshake']
4095 protocol_tests = [
4096 (['foo', 'bar'], 'foo'),
4097 (['bar', 'foo'], 'foo'),
4098 (['milkshake'], 'milkshake'),
4099 (['http/3.0', 'http/4.0'], None)
4100 ]
4101 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004102 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004103 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004104 client_context.set_alpn_protocols(client_protocols)
4105
4106 try:
4107 stats = server_params_test(client_context,
4108 server_context,
4109 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004110 connectionchatty=True,
4111 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004112 except ssl.SSLError as e:
4113 stats = e
4114
Christian Heimes05d9fe32018-02-27 08:55:39 +01004115 if (expected is None and IS_OPENSSL_1_1_0
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004116 and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)):
4117 # OpenSSL 1.1.0 to 1.1.0e raises handshake error
4118 self.assertIsInstance(stats, ssl.SSLError)
4119 else:
4120 msg = "failed trying %s (s) and %s (c).\n" \
4121 "was expecting %s, but got %%s from the %%s" \
4122 % (str(server_protocols), str(client_protocols),
4123 str(expected))
4124 client_result = stats['client_alpn_protocol']
4125 self.assertEqual(client_result, expected,
4126 msg % (client_result, "client"))
4127 server_result = stats['server_alpn_protocols'][-1] \
4128 if len(stats['server_alpn_protocols']) else 'nothing'
4129 self.assertEqual(server_result, expected,
4130 msg % (server_result, "server"))
4131
4132 def test_selected_npn_protocol(self):
4133 # selected_npn_protocol() is None unless NPN is used
Christian Heimesa170fa12017-09-15 20:27:30 +02004134 client_context, server_context, hostname = testing_context()
4135 stats = server_params_test(client_context, server_context,
4136 chatty=True, connectionchatty=True,
4137 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004138 self.assertIs(stats['client_npn_protocol'], None)
4139
4140 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
4141 def test_npn_protocols(self):
4142 server_protocols = ['http/1.1', 'spdy/2']
4143 protocol_tests = [
4144 (['http/1.1', 'spdy/2'], 'http/1.1'),
4145 (['spdy/2', 'http/1.1'], 'http/1.1'),
4146 (['spdy/2', 'test'], 'spdy/2'),
4147 (['abc', 'def'], 'abc')
4148 ]
4149 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004150 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004151 server_context.set_npn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004152 client_context.set_npn_protocols(client_protocols)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004153 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004154 chatty=True, connectionchatty=True,
4155 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004156 msg = "failed trying %s (s) and %s (c).\n" \
4157 "was expecting %s, but got %%s from the %%s" \
4158 % (str(server_protocols), str(client_protocols),
4159 str(expected))
4160 client_result = stats['client_npn_protocol']
4161 self.assertEqual(client_result, expected, msg % (client_result, "client"))
4162 server_result = stats['server_npn_protocols'][-1] \
4163 if len(stats['server_npn_protocols']) else 'nothing'
4164 self.assertEqual(server_result, expected, msg % (server_result, "server"))
4165
4166 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004167 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004168 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004169 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004170 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004171 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004172 client_context.load_verify_locations(SIGNING_CA)
4173 return server_context, other_context, client_context
4174
4175 def check_common_name(self, stats, name):
4176 cert = stats['peercert']
4177 self.assertIn((('commonName', name),), cert['subject'])
4178
4179 @needs_sni
4180 def test_sni_callback(self):
4181 calls = []
4182 server_context, other_context, client_context = self.sni_contexts()
4183
Christian Heimesa170fa12017-09-15 20:27:30 +02004184 client_context.check_hostname = False
4185
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004186 def servername_cb(ssl_sock, server_name, initial_context):
4187 calls.append((server_name, initial_context))
4188 if server_name is not None:
4189 ssl_sock.context = other_context
4190 server_context.set_servername_callback(servername_cb)
4191
4192 stats = server_params_test(client_context, server_context,
4193 chatty=True,
4194 sni_name='supermessage')
4195 # The hostname was fetched properly, and the certificate was
4196 # changed for the connection.
4197 self.assertEqual(calls, [("supermessage", server_context)])
4198 # CERTFILE4 was selected
4199 self.check_common_name(stats, 'fakehostname')
4200
4201 calls = []
4202 # The callback is called with server_name=None
4203 stats = server_params_test(client_context, server_context,
4204 chatty=True,
4205 sni_name=None)
4206 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004207 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004208
4209 # Check disabling the callback
4210 calls = []
4211 server_context.set_servername_callback(None)
4212
4213 stats = server_params_test(client_context, server_context,
4214 chatty=True,
4215 sni_name='notfunny')
4216 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004217 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004218 self.assertEqual(calls, [])
4219
4220 @needs_sni
4221 def test_sni_callback_alert(self):
4222 # Returning a TLS alert is reflected to the connecting client
4223 server_context, other_context, client_context = self.sni_contexts()
4224
4225 def cb_returning_alert(ssl_sock, server_name, initial_context):
4226 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4227 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004228 with self.assertRaises(ssl.SSLError) as cm:
4229 stats = server_params_test(client_context, server_context,
4230 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004231 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004232 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004233
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004234 @needs_sni
4235 def test_sni_callback_raising(self):
4236 # Raising fails the connection with a TLS handshake failure alert.
4237 server_context, other_context, client_context = self.sni_contexts()
4238
4239 def cb_raising(ssl_sock, server_name, initial_context):
4240 1/0
4241 server_context.set_servername_callback(cb_raising)
4242
Victor Stinner00253502019-06-03 03:51:43 +02004243 with support.catch_unraisable_exception() as catch:
4244 with self.assertRaises(ssl.SSLError) as cm:
4245 stats = server_params_test(client_context, server_context,
4246 chatty=False,
4247 sni_name='supermessage')
4248
4249 self.assertEqual(cm.exception.reason,
4250 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4251 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004252
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004253 @needs_sni
4254 def test_sni_callback_wrong_return_type(self):
4255 # Returning the wrong return type terminates the TLS connection
4256 # with an internal error alert.
4257 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004258
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004259 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4260 return "foo"
4261 server_context.set_servername_callback(cb_wrong_return_type)
4262
Victor Stinner00253502019-06-03 03:51:43 +02004263 with support.catch_unraisable_exception() as catch:
4264 with self.assertRaises(ssl.SSLError) as cm:
4265 stats = server_params_test(client_context, server_context,
4266 chatty=False,
4267 sni_name='supermessage')
4268
4269
4270 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4271 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004272
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004273 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004274 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004275 client_context.set_ciphers("AES128:AES256")
4276 server_context.set_ciphers("AES256")
4277 expected_algs = [
4278 "AES256", "AES-256",
4279 # TLS 1.3 ciphers are always enabled
4280 "TLS_CHACHA20", "TLS_AES",
4281 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004282
Christian Heimesa170fa12017-09-15 20:27:30 +02004283 stats = server_params_test(client_context, server_context,
4284 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004285 ciphers = stats['server_shared_ciphers'][0]
4286 self.assertGreater(len(ciphers), 0)
4287 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004288 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004289 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004290
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004291 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004292 client_context, server_context, hostname = testing_context()
4293 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004294
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004295 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004296 s = client_context.wrap_socket(socket.socket(),
4297 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004298 s.connect((HOST, server.port))
4299 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004300
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004301 self.assertRaises(ValueError, s.read, 1024)
4302 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004303
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004304 def test_sendfile(self):
4305 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004306 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004307 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004308 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesa170fa12017-09-15 20:27:30 +02004309 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004310 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01004311 context.load_verify_locations(SIGNING_CA)
4312 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004313 server = ThreadedEchoServer(context=context, chatty=False)
4314 with server:
4315 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004316 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004317 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004318 s.sendfile(file)
4319 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004320
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004321 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004322 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004323 # TODO: sessions aren't compatible with TLSv1.3 yet
4324 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004325
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004326 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004327 stats = server_params_test(client_context, server_context,
4328 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004329 session = stats['session']
4330 self.assertTrue(session.id)
4331 self.assertGreater(session.time, 0)
4332 self.assertGreater(session.timeout, 0)
4333 self.assertTrue(session.has_ticket)
4334 if ssl.OPENSSL_VERSION_INFO > (1, 0, 1):
4335 self.assertGreater(session.ticket_lifetime_hint, 0)
4336 self.assertFalse(stats['session_reused'])
4337 sess_stat = server_context.session_stats()
4338 self.assertEqual(sess_stat['accept'], 1)
4339 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004340
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004341 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004342 stats = server_params_test(client_context, server_context,
4343 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004344 sess_stat = server_context.session_stats()
4345 self.assertEqual(sess_stat['accept'], 2)
4346 self.assertEqual(sess_stat['hits'], 1)
4347 self.assertTrue(stats['session_reused'])
4348 session2 = stats['session']
4349 self.assertEqual(session2.id, session.id)
4350 self.assertEqual(session2, session)
4351 self.assertIsNot(session2, session)
4352 self.assertGreaterEqual(session2.time, session.time)
4353 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004354
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004355 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004356 stats = server_params_test(client_context, server_context,
4357 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004358 self.assertFalse(stats['session_reused'])
4359 session3 = stats['session']
4360 self.assertNotEqual(session3.id, session.id)
4361 self.assertNotEqual(session3, session)
4362 sess_stat = server_context.session_stats()
4363 self.assertEqual(sess_stat['accept'], 3)
4364 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004365
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004366 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004367 stats = server_params_test(client_context, server_context,
4368 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004369 self.assertTrue(stats['session_reused'])
4370 session4 = stats['session']
4371 self.assertEqual(session4.id, session.id)
4372 self.assertEqual(session4, session)
4373 self.assertGreaterEqual(session4.time, session.time)
4374 self.assertGreaterEqual(session4.timeout, session.timeout)
4375 sess_stat = server_context.session_stats()
4376 self.assertEqual(sess_stat['accept'], 4)
4377 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004378
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004379 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004380 client_context, server_context, hostname = testing_context()
4381 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004382
Christian Heimes05d9fe32018-02-27 08:55:39 +01004383 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004384 client_context.options |= ssl.OP_NO_TLSv1_3
4385 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004386
Christian Heimesa170fa12017-09-15 20:27:30 +02004387 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004388 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004389 with client_context.wrap_socket(socket.socket(),
4390 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004391 # session is None before handshake
4392 self.assertEqual(s.session, None)
4393 self.assertEqual(s.session_reused, None)
4394 s.connect((HOST, server.port))
4395 session = s.session
4396 self.assertTrue(session)
4397 with self.assertRaises(TypeError) as e:
4398 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004399 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004400
Christian Heimesa170fa12017-09-15 20:27:30 +02004401 with client_context.wrap_socket(socket.socket(),
4402 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004403 s.connect((HOST, server.port))
4404 # cannot set session after handshake
4405 with self.assertRaises(ValueError) as e:
4406 s.session = session
4407 self.assertEqual(str(e.exception),
4408 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004409
Christian Heimesa170fa12017-09-15 20:27:30 +02004410 with client_context.wrap_socket(socket.socket(),
4411 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004412 # can set session before handshake and before the
4413 # connection was established
4414 s.session = session
4415 s.connect((HOST, server.port))
4416 self.assertEqual(s.session.id, session.id)
4417 self.assertEqual(s.session, session)
4418 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004419
Christian Heimesa170fa12017-09-15 20:27:30 +02004420 with client_context2.wrap_socket(socket.socket(),
4421 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004422 # cannot re-use session with a different SSLContext
4423 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004424 s.session = session
4425 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004426 self.assertEqual(str(e.exception),
4427 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004428
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004429
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004430@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004431class TestPostHandshakeAuth(unittest.TestCase):
4432 def test_pha_setter(self):
4433 protocols = [
4434 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
4435 ]
4436 for protocol in protocols:
4437 ctx = ssl.SSLContext(protocol)
4438 self.assertEqual(ctx.post_handshake_auth, False)
4439
4440 ctx.post_handshake_auth = True
4441 self.assertEqual(ctx.post_handshake_auth, True)
4442
4443 ctx.verify_mode = ssl.CERT_REQUIRED
4444 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4445 self.assertEqual(ctx.post_handshake_auth, True)
4446
4447 ctx.post_handshake_auth = False
4448 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4449 self.assertEqual(ctx.post_handshake_auth, False)
4450
4451 ctx.verify_mode = ssl.CERT_OPTIONAL
4452 ctx.post_handshake_auth = True
4453 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4454 self.assertEqual(ctx.post_handshake_auth, True)
4455
4456 def test_pha_required(self):
4457 client_context, server_context, hostname = testing_context()
4458 server_context.post_handshake_auth = True
4459 server_context.verify_mode = ssl.CERT_REQUIRED
4460 client_context.post_handshake_auth = True
4461 client_context.load_cert_chain(SIGNED_CERTFILE)
4462
4463 server = ThreadedEchoServer(context=server_context, chatty=False)
4464 with server:
4465 with client_context.wrap_socket(socket.socket(),
4466 server_hostname=hostname) as s:
4467 s.connect((HOST, server.port))
4468 s.write(b'HASCERT')
4469 self.assertEqual(s.recv(1024), b'FALSE\n')
4470 s.write(b'PHA')
4471 self.assertEqual(s.recv(1024), b'OK\n')
4472 s.write(b'HASCERT')
4473 self.assertEqual(s.recv(1024), b'TRUE\n')
4474 # PHA method just returns true when cert is already available
4475 s.write(b'PHA')
4476 self.assertEqual(s.recv(1024), b'OK\n')
4477 s.write(b'GETCERT')
4478 cert_text = s.recv(4096).decode('us-ascii')
4479 self.assertIn('Python Software Foundation CA', cert_text)
4480
4481 def test_pha_required_nocert(self):
4482 client_context, server_context, hostname = testing_context()
4483 server_context.post_handshake_auth = True
4484 server_context.verify_mode = ssl.CERT_REQUIRED
4485 client_context.post_handshake_auth = True
4486
Victor Stinner73ea5462019-07-09 14:33:49 +02004487 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4488 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004489 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004490 server = ThreadedEchoServer(context=server_context, chatty=False)
4491 with server:
4492 with client_context.wrap_socket(socket.socket(),
4493 server_hostname=hostname) as s:
4494 s.connect((HOST, server.port))
4495 s.write(b'PHA')
4496 # receive CertificateRequest
4497 self.assertEqual(s.recv(1024), b'OK\n')
4498 # send empty Certificate + Finish
4499 s.write(b'HASCERT')
4500 # receive alert
4501 with self.assertRaisesRegex(
4502 ssl.SSLError,
4503 'tlsv13 alert certificate required'):
4504 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004505
4506 def test_pha_optional(self):
4507 if support.verbose:
4508 sys.stdout.write("\n")
4509
4510 client_context, server_context, hostname = testing_context()
4511 server_context.post_handshake_auth = True
4512 server_context.verify_mode = ssl.CERT_REQUIRED
4513 client_context.post_handshake_auth = True
4514 client_context.load_cert_chain(SIGNED_CERTFILE)
4515
4516 # check CERT_OPTIONAL
4517 server_context.verify_mode = ssl.CERT_OPTIONAL
4518 server = ThreadedEchoServer(context=server_context, chatty=False)
4519 with server:
4520 with client_context.wrap_socket(socket.socket(),
4521 server_hostname=hostname) as s:
4522 s.connect((HOST, server.port))
4523 s.write(b'HASCERT')
4524 self.assertEqual(s.recv(1024), b'FALSE\n')
4525 s.write(b'PHA')
4526 self.assertEqual(s.recv(1024), b'OK\n')
4527 s.write(b'HASCERT')
4528 self.assertEqual(s.recv(1024), b'TRUE\n')
4529
4530 def test_pha_optional_nocert(self):
4531 if support.verbose:
4532 sys.stdout.write("\n")
4533
4534 client_context, server_context, hostname = testing_context()
4535 server_context.post_handshake_auth = True
4536 server_context.verify_mode = ssl.CERT_OPTIONAL
4537 client_context.post_handshake_auth = True
4538
4539 server = ThreadedEchoServer(context=server_context, chatty=False)
4540 with server:
4541 with client_context.wrap_socket(socket.socket(),
4542 server_hostname=hostname) as s:
4543 s.connect((HOST, server.port))
4544 s.write(b'HASCERT')
4545 self.assertEqual(s.recv(1024), b'FALSE\n')
4546 s.write(b'PHA')
4547 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004548 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004549 s.write(b'HASCERT')
4550 self.assertEqual(s.recv(1024), b'FALSE\n')
4551
4552 def test_pha_no_pha_client(self):
4553 client_context, server_context, hostname = testing_context()
4554 server_context.post_handshake_auth = True
4555 server_context.verify_mode = ssl.CERT_REQUIRED
4556 client_context.load_cert_chain(SIGNED_CERTFILE)
4557
4558 server = ThreadedEchoServer(context=server_context, chatty=False)
4559 with server:
4560 with client_context.wrap_socket(socket.socket(),
4561 server_hostname=hostname) as s:
4562 s.connect((HOST, server.port))
4563 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4564 s.verify_client_post_handshake()
4565 s.write(b'PHA')
4566 self.assertIn(b'extension not received', s.recv(1024))
4567
4568 def test_pha_no_pha_server(self):
4569 # server doesn't have PHA enabled, cert is requested in handshake
4570 client_context, server_context, hostname = testing_context()
4571 server_context.verify_mode = ssl.CERT_REQUIRED
4572 client_context.post_handshake_auth = True
4573 client_context.load_cert_chain(SIGNED_CERTFILE)
4574
4575 server = ThreadedEchoServer(context=server_context, chatty=False)
4576 with server:
4577 with client_context.wrap_socket(socket.socket(),
4578 server_hostname=hostname) as s:
4579 s.connect((HOST, server.port))
4580 s.write(b'HASCERT')
4581 self.assertEqual(s.recv(1024), b'TRUE\n')
4582 # PHA doesn't fail if there is already a cert
4583 s.write(b'PHA')
4584 self.assertEqual(s.recv(1024), b'OK\n')
4585 s.write(b'HASCERT')
4586 self.assertEqual(s.recv(1024), b'TRUE\n')
4587
4588 def test_pha_not_tls13(self):
4589 # TLS 1.2
4590 client_context, server_context, hostname = testing_context()
4591 server_context.verify_mode = ssl.CERT_REQUIRED
4592 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4593 client_context.post_handshake_auth = True
4594 client_context.load_cert_chain(SIGNED_CERTFILE)
4595
4596 server = ThreadedEchoServer(context=server_context, chatty=False)
4597 with server:
4598 with client_context.wrap_socket(socket.socket(),
4599 server_hostname=hostname) as s:
4600 s.connect((HOST, server.port))
4601 # PHA fails for TLS != 1.3
4602 s.write(b'PHA')
4603 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4604
Christian Heimesf0f59302019-07-01 08:29:17 +02004605 def test_bpo37428_pha_cert_none(self):
4606 # verify that post_handshake_auth does not implicitly enable cert
4607 # validation.
4608 hostname = SIGNED_CERTFILE_HOSTNAME
4609 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4610 client_context.post_handshake_auth = True
4611 client_context.load_cert_chain(SIGNED_CERTFILE)
4612 # no cert validation and CA on client side
4613 client_context.check_hostname = False
4614 client_context.verify_mode = ssl.CERT_NONE
4615
4616 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4617 server_context.load_cert_chain(SIGNED_CERTFILE)
4618 server_context.load_verify_locations(SIGNING_CA)
4619 server_context.post_handshake_auth = True
4620 server_context.verify_mode = ssl.CERT_REQUIRED
4621
4622 server = ThreadedEchoServer(context=server_context, chatty=False)
4623 with server:
4624 with client_context.wrap_socket(socket.socket(),
4625 server_hostname=hostname) as s:
4626 s.connect((HOST, server.port))
4627 s.write(b'HASCERT')
4628 self.assertEqual(s.recv(1024), b'FALSE\n')
4629 s.write(b'PHA')
4630 self.assertEqual(s.recv(1024), b'OK\n')
4631 s.write(b'HASCERT')
4632 self.assertEqual(s.recv(1024), b'TRUE\n')
4633 # server cert has not been validated
4634 self.assertEqual(s.getpeercert(), {})
4635
Christian Heimes9fb051f2018-09-23 08:32:31 +02004636
Christian Heimesc7f70692019-05-31 11:44:05 +02004637HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4638requires_keylog = unittest.skipUnless(
4639 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4640
4641class TestSSLDebug(unittest.TestCase):
4642
Hai Shia7f5d932020-08-04 00:41:24 +08004643 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004644 with open(fname) as f:
4645 return len(list(f))
4646
4647 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004648 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004649 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004650 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004651 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4652 self.assertEqual(ctx.keylog_filename, None)
4653
Hai Shia7f5d932020-08-04 00:41:24 +08004654 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4655 ctx.keylog_filename = os_helper.TESTFN
4656 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4657 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004658 self.assertEqual(self.keylog_lines(), 1)
4659
4660 ctx.keylog_filename = None
4661 self.assertEqual(ctx.keylog_filename, None)
4662
4663 with self.assertRaises((IsADirectoryError, PermissionError)):
4664 # Windows raises PermissionError
4665 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004666 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004667
4668 with self.assertRaises(TypeError):
4669 ctx.keylog_filename = 1
4670
4671 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004672 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004673 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004674 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004675 client_context, server_context, hostname = testing_context()
4676
Hai Shia7f5d932020-08-04 00:41:24 +08004677 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004678 server = ThreadedEchoServer(context=server_context, chatty=False)
4679 with server:
4680 with client_context.wrap_socket(socket.socket(),
4681 server_hostname=hostname) as s:
4682 s.connect((HOST, server.port))
4683 # header, 5 lines for TLS 1.3
4684 self.assertEqual(self.keylog_lines(), 6)
4685
4686 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004687 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004688 server = ThreadedEchoServer(context=server_context, chatty=False)
4689 with server:
4690 with client_context.wrap_socket(socket.socket(),
4691 server_hostname=hostname) as s:
4692 s.connect((HOST, server.port))
4693 self.assertGreaterEqual(self.keylog_lines(), 11)
4694
Hai Shia7f5d932020-08-04 00:41:24 +08004695 client_context.keylog_filename = os_helper.TESTFN
4696 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004697 server = ThreadedEchoServer(context=server_context, chatty=False)
4698 with server:
4699 with client_context.wrap_socket(socket.socket(),
4700 server_hostname=hostname) as s:
4701 s.connect((HOST, server.port))
4702 self.assertGreaterEqual(self.keylog_lines(), 21)
4703
4704 client_context.keylog_filename = None
4705 server_context.keylog_filename = None
4706
4707 @requires_keylog
4708 @unittest.skipIf(sys.flags.ignore_environment,
4709 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004710 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004711 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004712 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004713 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004714 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4715 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004716
4717 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4718 self.assertEqual(ctx.keylog_filename, None)
4719
4720 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004721 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004722
4723 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004724 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004725
4726 def test_msg_callback(self):
4727 client_context, server_context, hostname = testing_context()
4728
4729 def msg_cb(conn, direction, version, content_type, msg_type, data):
4730 pass
4731
4732 self.assertIs(client_context._msg_callback, None)
4733 client_context._msg_callback = msg_cb
4734 self.assertIs(client_context._msg_callback, msg_cb)
4735 with self.assertRaises(TypeError):
4736 client_context._msg_callback = object()
4737
4738 def test_msg_callback_tls12(self):
4739 client_context, server_context, hostname = testing_context()
4740 client_context.options |= ssl.OP_NO_TLSv1_3
4741
4742 msg = []
4743
4744 def msg_cb(conn, direction, version, content_type, msg_type, data):
4745 self.assertIsInstance(conn, ssl.SSLSocket)
4746 self.assertIsInstance(data, bytes)
4747 self.assertIn(direction, {'read', 'write'})
4748 msg.append((direction, version, content_type, msg_type))
4749
4750 client_context._msg_callback = msg_cb
4751
4752 server = ThreadedEchoServer(context=server_context, chatty=False)
4753 with server:
4754 with client_context.wrap_socket(socket.socket(),
4755 server_hostname=hostname) as s:
4756 s.connect((HOST, server.port))
4757
Christian Heimese35d1ba2019-06-03 20:40:15 +02004758 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004759 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4760 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004761 msg
4762 )
4763 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004764 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4765 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004766 msg
4767 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004768
Christian Heimes77cde502021-03-21 16:13:09 +01004769 def test_msg_callback_deadlock_bpo43577(self):
4770 client_context, server_context, hostname = testing_context()
4771 server_context2 = testing_context()[1]
4772
4773 def msg_cb(conn, direction, version, content_type, msg_type, data):
4774 pass
4775
4776 def sni_cb(sock, servername, ctx):
4777 sock.context = server_context2
4778
4779 server_context._msg_callback = msg_cb
4780 server_context.sni_callback = sni_cb
4781
4782 server = ThreadedEchoServer(context=server_context, chatty=False)
4783 with server:
4784 with client_context.wrap_socket(socket.socket(),
4785 server_hostname=hostname) as s:
4786 s.connect((HOST, server.port))
4787 with client_context.wrap_socket(socket.socket(),
4788 server_hostname=hostname) as s:
4789 s.connect((HOST, server.port))
4790
Christian Heimesc7f70692019-05-31 11:44:05 +02004791
Thomas Woutersed03b412007-08-28 21:37:11 +00004792def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004793 if support.verbose:
4794 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004795 'Mac': platform.mac_ver,
4796 'Windows': platform.win32_ver,
4797 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004798 for name, func in plats.items():
4799 plat = func()
4800 if plat and plat[0]:
4801 plat = '%s %r' % (name, plat)
4802 break
4803 else:
4804 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004805 print("test_ssl: testing with %r %r" %
4806 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4807 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004808 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004809 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4810 try:
4811 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4812 except AttributeError:
4813 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004814
Antoine Pitrou152efa22010-05-16 18:19:27 +00004815 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004816 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004817 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004818 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004819 BADCERT, BADKEY, EMPTYCERT]:
4820 if not os.path.exists(filename):
4821 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004822
Martin Panter3840b2a2016-03-27 01:53:46 +00004823 tests = [
4824 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004825 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004826 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004827 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004828
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004829 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004830 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004831
Hai Shie80697d2020-05-28 06:10:27 +08004832 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004833 try:
4834 support.run_unittest(*tests)
4835 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004836 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004837
4838if __name__ == "__main__":
4839 test_main()