blob: c0e040d77253fef9d144d38b489c50ab8172892c [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 Heimes358cfd42016-09-10 22:43:48 +0200154
Christian Heimesf6c6b582021-03-18 23:06:50 +0100155# Ubuntu has patched OpenSSL and changed behavior of security level 2
156# see https://bugs.python.org/issue41561#msg389003
157def is_ubuntu():
158 try:
159 # Assume that any references of "ubuntu" implies Ubuntu-like distro
160 # The workaround is not required for 18.04, but doesn't hurt either.
161 with open("/etc/os-release", encoding="utf-8") as f:
162 return "ubuntu" in f.read()
163 except FileNotFoundError:
164 return False
165
166if is_ubuntu():
167 def seclevel_workaround(*ctxs):
168 """"Lower security level to '1' and allow all ciphers for TLS 1.0/1"""
169 for ctx in ctxs:
170 if ctx.minimum_version <= ssl.TLSVersion.TLSv1_1:
171 ctx.set_ciphers("@SECLEVEL=1:ALL")
172else:
173 def seclevel_workaround(*ctxs):
174 pass
175
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100176
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200177def has_tls_protocol(protocol):
178 """Check if a TLS protocol is available and enabled
179
180 :param protocol: enum ssl._SSLMethod member or name
181 :return: bool
182 """
183 if isinstance(protocol, str):
184 assert protocol.startswith('PROTOCOL_')
185 protocol = getattr(ssl, protocol, None)
186 if protocol is None:
187 return False
188 if protocol in {
189 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
190 ssl.PROTOCOL_TLS_CLIENT
191 }:
192 # auto-negotiate protocols are always available
193 return True
194 name = protocol.name
195 return has_tls_version(name[len('PROTOCOL_'):])
196
197
198@functools.lru_cache
199def has_tls_version(version):
200 """Check if a TLS/SSL version is enabled
201
202 :param version: TLS version name or ssl.TLSVersion member
203 :return: bool
204 """
205 if version == "SSLv2":
206 # never supported and not even in TLSVersion enum
207 return False
208
209 if isinstance(version, str):
210 version = ssl.TLSVersion.__members__[version]
211
212 # check compile time flags like ssl.HAS_TLSv1_2
213 if not getattr(ssl, f'HAS_{version.name}'):
214 return False
215
Christian Heimes5151d642021-04-09 15:43:06 +0200216 if IS_OPENSSL_3_0_0 and version < ssl.TLSVersion.TLSv1_2:
217 # bpo43791: 3.0.0-alpha14 fails with TLSV1_ALERT_INTERNAL_ERROR
218 return False
219
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200220 # check runtime and dynamic crypto policy settings. A TLS version may
221 # be compiled in but disabled by a policy or config option.
222 ctx = ssl.SSLContext()
223 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200224 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200225 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
226 version < ctx.minimum_version
227 ):
228 return False
229 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200230 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200231 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
232 version > ctx.maximum_version
233 ):
234 return False
235
236 return True
237
238
239def requires_tls_version(version):
240 """Decorator to skip tests when a required TLS version is not available
241
242 :param version: TLS version name or ssl.TLSVersion member
243 :return:
244 """
245 def decorator(func):
246 @functools.wraps(func)
247 def wrapper(*args, **kw):
248 if not has_tls_version(version):
249 raise unittest.SkipTest(f"{version} is not available.")
250 else:
251 return func(*args, **kw)
252 return wrapper
253 return decorator
254
255
256requires_minimum_version = unittest.skipUnless(
257 hasattr(ssl.SSLContext, 'minimum_version'),
258 "required OpenSSL >= 1.1.0g"
259)
260
261
Thomas Woutersed03b412007-08-28 21:37:11 +0000262def handle_error(prefix):
263 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000264 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000265 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000266
Antoine Pitroub5218772010-05-21 09:56:06 +0000267def can_clear_options():
268 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +0200269 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +0000270
271def no_sslv2_implies_sslv3_hello():
272 # 0.9.7h or higher
273 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
274
Christian Heimes2427b502013-11-23 11:24:32 +0100275def have_verify_flags():
276 # 0.9.8 or higher
277 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
278
Christian Heimesb7b92252018-02-25 09:49:31 +0100279def _have_secp_curves():
280 if not ssl.HAS_ECDH:
281 return False
282 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
283 try:
284 ctx.set_ecdh_curve("secp384r1")
285 except ValueError:
286 return False
287 else:
288 return True
289
290
291HAVE_SECP_CURVES = _have_secp_curves()
292
293
Antoine Pitrouc695c952014-04-28 20:57:36 +0200294def utc_offset(): #NOTE: ignore issues like #1647654
295 # local time = utc time + utc offset
296 if time.daylight and time.localtime().tm_isdst > 0:
297 return -time.altzone # seconds
298 return -time.timezone
299
Christian Heimes9424bb42013-06-17 15:32:57 +0200300def asn1time(cert_time):
301 # Some versions of OpenSSL ignore seconds, see #18207
302 # 0.9.8.i
303 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
304 fmt = "%b %d %H:%M:%S %Y GMT"
305 dt = datetime.datetime.strptime(cert_time, fmt)
306 dt = dt.replace(second=0)
307 cert_time = dt.strftime(fmt)
308 # %d adds leading zero but ASN1_TIME_print() uses leading space
309 if cert_time[4] == "0":
310 cert_time = cert_time[:4] + " " + cert_time[5:]
311
312 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000313
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100314needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
315
Antoine Pitrou23df4832010-08-04 17:14:06 +0000316
Christian Heimesd0486372016-09-10 23:23:33 +0200317def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLS, *,
318 cert_reqs=ssl.CERT_NONE, ca_certs=None,
319 ciphers=None, certfile=None, keyfile=None,
320 **kwargs):
321 context = ssl.SSLContext(ssl_version)
322 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200323 if cert_reqs == ssl.CERT_NONE:
324 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200325 context.verify_mode = cert_reqs
326 if ca_certs is not None:
327 context.load_verify_locations(ca_certs)
328 if certfile is not None or keyfile is not None:
329 context.load_cert_chain(certfile, keyfile)
330 if ciphers is not None:
331 context.set_ciphers(ciphers)
332 return context.wrap_socket(sock, **kwargs)
333
Christian Heimesa170fa12017-09-15 20:27:30 +0200334
335def testing_context(server_cert=SIGNED_CERTFILE):
336 """Create context
337
338 client_context, server_context, hostname = testing_context()
339 """
340 if server_cert == SIGNED_CERTFILE:
341 hostname = SIGNED_CERTFILE_HOSTNAME
342 elif server_cert == SIGNED_CERTFILE2:
343 hostname = SIGNED_CERTFILE2_HOSTNAME
344 else:
345 raise ValueError(server_cert)
346
347 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
348 client_context.load_verify_locations(SIGNING_CA)
349
350 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
351 server_context.load_cert_chain(server_cert)
Christian Heimes9fb051f2018-09-23 08:32:31 +0200352 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200353
354 return client_context, server_context, hostname
355
356
Antoine Pitrou152efa22010-05-16 18:19:27 +0000357class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000358
Antoine Pitrou480a1242010-04-28 21:37:09 +0000359 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000360 ssl.CERT_NONE
361 ssl.CERT_OPTIONAL
362 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100363 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100364 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100365 if ssl.HAS_ECDH:
366 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100367 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
368 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000369 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100370 self.assertIn(ssl.HAS_ECDH, {True, False})
Christian Heimescb5b68a2017-09-07 18:07:00 -0700371 ssl.OP_NO_SSLv2
372 ssl.OP_NO_SSLv3
373 ssl.OP_NO_TLSv1
374 ssl.OP_NO_TLSv1_3
375 if ssl.OPENSSL_VERSION_INFO >= (1, 0, 1):
376 ssl.OP_NO_TLSv1_1
377 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200378 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000379
Christian Heimes9d50ab52018-02-27 10:17:30 +0100380 def test_private_init(self):
381 with self.assertRaisesRegex(TypeError, "public constructor"):
382 with socket.socket() as s:
383 ssl.SSLSocket(s)
384
Antoine Pitrou172f0252014-04-18 20:33:08 +0200385 def test_str_for_enums(self):
386 # Make sure that the PROTOCOL_* constants have enum-like string
387 # reprs.
Christian Heimes598894f2016-09-05 23:19:05 +0200388 proto = ssl.PROTOCOL_TLS
Ethan Furmanb7751062021-03-30 21:17:26 -0700389 self.assertEqual(str(proto), 'PROTOCOL_TLS')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200390 ctx = ssl.SSLContext(proto)
391 self.assertIs(ctx.protocol, proto)
392
Antoine Pitrou480a1242010-04-28 21:37:09 +0000393 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000394 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000395 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000396 sys.stdout.write("\n RAND_status is %d (%s)\n"
397 % (v, (v and "sufficient randomness") or
398 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200399
400 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
401 self.assertEqual(len(data), 16)
402 self.assertEqual(is_cryptographic, v == 1)
403 if v:
404 data = ssl.RAND_bytes(16)
405 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200406 else:
407 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200408
Victor Stinner1e81a392013-12-19 16:47:04 +0100409 # negative num is invalid
410 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
411 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
412
Victor Stinnerbeeb5122014-11-28 13:28:25 +0100413 if hasattr(ssl, 'RAND_egd'):
414 self.assertRaises(TypeError, ssl.RAND_egd, 1)
415 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000416 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200417 ssl.RAND_add(b"this is a random bytes object", 75.0)
418 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000419
pxinwr98a54172020-12-09 07:20:19 +0800420 @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
Christian Heimesf77b4b22013-08-21 13:26:05 +0200421 def test_random_fork(self):
422 status = ssl.RAND_status()
423 if not status:
424 self.fail("OpenSSL's PRNG has insufficient randomness")
425
426 rfd, wfd = os.pipe()
427 pid = os.fork()
428 if pid == 0:
429 try:
430 os.close(rfd)
431 child_random = ssl.RAND_pseudo_bytes(16)[0]
432 self.assertEqual(len(child_random), 16)
433 os.write(wfd, child_random)
434 os.close(wfd)
435 except BaseException:
436 os._exit(1)
437 else:
438 os._exit(0)
439 else:
440 os.close(wfd)
441 self.addCleanup(os.close, rfd)
Victor Stinner278c1e12020-03-31 20:08:12 +0200442 support.wait_process(pid, exitcode=0)
Christian Heimesf77b4b22013-08-21 13:26:05 +0200443
444 child_random = os.read(rfd, 16)
445 self.assertEqual(len(child_random), 16)
446 parent_random = ssl.RAND_pseudo_bytes(16)[0]
447 self.assertEqual(len(parent_random), 16)
448
449 self.assertNotEqual(child_random, parent_random)
450
Christian Heimese6dac002018-08-30 07:25:49 +0200451 maxDiff = None
452
Antoine Pitrou480a1242010-04-28 21:37:09 +0000453 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000454 # note that this uses an 'unofficial' function in _ssl.c,
455 # provided solely for this test, to exercise the certificate
456 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100457 self.assertEqual(
458 ssl._ssl._test_decode_cert(CERTFILE),
459 CERTFILE_INFO
460 )
461 self.assertEqual(
462 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
463 SIGNED_CERTFILE_INFO
464 )
465
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200466 # Issue #13034: the subjectAltName in some certificates
467 # (notably projects.developer.nokia.com:443) wasn't parsed
468 p = ssl._ssl._test_decode_cert(NOKIACERT)
469 if support.verbose:
470 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
471 self.assertEqual(p['subjectAltName'],
472 (('DNS', 'projects.developer.nokia.com'),
473 ('DNS', 'projects.forum.nokia.com'))
474 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100475 # extra OCSP and AIA fields
476 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
477 self.assertEqual(p['caIssuers'],
478 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
479 self.assertEqual(p['crlDistributionPoints'],
480 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000481
Christian Heimesa37f5242019-01-15 23:47:42 +0100482 def test_parse_cert_CVE_2019_5010(self):
483 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
484 if support.verbose:
485 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
486 self.assertEqual(
487 p,
488 {
489 'issuer': (
490 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
491 'notAfter': 'Jun 14 18:00:58 2028 GMT',
492 'notBefore': 'Jun 18 18:00:58 2018 GMT',
493 'serialNumber': '02',
494 'subject': ((('countryName', 'UK'),),
495 (('commonName',
496 'codenomicon-vm-2.test.lal.cisco.com'),)),
497 'subjectAltName': (
498 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
499 'version': 3
500 }
501 )
502
Christian Heimes824f7f32013-08-17 00:54:47 +0200503 def test_parse_cert_CVE_2013_4238(self):
504 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
505 if support.verbose:
506 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
507 subject = ((('countryName', 'US'),),
508 (('stateOrProvinceName', 'Oregon'),),
509 (('localityName', 'Beaverton'),),
510 (('organizationName', 'Python Software Foundation'),),
511 (('organizationalUnitName', 'Python Core Development'),),
512 (('commonName', 'null.python.org\x00example.org'),),
513 (('emailAddress', 'python-dev@python.org'),))
514 self.assertEqual(p['subject'], subject)
515 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200516 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
517 san = (('DNS', 'altnull.python.org\x00example.com'),
518 ('email', 'null@python.org\x00user@example.org'),
519 ('URI', 'http://null.python.org\x00http://example.org'),
520 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100521 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200522 else:
523 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
524 san = (('DNS', 'altnull.python.org\x00example.com'),
525 ('email', 'null@python.org\x00user@example.org'),
526 ('URI', 'http://null.python.org\x00http://example.org'),
527 ('IP Address', '192.0.2.1'),
528 ('IP Address', '<invalid>'))
529
530 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200531
Christian Heimes1c03abd2016-09-06 23:25:35 +0200532 def test_parse_all_sans(self):
533 p = ssl._ssl._test_decode_cert(ALLSANFILE)
534 self.assertEqual(p['subjectAltName'],
535 (
536 ('DNS', 'allsans'),
537 ('othername', '<unsupported>'),
538 ('othername', '<unsupported>'),
539 ('email', 'user@example.org'),
540 ('DNS', 'www.example.org'),
541 ('DirName',
542 ((('countryName', 'XY'),),
543 (('localityName', 'Castle Anthrax'),),
544 (('organizationName', 'Python Software Foundation'),),
545 (('commonName', 'dirname example'),))),
546 ('URI', 'https://www.python.org/'),
547 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100548 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200549 ('Registered ID', '1.2.3.4.5')
550 )
551 )
552
Antoine Pitrou480a1242010-04-28 21:37:09 +0000553 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000554 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000555 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000556 d1 = ssl.PEM_cert_to_DER_cert(pem)
557 p2 = ssl.DER_cert_to_PEM_cert(d1)
558 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000559 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000560 if not p2.startswith(ssl.PEM_HEADER + '\n'):
561 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
562 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
563 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000564
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000565 def test_openssl_version(self):
566 n = ssl.OPENSSL_VERSION_NUMBER
567 t = ssl.OPENSSL_VERSION_INFO
568 s = ssl.OPENSSL_VERSION
569 self.assertIsInstance(n, int)
570 self.assertIsInstance(t, tuple)
571 self.assertIsInstance(s, str)
572 # Some sanity checks follow
573 # >= 0.9
574 self.assertGreaterEqual(n, 0x900000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100575 # < 4.0
576 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000577 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100578 self.assertGreaterEqual(major, 1)
579 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000580 self.assertGreaterEqual(minor, 0)
581 self.assertLess(minor, 256)
582 self.assertGreaterEqual(fix, 0)
583 self.assertLess(fix, 256)
584 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100585 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000586 self.assertGreaterEqual(status, 0)
587 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400588 # Version string as returned by {Open,Libre}SSL, the format might change
Christian Heimes598894f2016-09-05 23:19:05 +0200589 if IS_LIBRESSL:
590 self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
Victor Stinner789b8052015-01-06 11:51:06 +0100591 (s, t, hex(n)))
Antoine Pitroudfab9352014-07-21 18:35:01 -0400592 else:
593 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
Victor Stinner789b8052015-01-06 11:51:06 +0100594 (s, t, hex(n)))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000595
Antoine Pitrou9d543662010-04-23 23:10:32 +0000596 @support.cpython_only
597 def test_refcycle(self):
598 # Issue #7943: an SSL object doesn't create reference cycles with
599 # itself.
600 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200601 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000602 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800603 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100604 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100605 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000606
Antoine Pitroua468adc2010-09-14 14:43:44 +0000607 def test_wrapped_unconnected(self):
608 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200609 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000610 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200611 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100612 self.assertRaises(OSError, ss.recv, 1)
613 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
614 self.assertRaises(OSError, ss.recvfrom, 1)
615 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
616 self.assertRaises(OSError, ss.send, b'x')
617 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200618 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100619 self.assertRaises(NotImplementedError, ss.sendmsg,
620 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200621 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
622 self.assertRaises(NotImplementedError, ss.recvmsg_into,
623 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000624
Antoine Pitrou40f08742010-04-24 22:04:40 +0000625 def test_timeout(self):
626 # Issue #8524: when creating an SSL socket, the timeout of the
627 # original socket should be retained.
628 for timeout in (None, 0.0, 5.0):
629 s = socket.socket(socket.AF_INET)
630 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200631 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100632 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000633
Christian Heimesd0486372016-09-10 23:23:33 +0200634 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000635 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000636 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000637 "certfile must be specified",
638 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000639 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000640 "certfile must be specified for server-side operations",
641 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000642 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000643 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200644 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100645 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
646 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200647 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200648 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000649 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000650 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000651 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200652 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000653 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000654 ssl.wrap_socket(sock,
655 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000656 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200657 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000658 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000659 ssl.wrap_socket(sock,
660 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000661 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000662
Martin Panter3464ea22016-02-01 21:58:11 +0000663 def bad_cert_test(self, certfile):
664 """Check that trying to use the given client certificate fails"""
665 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
666 certfile)
667 sock = socket.socket()
668 self.addCleanup(sock.close)
669 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200670 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200671 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000672
673 def test_empty_cert(self):
674 """Wrapping with an empty cert file"""
675 self.bad_cert_test("nullcert.pem")
676
677 def test_malformed_cert(self):
678 """Wrapping with a badly formatted certificate (syntax error)"""
679 self.bad_cert_test("badcert.pem")
680
681 def test_malformed_key(self):
682 """Wrapping with a badly formatted key (syntax error)"""
683 self.bad_cert_test("badkey.pem")
684
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000685 def test_match_hostname(self):
686 def ok(cert, hostname):
687 ssl.match_hostname(cert, hostname)
688 def fail(cert, hostname):
689 self.assertRaises(ssl.CertificateError,
690 ssl.match_hostname, cert, hostname)
691
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100692 # -- Hostname matching --
693
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000694 cert = {'subject': ((('commonName', 'example.com'),),)}
695 ok(cert, 'example.com')
696 ok(cert, 'ExAmple.cOm')
697 fail(cert, 'www.example.com')
698 fail(cert, '.example.com')
699 fail(cert, 'example.org')
700 fail(cert, 'exampleXcom')
701
702 cert = {'subject': ((('commonName', '*.a.com'),),)}
703 ok(cert, 'foo.a.com')
704 fail(cert, 'bar.foo.a.com')
705 fail(cert, 'a.com')
706 fail(cert, 'Xa.com')
707 fail(cert, '.a.com')
708
Mandeep Singhede2ac92017-11-27 04:01:27 +0530709 # only match wildcards when they are the only thing
710 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000711 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530712 fail(cert, 'foo.com')
713 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000714 fail(cert, 'bar.com')
715 fail(cert, 'foo.a.com')
716 fail(cert, 'bar.foo.com')
717
Christian Heimes824f7f32013-08-17 00:54:47 +0200718 # NULL bytes are bad, CVE-2013-4073
719 cert = {'subject': ((('commonName',
720 'null.python.org\x00example.org'),),)}
721 ok(cert, 'null.python.org\x00example.org') # or raise an error?
722 fail(cert, 'example.org')
723 fail(cert, 'null.python.org')
724
Georg Brandl72c98d32013-10-27 07:16:53 +0100725 # error cases with wildcards
726 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
727 fail(cert, 'bar.foo.a.com')
728 fail(cert, 'a.com')
729 fail(cert, 'Xa.com')
730 fail(cert, '.a.com')
731
732 cert = {'subject': ((('commonName', 'a.*.com'),),)}
733 fail(cert, 'a.foo.com')
734 fail(cert, 'a..com')
735 fail(cert, 'a.com')
736
737 # wildcard doesn't match IDNA prefix 'xn--'
738 idna = 'püthon.python.org'.encode("idna").decode("ascii")
739 cert = {'subject': ((('commonName', idna),),)}
740 ok(cert, idna)
741 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
742 fail(cert, idna)
743 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
744 fail(cert, idna)
745
746 # wildcard in first fragment and IDNA A-labels in sequent fragments
747 # are supported.
748 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
749 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530750 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
751 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100752 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
753 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
754
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000755 # Slightly fake real-world example
756 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
757 'subject': ((('commonName', 'linuxfrz.org'),),),
758 'subjectAltName': (('DNS', 'linuxfr.org'),
759 ('DNS', 'linuxfr.com'),
760 ('othername', '<unsupported>'))}
761 ok(cert, 'linuxfr.org')
762 ok(cert, 'linuxfr.com')
763 # Not a "DNS" entry
764 fail(cert, '<unsupported>')
765 # When there is a subjectAltName, commonName isn't used
766 fail(cert, 'linuxfrz.org')
767
768 # A pristine real-world example
769 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
770 'subject': ((('countryName', 'US'),),
771 (('stateOrProvinceName', 'California'),),
772 (('localityName', 'Mountain View'),),
773 (('organizationName', 'Google Inc'),),
774 (('commonName', 'mail.google.com'),))}
775 ok(cert, 'mail.google.com')
776 fail(cert, 'gmail.com')
777 # Only commonName is considered
778 fail(cert, 'California')
779
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100780 # -- IPv4 matching --
781 cert = {'subject': ((('commonName', 'example.com'),),),
782 'subjectAltName': (('DNS', 'example.com'),
783 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200784 ('IP Address', '14.15.16.17'),
785 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100786 ok(cert, '10.11.12.13')
787 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200788 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
789 fail(cert, '127.1')
790 fail(cert, '14.15.16.17 ')
791 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100792 fail(cert, '14.15.16.18')
793 fail(cert, 'example.net')
794
795 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300796 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100797 cert = {'subject': ((('commonName', 'example.com'),),),
798 'subjectAltName': (
799 ('DNS', 'example.com'),
800 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
801 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
802 ok(cert, '2001::cafe')
803 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200804 fail(cert, '2003::baba ')
805 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100806 fail(cert, '2003::bebe')
807 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100808
809 # -- Miscellaneous --
810
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000811 # Neither commonName nor subjectAltName
812 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
813 'subject': ((('countryName', 'US'),),
814 (('stateOrProvinceName', 'California'),),
815 (('localityName', 'Mountain View'),),
816 (('organizationName', 'Google Inc'),))}
817 fail(cert, 'mail.google.com')
818
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200819 # No DNS entry in subjectAltName but a commonName
820 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
821 'subject': ((('countryName', 'US'),),
822 (('stateOrProvinceName', 'California'),),
823 (('localityName', 'Mountain View'),),
824 (('commonName', 'mail.google.com'),)),
825 'subjectAltName': (('othername', 'blabla'), )}
826 ok(cert, 'mail.google.com')
827
828 # No DNS entry subjectAltName and no commonName
829 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
830 'subject': ((('countryName', 'US'),),
831 (('stateOrProvinceName', 'California'),),
832 (('localityName', 'Mountain View'),),
833 (('organizationName', 'Google Inc'),)),
834 'subjectAltName': (('othername', 'blabla'),)}
835 fail(cert, 'google.com')
836
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000837 # Empty cert / no cert
838 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
839 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
840
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200841 # Issue #17980: avoid denials of service by refusing more than one
842 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100843 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
844 with self.assertRaisesRegex(
845 ssl.CertificateError,
846 "partial wildcards in leftmost label are not supported"):
847 ssl.match_hostname(cert, 'axxb.example.com')
848
849 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
850 with self.assertRaisesRegex(
851 ssl.CertificateError,
852 "wildcard can only be present in the leftmost label"):
853 ssl.match_hostname(cert, 'www.sub.example.com')
854
855 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
856 with self.assertRaisesRegex(
857 ssl.CertificateError,
858 "too many wildcards"):
859 ssl.match_hostname(cert, 'axxbxxc.example.com')
860
861 cert = {'subject': ((('commonName', '*'),),)}
862 with self.assertRaisesRegex(
863 ssl.CertificateError,
864 "sole wildcard without additional labels are not support"):
865 ssl.match_hostname(cert, 'host')
866
867 cert = {'subject': ((('commonName', '*.com'),),)}
868 with self.assertRaisesRegex(
869 ssl.CertificateError,
870 r"hostname 'com' doesn't match '\*.com'"):
871 ssl.match_hostname(cert, 'com')
872
873 # extra checks for _inet_paton()
874 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
875 with self.assertRaises(ValueError):
876 ssl._inet_paton(invalid)
877 for ipaddr in ['127.0.0.1', '192.168.0.1']:
878 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300879 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100880 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
881 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200882
Antoine Pitroud5323212010-10-22 18:19:07 +0000883 def test_server_side(self):
884 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200885 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000886 with socket.socket() as sock:
887 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
888 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000889
Antoine Pitroud6494802011-07-21 01:11:30 +0200890 def test_unknown_channel_binding(self):
891 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200892 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200893 c = socket.socket(socket.AF_INET)
894 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200895 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100896 with self.assertRaises(ValueError):
897 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200898 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200899
900 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
901 "'tls-unique' channel binding not available")
902 def test_tls_unique_channel_binding(self):
903 # unconnected should return None for known type
904 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200905 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100906 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200907 # the same for server-side
908 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200909 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100910 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200911
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600912 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200913 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600914 r = repr(ss)
915 with self.assertWarns(ResourceWarning) as cm:
916 ss = None
917 support.gc_collect()
918 self.assertIn(r, str(cm.warning.args[0]))
919
Christian Heimes6d7ad132013-06-09 18:02:55 +0200920 def test_get_default_verify_paths(self):
921 paths = ssl.get_default_verify_paths()
922 self.assertEqual(len(paths), 6)
923 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
924
Hai Shia7f5d932020-08-04 00:41:24 +0800925 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200926 env["SSL_CERT_DIR"] = CAPATH
927 env["SSL_CERT_FILE"] = CERTFILE
928 paths = ssl.get_default_verify_paths()
929 self.assertEqual(paths.cafile, CERTFILE)
930 self.assertEqual(paths.capath, CAPATH)
931
Christian Heimes44109d72013-11-22 01:51:30 +0100932 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
933 def test_enum_certificates(self):
934 self.assertTrue(ssl.enum_certificates("CA"))
935 self.assertTrue(ssl.enum_certificates("ROOT"))
936
937 self.assertRaises(TypeError, ssl.enum_certificates)
938 self.assertRaises(WindowsError, ssl.enum_certificates, "")
939
Christian Heimesc2d65e12013-11-22 16:13:55 +0100940 trust_oids = set()
941 for storename in ("CA", "ROOT"):
942 store = ssl.enum_certificates(storename)
943 self.assertIsInstance(store, list)
944 for element in store:
945 self.assertIsInstance(element, tuple)
946 self.assertEqual(len(element), 3)
947 cert, enc, trust = element
948 self.assertIsInstance(cert, bytes)
949 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200950 self.assertIsInstance(trust, (frozenset, set, bool))
951 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100952 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100953
954 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100955 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200956
Christian Heimes46bebee2013-06-09 19:03:31 +0200957 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100958 def test_enum_crls(self):
959 self.assertTrue(ssl.enum_crls("CA"))
960 self.assertRaises(TypeError, ssl.enum_crls)
961 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200962
Christian Heimes44109d72013-11-22 01:51:30 +0100963 crls = ssl.enum_crls("CA")
964 self.assertIsInstance(crls, list)
965 for element in crls:
966 self.assertIsInstance(element, tuple)
967 self.assertEqual(len(element), 2)
968 self.assertIsInstance(element[0], bytes)
969 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200970
Christian Heimes46bebee2013-06-09 19:03:31 +0200971
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100972 def test_asn1object(self):
973 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
974 '1.3.6.1.5.5.7.3.1')
975
976 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
977 self.assertEqual(val, expected)
978 self.assertEqual(val.nid, 129)
979 self.assertEqual(val.shortname, 'serverAuth')
980 self.assertEqual(val.longname, 'TLS Web Server Authentication')
981 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
982 self.assertIsInstance(val, ssl._ASN1Object)
983 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
984
985 val = ssl._ASN1Object.fromnid(129)
986 self.assertEqual(val, expected)
987 self.assertIsInstance(val, ssl._ASN1Object)
988 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100989 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
990 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100991 for i in range(1000):
992 try:
993 obj = ssl._ASN1Object.fromnid(i)
994 except ValueError:
995 pass
996 else:
997 self.assertIsInstance(obj.nid, int)
998 self.assertIsInstance(obj.shortname, str)
999 self.assertIsInstance(obj.longname, str)
1000 self.assertIsInstance(obj.oid, (str, type(None)))
1001
1002 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
1003 self.assertEqual(val, expected)
1004 self.assertIsInstance(val, ssl._ASN1Object)
1005 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
1006 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
1007 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +01001008 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
1009 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001010
Christian Heimes72d28502013-11-23 13:56:58 +01001011 def test_purpose_enum(self):
1012 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
1013 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
1014 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
1015 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
1016 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
1017 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
1018 '1.3.6.1.5.5.7.3.1')
1019
1020 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
1021 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
1022 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
1023 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
1024 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
1025 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
1026 '1.3.6.1.5.5.7.3.2')
1027
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001028 def test_unsupported_dtls(self):
1029 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1030 self.addCleanup(s.close)
1031 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +02001032 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001033 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +02001034 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001035 with self.assertRaises(NotImplementedError) as cx:
1036 ctx.wrap_socket(s)
1037 self.assertEqual(str(cx.exception), "only stream sockets are supported")
1038
Antoine Pitrouc695c952014-04-28 20:57:36 +02001039 def cert_time_ok(self, timestring, timestamp):
1040 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
1041
1042 def cert_time_fail(self, timestring):
1043 with self.assertRaises(ValueError):
1044 ssl.cert_time_to_seconds(timestring)
1045
1046 @unittest.skipUnless(utc_offset(),
1047 'local time needs to be different from UTC')
1048 def test_cert_time_to_seconds_timezone(self):
1049 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
1050 # results if local timezone is not UTC
1051 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
1052 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
1053
1054 def test_cert_time_to_seconds(self):
1055 timestring = "Jan 5 09:34:43 2018 GMT"
1056 ts = 1515144883.0
1057 self.cert_time_ok(timestring, ts)
1058 # accept keyword parameter, assert its name
1059 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
1060 # accept both %e and %d (space or zero generated by strftime)
1061 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
1062 # case-insensitive
1063 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
1064 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
1065 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1066 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1067 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1068 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1069 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1070 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1071
1072 newyear_ts = 1230768000.0
1073 # leap seconds
1074 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1075 # same timestamp
1076 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1077
1078 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1079 # allow 60th second (even if it is not a leap second)
1080 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1081 # allow 2nd leap second for compatibility with time.strptime()
1082 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1083 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1084
Mike53f7a7c2017-12-14 14:04:53 +03001085 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001086 # 99991231235959Z (rfc 5280)
1087 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1088
1089 @support.run_with_locale('LC_ALL', '')
1090 def test_cert_time_to_seconds_locale(self):
1091 # `cert_time_to_seconds()` should be locale independent
1092
1093 def local_february_name():
1094 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1095
1096 if local_february_name().lower() == 'feb':
1097 self.skipTest("locale-specific month name needs to be "
1098 "different from C locale")
1099
1100 # locale-independent
1101 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1102 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1103
Martin Panter3840b2a2016-03-27 01:53:46 +00001104 def test_connect_ex_error(self):
1105 server = socket.socket(socket.AF_INET)
1106 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001107 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001108 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001109 cert_reqs=ssl.CERT_REQUIRED)
1110 self.addCleanup(s.close)
1111 rc = s.connect_ex((HOST, port))
1112 # Issue #19919: Windows machines or VMs hosted on Windows
1113 # machines sometimes return EWOULDBLOCK.
1114 errors = (
1115 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1116 errno.EWOULDBLOCK,
1117 )
1118 self.assertIn(rc, errors)
1119
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001120
Antoine Pitrou152efa22010-05-16 18:19:27 +00001121class ContextTests(unittest.TestCase):
1122
1123 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001124 for protocol in PROTOCOLS:
1125 ssl.SSLContext(protocol)
Christian Heimes598894f2016-09-05 23:19:05 +02001126 ctx = ssl.SSLContext()
1127 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001128 self.assertRaises(ValueError, ssl.SSLContext, -1)
1129 self.assertRaises(ValueError, ssl.SSLContext, 42)
1130
1131 def test_protocol(self):
1132 for proto in PROTOCOLS:
1133 ctx = ssl.SSLContext(proto)
1134 self.assertEqual(ctx.protocol, proto)
1135
1136 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001137 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001138 ctx.set_ciphers("ALL")
1139 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001140 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001141 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001142
Christian Heimes892d66e2018-01-29 14:10:18 +01001143 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1144 "Test applies only to Python default ciphers")
1145 def test_python_ciphers(self):
1146 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1147 ciphers = ctx.get_ciphers()
1148 for suite in ciphers:
1149 name = suite['name']
1150 self.assertNotIn("PSK", name)
1151 self.assertNotIn("SRP", name)
1152 self.assertNotIn("MD5", name)
1153 self.assertNotIn("RC4", name)
1154 self.assertNotIn("3DES", name)
1155
Christian Heimes25bfcd52016-09-06 00:04:45 +02001156 @unittest.skipIf(ssl.OPENSSL_VERSION_INFO < (1, 0, 2, 0, 0), 'OpenSSL too old')
1157 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001158 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001159 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001160 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001161 self.assertIn('AES256-GCM-SHA384', names)
1162 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001163
Antoine Pitroub5218772010-05-21 09:56:06 +00001164 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001165 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001166 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001167 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001168 # SSLContext also enables these by default
1169 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001170 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
1171 OP_ENABLE_MIDDLEBOX_COMPAT)
Christian Heimes598894f2016-09-05 23:19:05 +02001172 self.assertEqual(default, ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001173 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001174 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +00001175 if can_clear_options():
Christian Heimes598894f2016-09-05 23:19:05 +02001176 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
1177 self.assertEqual(default, ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +00001178 ctx.options = 0
Matthias Klosef7c56242016-06-12 23:40:00 -07001179 # Ubuntu has OP_NO_SSLv3 forced on by default
1180 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001181 else:
1182 with self.assertRaises(ValueError):
1183 ctx.options = 0
1184
Christian Heimesa170fa12017-09-15 20:27:30 +02001185 def test_verify_mode_protocol(self):
1186 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001187 # Default value
1188 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1189 ctx.verify_mode = ssl.CERT_OPTIONAL
1190 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1191 ctx.verify_mode = ssl.CERT_REQUIRED
1192 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1193 ctx.verify_mode = ssl.CERT_NONE
1194 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1195 with self.assertRaises(TypeError):
1196 ctx.verify_mode = None
1197 with self.assertRaises(ValueError):
1198 ctx.verify_mode = 42
1199
Christian Heimesa170fa12017-09-15 20:27:30 +02001200 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1201 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1202 self.assertFalse(ctx.check_hostname)
1203
1204 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1205 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1206 self.assertTrue(ctx.check_hostname)
1207
Christian Heimes61d478c2018-01-27 15:51:38 +01001208 def test_hostname_checks_common_name(self):
1209 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1210 self.assertTrue(ctx.hostname_checks_common_name)
1211 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1212 ctx.hostname_checks_common_name = True
1213 self.assertTrue(ctx.hostname_checks_common_name)
1214 ctx.hostname_checks_common_name = False
1215 self.assertFalse(ctx.hostname_checks_common_name)
1216 ctx.hostname_checks_common_name = True
1217 self.assertTrue(ctx.hostname_checks_common_name)
1218 else:
1219 with self.assertRaises(AttributeError):
1220 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001221
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001222 @requires_minimum_version
Christian Heimesc9bc49c2019-09-11 19:24:47 +02001223 @unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
Christian Heimes698dde12018-02-27 11:54:43 +01001224 def test_min_max_version(self):
1225 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001226 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1227 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001228 minimum_range = {
1229 # stock OpenSSL
1230 ssl.TLSVersion.MINIMUM_SUPPORTED,
1231 # Fedora 29 uses TLS 1.0 by default
1232 ssl.TLSVersion.TLSv1,
1233 # RHEL 8 uses TLS 1.2 by default
1234 ssl.TLSVersion.TLSv1_2
1235 }
torsava34864d12019-12-02 17:15:42 +01001236 maximum_range = {
1237 # stock OpenSSL
1238 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1239 # Fedora 32 uses TLS 1.3 by default
1240 ssl.TLSVersion.TLSv1_3
1241 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001242
Christian Heimes34de2d32019-01-18 16:09:30 +01001243 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001244 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001245 )
torsava34864d12019-12-02 17:15:42 +01001246 self.assertIn(
1247 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001248 )
1249
1250 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1251 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1252 self.assertEqual(
1253 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1254 )
1255 self.assertEqual(
1256 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1257 )
1258
1259 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1260 ctx.maximum_version = ssl.TLSVersion.TLSv1
1261 self.assertEqual(
1262 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1263 )
1264 self.assertEqual(
1265 ctx.maximum_version, ssl.TLSVersion.TLSv1
1266 )
1267
1268 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1269 self.assertEqual(
1270 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1271 )
1272
1273 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1274 self.assertIn(
1275 ctx.maximum_version,
1276 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1277 )
1278
1279 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1280 self.assertIn(
1281 ctx.minimum_version,
1282 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1283 )
1284
1285 with self.assertRaises(ValueError):
1286 ctx.minimum_version = 42
1287
1288 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1289
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001290 self.assertIn(
1291 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001292 )
1293 self.assertEqual(
1294 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1295 )
1296 with self.assertRaises(ValueError):
1297 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1298 with self.assertRaises(ValueError):
1299 ctx.maximum_version = ssl.TLSVersion.TLSv1
1300
1301
matthewhughes9348e836bb2020-07-17 09:59:15 +01001302 @unittest.skipUnless(
1303 hasattr(ssl.SSLContext, 'security_level'),
1304 "requires OpenSSL >= 1.1.0"
1305 )
1306 def test_security_level(self):
1307 ctx = ssl.SSLContext()
1308 # The default security callback allows for levels between 0-5
1309 # with OpenSSL defaulting to 1, however some vendors override the
1310 # default value (e.g. Debian defaults to 2)
1311 security_level_range = {
1312 0,
1313 1, # OpenSSL default
1314 2, # Debian
1315 3,
1316 4,
1317 5,
1318 }
1319 self.assertIn(ctx.security_level, security_level_range)
1320
Christian Heimes2427b502013-11-23 11:24:32 +01001321 @unittest.skipUnless(have_verify_flags(),
1322 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01001323 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001324 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001325 # default value
1326 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1327 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001328 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1329 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1330 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1331 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1332 ctx.verify_flags = ssl.VERIFY_DEFAULT
1333 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001334 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1335 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001336 # supports any value
1337 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1338 self.assertEqual(ctx.verify_flags,
1339 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1340 with self.assertRaises(TypeError):
1341 ctx.verify_flags = None
1342
Antoine Pitrou152efa22010-05-16 18:19:27 +00001343 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001344 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001345 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001346 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001347 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1348 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001349 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001350 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001351 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001352 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001353 ctx.load_cert_chain(BADCERT)
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(EMPTYCERT)
1356 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001357 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001358 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1359 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1360 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001361 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001362 ctx.load_cert_chain(ONLYCERT)
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(ONLYKEY)
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(certfile=ONLYKEY, keyfile=ONLYCERT)
1367 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001368 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001369 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001370 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001371 # Password protected key and cert
1372 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1373 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1374 ctx.load_cert_chain(CERTFILE_PROTECTED,
1375 password=bytearray(KEY_PASSWORD.encode()))
1376 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1377 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1378 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1379 bytearray(KEY_PASSWORD.encode()))
1380 with self.assertRaisesRegex(TypeError, "should be a string"):
1381 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1382 with self.assertRaises(ssl.SSLError):
1383 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1384 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1385 # openssl has a fixed limit on the password buffer.
1386 # PEM_BUFSIZE is generally set to 1kb.
1387 # Return a string larger than this.
1388 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1389 # Password callback
1390 def getpass_unicode():
1391 return KEY_PASSWORD
1392 def getpass_bytes():
1393 return KEY_PASSWORD.encode()
1394 def getpass_bytearray():
1395 return bytearray(KEY_PASSWORD.encode())
1396 def getpass_badpass():
1397 return "badpass"
1398 def getpass_huge():
1399 return b'a' * (1024 * 1024)
1400 def getpass_bad_type():
1401 return 9
1402 def getpass_exception():
1403 raise Exception('getpass error')
1404 class GetPassCallable:
1405 def __call__(self):
1406 return KEY_PASSWORD
1407 def getpass(self):
1408 return KEY_PASSWORD
1409 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1410 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1411 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1412 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1413 ctx.load_cert_chain(CERTFILE_PROTECTED,
1414 password=GetPassCallable().getpass)
1415 with self.assertRaises(ssl.SSLError):
1416 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1417 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1418 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1419 with self.assertRaisesRegex(TypeError, "must return a string"):
1420 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1421 with self.assertRaisesRegex(Exception, "getpass error"):
1422 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1423 # Make sure the password function isn't called if it isn't needed
1424 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001425
1426 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001427 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001428 ctx.load_verify_locations(CERTFILE)
1429 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1430 ctx.load_verify_locations(BYTES_CERTFILE)
1431 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1432 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001433 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001434 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001435 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001436 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001437 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001438 ctx.load_verify_locations(BADCERT)
1439 ctx.load_verify_locations(CERTFILE, CAPATH)
1440 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1441
Victor Stinner80f75e62011-01-29 11:31:20 +00001442 # Issue #10989: crash if the second argument type is invalid
1443 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1444
Christian Heimesefff7062013-11-21 03:35:02 +01001445 def test_load_verify_cadata(self):
1446 # test cadata
1447 with open(CAFILE_CACERT) as f:
1448 cacert_pem = f.read()
1449 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1450 with open(CAFILE_NEURONIO) as f:
1451 neuronio_pem = f.read()
1452 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1453
1454 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001455 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001456 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1457 ctx.load_verify_locations(cadata=cacert_pem)
1458 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1459 ctx.load_verify_locations(cadata=neuronio_pem)
1460 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1461 # cert already in hash table
1462 ctx.load_verify_locations(cadata=neuronio_pem)
1463 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1464
1465 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001466 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001467 combined = "\n".join((cacert_pem, neuronio_pem))
1468 ctx.load_verify_locations(cadata=combined)
1469 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1470
1471 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001472 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001473 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1474 neuronio_pem, "tail"]
1475 ctx.load_verify_locations(cadata="\n".join(combined))
1476 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1477
1478 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001479 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001480 ctx.load_verify_locations(cadata=cacert_der)
1481 ctx.load_verify_locations(cadata=neuronio_der)
1482 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1483 # cert already in hash table
1484 ctx.load_verify_locations(cadata=cacert_der)
1485 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1486
1487 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001488 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001489 combined = b"".join((cacert_der, neuronio_der))
1490 ctx.load_verify_locations(cadata=combined)
1491 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1492
1493 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001494 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001495 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1496
1497 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1498 ctx.load_verify_locations(cadata="broken")
1499 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1500 ctx.load_verify_locations(cadata=b"broken")
1501
1502
Paul Monsonf3550692019-06-19 13:09:54 -07001503 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001504 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001505 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001506 ctx.load_dh_params(DHFILE)
1507 if os.name != 'nt':
1508 ctx.load_dh_params(BYTES_DHFILE)
1509 self.assertRaises(TypeError, ctx.load_dh_params)
1510 self.assertRaises(TypeError, ctx.load_dh_params, None)
1511 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001512 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001513 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001514 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001515 ctx.load_dh_params(CERTFILE)
1516
Antoine Pitroub0182c82010-10-12 20:09:02 +00001517 def test_session_stats(self):
1518 for proto in PROTOCOLS:
1519 ctx = ssl.SSLContext(proto)
1520 self.assertEqual(ctx.session_stats(), {
1521 'number': 0,
1522 'connect': 0,
1523 'connect_good': 0,
1524 'connect_renegotiate': 0,
1525 'accept': 0,
1526 'accept_good': 0,
1527 'accept_renegotiate': 0,
1528 'hits': 0,
1529 'misses': 0,
1530 'timeouts': 0,
1531 'cache_full': 0,
1532 })
1533
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001534 def test_set_default_verify_paths(self):
1535 # There's not much we can do to test that it acts as expected,
1536 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001537 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001538 ctx.set_default_verify_paths()
1539
Antoine Pitrou501da612011-12-21 09:27:41 +01001540 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001541 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001542 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001543 ctx.set_ecdh_curve("prime256v1")
1544 ctx.set_ecdh_curve(b"prime256v1")
1545 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1546 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1547 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1548 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1549
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001550 @needs_sni
1551 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001552 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001553
1554 # set_servername_callback expects a callable, or None
1555 self.assertRaises(TypeError, ctx.set_servername_callback)
1556 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1557 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1558 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1559
1560 def dummycallback(sock, servername, ctx):
1561 pass
1562 ctx.set_servername_callback(None)
1563 ctx.set_servername_callback(dummycallback)
1564
1565 @needs_sni
1566 def test_sni_callback_refcycle(self):
1567 # Reference cycles through the servername callback are detected
1568 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001569 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001570 def dummycallback(sock, servername, ctx, cycle=ctx):
1571 pass
1572 ctx.set_servername_callback(dummycallback)
1573 wr = weakref.ref(ctx)
1574 del ctx, dummycallback
1575 gc.collect()
1576 self.assertIs(wr(), None)
1577
Christian Heimes9a5395a2013-06-17 15:44:12 +02001578 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001579 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001580 self.assertEqual(ctx.cert_store_stats(),
1581 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1582 ctx.load_cert_chain(CERTFILE)
1583 self.assertEqual(ctx.cert_store_stats(),
1584 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1585 ctx.load_verify_locations(CERTFILE)
1586 self.assertEqual(ctx.cert_store_stats(),
1587 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001588 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001589 self.assertEqual(ctx.cert_store_stats(),
1590 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1591
1592 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001593 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001594 self.assertEqual(ctx.get_ca_certs(), [])
1595 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1596 ctx.load_verify_locations(CERTFILE)
1597 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001598 # but CAFILE_CACERT is a CA cert
1599 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001600 self.assertEqual(ctx.get_ca_certs(),
1601 [{'issuer': ((('organizationName', 'Root CA'),),
1602 (('organizationalUnitName', 'http://www.cacert.org'),),
1603 (('commonName', 'CA Cert Signing Authority'),),
1604 (('emailAddress', 'support@cacert.org'),)),
1605 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1606 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1607 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001608 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001609 'subject': ((('organizationName', 'Root CA'),),
1610 (('organizationalUnitName', 'http://www.cacert.org'),),
1611 (('commonName', 'CA Cert Signing Authority'),),
1612 (('emailAddress', 'support@cacert.org'),)),
1613 'version': 3}])
1614
Martin Panterb55f8b72016-01-14 12:53:56 +00001615 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001616 pem = f.read()
1617 der = ssl.PEM_cert_to_DER_cert(pem)
1618 self.assertEqual(ctx.get_ca_certs(True), [der])
1619
Christian Heimes72d28502013-11-23 13:56:58 +01001620 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001621 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001622 ctx.load_default_certs()
1623
Christian Heimesa170fa12017-09-15 20:27:30 +02001624 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001625 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1626 ctx.load_default_certs()
1627
Christian Heimesa170fa12017-09-15 20:27:30 +02001628 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001629 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1630
Christian Heimesa170fa12017-09-15 20:27:30 +02001631 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001632 self.assertRaises(TypeError, ctx.load_default_certs, None)
1633 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1634
Benjamin Peterson91244e02014-10-03 18:17:15 -04001635 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimes598894f2016-09-05 23:19:05 +02001636 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001637 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001638 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001639 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001640 env["SSL_CERT_DIR"] = CAPATH
1641 env["SSL_CERT_FILE"] = CERTFILE
1642 ctx.load_default_certs()
1643 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1644
Benjamin Peterson91244e02014-10-03 18:17:15 -04001645 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001646 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001647 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001648 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001649 ctx.load_default_certs()
1650 stats = ctx.cert_store_stats()
1651
Christian Heimesa170fa12017-09-15 20:27:30 +02001652 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001653 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001654 env["SSL_CERT_DIR"] = CAPATH
1655 env["SSL_CERT_FILE"] = CERTFILE
1656 ctx.load_default_certs()
1657 stats["x509"] += 1
1658 self.assertEqual(ctx.cert_store_stats(), stats)
1659
Christian Heimes358cfd42016-09-10 22:43:48 +02001660 def _assert_context_options(self, ctx):
1661 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1662 if OP_NO_COMPRESSION != 0:
1663 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1664 OP_NO_COMPRESSION)
1665 if OP_SINGLE_DH_USE != 0:
1666 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1667 OP_SINGLE_DH_USE)
1668 if OP_SINGLE_ECDH_USE != 0:
1669 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1670 OP_SINGLE_ECDH_USE)
1671 if OP_CIPHER_SERVER_PREFERENCE != 0:
1672 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1673 OP_CIPHER_SERVER_PREFERENCE)
1674
Christian Heimes4c05b472013-11-23 15:58:30 +01001675 def test_create_default_context(self):
1676 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001677
Christian Heimesa170fa12017-09-15 20:27:30 +02001678 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001679 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001680 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001681 self._assert_context_options(ctx)
1682
Christian Heimes4c05b472013-11-23 15:58:30 +01001683 with open(SIGNING_CA) as f:
1684 cadata = f.read()
1685 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1686 cadata=cadata)
Christian Heimesa170fa12017-09-15 20:27:30 +02001687 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001688 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001689 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001690
1691 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001692 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001693 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001694 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001695
Christian Heimes67986f92013-11-23 22:43:47 +01001696 def test__create_stdlib_context(self):
1697 ctx = ssl._create_stdlib_context()
Christian Heimesa170fa12017-09-15 20:27:30 +02001698 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001699 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001700 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001701 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001702
1703 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1704 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1705 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001706 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001707
1708 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001709 cert_reqs=ssl.CERT_REQUIRED,
1710 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001711 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1712 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001713 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001714 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001715
1716 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001717 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001718 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001719 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001720
Christian Heimes1aa9a752013-12-02 02:41:19 +01001721 def test_check_hostname(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001722 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001723 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001724 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001725
Christian Heimese82c0342017-09-15 20:29:57 +02001726 # Auto set CERT_REQUIRED
1727 ctx.check_hostname = True
1728 self.assertTrue(ctx.check_hostname)
1729 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1730 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001731 ctx.verify_mode = ssl.CERT_REQUIRED
1732 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001733 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001734
Christian Heimese82c0342017-09-15 20:29:57 +02001735 # Changing verify_mode does not affect check_hostname
1736 ctx.check_hostname = False
1737 ctx.verify_mode = ssl.CERT_NONE
1738 ctx.check_hostname = False
1739 self.assertFalse(ctx.check_hostname)
1740 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1741 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001742 ctx.check_hostname = True
1743 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001744 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1745
1746 ctx.check_hostname = False
1747 ctx.verify_mode = ssl.CERT_OPTIONAL
1748 ctx.check_hostname = False
1749 self.assertFalse(ctx.check_hostname)
1750 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1751 # keep CERT_OPTIONAL
1752 ctx.check_hostname = True
1753 self.assertTrue(ctx.check_hostname)
1754 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001755
1756 # Cannot set CERT_NONE with check_hostname enabled
1757 with self.assertRaises(ValueError):
1758 ctx.verify_mode = ssl.CERT_NONE
1759 ctx.check_hostname = False
1760 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001761 ctx.verify_mode = ssl.CERT_NONE
1762 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001763
Christian Heimes5fe668c2016-09-12 00:01:11 +02001764 def test_context_client_server(self):
1765 # PROTOCOL_TLS_CLIENT has sane defaults
1766 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1767 self.assertTrue(ctx.check_hostname)
1768 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1769
1770 # PROTOCOL_TLS_SERVER has different but also sane defaults
1771 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1772 self.assertFalse(ctx.check_hostname)
1773 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1774
Christian Heimes4df60f12017-09-15 20:26:05 +02001775 def test_context_custom_class(self):
1776 class MySSLSocket(ssl.SSLSocket):
1777 pass
1778
1779 class MySSLObject(ssl.SSLObject):
1780 pass
1781
1782 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1783 ctx.sslsocket_class = MySSLSocket
1784 ctx.sslobject_class = MySSLObject
1785
1786 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1787 self.assertIsInstance(sock, MySSLSocket)
1788 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1789 self.assertIsInstance(obj, MySSLObject)
1790
Christian Heimes78c7d522019-06-03 21:00:10 +02001791 @unittest.skipUnless(IS_OPENSSL_1_1_1, "Test requires OpenSSL 1.1.1")
1792 def test_num_tickest(self):
1793 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1794 self.assertEqual(ctx.num_tickets, 2)
1795 ctx.num_tickets = 1
1796 self.assertEqual(ctx.num_tickets, 1)
1797 ctx.num_tickets = 0
1798 self.assertEqual(ctx.num_tickets, 0)
1799 with self.assertRaises(ValueError):
1800 ctx.num_tickets = -1
1801 with self.assertRaises(TypeError):
1802 ctx.num_tickets = None
1803
1804 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1805 self.assertEqual(ctx.num_tickets, 2)
1806 with self.assertRaises(ValueError):
1807 ctx.num_tickets = 1
1808
Antoine Pitrou152efa22010-05-16 18:19:27 +00001809
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001810class SSLErrorTests(unittest.TestCase):
1811
1812 def test_str(self):
1813 # The str() of a SSLError doesn't include the errno
1814 e = ssl.SSLError(1, "foo")
1815 self.assertEqual(str(e), "foo")
1816 self.assertEqual(e.errno, 1)
1817 # Same for a subclass
1818 e = ssl.SSLZeroReturnError(1, "foo")
1819 self.assertEqual(str(e), "foo")
1820 self.assertEqual(e.errno, 1)
1821
Paul Monsonf3550692019-06-19 13:09:54 -07001822 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001823 def test_lib_reason(self):
1824 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001825 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001826 with self.assertRaises(ssl.SSLError) as cm:
1827 ctx.load_dh_params(CERTFILE)
1828 self.assertEqual(cm.exception.library, 'PEM')
1829 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1830 s = str(cm.exception)
1831 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1832
1833 def test_subclass(self):
1834 # Check that the appropriate SSLError subclass is raised
1835 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001836 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1837 ctx.check_hostname = False
1838 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001839 with socket.create_server(("127.0.0.1", 0)) as s:
1840 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001841 c.setblocking(False)
1842 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001843 with self.assertRaises(ssl.SSLWantReadError) as cm:
1844 c.do_handshake()
1845 s = str(cm.exception)
1846 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1847 # For compatibility
1848 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1849
1850
Christian Heimes61d478c2018-01-27 15:51:38 +01001851 def test_bad_server_hostname(self):
1852 ctx = ssl.create_default_context()
1853 with self.assertRaises(ValueError):
1854 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1855 server_hostname="")
1856 with self.assertRaises(ValueError):
1857 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1858 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001859 with self.assertRaises(TypeError):
1860 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1861 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001862
1863
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001864class MemoryBIOTests(unittest.TestCase):
1865
1866 def test_read_write(self):
1867 bio = ssl.MemoryBIO()
1868 bio.write(b'foo')
1869 self.assertEqual(bio.read(), b'foo')
1870 self.assertEqual(bio.read(), b'')
1871 bio.write(b'foo')
1872 bio.write(b'bar')
1873 self.assertEqual(bio.read(), b'foobar')
1874 self.assertEqual(bio.read(), b'')
1875 bio.write(b'baz')
1876 self.assertEqual(bio.read(2), b'ba')
1877 self.assertEqual(bio.read(1), b'z')
1878 self.assertEqual(bio.read(1), b'')
1879
1880 def test_eof(self):
1881 bio = ssl.MemoryBIO()
1882 self.assertFalse(bio.eof)
1883 self.assertEqual(bio.read(), b'')
1884 self.assertFalse(bio.eof)
1885 bio.write(b'foo')
1886 self.assertFalse(bio.eof)
1887 bio.write_eof()
1888 self.assertFalse(bio.eof)
1889 self.assertEqual(bio.read(2), b'fo')
1890 self.assertFalse(bio.eof)
1891 self.assertEqual(bio.read(1), b'o')
1892 self.assertTrue(bio.eof)
1893 self.assertEqual(bio.read(), b'')
1894 self.assertTrue(bio.eof)
1895
1896 def test_pending(self):
1897 bio = ssl.MemoryBIO()
1898 self.assertEqual(bio.pending, 0)
1899 bio.write(b'foo')
1900 self.assertEqual(bio.pending, 3)
1901 for i in range(3):
1902 bio.read(1)
1903 self.assertEqual(bio.pending, 3-i-1)
1904 for i in range(3):
1905 bio.write(b'x')
1906 self.assertEqual(bio.pending, i+1)
1907 bio.read()
1908 self.assertEqual(bio.pending, 0)
1909
1910 def test_buffer_types(self):
1911 bio = ssl.MemoryBIO()
1912 bio.write(b'foo')
1913 self.assertEqual(bio.read(), b'foo')
1914 bio.write(bytearray(b'bar'))
1915 self.assertEqual(bio.read(), b'bar')
1916 bio.write(memoryview(b'baz'))
1917 self.assertEqual(bio.read(), b'baz')
1918
1919 def test_error_types(self):
1920 bio = ssl.MemoryBIO()
1921 self.assertRaises(TypeError, bio.write, 'foo')
1922 self.assertRaises(TypeError, bio.write, None)
1923 self.assertRaises(TypeError, bio.write, True)
1924 self.assertRaises(TypeError, bio.write, 1)
1925
1926
Christian Heimes9d50ab52018-02-27 10:17:30 +01001927class SSLObjectTests(unittest.TestCase):
1928 def test_private_init(self):
1929 bio = ssl.MemoryBIO()
1930 with self.assertRaisesRegex(TypeError, "public constructor"):
1931 ssl.SSLObject(bio, bio)
1932
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001933 def test_unwrap(self):
1934 client_ctx, server_ctx, hostname = testing_context()
1935 c_in = ssl.MemoryBIO()
1936 c_out = ssl.MemoryBIO()
1937 s_in = ssl.MemoryBIO()
1938 s_out = ssl.MemoryBIO()
1939 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1940 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1941
1942 # Loop on the handshake for a bit to get it settled
1943 for _ in range(5):
1944 try:
1945 client.do_handshake()
1946 except ssl.SSLWantReadError:
1947 pass
1948 if c_out.pending:
1949 s_in.write(c_out.read())
1950 try:
1951 server.do_handshake()
1952 except ssl.SSLWantReadError:
1953 pass
1954 if s_out.pending:
1955 c_in.write(s_out.read())
1956 # Now the handshakes should be complete (don't raise WantReadError)
1957 client.do_handshake()
1958 server.do_handshake()
1959
1960 # Now if we unwrap one side unilaterally, it should send close-notify
1961 # and raise WantReadError:
1962 with self.assertRaises(ssl.SSLWantReadError):
1963 client.unwrap()
1964
1965 # But server.unwrap() does not raise, because it reads the client's
1966 # close-notify:
1967 s_in.write(c_out.read())
1968 server.unwrap()
1969
1970 # And now that the client gets the server's close-notify, it doesn't
1971 # raise either.
1972 c_in.write(s_out.read())
1973 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001974
Martin Panter3840b2a2016-03-27 01:53:46 +00001975class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001976 """Tests that connect to a simple server running in the background"""
1977
1978 def setUp(self):
1979 server = ThreadedEchoServer(SIGNED_CERTFILE)
1980 self.server_addr = (HOST, server.port)
1981 server.__enter__()
1982 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001983
Antoine Pitrou480a1242010-04-28 21:37:09 +00001984 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001985 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001986 cert_reqs=ssl.CERT_NONE) as s:
1987 s.connect(self.server_addr)
1988 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001989 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001990
Martin Panter3840b2a2016-03-27 01:53:46 +00001991 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001992 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001993 cert_reqs=ssl.CERT_REQUIRED,
1994 ca_certs=SIGNING_CA) as s:
1995 s.connect(self.server_addr)
1996 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001997 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001998
Martin Panter3840b2a2016-03-27 01:53:46 +00001999 def test_connect_fail(self):
2000 # This should fail because we have no verification certs. Connection
2001 # failure crashes ThreadedEchoServer, so run this in an independent
2002 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02002003 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002004 cert_reqs=ssl.CERT_REQUIRED)
2005 self.addCleanup(s.close)
2006 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2007 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002008
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002009 def test_connect_ex(self):
2010 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02002011 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002012 cert_reqs=ssl.CERT_REQUIRED,
2013 ca_certs=SIGNING_CA)
2014 self.addCleanup(s.close)
2015 self.assertEqual(0, s.connect_ex(self.server_addr))
2016 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002017
2018 def test_non_blocking_connect_ex(self):
2019 # Issue #11326: non-blocking connect_ex() should allow handshake
2020 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02002021 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002022 cert_reqs=ssl.CERT_REQUIRED,
2023 ca_certs=SIGNING_CA,
2024 do_handshake_on_connect=False)
2025 self.addCleanup(s.close)
2026 s.setblocking(False)
2027 rc = s.connect_ex(self.server_addr)
2028 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2029 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2030 # Wait for connect to finish
2031 select.select([], [s], [], 5.0)
2032 # Non-blocking handshake
2033 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002034 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002035 s.do_handshake()
2036 break
2037 except ssl.SSLWantReadError:
2038 select.select([s], [], [], 5.0)
2039 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002040 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002041 # SSL established
2042 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002043
Antoine Pitrou152efa22010-05-16 18:19:27 +00002044 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002045 # Same as test_connect, but with a separately created context
Christian Heimesa170fa12017-09-15 20:27:30 +02002046 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002047 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2048 s.connect(self.server_addr)
2049 self.assertEqual({}, s.getpeercert())
2050 # Same with a server hostname
2051 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2052 server_hostname="dummy") as s:
2053 s.connect(self.server_addr)
2054 ctx.verify_mode = ssl.CERT_REQUIRED
2055 # This should succeed because we specify the root cert
2056 ctx.load_verify_locations(SIGNING_CA)
2057 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2058 s.connect(self.server_addr)
2059 cert = s.getpeercert()
2060 self.assertTrue(cert)
2061
2062 def test_connect_with_context_fail(self):
2063 # This should fail because we have no verification certs. Connection
2064 # failure crashes ThreadedEchoServer, so run this in an independent
2065 # test method.
Christian Heimesa170fa12017-09-15 20:27:30 +02002066 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002067 ctx.verify_mode = ssl.CERT_REQUIRED
2068 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
2069 self.addCleanup(s.close)
2070 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2071 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002072
2073 def test_connect_capath(self):
2074 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002075 # NOTE: the subject hashing algorithm has been changed between
2076 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2077 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002078 # filename) for this test to be portable across OpenSSL releases.
Christian Heimesa170fa12017-09-15 20:27:30 +02002079 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002080 ctx.verify_mode = ssl.CERT_REQUIRED
2081 ctx.load_verify_locations(capath=CAPATH)
2082 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2083 s.connect(self.server_addr)
2084 cert = s.getpeercert()
2085 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002086
Martin Panter3840b2a2016-03-27 01:53:46 +00002087 # Same with a bytes `capath` argument
Christian Heimesa170fa12017-09-15 20:27:30 +02002088 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002089 ctx.verify_mode = ssl.CERT_REQUIRED
2090 ctx.load_verify_locations(capath=BYTES_CAPATH)
2091 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2092 s.connect(self.server_addr)
2093 cert = s.getpeercert()
2094 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002095
Christian Heimesefff7062013-11-21 03:35:02 +01002096 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002097 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002098 pem = f.read()
2099 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimesa170fa12017-09-15 20:27:30 +02002100 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002101 ctx.verify_mode = ssl.CERT_REQUIRED
2102 ctx.load_verify_locations(cadata=pem)
2103 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2104 s.connect(self.server_addr)
2105 cert = s.getpeercert()
2106 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002107
Martin Panter3840b2a2016-03-27 01:53:46 +00002108 # same with DER
Christian Heimesa170fa12017-09-15 20:27:30 +02002109 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002110 ctx.verify_mode = ssl.CERT_REQUIRED
2111 ctx.load_verify_locations(cadata=der)
2112 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2113 s.connect(self.server_addr)
2114 cert = s.getpeercert()
2115 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002116
Antoine Pitroue3220242010-04-24 11:13:53 +00002117 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2118 def test_makefile_close(self):
2119 # Issue #5238: creating a file-like object with makefile() shouldn't
2120 # delay closing the underlying "real socket" (here tested with its
2121 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002122 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002123 ss.connect(self.server_addr)
2124 fd = ss.fileno()
2125 f = ss.makefile()
2126 f.close()
2127 # The fd is still open
2128 os.read(fd, 0)
2129 # Closing the SSL socket should close the fd too
2130 ss.close()
2131 gc.collect()
2132 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002133 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002134 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002135
Antoine Pitrou480a1242010-04-28 21:37:09 +00002136 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002137 s = socket.socket(socket.AF_INET)
2138 s.connect(self.server_addr)
2139 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002140 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002141 cert_reqs=ssl.CERT_NONE,
2142 do_handshake_on_connect=False)
2143 self.addCleanup(s.close)
2144 count = 0
2145 while True:
2146 try:
2147 count += 1
2148 s.do_handshake()
2149 break
2150 except ssl.SSLWantReadError:
2151 select.select([s], [], [])
2152 except ssl.SSLWantWriteError:
2153 select.select([], [s], [])
2154 if support.verbose:
2155 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002156
Antoine Pitrou480a1242010-04-28 21:37:09 +00002157 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002158 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002159
Martin Panter3840b2a2016-03-27 01:53:46 +00002160 def test_get_server_certificate_fail(self):
2161 # Connection failure crashes ThreadedEchoServer, so run this in an
2162 # independent test method
2163 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002164
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002165 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002166 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002167 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2168 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002169 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002170 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2171 s.connect(self.server_addr)
2172 # Error checking can happen at instantiation or when connecting
2173 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2174 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002175 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002176 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2177 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002178
Christian Heimes9a5395a2013-06-17 15:44:12 +02002179 def test_get_ca_certs_capath(self):
2180 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002181 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002182 ctx.load_verify_locations(capath=CAPATH)
2183 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002184 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2185 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002186 s.connect(self.server_addr)
2187 cert = s.getpeercert()
2188 self.assertTrue(cert)
2189 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002190
Christian Heimes575596e2013-12-15 21:49:17 +01002191 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01002192 def test_context_setget(self):
2193 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002194 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2195 ctx1.load_verify_locations(capath=CAPATH)
2196 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2197 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002198 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002199 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002200 ss.connect(self.server_addr)
2201 self.assertIs(ss.context, ctx1)
2202 self.assertIs(ss._sslobj.context, ctx1)
2203 ss.context = ctx2
2204 self.assertIs(ss.context, ctx2)
2205 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002206
2207 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2208 # A simple IO loop. Call func(*args) depending on the error we get
2209 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002210 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002211 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002212 count = 0
2213 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002214 if time.monotonic() > deadline:
2215 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002216 errno = None
2217 count += 1
2218 try:
2219 ret = func(*args)
2220 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002221 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002222 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002223 raise
2224 errno = e.errno
2225 # Get any data from the outgoing BIO irrespective of any error, and
2226 # send it to the socket.
2227 buf = outgoing.read()
2228 sock.sendall(buf)
2229 # If there's no error, we're done. For WANT_READ, we need to get
2230 # data from the socket and put it in the incoming BIO.
2231 if errno is None:
2232 break
2233 elif errno == ssl.SSL_ERROR_WANT_READ:
2234 buf = sock.recv(32768)
2235 if buf:
2236 incoming.write(buf)
2237 else:
2238 incoming.write_eof()
2239 if support.verbose:
2240 sys.stdout.write("Needed %d calls to complete %s().\n"
2241 % (count, func.__name__))
2242 return ret
2243
Martin Panter3840b2a2016-03-27 01:53:46 +00002244 def test_bio_handshake(self):
2245 sock = socket.socket(socket.AF_INET)
2246 self.addCleanup(sock.close)
2247 sock.connect(self.server_addr)
2248 incoming = ssl.MemoryBIO()
2249 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002250 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2251 self.assertTrue(ctx.check_hostname)
2252 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002253 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002254 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2255 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002256 self.assertIs(sslobj._sslobj.owner, sslobj)
2257 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002258 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002259 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002260 self.assertRaises(ValueError, sslobj.getpeercert)
2261 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2262 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2263 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2264 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002265 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002266 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002267 self.assertTrue(sslobj.getpeercert())
2268 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2269 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2270 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002271 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002272 except ssl.SSLSyscallError:
2273 # If the server shuts down the TCP connection without sending a
2274 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2275 pass
2276 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2277
2278 def test_bio_read_write_data(self):
2279 sock = socket.socket(socket.AF_INET)
2280 self.addCleanup(sock.close)
2281 sock.connect(self.server_addr)
2282 incoming = ssl.MemoryBIO()
2283 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002284 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002285 ctx.verify_mode = ssl.CERT_NONE
2286 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2287 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2288 req = b'FOO\n'
2289 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2290 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2291 self.assertEqual(buf, b'foo\n')
2292 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002293
2294
Martin Panter3840b2a2016-03-27 01:53:46 +00002295class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002296
Martin Panter3840b2a2016-03-27 01:53:46 +00002297 def test_timeout_connect_ex(self):
2298 # Issue #12065: on a timeout, connect_ex() should return the original
2299 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002300 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002301 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002302 cert_reqs=ssl.CERT_REQUIRED,
2303 do_handshake_on_connect=False)
2304 self.addCleanup(s.close)
2305 s.settimeout(0.0000001)
2306 rc = s.connect_ex((REMOTE_HOST, 443))
2307 if rc == 0:
2308 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002309 elif rc == errno.ENETUNREACH:
2310 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002311 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2312
Serhiy Storchaka16994912020-04-25 10:06:29 +03002313 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002314 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002315 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002316 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2317 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2318
Martin Panter3840b2a2016-03-27 01:53:46 +00002319
2320def _test_get_server_certificate(test, host, port, cert=None):
2321 pem = ssl.get_server_certificate((host, port))
2322 if not pem:
2323 test.fail("No server certificate on %s:%s!" % (host, port))
2324
2325 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2326 if not pem:
2327 test.fail("No server certificate on %s:%s!" % (host, port))
2328 if support.verbose:
2329 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2330
2331def _test_get_server_certificate_fail(test, host, port):
2332 try:
2333 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2334 except ssl.SSLError as x:
2335 #should fail
2336 if support.verbose:
2337 sys.stdout.write("%s\n" % x)
2338 else:
2339 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2340
2341
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002342from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002343
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002344class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002345
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002346 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002347
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002348 """A mildly complicated class, because we want it to work both
2349 with and without the SSL wrapper around the socket connection, so
2350 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002351
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002352 def __init__(self, server, connsock, addr):
2353 self.server = server
2354 self.running = False
2355 self.sock = connsock
2356 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002357 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002358 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002359 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002360 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002361
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002362 def wrap_conn(self):
2363 try:
2364 self.sslconn = self.server.context.wrap_socket(
2365 self.sock, server_side=True)
2366 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
2367 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002368 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002369 # We treat ConnectionResetError as though it were an
2370 # SSLError - OpenSSL on Ubuntu abruptly closes the
2371 # connection when asked to use an unsupported protocol.
2372 #
Christian Heimes529525f2018-05-23 22:24:45 +02002373 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2374 # tries to send session tickets after handshake.
2375 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002376 #
2377 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2378 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002379 self.server.conn_errors.append(str(e))
2380 if self.server.chatty:
2381 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2382 self.running = False
2383 self.close()
2384 return False
2385 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002386 # OSError may occur with wrong protocols, e.g. both
2387 # sides use PROTOCOL_TLS_SERVER.
2388 #
2389 # XXX Various errors can have happened here, for example
2390 # a mismatching protocol version, an invalid certificate,
2391 # or a low-level bug. This should be made more discriminating.
2392 #
2393 # bpo-31323: Store the exception as string to prevent
2394 # a reference leak: server -> conn_errors -> exception
2395 # -> traceback -> self (ConnectionHandler) -> server
2396 self.server.conn_errors.append(str(e))
2397 if self.server.chatty:
2398 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2399 self.running = False
2400 self.server.stop()
2401 self.close()
2402 return False
2403 else:
2404 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2405 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2406 cert = self.sslconn.getpeercert()
2407 if support.verbose and self.server.chatty:
2408 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2409 cert_binary = self.sslconn.getpeercert(True)
2410 if support.verbose and self.server.chatty:
2411 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2412 cipher = self.sslconn.cipher()
2413 if support.verbose and self.server.chatty:
2414 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
2415 sys.stdout.write(" server: selected protocol is now "
2416 + str(self.sslconn.selected_npn_protocol()) + "\n")
2417 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002418
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002419 def read(self):
2420 if self.sslconn:
2421 return self.sslconn.read()
2422 else:
2423 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002424
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002425 def write(self, bytes):
2426 if self.sslconn:
2427 return self.sslconn.write(bytes)
2428 else:
2429 return self.sock.send(bytes)
2430
2431 def close(self):
2432 if self.sslconn:
2433 self.sslconn.close()
2434 else:
2435 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002436
Antoine Pitrou480a1242010-04-28 21:37:09 +00002437 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002438 self.running = True
2439 if not self.server.starttls_server:
2440 if not self.wrap_conn():
2441 return
2442 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002443 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002444 msg = self.read()
2445 stripped = msg.strip()
2446 if not stripped:
2447 # eof, so quit this handler
2448 self.running = False
2449 try:
2450 self.sock = self.sslconn.unwrap()
2451 except OSError:
2452 # Many tests shut the TCP connection down
2453 # without an SSL shutdown. This causes
2454 # unwrap() to raise OSError with errno=0!
2455 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002456 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002457 self.sslconn = None
2458 self.close()
2459 elif stripped == b'over':
2460 if support.verbose and self.server.connectionchatty:
2461 sys.stdout.write(" server: client closed connection\n")
2462 self.close()
2463 return
2464 elif (self.server.starttls_server and
2465 stripped == b'STARTTLS'):
2466 if support.verbose and self.server.connectionchatty:
2467 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2468 self.write(b"OK\n")
2469 if not self.wrap_conn():
2470 return
2471 elif (self.server.starttls_server and self.sslconn
2472 and stripped == b'ENDTLS'):
2473 if support.verbose and self.server.connectionchatty:
2474 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2475 self.write(b"OK\n")
2476 self.sock = self.sslconn.unwrap()
2477 self.sslconn = None
2478 if support.verbose and self.server.connectionchatty:
2479 sys.stdout.write(" server: connection is now unencrypted...\n")
2480 elif stripped == b'CB tls-unique':
2481 if support.verbose and self.server.connectionchatty:
2482 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2483 data = self.sslconn.get_channel_binding("tls-unique")
2484 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002485 elif stripped == b'PHA':
2486 if support.verbose and self.server.connectionchatty:
2487 sys.stdout.write(" server: initiating post handshake auth\n")
2488 try:
2489 self.sslconn.verify_client_post_handshake()
2490 except ssl.SSLError as e:
2491 self.write(repr(e).encode("us-ascii") + b"\n")
2492 else:
2493 self.write(b"OK\n")
2494 elif stripped == b'HASCERT':
2495 if self.sslconn.getpeercert() is not None:
2496 self.write(b'TRUE\n')
2497 else:
2498 self.write(b'FALSE\n')
2499 elif stripped == b'GETCERT':
2500 cert = self.sslconn.getpeercert()
2501 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002502 else:
2503 if (support.verbose and
2504 self.server.connectionchatty):
2505 ctype = (self.sslconn and "encrypted") or "unencrypted"
2506 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2507 % (msg, ctype, msg.lower(), ctype))
2508 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002509 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002510 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2511 # when connection is not shut down gracefully.
2512 if self.server.chatty and support.verbose:
2513 sys.stdout.write(
2514 " Connection reset by peer: {}\n".format(
2515 self.addr)
2516 )
2517 self.close()
2518 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002519 except ssl.SSLError as err:
2520 # On Windows sometimes test_pha_required_nocert receives the
2521 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2522 # before the 'tlsv13 alert certificate required' exception.
2523 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2524 # is received test_pha_required_nocert fails with ConnectionResetError
2525 # because the underlying socket is closed
2526 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2527 if self.server.chatty and support.verbose:
2528 sys.stdout.write(err.args[1])
2529 # test_pha_required_nocert is expecting this exception
2530 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002531 except OSError:
2532 if self.server.chatty:
2533 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002534 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002535 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002536
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002537 # normally, we'd just stop here, but for the test
2538 # harness, we want to stop the server
2539 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002540
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002541 def __init__(self, certificate=None, ssl_version=None,
2542 certreqs=None, cacerts=None,
2543 chatty=True, connectionchatty=False, starttls_server=False,
2544 npn_protocols=None, alpn_protocols=None,
2545 ciphers=None, context=None):
2546 if context:
2547 self.context = context
2548 else:
2549 self.context = ssl.SSLContext(ssl_version
2550 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002551 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002552 self.context.verify_mode = (certreqs if certreqs is not None
2553 else ssl.CERT_NONE)
2554 if cacerts:
2555 self.context.load_verify_locations(cacerts)
2556 if certificate:
2557 self.context.load_cert_chain(certificate)
2558 if npn_protocols:
2559 self.context.set_npn_protocols(npn_protocols)
2560 if alpn_protocols:
2561 self.context.set_alpn_protocols(alpn_protocols)
2562 if ciphers:
2563 self.context.set_ciphers(ciphers)
2564 self.chatty = chatty
2565 self.connectionchatty = connectionchatty
2566 self.starttls_server = starttls_server
2567 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002568 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002569 self.flag = None
2570 self.active = False
2571 self.selected_npn_protocols = []
2572 self.selected_alpn_protocols = []
2573 self.shared_ciphers = []
2574 self.conn_errors = []
2575 threading.Thread.__init__(self)
2576 self.daemon = True
2577
2578 def __enter__(self):
2579 self.start(threading.Event())
2580 self.flag.wait()
2581 return self
2582
2583 def __exit__(self, *args):
2584 self.stop()
2585 self.join()
2586
2587 def start(self, flag=None):
2588 self.flag = flag
2589 threading.Thread.start(self)
2590
2591 def run(self):
2592 self.sock.settimeout(0.05)
2593 self.sock.listen()
2594 self.active = True
2595 if self.flag:
2596 # signal an event
2597 self.flag.set()
2598 while self.active:
2599 try:
2600 newconn, connaddr = self.sock.accept()
2601 if support.verbose and self.chatty:
2602 sys.stdout.write(' server: new connection from '
2603 + repr(connaddr) + '\n')
2604 handler = self.ConnectionHandler(self, newconn, connaddr)
2605 handler.start()
2606 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002607 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002608 pass
2609 except KeyboardInterrupt:
2610 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002611 except BaseException as e:
2612 if support.verbose and self.chatty:
2613 sys.stdout.write(
2614 ' connection handling failed: ' + repr(e) + '\n')
2615
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002616 self.sock.close()
2617
2618 def stop(self):
2619 self.active = False
2620
2621class AsyncoreEchoServer(threading.Thread):
2622
2623 # this one's based on asyncore.dispatcher
2624
2625 class EchoServer (asyncore.dispatcher):
2626
2627 class ConnectionHandler(asyncore.dispatcher_with_send):
2628
2629 def __init__(self, conn, certfile):
2630 self.socket = test_wrap_socket(conn, server_side=True,
2631 certfile=certfile,
2632 do_handshake_on_connect=False)
2633 asyncore.dispatcher_with_send.__init__(self, self.socket)
2634 self._ssl_accepting = True
2635 self._do_ssl_handshake()
2636
2637 def readable(self):
2638 if isinstance(self.socket, ssl.SSLSocket):
2639 while self.socket.pending() > 0:
2640 self.handle_read_event()
2641 return True
2642
2643 def _do_ssl_handshake(self):
2644 try:
2645 self.socket.do_handshake()
2646 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2647 return
2648 except ssl.SSLEOFError:
2649 return self.handle_close()
2650 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002651 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002652 except OSError as err:
2653 if err.args[0] == errno.ECONNABORTED:
2654 return self.handle_close()
2655 else:
2656 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002657
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002658 def handle_read(self):
2659 if self._ssl_accepting:
2660 self._do_ssl_handshake()
2661 else:
2662 data = self.recv(1024)
2663 if support.verbose:
2664 sys.stdout.write(" server: read %s from client\n" % repr(data))
2665 if not data:
2666 self.close()
2667 else:
2668 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002669
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002670 def handle_close(self):
2671 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002672 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002673 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002674
2675 def handle_error(self):
2676 raise
2677
Trent Nelson78520002008-04-10 20:54:35 +00002678 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002679 self.certfile = certfile
2680 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002681 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002682 asyncore.dispatcher.__init__(self, sock)
2683 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002684
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002685 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002686 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002687 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2688 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002689
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002690 def handle_error(self):
2691 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002692
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002693 def __init__(self, certfile):
2694 self.flag = None
2695 self.active = False
2696 self.server = self.EchoServer(certfile)
2697 self.port = self.server.port
2698 threading.Thread.__init__(self)
2699 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002700
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002701 def __str__(self):
2702 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002703
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002704 def __enter__(self):
2705 self.start(threading.Event())
2706 self.flag.wait()
2707 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002708
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002709 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002710 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002711 sys.stdout.write(" cleanup: stopping server.\n")
2712 self.stop()
2713 if support.verbose:
2714 sys.stdout.write(" cleanup: joining server thread.\n")
2715 self.join()
2716 if support.verbose:
2717 sys.stdout.write(" cleanup: successfully joined.\n")
2718 # make sure that ConnectionHandler is removed from socket_map
2719 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002720
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002721 def start (self, flag=None):
2722 self.flag = flag
2723 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002724
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002725 def run(self):
2726 self.active = True
2727 if self.flag:
2728 self.flag.set()
2729 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002730 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002731 asyncore.loop(1)
2732 except:
2733 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002734
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002735 def stop(self):
2736 self.active = False
2737 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002738
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002739def server_params_test(client_context, server_context, indata=b"FOO\n",
2740 chatty=True, connectionchatty=False, sni_name=None,
2741 session=None):
2742 """
2743 Launch a server, connect a client to it and try various reads
2744 and writes.
2745 """
2746 stats = {}
2747 server = ThreadedEchoServer(context=server_context,
2748 chatty=chatty,
2749 connectionchatty=False)
2750 with server:
2751 with client_context.wrap_socket(socket.socket(),
2752 server_hostname=sni_name, session=session) as s:
2753 s.connect((HOST, server.port))
2754 for arg in [indata, bytearray(indata), memoryview(indata)]:
2755 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002756 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002757 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002758 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002759 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002760 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002761 if connectionchatty:
2762 if support.verbose:
2763 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002764 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002765 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002766 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2767 % (outdata[:20], len(outdata),
2768 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002769 s.write(b"over\n")
2770 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002771 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002772 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002773 stats.update({
2774 'compression': s.compression(),
2775 'cipher': s.cipher(),
2776 'peercert': s.getpeercert(),
2777 'client_alpn_protocol': s.selected_alpn_protocol(),
2778 'client_npn_protocol': s.selected_npn_protocol(),
2779 'version': s.version(),
2780 'session_reused': s.session_reused,
2781 'session': s.session,
2782 })
2783 s.close()
2784 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2785 stats['server_npn_protocols'] = server.selected_npn_protocols
2786 stats['server_shared_ciphers'] = server.shared_ciphers
2787 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002788
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002789def try_protocol_combo(server_protocol, client_protocol, expect_success,
2790 certsreqs=None, server_options=0, client_options=0):
2791 """
2792 Try to SSL-connect using *client_protocol* to *server_protocol*.
2793 If *expect_success* is true, assert that the connection succeeds,
2794 if it's false, assert that the connection fails.
2795 Also, if *expect_success* is a string, assert that it is the protocol
2796 version actually used by the connection.
2797 """
2798 if certsreqs is None:
2799 certsreqs = ssl.CERT_NONE
2800 certtype = {
2801 ssl.CERT_NONE: "CERT_NONE",
2802 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2803 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2804 }[certsreqs]
2805 if support.verbose:
2806 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2807 sys.stdout.write(formatstr %
2808 (ssl.get_protocol_name(client_protocol),
2809 ssl.get_protocol_name(server_protocol),
2810 certtype))
2811 client_context = ssl.SSLContext(client_protocol)
2812 client_context.options |= client_options
2813 server_context = ssl.SSLContext(server_protocol)
2814 server_context.options |= server_options
2815
Victor Stinner3ef63442019-02-19 18:06:03 +01002816 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2817 if (min_version is not None
2818 # SSLContext.minimum_version is only available on recent OpenSSL
2819 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2820 and hasattr(server_context, 'minimum_version')
2821 and server_protocol == ssl.PROTOCOL_TLS
2822 and server_context.minimum_version > min_version):
2823 # If OpenSSL configuration is strict and requires more recent TLS
2824 # version, we have to change the minimum to test old TLS versions.
2825 server_context.minimum_version = min_version
2826
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002827 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2828 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2829 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002830 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002831 client_context.set_ciphers("ALL")
2832
Christian Heimesf6c6b582021-03-18 23:06:50 +01002833 seclevel_workaround(server_context, client_context)
2834
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002835 for ctx in (client_context, server_context):
2836 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002837 ctx.load_cert_chain(SIGNED_CERTFILE)
2838 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002839 try:
2840 stats = server_params_test(client_context, server_context,
2841 chatty=False, connectionchatty=False)
2842 # Protocol mismatch can result in either an SSLError, or a
2843 # "Connection reset by peer" error.
2844 except ssl.SSLError:
2845 if expect_success:
2846 raise
2847 except OSError as e:
2848 if expect_success or e.errno != errno.ECONNRESET:
2849 raise
2850 else:
2851 if not expect_success:
2852 raise AssertionError(
2853 "Client protocol %s succeeded with server protocol %s!"
2854 % (ssl.get_protocol_name(client_protocol),
2855 ssl.get_protocol_name(server_protocol)))
2856 elif (expect_success is not True
2857 and expect_success != stats['version']):
2858 raise AssertionError("version mismatch: expected %r, got %r"
2859 % (expect_success, stats['version']))
2860
2861
2862class ThreadedTests(unittest.TestCase):
2863
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002864 def test_echo(self):
2865 """Basic test of an SSL client connecting to a server"""
2866 if support.verbose:
2867 sys.stdout.write("\n")
2868 for protocol in PROTOCOLS:
2869 if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
2870 continue
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02002871 if not has_tls_protocol(protocol):
2872 continue
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002873 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2874 context = ssl.SSLContext(protocol)
2875 context.load_cert_chain(CERTFILE)
Christian Heimesf6c6b582021-03-18 23:06:50 +01002876 seclevel_workaround(context)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002877 server_params_test(context, context,
2878 chatty=True, connectionchatty=True)
2879
Christian Heimesa170fa12017-09-15 20:27:30 +02002880 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002881
2882 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2883 server_params_test(client_context=client_context,
2884 server_context=server_context,
2885 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002886 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002887
2888 client_context.check_hostname = False
2889 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2890 with self.assertRaises(ssl.SSLError) as e:
2891 server_params_test(client_context=server_context,
2892 server_context=client_context,
2893 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002894 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002895 self.assertIn('called a function you should not call',
2896 str(e.exception))
2897
2898 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2899 with self.assertRaises(ssl.SSLError) as e:
2900 server_params_test(client_context=server_context,
2901 server_context=server_context,
2902 chatty=True, connectionchatty=True)
2903 self.assertIn('called a function you should not call',
2904 str(e.exception))
2905
2906 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2907 with self.assertRaises(ssl.SSLError) as e:
2908 server_params_test(client_context=server_context,
2909 server_context=client_context,
2910 chatty=True, connectionchatty=True)
2911 self.assertIn('called a function you should not call',
2912 str(e.exception))
2913
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002914 def test_getpeercert(self):
2915 if support.verbose:
2916 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002917
2918 client_context, server_context, hostname = testing_context()
2919 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002920 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002921 with client_context.wrap_socket(socket.socket(),
2922 do_handshake_on_connect=False,
2923 server_hostname=hostname) as s:
2924 s.connect((HOST, server.port))
2925 # getpeercert() raise ValueError while the handshake isn't
2926 # done.
2927 with self.assertRaises(ValueError):
2928 s.getpeercert()
2929 s.do_handshake()
2930 cert = s.getpeercert()
2931 self.assertTrue(cert, "Can't get peer certificate.")
2932 cipher = s.cipher()
2933 if support.verbose:
2934 sys.stdout.write(pprint.pformat(cert) + '\n')
2935 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2936 if 'subject' not in cert:
2937 self.fail("No subject field in certificate: %s." %
2938 pprint.pformat(cert))
2939 if ((('organizationName', 'Python Software Foundation'),)
2940 not in cert['subject']):
2941 self.fail(
2942 "Missing or invalid 'organizationName' field in certificate subject; "
2943 "should be 'Python Software Foundation'.")
2944 self.assertIn('notBefore', cert)
2945 self.assertIn('notAfter', cert)
2946 before = ssl.cert_time_to_seconds(cert['notBefore'])
2947 after = ssl.cert_time_to_seconds(cert['notAfter'])
2948 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002949
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002950 @unittest.skipUnless(have_verify_flags(),
2951 "verify_flags need OpenSSL > 0.9.8")
2952 def test_crl_check(self):
2953 if support.verbose:
2954 sys.stdout.write("\n")
2955
Christian Heimesa170fa12017-09-15 20:27:30 +02002956 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002957
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002958 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002959 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002960
2961 # VERIFY_DEFAULT should pass
2962 server = ThreadedEchoServer(context=server_context, chatty=True)
2963 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002964 with client_context.wrap_socket(socket.socket(),
2965 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002966 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002967 cert = s.getpeercert()
2968 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002969
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002970 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002971 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002972
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002973 server = ThreadedEchoServer(context=server_context, chatty=True)
2974 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002975 with client_context.wrap_socket(socket.socket(),
2976 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002977 with self.assertRaisesRegex(ssl.SSLError,
2978 "certificate verify failed"):
2979 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002980
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002981 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002982 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002983
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002984 server = ThreadedEchoServer(context=server_context, chatty=True)
2985 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002986 with client_context.wrap_socket(socket.socket(),
2987 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002988 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002989 cert = s.getpeercert()
2990 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002991
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002992 def test_check_hostname(self):
2993 if support.verbose:
2994 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002995
Christian Heimesa170fa12017-09-15 20:27:30 +02002996 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002997
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002998 # correct hostname should verify
2999 server = ThreadedEchoServer(context=server_context, chatty=True)
3000 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003001 with client_context.wrap_socket(socket.socket(),
3002 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003003 s.connect((HOST, server.port))
3004 cert = s.getpeercert()
3005 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003006
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003007 # incorrect hostname should raise an exception
3008 server = ThreadedEchoServer(context=server_context, chatty=True)
3009 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02003010 with client_context.wrap_socket(socket.socket(),
3011 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01003012 with self.assertRaisesRegex(
3013 ssl.CertificateError,
3014 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003015 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003016
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003017 # missing server_hostname arg should cause an exception, too
3018 server = ThreadedEchoServer(context=server_context, chatty=True)
3019 with server:
3020 with socket.socket() as s:
3021 with self.assertRaisesRegex(ValueError,
3022 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02003023 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003024
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003025 def test_ecc_cert(self):
3026 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3027 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003028 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003029 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3030
3031 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3032 # load ECC cert
3033 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3034
3035 # correct hostname should verify
3036 server = ThreadedEchoServer(context=server_context, chatty=True)
3037 with server:
3038 with client_context.wrap_socket(socket.socket(),
3039 server_hostname=hostname) as s:
3040 s.connect((HOST, server.port))
3041 cert = s.getpeercert()
3042 self.assertTrue(cert, "Can't get peer certificate.")
3043 cipher = s.cipher()[0].split('-')
3044 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3045
3046 def test_dual_rsa_ecc(self):
3047 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3048 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003049 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3050 # algorithms.
3051 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003052 # only ECDSA certs
3053 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3054 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3055
3056 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3057 # load ECC and RSA key/cert pairs
3058 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3059 server_context.load_cert_chain(SIGNED_CERTFILE)
3060
3061 # correct hostname should verify
3062 server = ThreadedEchoServer(context=server_context, chatty=True)
3063 with server:
3064 with client_context.wrap_socket(socket.socket(),
3065 server_hostname=hostname) as s:
3066 s.connect((HOST, server.port))
3067 cert = s.getpeercert()
3068 self.assertTrue(cert, "Can't get peer certificate.")
3069 cipher = s.cipher()[0].split('-')
3070 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3071
Christian Heimes66e57422018-01-29 14:25:13 +01003072 def test_check_hostname_idn(self):
3073 if support.verbose:
3074 sys.stdout.write("\n")
3075
Christian Heimes11a14932018-02-24 02:35:08 +01003076 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003077 server_context.load_cert_chain(IDNSANSFILE)
3078
Christian Heimes11a14932018-02-24 02:35:08 +01003079 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003080 context.verify_mode = ssl.CERT_REQUIRED
3081 context.check_hostname = True
3082 context.load_verify_locations(SIGNING_CA)
3083
3084 # correct hostname should verify, when specified in several
3085 # different ways
3086 idn_hostnames = [
3087 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003088 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003089 ('xn--knig-5qa.idn.pythontest.net',
3090 'xn--knig-5qa.idn.pythontest.net'),
3091 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003092 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003093
3094 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003095 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003096 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3097 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3098 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003099 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3100
3101 # ('königsgäßchen.idna2008.pythontest.net',
3102 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3103 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3104 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3105 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3106 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3107
Christian Heimes66e57422018-01-29 14:25:13 +01003108 ]
3109 for server_hostname, expected_hostname in idn_hostnames:
3110 server = ThreadedEchoServer(context=server_context, chatty=True)
3111 with server:
3112 with context.wrap_socket(socket.socket(),
3113 server_hostname=server_hostname) as s:
3114 self.assertEqual(s.server_hostname, expected_hostname)
3115 s.connect((HOST, server.port))
3116 cert = s.getpeercert()
3117 self.assertEqual(s.server_hostname, expected_hostname)
3118 self.assertTrue(cert, "Can't get peer certificate.")
3119
Christian Heimes66e57422018-01-29 14:25:13 +01003120 # incorrect hostname should raise an exception
3121 server = ThreadedEchoServer(context=server_context, chatty=True)
3122 with server:
3123 with context.wrap_socket(socket.socket(),
3124 server_hostname="python.example.org") as s:
3125 with self.assertRaises(ssl.CertificateError):
3126 s.connect((HOST, server.port))
3127
Christian Heimes529525f2018-05-23 22:24:45 +02003128 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003129 """Connecting when the server rejects the client's certificate
3130
3131 Launch a server with CERT_REQUIRED, and check that trying to
3132 connect to it with a wrong client certificate fails.
3133 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003134 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003135 # load client cert that is not signed by trusted CA
3136 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003137 # require TLS client authentication
3138 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003139 # TLS 1.3 has different handshake
3140 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003141
3142 server = ThreadedEchoServer(
3143 context=server_context, chatty=True, connectionchatty=True,
3144 )
3145
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003146 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003147 client_context.wrap_socket(socket.socket(),
3148 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003149 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003150 # Expect either an SSL error about the server rejecting
3151 # the connection, or a low-level connection reset (which
3152 # sometimes happens on Windows)
3153 s.connect((HOST, server.port))
3154 except ssl.SSLError as e:
3155 if support.verbose:
3156 sys.stdout.write("\nSSLError is %r\n" % e)
3157 except OSError as e:
3158 if e.errno != errno.ECONNRESET:
3159 raise
3160 if support.verbose:
3161 sys.stdout.write("\nsocket.error is %r\n" % e)
3162 else:
3163 self.fail("Use of invalid cert should have failed!")
3164
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003165 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003166 def test_wrong_cert_tls13(self):
3167 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003168 # load client cert that is not signed by trusted CA
3169 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003170 server_context.verify_mode = ssl.CERT_REQUIRED
3171 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3172 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3173
3174 server = ThreadedEchoServer(
3175 context=server_context, chatty=True, connectionchatty=True,
3176 )
3177 with server, \
3178 client_context.wrap_socket(socket.socket(),
3179 server_hostname=hostname) as s:
3180 # TLS 1.3 perform client cert exchange after handshake
3181 s.connect((HOST, server.port))
3182 try:
3183 s.write(b'data')
3184 s.read(4)
3185 except ssl.SSLError as e:
3186 if support.verbose:
3187 sys.stdout.write("\nSSLError is %r\n" % e)
3188 except OSError as e:
3189 if e.errno != errno.ECONNRESET:
3190 raise
3191 if support.verbose:
3192 sys.stdout.write("\nsocket.error is %r\n" % e)
3193 else:
3194 self.fail("Use of invalid cert should have failed!")
3195
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003196 def test_rude_shutdown(self):
3197 """A brutal shutdown of an SSL server should raise an OSError
3198 in the client when attempting handshake.
3199 """
3200 listener_ready = threading.Event()
3201 listener_gone = threading.Event()
3202
3203 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003204 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003205
3206 # `listener` runs in a thread. It sits in an accept() until
3207 # the main thread connects. Then it rudely closes the socket,
3208 # and sets Event `listener_gone` to let the main thread know
3209 # the socket is gone.
3210 def listener():
3211 s.listen()
3212 listener_ready.set()
3213 newsock, addr = s.accept()
3214 newsock.close()
3215 s.close()
3216 listener_gone.set()
3217
3218 def connector():
3219 listener_ready.wait()
3220 with socket.socket() as c:
3221 c.connect((HOST, port))
3222 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003223 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003224 ssl_sock = test_wrap_socket(c)
3225 except OSError:
3226 pass
3227 else:
3228 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003229
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003230 t = threading.Thread(target=listener)
3231 t.start()
3232 try:
3233 connector()
3234 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003235 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003236
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003237 def test_ssl_cert_verify_error(self):
3238 if support.verbose:
3239 sys.stdout.write("\n")
3240
3241 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3242 server_context.load_cert_chain(SIGNED_CERTFILE)
3243
3244 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3245
3246 server = ThreadedEchoServer(context=server_context, chatty=True)
3247 with server:
3248 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003249 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003250 try:
3251 s.connect((HOST, server.port))
3252 except ssl.SSLError as e:
3253 msg = 'unable to get local issuer certificate'
3254 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3255 self.assertEqual(e.verify_code, 20)
3256 self.assertEqual(e.verify_message, msg)
3257 self.assertIn(msg, repr(e))
3258 self.assertIn('certificate verify failed', repr(e))
3259
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003260 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003261 def test_protocol_sslv2(self):
3262 """Connecting to an SSLv2 server with various client options"""
3263 if support.verbose:
3264 sys.stdout.write("\n")
3265 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3266 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3267 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003268 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003269 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003270 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3271 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3272 # SSLv23 client with specific SSL options
3273 if no_sslv2_implies_sslv3_hello():
3274 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003275 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003276 client_options=ssl.OP_NO_SSLv2)
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_SSLv3)
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_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003281
Christian Heimesa170fa12017-09-15 20:27:30 +02003282 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003283 """Connecting to an SSLv23 server with various client options"""
3284 if support.verbose:
3285 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003286 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003287 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003288 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003289 except OSError as x:
3290 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3291 if support.verbose:
3292 sys.stdout.write(
3293 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3294 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003295 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003296 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3297 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003298 if has_tls_version('TLSv1'):
3299 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003300
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003301 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003302 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3303 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003304 if has_tls_version('TLSv1'):
3305 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003306
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003307 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003308 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3309 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003310 if has_tls_version('TLSv1'):
3311 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003312
3313 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003314 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003315 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003316 server_options=ssl.OP_NO_SSLv3)
3317 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003318 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003319 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003320 if has_tls_version('TLSv1'):
3321 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3322 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003323
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003324 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003325 def test_protocol_sslv3(self):
3326 """Connecting to an SSLv3 server with various client options"""
3327 if support.verbose:
3328 sys.stdout.write("\n")
3329 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3330 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3331 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003332 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003333 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003334 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003335 client_options=ssl.OP_NO_SSLv3)
3336 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3337 if no_sslv2_implies_sslv3_hello():
3338 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003339 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003340 False, client_options=ssl.OP_NO_SSLv2)
3341
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003342 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003343 def test_protocol_tlsv1(self):
3344 """Connecting to a TLSv1 server with various client options"""
3345 if support.verbose:
3346 sys.stdout.write("\n")
3347 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3348 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3349 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003350 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003351 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003352 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003353 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003354 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003355 client_options=ssl.OP_NO_TLSv1)
3356
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003357 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003358 def test_protocol_tlsv1_1(self):
3359 """Connecting to a TLSv1.1 server with various client options.
3360 Testing against older TLS versions."""
3361 if support.verbose:
3362 sys.stdout.write("\n")
3363 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003364 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003365 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003366 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003367 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003368 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003369 client_options=ssl.OP_NO_TLSv1_1)
3370
Christian Heimesa170fa12017-09-15 20:27:30 +02003371 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003372 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3373 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003374
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003375 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003376 def test_protocol_tlsv1_2(self):
3377 """Connecting to a TLSv1.2 server with various client options.
3378 Testing against older TLS versions."""
3379 if support.verbose:
3380 sys.stdout.write("\n")
3381 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3382 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3383 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003384 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003385 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003386 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003387 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003388 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003389 client_options=ssl.OP_NO_TLSv1_2)
3390
Christian Heimesa170fa12017-09-15 20:27:30 +02003391 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003392 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3393 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3394 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3395 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3396
3397 def test_starttls(self):
3398 """Switching from clear text to encrypted and back again."""
3399 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3400
3401 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003402 starttls_server=True,
3403 chatty=True,
3404 connectionchatty=True)
3405 wrapped = False
3406 with server:
3407 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003408 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003409 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003410 if support.verbose:
3411 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003412 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003413 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003414 sys.stdout.write(
3415 " client: sending %r...\n" % indata)
3416 if wrapped:
3417 conn.write(indata)
3418 outdata = conn.read()
3419 else:
3420 s.send(indata)
3421 outdata = s.recv(1024)
3422 msg = outdata.strip().lower()
3423 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3424 # STARTTLS ok, switch to secure mode
3425 if support.verbose:
3426 sys.stdout.write(
3427 " client: read %r from server, starting TLS...\n"
3428 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003429 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003430 wrapped = True
3431 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3432 # ENDTLS ok, switch back to clear text
3433 if support.verbose:
3434 sys.stdout.write(
3435 " client: read %r from server, ending TLS...\n"
3436 % msg)
3437 s = conn.unwrap()
3438 wrapped = False
3439 else:
3440 if support.verbose:
3441 sys.stdout.write(
3442 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003443 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003444 sys.stdout.write(" client: closing connection.\n")
3445 if wrapped:
3446 conn.write(b"over\n")
3447 else:
3448 s.send(b"over\n")
3449 if wrapped:
3450 conn.close()
3451 else:
3452 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003453
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003454 def test_socketserver(self):
3455 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003456 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003457 # try to connect
3458 if support.verbose:
3459 sys.stdout.write('\n')
3460 with open(CERTFILE, 'rb') as f:
3461 d1 = f.read()
3462 d2 = ''
3463 # now fetch the same data from the HTTPS server
3464 url = 'https://localhost:%d/%s' % (
3465 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003466 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003467 f = urllib.request.urlopen(url, context=context)
3468 try:
3469 dlen = f.info().get("content-length")
3470 if dlen and (int(dlen) > 0):
3471 d2 = f.read(int(dlen))
3472 if support.verbose:
3473 sys.stdout.write(
3474 " client: read %d bytes from remote server '%s'\n"
3475 % (len(d2), server))
3476 finally:
3477 f.close()
3478 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003479
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003480 def test_asyncore_server(self):
3481 """Check the example asyncore integration."""
3482 if support.verbose:
3483 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003484
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003485 indata = b"FOO\n"
3486 server = AsyncoreEchoServer(CERTFILE)
3487 with server:
3488 s = test_wrap_socket(socket.socket())
3489 s.connect(('127.0.0.1', server.port))
3490 if support.verbose:
3491 sys.stdout.write(
3492 " client: sending %r...\n" % indata)
3493 s.write(indata)
3494 outdata = s.read()
3495 if support.verbose:
3496 sys.stdout.write(" client: read %r\n" % outdata)
3497 if outdata != indata.lower():
3498 self.fail(
3499 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3500 % (outdata[:20], len(outdata),
3501 indata[:20].lower(), len(indata)))
3502 s.write(b"over\n")
3503 if support.verbose:
3504 sys.stdout.write(" client: closing connection.\n")
3505 s.close()
3506 if support.verbose:
3507 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003508
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003509 def test_recv_send(self):
3510 """Test recv(), send() and friends."""
3511 if support.verbose:
3512 sys.stdout.write("\n")
3513
3514 server = ThreadedEchoServer(CERTFILE,
3515 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003516 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003517 cacerts=CERTFILE,
3518 chatty=True,
3519 connectionchatty=False)
3520 with server:
3521 s = test_wrap_socket(socket.socket(),
3522 server_side=False,
3523 certfile=CERTFILE,
3524 ca_certs=CERTFILE,
3525 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003526 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003527 s.connect((HOST, server.port))
3528 # helper methods for standardising recv* method signatures
3529 def _recv_into():
3530 b = bytearray(b"\0"*100)
3531 count = s.recv_into(b)
3532 return b[:count]
3533
3534 def _recvfrom_into():
3535 b = bytearray(b"\0"*100)
3536 count, addr = s.recvfrom_into(b)
3537 return b[:count]
3538
3539 # (name, method, expect success?, *args, return value func)
3540 send_methods = [
3541 ('send', s.send, True, [], len),
3542 ('sendto', s.sendto, False, ["some.address"], len),
3543 ('sendall', s.sendall, True, [], lambda x: None),
3544 ]
3545 # (name, method, whether to expect success, *args)
3546 recv_methods = [
3547 ('recv', s.recv, True, []),
3548 ('recvfrom', s.recvfrom, False, ["some.address"]),
3549 ('recv_into', _recv_into, True, []),
3550 ('recvfrom_into', _recvfrom_into, False, []),
3551 ]
3552 data_prefix = "PREFIX_"
3553
3554 for (meth_name, send_meth, expect_success, args,
3555 ret_val_meth) in send_methods:
3556 indata = (data_prefix + meth_name).encode('ascii')
3557 try:
3558 ret = send_meth(indata, *args)
3559 msg = "sending with {}".format(meth_name)
3560 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3561 outdata = s.read()
3562 if outdata != indata.lower():
3563 self.fail(
3564 "While sending with <<{name:s}>> bad data "
3565 "<<{outdata:r}>> ({nout:d}) received; "
3566 "expected <<{indata:r}>> ({nin:d})\n".format(
3567 name=meth_name, outdata=outdata[:20],
3568 nout=len(outdata),
3569 indata=indata[:20], nin=len(indata)
3570 )
3571 )
3572 except ValueError as e:
3573 if expect_success:
3574 self.fail(
3575 "Failed to send with method <<{name:s}>>; "
3576 "expected to succeed.\n".format(name=meth_name)
3577 )
3578 if not str(e).startswith(meth_name):
3579 self.fail(
3580 "Method <<{name:s}>> failed with unexpected "
3581 "exception message: {exp:s}\n".format(
3582 name=meth_name, exp=e
3583 )
3584 )
3585
3586 for meth_name, recv_meth, expect_success, args in recv_methods:
3587 indata = (data_prefix + meth_name).encode('ascii')
3588 try:
3589 s.send(indata)
3590 outdata = recv_meth(*args)
3591 if outdata != indata.lower():
3592 self.fail(
3593 "While receiving with <<{name:s}>> bad data "
3594 "<<{outdata:r}>> ({nout:d}) received; "
3595 "expected <<{indata:r}>> ({nin:d})\n".format(
3596 name=meth_name, outdata=outdata[:20],
3597 nout=len(outdata),
3598 indata=indata[:20], nin=len(indata)
3599 )
3600 )
3601 except ValueError as e:
3602 if expect_success:
3603 self.fail(
3604 "Failed to receive with method <<{name:s}>>; "
3605 "expected to succeed.\n".format(name=meth_name)
3606 )
3607 if not str(e).startswith(meth_name):
3608 self.fail(
3609 "Method <<{name:s}>> failed with unexpected "
3610 "exception message: {exp:s}\n".format(
3611 name=meth_name, exp=e
3612 )
3613 )
3614 # consume data
3615 s.read()
3616
3617 # read(-1, buffer) is supported, even though read(-1) is not
3618 data = b"data"
3619 s.send(data)
3620 buffer = bytearray(len(data))
3621 self.assertEqual(s.read(-1, buffer), len(data))
3622 self.assertEqual(buffer, data)
3623
Christian Heimes888bbdc2017-09-07 14:18:21 -07003624 # sendall accepts bytes-like objects
3625 if ctypes is not None:
3626 ubyte = ctypes.c_ubyte * len(data)
3627 byteslike = ubyte.from_buffer_copy(data)
3628 s.sendall(byteslike)
3629 self.assertEqual(s.read(), data)
3630
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003631 # Make sure sendmsg et al are disallowed to avoid
3632 # inadvertent disclosure of data and/or corruption
3633 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003634 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003635 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3636 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3637 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003638 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003639 s.write(b"over\n")
3640
3641 self.assertRaises(ValueError, s.recv, -1)
3642 self.assertRaises(ValueError, s.read, -1)
3643
3644 s.close()
3645
3646 def test_recv_zero(self):
3647 server = ThreadedEchoServer(CERTFILE)
3648 server.__enter__()
3649 self.addCleanup(server.__exit__, None, None)
3650 s = socket.create_connection((HOST, server.port))
3651 self.addCleanup(s.close)
3652 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3653 self.addCleanup(s.close)
3654
3655 # recv/read(0) should return no data
3656 s.send(b"data")
3657 self.assertEqual(s.recv(0), b"")
3658 self.assertEqual(s.read(0), b"")
3659 self.assertEqual(s.read(), b"data")
3660
3661 # Should not block if the other end sends no data
3662 s.setblocking(False)
3663 self.assertEqual(s.recv(0), b"")
3664 self.assertEqual(s.recv_into(bytearray()), 0)
3665
3666 def test_nonblocking_send(self):
3667 server = ThreadedEchoServer(CERTFILE,
3668 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003669 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003670 cacerts=CERTFILE,
3671 chatty=True,
3672 connectionchatty=False)
3673 with server:
3674 s = test_wrap_socket(socket.socket(),
3675 server_side=False,
3676 certfile=CERTFILE,
3677 ca_certs=CERTFILE,
3678 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003679 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003680 s.connect((HOST, server.port))
3681 s.setblocking(False)
3682
3683 # If we keep sending data, at some point the buffers
3684 # will be full and the call will block
3685 buf = bytearray(8192)
3686 def fill_buffer():
3687 while True:
3688 s.send(buf)
3689 self.assertRaises((ssl.SSLWantWriteError,
3690 ssl.SSLWantReadError), fill_buffer)
3691
3692 # Now read all the output and discard it
3693 s.setblocking(True)
3694 s.close()
3695
3696 def test_handshake_timeout(self):
3697 # Issue #5103: SSL handshake must respect the socket timeout
3698 server = socket.socket(socket.AF_INET)
3699 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003700 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003701 started = threading.Event()
3702 finish = False
3703
3704 def serve():
3705 server.listen()
3706 started.set()
3707 conns = []
3708 while not finish:
3709 r, w, e = select.select([server], [], [], 0.1)
3710 if server in r:
3711 # Let the socket hang around rather than having
3712 # it closed by garbage collection.
3713 conns.append(server.accept()[0])
3714 for sock in conns:
3715 sock.close()
3716
3717 t = threading.Thread(target=serve)
3718 t.start()
3719 started.wait()
3720
3721 try:
3722 try:
3723 c = socket.socket(socket.AF_INET)
3724 c.settimeout(0.2)
3725 c.connect((host, port))
3726 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003727 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003728 test_wrap_socket, c)
3729 finally:
3730 c.close()
3731 try:
3732 c = socket.socket(socket.AF_INET)
3733 c = test_wrap_socket(c)
3734 c.settimeout(0.2)
3735 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003736 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003737 c.connect, (host, port))
3738 finally:
3739 c.close()
3740 finally:
3741 finish = True
3742 t.join()
3743 server.close()
3744
3745 def test_server_accept(self):
3746 # Issue #16357: accept() on a SSLSocket created through
3747 # SSLContext.wrap_socket().
Christian Heimesa170fa12017-09-15 20:27:30 +02003748 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003749 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003750 context.load_verify_locations(SIGNING_CA)
3751 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003752 server = socket.socket(socket.AF_INET)
3753 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003754 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003755 server = context.wrap_socket(server, server_side=True)
3756 self.assertTrue(server.server_side)
3757
3758 evt = threading.Event()
3759 remote = None
3760 peer = None
3761 def serve():
3762 nonlocal remote, peer
3763 server.listen()
3764 # Block on the accept and wait on the connection to close.
3765 evt.set()
3766 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003767 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003768
3769 t = threading.Thread(target=serve)
3770 t.start()
3771 # Client wait until server setup and perform a connect.
3772 evt.wait()
3773 client = context.wrap_socket(socket.socket())
3774 client.connect((host, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003775 client.send(b'data')
3776 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003777 client_addr = client.getsockname()
3778 client.close()
3779 t.join()
3780 remote.close()
3781 server.close()
3782 # Sanity checks.
3783 self.assertIsInstance(remote, ssl.SSLSocket)
3784 self.assertEqual(peer, client_addr)
3785
3786 def test_getpeercert_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003787 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003788 with context.wrap_socket(socket.socket()) as sock:
3789 with self.assertRaises(OSError) as cm:
3790 sock.getpeercert()
3791 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3792
3793 def test_do_handshake_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003794 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003795 with context.wrap_socket(socket.socket()) as sock:
3796 with self.assertRaises(OSError) as cm:
3797 sock.do_handshake()
3798 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3799
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003800 def test_no_shared_ciphers(self):
3801 client_context, server_context, hostname = testing_context()
3802 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3803 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003804 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003805 client_context.set_ciphers("AES128")
3806 server_context.set_ciphers("AES256")
3807 with ThreadedEchoServer(context=server_context) as server:
3808 with client_context.wrap_socket(socket.socket(),
3809 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003810 with self.assertRaises(OSError):
3811 s.connect((HOST, server.port))
3812 self.assertIn("no shared cipher", server.conn_errors[0])
3813
3814 def test_version_basic(self):
3815 """
3816 Basic tests for SSLSocket.version().
3817 More tests are done in the test_protocol_*() methods.
3818 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003819 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3820 context.check_hostname = False
3821 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003822 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003823 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003824 chatty=False) as server:
3825 with context.wrap_socket(socket.socket()) as s:
3826 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003827 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003828 s.connect((HOST, server.port))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003829 if IS_OPENSSL_1_1_1 and has_tls_version('TLSv1_3'):
Christian Heimes05d9fe32018-02-27 08:55:39 +01003830 self.assertEqual(s.version(), 'TLSv1.3')
3831 elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
Christian Heimesa170fa12017-09-15 20:27:30 +02003832 self.assertEqual(s.version(), 'TLSv1.2')
3833 else: # 0.9.8 to 1.0.1
3834 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2'))
Christian Heimes141c5e82018-02-24 21:10:57 +01003835 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003836 self.assertIs(s.version(), None)
3837
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003838 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003839 def test_tls1_3(self):
3840 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
3841 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003842 context.options |= (
3843 ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2
3844 )
3845 with ThreadedEchoServer(context=context) as server:
3846 with context.wrap_socket(socket.socket()) as s:
3847 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003848 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003849 'TLS_AES_256_GCM_SHA384',
3850 'TLS_CHACHA20_POLY1305_SHA256',
3851 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003852 })
3853 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003854
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003855 @requires_minimum_version
3856 @requires_tls_version('TLSv1_2')
3857 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003858 client_context, server_context, hostname = testing_context()
3859 # client TLSv1.0 to 1.2
3860 client_context.minimum_version = ssl.TLSVersion.TLSv1
3861 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3862 # server only TLSv1.2
3863 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3864 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3865
3866 with ThreadedEchoServer(context=server_context) as server:
3867 with client_context.wrap_socket(socket.socket(),
3868 server_hostname=hostname) as s:
3869 s.connect((HOST, server.port))
3870 self.assertEqual(s.version(), 'TLSv1.2')
3871
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003872 @requires_minimum_version
3873 @requires_tls_version('TLSv1_1')
3874 def test_min_max_version_tlsv1_1(self):
3875 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003876 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003877 client_context.minimum_version = ssl.TLSVersion.TLSv1
3878 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003879 server_context.minimum_version = ssl.TLSVersion.TLSv1
3880 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003881 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003882
3883 with ThreadedEchoServer(context=server_context) as server:
3884 with client_context.wrap_socket(socket.socket(),
3885 server_hostname=hostname) as s:
3886 s.connect((HOST, server.port))
3887 self.assertEqual(s.version(), 'TLSv1.1')
3888
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003889 @requires_minimum_version
3890 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003891 @requires_tls_version('TLSv1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003892 def test_min_max_version_mismatch(self):
3893 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003894 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003895 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003896 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003897 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003898 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003899 seclevel_workaround(client_context, server_context)
3900
Christian Heimes698dde12018-02-27 11:54:43 +01003901 with ThreadedEchoServer(context=server_context) as server:
3902 with client_context.wrap_socket(socket.socket(),
3903 server_hostname=hostname) as s:
3904 with self.assertRaises(ssl.SSLError) as e:
3905 s.connect((HOST, server.port))
3906 self.assertIn("alert", str(e.exception))
3907
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003908 @requires_minimum_version
3909 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003910 def test_min_max_version_sslv3(self):
3911 client_context, server_context, hostname = testing_context()
3912 server_context.minimum_version = ssl.TLSVersion.SSLv3
3913 client_context.minimum_version = ssl.TLSVersion.SSLv3
3914 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003915 seclevel_workaround(client_context, server_context)
3916
Christian Heimes698dde12018-02-27 11:54:43 +01003917 with ThreadedEchoServer(context=server_context) as server:
3918 with client_context.wrap_socket(socket.socket(),
3919 server_hostname=hostname) as s:
3920 s.connect((HOST, server.port))
3921 self.assertEqual(s.version(), 'SSLv3')
3922
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003923 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3924 def test_default_ecdh_curve(self):
3925 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3926 # should be enabled by default on SSL contexts.
Christian Heimesa170fa12017-09-15 20:27:30 +02003927 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003928 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003929 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3930 # cipher name.
3931 context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003932 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3933 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3934 # our default cipher list should prefer ECDH-based ciphers
3935 # automatically.
3936 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
3937 context.set_ciphers("ECCdraft:ECDH")
3938 with ThreadedEchoServer(context=context) as server:
3939 with context.wrap_socket(socket.socket()) as s:
3940 s.connect((HOST, server.port))
3941 self.assertIn("ECDH", s.cipher()[0])
3942
3943 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3944 "'tls-unique' channel binding not available")
3945 def test_tls_unique_channel_binding(self):
3946 """Test tls-unique channel binding."""
3947 if support.verbose:
3948 sys.stdout.write("\n")
3949
Christian Heimes05d9fe32018-02-27 08:55:39 +01003950 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003951
3952 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003953 chatty=True,
3954 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003955
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003956 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003957 with client_context.wrap_socket(
3958 socket.socket(),
3959 server_hostname=hostname) as s:
3960 s.connect((HOST, server.port))
3961 # get the data
3962 cb_data = s.get_channel_binding("tls-unique")
3963 if support.verbose:
3964 sys.stdout.write(
3965 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003966
Christian Heimes05d9fe32018-02-27 08:55:39 +01003967 # check if it is sane
3968 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003969 if s.version() == 'TLSv1.3':
3970 self.assertEqual(len(cb_data), 48)
3971 else:
3972 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003973
Christian Heimes05d9fe32018-02-27 08:55:39 +01003974 # and compare with the peers version
3975 s.write(b"CB tls-unique\n")
3976 peer_data_repr = s.read().strip()
3977 self.assertEqual(peer_data_repr,
3978 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003979
3980 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003981 with client_context.wrap_socket(
3982 socket.socket(),
3983 server_hostname=hostname) as s:
3984 s.connect((HOST, server.port))
3985 new_cb_data = s.get_channel_binding("tls-unique")
3986 if support.verbose:
3987 sys.stdout.write(
3988 "got another channel binding data: {0!r}\n".format(
3989 new_cb_data)
3990 )
3991 # is it really unique
3992 self.assertNotEqual(cb_data, new_cb_data)
3993 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003994 if s.version() == 'TLSv1.3':
3995 self.assertEqual(len(cb_data), 48)
3996 else:
3997 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003998 s.write(b"CB tls-unique\n")
3999 peer_data_repr = s.read().strip()
4000 self.assertEqual(peer_data_repr,
4001 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004002
4003 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004004 client_context, server_context, hostname = testing_context()
4005 stats = server_params_test(client_context, server_context,
4006 chatty=True, connectionchatty=True,
4007 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004008 if support.verbose:
4009 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
4010 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
4011
4012 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
4013 "ssl.OP_NO_COMPRESSION needed for this test")
4014 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004015 client_context, server_context, hostname = testing_context()
4016 client_context.options |= ssl.OP_NO_COMPRESSION
4017 server_context.options |= ssl.OP_NO_COMPRESSION
4018 stats = server_params_test(client_context, server_context,
4019 chatty=True, connectionchatty=True,
4020 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004021 self.assertIs(stats['compression'], None)
4022
Paul Monsonf3550692019-06-19 13:09:54 -07004023 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004024 def test_dh_params(self):
4025 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004026 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004027 # test scenario needs TLS <= 1.2
4028 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004029 server_context.load_dh_params(DHFILE)
4030 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004031 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004032 stats = server_params_test(client_context, server_context,
4033 chatty=True, connectionchatty=True,
4034 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004035 cipher = stats["cipher"][0]
4036 parts = cipher.split("-")
4037 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4038 self.fail("Non-DH cipher: " + cipher[0])
4039
Christian Heimesb7b92252018-02-25 09:49:31 +01004040 @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004041 @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
Christian Heimesb7b92252018-02-25 09:49:31 +01004042 def test_ecdh_curve(self):
4043 # server secp384r1, client auto
4044 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004045
Christian Heimesb7b92252018-02-25 09:49:31 +01004046 server_context.set_ecdh_curve("secp384r1")
4047 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4048 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4049 stats = server_params_test(client_context, server_context,
4050 chatty=True, connectionchatty=True,
4051 sni_name=hostname)
4052
4053 # server auto, client secp384r1
4054 client_context, server_context, hostname = testing_context()
4055 client_context.set_ecdh_curve("secp384r1")
4056 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4057 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4058 stats = server_params_test(client_context, server_context,
4059 chatty=True, connectionchatty=True,
4060 sni_name=hostname)
4061
4062 # server / client curve mismatch
4063 client_context, server_context, hostname = testing_context()
4064 client_context.set_ecdh_curve("prime256v1")
4065 server_context.set_ecdh_curve("secp384r1")
4066 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4067 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4068 try:
4069 stats = server_params_test(client_context, server_context,
4070 chatty=True, connectionchatty=True,
4071 sni_name=hostname)
4072 except ssl.SSLError:
4073 pass
4074 else:
4075 # OpenSSL 1.0.2 does not fail although it should.
Christian Heimes05d9fe32018-02-27 08:55:39 +01004076 if IS_OPENSSL_1_1_0:
Christian Heimesb7b92252018-02-25 09:49:31 +01004077 self.fail("mismatch curve did not fail")
4078
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004079 def test_selected_alpn_protocol(self):
4080 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004081 client_context, server_context, hostname = testing_context()
4082 stats = server_params_test(client_context, server_context,
4083 chatty=True, connectionchatty=True,
4084 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004085 self.assertIs(stats['client_alpn_protocol'], None)
4086
4087 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
4088 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4089 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004090 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004091 server_context.set_alpn_protocols(['foo', 'bar'])
4092 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004093 chatty=True, connectionchatty=True,
4094 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004095 self.assertIs(stats['client_alpn_protocol'], None)
4096
4097 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
4098 def test_alpn_protocols(self):
4099 server_protocols = ['foo', 'bar', 'milkshake']
4100 protocol_tests = [
4101 (['foo', 'bar'], 'foo'),
4102 (['bar', 'foo'], 'foo'),
4103 (['milkshake'], 'milkshake'),
4104 (['http/3.0', 'http/4.0'], None)
4105 ]
4106 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004107 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004108 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004109 client_context.set_alpn_protocols(client_protocols)
4110
4111 try:
4112 stats = server_params_test(client_context,
4113 server_context,
4114 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004115 connectionchatty=True,
4116 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004117 except ssl.SSLError as e:
4118 stats = e
4119
Christian Heimes05d9fe32018-02-27 08:55:39 +01004120 if (expected is None and IS_OPENSSL_1_1_0
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004121 and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)):
4122 # OpenSSL 1.1.0 to 1.1.0e raises handshake error
4123 self.assertIsInstance(stats, ssl.SSLError)
4124 else:
4125 msg = "failed trying %s (s) and %s (c).\n" \
4126 "was expecting %s, but got %%s from the %%s" \
4127 % (str(server_protocols), str(client_protocols),
4128 str(expected))
4129 client_result = stats['client_alpn_protocol']
4130 self.assertEqual(client_result, expected,
4131 msg % (client_result, "client"))
4132 server_result = stats['server_alpn_protocols'][-1] \
4133 if len(stats['server_alpn_protocols']) else 'nothing'
4134 self.assertEqual(server_result, expected,
4135 msg % (server_result, "server"))
4136
4137 def test_selected_npn_protocol(self):
4138 # selected_npn_protocol() is None unless NPN is used
Christian Heimesa170fa12017-09-15 20:27:30 +02004139 client_context, server_context, hostname = testing_context()
4140 stats = server_params_test(client_context, server_context,
4141 chatty=True, connectionchatty=True,
4142 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004143 self.assertIs(stats['client_npn_protocol'], None)
4144
4145 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
4146 def test_npn_protocols(self):
4147 server_protocols = ['http/1.1', 'spdy/2']
4148 protocol_tests = [
4149 (['http/1.1', 'spdy/2'], 'http/1.1'),
4150 (['spdy/2', 'http/1.1'], 'http/1.1'),
4151 (['spdy/2', 'test'], 'spdy/2'),
4152 (['abc', 'def'], 'abc')
4153 ]
4154 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004155 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004156 server_context.set_npn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004157 client_context.set_npn_protocols(client_protocols)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004158 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004159 chatty=True, connectionchatty=True,
4160 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004161 msg = "failed trying %s (s) and %s (c).\n" \
4162 "was expecting %s, but got %%s from the %%s" \
4163 % (str(server_protocols), str(client_protocols),
4164 str(expected))
4165 client_result = stats['client_npn_protocol']
4166 self.assertEqual(client_result, expected, msg % (client_result, "client"))
4167 server_result = stats['server_npn_protocols'][-1] \
4168 if len(stats['server_npn_protocols']) else 'nothing'
4169 self.assertEqual(server_result, expected, msg % (server_result, "server"))
4170
4171 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004172 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004173 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004174 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004175 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004176 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004177 client_context.load_verify_locations(SIGNING_CA)
4178 return server_context, other_context, client_context
4179
4180 def check_common_name(self, stats, name):
4181 cert = stats['peercert']
4182 self.assertIn((('commonName', name),), cert['subject'])
4183
4184 @needs_sni
4185 def test_sni_callback(self):
4186 calls = []
4187 server_context, other_context, client_context = self.sni_contexts()
4188
Christian Heimesa170fa12017-09-15 20:27:30 +02004189 client_context.check_hostname = False
4190
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004191 def servername_cb(ssl_sock, server_name, initial_context):
4192 calls.append((server_name, initial_context))
4193 if server_name is not None:
4194 ssl_sock.context = other_context
4195 server_context.set_servername_callback(servername_cb)
4196
4197 stats = server_params_test(client_context, server_context,
4198 chatty=True,
4199 sni_name='supermessage')
4200 # The hostname was fetched properly, and the certificate was
4201 # changed for the connection.
4202 self.assertEqual(calls, [("supermessage", server_context)])
4203 # CERTFILE4 was selected
4204 self.check_common_name(stats, 'fakehostname')
4205
4206 calls = []
4207 # The callback is called with server_name=None
4208 stats = server_params_test(client_context, server_context,
4209 chatty=True,
4210 sni_name=None)
4211 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004212 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004213
4214 # Check disabling the callback
4215 calls = []
4216 server_context.set_servername_callback(None)
4217
4218 stats = server_params_test(client_context, server_context,
4219 chatty=True,
4220 sni_name='notfunny')
4221 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004222 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004223 self.assertEqual(calls, [])
4224
4225 @needs_sni
4226 def test_sni_callback_alert(self):
4227 # Returning a TLS alert is reflected to the connecting client
4228 server_context, other_context, client_context = self.sni_contexts()
4229
4230 def cb_returning_alert(ssl_sock, server_name, initial_context):
4231 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4232 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004233 with self.assertRaises(ssl.SSLError) as cm:
4234 stats = server_params_test(client_context, server_context,
4235 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004236 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004237 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004238
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004239 @needs_sni
4240 def test_sni_callback_raising(self):
4241 # Raising fails the connection with a TLS handshake failure alert.
4242 server_context, other_context, client_context = self.sni_contexts()
4243
4244 def cb_raising(ssl_sock, server_name, initial_context):
4245 1/0
4246 server_context.set_servername_callback(cb_raising)
4247
Victor Stinner00253502019-06-03 03:51:43 +02004248 with support.catch_unraisable_exception() as catch:
4249 with self.assertRaises(ssl.SSLError) as cm:
4250 stats = server_params_test(client_context, server_context,
4251 chatty=False,
4252 sni_name='supermessage')
4253
4254 self.assertEqual(cm.exception.reason,
4255 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4256 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004257
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004258 @needs_sni
4259 def test_sni_callback_wrong_return_type(self):
4260 # Returning the wrong return type terminates the TLS connection
4261 # with an internal error alert.
4262 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004263
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004264 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4265 return "foo"
4266 server_context.set_servername_callback(cb_wrong_return_type)
4267
Victor Stinner00253502019-06-03 03:51:43 +02004268 with support.catch_unraisable_exception() as catch:
4269 with self.assertRaises(ssl.SSLError) as cm:
4270 stats = server_params_test(client_context, server_context,
4271 chatty=False,
4272 sni_name='supermessage')
4273
4274
4275 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4276 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004277
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004278 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004279 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004280 client_context.set_ciphers("AES128:AES256")
4281 server_context.set_ciphers("AES256")
4282 expected_algs = [
4283 "AES256", "AES-256",
4284 # TLS 1.3 ciphers are always enabled
4285 "TLS_CHACHA20", "TLS_AES",
4286 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004287
Christian Heimesa170fa12017-09-15 20:27:30 +02004288 stats = server_params_test(client_context, server_context,
4289 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004290 ciphers = stats['server_shared_ciphers'][0]
4291 self.assertGreater(len(ciphers), 0)
4292 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004293 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004294 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004295
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004296 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004297 client_context, server_context, hostname = testing_context()
4298 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004299
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004300 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004301 s = client_context.wrap_socket(socket.socket(),
4302 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004303 s.connect((HOST, server.port))
4304 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004305
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004306 self.assertRaises(ValueError, s.read, 1024)
4307 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004308
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004309 def test_sendfile(self):
4310 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004311 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004312 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004313 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesa170fa12017-09-15 20:27:30 +02004314 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004315 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01004316 context.load_verify_locations(SIGNING_CA)
4317 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004318 server = ThreadedEchoServer(context=context, chatty=False)
4319 with server:
4320 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004321 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004322 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004323 s.sendfile(file)
4324 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004325
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004326 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004327 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004328 # TODO: sessions aren't compatible with TLSv1.3 yet
4329 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004330
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004331 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004332 stats = server_params_test(client_context, server_context,
4333 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004334 session = stats['session']
4335 self.assertTrue(session.id)
4336 self.assertGreater(session.time, 0)
4337 self.assertGreater(session.timeout, 0)
4338 self.assertTrue(session.has_ticket)
4339 if ssl.OPENSSL_VERSION_INFO > (1, 0, 1):
4340 self.assertGreater(session.ticket_lifetime_hint, 0)
4341 self.assertFalse(stats['session_reused'])
4342 sess_stat = server_context.session_stats()
4343 self.assertEqual(sess_stat['accept'], 1)
4344 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004345
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004346 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004347 stats = server_params_test(client_context, server_context,
4348 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004349 sess_stat = server_context.session_stats()
4350 self.assertEqual(sess_stat['accept'], 2)
4351 self.assertEqual(sess_stat['hits'], 1)
4352 self.assertTrue(stats['session_reused'])
4353 session2 = stats['session']
4354 self.assertEqual(session2.id, session.id)
4355 self.assertEqual(session2, session)
4356 self.assertIsNot(session2, session)
4357 self.assertGreaterEqual(session2.time, session.time)
4358 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004359
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004360 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004361 stats = server_params_test(client_context, server_context,
4362 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004363 self.assertFalse(stats['session_reused'])
4364 session3 = stats['session']
4365 self.assertNotEqual(session3.id, session.id)
4366 self.assertNotEqual(session3, session)
4367 sess_stat = server_context.session_stats()
4368 self.assertEqual(sess_stat['accept'], 3)
4369 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004370
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004371 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004372 stats = server_params_test(client_context, server_context,
4373 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004374 self.assertTrue(stats['session_reused'])
4375 session4 = stats['session']
4376 self.assertEqual(session4.id, session.id)
4377 self.assertEqual(session4, session)
4378 self.assertGreaterEqual(session4.time, session.time)
4379 self.assertGreaterEqual(session4.timeout, session.timeout)
4380 sess_stat = server_context.session_stats()
4381 self.assertEqual(sess_stat['accept'], 4)
4382 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004383
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004384 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004385 client_context, server_context, hostname = testing_context()
4386 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004387
Christian Heimes05d9fe32018-02-27 08:55:39 +01004388 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004389 client_context.options |= ssl.OP_NO_TLSv1_3
4390 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004391
Christian Heimesa170fa12017-09-15 20:27:30 +02004392 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004393 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004394 with client_context.wrap_socket(socket.socket(),
4395 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004396 # session is None before handshake
4397 self.assertEqual(s.session, None)
4398 self.assertEqual(s.session_reused, None)
4399 s.connect((HOST, server.port))
4400 session = s.session
4401 self.assertTrue(session)
4402 with self.assertRaises(TypeError) as e:
4403 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004404 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004405
Christian Heimesa170fa12017-09-15 20:27:30 +02004406 with client_context.wrap_socket(socket.socket(),
4407 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004408 s.connect((HOST, server.port))
4409 # cannot set session after handshake
4410 with self.assertRaises(ValueError) as e:
4411 s.session = session
4412 self.assertEqual(str(e.exception),
4413 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004414
Christian Heimesa170fa12017-09-15 20:27:30 +02004415 with client_context.wrap_socket(socket.socket(),
4416 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004417 # can set session before handshake and before the
4418 # connection was established
4419 s.session = session
4420 s.connect((HOST, server.port))
4421 self.assertEqual(s.session.id, session.id)
4422 self.assertEqual(s.session, session)
4423 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004424
Christian Heimesa170fa12017-09-15 20:27:30 +02004425 with client_context2.wrap_socket(socket.socket(),
4426 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004427 # cannot re-use session with a different SSLContext
4428 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004429 s.session = session
4430 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004431 self.assertEqual(str(e.exception),
4432 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004433
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004434
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004435@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004436class TestPostHandshakeAuth(unittest.TestCase):
4437 def test_pha_setter(self):
4438 protocols = [
4439 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
4440 ]
4441 for protocol in protocols:
4442 ctx = ssl.SSLContext(protocol)
4443 self.assertEqual(ctx.post_handshake_auth, False)
4444
4445 ctx.post_handshake_auth = True
4446 self.assertEqual(ctx.post_handshake_auth, True)
4447
4448 ctx.verify_mode = ssl.CERT_REQUIRED
4449 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4450 self.assertEqual(ctx.post_handshake_auth, True)
4451
4452 ctx.post_handshake_auth = False
4453 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4454 self.assertEqual(ctx.post_handshake_auth, False)
4455
4456 ctx.verify_mode = ssl.CERT_OPTIONAL
4457 ctx.post_handshake_auth = True
4458 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4459 self.assertEqual(ctx.post_handshake_auth, True)
4460
4461 def test_pha_required(self):
4462 client_context, server_context, hostname = testing_context()
4463 server_context.post_handshake_auth = True
4464 server_context.verify_mode = ssl.CERT_REQUIRED
4465 client_context.post_handshake_auth = True
4466 client_context.load_cert_chain(SIGNED_CERTFILE)
4467
4468 server = ThreadedEchoServer(context=server_context, chatty=False)
4469 with server:
4470 with client_context.wrap_socket(socket.socket(),
4471 server_hostname=hostname) as s:
4472 s.connect((HOST, server.port))
4473 s.write(b'HASCERT')
4474 self.assertEqual(s.recv(1024), b'FALSE\n')
4475 s.write(b'PHA')
4476 self.assertEqual(s.recv(1024), b'OK\n')
4477 s.write(b'HASCERT')
4478 self.assertEqual(s.recv(1024), b'TRUE\n')
4479 # PHA method just returns true when cert is already available
4480 s.write(b'PHA')
4481 self.assertEqual(s.recv(1024), b'OK\n')
4482 s.write(b'GETCERT')
4483 cert_text = s.recv(4096).decode('us-ascii')
4484 self.assertIn('Python Software Foundation CA', cert_text)
4485
4486 def test_pha_required_nocert(self):
4487 client_context, server_context, hostname = testing_context()
4488 server_context.post_handshake_auth = True
4489 server_context.verify_mode = ssl.CERT_REQUIRED
4490 client_context.post_handshake_auth = True
4491
Victor Stinner73ea5462019-07-09 14:33:49 +02004492 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4493 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004494 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004495 server = ThreadedEchoServer(context=server_context, chatty=False)
4496 with server:
4497 with client_context.wrap_socket(socket.socket(),
4498 server_hostname=hostname) as s:
4499 s.connect((HOST, server.port))
4500 s.write(b'PHA')
4501 # receive CertificateRequest
4502 self.assertEqual(s.recv(1024), b'OK\n')
4503 # send empty Certificate + Finish
4504 s.write(b'HASCERT')
4505 # receive alert
4506 with self.assertRaisesRegex(
4507 ssl.SSLError,
4508 'tlsv13 alert certificate required'):
4509 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004510
4511 def test_pha_optional(self):
4512 if support.verbose:
4513 sys.stdout.write("\n")
4514
4515 client_context, server_context, hostname = testing_context()
4516 server_context.post_handshake_auth = True
4517 server_context.verify_mode = ssl.CERT_REQUIRED
4518 client_context.post_handshake_auth = True
4519 client_context.load_cert_chain(SIGNED_CERTFILE)
4520
4521 # check CERT_OPTIONAL
4522 server_context.verify_mode = ssl.CERT_OPTIONAL
4523 server = ThreadedEchoServer(context=server_context, chatty=False)
4524 with server:
4525 with client_context.wrap_socket(socket.socket(),
4526 server_hostname=hostname) as s:
4527 s.connect((HOST, server.port))
4528 s.write(b'HASCERT')
4529 self.assertEqual(s.recv(1024), b'FALSE\n')
4530 s.write(b'PHA')
4531 self.assertEqual(s.recv(1024), b'OK\n')
4532 s.write(b'HASCERT')
4533 self.assertEqual(s.recv(1024), b'TRUE\n')
4534
4535 def test_pha_optional_nocert(self):
4536 if support.verbose:
4537 sys.stdout.write("\n")
4538
4539 client_context, server_context, hostname = testing_context()
4540 server_context.post_handshake_auth = True
4541 server_context.verify_mode = ssl.CERT_OPTIONAL
4542 client_context.post_handshake_auth = True
4543
4544 server = ThreadedEchoServer(context=server_context, chatty=False)
4545 with server:
4546 with client_context.wrap_socket(socket.socket(),
4547 server_hostname=hostname) as s:
4548 s.connect((HOST, server.port))
4549 s.write(b'HASCERT')
4550 self.assertEqual(s.recv(1024), b'FALSE\n')
4551 s.write(b'PHA')
4552 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004553 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004554 s.write(b'HASCERT')
4555 self.assertEqual(s.recv(1024), b'FALSE\n')
4556
4557 def test_pha_no_pha_client(self):
4558 client_context, server_context, hostname = testing_context()
4559 server_context.post_handshake_auth = True
4560 server_context.verify_mode = ssl.CERT_REQUIRED
4561 client_context.load_cert_chain(SIGNED_CERTFILE)
4562
4563 server = ThreadedEchoServer(context=server_context, chatty=False)
4564 with server:
4565 with client_context.wrap_socket(socket.socket(),
4566 server_hostname=hostname) as s:
4567 s.connect((HOST, server.port))
4568 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4569 s.verify_client_post_handshake()
4570 s.write(b'PHA')
4571 self.assertIn(b'extension not received', s.recv(1024))
4572
4573 def test_pha_no_pha_server(self):
4574 # server doesn't have PHA enabled, cert is requested in handshake
4575 client_context, server_context, hostname = testing_context()
4576 server_context.verify_mode = ssl.CERT_REQUIRED
4577 client_context.post_handshake_auth = True
4578 client_context.load_cert_chain(SIGNED_CERTFILE)
4579
4580 server = ThreadedEchoServer(context=server_context, chatty=False)
4581 with server:
4582 with client_context.wrap_socket(socket.socket(),
4583 server_hostname=hostname) as s:
4584 s.connect((HOST, server.port))
4585 s.write(b'HASCERT')
4586 self.assertEqual(s.recv(1024), b'TRUE\n')
4587 # PHA doesn't fail if there is already a cert
4588 s.write(b'PHA')
4589 self.assertEqual(s.recv(1024), b'OK\n')
4590 s.write(b'HASCERT')
4591 self.assertEqual(s.recv(1024), b'TRUE\n')
4592
4593 def test_pha_not_tls13(self):
4594 # TLS 1.2
4595 client_context, server_context, hostname = testing_context()
4596 server_context.verify_mode = ssl.CERT_REQUIRED
4597 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4598 client_context.post_handshake_auth = True
4599 client_context.load_cert_chain(SIGNED_CERTFILE)
4600
4601 server = ThreadedEchoServer(context=server_context, chatty=False)
4602 with server:
4603 with client_context.wrap_socket(socket.socket(),
4604 server_hostname=hostname) as s:
4605 s.connect((HOST, server.port))
4606 # PHA fails for TLS != 1.3
4607 s.write(b'PHA')
4608 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4609
Christian Heimesf0f59302019-07-01 08:29:17 +02004610 def test_bpo37428_pha_cert_none(self):
4611 # verify that post_handshake_auth does not implicitly enable cert
4612 # validation.
4613 hostname = SIGNED_CERTFILE_HOSTNAME
4614 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4615 client_context.post_handshake_auth = True
4616 client_context.load_cert_chain(SIGNED_CERTFILE)
4617 # no cert validation and CA on client side
4618 client_context.check_hostname = False
4619 client_context.verify_mode = ssl.CERT_NONE
4620
4621 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4622 server_context.load_cert_chain(SIGNED_CERTFILE)
4623 server_context.load_verify_locations(SIGNING_CA)
4624 server_context.post_handshake_auth = True
4625 server_context.verify_mode = ssl.CERT_REQUIRED
4626
4627 server = ThreadedEchoServer(context=server_context, chatty=False)
4628 with server:
4629 with client_context.wrap_socket(socket.socket(),
4630 server_hostname=hostname) as s:
4631 s.connect((HOST, server.port))
4632 s.write(b'HASCERT')
4633 self.assertEqual(s.recv(1024), b'FALSE\n')
4634 s.write(b'PHA')
4635 self.assertEqual(s.recv(1024), b'OK\n')
4636 s.write(b'HASCERT')
4637 self.assertEqual(s.recv(1024), b'TRUE\n')
4638 # server cert has not been validated
4639 self.assertEqual(s.getpeercert(), {})
4640
Christian Heimes9fb051f2018-09-23 08:32:31 +02004641
Christian Heimesc7f70692019-05-31 11:44:05 +02004642HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4643requires_keylog = unittest.skipUnless(
4644 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4645
4646class TestSSLDebug(unittest.TestCase):
4647
Hai Shia7f5d932020-08-04 00:41:24 +08004648 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004649 with open(fname) as f:
4650 return len(list(f))
4651
4652 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004653 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004654 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004655 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004656 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4657 self.assertEqual(ctx.keylog_filename, None)
4658
Hai Shia7f5d932020-08-04 00:41:24 +08004659 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4660 ctx.keylog_filename = os_helper.TESTFN
4661 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4662 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004663 self.assertEqual(self.keylog_lines(), 1)
4664
4665 ctx.keylog_filename = None
4666 self.assertEqual(ctx.keylog_filename, None)
4667
4668 with self.assertRaises((IsADirectoryError, PermissionError)):
4669 # Windows raises PermissionError
4670 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004671 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004672
4673 with self.assertRaises(TypeError):
4674 ctx.keylog_filename = 1
4675
4676 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004677 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004678 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004679 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004680 client_context, server_context, hostname = testing_context()
4681
Hai Shia7f5d932020-08-04 00:41:24 +08004682 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004683 server = ThreadedEchoServer(context=server_context, chatty=False)
4684 with server:
4685 with client_context.wrap_socket(socket.socket(),
4686 server_hostname=hostname) as s:
4687 s.connect((HOST, server.port))
4688 # header, 5 lines for TLS 1.3
4689 self.assertEqual(self.keylog_lines(), 6)
4690
4691 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004692 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004693 server = ThreadedEchoServer(context=server_context, chatty=False)
4694 with server:
4695 with client_context.wrap_socket(socket.socket(),
4696 server_hostname=hostname) as s:
4697 s.connect((HOST, server.port))
4698 self.assertGreaterEqual(self.keylog_lines(), 11)
4699
Hai Shia7f5d932020-08-04 00:41:24 +08004700 client_context.keylog_filename = os_helper.TESTFN
4701 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004702 server = ThreadedEchoServer(context=server_context, chatty=False)
4703 with server:
4704 with client_context.wrap_socket(socket.socket(),
4705 server_hostname=hostname) as s:
4706 s.connect((HOST, server.port))
4707 self.assertGreaterEqual(self.keylog_lines(), 21)
4708
4709 client_context.keylog_filename = None
4710 server_context.keylog_filename = None
4711
4712 @requires_keylog
4713 @unittest.skipIf(sys.flags.ignore_environment,
4714 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004715 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004716 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004717 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004718 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004719 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4720 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004721
4722 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4723 self.assertEqual(ctx.keylog_filename, None)
4724
4725 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004726 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004727
4728 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004729 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004730
4731 def test_msg_callback(self):
4732 client_context, server_context, hostname = testing_context()
4733
4734 def msg_cb(conn, direction, version, content_type, msg_type, data):
4735 pass
4736
4737 self.assertIs(client_context._msg_callback, None)
4738 client_context._msg_callback = msg_cb
4739 self.assertIs(client_context._msg_callback, msg_cb)
4740 with self.assertRaises(TypeError):
4741 client_context._msg_callback = object()
4742
4743 def test_msg_callback_tls12(self):
4744 client_context, server_context, hostname = testing_context()
4745 client_context.options |= ssl.OP_NO_TLSv1_3
4746
4747 msg = []
4748
4749 def msg_cb(conn, direction, version, content_type, msg_type, data):
4750 self.assertIsInstance(conn, ssl.SSLSocket)
4751 self.assertIsInstance(data, bytes)
4752 self.assertIn(direction, {'read', 'write'})
4753 msg.append((direction, version, content_type, msg_type))
4754
4755 client_context._msg_callback = msg_cb
4756
4757 server = ThreadedEchoServer(context=server_context, chatty=False)
4758 with server:
4759 with client_context.wrap_socket(socket.socket(),
4760 server_hostname=hostname) as s:
4761 s.connect((HOST, server.port))
4762
Christian Heimese35d1ba2019-06-03 20:40:15 +02004763 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004764 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4765 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004766 msg
4767 )
4768 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004769 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4770 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004771 msg
4772 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004773
Christian Heimes77cde502021-03-21 16:13:09 +01004774 def test_msg_callback_deadlock_bpo43577(self):
4775 client_context, server_context, hostname = testing_context()
4776 server_context2 = testing_context()[1]
4777
4778 def msg_cb(conn, direction, version, content_type, msg_type, data):
4779 pass
4780
4781 def sni_cb(sock, servername, ctx):
4782 sock.context = server_context2
4783
4784 server_context._msg_callback = msg_cb
4785 server_context.sni_callback = sni_cb
4786
4787 server = ThreadedEchoServer(context=server_context, chatty=False)
4788 with server:
4789 with client_context.wrap_socket(socket.socket(),
4790 server_hostname=hostname) as s:
4791 s.connect((HOST, server.port))
4792 with client_context.wrap_socket(socket.socket(),
4793 server_hostname=hostname) as s:
4794 s.connect((HOST, server.port))
4795
Christian Heimesc7f70692019-05-31 11:44:05 +02004796
Thomas Woutersed03b412007-08-28 21:37:11 +00004797def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004798 if support.verbose:
4799 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004800 'Mac': platform.mac_ver,
4801 'Windows': platform.win32_ver,
4802 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004803 for name, func in plats.items():
4804 plat = func()
4805 if plat and plat[0]:
4806 plat = '%s %r' % (name, plat)
4807 break
4808 else:
4809 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004810 print("test_ssl: testing with %r %r" %
4811 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4812 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004813 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004814 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4815 try:
4816 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4817 except AttributeError:
4818 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004819
Antoine Pitrou152efa22010-05-16 18:19:27 +00004820 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004821 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004822 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004823 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004824 BADCERT, BADKEY, EMPTYCERT]:
4825 if not os.path.exists(filename):
4826 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004827
Martin Panter3840b2a2016-03-27 01:53:46 +00004828 tests = [
4829 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004830 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004831 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004832 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004833
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004834 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004835 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004836
Hai Shie80697d2020-05-28 06:10:27 +08004837 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004838 try:
4839 support.run_unittest(*tests)
4840 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004841 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004842
4843if __name__ == "__main__":
4844 test_main()