blob: 831f411b12be6fa6604eb46520bdf3e96019bbda [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 Heimes5151d642021-04-09 15:43:06 +020045IS_OPENSSL_3_0_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
Christian Heimes892d66e2018-01-29 14:10:18 +010046PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
Victor Stinner3ef63442019-02-19 18:06:03 +010048PROTOCOL_TO_TLS_VERSION = {}
49for proto, ver in (
50 ("PROTOCOL_SSLv23", "SSLv3"),
51 ("PROTOCOL_TLSv1", "TLSv1"),
52 ("PROTOCOL_TLSv1_1", "TLSv1_1"),
53):
54 try:
55 proto = getattr(ssl, proto)
56 ver = getattr(ssl.TLSVersion, ver)
57 except AttributeError:
58 continue
59 PROTOCOL_TO_TLS_VERSION[proto] = ver
60
Christian Heimesefff7062013-11-21 03:35:02 +010061def data_file(*name):
62 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000063
Antoine Pitrou81564092010-10-08 23:06:24 +000064# The custom key and certificate files used in test_ssl are generated
65# using Lib/test/make_ssl_certs.py.
66# Other certificates are simply fetched from the Internet servers they
67# are meant to authenticate.
68
Antoine Pitrou152efa22010-05-16 18:19:27 +000069CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000070BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000071ONLYCERT = data_file("ssl_cert.pem")
72ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000073BYTES_ONLYCERT = os.fsencode(ONLYCERT)
74BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020075CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
76ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
77KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000078CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000079BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010080CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
81CAFILE_CACERT = data_file("capath", "5ed36f99.0")
82
Christian Heimesbd5c7d22018-01-20 15:16:30 +010083CERTFILE_INFO = {
84 'issuer': ((('countryName', 'XY'),),
85 (('localityName', 'Castle Anthrax'),),
86 (('organizationName', 'Python Software Foundation'),),
87 (('commonName', 'localhost'),)),
Christian Heimese6dac002018-08-30 07:25:49 +020088 'notAfter': 'Aug 26 14:23:15 2028 GMT',
89 'notBefore': 'Aug 29 14:23:15 2018 GMT',
90 'serialNumber': '98A7CF88C74A32ED',
Christian Heimesbd5c7d22018-01-20 15:16:30 +010091 'subject': ((('countryName', 'XY'),),
92 (('localityName', 'Castle Anthrax'),),
93 (('organizationName', 'Python Software Foundation'),),
94 (('commonName', 'localhost'),)),
95 'subjectAltName': (('DNS', 'localhost'),),
96 'version': 3
97}
Antoine Pitrou152efa22010-05-16 18:19:27 +000098
Christian Heimes22587792013-11-21 23:56:13 +010099# empty CRL
100CRLFILE = data_file("revocation.crl")
101
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100102# Two keys and certs signed by the same CA (for SNI tests)
103SIGNED_CERTFILE = data_file("keycert3.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200104SIGNED_CERTFILE_HOSTNAME = 'localhost'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100105
106SIGNED_CERTFILE_INFO = {
107 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
108 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
109 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
110 'issuer': ((('countryName', 'XY'),),
111 (('organizationName', 'Python Software Foundation CA'),),
112 (('commonName', 'our-ca-server'),)),
Christian Heimese6dac002018-08-30 07:25:49 +0200113 'notAfter': 'Jul 7 14:23:16 2028 GMT',
114 'notBefore': 'Aug 29 14:23:16 2018 GMT',
115 'serialNumber': 'CB2D80995A69525C',
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100116 'subject': ((('countryName', 'XY'),),
117 (('localityName', 'Castle Anthrax'),),
118 (('organizationName', 'Python Software Foundation'),),
119 (('commonName', 'localhost'),)),
120 'subjectAltName': (('DNS', 'localhost'),),
121 'version': 3
122}
123
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100124SIGNED_CERTFILE2 = data_file("keycert4.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200125SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100126SIGNED_CERTFILE_ECC = data_file("keycertecc.pem")
127SIGNED_CERTFILE_ECC_HOSTNAME = 'localhost-ecc'
128
Martin Panter3840b2a2016-03-27 01:53:46 +0000129# Same certificate as pycacert.pem, but without extra text in file
130SIGNING_CA = data_file("capath", "ceff1710.0")
Christian Heimes1c03abd2016-09-06 23:25:35 +0200131# cert with all kinds of subject alt names
132ALLSANFILE = data_file("allsans.pem")
Christian Heimes66e57422018-01-29 14:25:13 +0100133IDNSANSFILE = data_file("idnsans.pem")
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100134
Martin Panter3d81d932016-01-14 09:36:00 +0000135REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +0000136
137EMPTYCERT = data_file("nullcert.pem")
138BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +0000139NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000140BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200141NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +0200142NULLBYTECERT = data_file("nullbytecert.pem")
Christian Heimesa37f5242019-01-15 23:47:42 +0100143TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000144
Christian Heimes88bfd0b2018-08-14 12:54:19 +0200145DHFILE = data_file("ffdh3072.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100146BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +0000147
Christian Heimes358cfd42016-09-10 22:43:48 +0200148# Not defined in all versions of OpenSSL
149OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
150OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
151OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
152OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
Christian Heimes05d9fe32018-02-27 08:55:39 +0100153OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
Christian Heimes6f37ebc2021-04-09 17:59:21 +0200154OP_IGNORE_UNEXPECTED_EOF = getattr(ssl, "OP_IGNORE_UNEXPECTED_EOF", 0)
Christian Heimes358cfd42016-09-10 22:43:48 +0200155
Christian Heimesf6c6b582021-03-18 23:06:50 +0100156# Ubuntu has patched OpenSSL and changed behavior of security level 2
157# see https://bugs.python.org/issue41561#msg389003
158def is_ubuntu():
159 try:
160 # Assume that any references of "ubuntu" implies Ubuntu-like distro
161 # The workaround is not required for 18.04, but doesn't hurt either.
162 with open("/etc/os-release", encoding="utf-8") as f:
163 return "ubuntu" in f.read()
164 except FileNotFoundError:
165 return False
166
167if is_ubuntu():
168 def seclevel_workaround(*ctxs):
169 """"Lower security level to '1' and allow all ciphers for TLS 1.0/1"""
170 for ctx in ctxs:
171 if ctx.minimum_version <= ssl.TLSVersion.TLSv1_1:
172 ctx.set_ciphers("@SECLEVEL=1:ALL")
173else:
174 def seclevel_workaround(*ctxs):
175 pass
176
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100177
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200178def has_tls_protocol(protocol):
179 """Check if a TLS protocol is available and enabled
180
181 :param protocol: enum ssl._SSLMethod member or name
182 :return: bool
183 """
184 if isinstance(protocol, str):
185 assert protocol.startswith('PROTOCOL_')
186 protocol = getattr(ssl, protocol, None)
187 if protocol is None:
188 return False
189 if protocol in {
190 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
191 ssl.PROTOCOL_TLS_CLIENT
192 }:
193 # auto-negotiate protocols are always available
194 return True
195 name = protocol.name
196 return has_tls_version(name[len('PROTOCOL_'):])
197
198
199@functools.lru_cache
200def has_tls_version(version):
201 """Check if a TLS/SSL version is enabled
202
203 :param version: TLS version name or ssl.TLSVersion member
204 :return: bool
205 """
206 if version == "SSLv2":
207 # never supported and not even in TLSVersion enum
208 return False
209
210 if isinstance(version, str):
211 version = ssl.TLSVersion.__members__[version]
212
213 # check compile time flags like ssl.HAS_TLSv1_2
214 if not getattr(ssl, f'HAS_{version.name}'):
215 return False
216
Christian Heimes5151d642021-04-09 15:43:06 +0200217 if IS_OPENSSL_3_0_0 and version < ssl.TLSVersion.TLSv1_2:
218 # bpo43791: 3.0.0-alpha14 fails with TLSV1_ALERT_INTERNAL_ERROR
219 return False
220
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200221 # check runtime and dynamic crypto policy settings. A TLS version may
222 # be compiled in but disabled by a policy or config option.
223 ctx = ssl.SSLContext()
224 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200225 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200226 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
227 version < ctx.minimum_version
228 ):
229 return False
230 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200231 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200232 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
233 version > ctx.maximum_version
234 ):
235 return False
236
237 return True
238
239
240def requires_tls_version(version):
241 """Decorator to skip tests when a required TLS version is not available
242
243 :param version: TLS version name or ssl.TLSVersion member
244 :return:
245 """
246 def decorator(func):
247 @functools.wraps(func)
248 def wrapper(*args, **kw):
249 if not has_tls_version(version):
250 raise unittest.SkipTest(f"{version} is not available.")
251 else:
252 return func(*args, **kw)
253 return wrapper
254 return decorator
255
256
257requires_minimum_version = unittest.skipUnless(
258 hasattr(ssl.SSLContext, 'minimum_version'),
259 "required OpenSSL >= 1.1.0g"
260)
261
262
Thomas Woutersed03b412007-08-28 21:37:11 +0000263def handle_error(prefix):
264 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000265 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000266 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000267
Antoine Pitroub5218772010-05-21 09:56:06 +0000268def can_clear_options():
269 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +0200270 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +0000271
272def no_sslv2_implies_sslv3_hello():
273 # 0.9.7h or higher
274 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
275
Christian Heimes2427b502013-11-23 11:24:32 +0100276def have_verify_flags():
277 # 0.9.8 or higher
278 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
279
Christian Heimesb7b92252018-02-25 09:49:31 +0100280def _have_secp_curves():
281 if not ssl.HAS_ECDH:
282 return False
283 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
284 try:
285 ctx.set_ecdh_curve("secp384r1")
286 except ValueError:
287 return False
288 else:
289 return True
290
291
292HAVE_SECP_CURVES = _have_secp_curves()
293
294
Antoine Pitrouc695c952014-04-28 20:57:36 +0200295def utc_offset(): #NOTE: ignore issues like #1647654
296 # local time = utc time + utc offset
297 if time.daylight and time.localtime().tm_isdst > 0:
298 return -time.altzone # seconds
299 return -time.timezone
300
Christian Heimes9424bb42013-06-17 15:32:57 +0200301def asn1time(cert_time):
302 # Some versions of OpenSSL ignore seconds, see #18207
303 # 0.9.8.i
304 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
305 fmt = "%b %d %H:%M:%S %Y GMT"
306 dt = datetime.datetime.strptime(cert_time, fmt)
307 dt = dt.replace(second=0)
308 cert_time = dt.strftime(fmt)
309 # %d adds leading zero but ASN1_TIME_print() uses leading space
310 if cert_time[4] == "0":
311 cert_time = cert_time[:4] + " " + cert_time[5:]
312
313 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000314
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100315needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
316
Antoine Pitrou23df4832010-08-04 17:14:06 +0000317
Christian Heimesd0486372016-09-10 23:23:33 +0200318def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLS, *,
319 cert_reqs=ssl.CERT_NONE, ca_certs=None,
320 ciphers=None, certfile=None, keyfile=None,
321 **kwargs):
322 context = ssl.SSLContext(ssl_version)
323 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200324 if cert_reqs == ssl.CERT_NONE:
325 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200326 context.verify_mode = cert_reqs
327 if ca_certs is not None:
328 context.load_verify_locations(ca_certs)
329 if certfile is not None or keyfile is not None:
330 context.load_cert_chain(certfile, keyfile)
331 if ciphers is not None:
332 context.set_ciphers(ciphers)
333 return context.wrap_socket(sock, **kwargs)
334
Christian Heimesa170fa12017-09-15 20:27:30 +0200335
336def testing_context(server_cert=SIGNED_CERTFILE):
337 """Create context
338
339 client_context, server_context, hostname = testing_context()
340 """
341 if server_cert == SIGNED_CERTFILE:
342 hostname = SIGNED_CERTFILE_HOSTNAME
343 elif server_cert == SIGNED_CERTFILE2:
344 hostname = SIGNED_CERTFILE2_HOSTNAME
345 else:
346 raise ValueError(server_cert)
347
348 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
349 client_context.load_verify_locations(SIGNING_CA)
350
351 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
352 server_context.load_cert_chain(server_cert)
Christian Heimes9fb051f2018-09-23 08:32:31 +0200353 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200354
355 return client_context, server_context, hostname
356
357
Antoine Pitrou152efa22010-05-16 18:19:27 +0000358class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000359
Antoine Pitrou480a1242010-04-28 21:37:09 +0000360 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000361 ssl.CERT_NONE
362 ssl.CERT_OPTIONAL
363 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100364 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100365 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100366 if ssl.HAS_ECDH:
367 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100368 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
369 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000370 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100371 self.assertIn(ssl.HAS_ECDH, {True, False})
Christian Heimescb5b68a2017-09-07 18:07:00 -0700372 ssl.OP_NO_SSLv2
373 ssl.OP_NO_SSLv3
374 ssl.OP_NO_TLSv1
375 ssl.OP_NO_TLSv1_3
376 if ssl.OPENSSL_VERSION_INFO >= (1, 0, 1):
377 ssl.OP_NO_TLSv1_1
378 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200379 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000380
Christian Heimes9d50ab52018-02-27 10:17:30 +0100381 def test_private_init(self):
382 with self.assertRaisesRegex(TypeError, "public constructor"):
383 with socket.socket() as s:
384 ssl.SSLSocket(s)
385
Antoine Pitrou172f0252014-04-18 20:33:08 +0200386 def test_str_for_enums(self):
387 # Make sure that the PROTOCOL_* constants have enum-like string
388 # reprs.
Christian Heimes598894f2016-09-05 23:19:05 +0200389 proto = ssl.PROTOCOL_TLS
Ethan Furmanb7751062021-03-30 21:17:26 -0700390 self.assertEqual(str(proto), 'PROTOCOL_TLS')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200391 ctx = ssl.SSLContext(proto)
392 self.assertIs(ctx.protocol, proto)
393
Antoine Pitrou480a1242010-04-28 21:37:09 +0000394 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000395 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000396 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000397 sys.stdout.write("\n RAND_status is %d (%s)\n"
398 % (v, (v and "sufficient randomness") or
399 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200400
401 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
402 self.assertEqual(len(data), 16)
403 self.assertEqual(is_cryptographic, v == 1)
404 if v:
405 data = ssl.RAND_bytes(16)
406 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200407 else:
408 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200409
Victor Stinner1e81a392013-12-19 16:47:04 +0100410 # negative num is invalid
411 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
412 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
413
Victor Stinnerbeeb5122014-11-28 13:28:25 +0100414 if hasattr(ssl, 'RAND_egd'):
415 self.assertRaises(TypeError, ssl.RAND_egd, 1)
416 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000417 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200418 ssl.RAND_add(b"this is a random bytes object", 75.0)
419 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000420
pxinwr98a54172020-12-09 07:20:19 +0800421 @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
Christian Heimesf77b4b22013-08-21 13:26:05 +0200422 def test_random_fork(self):
423 status = ssl.RAND_status()
424 if not status:
425 self.fail("OpenSSL's PRNG has insufficient randomness")
426
427 rfd, wfd = os.pipe()
428 pid = os.fork()
429 if pid == 0:
430 try:
431 os.close(rfd)
432 child_random = ssl.RAND_pseudo_bytes(16)[0]
433 self.assertEqual(len(child_random), 16)
434 os.write(wfd, child_random)
435 os.close(wfd)
436 except BaseException:
437 os._exit(1)
438 else:
439 os._exit(0)
440 else:
441 os.close(wfd)
442 self.addCleanup(os.close, rfd)
Victor Stinner278c1e12020-03-31 20:08:12 +0200443 support.wait_process(pid, exitcode=0)
Christian Heimesf77b4b22013-08-21 13:26:05 +0200444
445 child_random = os.read(rfd, 16)
446 self.assertEqual(len(child_random), 16)
447 parent_random = ssl.RAND_pseudo_bytes(16)[0]
448 self.assertEqual(len(parent_random), 16)
449
450 self.assertNotEqual(child_random, parent_random)
451
Christian Heimese6dac002018-08-30 07:25:49 +0200452 maxDiff = None
453
Antoine Pitrou480a1242010-04-28 21:37:09 +0000454 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000455 # note that this uses an 'unofficial' function in _ssl.c,
456 # provided solely for this test, to exercise the certificate
457 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100458 self.assertEqual(
459 ssl._ssl._test_decode_cert(CERTFILE),
460 CERTFILE_INFO
461 )
462 self.assertEqual(
463 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
464 SIGNED_CERTFILE_INFO
465 )
466
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200467 # Issue #13034: the subjectAltName in some certificates
468 # (notably projects.developer.nokia.com:443) wasn't parsed
469 p = ssl._ssl._test_decode_cert(NOKIACERT)
470 if support.verbose:
471 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
472 self.assertEqual(p['subjectAltName'],
473 (('DNS', 'projects.developer.nokia.com'),
474 ('DNS', 'projects.forum.nokia.com'))
475 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100476 # extra OCSP and AIA fields
477 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
478 self.assertEqual(p['caIssuers'],
479 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
480 self.assertEqual(p['crlDistributionPoints'],
481 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000482
Christian Heimesa37f5242019-01-15 23:47:42 +0100483 def test_parse_cert_CVE_2019_5010(self):
484 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
485 if support.verbose:
486 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
487 self.assertEqual(
488 p,
489 {
490 'issuer': (
491 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
492 'notAfter': 'Jun 14 18:00:58 2028 GMT',
493 'notBefore': 'Jun 18 18:00:58 2018 GMT',
494 'serialNumber': '02',
495 'subject': ((('countryName', 'UK'),),
496 (('commonName',
497 'codenomicon-vm-2.test.lal.cisco.com'),)),
498 'subjectAltName': (
499 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
500 'version': 3
501 }
502 )
503
Christian Heimes824f7f32013-08-17 00:54:47 +0200504 def test_parse_cert_CVE_2013_4238(self):
505 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
506 if support.verbose:
507 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
508 subject = ((('countryName', 'US'),),
509 (('stateOrProvinceName', 'Oregon'),),
510 (('localityName', 'Beaverton'),),
511 (('organizationName', 'Python Software Foundation'),),
512 (('organizationalUnitName', 'Python Core Development'),),
513 (('commonName', 'null.python.org\x00example.org'),),
514 (('emailAddress', 'python-dev@python.org'),))
515 self.assertEqual(p['subject'], subject)
516 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200517 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
518 san = (('DNS', 'altnull.python.org\x00example.com'),
519 ('email', 'null@python.org\x00user@example.org'),
520 ('URI', 'http://null.python.org\x00http://example.org'),
521 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100522 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200523 else:
524 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
525 san = (('DNS', 'altnull.python.org\x00example.com'),
526 ('email', 'null@python.org\x00user@example.org'),
527 ('URI', 'http://null.python.org\x00http://example.org'),
528 ('IP Address', '192.0.2.1'),
529 ('IP Address', '<invalid>'))
530
531 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200532
Christian Heimes1c03abd2016-09-06 23:25:35 +0200533 def test_parse_all_sans(self):
534 p = ssl._ssl._test_decode_cert(ALLSANFILE)
535 self.assertEqual(p['subjectAltName'],
536 (
537 ('DNS', 'allsans'),
538 ('othername', '<unsupported>'),
539 ('othername', '<unsupported>'),
540 ('email', 'user@example.org'),
541 ('DNS', 'www.example.org'),
542 ('DirName',
543 ((('countryName', 'XY'),),
544 (('localityName', 'Castle Anthrax'),),
545 (('organizationName', 'Python Software Foundation'),),
546 (('commonName', 'dirname example'),))),
547 ('URI', 'https://www.python.org/'),
548 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100549 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200550 ('Registered ID', '1.2.3.4.5')
551 )
552 )
553
Antoine Pitrou480a1242010-04-28 21:37:09 +0000554 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000555 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000556 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000557 d1 = ssl.PEM_cert_to_DER_cert(pem)
558 p2 = ssl.DER_cert_to_PEM_cert(d1)
559 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000560 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000561 if not p2.startswith(ssl.PEM_HEADER + '\n'):
562 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
563 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
564 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000565
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000566 def test_openssl_version(self):
567 n = ssl.OPENSSL_VERSION_NUMBER
568 t = ssl.OPENSSL_VERSION_INFO
569 s = ssl.OPENSSL_VERSION
570 self.assertIsInstance(n, int)
571 self.assertIsInstance(t, tuple)
572 self.assertIsInstance(s, str)
573 # Some sanity checks follow
574 # >= 0.9
575 self.assertGreaterEqual(n, 0x900000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100576 # < 4.0
577 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000578 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100579 self.assertGreaterEqual(major, 1)
580 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000581 self.assertGreaterEqual(minor, 0)
582 self.assertLess(minor, 256)
583 self.assertGreaterEqual(fix, 0)
584 self.assertLess(fix, 256)
585 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100586 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000587 self.assertGreaterEqual(status, 0)
588 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400589 # Version string as returned by {Open,Libre}SSL, the format might change
Christian Heimes598894f2016-09-05 23:19:05 +0200590 if IS_LIBRESSL:
591 self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
Victor Stinner789b8052015-01-06 11:51:06 +0100592 (s, t, hex(n)))
Antoine Pitroudfab9352014-07-21 18:35:01 -0400593 else:
594 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
Victor Stinner789b8052015-01-06 11:51:06 +0100595 (s, t, hex(n)))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000596
Antoine Pitrou9d543662010-04-23 23:10:32 +0000597 @support.cpython_only
598 def test_refcycle(self):
599 # Issue #7943: an SSL object doesn't create reference cycles with
600 # itself.
601 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200602 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000603 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800604 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100605 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100606 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000607
Antoine Pitroua468adc2010-09-14 14:43:44 +0000608 def test_wrapped_unconnected(self):
609 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200610 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000611 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200612 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100613 self.assertRaises(OSError, ss.recv, 1)
614 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
615 self.assertRaises(OSError, ss.recvfrom, 1)
616 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
617 self.assertRaises(OSError, ss.send, b'x')
618 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200619 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100620 self.assertRaises(NotImplementedError, ss.sendmsg,
621 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200622 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
623 self.assertRaises(NotImplementedError, ss.recvmsg_into,
624 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000625
Antoine Pitrou40f08742010-04-24 22:04:40 +0000626 def test_timeout(self):
627 # Issue #8524: when creating an SSL socket, the timeout of the
628 # original socket should be retained.
629 for timeout in (None, 0.0, 5.0):
630 s = socket.socket(socket.AF_INET)
631 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200632 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100633 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000634
Christian Heimesd0486372016-09-10 23:23:33 +0200635 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000636 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000637 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000638 "certfile must be specified",
639 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000640 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000641 "certfile must be specified for server-side operations",
642 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000643 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000644 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200645 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100646 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
647 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200648 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200649 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000650 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000651 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000652 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200653 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000654 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000655 ssl.wrap_socket(sock,
656 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000657 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200658 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000659 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000660 ssl.wrap_socket(sock,
661 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000662 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000663
Martin Panter3464ea22016-02-01 21:58:11 +0000664 def bad_cert_test(self, certfile):
665 """Check that trying to use the given client certificate fails"""
666 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
667 certfile)
668 sock = socket.socket()
669 self.addCleanup(sock.close)
670 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200671 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200672 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000673
674 def test_empty_cert(self):
675 """Wrapping with an empty cert file"""
676 self.bad_cert_test("nullcert.pem")
677
678 def test_malformed_cert(self):
679 """Wrapping with a badly formatted certificate (syntax error)"""
680 self.bad_cert_test("badcert.pem")
681
682 def test_malformed_key(self):
683 """Wrapping with a badly formatted key (syntax error)"""
684 self.bad_cert_test("badkey.pem")
685
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000686 def test_match_hostname(self):
687 def ok(cert, hostname):
688 ssl.match_hostname(cert, hostname)
689 def fail(cert, hostname):
690 self.assertRaises(ssl.CertificateError,
691 ssl.match_hostname, cert, hostname)
692
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100693 # -- Hostname matching --
694
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000695 cert = {'subject': ((('commonName', 'example.com'),),)}
696 ok(cert, 'example.com')
697 ok(cert, 'ExAmple.cOm')
698 fail(cert, 'www.example.com')
699 fail(cert, '.example.com')
700 fail(cert, 'example.org')
701 fail(cert, 'exampleXcom')
702
703 cert = {'subject': ((('commonName', '*.a.com'),),)}
704 ok(cert, 'foo.a.com')
705 fail(cert, 'bar.foo.a.com')
706 fail(cert, 'a.com')
707 fail(cert, 'Xa.com')
708 fail(cert, '.a.com')
709
Mandeep Singhede2ac92017-11-27 04:01:27 +0530710 # only match wildcards when they are the only thing
711 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000712 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530713 fail(cert, 'foo.com')
714 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000715 fail(cert, 'bar.com')
716 fail(cert, 'foo.a.com')
717 fail(cert, 'bar.foo.com')
718
Christian Heimes824f7f32013-08-17 00:54:47 +0200719 # NULL bytes are bad, CVE-2013-4073
720 cert = {'subject': ((('commonName',
721 'null.python.org\x00example.org'),),)}
722 ok(cert, 'null.python.org\x00example.org') # or raise an error?
723 fail(cert, 'example.org')
724 fail(cert, 'null.python.org')
725
Georg Brandl72c98d32013-10-27 07:16:53 +0100726 # error cases with wildcards
727 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
728 fail(cert, 'bar.foo.a.com')
729 fail(cert, 'a.com')
730 fail(cert, 'Xa.com')
731 fail(cert, '.a.com')
732
733 cert = {'subject': ((('commonName', 'a.*.com'),),)}
734 fail(cert, 'a.foo.com')
735 fail(cert, 'a..com')
736 fail(cert, 'a.com')
737
738 # wildcard doesn't match IDNA prefix 'xn--'
739 idna = 'püthon.python.org'.encode("idna").decode("ascii")
740 cert = {'subject': ((('commonName', idna),),)}
741 ok(cert, idna)
742 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
743 fail(cert, idna)
744 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
745 fail(cert, idna)
746
747 # wildcard in first fragment and IDNA A-labels in sequent fragments
748 # are supported.
749 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
750 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530751 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
752 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100753 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
754 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
755
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000756 # Slightly fake real-world example
757 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
758 'subject': ((('commonName', 'linuxfrz.org'),),),
759 'subjectAltName': (('DNS', 'linuxfr.org'),
760 ('DNS', 'linuxfr.com'),
761 ('othername', '<unsupported>'))}
762 ok(cert, 'linuxfr.org')
763 ok(cert, 'linuxfr.com')
764 # Not a "DNS" entry
765 fail(cert, '<unsupported>')
766 # When there is a subjectAltName, commonName isn't used
767 fail(cert, 'linuxfrz.org')
768
769 # A pristine real-world example
770 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
771 'subject': ((('countryName', 'US'),),
772 (('stateOrProvinceName', 'California'),),
773 (('localityName', 'Mountain View'),),
774 (('organizationName', 'Google Inc'),),
775 (('commonName', 'mail.google.com'),))}
776 ok(cert, 'mail.google.com')
777 fail(cert, 'gmail.com')
778 # Only commonName is considered
779 fail(cert, 'California')
780
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100781 # -- IPv4 matching --
782 cert = {'subject': ((('commonName', 'example.com'),),),
783 'subjectAltName': (('DNS', 'example.com'),
784 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200785 ('IP Address', '14.15.16.17'),
786 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100787 ok(cert, '10.11.12.13')
788 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200789 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
790 fail(cert, '127.1')
791 fail(cert, '14.15.16.17 ')
792 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100793 fail(cert, '14.15.16.18')
794 fail(cert, 'example.net')
795
796 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300797 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100798 cert = {'subject': ((('commonName', 'example.com'),),),
799 'subjectAltName': (
800 ('DNS', 'example.com'),
801 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
802 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
803 ok(cert, '2001::cafe')
804 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200805 fail(cert, '2003::baba ')
806 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100807 fail(cert, '2003::bebe')
808 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100809
810 # -- Miscellaneous --
811
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000812 # Neither commonName nor subjectAltName
813 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
814 'subject': ((('countryName', 'US'),),
815 (('stateOrProvinceName', 'California'),),
816 (('localityName', 'Mountain View'),),
817 (('organizationName', 'Google Inc'),))}
818 fail(cert, 'mail.google.com')
819
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200820 # No DNS entry in subjectAltName but a commonName
821 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
822 'subject': ((('countryName', 'US'),),
823 (('stateOrProvinceName', 'California'),),
824 (('localityName', 'Mountain View'),),
825 (('commonName', 'mail.google.com'),)),
826 'subjectAltName': (('othername', 'blabla'), )}
827 ok(cert, 'mail.google.com')
828
829 # No DNS entry subjectAltName and no commonName
830 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
831 'subject': ((('countryName', 'US'),),
832 (('stateOrProvinceName', 'California'),),
833 (('localityName', 'Mountain View'),),
834 (('organizationName', 'Google Inc'),)),
835 'subjectAltName': (('othername', 'blabla'),)}
836 fail(cert, 'google.com')
837
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000838 # Empty cert / no cert
839 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
840 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
841
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200842 # Issue #17980: avoid denials of service by refusing more than one
843 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100844 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
845 with self.assertRaisesRegex(
846 ssl.CertificateError,
847 "partial wildcards in leftmost label are not supported"):
848 ssl.match_hostname(cert, 'axxb.example.com')
849
850 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
851 with self.assertRaisesRegex(
852 ssl.CertificateError,
853 "wildcard can only be present in the leftmost label"):
854 ssl.match_hostname(cert, 'www.sub.example.com')
855
856 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
857 with self.assertRaisesRegex(
858 ssl.CertificateError,
859 "too many wildcards"):
860 ssl.match_hostname(cert, 'axxbxxc.example.com')
861
862 cert = {'subject': ((('commonName', '*'),),)}
863 with self.assertRaisesRegex(
864 ssl.CertificateError,
865 "sole wildcard without additional labels are not support"):
866 ssl.match_hostname(cert, 'host')
867
868 cert = {'subject': ((('commonName', '*.com'),),)}
869 with self.assertRaisesRegex(
870 ssl.CertificateError,
871 r"hostname 'com' doesn't match '\*.com'"):
872 ssl.match_hostname(cert, 'com')
873
874 # extra checks for _inet_paton()
875 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
876 with self.assertRaises(ValueError):
877 ssl._inet_paton(invalid)
878 for ipaddr in ['127.0.0.1', '192.168.0.1']:
879 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300880 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100881 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
882 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200883
Antoine Pitroud5323212010-10-22 18:19:07 +0000884 def test_server_side(self):
885 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200886 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000887 with socket.socket() as sock:
888 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
889 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000890
Antoine Pitroud6494802011-07-21 01:11:30 +0200891 def test_unknown_channel_binding(self):
892 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200893 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200894 c = socket.socket(socket.AF_INET)
895 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200896 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100897 with self.assertRaises(ValueError):
898 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200899 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200900
901 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
902 "'tls-unique' channel binding not available")
903 def test_tls_unique_channel_binding(self):
904 # unconnected should return None for known type
905 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200906 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100907 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200908 # the same for server-side
909 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200910 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100911 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200912
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600913 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200914 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600915 r = repr(ss)
916 with self.assertWarns(ResourceWarning) as cm:
917 ss = None
918 support.gc_collect()
919 self.assertIn(r, str(cm.warning.args[0]))
920
Christian Heimes6d7ad132013-06-09 18:02:55 +0200921 def test_get_default_verify_paths(self):
922 paths = ssl.get_default_verify_paths()
923 self.assertEqual(len(paths), 6)
924 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
925
Hai Shia7f5d932020-08-04 00:41:24 +0800926 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200927 env["SSL_CERT_DIR"] = CAPATH
928 env["SSL_CERT_FILE"] = CERTFILE
929 paths = ssl.get_default_verify_paths()
930 self.assertEqual(paths.cafile, CERTFILE)
931 self.assertEqual(paths.capath, CAPATH)
932
Christian Heimes44109d72013-11-22 01:51:30 +0100933 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
934 def test_enum_certificates(self):
935 self.assertTrue(ssl.enum_certificates("CA"))
936 self.assertTrue(ssl.enum_certificates("ROOT"))
937
938 self.assertRaises(TypeError, ssl.enum_certificates)
939 self.assertRaises(WindowsError, ssl.enum_certificates, "")
940
Christian Heimesc2d65e12013-11-22 16:13:55 +0100941 trust_oids = set()
942 for storename in ("CA", "ROOT"):
943 store = ssl.enum_certificates(storename)
944 self.assertIsInstance(store, list)
945 for element in store:
946 self.assertIsInstance(element, tuple)
947 self.assertEqual(len(element), 3)
948 cert, enc, trust = element
949 self.assertIsInstance(cert, bytes)
950 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200951 self.assertIsInstance(trust, (frozenset, set, bool))
952 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100953 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100954
955 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100956 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200957
Christian Heimes46bebee2013-06-09 19:03:31 +0200958 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100959 def test_enum_crls(self):
960 self.assertTrue(ssl.enum_crls("CA"))
961 self.assertRaises(TypeError, ssl.enum_crls)
962 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200963
Christian Heimes44109d72013-11-22 01:51:30 +0100964 crls = ssl.enum_crls("CA")
965 self.assertIsInstance(crls, list)
966 for element in crls:
967 self.assertIsInstance(element, tuple)
968 self.assertEqual(len(element), 2)
969 self.assertIsInstance(element[0], bytes)
970 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200971
Christian Heimes46bebee2013-06-09 19:03:31 +0200972
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100973 def test_asn1object(self):
974 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
975 '1.3.6.1.5.5.7.3.1')
976
977 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
978 self.assertEqual(val, expected)
979 self.assertEqual(val.nid, 129)
980 self.assertEqual(val.shortname, 'serverAuth')
981 self.assertEqual(val.longname, 'TLS Web Server Authentication')
982 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
983 self.assertIsInstance(val, ssl._ASN1Object)
984 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
985
986 val = ssl._ASN1Object.fromnid(129)
987 self.assertEqual(val, expected)
988 self.assertIsInstance(val, ssl._ASN1Object)
989 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100990 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
991 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100992 for i in range(1000):
993 try:
994 obj = ssl._ASN1Object.fromnid(i)
995 except ValueError:
996 pass
997 else:
998 self.assertIsInstance(obj.nid, int)
999 self.assertIsInstance(obj.shortname, str)
1000 self.assertIsInstance(obj.longname, str)
1001 self.assertIsInstance(obj.oid, (str, type(None)))
1002
1003 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
1004 self.assertEqual(val, expected)
1005 self.assertIsInstance(val, ssl._ASN1Object)
1006 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
1007 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
1008 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +01001009 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
1010 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001011
Christian Heimes72d28502013-11-23 13:56:58 +01001012 def test_purpose_enum(self):
1013 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
1014 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
1015 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
1016 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
1017 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
1018 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
1019 '1.3.6.1.5.5.7.3.1')
1020
1021 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
1022 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
1023 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
1024 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
1025 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
1026 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
1027 '1.3.6.1.5.5.7.3.2')
1028
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001029 def test_unsupported_dtls(self):
1030 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1031 self.addCleanup(s.close)
1032 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +02001033 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001034 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +02001035 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001036 with self.assertRaises(NotImplementedError) as cx:
1037 ctx.wrap_socket(s)
1038 self.assertEqual(str(cx.exception), "only stream sockets are supported")
1039
Antoine Pitrouc695c952014-04-28 20:57:36 +02001040 def cert_time_ok(self, timestring, timestamp):
1041 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
1042
1043 def cert_time_fail(self, timestring):
1044 with self.assertRaises(ValueError):
1045 ssl.cert_time_to_seconds(timestring)
1046
1047 @unittest.skipUnless(utc_offset(),
1048 'local time needs to be different from UTC')
1049 def test_cert_time_to_seconds_timezone(self):
1050 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
1051 # results if local timezone is not UTC
1052 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
1053 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
1054
1055 def test_cert_time_to_seconds(self):
1056 timestring = "Jan 5 09:34:43 2018 GMT"
1057 ts = 1515144883.0
1058 self.cert_time_ok(timestring, ts)
1059 # accept keyword parameter, assert its name
1060 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
1061 # accept both %e and %d (space or zero generated by strftime)
1062 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
1063 # case-insensitive
1064 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
1065 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
1066 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1067 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1068 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1069 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1070 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1071 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1072
1073 newyear_ts = 1230768000.0
1074 # leap seconds
1075 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1076 # same timestamp
1077 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1078
1079 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1080 # allow 60th second (even if it is not a leap second)
1081 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1082 # allow 2nd leap second for compatibility with time.strptime()
1083 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1084 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1085
Mike53f7a7c2017-12-14 14:04:53 +03001086 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001087 # 99991231235959Z (rfc 5280)
1088 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1089
1090 @support.run_with_locale('LC_ALL', '')
1091 def test_cert_time_to_seconds_locale(self):
1092 # `cert_time_to_seconds()` should be locale independent
1093
1094 def local_february_name():
1095 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1096
1097 if local_february_name().lower() == 'feb':
1098 self.skipTest("locale-specific month name needs to be "
1099 "different from C locale")
1100
1101 # locale-independent
1102 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1103 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1104
Martin Panter3840b2a2016-03-27 01:53:46 +00001105 def test_connect_ex_error(self):
1106 server = socket.socket(socket.AF_INET)
1107 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001108 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001109 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001110 cert_reqs=ssl.CERT_REQUIRED)
1111 self.addCleanup(s.close)
1112 rc = s.connect_ex((HOST, port))
1113 # Issue #19919: Windows machines or VMs hosted on Windows
1114 # machines sometimes return EWOULDBLOCK.
1115 errors = (
1116 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1117 errno.EWOULDBLOCK,
1118 )
1119 self.assertIn(rc, errors)
1120
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001121
Antoine Pitrou152efa22010-05-16 18:19:27 +00001122class ContextTests(unittest.TestCase):
1123
1124 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001125 for protocol in PROTOCOLS:
1126 ssl.SSLContext(protocol)
Christian Heimes598894f2016-09-05 23:19:05 +02001127 ctx = ssl.SSLContext()
1128 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001129 self.assertRaises(ValueError, ssl.SSLContext, -1)
1130 self.assertRaises(ValueError, ssl.SSLContext, 42)
1131
1132 def test_protocol(self):
1133 for proto in PROTOCOLS:
1134 ctx = ssl.SSLContext(proto)
1135 self.assertEqual(ctx.protocol, proto)
1136
1137 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001138 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001139 ctx.set_ciphers("ALL")
1140 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001141 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001142 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001143
Christian Heimes892d66e2018-01-29 14:10:18 +01001144 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1145 "Test applies only to Python default ciphers")
1146 def test_python_ciphers(self):
1147 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1148 ciphers = ctx.get_ciphers()
1149 for suite in ciphers:
1150 name = suite['name']
1151 self.assertNotIn("PSK", name)
1152 self.assertNotIn("SRP", name)
1153 self.assertNotIn("MD5", name)
1154 self.assertNotIn("RC4", name)
1155 self.assertNotIn("3DES", name)
1156
Christian Heimes25bfcd52016-09-06 00:04:45 +02001157 @unittest.skipIf(ssl.OPENSSL_VERSION_INFO < (1, 0, 2, 0, 0), 'OpenSSL too old')
1158 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001159 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001160 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001161 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001162 self.assertIn('AES256-GCM-SHA384', names)
1163 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001164
Antoine Pitroub5218772010-05-21 09:56:06 +00001165 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001166 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001167 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001168 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001169 # SSLContext also enables these by default
1170 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001171 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001172 OP_ENABLE_MIDDLEBOX_COMPAT |
1173 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001174 self.assertEqual(default, ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001175 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001176 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +00001177 if can_clear_options():
Christian Heimes598894f2016-09-05 23:19:05 +02001178 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
1179 self.assertEqual(default, ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +00001180 ctx.options = 0
Matthias Klosef7c56242016-06-12 23:40:00 -07001181 # Ubuntu has OP_NO_SSLv3 forced on by default
1182 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001183 else:
1184 with self.assertRaises(ValueError):
1185 ctx.options = 0
1186
Christian Heimesa170fa12017-09-15 20:27:30 +02001187 def test_verify_mode_protocol(self):
1188 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001189 # Default value
1190 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1191 ctx.verify_mode = ssl.CERT_OPTIONAL
1192 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1193 ctx.verify_mode = ssl.CERT_REQUIRED
1194 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1195 ctx.verify_mode = ssl.CERT_NONE
1196 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1197 with self.assertRaises(TypeError):
1198 ctx.verify_mode = None
1199 with self.assertRaises(ValueError):
1200 ctx.verify_mode = 42
1201
Christian Heimesa170fa12017-09-15 20:27:30 +02001202 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1203 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1204 self.assertFalse(ctx.check_hostname)
1205
1206 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1207 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1208 self.assertTrue(ctx.check_hostname)
1209
Christian Heimes61d478c2018-01-27 15:51:38 +01001210 def test_hostname_checks_common_name(self):
1211 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1212 self.assertTrue(ctx.hostname_checks_common_name)
1213 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1214 ctx.hostname_checks_common_name = True
1215 self.assertTrue(ctx.hostname_checks_common_name)
1216 ctx.hostname_checks_common_name = False
1217 self.assertFalse(ctx.hostname_checks_common_name)
1218 ctx.hostname_checks_common_name = True
1219 self.assertTrue(ctx.hostname_checks_common_name)
1220 else:
1221 with self.assertRaises(AttributeError):
1222 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001223
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001224 @requires_minimum_version
Christian Heimesc9bc49c2019-09-11 19:24:47 +02001225 @unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
Christian Heimes698dde12018-02-27 11:54:43 +01001226 def test_min_max_version(self):
1227 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001228 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1229 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001230 minimum_range = {
1231 # stock OpenSSL
1232 ssl.TLSVersion.MINIMUM_SUPPORTED,
1233 # Fedora 29 uses TLS 1.0 by default
1234 ssl.TLSVersion.TLSv1,
1235 # RHEL 8 uses TLS 1.2 by default
1236 ssl.TLSVersion.TLSv1_2
1237 }
torsava34864d12019-12-02 17:15:42 +01001238 maximum_range = {
1239 # stock OpenSSL
1240 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1241 # Fedora 32 uses TLS 1.3 by default
1242 ssl.TLSVersion.TLSv1_3
1243 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001244
Christian Heimes34de2d32019-01-18 16:09:30 +01001245 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001246 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001247 )
torsava34864d12019-12-02 17:15:42 +01001248 self.assertIn(
1249 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001250 )
1251
1252 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1253 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1254 self.assertEqual(
1255 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1256 )
1257 self.assertEqual(
1258 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1259 )
1260
1261 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1262 ctx.maximum_version = ssl.TLSVersion.TLSv1
1263 self.assertEqual(
1264 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1265 )
1266 self.assertEqual(
1267 ctx.maximum_version, ssl.TLSVersion.TLSv1
1268 )
1269
1270 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1271 self.assertEqual(
1272 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1273 )
1274
1275 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1276 self.assertIn(
1277 ctx.maximum_version,
1278 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1279 )
1280
1281 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1282 self.assertIn(
1283 ctx.minimum_version,
1284 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1285 )
1286
1287 with self.assertRaises(ValueError):
1288 ctx.minimum_version = 42
1289
1290 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1291
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001292 self.assertIn(
1293 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001294 )
1295 self.assertEqual(
1296 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1297 )
1298 with self.assertRaises(ValueError):
1299 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1300 with self.assertRaises(ValueError):
1301 ctx.maximum_version = ssl.TLSVersion.TLSv1
1302
1303
matthewhughes9348e836bb2020-07-17 09:59:15 +01001304 @unittest.skipUnless(
1305 hasattr(ssl.SSLContext, 'security_level'),
1306 "requires OpenSSL >= 1.1.0"
1307 )
1308 def test_security_level(self):
1309 ctx = ssl.SSLContext()
1310 # The default security callback allows for levels between 0-5
1311 # with OpenSSL defaulting to 1, however some vendors override the
1312 # default value (e.g. Debian defaults to 2)
1313 security_level_range = {
1314 0,
1315 1, # OpenSSL default
1316 2, # Debian
1317 3,
1318 4,
1319 5,
1320 }
1321 self.assertIn(ctx.security_level, security_level_range)
1322
Christian Heimes2427b502013-11-23 11:24:32 +01001323 @unittest.skipUnless(have_verify_flags(),
1324 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01001325 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001326 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001327 # default value
1328 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1329 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001330 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1331 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1332 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1333 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1334 ctx.verify_flags = ssl.VERIFY_DEFAULT
1335 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001336 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1337 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001338 # supports any value
1339 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1340 self.assertEqual(ctx.verify_flags,
1341 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1342 with self.assertRaises(TypeError):
1343 ctx.verify_flags = None
1344
Antoine Pitrou152efa22010-05-16 18:19:27 +00001345 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001346 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001347 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001348 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001349 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1350 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001351 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001352 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001353 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001354 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001355 ctx.load_cert_chain(BADCERT)
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(EMPTYCERT)
1358 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001359 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001360 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1361 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1362 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001363 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001364 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001365 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001366 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001367 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001368 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1369 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001370 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001371 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001372 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001373 # Password protected key and cert
1374 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1375 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1376 ctx.load_cert_chain(CERTFILE_PROTECTED,
1377 password=bytearray(KEY_PASSWORD.encode()))
1378 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1379 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1380 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1381 bytearray(KEY_PASSWORD.encode()))
1382 with self.assertRaisesRegex(TypeError, "should be a string"):
1383 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1384 with self.assertRaises(ssl.SSLError):
1385 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1386 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1387 # openssl has a fixed limit on the password buffer.
1388 # PEM_BUFSIZE is generally set to 1kb.
1389 # Return a string larger than this.
1390 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1391 # Password callback
1392 def getpass_unicode():
1393 return KEY_PASSWORD
1394 def getpass_bytes():
1395 return KEY_PASSWORD.encode()
1396 def getpass_bytearray():
1397 return bytearray(KEY_PASSWORD.encode())
1398 def getpass_badpass():
1399 return "badpass"
1400 def getpass_huge():
1401 return b'a' * (1024 * 1024)
1402 def getpass_bad_type():
1403 return 9
1404 def getpass_exception():
1405 raise Exception('getpass error')
1406 class GetPassCallable:
1407 def __call__(self):
1408 return KEY_PASSWORD
1409 def getpass(self):
1410 return KEY_PASSWORD
1411 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1412 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1413 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1414 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1415 ctx.load_cert_chain(CERTFILE_PROTECTED,
1416 password=GetPassCallable().getpass)
1417 with self.assertRaises(ssl.SSLError):
1418 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1419 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1420 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1421 with self.assertRaisesRegex(TypeError, "must return a string"):
1422 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1423 with self.assertRaisesRegex(Exception, "getpass error"):
1424 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1425 # Make sure the password function isn't called if it isn't needed
1426 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001427
1428 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001429 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001430 ctx.load_verify_locations(CERTFILE)
1431 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1432 ctx.load_verify_locations(BYTES_CERTFILE)
1433 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1434 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001435 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001436 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001437 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001438 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001439 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001440 ctx.load_verify_locations(BADCERT)
1441 ctx.load_verify_locations(CERTFILE, CAPATH)
1442 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1443
Victor Stinner80f75e62011-01-29 11:31:20 +00001444 # Issue #10989: crash if the second argument type is invalid
1445 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1446
Christian Heimesefff7062013-11-21 03:35:02 +01001447 def test_load_verify_cadata(self):
1448 # test cadata
1449 with open(CAFILE_CACERT) as f:
1450 cacert_pem = f.read()
1451 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1452 with open(CAFILE_NEURONIO) as f:
1453 neuronio_pem = f.read()
1454 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1455
1456 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001457 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001458 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1459 ctx.load_verify_locations(cadata=cacert_pem)
1460 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1461 ctx.load_verify_locations(cadata=neuronio_pem)
1462 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1463 # cert already in hash table
1464 ctx.load_verify_locations(cadata=neuronio_pem)
1465 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1466
1467 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001468 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001469 combined = "\n".join((cacert_pem, neuronio_pem))
1470 ctx.load_verify_locations(cadata=combined)
1471 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1472
1473 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001474 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001475 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1476 neuronio_pem, "tail"]
1477 ctx.load_verify_locations(cadata="\n".join(combined))
1478 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1479
1480 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001481 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001482 ctx.load_verify_locations(cadata=cacert_der)
1483 ctx.load_verify_locations(cadata=neuronio_der)
1484 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1485 # cert already in hash table
1486 ctx.load_verify_locations(cadata=cacert_der)
1487 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1488
1489 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001490 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001491 combined = b"".join((cacert_der, neuronio_der))
1492 ctx.load_verify_locations(cadata=combined)
1493 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1494
1495 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001496 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001497 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1498
1499 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1500 ctx.load_verify_locations(cadata="broken")
1501 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1502 ctx.load_verify_locations(cadata=b"broken")
1503
1504
Paul Monsonf3550692019-06-19 13:09:54 -07001505 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001506 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001507 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001508 ctx.load_dh_params(DHFILE)
1509 if os.name != 'nt':
1510 ctx.load_dh_params(BYTES_DHFILE)
1511 self.assertRaises(TypeError, ctx.load_dh_params)
1512 self.assertRaises(TypeError, ctx.load_dh_params, None)
1513 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001514 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001515 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001516 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001517 ctx.load_dh_params(CERTFILE)
1518
Antoine Pitroub0182c82010-10-12 20:09:02 +00001519 def test_session_stats(self):
1520 for proto in PROTOCOLS:
1521 ctx = ssl.SSLContext(proto)
1522 self.assertEqual(ctx.session_stats(), {
1523 'number': 0,
1524 'connect': 0,
1525 'connect_good': 0,
1526 'connect_renegotiate': 0,
1527 'accept': 0,
1528 'accept_good': 0,
1529 'accept_renegotiate': 0,
1530 'hits': 0,
1531 'misses': 0,
1532 'timeouts': 0,
1533 'cache_full': 0,
1534 })
1535
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001536 def test_set_default_verify_paths(self):
1537 # There's not much we can do to test that it acts as expected,
1538 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001539 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001540 ctx.set_default_verify_paths()
1541
Antoine Pitrou501da612011-12-21 09:27:41 +01001542 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001543 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001544 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001545 ctx.set_ecdh_curve("prime256v1")
1546 ctx.set_ecdh_curve(b"prime256v1")
1547 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1548 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1549 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1550 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1551
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001552 @needs_sni
1553 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001554 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001555
1556 # set_servername_callback expects a callable, or None
1557 self.assertRaises(TypeError, ctx.set_servername_callback)
1558 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1559 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1560 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1561
1562 def dummycallback(sock, servername, ctx):
1563 pass
1564 ctx.set_servername_callback(None)
1565 ctx.set_servername_callback(dummycallback)
1566
1567 @needs_sni
1568 def test_sni_callback_refcycle(self):
1569 # Reference cycles through the servername callback are detected
1570 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001571 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001572 def dummycallback(sock, servername, ctx, cycle=ctx):
1573 pass
1574 ctx.set_servername_callback(dummycallback)
1575 wr = weakref.ref(ctx)
1576 del ctx, dummycallback
1577 gc.collect()
1578 self.assertIs(wr(), None)
1579
Christian Heimes9a5395a2013-06-17 15:44:12 +02001580 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001581 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001582 self.assertEqual(ctx.cert_store_stats(),
1583 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1584 ctx.load_cert_chain(CERTFILE)
1585 self.assertEqual(ctx.cert_store_stats(),
1586 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1587 ctx.load_verify_locations(CERTFILE)
1588 self.assertEqual(ctx.cert_store_stats(),
1589 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001590 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001591 self.assertEqual(ctx.cert_store_stats(),
1592 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1593
1594 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001595 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001596 self.assertEqual(ctx.get_ca_certs(), [])
1597 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1598 ctx.load_verify_locations(CERTFILE)
1599 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001600 # but CAFILE_CACERT is a CA cert
1601 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001602 self.assertEqual(ctx.get_ca_certs(),
1603 [{'issuer': ((('organizationName', 'Root CA'),),
1604 (('organizationalUnitName', 'http://www.cacert.org'),),
1605 (('commonName', 'CA Cert Signing Authority'),),
1606 (('emailAddress', 'support@cacert.org'),)),
1607 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1608 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1609 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001610 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001611 'subject': ((('organizationName', 'Root CA'),),
1612 (('organizationalUnitName', 'http://www.cacert.org'),),
1613 (('commonName', 'CA Cert Signing Authority'),),
1614 (('emailAddress', 'support@cacert.org'),)),
1615 'version': 3}])
1616
Martin Panterb55f8b72016-01-14 12:53:56 +00001617 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001618 pem = f.read()
1619 der = ssl.PEM_cert_to_DER_cert(pem)
1620 self.assertEqual(ctx.get_ca_certs(True), [der])
1621
Christian Heimes72d28502013-11-23 13:56:58 +01001622 def test_load_default_certs(self):
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()
1625
Christian Heimesa170fa12017-09-15 20:27:30 +02001626 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001627 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1628 ctx.load_default_certs()
1629
Christian Heimesa170fa12017-09-15 20:27:30 +02001630 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001631 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1632
Christian Heimesa170fa12017-09-15 20:27:30 +02001633 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001634 self.assertRaises(TypeError, ctx.load_default_certs, None)
1635 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1636
Benjamin Peterson91244e02014-10-03 18:17:15 -04001637 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimes598894f2016-09-05 23:19:05 +02001638 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001639 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001640 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001641 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001642 env["SSL_CERT_DIR"] = CAPATH
1643 env["SSL_CERT_FILE"] = CERTFILE
1644 ctx.load_default_certs()
1645 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1646
Benjamin Peterson91244e02014-10-03 18:17:15 -04001647 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001648 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001649 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001650 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001651 ctx.load_default_certs()
1652 stats = ctx.cert_store_stats()
1653
Christian Heimesa170fa12017-09-15 20:27:30 +02001654 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001655 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001656 env["SSL_CERT_DIR"] = CAPATH
1657 env["SSL_CERT_FILE"] = CERTFILE
1658 ctx.load_default_certs()
1659 stats["x509"] += 1
1660 self.assertEqual(ctx.cert_store_stats(), stats)
1661
Christian Heimes358cfd42016-09-10 22:43:48 +02001662 def _assert_context_options(self, ctx):
1663 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1664 if OP_NO_COMPRESSION != 0:
1665 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1666 OP_NO_COMPRESSION)
1667 if OP_SINGLE_DH_USE != 0:
1668 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1669 OP_SINGLE_DH_USE)
1670 if OP_SINGLE_ECDH_USE != 0:
1671 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1672 OP_SINGLE_ECDH_USE)
1673 if OP_CIPHER_SERVER_PREFERENCE != 0:
1674 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1675 OP_CIPHER_SERVER_PREFERENCE)
1676
Christian Heimes4c05b472013-11-23 15:58:30 +01001677 def test_create_default_context(self):
1678 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001679
Christian Heimesa170fa12017-09-15 20:27:30 +02001680 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001681 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001682 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001683 self._assert_context_options(ctx)
1684
Christian Heimes4c05b472013-11-23 15:58:30 +01001685 with open(SIGNING_CA) as f:
1686 cadata = f.read()
1687 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1688 cadata=cadata)
Christian Heimesa170fa12017-09-15 20:27:30 +02001689 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001690 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001691 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001692
1693 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001694 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001695 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001696 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001697
Christian Heimes67986f92013-11-23 22:43:47 +01001698 def test__create_stdlib_context(self):
1699 ctx = ssl._create_stdlib_context()
Christian Heimesa170fa12017-09-15 20:27:30 +02001700 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001701 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001702 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001703 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001704
1705 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1706 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1707 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001708 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001709
1710 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001711 cert_reqs=ssl.CERT_REQUIRED,
1712 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001713 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1714 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001715 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001716 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001717
1718 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001719 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001720 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001721 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001722
Christian Heimes1aa9a752013-12-02 02:41:19 +01001723 def test_check_hostname(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001724 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001725 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001726 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001727
Christian Heimese82c0342017-09-15 20:29:57 +02001728 # Auto set CERT_REQUIRED
1729 ctx.check_hostname = True
1730 self.assertTrue(ctx.check_hostname)
1731 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1732 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001733 ctx.verify_mode = ssl.CERT_REQUIRED
1734 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001735 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001736
Christian Heimese82c0342017-09-15 20:29:57 +02001737 # Changing verify_mode does not affect check_hostname
1738 ctx.check_hostname = False
1739 ctx.verify_mode = ssl.CERT_NONE
1740 ctx.check_hostname = False
1741 self.assertFalse(ctx.check_hostname)
1742 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1743 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001744 ctx.check_hostname = True
1745 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001746 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1747
1748 ctx.check_hostname = False
1749 ctx.verify_mode = ssl.CERT_OPTIONAL
1750 ctx.check_hostname = False
1751 self.assertFalse(ctx.check_hostname)
1752 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1753 # keep CERT_OPTIONAL
1754 ctx.check_hostname = True
1755 self.assertTrue(ctx.check_hostname)
1756 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001757
1758 # Cannot set CERT_NONE with check_hostname enabled
1759 with self.assertRaises(ValueError):
1760 ctx.verify_mode = ssl.CERT_NONE
1761 ctx.check_hostname = False
1762 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001763 ctx.verify_mode = ssl.CERT_NONE
1764 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001765
Christian Heimes5fe668c2016-09-12 00:01:11 +02001766 def test_context_client_server(self):
1767 # PROTOCOL_TLS_CLIENT has sane defaults
1768 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1769 self.assertTrue(ctx.check_hostname)
1770 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1771
1772 # PROTOCOL_TLS_SERVER has different but also sane defaults
1773 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1774 self.assertFalse(ctx.check_hostname)
1775 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1776
Christian Heimes4df60f12017-09-15 20:26:05 +02001777 def test_context_custom_class(self):
1778 class MySSLSocket(ssl.SSLSocket):
1779 pass
1780
1781 class MySSLObject(ssl.SSLObject):
1782 pass
1783
1784 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1785 ctx.sslsocket_class = MySSLSocket
1786 ctx.sslobject_class = MySSLObject
1787
1788 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1789 self.assertIsInstance(sock, MySSLSocket)
1790 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1791 self.assertIsInstance(obj, MySSLObject)
1792
Christian Heimes78c7d522019-06-03 21:00:10 +02001793 @unittest.skipUnless(IS_OPENSSL_1_1_1, "Test requires OpenSSL 1.1.1")
1794 def test_num_tickest(self):
1795 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1796 self.assertEqual(ctx.num_tickets, 2)
1797 ctx.num_tickets = 1
1798 self.assertEqual(ctx.num_tickets, 1)
1799 ctx.num_tickets = 0
1800 self.assertEqual(ctx.num_tickets, 0)
1801 with self.assertRaises(ValueError):
1802 ctx.num_tickets = -1
1803 with self.assertRaises(TypeError):
1804 ctx.num_tickets = None
1805
1806 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1807 self.assertEqual(ctx.num_tickets, 2)
1808 with self.assertRaises(ValueError):
1809 ctx.num_tickets = 1
1810
Antoine Pitrou152efa22010-05-16 18:19:27 +00001811
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001812class SSLErrorTests(unittest.TestCase):
1813
1814 def test_str(self):
1815 # The str() of a SSLError doesn't include the errno
1816 e = ssl.SSLError(1, "foo")
1817 self.assertEqual(str(e), "foo")
1818 self.assertEqual(e.errno, 1)
1819 # Same for a subclass
1820 e = ssl.SSLZeroReturnError(1, "foo")
1821 self.assertEqual(str(e), "foo")
1822 self.assertEqual(e.errno, 1)
1823
Paul Monsonf3550692019-06-19 13:09:54 -07001824 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001825 def test_lib_reason(self):
1826 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001827 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001828 with self.assertRaises(ssl.SSLError) as cm:
1829 ctx.load_dh_params(CERTFILE)
1830 self.assertEqual(cm.exception.library, 'PEM')
1831 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1832 s = str(cm.exception)
1833 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1834
1835 def test_subclass(self):
1836 # Check that the appropriate SSLError subclass is raised
1837 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001838 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1839 ctx.check_hostname = False
1840 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001841 with socket.create_server(("127.0.0.1", 0)) as s:
1842 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001843 c.setblocking(False)
1844 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001845 with self.assertRaises(ssl.SSLWantReadError) as cm:
1846 c.do_handshake()
1847 s = str(cm.exception)
1848 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1849 # For compatibility
1850 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1851
1852
Christian Heimes61d478c2018-01-27 15:51:38 +01001853 def test_bad_server_hostname(self):
1854 ctx = ssl.create_default_context()
1855 with self.assertRaises(ValueError):
1856 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1857 server_hostname="")
1858 with self.assertRaises(ValueError):
1859 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1860 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001861 with self.assertRaises(TypeError):
1862 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1863 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001864
1865
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001866class MemoryBIOTests(unittest.TestCase):
1867
1868 def test_read_write(self):
1869 bio = ssl.MemoryBIO()
1870 bio.write(b'foo')
1871 self.assertEqual(bio.read(), b'foo')
1872 self.assertEqual(bio.read(), b'')
1873 bio.write(b'foo')
1874 bio.write(b'bar')
1875 self.assertEqual(bio.read(), b'foobar')
1876 self.assertEqual(bio.read(), b'')
1877 bio.write(b'baz')
1878 self.assertEqual(bio.read(2), b'ba')
1879 self.assertEqual(bio.read(1), b'z')
1880 self.assertEqual(bio.read(1), b'')
1881
1882 def test_eof(self):
1883 bio = ssl.MemoryBIO()
1884 self.assertFalse(bio.eof)
1885 self.assertEqual(bio.read(), b'')
1886 self.assertFalse(bio.eof)
1887 bio.write(b'foo')
1888 self.assertFalse(bio.eof)
1889 bio.write_eof()
1890 self.assertFalse(bio.eof)
1891 self.assertEqual(bio.read(2), b'fo')
1892 self.assertFalse(bio.eof)
1893 self.assertEqual(bio.read(1), b'o')
1894 self.assertTrue(bio.eof)
1895 self.assertEqual(bio.read(), b'')
1896 self.assertTrue(bio.eof)
1897
1898 def test_pending(self):
1899 bio = ssl.MemoryBIO()
1900 self.assertEqual(bio.pending, 0)
1901 bio.write(b'foo')
1902 self.assertEqual(bio.pending, 3)
1903 for i in range(3):
1904 bio.read(1)
1905 self.assertEqual(bio.pending, 3-i-1)
1906 for i in range(3):
1907 bio.write(b'x')
1908 self.assertEqual(bio.pending, i+1)
1909 bio.read()
1910 self.assertEqual(bio.pending, 0)
1911
1912 def test_buffer_types(self):
1913 bio = ssl.MemoryBIO()
1914 bio.write(b'foo')
1915 self.assertEqual(bio.read(), b'foo')
1916 bio.write(bytearray(b'bar'))
1917 self.assertEqual(bio.read(), b'bar')
1918 bio.write(memoryview(b'baz'))
1919 self.assertEqual(bio.read(), b'baz')
1920
1921 def test_error_types(self):
1922 bio = ssl.MemoryBIO()
1923 self.assertRaises(TypeError, bio.write, 'foo')
1924 self.assertRaises(TypeError, bio.write, None)
1925 self.assertRaises(TypeError, bio.write, True)
1926 self.assertRaises(TypeError, bio.write, 1)
1927
1928
Christian Heimes9d50ab52018-02-27 10:17:30 +01001929class SSLObjectTests(unittest.TestCase):
1930 def test_private_init(self):
1931 bio = ssl.MemoryBIO()
1932 with self.assertRaisesRegex(TypeError, "public constructor"):
1933 ssl.SSLObject(bio, bio)
1934
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001935 def test_unwrap(self):
1936 client_ctx, server_ctx, hostname = testing_context()
1937 c_in = ssl.MemoryBIO()
1938 c_out = ssl.MemoryBIO()
1939 s_in = ssl.MemoryBIO()
1940 s_out = ssl.MemoryBIO()
1941 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1942 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1943
1944 # Loop on the handshake for a bit to get it settled
1945 for _ in range(5):
1946 try:
1947 client.do_handshake()
1948 except ssl.SSLWantReadError:
1949 pass
1950 if c_out.pending:
1951 s_in.write(c_out.read())
1952 try:
1953 server.do_handshake()
1954 except ssl.SSLWantReadError:
1955 pass
1956 if s_out.pending:
1957 c_in.write(s_out.read())
1958 # Now the handshakes should be complete (don't raise WantReadError)
1959 client.do_handshake()
1960 server.do_handshake()
1961
1962 # Now if we unwrap one side unilaterally, it should send close-notify
1963 # and raise WantReadError:
1964 with self.assertRaises(ssl.SSLWantReadError):
1965 client.unwrap()
1966
1967 # But server.unwrap() does not raise, because it reads the client's
1968 # close-notify:
1969 s_in.write(c_out.read())
1970 server.unwrap()
1971
1972 # And now that the client gets the server's close-notify, it doesn't
1973 # raise either.
1974 c_in.write(s_out.read())
1975 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001976
Martin Panter3840b2a2016-03-27 01:53:46 +00001977class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001978 """Tests that connect to a simple server running in the background"""
1979
1980 def setUp(self):
1981 server = ThreadedEchoServer(SIGNED_CERTFILE)
1982 self.server_addr = (HOST, server.port)
1983 server.__enter__()
1984 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001985
Antoine Pitrou480a1242010-04-28 21:37:09 +00001986 def test_connect(self):
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_NONE) as s:
1989 s.connect(self.server_addr)
1990 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001991 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001992
Martin Panter3840b2a2016-03-27 01:53:46 +00001993 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001994 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001995 cert_reqs=ssl.CERT_REQUIRED,
1996 ca_certs=SIGNING_CA) as s:
1997 s.connect(self.server_addr)
1998 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001999 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002000
Martin Panter3840b2a2016-03-27 01:53:46 +00002001 def test_connect_fail(self):
2002 # This should fail because we have no verification certs. Connection
2003 # failure crashes ThreadedEchoServer, so run this in an independent
2004 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02002005 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002006 cert_reqs=ssl.CERT_REQUIRED)
2007 self.addCleanup(s.close)
2008 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2009 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002010
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002011 def test_connect_ex(self):
2012 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02002013 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002014 cert_reqs=ssl.CERT_REQUIRED,
2015 ca_certs=SIGNING_CA)
2016 self.addCleanup(s.close)
2017 self.assertEqual(0, s.connect_ex(self.server_addr))
2018 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002019
2020 def test_non_blocking_connect_ex(self):
2021 # Issue #11326: non-blocking connect_ex() should allow handshake
2022 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02002023 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002024 cert_reqs=ssl.CERT_REQUIRED,
2025 ca_certs=SIGNING_CA,
2026 do_handshake_on_connect=False)
2027 self.addCleanup(s.close)
2028 s.setblocking(False)
2029 rc = s.connect_ex(self.server_addr)
2030 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2031 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2032 # Wait for connect to finish
2033 select.select([], [s], [], 5.0)
2034 # Non-blocking handshake
2035 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002036 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002037 s.do_handshake()
2038 break
2039 except ssl.SSLWantReadError:
2040 select.select([s], [], [], 5.0)
2041 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002042 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002043 # SSL established
2044 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002045
Antoine Pitrou152efa22010-05-16 18:19:27 +00002046 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002047 # Same as test_connect, but with a separately created context
Christian Heimesa170fa12017-09-15 20:27:30 +02002048 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002049 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2050 s.connect(self.server_addr)
2051 self.assertEqual({}, s.getpeercert())
2052 # Same with a server hostname
2053 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2054 server_hostname="dummy") as s:
2055 s.connect(self.server_addr)
2056 ctx.verify_mode = ssl.CERT_REQUIRED
2057 # This should succeed because we specify the root cert
2058 ctx.load_verify_locations(SIGNING_CA)
2059 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2060 s.connect(self.server_addr)
2061 cert = s.getpeercert()
2062 self.assertTrue(cert)
2063
2064 def test_connect_with_context_fail(self):
2065 # This should fail because we have no verification certs. Connection
2066 # failure crashes ThreadedEchoServer, so run this in an independent
2067 # test method.
Christian Heimesa170fa12017-09-15 20:27:30 +02002068 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002069 ctx.verify_mode = ssl.CERT_REQUIRED
2070 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
2071 self.addCleanup(s.close)
2072 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2073 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002074
2075 def test_connect_capath(self):
2076 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002077 # NOTE: the subject hashing algorithm has been changed between
2078 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2079 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002080 # filename) for this test to be portable across OpenSSL releases.
Christian Heimesa170fa12017-09-15 20:27:30 +02002081 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002082 ctx.verify_mode = ssl.CERT_REQUIRED
2083 ctx.load_verify_locations(capath=CAPATH)
2084 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2085 s.connect(self.server_addr)
2086 cert = s.getpeercert()
2087 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002088
Martin Panter3840b2a2016-03-27 01:53:46 +00002089 # Same with a bytes `capath` argument
Christian Heimesa170fa12017-09-15 20:27:30 +02002090 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002091 ctx.verify_mode = ssl.CERT_REQUIRED
2092 ctx.load_verify_locations(capath=BYTES_CAPATH)
2093 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2094 s.connect(self.server_addr)
2095 cert = s.getpeercert()
2096 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002097
Christian Heimesefff7062013-11-21 03:35:02 +01002098 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002099 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002100 pem = f.read()
2101 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimesa170fa12017-09-15 20:27:30 +02002102 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002103 ctx.verify_mode = ssl.CERT_REQUIRED
2104 ctx.load_verify_locations(cadata=pem)
2105 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2106 s.connect(self.server_addr)
2107 cert = s.getpeercert()
2108 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002109
Martin Panter3840b2a2016-03-27 01:53:46 +00002110 # same with DER
Christian Heimesa170fa12017-09-15 20:27:30 +02002111 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002112 ctx.verify_mode = ssl.CERT_REQUIRED
2113 ctx.load_verify_locations(cadata=der)
2114 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2115 s.connect(self.server_addr)
2116 cert = s.getpeercert()
2117 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002118
Antoine Pitroue3220242010-04-24 11:13:53 +00002119 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2120 def test_makefile_close(self):
2121 # Issue #5238: creating a file-like object with makefile() shouldn't
2122 # delay closing the underlying "real socket" (here tested with its
2123 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002124 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002125 ss.connect(self.server_addr)
2126 fd = ss.fileno()
2127 f = ss.makefile()
2128 f.close()
2129 # The fd is still open
2130 os.read(fd, 0)
2131 # Closing the SSL socket should close the fd too
2132 ss.close()
2133 gc.collect()
2134 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002135 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002136 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002137
Antoine Pitrou480a1242010-04-28 21:37:09 +00002138 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002139 s = socket.socket(socket.AF_INET)
2140 s.connect(self.server_addr)
2141 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002142 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002143 cert_reqs=ssl.CERT_NONE,
2144 do_handshake_on_connect=False)
2145 self.addCleanup(s.close)
2146 count = 0
2147 while True:
2148 try:
2149 count += 1
2150 s.do_handshake()
2151 break
2152 except ssl.SSLWantReadError:
2153 select.select([s], [], [])
2154 except ssl.SSLWantWriteError:
2155 select.select([], [s], [])
2156 if support.verbose:
2157 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002158
Antoine Pitrou480a1242010-04-28 21:37:09 +00002159 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002160 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002161
Martin Panter3840b2a2016-03-27 01:53:46 +00002162 def test_get_server_certificate_fail(self):
2163 # Connection failure crashes ThreadedEchoServer, so run this in an
2164 # independent test method
2165 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002166
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002167 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002168 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002169 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2170 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002171 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002172 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2173 s.connect(self.server_addr)
2174 # Error checking can happen at instantiation or when connecting
2175 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2176 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002177 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002178 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2179 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002180
Christian Heimes9a5395a2013-06-17 15:44:12 +02002181 def test_get_ca_certs_capath(self):
2182 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002183 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002184 ctx.load_verify_locations(capath=CAPATH)
2185 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002186 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2187 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002188 s.connect(self.server_addr)
2189 cert = s.getpeercert()
2190 self.assertTrue(cert)
2191 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002192
Christian Heimes575596e2013-12-15 21:49:17 +01002193 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01002194 def test_context_setget(self):
2195 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002196 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2197 ctx1.load_verify_locations(capath=CAPATH)
2198 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2199 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002200 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002201 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002202 ss.connect(self.server_addr)
2203 self.assertIs(ss.context, ctx1)
2204 self.assertIs(ss._sslobj.context, ctx1)
2205 ss.context = ctx2
2206 self.assertIs(ss.context, ctx2)
2207 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002208
2209 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2210 # A simple IO loop. Call func(*args) depending on the error we get
2211 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002212 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002213 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002214 count = 0
2215 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002216 if time.monotonic() > deadline:
2217 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002218 errno = None
2219 count += 1
2220 try:
2221 ret = func(*args)
2222 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002223 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002224 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002225 raise
2226 errno = e.errno
2227 # Get any data from the outgoing BIO irrespective of any error, and
2228 # send it to the socket.
2229 buf = outgoing.read()
2230 sock.sendall(buf)
2231 # If there's no error, we're done. For WANT_READ, we need to get
2232 # data from the socket and put it in the incoming BIO.
2233 if errno is None:
2234 break
2235 elif errno == ssl.SSL_ERROR_WANT_READ:
2236 buf = sock.recv(32768)
2237 if buf:
2238 incoming.write(buf)
2239 else:
2240 incoming.write_eof()
2241 if support.verbose:
2242 sys.stdout.write("Needed %d calls to complete %s().\n"
2243 % (count, func.__name__))
2244 return ret
2245
Martin Panter3840b2a2016-03-27 01:53:46 +00002246 def test_bio_handshake(self):
2247 sock = socket.socket(socket.AF_INET)
2248 self.addCleanup(sock.close)
2249 sock.connect(self.server_addr)
2250 incoming = ssl.MemoryBIO()
2251 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002252 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2253 self.assertTrue(ctx.check_hostname)
2254 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002255 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002256 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2257 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002258 self.assertIs(sslobj._sslobj.owner, sslobj)
2259 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002260 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002261 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002262 self.assertRaises(ValueError, sslobj.getpeercert)
2263 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2264 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2265 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2266 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002267 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002268 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002269 self.assertTrue(sslobj.getpeercert())
2270 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2271 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2272 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002273 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002274 except ssl.SSLSyscallError:
2275 # If the server shuts down the TCP connection without sending a
2276 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2277 pass
2278 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2279
2280 def test_bio_read_write_data(self):
2281 sock = socket.socket(socket.AF_INET)
2282 self.addCleanup(sock.close)
2283 sock.connect(self.server_addr)
2284 incoming = ssl.MemoryBIO()
2285 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002286 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002287 ctx.verify_mode = ssl.CERT_NONE
2288 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2289 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2290 req = b'FOO\n'
2291 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2292 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2293 self.assertEqual(buf, b'foo\n')
2294 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002295
2296
Martin Panter3840b2a2016-03-27 01:53:46 +00002297class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002298
Martin Panter3840b2a2016-03-27 01:53:46 +00002299 def test_timeout_connect_ex(self):
2300 # Issue #12065: on a timeout, connect_ex() should return the original
2301 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002302 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002303 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002304 cert_reqs=ssl.CERT_REQUIRED,
2305 do_handshake_on_connect=False)
2306 self.addCleanup(s.close)
2307 s.settimeout(0.0000001)
2308 rc = s.connect_ex((REMOTE_HOST, 443))
2309 if rc == 0:
2310 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002311 elif rc == errno.ENETUNREACH:
2312 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002313 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2314
Serhiy Storchaka16994912020-04-25 10:06:29 +03002315 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002316 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002317 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002318 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2319 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2320
Martin Panter3840b2a2016-03-27 01:53:46 +00002321
2322def _test_get_server_certificate(test, host, port, cert=None):
2323 pem = ssl.get_server_certificate((host, port))
2324 if not pem:
2325 test.fail("No server certificate on %s:%s!" % (host, port))
2326
2327 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2328 if not pem:
2329 test.fail("No server certificate on %s:%s!" % (host, port))
2330 if support.verbose:
2331 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2332
2333def _test_get_server_certificate_fail(test, host, port):
2334 try:
2335 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2336 except ssl.SSLError as x:
2337 #should fail
2338 if support.verbose:
2339 sys.stdout.write("%s\n" % x)
2340 else:
2341 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2342
2343
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002344from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002345
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002346class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002347
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002348 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002349
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002350 """A mildly complicated class, because we want it to work both
2351 with and without the SSL wrapper around the socket connection, so
2352 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002353
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002354 def __init__(self, server, connsock, addr):
2355 self.server = server
2356 self.running = False
2357 self.sock = connsock
2358 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002359 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002360 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002361 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002362 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002363
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002364 def wrap_conn(self):
2365 try:
2366 self.sslconn = self.server.context.wrap_socket(
2367 self.sock, server_side=True)
2368 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
2369 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002370 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002371 # We treat ConnectionResetError as though it were an
2372 # SSLError - OpenSSL on Ubuntu abruptly closes the
2373 # connection when asked to use an unsupported protocol.
2374 #
Christian Heimes529525f2018-05-23 22:24:45 +02002375 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2376 # tries to send session tickets after handshake.
2377 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002378 #
2379 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2380 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002381 self.server.conn_errors.append(str(e))
2382 if self.server.chatty:
2383 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2384 self.running = False
2385 self.close()
2386 return False
2387 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002388 # OSError may occur with wrong protocols, e.g. both
2389 # sides use PROTOCOL_TLS_SERVER.
2390 #
2391 # XXX Various errors can have happened here, for example
2392 # a mismatching protocol version, an invalid certificate,
2393 # or a low-level bug. This should be made more discriminating.
2394 #
2395 # bpo-31323: Store the exception as string to prevent
2396 # a reference leak: server -> conn_errors -> exception
2397 # -> traceback -> self (ConnectionHandler) -> server
2398 self.server.conn_errors.append(str(e))
2399 if self.server.chatty:
2400 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2401 self.running = False
2402 self.server.stop()
2403 self.close()
2404 return False
2405 else:
2406 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2407 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2408 cert = self.sslconn.getpeercert()
2409 if support.verbose and self.server.chatty:
2410 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2411 cert_binary = self.sslconn.getpeercert(True)
2412 if support.verbose and self.server.chatty:
2413 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2414 cipher = self.sslconn.cipher()
2415 if support.verbose and self.server.chatty:
2416 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
2417 sys.stdout.write(" server: selected protocol is now "
2418 + str(self.sslconn.selected_npn_protocol()) + "\n")
2419 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002420
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002421 def read(self):
2422 if self.sslconn:
2423 return self.sslconn.read()
2424 else:
2425 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002426
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002427 def write(self, bytes):
2428 if self.sslconn:
2429 return self.sslconn.write(bytes)
2430 else:
2431 return self.sock.send(bytes)
2432
2433 def close(self):
2434 if self.sslconn:
2435 self.sslconn.close()
2436 else:
2437 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002438
Antoine Pitrou480a1242010-04-28 21:37:09 +00002439 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002440 self.running = True
2441 if not self.server.starttls_server:
2442 if not self.wrap_conn():
2443 return
2444 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002445 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002446 msg = self.read()
2447 stripped = msg.strip()
2448 if not stripped:
2449 # eof, so quit this handler
2450 self.running = False
2451 try:
2452 self.sock = self.sslconn.unwrap()
2453 except OSError:
2454 # Many tests shut the TCP connection down
2455 # without an SSL shutdown. This causes
2456 # unwrap() to raise OSError with errno=0!
2457 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002458 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002459 self.sslconn = None
2460 self.close()
2461 elif stripped == b'over':
2462 if support.verbose and self.server.connectionchatty:
2463 sys.stdout.write(" server: client closed connection\n")
2464 self.close()
2465 return
2466 elif (self.server.starttls_server and
2467 stripped == b'STARTTLS'):
2468 if support.verbose and self.server.connectionchatty:
2469 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2470 self.write(b"OK\n")
2471 if not self.wrap_conn():
2472 return
2473 elif (self.server.starttls_server and self.sslconn
2474 and stripped == b'ENDTLS'):
2475 if support.verbose and self.server.connectionchatty:
2476 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2477 self.write(b"OK\n")
2478 self.sock = self.sslconn.unwrap()
2479 self.sslconn = None
2480 if support.verbose and self.server.connectionchatty:
2481 sys.stdout.write(" server: connection is now unencrypted...\n")
2482 elif stripped == b'CB tls-unique':
2483 if support.verbose and self.server.connectionchatty:
2484 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2485 data = self.sslconn.get_channel_binding("tls-unique")
2486 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002487 elif stripped == b'PHA':
2488 if support.verbose and self.server.connectionchatty:
2489 sys.stdout.write(" server: initiating post handshake auth\n")
2490 try:
2491 self.sslconn.verify_client_post_handshake()
2492 except ssl.SSLError as e:
2493 self.write(repr(e).encode("us-ascii") + b"\n")
2494 else:
2495 self.write(b"OK\n")
2496 elif stripped == b'HASCERT':
2497 if self.sslconn.getpeercert() is not None:
2498 self.write(b'TRUE\n')
2499 else:
2500 self.write(b'FALSE\n')
2501 elif stripped == b'GETCERT':
2502 cert = self.sslconn.getpeercert()
2503 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002504 else:
2505 if (support.verbose and
2506 self.server.connectionchatty):
2507 ctype = (self.sslconn and "encrypted") or "unencrypted"
2508 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2509 % (msg, ctype, msg.lower(), ctype))
2510 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002511 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002512 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2513 # when connection is not shut down gracefully.
2514 if self.server.chatty and support.verbose:
2515 sys.stdout.write(
2516 " Connection reset by peer: {}\n".format(
2517 self.addr)
2518 )
2519 self.close()
2520 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002521 except ssl.SSLError as err:
2522 # On Windows sometimes test_pha_required_nocert receives the
2523 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2524 # before the 'tlsv13 alert certificate required' exception.
2525 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2526 # is received test_pha_required_nocert fails with ConnectionResetError
2527 # because the underlying socket is closed
2528 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2529 if self.server.chatty and support.verbose:
2530 sys.stdout.write(err.args[1])
2531 # test_pha_required_nocert is expecting this exception
2532 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002533 except OSError:
2534 if self.server.chatty:
2535 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002536 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002537 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002538
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002539 # normally, we'd just stop here, but for the test
2540 # harness, we want to stop the server
2541 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002542
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002543 def __init__(self, certificate=None, ssl_version=None,
2544 certreqs=None, cacerts=None,
2545 chatty=True, connectionchatty=False, starttls_server=False,
2546 npn_protocols=None, alpn_protocols=None,
2547 ciphers=None, context=None):
2548 if context:
2549 self.context = context
2550 else:
2551 self.context = ssl.SSLContext(ssl_version
2552 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002553 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002554 self.context.verify_mode = (certreqs if certreqs is not None
2555 else ssl.CERT_NONE)
2556 if cacerts:
2557 self.context.load_verify_locations(cacerts)
2558 if certificate:
2559 self.context.load_cert_chain(certificate)
2560 if npn_protocols:
2561 self.context.set_npn_protocols(npn_protocols)
2562 if alpn_protocols:
2563 self.context.set_alpn_protocols(alpn_protocols)
2564 if ciphers:
2565 self.context.set_ciphers(ciphers)
2566 self.chatty = chatty
2567 self.connectionchatty = connectionchatty
2568 self.starttls_server = starttls_server
2569 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002570 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002571 self.flag = None
2572 self.active = False
2573 self.selected_npn_protocols = []
2574 self.selected_alpn_protocols = []
2575 self.shared_ciphers = []
2576 self.conn_errors = []
2577 threading.Thread.__init__(self)
2578 self.daemon = True
2579
2580 def __enter__(self):
2581 self.start(threading.Event())
2582 self.flag.wait()
2583 return self
2584
2585 def __exit__(self, *args):
2586 self.stop()
2587 self.join()
2588
2589 def start(self, flag=None):
2590 self.flag = flag
2591 threading.Thread.start(self)
2592
2593 def run(self):
2594 self.sock.settimeout(0.05)
2595 self.sock.listen()
2596 self.active = True
2597 if self.flag:
2598 # signal an event
2599 self.flag.set()
2600 while self.active:
2601 try:
2602 newconn, connaddr = self.sock.accept()
2603 if support.verbose and self.chatty:
2604 sys.stdout.write(' server: new connection from '
2605 + repr(connaddr) + '\n')
2606 handler = self.ConnectionHandler(self, newconn, connaddr)
2607 handler.start()
2608 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002609 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002610 pass
2611 except KeyboardInterrupt:
2612 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002613 except BaseException as e:
2614 if support.verbose and self.chatty:
2615 sys.stdout.write(
2616 ' connection handling failed: ' + repr(e) + '\n')
2617
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002618 self.sock.close()
2619
2620 def stop(self):
2621 self.active = False
2622
2623class AsyncoreEchoServer(threading.Thread):
2624
2625 # this one's based on asyncore.dispatcher
2626
2627 class EchoServer (asyncore.dispatcher):
2628
2629 class ConnectionHandler(asyncore.dispatcher_with_send):
2630
2631 def __init__(self, conn, certfile):
2632 self.socket = test_wrap_socket(conn, server_side=True,
2633 certfile=certfile,
2634 do_handshake_on_connect=False)
2635 asyncore.dispatcher_with_send.__init__(self, self.socket)
2636 self._ssl_accepting = True
2637 self._do_ssl_handshake()
2638
2639 def readable(self):
2640 if isinstance(self.socket, ssl.SSLSocket):
2641 while self.socket.pending() > 0:
2642 self.handle_read_event()
2643 return True
2644
2645 def _do_ssl_handshake(self):
2646 try:
2647 self.socket.do_handshake()
2648 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2649 return
2650 except ssl.SSLEOFError:
2651 return self.handle_close()
2652 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002653 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002654 except OSError as err:
2655 if err.args[0] == errno.ECONNABORTED:
2656 return self.handle_close()
2657 else:
2658 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002659
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002660 def handle_read(self):
2661 if self._ssl_accepting:
2662 self._do_ssl_handshake()
2663 else:
2664 data = self.recv(1024)
2665 if support.verbose:
2666 sys.stdout.write(" server: read %s from client\n" % repr(data))
2667 if not data:
2668 self.close()
2669 else:
2670 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002671
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002672 def handle_close(self):
2673 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002674 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002675 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002676
2677 def handle_error(self):
2678 raise
2679
Trent Nelson78520002008-04-10 20:54:35 +00002680 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002681 self.certfile = certfile
2682 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002683 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002684 asyncore.dispatcher.__init__(self, sock)
2685 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002686
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002687 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002688 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002689 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2690 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002691
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002692 def handle_error(self):
2693 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002694
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002695 def __init__(self, certfile):
2696 self.flag = None
2697 self.active = False
2698 self.server = self.EchoServer(certfile)
2699 self.port = self.server.port
2700 threading.Thread.__init__(self)
2701 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002702
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002703 def __str__(self):
2704 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002705
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002706 def __enter__(self):
2707 self.start(threading.Event())
2708 self.flag.wait()
2709 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002710
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002711 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002712 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002713 sys.stdout.write(" cleanup: stopping server.\n")
2714 self.stop()
2715 if support.verbose:
2716 sys.stdout.write(" cleanup: joining server thread.\n")
2717 self.join()
2718 if support.verbose:
2719 sys.stdout.write(" cleanup: successfully joined.\n")
2720 # make sure that ConnectionHandler is removed from socket_map
2721 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002722
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002723 def start (self, flag=None):
2724 self.flag = flag
2725 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002726
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002727 def run(self):
2728 self.active = True
2729 if self.flag:
2730 self.flag.set()
2731 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002732 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002733 asyncore.loop(1)
2734 except:
2735 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002736
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002737 def stop(self):
2738 self.active = False
2739 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002740
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002741def server_params_test(client_context, server_context, indata=b"FOO\n",
2742 chatty=True, connectionchatty=False, sni_name=None,
2743 session=None):
2744 """
2745 Launch a server, connect a client to it and try various reads
2746 and writes.
2747 """
2748 stats = {}
2749 server = ThreadedEchoServer(context=server_context,
2750 chatty=chatty,
2751 connectionchatty=False)
2752 with server:
2753 with client_context.wrap_socket(socket.socket(),
2754 server_hostname=sni_name, session=session) as s:
2755 s.connect((HOST, server.port))
2756 for arg in [indata, bytearray(indata), memoryview(indata)]:
2757 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002758 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002759 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002760 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002761 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002762 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002763 if connectionchatty:
2764 if support.verbose:
2765 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002766 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002767 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002768 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2769 % (outdata[:20], len(outdata),
2770 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002771 s.write(b"over\n")
2772 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002773 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002774 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002775 stats.update({
2776 'compression': s.compression(),
2777 'cipher': s.cipher(),
2778 'peercert': s.getpeercert(),
2779 'client_alpn_protocol': s.selected_alpn_protocol(),
2780 'client_npn_protocol': s.selected_npn_protocol(),
2781 'version': s.version(),
2782 'session_reused': s.session_reused,
2783 'session': s.session,
2784 })
2785 s.close()
2786 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2787 stats['server_npn_protocols'] = server.selected_npn_protocols
2788 stats['server_shared_ciphers'] = server.shared_ciphers
2789 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002790
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002791def try_protocol_combo(server_protocol, client_protocol, expect_success,
2792 certsreqs=None, server_options=0, client_options=0):
2793 """
2794 Try to SSL-connect using *client_protocol* to *server_protocol*.
2795 If *expect_success* is true, assert that the connection succeeds,
2796 if it's false, assert that the connection fails.
2797 Also, if *expect_success* is a string, assert that it is the protocol
2798 version actually used by the connection.
2799 """
2800 if certsreqs is None:
2801 certsreqs = ssl.CERT_NONE
2802 certtype = {
2803 ssl.CERT_NONE: "CERT_NONE",
2804 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2805 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2806 }[certsreqs]
2807 if support.verbose:
2808 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2809 sys.stdout.write(formatstr %
2810 (ssl.get_protocol_name(client_protocol),
2811 ssl.get_protocol_name(server_protocol),
2812 certtype))
2813 client_context = ssl.SSLContext(client_protocol)
2814 client_context.options |= client_options
2815 server_context = ssl.SSLContext(server_protocol)
2816 server_context.options |= server_options
2817
Victor Stinner3ef63442019-02-19 18:06:03 +01002818 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2819 if (min_version is not None
2820 # SSLContext.minimum_version is only available on recent OpenSSL
2821 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2822 and hasattr(server_context, 'minimum_version')
2823 and server_protocol == ssl.PROTOCOL_TLS
2824 and server_context.minimum_version > min_version):
2825 # If OpenSSL configuration is strict and requires more recent TLS
2826 # version, we have to change the minimum to test old TLS versions.
2827 server_context.minimum_version = min_version
2828
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002829 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2830 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2831 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002832 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002833 client_context.set_ciphers("ALL")
2834
Christian Heimesf6c6b582021-03-18 23:06:50 +01002835 seclevel_workaround(server_context, client_context)
2836
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002837 for ctx in (client_context, server_context):
2838 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002839 ctx.load_cert_chain(SIGNED_CERTFILE)
2840 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002841 try:
2842 stats = server_params_test(client_context, server_context,
2843 chatty=False, connectionchatty=False)
2844 # Protocol mismatch can result in either an SSLError, or a
2845 # "Connection reset by peer" error.
2846 except ssl.SSLError:
2847 if expect_success:
2848 raise
2849 except OSError as e:
2850 if expect_success or e.errno != errno.ECONNRESET:
2851 raise
2852 else:
2853 if not expect_success:
2854 raise AssertionError(
2855 "Client protocol %s succeeded with server protocol %s!"
2856 % (ssl.get_protocol_name(client_protocol),
2857 ssl.get_protocol_name(server_protocol)))
2858 elif (expect_success is not True
2859 and expect_success != stats['version']):
2860 raise AssertionError("version mismatch: expected %r, got %r"
2861 % (expect_success, stats['version']))
2862
2863
2864class ThreadedTests(unittest.TestCase):
2865
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002866 def test_echo(self):
2867 """Basic test of an SSL client connecting to a server"""
2868 if support.verbose:
2869 sys.stdout.write("\n")
2870 for protocol in PROTOCOLS:
2871 if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
2872 continue
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02002873 if not has_tls_protocol(protocol):
2874 continue
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002875 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2876 context = ssl.SSLContext(protocol)
2877 context.load_cert_chain(CERTFILE)
Christian Heimesf6c6b582021-03-18 23:06:50 +01002878 seclevel_workaround(context)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002879 server_params_test(context, context,
2880 chatty=True, connectionchatty=True)
2881
Christian Heimesa170fa12017-09-15 20:27:30 +02002882 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002883
2884 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2885 server_params_test(client_context=client_context,
2886 server_context=server_context,
2887 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002888 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002889
2890 client_context.check_hostname = False
2891 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2892 with self.assertRaises(ssl.SSLError) as e:
2893 server_params_test(client_context=server_context,
2894 server_context=client_context,
2895 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002896 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002897 self.assertIn('called a function you should not call',
2898 str(e.exception))
2899
2900 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2901 with self.assertRaises(ssl.SSLError) as e:
2902 server_params_test(client_context=server_context,
2903 server_context=server_context,
2904 chatty=True, connectionchatty=True)
2905 self.assertIn('called a function you should not call',
2906 str(e.exception))
2907
2908 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2909 with self.assertRaises(ssl.SSLError) as e:
2910 server_params_test(client_context=server_context,
2911 server_context=client_context,
2912 chatty=True, connectionchatty=True)
2913 self.assertIn('called a function you should not call',
2914 str(e.exception))
2915
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002916 def test_getpeercert(self):
2917 if support.verbose:
2918 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002919
2920 client_context, server_context, hostname = testing_context()
2921 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002922 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002923 with client_context.wrap_socket(socket.socket(),
2924 do_handshake_on_connect=False,
2925 server_hostname=hostname) as s:
2926 s.connect((HOST, server.port))
2927 # getpeercert() raise ValueError while the handshake isn't
2928 # done.
2929 with self.assertRaises(ValueError):
2930 s.getpeercert()
2931 s.do_handshake()
2932 cert = s.getpeercert()
2933 self.assertTrue(cert, "Can't get peer certificate.")
2934 cipher = s.cipher()
2935 if support.verbose:
2936 sys.stdout.write(pprint.pformat(cert) + '\n')
2937 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2938 if 'subject' not in cert:
2939 self.fail("No subject field in certificate: %s." %
2940 pprint.pformat(cert))
2941 if ((('organizationName', 'Python Software Foundation'),)
2942 not in cert['subject']):
2943 self.fail(
2944 "Missing or invalid 'organizationName' field in certificate subject; "
2945 "should be 'Python Software Foundation'.")
2946 self.assertIn('notBefore', cert)
2947 self.assertIn('notAfter', cert)
2948 before = ssl.cert_time_to_seconds(cert['notBefore'])
2949 after = ssl.cert_time_to_seconds(cert['notAfter'])
2950 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002951
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002952 @unittest.skipUnless(have_verify_flags(),
2953 "verify_flags need OpenSSL > 0.9.8")
2954 def test_crl_check(self):
2955 if support.verbose:
2956 sys.stdout.write("\n")
2957
Christian Heimesa170fa12017-09-15 20:27:30 +02002958 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002959
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002960 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002961 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002962
2963 # VERIFY_DEFAULT should pass
2964 server = ThreadedEchoServer(context=server_context, chatty=True)
2965 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002966 with client_context.wrap_socket(socket.socket(),
2967 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002968 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002969 cert = s.getpeercert()
2970 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002971
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002972 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002973 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002974
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002975 server = ThreadedEchoServer(context=server_context, chatty=True)
2976 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002977 with client_context.wrap_socket(socket.socket(),
2978 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002979 with self.assertRaisesRegex(ssl.SSLError,
2980 "certificate verify failed"):
2981 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002982
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002983 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002984 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002985
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002986 server = ThreadedEchoServer(context=server_context, chatty=True)
2987 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002988 with client_context.wrap_socket(socket.socket(),
2989 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002990 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002991 cert = s.getpeercert()
2992 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002993
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002994 def test_check_hostname(self):
2995 if support.verbose:
2996 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002997
Christian Heimesa170fa12017-09-15 20:27:30 +02002998 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002999
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003000 # correct hostname should verify
3001 server = ThreadedEchoServer(context=server_context, chatty=True)
3002 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003003 with client_context.wrap_socket(socket.socket(),
3004 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003005 s.connect((HOST, server.port))
3006 cert = s.getpeercert()
3007 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003008
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003009 # incorrect hostname should raise an exception
3010 server = ThreadedEchoServer(context=server_context, chatty=True)
3011 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003012 with client_context.wrap_socket(socket.socket(),
3013 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01003014 with self.assertRaisesRegex(
3015 ssl.CertificateError,
3016 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003017 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003018
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003019 # missing server_hostname arg should cause an exception, too
3020 server = ThreadedEchoServer(context=server_context, chatty=True)
3021 with server:
3022 with socket.socket() as s:
3023 with self.assertRaisesRegex(ValueError,
3024 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02003025 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003026
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003027 def test_ecc_cert(self):
3028 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3029 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003030 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003031 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3032
3033 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3034 # load ECC cert
3035 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3036
3037 # correct hostname should verify
3038 server = ThreadedEchoServer(context=server_context, chatty=True)
3039 with server:
3040 with client_context.wrap_socket(socket.socket(),
3041 server_hostname=hostname) as s:
3042 s.connect((HOST, server.port))
3043 cert = s.getpeercert()
3044 self.assertTrue(cert, "Can't get peer certificate.")
3045 cipher = s.cipher()[0].split('-')
3046 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3047
3048 def test_dual_rsa_ecc(self):
3049 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3050 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003051 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3052 # algorithms.
3053 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003054 # only ECDSA certs
3055 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3056 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3057
3058 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3059 # load ECC and RSA key/cert pairs
3060 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3061 server_context.load_cert_chain(SIGNED_CERTFILE)
3062
3063 # correct hostname should verify
3064 server = ThreadedEchoServer(context=server_context, chatty=True)
3065 with server:
3066 with client_context.wrap_socket(socket.socket(),
3067 server_hostname=hostname) as s:
3068 s.connect((HOST, server.port))
3069 cert = s.getpeercert()
3070 self.assertTrue(cert, "Can't get peer certificate.")
3071 cipher = s.cipher()[0].split('-')
3072 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3073
Christian Heimes66e57422018-01-29 14:25:13 +01003074 def test_check_hostname_idn(self):
3075 if support.verbose:
3076 sys.stdout.write("\n")
3077
Christian Heimes11a14932018-02-24 02:35:08 +01003078 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003079 server_context.load_cert_chain(IDNSANSFILE)
3080
Christian Heimes11a14932018-02-24 02:35:08 +01003081 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003082 context.verify_mode = ssl.CERT_REQUIRED
3083 context.check_hostname = True
3084 context.load_verify_locations(SIGNING_CA)
3085
3086 # correct hostname should verify, when specified in several
3087 # different ways
3088 idn_hostnames = [
3089 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003090 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003091 ('xn--knig-5qa.idn.pythontest.net',
3092 'xn--knig-5qa.idn.pythontest.net'),
3093 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003094 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003095
3096 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003097 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003098 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3099 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3100 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003101 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3102
3103 # ('königsgäßchen.idna2008.pythontest.net',
3104 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3105 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3106 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3107 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3108 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3109
Christian Heimes66e57422018-01-29 14:25:13 +01003110 ]
3111 for server_hostname, expected_hostname in idn_hostnames:
3112 server = ThreadedEchoServer(context=server_context, chatty=True)
3113 with server:
3114 with context.wrap_socket(socket.socket(),
3115 server_hostname=server_hostname) as s:
3116 self.assertEqual(s.server_hostname, expected_hostname)
3117 s.connect((HOST, server.port))
3118 cert = s.getpeercert()
3119 self.assertEqual(s.server_hostname, expected_hostname)
3120 self.assertTrue(cert, "Can't get peer certificate.")
3121
Christian Heimes66e57422018-01-29 14:25:13 +01003122 # incorrect hostname should raise an exception
3123 server = ThreadedEchoServer(context=server_context, chatty=True)
3124 with server:
3125 with context.wrap_socket(socket.socket(),
3126 server_hostname="python.example.org") as s:
3127 with self.assertRaises(ssl.CertificateError):
3128 s.connect((HOST, server.port))
3129
Christian Heimes529525f2018-05-23 22:24:45 +02003130 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003131 """Connecting when the server rejects the client's certificate
3132
3133 Launch a server with CERT_REQUIRED, and check that trying to
3134 connect to it with a wrong client certificate fails.
3135 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003136 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003137 # load client cert that is not signed by trusted CA
3138 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003139 # require TLS client authentication
3140 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003141 # TLS 1.3 has different handshake
3142 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003143
3144 server = ThreadedEchoServer(
3145 context=server_context, chatty=True, connectionchatty=True,
3146 )
3147
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003148 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003149 client_context.wrap_socket(socket.socket(),
3150 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003151 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003152 # Expect either an SSL error about the server rejecting
3153 # the connection, or a low-level connection reset (which
3154 # sometimes happens on Windows)
3155 s.connect((HOST, server.port))
3156 except ssl.SSLError as e:
3157 if support.verbose:
3158 sys.stdout.write("\nSSLError is %r\n" % e)
3159 except OSError as e:
3160 if e.errno != errno.ECONNRESET:
3161 raise
3162 if support.verbose:
3163 sys.stdout.write("\nsocket.error is %r\n" % e)
3164 else:
3165 self.fail("Use of invalid cert should have failed!")
3166
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003167 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003168 def test_wrong_cert_tls13(self):
3169 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003170 # load client cert that is not signed by trusted CA
3171 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003172 server_context.verify_mode = ssl.CERT_REQUIRED
3173 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3174 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3175
3176 server = ThreadedEchoServer(
3177 context=server_context, chatty=True, connectionchatty=True,
3178 )
3179 with server, \
3180 client_context.wrap_socket(socket.socket(),
3181 server_hostname=hostname) as s:
3182 # TLS 1.3 perform client cert exchange after handshake
3183 s.connect((HOST, server.port))
3184 try:
3185 s.write(b'data')
3186 s.read(4)
3187 except ssl.SSLError as e:
3188 if support.verbose:
3189 sys.stdout.write("\nSSLError is %r\n" % e)
3190 except OSError as e:
3191 if e.errno != errno.ECONNRESET:
3192 raise
3193 if support.verbose:
3194 sys.stdout.write("\nsocket.error is %r\n" % e)
3195 else:
3196 self.fail("Use of invalid cert should have failed!")
3197
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003198 def test_rude_shutdown(self):
3199 """A brutal shutdown of an SSL server should raise an OSError
3200 in the client when attempting handshake.
3201 """
3202 listener_ready = threading.Event()
3203 listener_gone = threading.Event()
3204
3205 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003206 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003207
3208 # `listener` runs in a thread. It sits in an accept() until
3209 # the main thread connects. Then it rudely closes the socket,
3210 # and sets Event `listener_gone` to let the main thread know
3211 # the socket is gone.
3212 def listener():
3213 s.listen()
3214 listener_ready.set()
3215 newsock, addr = s.accept()
3216 newsock.close()
3217 s.close()
3218 listener_gone.set()
3219
3220 def connector():
3221 listener_ready.wait()
3222 with socket.socket() as c:
3223 c.connect((HOST, port))
3224 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003225 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003226 ssl_sock = test_wrap_socket(c)
3227 except OSError:
3228 pass
3229 else:
3230 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003231
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003232 t = threading.Thread(target=listener)
3233 t.start()
3234 try:
3235 connector()
3236 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003237 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003238
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003239 def test_ssl_cert_verify_error(self):
3240 if support.verbose:
3241 sys.stdout.write("\n")
3242
3243 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3244 server_context.load_cert_chain(SIGNED_CERTFILE)
3245
3246 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3247
3248 server = ThreadedEchoServer(context=server_context, chatty=True)
3249 with server:
3250 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003251 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003252 try:
3253 s.connect((HOST, server.port))
3254 except ssl.SSLError as e:
3255 msg = 'unable to get local issuer certificate'
3256 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3257 self.assertEqual(e.verify_code, 20)
3258 self.assertEqual(e.verify_message, msg)
3259 self.assertIn(msg, repr(e))
3260 self.assertIn('certificate verify failed', repr(e))
3261
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003262 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003263 def test_protocol_sslv2(self):
3264 """Connecting to an SSLv2 server with various client options"""
3265 if support.verbose:
3266 sys.stdout.write("\n")
3267 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3268 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3269 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003270 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003271 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003272 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3273 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3274 # SSLv23 client with specific SSL options
3275 if no_sslv2_implies_sslv3_hello():
3276 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003277 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003278 client_options=ssl.OP_NO_SSLv2)
Christian Heimesa170fa12017-09-15 20:27:30 +02003279 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003280 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003281 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003282 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003283
Christian Heimesa170fa12017-09-15 20:27:30 +02003284 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003285 """Connecting to an SSLv23 server with various client options"""
3286 if support.verbose:
3287 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003288 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003289 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003290 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003291 except OSError as x:
3292 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3293 if support.verbose:
3294 sys.stdout.write(
3295 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3296 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003297 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003298 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3299 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003300 if has_tls_version('TLSv1'):
3301 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003302
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003303 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003304 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3305 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003306 if has_tls_version('TLSv1'):
3307 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003308
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, ssl.CERT_REQUIRED)
3311 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003312 if has_tls_version('TLSv1'):
3313 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003314
3315 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003316 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003317 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003318 server_options=ssl.OP_NO_SSLv3)
3319 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003320 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003321 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003322 if has_tls_version('TLSv1'):
3323 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3324 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003325
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003326 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003327 def test_protocol_sslv3(self):
3328 """Connecting to an SSLv3 server with various client options"""
3329 if support.verbose:
3330 sys.stdout.write("\n")
3331 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3332 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3333 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003334 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003335 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003336 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003337 client_options=ssl.OP_NO_SSLv3)
3338 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3339 if no_sslv2_implies_sslv3_hello():
3340 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003341 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003342 False, client_options=ssl.OP_NO_SSLv2)
3343
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003344 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003345 def test_protocol_tlsv1(self):
3346 """Connecting to a TLSv1 server with various client options"""
3347 if support.verbose:
3348 sys.stdout.write("\n")
3349 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3350 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3351 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003352 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003353 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003354 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003355 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003356 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003357 client_options=ssl.OP_NO_TLSv1)
3358
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003359 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003360 def test_protocol_tlsv1_1(self):
3361 """Connecting to a TLSv1.1 server with various client options.
3362 Testing against older TLS versions."""
3363 if support.verbose:
3364 sys.stdout.write("\n")
3365 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003366 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003367 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003368 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003369 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003370 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003371 client_options=ssl.OP_NO_TLSv1_1)
3372
Christian Heimesa170fa12017-09-15 20:27:30 +02003373 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003374 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3375 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003376
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003377 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003378 def test_protocol_tlsv1_2(self):
3379 """Connecting to a TLSv1.2 server with various client options.
3380 Testing against older TLS versions."""
3381 if support.verbose:
3382 sys.stdout.write("\n")
3383 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3384 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3385 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003386 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003387 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003388 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003389 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003390 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003391 client_options=ssl.OP_NO_TLSv1_2)
3392
Christian Heimesa170fa12017-09-15 20:27:30 +02003393 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003394 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3395 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3396 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3397 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3398
3399 def test_starttls(self):
3400 """Switching from clear text to encrypted and back again."""
3401 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3402
3403 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003404 starttls_server=True,
3405 chatty=True,
3406 connectionchatty=True)
3407 wrapped = False
3408 with server:
3409 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003410 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003411 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003412 if support.verbose:
3413 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003414 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003415 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003416 sys.stdout.write(
3417 " client: sending %r...\n" % indata)
3418 if wrapped:
3419 conn.write(indata)
3420 outdata = conn.read()
3421 else:
3422 s.send(indata)
3423 outdata = s.recv(1024)
3424 msg = outdata.strip().lower()
3425 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3426 # STARTTLS ok, switch to secure mode
3427 if support.verbose:
3428 sys.stdout.write(
3429 " client: read %r from server, starting TLS...\n"
3430 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003431 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003432 wrapped = True
3433 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3434 # ENDTLS ok, switch back to clear text
3435 if support.verbose:
3436 sys.stdout.write(
3437 " client: read %r from server, ending TLS...\n"
3438 % msg)
3439 s = conn.unwrap()
3440 wrapped = False
3441 else:
3442 if support.verbose:
3443 sys.stdout.write(
3444 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003445 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003446 sys.stdout.write(" client: closing connection.\n")
3447 if wrapped:
3448 conn.write(b"over\n")
3449 else:
3450 s.send(b"over\n")
3451 if wrapped:
3452 conn.close()
3453 else:
3454 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003455
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003456 def test_socketserver(self):
3457 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003458 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003459 # try to connect
3460 if support.verbose:
3461 sys.stdout.write('\n')
3462 with open(CERTFILE, 'rb') as f:
3463 d1 = f.read()
3464 d2 = ''
3465 # now fetch the same data from the HTTPS server
3466 url = 'https://localhost:%d/%s' % (
3467 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003468 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003469 f = urllib.request.urlopen(url, context=context)
3470 try:
3471 dlen = f.info().get("content-length")
3472 if dlen and (int(dlen) > 0):
3473 d2 = f.read(int(dlen))
3474 if support.verbose:
3475 sys.stdout.write(
3476 " client: read %d bytes from remote server '%s'\n"
3477 % (len(d2), server))
3478 finally:
3479 f.close()
3480 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003481
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003482 def test_asyncore_server(self):
3483 """Check the example asyncore integration."""
3484 if support.verbose:
3485 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003486
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003487 indata = b"FOO\n"
3488 server = AsyncoreEchoServer(CERTFILE)
3489 with server:
3490 s = test_wrap_socket(socket.socket())
3491 s.connect(('127.0.0.1', server.port))
3492 if support.verbose:
3493 sys.stdout.write(
3494 " client: sending %r...\n" % indata)
3495 s.write(indata)
3496 outdata = s.read()
3497 if support.verbose:
3498 sys.stdout.write(" client: read %r\n" % outdata)
3499 if outdata != indata.lower():
3500 self.fail(
3501 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3502 % (outdata[:20], len(outdata),
3503 indata[:20].lower(), len(indata)))
3504 s.write(b"over\n")
3505 if support.verbose:
3506 sys.stdout.write(" client: closing connection.\n")
3507 s.close()
3508 if support.verbose:
3509 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003510
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003511 def test_recv_send(self):
3512 """Test recv(), send() and friends."""
3513 if support.verbose:
3514 sys.stdout.write("\n")
3515
3516 server = ThreadedEchoServer(CERTFILE,
3517 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003518 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003519 cacerts=CERTFILE,
3520 chatty=True,
3521 connectionchatty=False)
3522 with server:
3523 s = test_wrap_socket(socket.socket(),
3524 server_side=False,
3525 certfile=CERTFILE,
3526 ca_certs=CERTFILE,
3527 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003528 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003529 s.connect((HOST, server.port))
3530 # helper methods for standardising recv* method signatures
3531 def _recv_into():
3532 b = bytearray(b"\0"*100)
3533 count = s.recv_into(b)
3534 return b[:count]
3535
3536 def _recvfrom_into():
3537 b = bytearray(b"\0"*100)
3538 count, addr = s.recvfrom_into(b)
3539 return b[:count]
3540
3541 # (name, method, expect success?, *args, return value func)
3542 send_methods = [
3543 ('send', s.send, True, [], len),
3544 ('sendto', s.sendto, False, ["some.address"], len),
3545 ('sendall', s.sendall, True, [], lambda x: None),
3546 ]
3547 # (name, method, whether to expect success, *args)
3548 recv_methods = [
3549 ('recv', s.recv, True, []),
3550 ('recvfrom', s.recvfrom, False, ["some.address"]),
3551 ('recv_into', _recv_into, True, []),
3552 ('recvfrom_into', _recvfrom_into, False, []),
3553 ]
3554 data_prefix = "PREFIX_"
3555
3556 for (meth_name, send_meth, expect_success, args,
3557 ret_val_meth) in send_methods:
3558 indata = (data_prefix + meth_name).encode('ascii')
3559 try:
3560 ret = send_meth(indata, *args)
3561 msg = "sending with {}".format(meth_name)
3562 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3563 outdata = s.read()
3564 if outdata != indata.lower():
3565 self.fail(
3566 "While sending with <<{name:s}>> bad data "
3567 "<<{outdata:r}>> ({nout:d}) received; "
3568 "expected <<{indata:r}>> ({nin:d})\n".format(
3569 name=meth_name, outdata=outdata[:20],
3570 nout=len(outdata),
3571 indata=indata[:20], nin=len(indata)
3572 )
3573 )
3574 except ValueError as e:
3575 if expect_success:
3576 self.fail(
3577 "Failed to send with method <<{name:s}>>; "
3578 "expected to succeed.\n".format(name=meth_name)
3579 )
3580 if not str(e).startswith(meth_name):
3581 self.fail(
3582 "Method <<{name:s}>> failed with unexpected "
3583 "exception message: {exp:s}\n".format(
3584 name=meth_name, exp=e
3585 )
3586 )
3587
3588 for meth_name, recv_meth, expect_success, args in recv_methods:
3589 indata = (data_prefix + meth_name).encode('ascii')
3590 try:
3591 s.send(indata)
3592 outdata = recv_meth(*args)
3593 if outdata != indata.lower():
3594 self.fail(
3595 "While receiving with <<{name:s}>> bad data "
3596 "<<{outdata:r}>> ({nout:d}) received; "
3597 "expected <<{indata:r}>> ({nin:d})\n".format(
3598 name=meth_name, outdata=outdata[:20],
3599 nout=len(outdata),
3600 indata=indata[:20], nin=len(indata)
3601 )
3602 )
3603 except ValueError as e:
3604 if expect_success:
3605 self.fail(
3606 "Failed to receive with method <<{name:s}>>; "
3607 "expected to succeed.\n".format(name=meth_name)
3608 )
3609 if not str(e).startswith(meth_name):
3610 self.fail(
3611 "Method <<{name:s}>> failed with unexpected "
3612 "exception message: {exp:s}\n".format(
3613 name=meth_name, exp=e
3614 )
3615 )
3616 # consume data
3617 s.read()
3618
3619 # read(-1, buffer) is supported, even though read(-1) is not
3620 data = b"data"
3621 s.send(data)
3622 buffer = bytearray(len(data))
3623 self.assertEqual(s.read(-1, buffer), len(data))
3624 self.assertEqual(buffer, data)
3625
Christian Heimes888bbdc2017-09-07 14:18:21 -07003626 # sendall accepts bytes-like objects
3627 if ctypes is not None:
3628 ubyte = ctypes.c_ubyte * len(data)
3629 byteslike = ubyte.from_buffer_copy(data)
3630 s.sendall(byteslike)
3631 self.assertEqual(s.read(), data)
3632
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003633 # Make sure sendmsg et al are disallowed to avoid
3634 # inadvertent disclosure of data and/or corruption
3635 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003636 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003637 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3638 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3639 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003640 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003641 s.write(b"over\n")
3642
3643 self.assertRaises(ValueError, s.recv, -1)
3644 self.assertRaises(ValueError, s.read, -1)
3645
3646 s.close()
3647
3648 def test_recv_zero(self):
3649 server = ThreadedEchoServer(CERTFILE)
3650 server.__enter__()
3651 self.addCleanup(server.__exit__, None, None)
3652 s = socket.create_connection((HOST, server.port))
3653 self.addCleanup(s.close)
3654 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3655 self.addCleanup(s.close)
3656
3657 # recv/read(0) should return no data
3658 s.send(b"data")
3659 self.assertEqual(s.recv(0), b"")
3660 self.assertEqual(s.read(0), b"")
3661 self.assertEqual(s.read(), b"data")
3662
3663 # Should not block if the other end sends no data
3664 s.setblocking(False)
3665 self.assertEqual(s.recv(0), b"")
3666 self.assertEqual(s.recv_into(bytearray()), 0)
3667
3668 def test_nonblocking_send(self):
3669 server = ThreadedEchoServer(CERTFILE,
3670 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003671 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003672 cacerts=CERTFILE,
3673 chatty=True,
3674 connectionchatty=False)
3675 with server:
3676 s = test_wrap_socket(socket.socket(),
3677 server_side=False,
3678 certfile=CERTFILE,
3679 ca_certs=CERTFILE,
3680 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003681 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003682 s.connect((HOST, server.port))
3683 s.setblocking(False)
3684
3685 # If we keep sending data, at some point the buffers
3686 # will be full and the call will block
3687 buf = bytearray(8192)
3688 def fill_buffer():
3689 while True:
3690 s.send(buf)
3691 self.assertRaises((ssl.SSLWantWriteError,
3692 ssl.SSLWantReadError), fill_buffer)
3693
3694 # Now read all the output and discard it
3695 s.setblocking(True)
3696 s.close()
3697
3698 def test_handshake_timeout(self):
3699 # Issue #5103: SSL handshake must respect the socket timeout
3700 server = socket.socket(socket.AF_INET)
3701 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003702 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003703 started = threading.Event()
3704 finish = False
3705
3706 def serve():
3707 server.listen()
3708 started.set()
3709 conns = []
3710 while not finish:
3711 r, w, e = select.select([server], [], [], 0.1)
3712 if server in r:
3713 # Let the socket hang around rather than having
3714 # it closed by garbage collection.
3715 conns.append(server.accept()[0])
3716 for sock in conns:
3717 sock.close()
3718
3719 t = threading.Thread(target=serve)
3720 t.start()
3721 started.wait()
3722
3723 try:
3724 try:
3725 c = socket.socket(socket.AF_INET)
3726 c.settimeout(0.2)
3727 c.connect((host, port))
3728 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003729 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003730 test_wrap_socket, c)
3731 finally:
3732 c.close()
3733 try:
3734 c = socket.socket(socket.AF_INET)
3735 c = test_wrap_socket(c)
3736 c.settimeout(0.2)
3737 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003738 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003739 c.connect, (host, port))
3740 finally:
3741 c.close()
3742 finally:
3743 finish = True
3744 t.join()
3745 server.close()
3746
3747 def test_server_accept(self):
3748 # Issue #16357: accept() on a SSLSocket created through
3749 # SSLContext.wrap_socket().
Christian Heimesa170fa12017-09-15 20:27:30 +02003750 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003751 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003752 context.load_verify_locations(SIGNING_CA)
3753 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003754 server = socket.socket(socket.AF_INET)
3755 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003756 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003757 server = context.wrap_socket(server, server_side=True)
3758 self.assertTrue(server.server_side)
3759
3760 evt = threading.Event()
3761 remote = None
3762 peer = None
3763 def serve():
3764 nonlocal remote, peer
3765 server.listen()
3766 # Block on the accept and wait on the connection to close.
3767 evt.set()
3768 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003769 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003770
3771 t = threading.Thread(target=serve)
3772 t.start()
3773 # Client wait until server setup and perform a connect.
3774 evt.wait()
3775 client = context.wrap_socket(socket.socket())
3776 client.connect((host, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003777 client.send(b'data')
3778 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003779 client_addr = client.getsockname()
3780 client.close()
3781 t.join()
3782 remote.close()
3783 server.close()
3784 # Sanity checks.
3785 self.assertIsInstance(remote, ssl.SSLSocket)
3786 self.assertEqual(peer, client_addr)
3787
3788 def test_getpeercert_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.getpeercert()
3793 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3794
3795 def test_do_handshake_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003796 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003797 with context.wrap_socket(socket.socket()) as sock:
3798 with self.assertRaises(OSError) as cm:
3799 sock.do_handshake()
3800 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3801
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003802 def test_no_shared_ciphers(self):
3803 client_context, server_context, hostname = testing_context()
3804 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3805 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003806 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003807 client_context.set_ciphers("AES128")
3808 server_context.set_ciphers("AES256")
3809 with ThreadedEchoServer(context=server_context) as server:
3810 with client_context.wrap_socket(socket.socket(),
3811 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003812 with self.assertRaises(OSError):
3813 s.connect((HOST, server.port))
3814 self.assertIn("no shared cipher", server.conn_errors[0])
3815
3816 def test_version_basic(self):
3817 """
3818 Basic tests for SSLSocket.version().
3819 More tests are done in the test_protocol_*() methods.
3820 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003821 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3822 context.check_hostname = False
3823 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003824 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003825 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003826 chatty=False) as server:
3827 with context.wrap_socket(socket.socket()) as s:
3828 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003829 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003830 s.connect((HOST, server.port))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003831 if IS_OPENSSL_1_1_1 and has_tls_version('TLSv1_3'):
Christian Heimes05d9fe32018-02-27 08:55:39 +01003832 self.assertEqual(s.version(), 'TLSv1.3')
3833 elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
Christian Heimesa170fa12017-09-15 20:27:30 +02003834 self.assertEqual(s.version(), 'TLSv1.2')
3835 else: # 0.9.8 to 1.0.1
3836 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2'))
Christian Heimes141c5e82018-02-24 21:10:57 +01003837 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003838 self.assertIs(s.version(), None)
3839
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003840 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003841 def test_tls1_3(self):
3842 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
3843 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003844 context.options |= (
3845 ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2
3846 )
3847 with ThreadedEchoServer(context=context) as server:
3848 with context.wrap_socket(socket.socket()) as s:
3849 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003850 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003851 'TLS_AES_256_GCM_SHA384',
3852 'TLS_CHACHA20_POLY1305_SHA256',
3853 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003854 })
3855 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003856
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003857 @requires_minimum_version
3858 @requires_tls_version('TLSv1_2')
3859 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003860 client_context, server_context, hostname = testing_context()
3861 # client TLSv1.0 to 1.2
3862 client_context.minimum_version = ssl.TLSVersion.TLSv1
3863 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3864 # server only TLSv1.2
3865 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3866 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3867
3868 with ThreadedEchoServer(context=server_context) as server:
3869 with client_context.wrap_socket(socket.socket(),
3870 server_hostname=hostname) as s:
3871 s.connect((HOST, server.port))
3872 self.assertEqual(s.version(), 'TLSv1.2')
3873
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003874 @requires_minimum_version
3875 @requires_tls_version('TLSv1_1')
3876 def test_min_max_version_tlsv1_1(self):
3877 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003878 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003879 client_context.minimum_version = ssl.TLSVersion.TLSv1
3880 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003881 server_context.minimum_version = ssl.TLSVersion.TLSv1
3882 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003883 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003884
3885 with ThreadedEchoServer(context=server_context) as server:
3886 with client_context.wrap_socket(socket.socket(),
3887 server_hostname=hostname) as s:
3888 s.connect((HOST, server.port))
3889 self.assertEqual(s.version(), 'TLSv1.1')
3890
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003891 @requires_minimum_version
3892 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003893 @requires_tls_version('TLSv1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003894 def test_min_max_version_mismatch(self):
3895 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003896 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003897 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003898 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003899 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003900 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003901 seclevel_workaround(client_context, server_context)
3902
Christian Heimes698dde12018-02-27 11:54:43 +01003903 with ThreadedEchoServer(context=server_context) as server:
3904 with client_context.wrap_socket(socket.socket(),
3905 server_hostname=hostname) as s:
3906 with self.assertRaises(ssl.SSLError) as e:
3907 s.connect((HOST, server.port))
3908 self.assertIn("alert", str(e.exception))
3909
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003910 @requires_minimum_version
3911 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003912 def test_min_max_version_sslv3(self):
3913 client_context, server_context, hostname = testing_context()
3914 server_context.minimum_version = ssl.TLSVersion.SSLv3
3915 client_context.minimum_version = ssl.TLSVersion.SSLv3
3916 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003917 seclevel_workaround(client_context, server_context)
3918
Christian Heimes698dde12018-02-27 11:54:43 +01003919 with ThreadedEchoServer(context=server_context) as server:
3920 with client_context.wrap_socket(socket.socket(),
3921 server_hostname=hostname) as s:
3922 s.connect((HOST, server.port))
3923 self.assertEqual(s.version(), 'SSLv3')
3924
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003925 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3926 def test_default_ecdh_curve(self):
3927 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3928 # should be enabled by default on SSL contexts.
Christian Heimesa170fa12017-09-15 20:27:30 +02003929 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003930 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003931 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3932 # cipher name.
3933 context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003934 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3935 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3936 # our default cipher list should prefer ECDH-based ciphers
3937 # automatically.
3938 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
3939 context.set_ciphers("ECCdraft:ECDH")
3940 with ThreadedEchoServer(context=context) as server:
3941 with context.wrap_socket(socket.socket()) as s:
3942 s.connect((HOST, server.port))
3943 self.assertIn("ECDH", s.cipher()[0])
3944
3945 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3946 "'tls-unique' channel binding not available")
3947 def test_tls_unique_channel_binding(self):
3948 """Test tls-unique channel binding."""
3949 if support.verbose:
3950 sys.stdout.write("\n")
3951
Christian Heimes05d9fe32018-02-27 08:55:39 +01003952 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003953
3954 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003955 chatty=True,
3956 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003957
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003958 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003959 with client_context.wrap_socket(
3960 socket.socket(),
3961 server_hostname=hostname) as s:
3962 s.connect((HOST, server.port))
3963 # get the data
3964 cb_data = s.get_channel_binding("tls-unique")
3965 if support.verbose:
3966 sys.stdout.write(
3967 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003968
Christian Heimes05d9fe32018-02-27 08:55:39 +01003969 # check if it is sane
3970 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003971 if s.version() == 'TLSv1.3':
3972 self.assertEqual(len(cb_data), 48)
3973 else:
3974 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003975
Christian Heimes05d9fe32018-02-27 08:55:39 +01003976 # and compare with the peers version
3977 s.write(b"CB tls-unique\n")
3978 peer_data_repr = s.read().strip()
3979 self.assertEqual(peer_data_repr,
3980 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003981
3982 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003983 with client_context.wrap_socket(
3984 socket.socket(),
3985 server_hostname=hostname) as s:
3986 s.connect((HOST, server.port))
3987 new_cb_data = s.get_channel_binding("tls-unique")
3988 if support.verbose:
3989 sys.stdout.write(
3990 "got another channel binding data: {0!r}\n".format(
3991 new_cb_data)
3992 )
3993 # is it really unique
3994 self.assertNotEqual(cb_data, new_cb_data)
3995 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003996 if s.version() == 'TLSv1.3':
3997 self.assertEqual(len(cb_data), 48)
3998 else:
3999 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01004000 s.write(b"CB tls-unique\n")
4001 peer_data_repr = s.read().strip()
4002 self.assertEqual(peer_data_repr,
4003 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004004
4005 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004006 client_context, server_context, hostname = testing_context()
4007 stats = server_params_test(client_context, server_context,
4008 chatty=True, connectionchatty=True,
4009 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004010 if support.verbose:
4011 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
4012 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
4013
4014 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
4015 "ssl.OP_NO_COMPRESSION needed for this test")
4016 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004017 client_context, server_context, hostname = testing_context()
4018 client_context.options |= ssl.OP_NO_COMPRESSION
4019 server_context.options |= ssl.OP_NO_COMPRESSION
4020 stats = server_params_test(client_context, server_context,
4021 chatty=True, connectionchatty=True,
4022 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004023 self.assertIs(stats['compression'], None)
4024
Paul Monsonf3550692019-06-19 13:09:54 -07004025 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004026 def test_dh_params(self):
4027 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004028 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004029 # test scenario needs TLS <= 1.2
4030 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004031 server_context.load_dh_params(DHFILE)
4032 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004033 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004034 stats = server_params_test(client_context, server_context,
4035 chatty=True, connectionchatty=True,
4036 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004037 cipher = stats["cipher"][0]
4038 parts = cipher.split("-")
4039 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4040 self.fail("Non-DH cipher: " + cipher[0])
4041
Christian Heimesb7b92252018-02-25 09:49:31 +01004042 @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004043 @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
Christian Heimesb7b92252018-02-25 09:49:31 +01004044 def test_ecdh_curve(self):
4045 # server secp384r1, client auto
4046 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004047
Christian Heimesb7b92252018-02-25 09:49:31 +01004048 server_context.set_ecdh_curve("secp384r1")
4049 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4050 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4051 stats = server_params_test(client_context, server_context,
4052 chatty=True, connectionchatty=True,
4053 sni_name=hostname)
4054
4055 # server auto, client secp384r1
4056 client_context, server_context, hostname = testing_context()
4057 client_context.set_ecdh_curve("secp384r1")
4058 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4059 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4060 stats = server_params_test(client_context, server_context,
4061 chatty=True, connectionchatty=True,
4062 sni_name=hostname)
4063
4064 # server / client curve mismatch
4065 client_context, server_context, hostname = testing_context()
4066 client_context.set_ecdh_curve("prime256v1")
4067 server_context.set_ecdh_curve("secp384r1")
4068 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4069 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4070 try:
4071 stats = server_params_test(client_context, server_context,
4072 chatty=True, connectionchatty=True,
4073 sni_name=hostname)
4074 except ssl.SSLError:
4075 pass
4076 else:
4077 # OpenSSL 1.0.2 does not fail although it should.
Christian Heimes05d9fe32018-02-27 08:55:39 +01004078 if IS_OPENSSL_1_1_0:
Christian Heimesb7b92252018-02-25 09:49:31 +01004079 self.fail("mismatch curve did not fail")
4080
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004081 def test_selected_alpn_protocol(self):
4082 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004083 client_context, server_context, hostname = testing_context()
4084 stats = server_params_test(client_context, server_context,
4085 chatty=True, connectionchatty=True,
4086 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004087 self.assertIs(stats['client_alpn_protocol'], None)
4088
4089 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
4090 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4091 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004092 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004093 server_context.set_alpn_protocols(['foo', 'bar'])
4094 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004095 chatty=True, connectionchatty=True,
4096 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004097 self.assertIs(stats['client_alpn_protocol'], None)
4098
4099 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
4100 def test_alpn_protocols(self):
4101 server_protocols = ['foo', 'bar', 'milkshake']
4102 protocol_tests = [
4103 (['foo', 'bar'], 'foo'),
4104 (['bar', 'foo'], 'foo'),
4105 (['milkshake'], 'milkshake'),
4106 (['http/3.0', 'http/4.0'], None)
4107 ]
4108 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004109 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004110 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004111 client_context.set_alpn_protocols(client_protocols)
4112
4113 try:
4114 stats = server_params_test(client_context,
4115 server_context,
4116 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004117 connectionchatty=True,
4118 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004119 except ssl.SSLError as e:
4120 stats = e
4121
Christian Heimes05d9fe32018-02-27 08:55:39 +01004122 if (expected is None and IS_OPENSSL_1_1_0
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004123 and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)):
4124 # OpenSSL 1.1.0 to 1.1.0e raises handshake error
4125 self.assertIsInstance(stats, ssl.SSLError)
4126 else:
4127 msg = "failed trying %s (s) and %s (c).\n" \
4128 "was expecting %s, but got %%s from the %%s" \
4129 % (str(server_protocols), str(client_protocols),
4130 str(expected))
4131 client_result = stats['client_alpn_protocol']
4132 self.assertEqual(client_result, expected,
4133 msg % (client_result, "client"))
4134 server_result = stats['server_alpn_protocols'][-1] \
4135 if len(stats['server_alpn_protocols']) else 'nothing'
4136 self.assertEqual(server_result, expected,
4137 msg % (server_result, "server"))
4138
4139 def test_selected_npn_protocol(self):
4140 # selected_npn_protocol() is None unless NPN is used
Christian Heimesa170fa12017-09-15 20:27:30 +02004141 client_context, server_context, hostname = testing_context()
4142 stats = server_params_test(client_context, server_context,
4143 chatty=True, connectionchatty=True,
4144 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004145 self.assertIs(stats['client_npn_protocol'], None)
4146
4147 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
4148 def test_npn_protocols(self):
4149 server_protocols = ['http/1.1', 'spdy/2']
4150 protocol_tests = [
4151 (['http/1.1', 'spdy/2'], 'http/1.1'),
4152 (['spdy/2', 'http/1.1'], 'http/1.1'),
4153 (['spdy/2', 'test'], 'spdy/2'),
4154 (['abc', 'def'], 'abc')
4155 ]
4156 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004157 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004158 server_context.set_npn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004159 client_context.set_npn_protocols(client_protocols)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004160 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004161 chatty=True, connectionchatty=True,
4162 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004163 msg = "failed trying %s (s) and %s (c).\n" \
4164 "was expecting %s, but got %%s from the %%s" \
4165 % (str(server_protocols), str(client_protocols),
4166 str(expected))
4167 client_result = stats['client_npn_protocol']
4168 self.assertEqual(client_result, expected, msg % (client_result, "client"))
4169 server_result = stats['server_npn_protocols'][-1] \
4170 if len(stats['server_npn_protocols']) else 'nothing'
4171 self.assertEqual(server_result, expected, msg % (server_result, "server"))
4172
4173 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004174 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004175 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004176 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004177 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004178 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004179 client_context.load_verify_locations(SIGNING_CA)
4180 return server_context, other_context, client_context
4181
4182 def check_common_name(self, stats, name):
4183 cert = stats['peercert']
4184 self.assertIn((('commonName', name),), cert['subject'])
4185
4186 @needs_sni
4187 def test_sni_callback(self):
4188 calls = []
4189 server_context, other_context, client_context = self.sni_contexts()
4190
Christian Heimesa170fa12017-09-15 20:27:30 +02004191 client_context.check_hostname = False
4192
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004193 def servername_cb(ssl_sock, server_name, initial_context):
4194 calls.append((server_name, initial_context))
4195 if server_name is not None:
4196 ssl_sock.context = other_context
4197 server_context.set_servername_callback(servername_cb)
4198
4199 stats = server_params_test(client_context, server_context,
4200 chatty=True,
4201 sni_name='supermessage')
4202 # The hostname was fetched properly, and the certificate was
4203 # changed for the connection.
4204 self.assertEqual(calls, [("supermessage", server_context)])
4205 # CERTFILE4 was selected
4206 self.check_common_name(stats, 'fakehostname')
4207
4208 calls = []
4209 # The callback is called with server_name=None
4210 stats = server_params_test(client_context, server_context,
4211 chatty=True,
4212 sni_name=None)
4213 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004214 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004215
4216 # Check disabling the callback
4217 calls = []
4218 server_context.set_servername_callback(None)
4219
4220 stats = server_params_test(client_context, server_context,
4221 chatty=True,
4222 sni_name='notfunny')
4223 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004224 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004225 self.assertEqual(calls, [])
4226
4227 @needs_sni
4228 def test_sni_callback_alert(self):
4229 # Returning a TLS alert is reflected to the connecting client
4230 server_context, other_context, client_context = self.sni_contexts()
4231
4232 def cb_returning_alert(ssl_sock, server_name, initial_context):
4233 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4234 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004235 with self.assertRaises(ssl.SSLError) as cm:
4236 stats = server_params_test(client_context, server_context,
4237 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004238 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004239 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004240
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004241 @needs_sni
4242 def test_sni_callback_raising(self):
4243 # Raising fails the connection with a TLS handshake failure alert.
4244 server_context, other_context, client_context = self.sni_contexts()
4245
4246 def cb_raising(ssl_sock, server_name, initial_context):
4247 1/0
4248 server_context.set_servername_callback(cb_raising)
4249
Victor Stinner00253502019-06-03 03:51:43 +02004250 with support.catch_unraisable_exception() as catch:
4251 with self.assertRaises(ssl.SSLError) as cm:
4252 stats = server_params_test(client_context, server_context,
4253 chatty=False,
4254 sni_name='supermessage')
4255
4256 self.assertEqual(cm.exception.reason,
4257 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4258 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004259
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004260 @needs_sni
4261 def test_sni_callback_wrong_return_type(self):
4262 # Returning the wrong return type terminates the TLS connection
4263 # with an internal error alert.
4264 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004265
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004266 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4267 return "foo"
4268 server_context.set_servername_callback(cb_wrong_return_type)
4269
Victor Stinner00253502019-06-03 03:51:43 +02004270 with support.catch_unraisable_exception() as catch:
4271 with self.assertRaises(ssl.SSLError) as cm:
4272 stats = server_params_test(client_context, server_context,
4273 chatty=False,
4274 sni_name='supermessage')
4275
4276
4277 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4278 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004279
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004280 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004281 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004282 client_context.set_ciphers("AES128:AES256")
4283 server_context.set_ciphers("AES256")
4284 expected_algs = [
4285 "AES256", "AES-256",
4286 # TLS 1.3 ciphers are always enabled
4287 "TLS_CHACHA20", "TLS_AES",
4288 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004289
Christian Heimesa170fa12017-09-15 20:27:30 +02004290 stats = server_params_test(client_context, server_context,
4291 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004292 ciphers = stats['server_shared_ciphers'][0]
4293 self.assertGreater(len(ciphers), 0)
4294 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004295 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004296 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004297
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004298 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004299 client_context, server_context, hostname = testing_context()
4300 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004301
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004302 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004303 s = client_context.wrap_socket(socket.socket(),
4304 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004305 s.connect((HOST, server.port))
4306 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004307
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004308 self.assertRaises(ValueError, s.read, 1024)
4309 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004310
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004311 def test_sendfile(self):
4312 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004313 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004314 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004315 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesa170fa12017-09-15 20:27:30 +02004316 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004317 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01004318 context.load_verify_locations(SIGNING_CA)
4319 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004320 server = ThreadedEchoServer(context=context, chatty=False)
4321 with server:
4322 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004323 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004324 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004325 s.sendfile(file)
4326 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004327
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004328 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004329 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004330 # TODO: sessions aren't compatible with TLSv1.3 yet
4331 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004332
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004333 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004334 stats = server_params_test(client_context, server_context,
4335 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004336 session = stats['session']
4337 self.assertTrue(session.id)
4338 self.assertGreater(session.time, 0)
4339 self.assertGreater(session.timeout, 0)
4340 self.assertTrue(session.has_ticket)
4341 if ssl.OPENSSL_VERSION_INFO > (1, 0, 1):
4342 self.assertGreater(session.ticket_lifetime_hint, 0)
4343 self.assertFalse(stats['session_reused'])
4344 sess_stat = server_context.session_stats()
4345 self.assertEqual(sess_stat['accept'], 1)
4346 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004347
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004348 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004349 stats = server_params_test(client_context, server_context,
4350 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004351 sess_stat = server_context.session_stats()
4352 self.assertEqual(sess_stat['accept'], 2)
4353 self.assertEqual(sess_stat['hits'], 1)
4354 self.assertTrue(stats['session_reused'])
4355 session2 = stats['session']
4356 self.assertEqual(session2.id, session.id)
4357 self.assertEqual(session2, session)
4358 self.assertIsNot(session2, session)
4359 self.assertGreaterEqual(session2.time, session.time)
4360 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004361
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004362 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004363 stats = server_params_test(client_context, server_context,
4364 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004365 self.assertFalse(stats['session_reused'])
4366 session3 = stats['session']
4367 self.assertNotEqual(session3.id, session.id)
4368 self.assertNotEqual(session3, session)
4369 sess_stat = server_context.session_stats()
4370 self.assertEqual(sess_stat['accept'], 3)
4371 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004372
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004373 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004374 stats = server_params_test(client_context, server_context,
4375 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004376 self.assertTrue(stats['session_reused'])
4377 session4 = stats['session']
4378 self.assertEqual(session4.id, session.id)
4379 self.assertEqual(session4, session)
4380 self.assertGreaterEqual(session4.time, session.time)
4381 self.assertGreaterEqual(session4.timeout, session.timeout)
4382 sess_stat = server_context.session_stats()
4383 self.assertEqual(sess_stat['accept'], 4)
4384 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004385
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004386 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004387 client_context, server_context, hostname = testing_context()
4388 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004389
Christian Heimes05d9fe32018-02-27 08:55:39 +01004390 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004391 client_context.options |= ssl.OP_NO_TLSv1_3
4392 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004393
Christian Heimesa170fa12017-09-15 20:27:30 +02004394 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004395 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004396 with client_context.wrap_socket(socket.socket(),
4397 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004398 # session is None before handshake
4399 self.assertEqual(s.session, None)
4400 self.assertEqual(s.session_reused, None)
4401 s.connect((HOST, server.port))
4402 session = s.session
4403 self.assertTrue(session)
4404 with self.assertRaises(TypeError) as e:
4405 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004406 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004407
Christian Heimesa170fa12017-09-15 20:27:30 +02004408 with client_context.wrap_socket(socket.socket(),
4409 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004410 s.connect((HOST, server.port))
4411 # cannot set session after handshake
4412 with self.assertRaises(ValueError) as e:
4413 s.session = session
4414 self.assertEqual(str(e.exception),
4415 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004416
Christian Heimesa170fa12017-09-15 20:27:30 +02004417 with client_context.wrap_socket(socket.socket(),
4418 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004419 # can set session before handshake and before the
4420 # connection was established
4421 s.session = session
4422 s.connect((HOST, server.port))
4423 self.assertEqual(s.session.id, session.id)
4424 self.assertEqual(s.session, session)
4425 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004426
Christian Heimesa170fa12017-09-15 20:27:30 +02004427 with client_context2.wrap_socket(socket.socket(),
4428 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004429 # cannot re-use session with a different SSLContext
4430 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004431 s.session = session
4432 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004433 self.assertEqual(str(e.exception),
4434 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004435
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004436
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004437@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004438class TestPostHandshakeAuth(unittest.TestCase):
4439 def test_pha_setter(self):
4440 protocols = [
4441 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
4442 ]
4443 for protocol in protocols:
4444 ctx = ssl.SSLContext(protocol)
4445 self.assertEqual(ctx.post_handshake_auth, False)
4446
4447 ctx.post_handshake_auth = True
4448 self.assertEqual(ctx.post_handshake_auth, True)
4449
4450 ctx.verify_mode = ssl.CERT_REQUIRED
4451 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4452 self.assertEqual(ctx.post_handshake_auth, True)
4453
4454 ctx.post_handshake_auth = False
4455 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4456 self.assertEqual(ctx.post_handshake_auth, False)
4457
4458 ctx.verify_mode = ssl.CERT_OPTIONAL
4459 ctx.post_handshake_auth = True
4460 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4461 self.assertEqual(ctx.post_handshake_auth, True)
4462
4463 def test_pha_required(self):
4464 client_context, server_context, hostname = testing_context()
4465 server_context.post_handshake_auth = True
4466 server_context.verify_mode = ssl.CERT_REQUIRED
4467 client_context.post_handshake_auth = True
4468 client_context.load_cert_chain(SIGNED_CERTFILE)
4469
4470 server = ThreadedEchoServer(context=server_context, chatty=False)
4471 with server:
4472 with client_context.wrap_socket(socket.socket(),
4473 server_hostname=hostname) as s:
4474 s.connect((HOST, server.port))
4475 s.write(b'HASCERT')
4476 self.assertEqual(s.recv(1024), b'FALSE\n')
4477 s.write(b'PHA')
4478 self.assertEqual(s.recv(1024), b'OK\n')
4479 s.write(b'HASCERT')
4480 self.assertEqual(s.recv(1024), b'TRUE\n')
4481 # PHA method just returns true when cert is already available
4482 s.write(b'PHA')
4483 self.assertEqual(s.recv(1024), b'OK\n')
4484 s.write(b'GETCERT')
4485 cert_text = s.recv(4096).decode('us-ascii')
4486 self.assertIn('Python Software Foundation CA', cert_text)
4487
4488 def test_pha_required_nocert(self):
4489 client_context, server_context, hostname = testing_context()
4490 server_context.post_handshake_auth = True
4491 server_context.verify_mode = ssl.CERT_REQUIRED
4492 client_context.post_handshake_auth = True
4493
Victor Stinner73ea5462019-07-09 14:33:49 +02004494 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4495 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004496 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004497 server = ThreadedEchoServer(context=server_context, chatty=False)
4498 with server:
4499 with client_context.wrap_socket(socket.socket(),
4500 server_hostname=hostname) as s:
4501 s.connect((HOST, server.port))
4502 s.write(b'PHA')
4503 # receive CertificateRequest
4504 self.assertEqual(s.recv(1024), b'OK\n')
4505 # send empty Certificate + Finish
4506 s.write(b'HASCERT')
4507 # receive alert
4508 with self.assertRaisesRegex(
4509 ssl.SSLError,
4510 'tlsv13 alert certificate required'):
4511 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004512
4513 def test_pha_optional(self):
4514 if support.verbose:
4515 sys.stdout.write("\n")
4516
4517 client_context, server_context, hostname = testing_context()
4518 server_context.post_handshake_auth = True
4519 server_context.verify_mode = ssl.CERT_REQUIRED
4520 client_context.post_handshake_auth = True
4521 client_context.load_cert_chain(SIGNED_CERTFILE)
4522
4523 # check CERT_OPTIONAL
4524 server_context.verify_mode = ssl.CERT_OPTIONAL
4525 server = ThreadedEchoServer(context=server_context, chatty=False)
4526 with server:
4527 with client_context.wrap_socket(socket.socket(),
4528 server_hostname=hostname) as s:
4529 s.connect((HOST, server.port))
4530 s.write(b'HASCERT')
4531 self.assertEqual(s.recv(1024), b'FALSE\n')
4532 s.write(b'PHA')
4533 self.assertEqual(s.recv(1024), b'OK\n')
4534 s.write(b'HASCERT')
4535 self.assertEqual(s.recv(1024), b'TRUE\n')
4536
4537 def test_pha_optional_nocert(self):
4538 if support.verbose:
4539 sys.stdout.write("\n")
4540
4541 client_context, server_context, hostname = testing_context()
4542 server_context.post_handshake_auth = True
4543 server_context.verify_mode = ssl.CERT_OPTIONAL
4544 client_context.post_handshake_auth = True
4545
4546 server = ThreadedEchoServer(context=server_context, chatty=False)
4547 with server:
4548 with client_context.wrap_socket(socket.socket(),
4549 server_hostname=hostname) as s:
4550 s.connect((HOST, server.port))
4551 s.write(b'HASCERT')
4552 self.assertEqual(s.recv(1024), b'FALSE\n')
4553 s.write(b'PHA')
4554 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004555 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004556 s.write(b'HASCERT')
4557 self.assertEqual(s.recv(1024), b'FALSE\n')
4558
4559 def test_pha_no_pha_client(self):
4560 client_context, server_context, hostname = testing_context()
4561 server_context.post_handshake_auth = True
4562 server_context.verify_mode = ssl.CERT_REQUIRED
4563 client_context.load_cert_chain(SIGNED_CERTFILE)
4564
4565 server = ThreadedEchoServer(context=server_context, chatty=False)
4566 with server:
4567 with client_context.wrap_socket(socket.socket(),
4568 server_hostname=hostname) as s:
4569 s.connect((HOST, server.port))
4570 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4571 s.verify_client_post_handshake()
4572 s.write(b'PHA')
4573 self.assertIn(b'extension not received', s.recv(1024))
4574
4575 def test_pha_no_pha_server(self):
4576 # server doesn't have PHA enabled, cert is requested in handshake
4577 client_context, server_context, hostname = testing_context()
4578 server_context.verify_mode = ssl.CERT_REQUIRED
4579 client_context.post_handshake_auth = True
4580 client_context.load_cert_chain(SIGNED_CERTFILE)
4581
4582 server = ThreadedEchoServer(context=server_context, chatty=False)
4583 with server:
4584 with client_context.wrap_socket(socket.socket(),
4585 server_hostname=hostname) as s:
4586 s.connect((HOST, server.port))
4587 s.write(b'HASCERT')
4588 self.assertEqual(s.recv(1024), b'TRUE\n')
4589 # PHA doesn't fail if there is already a cert
4590 s.write(b'PHA')
4591 self.assertEqual(s.recv(1024), b'OK\n')
4592 s.write(b'HASCERT')
4593 self.assertEqual(s.recv(1024), b'TRUE\n')
4594
4595 def test_pha_not_tls13(self):
4596 # TLS 1.2
4597 client_context, server_context, hostname = testing_context()
4598 server_context.verify_mode = ssl.CERT_REQUIRED
4599 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4600 client_context.post_handshake_auth = True
4601 client_context.load_cert_chain(SIGNED_CERTFILE)
4602
4603 server = ThreadedEchoServer(context=server_context, chatty=False)
4604 with server:
4605 with client_context.wrap_socket(socket.socket(),
4606 server_hostname=hostname) as s:
4607 s.connect((HOST, server.port))
4608 # PHA fails for TLS != 1.3
4609 s.write(b'PHA')
4610 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4611
Christian Heimesf0f59302019-07-01 08:29:17 +02004612 def test_bpo37428_pha_cert_none(self):
4613 # verify that post_handshake_auth does not implicitly enable cert
4614 # validation.
4615 hostname = SIGNED_CERTFILE_HOSTNAME
4616 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4617 client_context.post_handshake_auth = True
4618 client_context.load_cert_chain(SIGNED_CERTFILE)
4619 # no cert validation and CA on client side
4620 client_context.check_hostname = False
4621 client_context.verify_mode = ssl.CERT_NONE
4622
4623 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4624 server_context.load_cert_chain(SIGNED_CERTFILE)
4625 server_context.load_verify_locations(SIGNING_CA)
4626 server_context.post_handshake_auth = True
4627 server_context.verify_mode = ssl.CERT_REQUIRED
4628
4629 server = ThreadedEchoServer(context=server_context, chatty=False)
4630 with server:
4631 with client_context.wrap_socket(socket.socket(),
4632 server_hostname=hostname) as s:
4633 s.connect((HOST, server.port))
4634 s.write(b'HASCERT')
4635 self.assertEqual(s.recv(1024), b'FALSE\n')
4636 s.write(b'PHA')
4637 self.assertEqual(s.recv(1024), b'OK\n')
4638 s.write(b'HASCERT')
4639 self.assertEqual(s.recv(1024), b'TRUE\n')
4640 # server cert has not been validated
4641 self.assertEqual(s.getpeercert(), {})
4642
Christian Heimes9fb051f2018-09-23 08:32:31 +02004643
Christian Heimesc7f70692019-05-31 11:44:05 +02004644HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4645requires_keylog = unittest.skipUnless(
4646 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4647
4648class TestSSLDebug(unittest.TestCase):
4649
Hai Shia7f5d932020-08-04 00:41:24 +08004650 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004651 with open(fname) as f:
4652 return len(list(f))
4653
4654 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004655 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004656 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004657 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004658 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4659 self.assertEqual(ctx.keylog_filename, None)
4660
Hai Shia7f5d932020-08-04 00:41:24 +08004661 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4662 ctx.keylog_filename = os_helper.TESTFN
4663 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4664 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004665 self.assertEqual(self.keylog_lines(), 1)
4666
4667 ctx.keylog_filename = None
4668 self.assertEqual(ctx.keylog_filename, None)
4669
4670 with self.assertRaises((IsADirectoryError, PermissionError)):
4671 # Windows raises PermissionError
4672 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004673 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004674
4675 with self.assertRaises(TypeError):
4676 ctx.keylog_filename = 1
4677
4678 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004679 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004680 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004681 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004682 client_context, server_context, hostname = testing_context()
4683
Hai Shia7f5d932020-08-04 00:41:24 +08004684 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004685 server = ThreadedEchoServer(context=server_context, chatty=False)
4686 with server:
4687 with client_context.wrap_socket(socket.socket(),
4688 server_hostname=hostname) as s:
4689 s.connect((HOST, server.port))
4690 # header, 5 lines for TLS 1.3
4691 self.assertEqual(self.keylog_lines(), 6)
4692
4693 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004694 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004695 server = ThreadedEchoServer(context=server_context, chatty=False)
4696 with server:
4697 with client_context.wrap_socket(socket.socket(),
4698 server_hostname=hostname) as s:
4699 s.connect((HOST, server.port))
4700 self.assertGreaterEqual(self.keylog_lines(), 11)
4701
Hai Shia7f5d932020-08-04 00:41:24 +08004702 client_context.keylog_filename = os_helper.TESTFN
4703 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004704 server = ThreadedEchoServer(context=server_context, chatty=False)
4705 with server:
4706 with client_context.wrap_socket(socket.socket(),
4707 server_hostname=hostname) as s:
4708 s.connect((HOST, server.port))
4709 self.assertGreaterEqual(self.keylog_lines(), 21)
4710
4711 client_context.keylog_filename = None
4712 server_context.keylog_filename = None
4713
4714 @requires_keylog
4715 @unittest.skipIf(sys.flags.ignore_environment,
4716 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004717 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004718 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004719 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004720 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004721 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4722 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004723
4724 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4725 self.assertEqual(ctx.keylog_filename, None)
4726
4727 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004728 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004729
4730 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004731 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004732
4733 def test_msg_callback(self):
4734 client_context, server_context, hostname = testing_context()
4735
4736 def msg_cb(conn, direction, version, content_type, msg_type, data):
4737 pass
4738
4739 self.assertIs(client_context._msg_callback, None)
4740 client_context._msg_callback = msg_cb
4741 self.assertIs(client_context._msg_callback, msg_cb)
4742 with self.assertRaises(TypeError):
4743 client_context._msg_callback = object()
4744
4745 def test_msg_callback_tls12(self):
4746 client_context, server_context, hostname = testing_context()
4747 client_context.options |= ssl.OP_NO_TLSv1_3
4748
4749 msg = []
4750
4751 def msg_cb(conn, direction, version, content_type, msg_type, data):
4752 self.assertIsInstance(conn, ssl.SSLSocket)
4753 self.assertIsInstance(data, bytes)
4754 self.assertIn(direction, {'read', 'write'})
4755 msg.append((direction, version, content_type, msg_type))
4756
4757 client_context._msg_callback = msg_cb
4758
4759 server = ThreadedEchoServer(context=server_context, chatty=False)
4760 with server:
4761 with client_context.wrap_socket(socket.socket(),
4762 server_hostname=hostname) as s:
4763 s.connect((HOST, server.port))
4764
Christian Heimese35d1ba2019-06-03 20:40:15 +02004765 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004766 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4767 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004768 msg
4769 )
4770 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004771 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4772 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004773 msg
4774 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004775
Christian Heimes77cde502021-03-21 16:13:09 +01004776 def test_msg_callback_deadlock_bpo43577(self):
4777 client_context, server_context, hostname = testing_context()
4778 server_context2 = testing_context()[1]
4779
4780 def msg_cb(conn, direction, version, content_type, msg_type, data):
4781 pass
4782
4783 def sni_cb(sock, servername, ctx):
4784 sock.context = server_context2
4785
4786 server_context._msg_callback = msg_cb
4787 server_context.sni_callback = sni_cb
4788
4789 server = ThreadedEchoServer(context=server_context, chatty=False)
4790 with server:
4791 with client_context.wrap_socket(socket.socket(),
4792 server_hostname=hostname) as s:
4793 s.connect((HOST, server.port))
4794 with client_context.wrap_socket(socket.socket(),
4795 server_hostname=hostname) as s:
4796 s.connect((HOST, server.port))
4797
Christian Heimesc7f70692019-05-31 11:44:05 +02004798
Thomas Woutersed03b412007-08-28 21:37:11 +00004799def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004800 if support.verbose:
4801 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004802 'Mac': platform.mac_ver,
4803 'Windows': platform.win32_ver,
4804 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004805 for name, func in plats.items():
4806 plat = func()
4807 if plat and plat[0]:
4808 plat = '%s %r' % (name, plat)
4809 break
4810 else:
4811 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004812 print("test_ssl: testing with %r %r" %
4813 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4814 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004815 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004816 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4817 try:
4818 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4819 except AttributeError:
4820 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004821
Antoine Pitrou152efa22010-05-16 18:19:27 +00004822 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004823 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004824 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004825 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004826 BADCERT, BADKEY, EMPTYCERT]:
4827 if not os.path.exists(filename):
4828 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004829
Martin Panter3840b2a2016-03-27 01:53:46 +00004830 tests = [
4831 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004832 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004833 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004834 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004835
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004836 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004837 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004838
Hai Shie80697d2020-05-28 06:10:27 +08004839 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004840 try:
4841 support.run_unittest(*tests)
4842 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004843 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004844
4845if __name__ == "__main__":
4846 test_main()