blob: e2d0def9857675e342ef4828025584602a3b2bc0 [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
Ethan Furmana02cb472021-04-21 10:20:44 -070015import datetime
16import enum
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000017import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000018import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000019import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000020import pprint
Antoine Pitrou803e6d62010-10-13 10:36:15 +000021import urllib.request
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020022import threading
Thomas Woutersed03b412007-08-28 21:37:11 +000023import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000024import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000025import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000026import platform
Christian Heimes892d66e2018-01-29 14:10:18 +010027import sysconfig
Christian Heimesdf6ac7e2019-09-26 17:02:59 +020028import functools
Christian Heimes888bbdc2017-09-07 14:18:21 -070029try:
30 import ctypes
31except ImportError:
32 ctypes = None
Thomas Woutersed03b412007-08-28 21:37:11 +000033
Hai Shia7f5d932020-08-04 00:41:24 +080034ssl = import_helper.import_module("ssl")
Antoine Pitrou05d936d2010-10-13 11:38:36 +000035
Ethan Furmana02cb472021-04-21 10:20:44 -070036from ssl import TLSVersion, _TLSContentType, _TLSMessageType, _TLSAlertType
Martin Panter3840b2a2016-03-27 01:53:46 +000037
Paul Monsonf3550692019-06-19 13:09:54 -070038Py_DEBUG = hasattr(sys, 'gettotalrefcount')
39Py_DEBUG_WIN32 = Py_DEBUG and sys.platform == 'win32'
40
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010041PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Serhiy Storchaka16994912020-04-25 10:06:29 +030042HOST = socket_helper.HOST
Christian Heimesd37b74f2021-04-19 08:31:29 +020043IS_OPENSSL_3_0_0 = ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
Christian Heimes892d66e2018-01-29 14:10:18 +010044PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
Antoine Pitrou152efa22010-05-16 18:19:27 +000045
Victor Stinner3ef63442019-02-19 18:06:03 +010046PROTOCOL_TO_TLS_VERSION = {}
47for proto, ver in (
48 ("PROTOCOL_SSLv23", "SSLv3"),
49 ("PROTOCOL_TLSv1", "TLSv1"),
50 ("PROTOCOL_TLSv1_1", "TLSv1_1"),
51):
52 try:
53 proto = getattr(ssl, proto)
54 ver = getattr(ssl.TLSVersion, ver)
55 except AttributeError:
56 continue
57 PROTOCOL_TO_TLS_VERSION[proto] = ver
58
Christian Heimesefff7062013-11-21 03:35:02 +010059def data_file(*name):
60 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000061
Antoine Pitrou81564092010-10-08 23:06:24 +000062# The custom key and certificate files used in test_ssl are generated
63# using Lib/test/make_ssl_certs.py.
64# Other certificates are simply fetched from the Internet servers they
65# are meant to authenticate.
66
Antoine Pitrou152efa22010-05-16 18:19:27 +000067CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000068BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000069ONLYCERT = data_file("ssl_cert.pem")
70ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000071BYTES_ONLYCERT = os.fsencode(ONLYCERT)
72BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020073CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
74ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
75KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000076CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000077BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010078CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
79CAFILE_CACERT = data_file("capath", "5ed36f99.0")
80
Christian Heimesbd5c7d22018-01-20 15:16:30 +010081CERTFILE_INFO = {
82 'issuer': ((('countryName', 'XY'),),
83 (('localityName', 'Castle Anthrax'),),
84 (('organizationName', 'Python Software Foundation'),),
85 (('commonName', 'localhost'),)),
Christian Heimese6dac002018-08-30 07:25:49 +020086 'notAfter': 'Aug 26 14:23:15 2028 GMT',
87 'notBefore': 'Aug 29 14:23:15 2018 GMT',
88 'serialNumber': '98A7CF88C74A32ED',
Christian Heimesbd5c7d22018-01-20 15:16:30 +010089 'subject': ((('countryName', 'XY'),),
90 (('localityName', 'Castle Anthrax'),),
91 (('organizationName', 'Python Software Foundation'),),
92 (('commonName', 'localhost'),)),
93 'subjectAltName': (('DNS', 'localhost'),),
94 'version': 3
95}
Antoine Pitrou152efa22010-05-16 18:19:27 +000096
Christian Heimes22587792013-11-21 23:56:13 +010097# empty CRL
98CRLFILE = data_file("revocation.crl")
99
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100100# Two keys and certs signed by the same CA (for SNI tests)
101SIGNED_CERTFILE = data_file("keycert3.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200102SIGNED_CERTFILE_HOSTNAME = 'localhost'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100103
104SIGNED_CERTFILE_INFO = {
105 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
106 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
107 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
108 'issuer': ((('countryName', 'XY'),),
109 (('organizationName', 'Python Software Foundation CA'),),
110 (('commonName', 'our-ca-server'),)),
Christian Heimesb467d9a2021-04-17 10:07:19 +0200111 'notAfter': 'Oct 28 14:23:16 2037 GMT',
Christian Heimese6dac002018-08-30 07:25:49 +0200112 'notBefore': 'Aug 29 14:23:16 2018 GMT',
113 'serialNumber': 'CB2D80995A69525C',
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100114 'subject': ((('countryName', 'XY'),),
115 (('localityName', 'Castle Anthrax'),),
116 (('organizationName', 'Python Software Foundation'),),
117 (('commonName', 'localhost'),)),
118 'subjectAltName': (('DNS', 'localhost'),),
119 'version': 3
120}
121
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100122SIGNED_CERTFILE2 = data_file("keycert4.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200123SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100124SIGNED_CERTFILE_ECC = data_file("keycertecc.pem")
125SIGNED_CERTFILE_ECC_HOSTNAME = 'localhost-ecc'
126
Martin Panter3840b2a2016-03-27 01:53:46 +0000127# Same certificate as pycacert.pem, but without extra text in file
128SIGNING_CA = data_file("capath", "ceff1710.0")
Christian Heimes1c03abd2016-09-06 23:25:35 +0200129# cert with all kinds of subject alt names
130ALLSANFILE = data_file("allsans.pem")
Christian Heimes66e57422018-01-29 14:25:13 +0100131IDNSANSFILE = data_file("idnsans.pem")
Christian Heimesb467d9a2021-04-17 10:07:19 +0200132NOSANFILE = data_file("nosan.pem")
133NOSAN_HOSTNAME = 'localhost'
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100134
Martin Panter3d81d932016-01-14 09:36:00 +0000135REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +0000136
137EMPTYCERT = data_file("nullcert.pem")
138BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +0000139NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000140BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200141NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +0200142NULLBYTECERT = data_file("nullbytecert.pem")
Christian Heimesa37f5242019-01-15 23:47:42 +0100143TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000144
Christian Heimes88bfd0b2018-08-14 12:54:19 +0200145DHFILE = data_file("ffdh3072.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100146BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +0000147
Christian Heimes358cfd42016-09-10 22:43:48 +0200148# Not defined in all versions of OpenSSL
149OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
150OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
151OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
152OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
Christian Heimes05d9fe32018-02-27 08:55:39 +0100153OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
Christian Heimes6f37ebc2021-04-09 17:59:21 +0200154OP_IGNORE_UNEXPECTED_EOF = getattr(ssl, "OP_IGNORE_UNEXPECTED_EOF", 0)
Christian Heimes358cfd42016-09-10 22:43:48 +0200155
Christian Heimesf6c6b582021-03-18 23:06:50 +0100156# Ubuntu has patched OpenSSL and changed behavior of security level 2
157# see https://bugs.python.org/issue41561#msg389003
158def is_ubuntu():
159 try:
160 # Assume that any references of "ubuntu" implies Ubuntu-like distro
161 # The workaround is not required for 18.04, but doesn't hurt either.
162 with open("/etc/os-release", encoding="utf-8") as f:
163 return "ubuntu" in f.read()
164 except FileNotFoundError:
165 return False
166
167if is_ubuntu():
168 def seclevel_workaround(*ctxs):
169 """"Lower security level to '1' and allow all ciphers for TLS 1.0/1"""
170 for ctx in ctxs:
Christian Heimes34477502021-04-12 12:00:38 +0200171 if (
172 hasattr(ctx, "minimum_version") and
173 ctx.minimum_version <= ssl.TLSVersion.TLSv1_1
174 ):
Christian Heimesf6c6b582021-03-18 23:06:50 +0100175 ctx.set_ciphers("@SECLEVEL=1:ALL")
176else:
177 def seclevel_workaround(*ctxs):
178 pass
179
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100180
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200181def has_tls_protocol(protocol):
182 """Check if a TLS protocol is available and enabled
183
184 :param protocol: enum ssl._SSLMethod member or name
185 :return: bool
186 """
187 if isinstance(protocol, str):
188 assert protocol.startswith('PROTOCOL_')
189 protocol = getattr(ssl, protocol, None)
190 if protocol is None:
191 return False
192 if protocol in {
193 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
194 ssl.PROTOCOL_TLS_CLIENT
195 }:
196 # auto-negotiate protocols are always available
197 return True
198 name = protocol.name
199 return has_tls_version(name[len('PROTOCOL_'):])
200
201
202@functools.lru_cache
203def has_tls_version(version):
204 """Check if a TLS/SSL version is enabled
205
206 :param version: TLS version name or ssl.TLSVersion member
207 :return: bool
208 """
209 if version == "SSLv2":
210 # never supported and not even in TLSVersion enum
211 return False
212
213 if isinstance(version, str):
214 version = ssl.TLSVersion.__members__[version]
215
216 # check compile time flags like ssl.HAS_TLSv1_2
217 if not getattr(ssl, f'HAS_{version.name}'):
218 return False
219
Christian Heimes5151d642021-04-09 15:43:06 +0200220 if IS_OPENSSL_3_0_0 and version < ssl.TLSVersion.TLSv1_2:
221 # bpo43791: 3.0.0-alpha14 fails with TLSV1_ALERT_INTERNAL_ERROR
222 return False
223
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200224 # check runtime and dynamic crypto policy settings. A TLS version may
225 # be compiled in but disabled by a policy or config option.
Christian Heimes2875c602021-04-19 07:27:10 +0200226 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200227 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200228 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200229 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
230 version < ctx.minimum_version
231 ):
232 return False
233 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200234 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200235 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
236 version > ctx.maximum_version
237 ):
238 return False
239
240 return True
241
242
243def requires_tls_version(version):
244 """Decorator to skip tests when a required TLS version is not available
245
246 :param version: TLS version name or ssl.TLSVersion member
247 :return:
248 """
249 def decorator(func):
250 @functools.wraps(func)
251 def wrapper(*args, **kw):
252 if not has_tls_version(version):
253 raise unittest.SkipTest(f"{version} is not available.")
254 else:
255 return func(*args, **kw)
256 return wrapper
257 return decorator
258
259
Thomas Woutersed03b412007-08-28 21:37:11 +0000260def handle_error(prefix):
261 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000262 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000263 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000264
Christian Heimesb7b92252018-02-25 09:49:31 +0100265
Antoine Pitrouc695c952014-04-28 20:57:36 +0200266def utc_offset(): #NOTE: ignore issues like #1647654
267 # local time = utc time + utc offset
268 if time.daylight and time.localtime().tm_isdst > 0:
269 return -time.altzone # seconds
270 return -time.timezone
271
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100272
Christian Heimes2875c602021-04-19 07:27:10 +0200273ignore_deprecation = warnings_helper.ignore_warnings(
274 category=DeprecationWarning
275)
Antoine Pitrou23df4832010-08-04 17:14:06 +0000276
Christian Heimes2875c602021-04-19 07:27:10 +0200277
278def test_wrap_socket(sock, *,
Christian Heimesd0486372016-09-10 23:23:33 +0200279 cert_reqs=ssl.CERT_NONE, ca_certs=None,
280 ciphers=None, certfile=None, keyfile=None,
281 **kwargs):
Christian Heimes2875c602021-04-19 07:27:10 +0200282 if not kwargs.get("server_side"):
283 kwargs["server_hostname"] = SIGNED_CERTFILE_HOSTNAME
284 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
285 else:
286 context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimesd0486372016-09-10 23:23:33 +0200287 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200288 if cert_reqs == ssl.CERT_NONE:
289 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200290 context.verify_mode = cert_reqs
291 if ca_certs is not None:
292 context.load_verify_locations(ca_certs)
293 if certfile is not None or keyfile is not None:
294 context.load_cert_chain(certfile, keyfile)
295 if ciphers is not None:
296 context.set_ciphers(ciphers)
297 return context.wrap_socket(sock, **kwargs)
298
Christian Heimesa170fa12017-09-15 20:27:30 +0200299
300def testing_context(server_cert=SIGNED_CERTFILE):
301 """Create context
302
303 client_context, server_context, hostname = testing_context()
304 """
305 if server_cert == SIGNED_CERTFILE:
306 hostname = SIGNED_CERTFILE_HOSTNAME
307 elif server_cert == SIGNED_CERTFILE2:
308 hostname = SIGNED_CERTFILE2_HOSTNAME
Christian Heimesb467d9a2021-04-17 10:07:19 +0200309 elif server_cert == NOSANFILE:
310 hostname = NOSAN_HOSTNAME
Christian Heimesa170fa12017-09-15 20:27:30 +0200311 else:
312 raise ValueError(server_cert)
313
314 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
315 client_context.load_verify_locations(SIGNING_CA)
316
317 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
318 server_context.load_cert_chain(server_cert)
Christian Heimes9fb051f2018-09-23 08:32:31 +0200319 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200320
321 return client_context, server_context, hostname
322
323
Antoine Pitrou152efa22010-05-16 18:19:27 +0000324class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000325
Antoine Pitrou480a1242010-04-28 21:37:09 +0000326 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000327 ssl.CERT_NONE
328 ssl.CERT_OPTIONAL
329 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100330 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100331 ssl.OP_SINGLE_DH_USE
Christian Heimesd37b74f2021-04-19 08:31:29 +0200332 ssl.OP_SINGLE_ECDH_USE
Christian Heimes39258d32021-04-17 11:36:35 +0200333 ssl.OP_NO_COMPRESSION
Christian Heimesd37b74f2021-04-19 08:31:29 +0200334 self.assertEqual(ssl.HAS_SNI, True)
335 self.assertEqual(ssl.HAS_ECDH, True)
336 self.assertEqual(ssl.HAS_TLSv1_2, True)
337 self.assertEqual(ssl.HAS_TLSv1_3, True)
Christian Heimescb5b68a2017-09-07 18:07:00 -0700338 ssl.OP_NO_SSLv2
339 ssl.OP_NO_SSLv3
340 ssl.OP_NO_TLSv1
341 ssl.OP_NO_TLSv1_3
Christian Heimes39258d32021-04-17 11:36:35 +0200342 ssl.OP_NO_TLSv1_1
343 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200344 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000345
Christian Heimes9d50ab52018-02-27 10:17:30 +0100346 def test_private_init(self):
347 with self.assertRaisesRegex(TypeError, "public constructor"):
348 with socket.socket() as s:
349 ssl.SSLSocket(s)
350
Antoine Pitrou172f0252014-04-18 20:33:08 +0200351 def test_str_for_enums(self):
352 # Make sure that the PROTOCOL_* constants have enum-like string
353 # reprs.
Christian Heimes2875c602021-04-19 07:27:10 +0200354 proto = ssl.PROTOCOL_TLS_CLIENT
355 self.assertEqual(str(proto), 'PROTOCOL_TLS_CLIENT')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200356 ctx = ssl.SSLContext(proto)
357 self.assertIs(ctx.protocol, proto)
358
Antoine Pitrou480a1242010-04-28 21:37:09 +0000359 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000360 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000361 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000362 sys.stdout.write("\n RAND_status is %d (%s)\n"
363 % (v, (v and "sufficient randomness") or
364 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200365
Christian Heimes2875c602021-04-19 07:27:10 +0200366 with warnings_helper.check_warnings():
367 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200368 self.assertEqual(len(data), 16)
369 self.assertEqual(is_cryptographic, v == 1)
370 if v:
371 data = ssl.RAND_bytes(16)
372 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200373 else:
374 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200375
Victor Stinner1e81a392013-12-19 16:47:04 +0100376 # negative num is invalid
377 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
Christian Heimes2875c602021-04-19 07:27:10 +0200378 with warnings_helper.check_warnings():
379 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
Victor Stinner1e81a392013-12-19 16:47:04 +0100380
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000381 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200382 ssl.RAND_add(b"this is a random bytes object", 75.0)
383 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000384
Antoine Pitrou480a1242010-04-28 21:37:09 +0000385 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000386 # note that this uses an 'unofficial' function in _ssl.c,
387 # provided solely for this test, to exercise the certificate
388 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100389 self.assertEqual(
390 ssl._ssl._test_decode_cert(CERTFILE),
391 CERTFILE_INFO
392 )
393 self.assertEqual(
394 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
395 SIGNED_CERTFILE_INFO
396 )
397
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200398 # Issue #13034: the subjectAltName in some certificates
399 # (notably projects.developer.nokia.com:443) wasn't parsed
400 p = ssl._ssl._test_decode_cert(NOKIACERT)
401 if support.verbose:
402 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
403 self.assertEqual(p['subjectAltName'],
404 (('DNS', 'projects.developer.nokia.com'),
405 ('DNS', 'projects.forum.nokia.com'))
406 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100407 # extra OCSP and AIA fields
408 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
409 self.assertEqual(p['caIssuers'],
410 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
411 self.assertEqual(p['crlDistributionPoints'],
412 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000413
Christian Heimesa37f5242019-01-15 23:47:42 +0100414 def test_parse_cert_CVE_2019_5010(self):
415 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
416 if support.verbose:
417 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
418 self.assertEqual(
419 p,
420 {
421 'issuer': (
422 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
423 'notAfter': 'Jun 14 18:00:58 2028 GMT',
424 'notBefore': 'Jun 18 18:00:58 2018 GMT',
425 'serialNumber': '02',
426 'subject': ((('countryName', 'UK'),),
427 (('commonName',
428 'codenomicon-vm-2.test.lal.cisco.com'),)),
429 'subjectAltName': (
430 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
431 'version': 3
432 }
433 )
434
Christian Heimes824f7f32013-08-17 00:54:47 +0200435 def test_parse_cert_CVE_2013_4238(self):
436 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
437 if support.verbose:
438 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
439 subject = ((('countryName', 'US'),),
440 (('stateOrProvinceName', 'Oregon'),),
441 (('localityName', 'Beaverton'),),
442 (('organizationName', 'Python Software Foundation'),),
443 (('organizationalUnitName', 'Python Core Development'),),
444 (('commonName', 'null.python.org\x00example.org'),),
445 (('emailAddress', 'python-dev@python.org'),))
446 self.assertEqual(p['subject'], subject)
447 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200448 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
449 san = (('DNS', 'altnull.python.org\x00example.com'),
450 ('email', 'null@python.org\x00user@example.org'),
451 ('URI', 'http://null.python.org\x00http://example.org'),
452 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100453 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200454 else:
455 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
456 san = (('DNS', 'altnull.python.org\x00example.com'),
457 ('email', 'null@python.org\x00user@example.org'),
458 ('URI', 'http://null.python.org\x00http://example.org'),
459 ('IP Address', '192.0.2.1'),
460 ('IP Address', '<invalid>'))
461
462 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200463
Christian Heimes1c03abd2016-09-06 23:25:35 +0200464 def test_parse_all_sans(self):
465 p = ssl._ssl._test_decode_cert(ALLSANFILE)
466 self.assertEqual(p['subjectAltName'],
467 (
468 ('DNS', 'allsans'),
469 ('othername', '<unsupported>'),
470 ('othername', '<unsupported>'),
471 ('email', 'user@example.org'),
472 ('DNS', 'www.example.org'),
473 ('DirName',
474 ((('countryName', 'XY'),),
475 (('localityName', 'Castle Anthrax'),),
476 (('organizationName', 'Python Software Foundation'),),
477 (('commonName', 'dirname example'),))),
478 ('URI', 'https://www.python.org/'),
479 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100480 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200481 ('Registered ID', '1.2.3.4.5')
482 )
483 )
484
Antoine Pitrou480a1242010-04-28 21:37:09 +0000485 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000486 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000487 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000488 d1 = ssl.PEM_cert_to_DER_cert(pem)
489 p2 = ssl.DER_cert_to_PEM_cert(d1)
490 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000491 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000492 if not p2.startswith(ssl.PEM_HEADER + '\n'):
493 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
494 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
495 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000496
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000497 def test_openssl_version(self):
498 n = ssl.OPENSSL_VERSION_NUMBER
499 t = ssl.OPENSSL_VERSION_INFO
500 s = ssl.OPENSSL_VERSION
501 self.assertIsInstance(n, int)
502 self.assertIsInstance(t, tuple)
503 self.assertIsInstance(s, str)
504 # Some sanity checks follow
Christian Heimesd37b74f2021-04-19 08:31:29 +0200505 # >= 1.1.1
506 self.assertGreaterEqual(n, 0x10101000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100507 # < 4.0
508 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000509 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100510 self.assertGreaterEqual(major, 1)
511 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000512 self.assertGreaterEqual(minor, 0)
513 self.assertLess(minor, 256)
514 self.assertGreaterEqual(fix, 0)
515 self.assertLess(fix, 256)
516 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100517 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000518 self.assertGreaterEqual(status, 0)
519 self.assertLessEqual(status, 15)
Christian Heimesd37b74f2021-04-19 08:31:29 +0200520
521 libressl_ver = f"LibreSSL {major:d}"
522 openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}"
523 self.assertTrue(
524 s.startswith((openssl_ver, libressl_ver)),
525 (s, t, hex(n))
526 )
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000527
Antoine Pitrou9d543662010-04-23 23:10:32 +0000528 @support.cpython_only
529 def test_refcycle(self):
530 # Issue #7943: an SSL object doesn't create reference cycles with
531 # itself.
532 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200533 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000534 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800535 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100536 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100537 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000538
Antoine Pitroua468adc2010-09-14 14:43:44 +0000539 def test_wrapped_unconnected(self):
540 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200541 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000542 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200543 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100544 self.assertRaises(OSError, ss.recv, 1)
545 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
546 self.assertRaises(OSError, ss.recvfrom, 1)
547 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
548 self.assertRaises(OSError, ss.send, b'x')
549 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200550 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100551 self.assertRaises(NotImplementedError, ss.sendmsg,
552 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200553 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
554 self.assertRaises(NotImplementedError, ss.recvmsg_into,
555 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000556
Antoine Pitrou40f08742010-04-24 22:04:40 +0000557 def test_timeout(self):
558 # Issue #8524: when creating an SSL socket, the timeout of the
559 # original socket should be retained.
560 for timeout in (None, 0.0, 5.0):
561 s = socket.socket(socket.AF_INET)
562 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200563 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100564 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000565
Christian Heimes2875c602021-04-19 07:27:10 +0200566 @ignore_deprecation
Christian Heimesd0486372016-09-10 23:23:33 +0200567 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000568 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000569 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000570 "certfile must be specified",
571 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000572 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000573 "certfile must be specified for server-side operations",
574 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000575 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000576 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200577 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100578 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
579 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200580 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200581 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000582 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000583 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000584 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200585 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000586 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000587 ssl.wrap_socket(sock,
588 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000589 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200590 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000591 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000592 ssl.wrap_socket(sock,
593 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000594 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000595
Martin Panter3464ea22016-02-01 21:58:11 +0000596 def bad_cert_test(self, certfile):
597 """Check that trying to use the given client certificate fails"""
598 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
599 certfile)
600 sock = socket.socket()
601 self.addCleanup(sock.close)
602 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200603 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200604 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000605
606 def test_empty_cert(self):
607 """Wrapping with an empty cert file"""
608 self.bad_cert_test("nullcert.pem")
609
610 def test_malformed_cert(self):
611 """Wrapping with a badly formatted certificate (syntax error)"""
612 self.bad_cert_test("badcert.pem")
613
614 def test_malformed_key(self):
615 """Wrapping with a badly formatted key (syntax error)"""
616 self.bad_cert_test("badkey.pem")
617
Christian Heimes2875c602021-04-19 07:27:10 +0200618 @ignore_deprecation
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000619 def test_match_hostname(self):
620 def ok(cert, hostname):
621 ssl.match_hostname(cert, hostname)
622 def fail(cert, hostname):
623 self.assertRaises(ssl.CertificateError,
624 ssl.match_hostname, cert, hostname)
625
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100626 # -- Hostname matching --
627
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000628 cert = {'subject': ((('commonName', 'example.com'),),)}
629 ok(cert, 'example.com')
630 ok(cert, 'ExAmple.cOm')
631 fail(cert, 'www.example.com')
632 fail(cert, '.example.com')
633 fail(cert, 'example.org')
634 fail(cert, 'exampleXcom')
635
636 cert = {'subject': ((('commonName', '*.a.com'),),)}
637 ok(cert, 'foo.a.com')
638 fail(cert, 'bar.foo.a.com')
639 fail(cert, 'a.com')
640 fail(cert, 'Xa.com')
641 fail(cert, '.a.com')
642
Mandeep Singhede2ac92017-11-27 04:01:27 +0530643 # only match wildcards when they are the only thing
644 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000645 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530646 fail(cert, 'foo.com')
647 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000648 fail(cert, 'bar.com')
649 fail(cert, 'foo.a.com')
650 fail(cert, 'bar.foo.com')
651
Christian Heimes824f7f32013-08-17 00:54:47 +0200652 # NULL bytes are bad, CVE-2013-4073
653 cert = {'subject': ((('commonName',
654 'null.python.org\x00example.org'),),)}
655 ok(cert, 'null.python.org\x00example.org') # or raise an error?
656 fail(cert, 'example.org')
657 fail(cert, 'null.python.org')
658
Georg Brandl72c98d32013-10-27 07:16:53 +0100659 # error cases with wildcards
660 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
661 fail(cert, 'bar.foo.a.com')
662 fail(cert, 'a.com')
663 fail(cert, 'Xa.com')
664 fail(cert, '.a.com')
665
666 cert = {'subject': ((('commonName', 'a.*.com'),),)}
667 fail(cert, 'a.foo.com')
668 fail(cert, 'a..com')
669 fail(cert, 'a.com')
670
671 # wildcard doesn't match IDNA prefix 'xn--'
672 idna = 'püthon.python.org'.encode("idna").decode("ascii")
673 cert = {'subject': ((('commonName', idna),),)}
674 ok(cert, idna)
675 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
676 fail(cert, idna)
677 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
678 fail(cert, idna)
679
680 # wildcard in first fragment and IDNA A-labels in sequent fragments
681 # are supported.
682 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
683 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530684 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
685 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100686 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
687 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
688
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000689 # Slightly fake real-world example
690 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
691 'subject': ((('commonName', 'linuxfrz.org'),),),
692 'subjectAltName': (('DNS', 'linuxfr.org'),
693 ('DNS', 'linuxfr.com'),
694 ('othername', '<unsupported>'))}
695 ok(cert, 'linuxfr.org')
696 ok(cert, 'linuxfr.com')
697 # Not a "DNS" entry
698 fail(cert, '<unsupported>')
699 # When there is a subjectAltName, commonName isn't used
700 fail(cert, 'linuxfrz.org')
701
702 # A pristine real-world example
703 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
704 'subject': ((('countryName', 'US'),),
705 (('stateOrProvinceName', 'California'),),
706 (('localityName', 'Mountain View'),),
707 (('organizationName', 'Google Inc'),),
708 (('commonName', 'mail.google.com'),))}
709 ok(cert, 'mail.google.com')
710 fail(cert, 'gmail.com')
711 # Only commonName is considered
712 fail(cert, 'California')
713
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100714 # -- IPv4 matching --
715 cert = {'subject': ((('commonName', 'example.com'),),),
716 'subjectAltName': (('DNS', 'example.com'),
717 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200718 ('IP Address', '14.15.16.17'),
719 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100720 ok(cert, '10.11.12.13')
721 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200722 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
723 fail(cert, '127.1')
724 fail(cert, '14.15.16.17 ')
725 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100726 fail(cert, '14.15.16.18')
727 fail(cert, 'example.net')
728
729 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300730 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100731 cert = {'subject': ((('commonName', 'example.com'),),),
732 'subjectAltName': (
733 ('DNS', 'example.com'),
734 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
735 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
736 ok(cert, '2001::cafe')
737 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200738 fail(cert, '2003::baba ')
739 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100740 fail(cert, '2003::bebe')
741 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100742
743 # -- Miscellaneous --
744
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000745 # Neither commonName nor subjectAltName
746 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
747 'subject': ((('countryName', 'US'),),
748 (('stateOrProvinceName', 'California'),),
749 (('localityName', 'Mountain View'),),
750 (('organizationName', 'Google Inc'),))}
751 fail(cert, 'mail.google.com')
752
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200753 # No DNS entry in subjectAltName but a commonName
754 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
755 'subject': ((('countryName', 'US'),),
756 (('stateOrProvinceName', 'California'),),
757 (('localityName', 'Mountain View'),),
758 (('commonName', 'mail.google.com'),)),
759 'subjectAltName': (('othername', 'blabla'), )}
760 ok(cert, 'mail.google.com')
761
762 # No DNS entry subjectAltName and no commonName
763 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
764 'subject': ((('countryName', 'US'),),
765 (('stateOrProvinceName', 'California'),),
766 (('localityName', 'Mountain View'),),
767 (('organizationName', 'Google Inc'),)),
768 'subjectAltName': (('othername', 'blabla'),)}
769 fail(cert, 'google.com')
770
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000771 # Empty cert / no cert
772 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
773 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
774
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200775 # Issue #17980: avoid denials of service by refusing more than one
776 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100777 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
778 with self.assertRaisesRegex(
779 ssl.CertificateError,
780 "partial wildcards in leftmost label are not supported"):
781 ssl.match_hostname(cert, 'axxb.example.com')
782
783 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
784 with self.assertRaisesRegex(
785 ssl.CertificateError,
786 "wildcard can only be present in the leftmost label"):
787 ssl.match_hostname(cert, 'www.sub.example.com')
788
789 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
790 with self.assertRaisesRegex(
791 ssl.CertificateError,
792 "too many wildcards"):
793 ssl.match_hostname(cert, 'axxbxxc.example.com')
794
795 cert = {'subject': ((('commonName', '*'),),)}
796 with self.assertRaisesRegex(
797 ssl.CertificateError,
798 "sole wildcard without additional labels are not support"):
799 ssl.match_hostname(cert, 'host')
800
801 cert = {'subject': ((('commonName', '*.com'),),)}
802 with self.assertRaisesRegex(
803 ssl.CertificateError,
804 r"hostname 'com' doesn't match '\*.com'"):
805 ssl.match_hostname(cert, 'com')
806
807 # extra checks for _inet_paton()
808 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
809 with self.assertRaises(ValueError):
810 ssl._inet_paton(invalid)
811 for ipaddr in ['127.0.0.1', '192.168.0.1']:
812 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300813 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100814 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
815 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200816
Antoine Pitroud5323212010-10-22 18:19:07 +0000817 def test_server_side(self):
818 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200819 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000820 with socket.socket() as sock:
821 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
822 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000823
Antoine Pitroud6494802011-07-21 01:11:30 +0200824 def test_unknown_channel_binding(self):
825 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200826 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200827 c = socket.socket(socket.AF_INET)
828 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200829 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100830 with self.assertRaises(ValueError):
831 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200832 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200833
834 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
835 "'tls-unique' channel binding not available")
836 def test_tls_unique_channel_binding(self):
837 # unconnected should return None for known type
838 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200839 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100840 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200841 # the same for server-side
842 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200843 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100844 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200845
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600846 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200847 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600848 r = repr(ss)
849 with self.assertWarns(ResourceWarning) as cm:
850 ss = None
851 support.gc_collect()
852 self.assertIn(r, str(cm.warning.args[0]))
853
Christian Heimes6d7ad132013-06-09 18:02:55 +0200854 def test_get_default_verify_paths(self):
855 paths = ssl.get_default_verify_paths()
856 self.assertEqual(len(paths), 6)
857 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
858
Hai Shia7f5d932020-08-04 00:41:24 +0800859 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200860 env["SSL_CERT_DIR"] = CAPATH
861 env["SSL_CERT_FILE"] = CERTFILE
862 paths = ssl.get_default_verify_paths()
863 self.assertEqual(paths.cafile, CERTFILE)
864 self.assertEqual(paths.capath, CAPATH)
865
Christian Heimes44109d72013-11-22 01:51:30 +0100866 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
867 def test_enum_certificates(self):
868 self.assertTrue(ssl.enum_certificates("CA"))
869 self.assertTrue(ssl.enum_certificates("ROOT"))
870
871 self.assertRaises(TypeError, ssl.enum_certificates)
872 self.assertRaises(WindowsError, ssl.enum_certificates, "")
873
Christian Heimesc2d65e12013-11-22 16:13:55 +0100874 trust_oids = set()
875 for storename in ("CA", "ROOT"):
876 store = ssl.enum_certificates(storename)
877 self.assertIsInstance(store, list)
878 for element in store:
879 self.assertIsInstance(element, tuple)
880 self.assertEqual(len(element), 3)
881 cert, enc, trust = element
882 self.assertIsInstance(cert, bytes)
883 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200884 self.assertIsInstance(trust, (frozenset, set, bool))
885 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100886 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100887
888 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100889 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200890
Christian Heimes46bebee2013-06-09 19:03:31 +0200891 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100892 def test_enum_crls(self):
893 self.assertTrue(ssl.enum_crls("CA"))
894 self.assertRaises(TypeError, ssl.enum_crls)
895 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200896
Christian Heimes44109d72013-11-22 01:51:30 +0100897 crls = ssl.enum_crls("CA")
898 self.assertIsInstance(crls, list)
899 for element in crls:
900 self.assertIsInstance(element, tuple)
901 self.assertEqual(len(element), 2)
902 self.assertIsInstance(element[0], bytes)
903 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200904
Christian Heimes46bebee2013-06-09 19:03:31 +0200905
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100906 def test_asn1object(self):
907 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
908 '1.3.6.1.5.5.7.3.1')
909
910 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
911 self.assertEqual(val, expected)
912 self.assertEqual(val.nid, 129)
913 self.assertEqual(val.shortname, 'serverAuth')
914 self.assertEqual(val.longname, 'TLS Web Server Authentication')
915 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
916 self.assertIsInstance(val, ssl._ASN1Object)
917 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
918
919 val = ssl._ASN1Object.fromnid(129)
920 self.assertEqual(val, expected)
921 self.assertIsInstance(val, ssl._ASN1Object)
922 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100923 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
924 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100925 for i in range(1000):
926 try:
927 obj = ssl._ASN1Object.fromnid(i)
928 except ValueError:
929 pass
930 else:
931 self.assertIsInstance(obj.nid, int)
932 self.assertIsInstance(obj.shortname, str)
933 self.assertIsInstance(obj.longname, str)
934 self.assertIsInstance(obj.oid, (str, type(None)))
935
936 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
937 self.assertEqual(val, expected)
938 self.assertIsInstance(val, ssl._ASN1Object)
939 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
940 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
941 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100942 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
943 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100944
Christian Heimes72d28502013-11-23 13:56:58 +0100945 def test_purpose_enum(self):
946 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
947 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
948 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
949 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
950 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
951 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
952 '1.3.6.1.5.5.7.3.1')
953
954 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
955 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
956 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
957 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
958 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
959 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
960 '1.3.6.1.5.5.7.3.2')
961
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100962 def test_unsupported_dtls(self):
963 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
964 self.addCleanup(s.close)
965 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +0200966 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100967 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +0200968 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100969 with self.assertRaises(NotImplementedError) as cx:
970 ctx.wrap_socket(s)
971 self.assertEqual(str(cx.exception), "only stream sockets are supported")
972
Antoine Pitrouc695c952014-04-28 20:57:36 +0200973 def cert_time_ok(self, timestring, timestamp):
974 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
975
976 def cert_time_fail(self, timestring):
977 with self.assertRaises(ValueError):
978 ssl.cert_time_to_seconds(timestring)
979
980 @unittest.skipUnless(utc_offset(),
981 'local time needs to be different from UTC')
982 def test_cert_time_to_seconds_timezone(self):
983 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
984 # results if local timezone is not UTC
985 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
986 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
987
988 def test_cert_time_to_seconds(self):
989 timestring = "Jan 5 09:34:43 2018 GMT"
990 ts = 1515144883.0
991 self.cert_time_ok(timestring, ts)
992 # accept keyword parameter, assert its name
993 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
994 # accept both %e and %d (space or zero generated by strftime)
995 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
996 # case-insensitive
997 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
998 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
999 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1000 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1001 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1002 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1003 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1004 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1005
1006 newyear_ts = 1230768000.0
1007 # leap seconds
1008 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1009 # same timestamp
1010 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1011
1012 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1013 # allow 60th second (even if it is not a leap second)
1014 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1015 # allow 2nd leap second for compatibility with time.strptime()
1016 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1017 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1018
Mike53f7a7c2017-12-14 14:04:53 +03001019 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001020 # 99991231235959Z (rfc 5280)
1021 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1022
1023 @support.run_with_locale('LC_ALL', '')
1024 def test_cert_time_to_seconds_locale(self):
1025 # `cert_time_to_seconds()` should be locale independent
1026
1027 def local_february_name():
1028 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1029
1030 if local_february_name().lower() == 'feb':
1031 self.skipTest("locale-specific month name needs to be "
1032 "different from C locale")
1033
1034 # locale-independent
1035 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1036 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1037
Martin Panter3840b2a2016-03-27 01:53:46 +00001038 def test_connect_ex_error(self):
1039 server = socket.socket(socket.AF_INET)
1040 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001041 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001042 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001043 cert_reqs=ssl.CERT_REQUIRED)
1044 self.addCleanup(s.close)
1045 rc = s.connect_ex((HOST, port))
1046 # Issue #19919: Windows machines or VMs hosted on Windows
1047 # machines sometimes return EWOULDBLOCK.
1048 errors = (
1049 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1050 errno.EWOULDBLOCK,
1051 )
1052 self.assertIn(rc, errors)
1053
Christian Heimes89d15502021-04-19 06:55:30 +02001054 def test_read_write_zero(self):
1055 # empty reads and writes now work, bpo-42854, bpo-31711
1056 client_context, server_context, hostname = testing_context()
1057 server = ThreadedEchoServer(context=server_context)
1058 with server:
1059 with client_context.wrap_socket(socket.socket(),
1060 server_hostname=hostname) as s:
1061 s.connect((HOST, server.port))
1062 self.assertEqual(s.recv(0), b"")
1063 self.assertEqual(s.send(b""), 0)
1064
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001065
Antoine Pitrou152efa22010-05-16 18:19:27 +00001066class ContextTests(unittest.TestCase):
1067
1068 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001069 for protocol in PROTOCOLS:
Christian Heimes2875c602021-04-19 07:27:10 +02001070 with warnings_helper.check_warnings():
1071 ctx = ssl.SSLContext(protocol)
1072 self.assertEqual(ctx.protocol, protocol)
1073 with warnings_helper.check_warnings():
1074 ctx = ssl.SSLContext()
Christian Heimes598894f2016-09-05 23:19:05 +02001075 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001076 self.assertRaises(ValueError, ssl.SSLContext, -1)
1077 self.assertRaises(ValueError, ssl.SSLContext, 42)
1078
Antoine Pitrou152efa22010-05-16 18:19:27 +00001079 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001080 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001081 ctx.set_ciphers("ALL")
1082 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001083 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001084 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001085
Christian Heimes892d66e2018-01-29 14:10:18 +01001086 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1087 "Test applies only to Python default ciphers")
1088 def test_python_ciphers(self):
1089 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1090 ciphers = ctx.get_ciphers()
1091 for suite in ciphers:
1092 name = suite['name']
1093 self.assertNotIn("PSK", name)
1094 self.assertNotIn("SRP", name)
1095 self.assertNotIn("MD5", name)
1096 self.assertNotIn("RC4", name)
1097 self.assertNotIn("3DES", name)
1098
Christian Heimes25bfcd52016-09-06 00:04:45 +02001099 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001100 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001101 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001102 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001103 self.assertIn('AES256-GCM-SHA384', names)
1104 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001105
Antoine Pitroub5218772010-05-21 09:56:06 +00001106 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001107 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001108 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001109 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001110 # SSLContext also enables these by default
1111 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001112 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001113 OP_ENABLE_MIDDLEBOX_COMPAT |
1114 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001115 self.assertEqual(default, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001116 with warnings_helper.check_warnings():
1117 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001118 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001119 with warnings_helper.check_warnings():
1120 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
Christian Heimes39258d32021-04-17 11:36:35 +02001121 self.assertEqual(default, ctx.options)
1122 ctx.options = 0
1123 # Ubuntu has OP_NO_SSLv3 forced on by default
1124 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001125
Christian Heimesa170fa12017-09-15 20:27:30 +02001126 def test_verify_mode_protocol(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001127 with warnings_helper.check_warnings():
1128 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001129 # Default value
1130 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1131 ctx.verify_mode = ssl.CERT_OPTIONAL
1132 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1133 ctx.verify_mode = ssl.CERT_REQUIRED
1134 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1135 ctx.verify_mode = ssl.CERT_NONE
1136 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1137 with self.assertRaises(TypeError):
1138 ctx.verify_mode = None
1139 with self.assertRaises(ValueError):
1140 ctx.verify_mode = 42
1141
Christian Heimesa170fa12017-09-15 20:27:30 +02001142 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1143 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1144 self.assertFalse(ctx.check_hostname)
1145
1146 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1147 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1148 self.assertTrue(ctx.check_hostname)
1149
Christian Heimes61d478c2018-01-27 15:51:38 +01001150 def test_hostname_checks_common_name(self):
1151 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1152 self.assertTrue(ctx.hostname_checks_common_name)
1153 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1154 ctx.hostname_checks_common_name = True
1155 self.assertTrue(ctx.hostname_checks_common_name)
1156 ctx.hostname_checks_common_name = False
1157 self.assertFalse(ctx.hostname_checks_common_name)
1158 ctx.hostname_checks_common_name = True
1159 self.assertTrue(ctx.hostname_checks_common_name)
1160 else:
1161 with self.assertRaises(AttributeError):
1162 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001163
Christian Heimes2875c602021-04-19 07:27:10 +02001164 @ignore_deprecation
Christian Heimes698dde12018-02-27 11:54:43 +01001165 def test_min_max_version(self):
1166 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001167 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1168 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001169 minimum_range = {
1170 # stock OpenSSL
1171 ssl.TLSVersion.MINIMUM_SUPPORTED,
1172 # Fedora 29 uses TLS 1.0 by default
1173 ssl.TLSVersion.TLSv1,
1174 # RHEL 8 uses TLS 1.2 by default
1175 ssl.TLSVersion.TLSv1_2
1176 }
torsava34864d12019-12-02 17:15:42 +01001177 maximum_range = {
1178 # stock OpenSSL
1179 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1180 # Fedora 32 uses TLS 1.3 by default
1181 ssl.TLSVersion.TLSv1_3
1182 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001183
Christian Heimes34de2d32019-01-18 16:09:30 +01001184 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001185 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001186 )
torsava34864d12019-12-02 17:15:42 +01001187 self.assertIn(
1188 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001189 )
1190
1191 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1192 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1193 self.assertEqual(
1194 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1195 )
1196 self.assertEqual(
1197 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1198 )
1199
1200 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1201 ctx.maximum_version = ssl.TLSVersion.TLSv1
1202 self.assertEqual(
1203 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1204 )
1205 self.assertEqual(
1206 ctx.maximum_version, ssl.TLSVersion.TLSv1
1207 )
1208
1209 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1210 self.assertEqual(
1211 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1212 )
1213
1214 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1215 self.assertIn(
1216 ctx.maximum_version,
1217 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1218 )
1219
1220 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1221 self.assertIn(
1222 ctx.minimum_version,
1223 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1224 )
1225
1226 with self.assertRaises(ValueError):
1227 ctx.minimum_version = 42
1228
1229 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1230
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001231 self.assertIn(
1232 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001233 )
1234 self.assertEqual(
1235 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1236 )
1237 with self.assertRaises(ValueError):
1238 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1239 with self.assertRaises(ValueError):
1240 ctx.maximum_version = ssl.TLSVersion.TLSv1
1241
1242
matthewhughes9348e836bb2020-07-17 09:59:15 +01001243 @unittest.skipUnless(
1244 hasattr(ssl.SSLContext, 'security_level'),
1245 "requires OpenSSL >= 1.1.0"
1246 )
1247 def test_security_level(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001248 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
matthewhughes9348e836bb2020-07-17 09:59:15 +01001249 # The default security callback allows for levels between 0-5
1250 # with OpenSSL defaulting to 1, however some vendors override the
1251 # default value (e.g. Debian defaults to 2)
1252 security_level_range = {
1253 0,
1254 1, # OpenSSL default
1255 2, # Debian
1256 3,
1257 4,
1258 5,
1259 }
1260 self.assertIn(ctx.security_level, security_level_range)
1261
Christian Heimes22587792013-11-21 23:56:13 +01001262 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001263 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001264 # default value
1265 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1266 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001267 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1268 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1269 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1270 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1271 ctx.verify_flags = ssl.VERIFY_DEFAULT
1272 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001273 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1274 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001275 # supports any value
1276 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1277 self.assertEqual(ctx.verify_flags,
1278 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1279 with self.assertRaises(TypeError):
1280 ctx.verify_flags = None
1281
Antoine Pitrou152efa22010-05-16 18:19:27 +00001282 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001283 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001284 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001285 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001286 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1287 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001288 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001289 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001290 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001291 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001292 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001293 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001294 ctx.load_cert_chain(EMPTYCERT)
1295 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001296 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001297 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1298 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1299 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001300 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001301 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001302 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001303 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001304 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001305 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1306 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001307 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001308 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001309 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001310 # Password protected key and cert
1311 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1312 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1313 ctx.load_cert_chain(CERTFILE_PROTECTED,
1314 password=bytearray(KEY_PASSWORD.encode()))
1315 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1316 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1317 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1318 bytearray(KEY_PASSWORD.encode()))
1319 with self.assertRaisesRegex(TypeError, "should be a string"):
1320 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1321 with self.assertRaises(ssl.SSLError):
1322 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1323 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1324 # openssl has a fixed limit on the password buffer.
1325 # PEM_BUFSIZE is generally set to 1kb.
1326 # Return a string larger than this.
1327 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1328 # Password callback
1329 def getpass_unicode():
1330 return KEY_PASSWORD
1331 def getpass_bytes():
1332 return KEY_PASSWORD.encode()
1333 def getpass_bytearray():
1334 return bytearray(KEY_PASSWORD.encode())
1335 def getpass_badpass():
1336 return "badpass"
1337 def getpass_huge():
1338 return b'a' * (1024 * 1024)
1339 def getpass_bad_type():
1340 return 9
1341 def getpass_exception():
1342 raise Exception('getpass error')
1343 class GetPassCallable:
1344 def __call__(self):
1345 return KEY_PASSWORD
1346 def getpass(self):
1347 return KEY_PASSWORD
1348 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1349 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1350 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1351 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1352 ctx.load_cert_chain(CERTFILE_PROTECTED,
1353 password=GetPassCallable().getpass)
1354 with self.assertRaises(ssl.SSLError):
1355 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1356 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1357 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1358 with self.assertRaisesRegex(TypeError, "must return a string"):
1359 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1360 with self.assertRaisesRegex(Exception, "getpass error"):
1361 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1362 # Make sure the password function isn't called if it isn't needed
1363 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001364
1365 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001366 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001367 ctx.load_verify_locations(CERTFILE)
1368 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1369 ctx.load_verify_locations(BYTES_CERTFILE)
1370 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1371 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001372 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001373 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001374 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001375 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001376 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001377 ctx.load_verify_locations(BADCERT)
1378 ctx.load_verify_locations(CERTFILE, CAPATH)
1379 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1380
Victor Stinner80f75e62011-01-29 11:31:20 +00001381 # Issue #10989: crash if the second argument type is invalid
1382 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1383
Christian Heimesefff7062013-11-21 03:35:02 +01001384 def test_load_verify_cadata(self):
1385 # test cadata
1386 with open(CAFILE_CACERT) as f:
1387 cacert_pem = f.read()
1388 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1389 with open(CAFILE_NEURONIO) as f:
1390 neuronio_pem = f.read()
1391 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1392
1393 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001394 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001395 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1396 ctx.load_verify_locations(cadata=cacert_pem)
1397 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1398 ctx.load_verify_locations(cadata=neuronio_pem)
1399 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1400 # cert already in hash table
1401 ctx.load_verify_locations(cadata=neuronio_pem)
1402 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1403
1404 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001405 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001406 combined = "\n".join((cacert_pem, neuronio_pem))
1407 ctx.load_verify_locations(cadata=combined)
1408 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1409
1410 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001411 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001412 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1413 neuronio_pem, "tail"]
1414 ctx.load_verify_locations(cadata="\n".join(combined))
1415 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1416
1417 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001418 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001419 ctx.load_verify_locations(cadata=cacert_der)
1420 ctx.load_verify_locations(cadata=neuronio_der)
1421 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1422 # cert already in hash table
1423 ctx.load_verify_locations(cadata=cacert_der)
1424 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1425
1426 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001427 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001428 combined = b"".join((cacert_der, neuronio_der))
1429 ctx.load_verify_locations(cadata=combined)
1430 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1431
1432 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001433 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001434 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1435
Christian Heimesb9ad88b2021-04-23 13:51:40 +02001436 with self.assertRaisesRegex(
1437 ssl.SSLError,
1438 "no start line: cadata does not contain a certificate"
1439 ):
Christian Heimesefff7062013-11-21 03:35:02 +01001440 ctx.load_verify_locations(cadata="broken")
Christian Heimesb9ad88b2021-04-23 13:51:40 +02001441 with self.assertRaisesRegex(
1442 ssl.SSLError,
1443 "not enough data: cadata does not contain a certificate"
1444 ):
Christian Heimesefff7062013-11-21 03:35:02 +01001445 ctx.load_verify_locations(cadata=b"broken")
1446
Paul Monsonf3550692019-06-19 13:09:54 -07001447 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001448 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001449 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001450 ctx.load_dh_params(DHFILE)
1451 if os.name != 'nt':
1452 ctx.load_dh_params(BYTES_DHFILE)
1453 self.assertRaises(TypeError, ctx.load_dh_params)
1454 self.assertRaises(TypeError, ctx.load_dh_params, None)
1455 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001456 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001457 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001458 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001459 ctx.load_dh_params(CERTFILE)
1460
Antoine Pitroub0182c82010-10-12 20:09:02 +00001461 def test_session_stats(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001462 for proto in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
Antoine Pitroub0182c82010-10-12 20:09:02 +00001463 ctx = ssl.SSLContext(proto)
1464 self.assertEqual(ctx.session_stats(), {
1465 'number': 0,
1466 'connect': 0,
1467 'connect_good': 0,
1468 'connect_renegotiate': 0,
1469 'accept': 0,
1470 'accept_good': 0,
1471 'accept_renegotiate': 0,
1472 'hits': 0,
1473 'misses': 0,
1474 'timeouts': 0,
1475 'cache_full': 0,
1476 })
1477
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001478 def test_set_default_verify_paths(self):
1479 # There's not much we can do to test that it acts as expected,
1480 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001481 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001482 ctx.set_default_verify_paths()
1483
Antoine Pitrou501da612011-12-21 09:27:41 +01001484 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001485 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001486 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001487 ctx.set_ecdh_curve("prime256v1")
1488 ctx.set_ecdh_curve(b"prime256v1")
1489 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1490 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1491 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1492 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1493
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001494 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001495 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001496
1497 # set_servername_callback expects a callable, or None
1498 self.assertRaises(TypeError, ctx.set_servername_callback)
1499 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1500 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1501 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1502
1503 def dummycallback(sock, servername, ctx):
1504 pass
1505 ctx.set_servername_callback(None)
1506 ctx.set_servername_callback(dummycallback)
1507
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001508 def test_sni_callback_refcycle(self):
1509 # Reference cycles through the servername callback are detected
1510 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001511 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001512 def dummycallback(sock, servername, ctx, cycle=ctx):
1513 pass
1514 ctx.set_servername_callback(dummycallback)
1515 wr = weakref.ref(ctx)
1516 del ctx, dummycallback
1517 gc.collect()
1518 self.assertIs(wr(), None)
1519
Christian Heimes9a5395a2013-06-17 15:44:12 +02001520 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001521 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001522 self.assertEqual(ctx.cert_store_stats(),
1523 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1524 ctx.load_cert_chain(CERTFILE)
1525 self.assertEqual(ctx.cert_store_stats(),
1526 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1527 ctx.load_verify_locations(CERTFILE)
1528 self.assertEqual(ctx.cert_store_stats(),
1529 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001530 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001531 self.assertEqual(ctx.cert_store_stats(),
1532 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1533
1534 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001535 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001536 self.assertEqual(ctx.get_ca_certs(), [])
1537 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1538 ctx.load_verify_locations(CERTFILE)
1539 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001540 # but CAFILE_CACERT is a CA cert
1541 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001542 self.assertEqual(ctx.get_ca_certs(),
1543 [{'issuer': ((('organizationName', 'Root CA'),),
1544 (('organizationalUnitName', 'http://www.cacert.org'),),
1545 (('commonName', 'CA Cert Signing Authority'),),
1546 (('emailAddress', 'support@cacert.org'),)),
Christian Heimesd37b74f2021-04-19 08:31:29 +02001547 'notAfter': 'Mar 29 12:29:49 2033 GMT',
1548 'notBefore': 'Mar 30 12:29:49 2003 GMT',
Christian Heimes9a5395a2013-06-17 15:44:12 +02001549 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001550 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001551 'subject': ((('organizationName', 'Root CA'),),
1552 (('organizationalUnitName', 'http://www.cacert.org'),),
1553 (('commonName', 'CA Cert Signing Authority'),),
1554 (('emailAddress', 'support@cacert.org'),)),
1555 'version': 3}])
1556
Martin Panterb55f8b72016-01-14 12:53:56 +00001557 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001558 pem = f.read()
1559 der = ssl.PEM_cert_to_DER_cert(pem)
1560 self.assertEqual(ctx.get_ca_certs(True), [der])
1561
Christian Heimes72d28502013-11-23 13:56:58 +01001562 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001563 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001564 ctx.load_default_certs()
1565
Christian Heimesa170fa12017-09-15 20:27:30 +02001566 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001567 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1568 ctx.load_default_certs()
1569
Christian Heimesa170fa12017-09-15 20:27:30 +02001570 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001571 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1572
Christian Heimesa170fa12017-09-15 20:27:30 +02001573 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001574 self.assertRaises(TypeError, ctx.load_default_certs, None)
1575 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1576
Benjamin Peterson91244e02014-10-03 18:17:15 -04001577 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001578 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001579 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001580 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001581 env["SSL_CERT_DIR"] = CAPATH
1582 env["SSL_CERT_FILE"] = CERTFILE
1583 ctx.load_default_certs()
1584 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1585
Benjamin Peterson91244e02014-10-03 18:17:15 -04001586 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001587 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001588 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001589 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001590 ctx.load_default_certs()
1591 stats = ctx.cert_store_stats()
1592
Christian Heimesa170fa12017-09-15 20:27:30 +02001593 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001594 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001595 env["SSL_CERT_DIR"] = CAPATH
1596 env["SSL_CERT_FILE"] = CERTFILE
1597 ctx.load_default_certs()
1598 stats["x509"] += 1
1599 self.assertEqual(ctx.cert_store_stats(), stats)
1600
Christian Heimes358cfd42016-09-10 22:43:48 +02001601 def _assert_context_options(self, ctx):
1602 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1603 if OP_NO_COMPRESSION != 0:
1604 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1605 OP_NO_COMPRESSION)
1606 if OP_SINGLE_DH_USE != 0:
1607 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1608 OP_SINGLE_DH_USE)
1609 if OP_SINGLE_ECDH_USE != 0:
1610 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1611 OP_SINGLE_ECDH_USE)
1612 if OP_CIPHER_SERVER_PREFERENCE != 0:
1613 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1614 OP_CIPHER_SERVER_PREFERENCE)
1615
Christian Heimes4c05b472013-11-23 15:58:30 +01001616 def test_create_default_context(self):
1617 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001618
Christian Heimes2875c602021-04-19 07:27:10 +02001619 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001620 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001621 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001622 self._assert_context_options(ctx)
1623
Christian Heimes4c05b472013-11-23 15:58:30 +01001624 with open(SIGNING_CA) as f:
1625 cadata = f.read()
1626 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1627 cadata=cadata)
Christian Heimes2875c602021-04-19 07:27:10 +02001628 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001629 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001630 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001631
1632 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001633 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes4c05b472013-11-23 15:58:30 +01001634 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001635 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001636
Christian Heimes2875c602021-04-19 07:27:10 +02001637
1638
Christian Heimes67986f92013-11-23 22:43:47 +01001639 def test__create_stdlib_context(self):
1640 ctx = ssl._create_stdlib_context()
Christian Heimes2875c602021-04-19 07:27:10 +02001641 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes67986f92013-11-23 22:43:47 +01001642 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001643 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001644 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001645
Christian Heimes2875c602021-04-19 07:27:10 +02001646 with warnings_helper.check_warnings():
1647 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
Christian Heimes67986f92013-11-23 22:43:47 +01001648 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1649 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001650 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001651
Christian Heimes2875c602021-04-19 07:27:10 +02001652 with warnings_helper.check_warnings():
1653 ctx = ssl._create_stdlib_context(
1654 ssl.PROTOCOL_TLSv1_2,
1655 cert_reqs=ssl.CERT_REQUIRED,
1656 check_hostname=True
1657 )
1658 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
Christian Heimes67986f92013-11-23 22:43:47 +01001659 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001660 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001661 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001662
1663 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001664 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes67986f92013-11-23 22:43:47 +01001665 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001666 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001667
Christian Heimes1aa9a752013-12-02 02:41:19 +01001668 def test_check_hostname(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001669 with warnings_helper.check_warnings():
1670 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001671 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001672 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001673
Christian Heimese82c0342017-09-15 20:29:57 +02001674 # Auto set CERT_REQUIRED
1675 ctx.check_hostname = True
1676 self.assertTrue(ctx.check_hostname)
1677 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1678 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001679 ctx.verify_mode = ssl.CERT_REQUIRED
1680 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001681 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001682
Christian Heimese82c0342017-09-15 20:29:57 +02001683 # Changing verify_mode does not affect check_hostname
1684 ctx.check_hostname = False
1685 ctx.verify_mode = ssl.CERT_NONE
1686 ctx.check_hostname = False
1687 self.assertFalse(ctx.check_hostname)
1688 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1689 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001690 ctx.check_hostname = True
1691 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001692 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1693
1694 ctx.check_hostname = False
1695 ctx.verify_mode = ssl.CERT_OPTIONAL
1696 ctx.check_hostname = False
1697 self.assertFalse(ctx.check_hostname)
1698 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1699 # keep CERT_OPTIONAL
1700 ctx.check_hostname = True
1701 self.assertTrue(ctx.check_hostname)
1702 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001703
1704 # Cannot set CERT_NONE with check_hostname enabled
1705 with self.assertRaises(ValueError):
1706 ctx.verify_mode = ssl.CERT_NONE
1707 ctx.check_hostname = False
1708 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001709 ctx.verify_mode = ssl.CERT_NONE
1710 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001711
Christian Heimes5fe668c2016-09-12 00:01:11 +02001712 def test_context_client_server(self):
1713 # PROTOCOL_TLS_CLIENT has sane defaults
1714 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1715 self.assertTrue(ctx.check_hostname)
1716 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1717
1718 # PROTOCOL_TLS_SERVER has different but also sane defaults
1719 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1720 self.assertFalse(ctx.check_hostname)
1721 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1722
Christian Heimes4df60f12017-09-15 20:26:05 +02001723 def test_context_custom_class(self):
1724 class MySSLSocket(ssl.SSLSocket):
1725 pass
1726
1727 class MySSLObject(ssl.SSLObject):
1728 pass
1729
1730 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1731 ctx.sslsocket_class = MySSLSocket
1732 ctx.sslobject_class = MySSLObject
1733
1734 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1735 self.assertIsInstance(sock, MySSLSocket)
1736 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1737 self.assertIsInstance(obj, MySSLObject)
1738
Christian Heimes78c7d522019-06-03 21:00:10 +02001739 def test_num_tickest(self):
1740 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1741 self.assertEqual(ctx.num_tickets, 2)
1742 ctx.num_tickets = 1
1743 self.assertEqual(ctx.num_tickets, 1)
1744 ctx.num_tickets = 0
1745 self.assertEqual(ctx.num_tickets, 0)
1746 with self.assertRaises(ValueError):
1747 ctx.num_tickets = -1
1748 with self.assertRaises(TypeError):
1749 ctx.num_tickets = None
1750
1751 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1752 self.assertEqual(ctx.num_tickets, 2)
1753 with self.assertRaises(ValueError):
1754 ctx.num_tickets = 1
1755
Antoine Pitrou152efa22010-05-16 18:19:27 +00001756
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001757class SSLErrorTests(unittest.TestCase):
1758
1759 def test_str(self):
1760 # The str() of a SSLError doesn't include the errno
1761 e = ssl.SSLError(1, "foo")
1762 self.assertEqual(str(e), "foo")
1763 self.assertEqual(e.errno, 1)
1764 # Same for a subclass
1765 e = ssl.SSLZeroReturnError(1, "foo")
1766 self.assertEqual(str(e), "foo")
1767 self.assertEqual(e.errno, 1)
1768
Paul Monsonf3550692019-06-19 13:09:54 -07001769 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001770 def test_lib_reason(self):
1771 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001772 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001773 with self.assertRaises(ssl.SSLError) as cm:
1774 ctx.load_dh_params(CERTFILE)
1775 self.assertEqual(cm.exception.library, 'PEM')
1776 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1777 s = str(cm.exception)
1778 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1779
1780 def test_subclass(self):
1781 # Check that the appropriate SSLError subclass is raised
1782 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001783 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1784 ctx.check_hostname = False
1785 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001786 with socket.create_server(("127.0.0.1", 0)) as s:
1787 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001788 c.setblocking(False)
1789 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001790 with self.assertRaises(ssl.SSLWantReadError) as cm:
1791 c.do_handshake()
1792 s = str(cm.exception)
1793 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1794 # For compatibility
1795 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1796
1797
Christian Heimes61d478c2018-01-27 15:51:38 +01001798 def test_bad_server_hostname(self):
1799 ctx = ssl.create_default_context()
1800 with self.assertRaises(ValueError):
1801 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1802 server_hostname="")
1803 with self.assertRaises(ValueError):
1804 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1805 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001806 with self.assertRaises(TypeError):
1807 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1808 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001809
1810
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001811class MemoryBIOTests(unittest.TestCase):
1812
1813 def test_read_write(self):
1814 bio = ssl.MemoryBIO()
1815 bio.write(b'foo')
1816 self.assertEqual(bio.read(), b'foo')
1817 self.assertEqual(bio.read(), b'')
1818 bio.write(b'foo')
1819 bio.write(b'bar')
1820 self.assertEqual(bio.read(), b'foobar')
1821 self.assertEqual(bio.read(), b'')
1822 bio.write(b'baz')
1823 self.assertEqual(bio.read(2), b'ba')
1824 self.assertEqual(bio.read(1), b'z')
1825 self.assertEqual(bio.read(1), b'')
1826
1827 def test_eof(self):
1828 bio = ssl.MemoryBIO()
1829 self.assertFalse(bio.eof)
1830 self.assertEqual(bio.read(), b'')
1831 self.assertFalse(bio.eof)
1832 bio.write(b'foo')
1833 self.assertFalse(bio.eof)
1834 bio.write_eof()
1835 self.assertFalse(bio.eof)
1836 self.assertEqual(bio.read(2), b'fo')
1837 self.assertFalse(bio.eof)
1838 self.assertEqual(bio.read(1), b'o')
1839 self.assertTrue(bio.eof)
1840 self.assertEqual(bio.read(), b'')
1841 self.assertTrue(bio.eof)
1842
1843 def test_pending(self):
1844 bio = ssl.MemoryBIO()
1845 self.assertEqual(bio.pending, 0)
1846 bio.write(b'foo')
1847 self.assertEqual(bio.pending, 3)
1848 for i in range(3):
1849 bio.read(1)
1850 self.assertEqual(bio.pending, 3-i-1)
1851 for i in range(3):
1852 bio.write(b'x')
1853 self.assertEqual(bio.pending, i+1)
1854 bio.read()
1855 self.assertEqual(bio.pending, 0)
1856
1857 def test_buffer_types(self):
1858 bio = ssl.MemoryBIO()
1859 bio.write(b'foo')
1860 self.assertEqual(bio.read(), b'foo')
1861 bio.write(bytearray(b'bar'))
1862 self.assertEqual(bio.read(), b'bar')
1863 bio.write(memoryview(b'baz'))
1864 self.assertEqual(bio.read(), b'baz')
1865
1866 def test_error_types(self):
1867 bio = ssl.MemoryBIO()
1868 self.assertRaises(TypeError, bio.write, 'foo')
1869 self.assertRaises(TypeError, bio.write, None)
1870 self.assertRaises(TypeError, bio.write, True)
1871 self.assertRaises(TypeError, bio.write, 1)
1872
1873
Christian Heimes9d50ab52018-02-27 10:17:30 +01001874class SSLObjectTests(unittest.TestCase):
1875 def test_private_init(self):
1876 bio = ssl.MemoryBIO()
1877 with self.assertRaisesRegex(TypeError, "public constructor"):
1878 ssl.SSLObject(bio, bio)
1879
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001880 def test_unwrap(self):
1881 client_ctx, server_ctx, hostname = testing_context()
1882 c_in = ssl.MemoryBIO()
1883 c_out = ssl.MemoryBIO()
1884 s_in = ssl.MemoryBIO()
1885 s_out = ssl.MemoryBIO()
1886 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1887 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1888
1889 # Loop on the handshake for a bit to get it settled
1890 for _ in range(5):
1891 try:
1892 client.do_handshake()
1893 except ssl.SSLWantReadError:
1894 pass
1895 if c_out.pending:
1896 s_in.write(c_out.read())
1897 try:
1898 server.do_handshake()
1899 except ssl.SSLWantReadError:
1900 pass
1901 if s_out.pending:
1902 c_in.write(s_out.read())
1903 # Now the handshakes should be complete (don't raise WantReadError)
1904 client.do_handshake()
1905 server.do_handshake()
1906
1907 # Now if we unwrap one side unilaterally, it should send close-notify
1908 # and raise WantReadError:
1909 with self.assertRaises(ssl.SSLWantReadError):
1910 client.unwrap()
1911
1912 # But server.unwrap() does not raise, because it reads the client's
1913 # close-notify:
1914 s_in.write(c_out.read())
1915 server.unwrap()
1916
1917 # And now that the client gets the server's close-notify, it doesn't
1918 # raise either.
1919 c_in.write(s_out.read())
1920 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001921
Martin Panter3840b2a2016-03-27 01:53:46 +00001922class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001923 """Tests that connect to a simple server running in the background"""
1924
1925 def setUp(self):
juhovh49fdf112021-04-18 21:11:48 +10001926 self.server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1927 self.server_context.load_cert_chain(SIGNED_CERTFILE)
1928 server = ThreadedEchoServer(context=self.server_context)
Martin Panter3840b2a2016-03-27 01:53:46 +00001929 self.server_addr = (HOST, server.port)
1930 server.__enter__()
1931 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001932
Antoine Pitrou480a1242010-04-28 21:37:09 +00001933 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001934 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001935 cert_reqs=ssl.CERT_NONE) as s:
1936 s.connect(self.server_addr)
1937 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001938 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001939
Martin Panter3840b2a2016-03-27 01:53:46 +00001940 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001941 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001942 cert_reqs=ssl.CERT_REQUIRED,
1943 ca_certs=SIGNING_CA) as s:
1944 s.connect(self.server_addr)
1945 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001946 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001947
Martin Panter3840b2a2016-03-27 01:53:46 +00001948 def test_connect_fail(self):
1949 # This should fail because we have no verification certs. Connection
1950 # failure crashes ThreadedEchoServer, so run this in an independent
1951 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001952 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001953 cert_reqs=ssl.CERT_REQUIRED)
1954 self.addCleanup(s.close)
1955 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1956 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001957
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001958 def test_connect_ex(self):
1959 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02001960 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001961 cert_reqs=ssl.CERT_REQUIRED,
1962 ca_certs=SIGNING_CA)
1963 self.addCleanup(s.close)
1964 self.assertEqual(0, s.connect_ex(self.server_addr))
1965 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001966
1967 def test_non_blocking_connect_ex(self):
1968 # Issue #11326: non-blocking connect_ex() should allow handshake
1969 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02001970 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001971 cert_reqs=ssl.CERT_REQUIRED,
1972 ca_certs=SIGNING_CA,
1973 do_handshake_on_connect=False)
1974 self.addCleanup(s.close)
1975 s.setblocking(False)
1976 rc = s.connect_ex(self.server_addr)
1977 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1978 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
1979 # Wait for connect to finish
1980 select.select([], [s], [], 5.0)
1981 # Non-blocking handshake
1982 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001983 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00001984 s.do_handshake()
1985 break
1986 except ssl.SSLWantReadError:
1987 select.select([s], [], [], 5.0)
1988 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001989 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00001990 # SSL established
1991 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001992
Antoine Pitrou152efa22010-05-16 18:19:27 +00001993 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001994 # Same as test_connect, but with a separately created context
Christian Heimes2875c602021-04-19 07:27:10 +02001995 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1996 ctx.check_hostname = False
1997 ctx.verify_mode = ssl.CERT_NONE
Martin Panter3840b2a2016-03-27 01:53:46 +00001998 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1999 s.connect(self.server_addr)
2000 self.assertEqual({}, s.getpeercert())
2001 # Same with a server hostname
2002 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2003 server_hostname="dummy") as s:
2004 s.connect(self.server_addr)
2005 ctx.verify_mode = ssl.CERT_REQUIRED
2006 # This should succeed because we specify the root cert
2007 ctx.load_verify_locations(SIGNING_CA)
2008 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2009 s.connect(self.server_addr)
2010 cert = s.getpeercert()
2011 self.assertTrue(cert)
2012
2013 def test_connect_with_context_fail(self):
2014 # This should fail because we have no verification certs. Connection
2015 # failure crashes ThreadedEchoServer, so run this in an independent
2016 # test method.
Christian Heimes2875c602021-04-19 07:27:10 +02002017 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2018 s = ctx.wrap_socket(
2019 socket.socket(socket.AF_INET),
2020 server_hostname=SIGNED_CERTFILE_HOSTNAME
2021 )
Martin Panter3840b2a2016-03-27 01:53:46 +00002022 self.addCleanup(s.close)
2023 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2024 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002025
2026 def test_connect_capath(self):
2027 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002028 # NOTE: the subject hashing algorithm has been changed between
2029 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2030 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002031 # filename) for this test to be portable across OpenSSL releases.
Christian Heimes2875c602021-04-19 07:27:10 +02002032 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002033 ctx.load_verify_locations(capath=CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002034 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2035 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002036 s.connect(self.server_addr)
2037 cert = s.getpeercert()
2038 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002039
Martin Panter3840b2a2016-03-27 01:53:46 +00002040 # Same with a bytes `capath` argument
Christian Heimes2875c602021-04-19 07:27:10 +02002041 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002042 ctx.load_verify_locations(capath=BYTES_CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002043 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2044 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002045 s.connect(self.server_addr)
2046 cert = s.getpeercert()
2047 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002048
Christian Heimesefff7062013-11-21 03:35:02 +01002049 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002050 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002051 pem = f.read()
2052 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002053 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002054 ctx.load_verify_locations(cadata=pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002055 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2056 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002057 s.connect(self.server_addr)
2058 cert = s.getpeercert()
2059 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002060
Martin Panter3840b2a2016-03-27 01:53:46 +00002061 # same with DER
Christian Heimes2875c602021-04-19 07:27:10 +02002062 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002063 ctx.load_verify_locations(cadata=der)
Christian Heimes2875c602021-04-19 07:27:10 +02002064 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2065 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002066 s.connect(self.server_addr)
2067 cert = s.getpeercert()
2068 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002069
Antoine Pitroue3220242010-04-24 11:13:53 +00002070 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2071 def test_makefile_close(self):
2072 # Issue #5238: creating a file-like object with makefile() shouldn't
2073 # delay closing the underlying "real socket" (here tested with its
2074 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002075 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002076 ss.connect(self.server_addr)
2077 fd = ss.fileno()
2078 f = ss.makefile()
2079 f.close()
2080 # The fd is still open
2081 os.read(fd, 0)
2082 # Closing the SSL socket should close the fd too
2083 ss.close()
2084 gc.collect()
2085 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002086 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002087 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002088
Antoine Pitrou480a1242010-04-28 21:37:09 +00002089 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002090 s = socket.socket(socket.AF_INET)
2091 s.connect(self.server_addr)
2092 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002093 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002094 cert_reqs=ssl.CERT_NONE,
2095 do_handshake_on_connect=False)
2096 self.addCleanup(s.close)
2097 count = 0
2098 while True:
2099 try:
2100 count += 1
2101 s.do_handshake()
2102 break
2103 except ssl.SSLWantReadError:
2104 select.select([s], [], [])
2105 except ssl.SSLWantWriteError:
2106 select.select([], [s], [])
2107 if support.verbose:
2108 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002109
Antoine Pitrou480a1242010-04-28 21:37:09 +00002110 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002111 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002112
juhovh49fdf112021-04-18 21:11:48 +10002113 def test_get_server_certificate_sni(self):
2114 host, port = self.server_addr
2115 server_names = []
2116
2117 # We store servername_cb arguments to make sure they match the host
2118 def servername_cb(ssl_sock, server_name, initial_context):
2119 server_names.append(server_name)
2120 self.server_context.set_servername_callback(servername_cb)
2121
2122 pem = ssl.get_server_certificate((host, port))
2123 if not pem:
2124 self.fail("No server certificate on %s:%s!" % (host, port))
2125
2126 pem = ssl.get_server_certificate((host, port), ca_certs=SIGNING_CA)
2127 if not pem:
2128 self.fail("No server certificate on %s:%s!" % (host, port))
2129 if support.verbose:
2130 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port, pem))
2131
2132 self.assertEqual(server_names, [host, host])
2133
Martin Panter3840b2a2016-03-27 01:53:46 +00002134 def test_get_server_certificate_fail(self):
2135 # Connection failure crashes ThreadedEchoServer, so run this in an
2136 # independent test method
2137 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002138
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002139 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002140 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002141 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2142 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002143 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002144 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2145 s.connect(self.server_addr)
2146 # Error checking can happen at instantiation or when connecting
2147 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2148 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002149 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002150 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2151 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002152
Christian Heimes9a5395a2013-06-17 15:44:12 +02002153 def test_get_ca_certs_capath(self):
2154 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002155 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002156 ctx.load_verify_locations(capath=CAPATH)
2157 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002158 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2159 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002160 s.connect(self.server_addr)
2161 cert = s.getpeercert()
2162 self.assertTrue(cert)
2163 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002164
Christian Heimes8e7f3942013-12-05 07:41:08 +01002165 def test_context_setget(self):
2166 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002167 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2168 ctx1.load_verify_locations(capath=CAPATH)
2169 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2170 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002171 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002172 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002173 ss.connect(self.server_addr)
2174 self.assertIs(ss.context, ctx1)
2175 self.assertIs(ss._sslobj.context, ctx1)
2176 ss.context = ctx2
2177 self.assertIs(ss.context, ctx2)
2178 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002179
2180 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2181 # A simple IO loop. Call func(*args) depending on the error we get
2182 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002183 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002184 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002185 count = 0
2186 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002187 if time.monotonic() > deadline:
2188 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002189 errno = None
2190 count += 1
2191 try:
2192 ret = func(*args)
2193 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002194 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002195 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002196 raise
2197 errno = e.errno
2198 # Get any data from the outgoing BIO irrespective of any error, and
2199 # send it to the socket.
2200 buf = outgoing.read()
2201 sock.sendall(buf)
2202 # If there's no error, we're done. For WANT_READ, we need to get
2203 # data from the socket and put it in the incoming BIO.
2204 if errno is None:
2205 break
2206 elif errno == ssl.SSL_ERROR_WANT_READ:
2207 buf = sock.recv(32768)
2208 if buf:
2209 incoming.write(buf)
2210 else:
2211 incoming.write_eof()
2212 if support.verbose:
2213 sys.stdout.write("Needed %d calls to complete %s().\n"
2214 % (count, func.__name__))
2215 return ret
2216
Martin Panter3840b2a2016-03-27 01:53:46 +00002217 def test_bio_handshake(self):
2218 sock = socket.socket(socket.AF_INET)
2219 self.addCleanup(sock.close)
2220 sock.connect(self.server_addr)
2221 incoming = ssl.MemoryBIO()
2222 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002223 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2224 self.assertTrue(ctx.check_hostname)
2225 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002226 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002227 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2228 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002229 self.assertIs(sslobj._sslobj.owner, sslobj)
2230 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002231 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002232 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002233 self.assertRaises(ValueError, sslobj.getpeercert)
2234 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2235 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2236 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2237 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002238 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002239 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002240 self.assertTrue(sslobj.getpeercert())
2241 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2242 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2243 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002244 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002245 except ssl.SSLSyscallError:
2246 # If the server shuts down the TCP connection without sending a
2247 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2248 pass
2249 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2250
2251 def test_bio_read_write_data(self):
2252 sock = socket.socket(socket.AF_INET)
2253 self.addCleanup(sock.close)
2254 sock.connect(self.server_addr)
2255 incoming = ssl.MemoryBIO()
2256 outgoing = ssl.MemoryBIO()
Christian Heimes2875c602021-04-19 07:27:10 +02002257 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2258 ctx.check_hostname = False
Martin Panter3840b2a2016-03-27 01:53:46 +00002259 ctx.verify_mode = ssl.CERT_NONE
2260 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2261 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2262 req = b'FOO\n'
2263 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2264 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2265 self.assertEqual(buf, b'foo\n')
2266 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002267
2268
Martin Panter3840b2a2016-03-27 01:53:46 +00002269class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002270
Martin Panter3840b2a2016-03-27 01:53:46 +00002271 def test_timeout_connect_ex(self):
2272 # Issue #12065: on a timeout, connect_ex() should return the original
2273 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002274 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002275 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002276 cert_reqs=ssl.CERT_REQUIRED,
2277 do_handshake_on_connect=False)
2278 self.addCleanup(s.close)
2279 s.settimeout(0.0000001)
2280 rc = s.connect_ex((REMOTE_HOST, 443))
2281 if rc == 0:
2282 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002283 elif rc == errno.ENETUNREACH:
2284 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002285 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2286
Serhiy Storchaka16994912020-04-25 10:06:29 +03002287 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002288 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002289 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002290 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2291 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2292
Martin Panter3840b2a2016-03-27 01:53:46 +00002293
2294def _test_get_server_certificate(test, host, port, cert=None):
2295 pem = ssl.get_server_certificate((host, port))
2296 if not pem:
2297 test.fail("No server certificate on %s:%s!" % (host, port))
2298
2299 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2300 if not pem:
2301 test.fail("No server certificate on %s:%s!" % (host, port))
2302 if support.verbose:
2303 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2304
2305def _test_get_server_certificate_fail(test, host, port):
2306 try:
2307 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2308 except ssl.SSLError as x:
2309 #should fail
2310 if support.verbose:
2311 sys.stdout.write("%s\n" % x)
2312 else:
2313 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2314
2315
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002316from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002317
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002318class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002319
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002320 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002321
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002322 """A mildly complicated class, because we want it to work both
2323 with and without the SSL wrapper around the socket connection, so
2324 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002325
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002326 def __init__(self, server, connsock, addr):
2327 self.server = server
2328 self.running = False
2329 self.sock = connsock
2330 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002331 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002332 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002333 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002334 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002335
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002336 def wrap_conn(self):
2337 try:
2338 self.sslconn = self.server.context.wrap_socket(
2339 self.sock, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002340 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002341 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002342 # We treat ConnectionResetError as though it were an
2343 # SSLError - OpenSSL on Ubuntu abruptly closes the
2344 # connection when asked to use an unsupported protocol.
2345 #
Christian Heimes529525f2018-05-23 22:24:45 +02002346 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2347 # tries to send session tickets after handshake.
2348 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002349 #
2350 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2351 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002352 self.server.conn_errors.append(str(e))
2353 if self.server.chatty:
2354 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2355 self.running = False
2356 self.close()
2357 return False
2358 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002359 # OSError may occur with wrong protocols, e.g. both
2360 # sides use PROTOCOL_TLS_SERVER.
2361 #
2362 # XXX Various errors can have happened here, for example
2363 # a mismatching protocol version, an invalid certificate,
2364 # or a low-level bug. This should be made more discriminating.
2365 #
2366 # bpo-31323: Store the exception as string to prevent
2367 # a reference leak: server -> conn_errors -> exception
2368 # -> traceback -> self (ConnectionHandler) -> server
2369 self.server.conn_errors.append(str(e))
2370 if self.server.chatty:
2371 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2372 self.running = False
2373 self.server.stop()
2374 self.close()
2375 return False
2376 else:
2377 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2378 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2379 cert = self.sslconn.getpeercert()
2380 if support.verbose and self.server.chatty:
2381 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2382 cert_binary = self.sslconn.getpeercert(True)
2383 if support.verbose and self.server.chatty:
2384 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2385 cipher = self.sslconn.cipher()
2386 if support.verbose and self.server.chatty:
2387 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002388 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002389
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002390 def read(self):
2391 if self.sslconn:
2392 return self.sslconn.read()
2393 else:
2394 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002395
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002396 def write(self, bytes):
2397 if self.sslconn:
2398 return self.sslconn.write(bytes)
2399 else:
2400 return self.sock.send(bytes)
2401
2402 def close(self):
2403 if self.sslconn:
2404 self.sslconn.close()
2405 else:
2406 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002407
Antoine Pitrou480a1242010-04-28 21:37:09 +00002408 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002409 self.running = True
2410 if not self.server.starttls_server:
2411 if not self.wrap_conn():
2412 return
2413 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002414 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002415 msg = self.read()
2416 stripped = msg.strip()
2417 if not stripped:
2418 # eof, so quit this handler
2419 self.running = False
2420 try:
2421 self.sock = self.sslconn.unwrap()
2422 except OSError:
2423 # Many tests shut the TCP connection down
2424 # without an SSL shutdown. This causes
2425 # unwrap() to raise OSError with errno=0!
2426 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002427 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002428 self.sslconn = None
2429 self.close()
2430 elif stripped == b'over':
2431 if support.verbose and self.server.connectionchatty:
2432 sys.stdout.write(" server: client closed connection\n")
2433 self.close()
2434 return
2435 elif (self.server.starttls_server and
2436 stripped == b'STARTTLS'):
2437 if support.verbose and self.server.connectionchatty:
2438 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2439 self.write(b"OK\n")
2440 if not self.wrap_conn():
2441 return
2442 elif (self.server.starttls_server and self.sslconn
2443 and stripped == b'ENDTLS'):
2444 if support.verbose and self.server.connectionchatty:
2445 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2446 self.write(b"OK\n")
2447 self.sock = self.sslconn.unwrap()
2448 self.sslconn = None
2449 if support.verbose and self.server.connectionchatty:
2450 sys.stdout.write(" server: connection is now unencrypted...\n")
2451 elif stripped == b'CB tls-unique':
2452 if support.verbose and self.server.connectionchatty:
2453 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2454 data = self.sslconn.get_channel_binding("tls-unique")
2455 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002456 elif stripped == b'PHA':
2457 if support.verbose and self.server.connectionchatty:
2458 sys.stdout.write(" server: initiating post handshake auth\n")
2459 try:
2460 self.sslconn.verify_client_post_handshake()
2461 except ssl.SSLError as e:
2462 self.write(repr(e).encode("us-ascii") + b"\n")
2463 else:
2464 self.write(b"OK\n")
2465 elif stripped == b'HASCERT':
2466 if self.sslconn.getpeercert() is not None:
2467 self.write(b'TRUE\n')
2468 else:
2469 self.write(b'FALSE\n')
2470 elif stripped == b'GETCERT':
2471 cert = self.sslconn.getpeercert()
2472 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002473 else:
2474 if (support.verbose and
2475 self.server.connectionchatty):
2476 ctype = (self.sslconn and "encrypted") or "unencrypted"
2477 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2478 % (msg, ctype, msg.lower(), ctype))
2479 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002480 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002481 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2482 # when connection is not shut down gracefully.
2483 if self.server.chatty and support.verbose:
2484 sys.stdout.write(
2485 " Connection reset by peer: {}\n".format(
2486 self.addr)
2487 )
2488 self.close()
2489 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002490 except ssl.SSLError as err:
2491 # On Windows sometimes test_pha_required_nocert receives the
2492 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2493 # before the 'tlsv13 alert certificate required' exception.
2494 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2495 # is received test_pha_required_nocert fails with ConnectionResetError
2496 # because the underlying socket is closed
2497 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2498 if self.server.chatty and support.verbose:
2499 sys.stdout.write(err.args[1])
2500 # test_pha_required_nocert is expecting this exception
2501 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002502 except OSError:
2503 if self.server.chatty:
2504 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002505 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002506 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002507
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002508 # normally, we'd just stop here, but for the test
2509 # harness, we want to stop the server
2510 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002511
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002512 def __init__(self, certificate=None, ssl_version=None,
2513 certreqs=None, cacerts=None,
2514 chatty=True, connectionchatty=False, starttls_server=False,
Christian Heimes2875c602021-04-19 07:27:10 +02002515 alpn_protocols=None,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002516 ciphers=None, context=None):
2517 if context:
2518 self.context = context
2519 else:
2520 self.context = ssl.SSLContext(ssl_version
2521 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002522 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002523 self.context.verify_mode = (certreqs if certreqs is not None
2524 else ssl.CERT_NONE)
2525 if cacerts:
2526 self.context.load_verify_locations(cacerts)
2527 if certificate:
2528 self.context.load_cert_chain(certificate)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002529 if alpn_protocols:
2530 self.context.set_alpn_protocols(alpn_protocols)
2531 if ciphers:
2532 self.context.set_ciphers(ciphers)
2533 self.chatty = chatty
2534 self.connectionchatty = connectionchatty
2535 self.starttls_server = starttls_server
2536 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002537 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002538 self.flag = None
2539 self.active = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002540 self.selected_alpn_protocols = []
2541 self.shared_ciphers = []
2542 self.conn_errors = []
2543 threading.Thread.__init__(self)
2544 self.daemon = True
2545
2546 def __enter__(self):
2547 self.start(threading.Event())
2548 self.flag.wait()
2549 return self
2550
2551 def __exit__(self, *args):
2552 self.stop()
2553 self.join()
2554
2555 def start(self, flag=None):
2556 self.flag = flag
2557 threading.Thread.start(self)
2558
2559 def run(self):
2560 self.sock.settimeout(0.05)
2561 self.sock.listen()
2562 self.active = True
2563 if self.flag:
2564 # signal an event
2565 self.flag.set()
2566 while self.active:
2567 try:
2568 newconn, connaddr = self.sock.accept()
2569 if support.verbose and self.chatty:
2570 sys.stdout.write(' server: new connection from '
2571 + repr(connaddr) + '\n')
2572 handler = self.ConnectionHandler(self, newconn, connaddr)
2573 handler.start()
2574 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002575 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002576 pass
2577 except KeyboardInterrupt:
2578 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002579 except BaseException as e:
2580 if support.verbose and self.chatty:
2581 sys.stdout.write(
2582 ' connection handling failed: ' + repr(e) + '\n')
2583
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002584 self.sock.close()
2585
2586 def stop(self):
2587 self.active = False
2588
2589class AsyncoreEchoServer(threading.Thread):
2590
2591 # this one's based on asyncore.dispatcher
2592
2593 class EchoServer (asyncore.dispatcher):
2594
2595 class ConnectionHandler(asyncore.dispatcher_with_send):
2596
2597 def __init__(self, conn, certfile):
2598 self.socket = test_wrap_socket(conn, server_side=True,
2599 certfile=certfile,
2600 do_handshake_on_connect=False)
2601 asyncore.dispatcher_with_send.__init__(self, self.socket)
2602 self._ssl_accepting = True
2603 self._do_ssl_handshake()
2604
2605 def readable(self):
2606 if isinstance(self.socket, ssl.SSLSocket):
2607 while self.socket.pending() > 0:
2608 self.handle_read_event()
2609 return True
2610
2611 def _do_ssl_handshake(self):
2612 try:
2613 self.socket.do_handshake()
2614 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2615 return
2616 except ssl.SSLEOFError:
2617 return self.handle_close()
2618 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002619 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002620 except OSError as err:
2621 if err.args[0] == errno.ECONNABORTED:
2622 return self.handle_close()
2623 else:
2624 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002625
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002626 def handle_read(self):
2627 if self._ssl_accepting:
2628 self._do_ssl_handshake()
2629 else:
2630 data = self.recv(1024)
2631 if support.verbose:
2632 sys.stdout.write(" server: read %s from client\n" % repr(data))
2633 if not data:
2634 self.close()
2635 else:
2636 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002637
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002638 def handle_close(self):
2639 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002640 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002641 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002642
2643 def handle_error(self):
2644 raise
2645
Trent Nelson78520002008-04-10 20:54:35 +00002646 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002647 self.certfile = certfile
2648 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002649 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002650 asyncore.dispatcher.__init__(self, sock)
2651 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002652
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002653 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002654 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002655 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2656 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002657
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002658 def handle_error(self):
2659 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002660
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002661 def __init__(self, certfile):
2662 self.flag = None
2663 self.active = False
2664 self.server = self.EchoServer(certfile)
2665 self.port = self.server.port
2666 threading.Thread.__init__(self)
2667 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002668
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002669 def __str__(self):
2670 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002671
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002672 def __enter__(self):
2673 self.start(threading.Event())
2674 self.flag.wait()
2675 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002676
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002677 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002678 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002679 sys.stdout.write(" cleanup: stopping server.\n")
2680 self.stop()
2681 if support.verbose:
2682 sys.stdout.write(" cleanup: joining server thread.\n")
2683 self.join()
2684 if support.verbose:
2685 sys.stdout.write(" cleanup: successfully joined.\n")
2686 # make sure that ConnectionHandler is removed from socket_map
2687 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002688
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002689 def start (self, flag=None):
2690 self.flag = flag
2691 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002692
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002693 def run(self):
2694 self.active = True
2695 if self.flag:
2696 self.flag.set()
2697 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002698 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002699 asyncore.loop(1)
2700 except:
2701 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002702
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002703 def stop(self):
2704 self.active = False
2705 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002706
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002707def server_params_test(client_context, server_context, indata=b"FOO\n",
2708 chatty=True, connectionchatty=False, sni_name=None,
2709 session=None):
2710 """
2711 Launch a server, connect a client to it and try various reads
2712 and writes.
2713 """
2714 stats = {}
2715 server = ThreadedEchoServer(context=server_context,
2716 chatty=chatty,
2717 connectionchatty=False)
2718 with server:
2719 with client_context.wrap_socket(socket.socket(),
2720 server_hostname=sni_name, session=session) as s:
2721 s.connect((HOST, server.port))
2722 for arg in [indata, bytearray(indata), memoryview(indata)]:
2723 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002724 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002725 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002726 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002727 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002728 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002729 if connectionchatty:
2730 if support.verbose:
2731 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002732 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002733 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002734 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2735 % (outdata[:20], len(outdata),
2736 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002737 s.write(b"over\n")
2738 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002739 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002740 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002741 stats.update({
2742 'compression': s.compression(),
2743 'cipher': s.cipher(),
2744 'peercert': s.getpeercert(),
2745 'client_alpn_protocol': s.selected_alpn_protocol(),
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002746 'version': s.version(),
2747 'session_reused': s.session_reused,
2748 'session': s.session,
2749 })
2750 s.close()
2751 stats['server_alpn_protocols'] = server.selected_alpn_protocols
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002752 stats['server_shared_ciphers'] = server.shared_ciphers
2753 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002754
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002755def try_protocol_combo(server_protocol, client_protocol, expect_success,
2756 certsreqs=None, server_options=0, client_options=0):
2757 """
2758 Try to SSL-connect using *client_protocol* to *server_protocol*.
2759 If *expect_success* is true, assert that the connection succeeds,
2760 if it's false, assert that the connection fails.
2761 Also, if *expect_success* is a string, assert that it is the protocol
2762 version actually used by the connection.
2763 """
2764 if certsreqs is None:
2765 certsreqs = ssl.CERT_NONE
2766 certtype = {
2767 ssl.CERT_NONE: "CERT_NONE",
2768 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2769 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2770 }[certsreqs]
2771 if support.verbose:
2772 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2773 sys.stdout.write(formatstr %
2774 (ssl.get_protocol_name(client_protocol),
2775 ssl.get_protocol_name(server_protocol),
2776 certtype))
Christian Heimes2875c602021-04-19 07:27:10 +02002777
2778 with warnings_helper.check_warnings():
2779 # ignore Deprecation warnings
2780 client_context = ssl.SSLContext(client_protocol)
2781 client_context.options |= client_options
2782 server_context = ssl.SSLContext(server_protocol)
2783 server_context.options |= server_options
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002784
Victor Stinner3ef63442019-02-19 18:06:03 +01002785 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2786 if (min_version is not None
Christian Heimes2875c602021-04-19 07:27:10 +02002787 # SSLContext.minimum_version is only available on recent OpenSSL
2788 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2789 and hasattr(server_context, 'minimum_version')
2790 and server_protocol == ssl.PROTOCOL_TLS
2791 and server_context.minimum_version > min_version
2792 ):
Victor Stinner3ef63442019-02-19 18:06:03 +01002793 # If OpenSSL configuration is strict and requires more recent TLS
2794 # version, we have to change the minimum to test old TLS versions.
Christian Heimes2875c602021-04-19 07:27:10 +02002795 with warnings_helper.check_warnings():
2796 server_context.minimum_version = min_version
Victor Stinner3ef63442019-02-19 18:06:03 +01002797
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002798 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2799 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2800 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002801 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002802 client_context.set_ciphers("ALL")
2803
Christian Heimesf6c6b582021-03-18 23:06:50 +01002804 seclevel_workaround(server_context, client_context)
2805
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002806 for ctx in (client_context, server_context):
2807 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002808 ctx.load_cert_chain(SIGNED_CERTFILE)
2809 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002810 try:
2811 stats = server_params_test(client_context, server_context,
2812 chatty=False, connectionchatty=False)
2813 # Protocol mismatch can result in either an SSLError, or a
2814 # "Connection reset by peer" error.
2815 except ssl.SSLError:
2816 if expect_success:
2817 raise
2818 except OSError as e:
2819 if expect_success or e.errno != errno.ECONNRESET:
2820 raise
2821 else:
2822 if not expect_success:
2823 raise AssertionError(
2824 "Client protocol %s succeeded with server protocol %s!"
2825 % (ssl.get_protocol_name(client_protocol),
2826 ssl.get_protocol_name(server_protocol)))
2827 elif (expect_success is not True
2828 and expect_success != stats['version']):
2829 raise AssertionError("version mismatch: expected %r, got %r"
2830 % (expect_success, stats['version']))
2831
2832
2833class ThreadedTests(unittest.TestCase):
2834
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002835 def test_echo(self):
2836 """Basic test of an SSL client connecting to a server"""
2837 if support.verbose:
2838 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002839
Christian Heimesa170fa12017-09-15 20:27:30 +02002840 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002841
2842 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2843 server_params_test(client_context=client_context,
2844 server_context=server_context,
2845 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002846 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002847
2848 client_context.check_hostname = False
2849 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2850 with self.assertRaises(ssl.SSLError) as e:
2851 server_params_test(client_context=server_context,
2852 server_context=client_context,
2853 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002854 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002855 self.assertIn('called a function you should not call',
2856 str(e.exception))
2857
2858 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2859 with self.assertRaises(ssl.SSLError) as e:
2860 server_params_test(client_context=server_context,
2861 server_context=server_context,
2862 chatty=True, connectionchatty=True)
2863 self.assertIn('called a function you should not call',
2864 str(e.exception))
2865
2866 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2867 with self.assertRaises(ssl.SSLError) as e:
2868 server_params_test(client_context=server_context,
2869 server_context=client_context,
2870 chatty=True, connectionchatty=True)
2871 self.assertIn('called a function you should not call',
2872 str(e.exception))
2873
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002874 def test_getpeercert(self):
2875 if support.verbose:
2876 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002877
2878 client_context, server_context, hostname = testing_context()
2879 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002880 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002881 with client_context.wrap_socket(socket.socket(),
2882 do_handshake_on_connect=False,
2883 server_hostname=hostname) as s:
2884 s.connect((HOST, server.port))
2885 # getpeercert() raise ValueError while the handshake isn't
2886 # done.
2887 with self.assertRaises(ValueError):
2888 s.getpeercert()
2889 s.do_handshake()
2890 cert = s.getpeercert()
2891 self.assertTrue(cert, "Can't get peer certificate.")
2892 cipher = s.cipher()
2893 if support.verbose:
2894 sys.stdout.write(pprint.pformat(cert) + '\n')
2895 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2896 if 'subject' not in cert:
2897 self.fail("No subject field in certificate: %s." %
2898 pprint.pformat(cert))
2899 if ((('organizationName', 'Python Software Foundation'),)
2900 not in cert['subject']):
2901 self.fail(
2902 "Missing or invalid 'organizationName' field in certificate subject; "
2903 "should be 'Python Software Foundation'.")
2904 self.assertIn('notBefore', cert)
2905 self.assertIn('notAfter', cert)
2906 before = ssl.cert_time_to_seconds(cert['notBefore'])
2907 after = ssl.cert_time_to_seconds(cert['notAfter'])
2908 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002909
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002910 def test_crl_check(self):
2911 if support.verbose:
2912 sys.stdout.write("\n")
2913
Christian Heimesa170fa12017-09-15 20:27:30 +02002914 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002915
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002916 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002917 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002918
2919 # VERIFY_DEFAULT should pass
2920 server = ThreadedEchoServer(context=server_context, chatty=True)
2921 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002922 with client_context.wrap_socket(socket.socket(),
2923 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002924 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002925 cert = s.getpeercert()
2926 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002927
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002928 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002929 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002930
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002931 server = ThreadedEchoServer(context=server_context, chatty=True)
2932 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002933 with client_context.wrap_socket(socket.socket(),
2934 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002935 with self.assertRaisesRegex(ssl.SSLError,
2936 "certificate verify failed"):
2937 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002938
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002939 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002940 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002941
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002942 server = ThreadedEchoServer(context=server_context, chatty=True)
2943 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002944 with client_context.wrap_socket(socket.socket(),
2945 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002946 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002947 cert = s.getpeercert()
2948 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002949
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002950 def test_check_hostname(self):
2951 if support.verbose:
2952 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002953
Christian Heimesa170fa12017-09-15 20:27:30 +02002954 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002955
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002956 # correct hostname should verify
2957 server = ThreadedEchoServer(context=server_context, chatty=True)
2958 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002959 with client_context.wrap_socket(socket.socket(),
2960 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002961 s.connect((HOST, server.port))
2962 cert = s.getpeercert()
2963 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002964
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002965 # incorrect hostname should raise an exception
2966 server = ThreadedEchoServer(context=server_context, chatty=True)
2967 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002968 with client_context.wrap_socket(socket.socket(),
2969 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01002970 with self.assertRaisesRegex(
2971 ssl.CertificateError,
2972 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002973 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002974
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002975 # missing server_hostname arg should cause an exception, too
2976 server = ThreadedEchoServer(context=server_context, chatty=True)
2977 with server:
2978 with socket.socket() as s:
2979 with self.assertRaisesRegex(ValueError,
2980 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02002981 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002982
Christian Heimesb467d9a2021-04-17 10:07:19 +02002983 @unittest.skipUnless(
2984 ssl.HAS_NEVER_CHECK_COMMON_NAME, "test requires hostname_checks_common_name"
2985 )
2986 def test_hostname_checks_common_name(self):
2987 client_context, server_context, hostname = testing_context()
2988 assert client_context.hostname_checks_common_name
2989 client_context.hostname_checks_common_name = False
2990
2991 # default cert has a SAN
2992 server = ThreadedEchoServer(context=server_context, chatty=True)
2993 with server:
2994 with client_context.wrap_socket(socket.socket(),
2995 server_hostname=hostname) as s:
2996 s.connect((HOST, server.port))
2997
2998 client_context, server_context, hostname = testing_context(NOSANFILE)
2999 client_context.hostname_checks_common_name = False
3000 server = ThreadedEchoServer(context=server_context, chatty=True)
3001 with server:
3002 with client_context.wrap_socket(socket.socket(),
3003 server_hostname=hostname) as s:
3004 with self.assertRaises(ssl.SSLCertVerificationError):
3005 s.connect((HOST, server.port))
3006
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003007 def test_ecc_cert(self):
3008 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3009 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003010 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003011 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3012
3013 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3014 # load ECC cert
3015 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3016
3017 # correct hostname should verify
3018 server = ThreadedEchoServer(context=server_context, chatty=True)
3019 with server:
3020 with client_context.wrap_socket(socket.socket(),
3021 server_hostname=hostname) as s:
3022 s.connect((HOST, server.port))
3023 cert = s.getpeercert()
3024 self.assertTrue(cert, "Can't get peer certificate.")
3025 cipher = s.cipher()[0].split('-')
3026 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3027
3028 def test_dual_rsa_ecc(self):
3029 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3030 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003031 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3032 # algorithms.
3033 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003034 # only ECDSA certs
3035 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3036 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3037
3038 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3039 # load ECC and RSA key/cert pairs
3040 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3041 server_context.load_cert_chain(SIGNED_CERTFILE)
3042
3043 # correct hostname should verify
3044 server = ThreadedEchoServer(context=server_context, chatty=True)
3045 with server:
3046 with client_context.wrap_socket(socket.socket(),
3047 server_hostname=hostname) as s:
3048 s.connect((HOST, server.port))
3049 cert = s.getpeercert()
3050 self.assertTrue(cert, "Can't get peer certificate.")
3051 cipher = s.cipher()[0].split('-')
3052 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3053
Christian Heimes66e57422018-01-29 14:25:13 +01003054 def test_check_hostname_idn(self):
3055 if support.verbose:
3056 sys.stdout.write("\n")
3057
Christian Heimes11a14932018-02-24 02:35:08 +01003058 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003059 server_context.load_cert_chain(IDNSANSFILE)
3060
Christian Heimes11a14932018-02-24 02:35:08 +01003061 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003062 context.verify_mode = ssl.CERT_REQUIRED
3063 context.check_hostname = True
3064 context.load_verify_locations(SIGNING_CA)
3065
3066 # correct hostname should verify, when specified in several
3067 # different ways
3068 idn_hostnames = [
3069 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003070 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003071 ('xn--knig-5qa.idn.pythontest.net',
3072 'xn--knig-5qa.idn.pythontest.net'),
3073 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003074 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003075
3076 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003077 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003078 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3079 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3080 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003081 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3082
3083 # ('königsgäßchen.idna2008.pythontest.net',
3084 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3085 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3086 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3087 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3088 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3089
Christian Heimes66e57422018-01-29 14:25:13 +01003090 ]
3091 for server_hostname, expected_hostname in idn_hostnames:
3092 server = ThreadedEchoServer(context=server_context, chatty=True)
3093 with server:
3094 with context.wrap_socket(socket.socket(),
3095 server_hostname=server_hostname) as s:
3096 self.assertEqual(s.server_hostname, expected_hostname)
3097 s.connect((HOST, server.port))
3098 cert = s.getpeercert()
3099 self.assertEqual(s.server_hostname, expected_hostname)
3100 self.assertTrue(cert, "Can't get peer certificate.")
3101
Christian Heimes66e57422018-01-29 14:25:13 +01003102 # incorrect hostname should raise an exception
3103 server = ThreadedEchoServer(context=server_context, chatty=True)
3104 with server:
3105 with context.wrap_socket(socket.socket(),
3106 server_hostname="python.example.org") as s:
3107 with self.assertRaises(ssl.CertificateError):
3108 s.connect((HOST, server.port))
3109
Christian Heimes529525f2018-05-23 22:24:45 +02003110 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003111 """Connecting when the server rejects the client's certificate
3112
3113 Launch a server with CERT_REQUIRED, and check that trying to
3114 connect to it with a wrong client certificate fails.
3115 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003116 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003117 # load client cert that is not signed by trusted CA
3118 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003119 # require TLS client authentication
3120 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003121 # TLS 1.3 has different handshake
3122 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003123
3124 server = ThreadedEchoServer(
3125 context=server_context, chatty=True, connectionchatty=True,
3126 )
3127
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003128 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003129 client_context.wrap_socket(socket.socket(),
3130 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003131 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003132 # Expect either an SSL error about the server rejecting
3133 # the connection, or a low-level connection reset (which
3134 # sometimes happens on Windows)
3135 s.connect((HOST, server.port))
3136 except ssl.SSLError as e:
3137 if support.verbose:
3138 sys.stdout.write("\nSSLError is %r\n" % e)
3139 except OSError as e:
3140 if e.errno != errno.ECONNRESET:
3141 raise
3142 if support.verbose:
3143 sys.stdout.write("\nsocket.error is %r\n" % e)
3144 else:
3145 self.fail("Use of invalid cert should have failed!")
3146
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003147 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003148 def test_wrong_cert_tls13(self):
3149 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003150 # load client cert that is not signed by trusted CA
3151 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003152 server_context.verify_mode = ssl.CERT_REQUIRED
3153 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3154 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3155
3156 server = ThreadedEchoServer(
3157 context=server_context, chatty=True, connectionchatty=True,
3158 )
3159 with server, \
3160 client_context.wrap_socket(socket.socket(),
3161 server_hostname=hostname) as s:
3162 # TLS 1.3 perform client cert exchange after handshake
3163 s.connect((HOST, server.port))
3164 try:
3165 s.write(b'data')
Christian Heimese0472392021-04-23 20:03:25 +02003166 s.read(1000)
3167 s.write(b'should have failed already')
3168 s.read(1000)
Christian Heimes529525f2018-05-23 22:24:45 +02003169 except ssl.SSLError as e:
3170 if support.verbose:
3171 sys.stdout.write("\nSSLError is %r\n" % e)
3172 except OSError as e:
3173 if e.errno != errno.ECONNRESET:
3174 raise
3175 if support.verbose:
3176 sys.stdout.write("\nsocket.error is %r\n" % e)
3177 else:
Christian Heimese0472392021-04-23 20:03:25 +02003178 if sys.platform == "win32":
3179 self.skipTest(
3180 "Ignoring failed test_wrong_cert_tls13 test case. "
3181 "The test is flaky on Windows, see bpo-43921."
3182 )
3183 else:
3184 self.fail("Use of invalid cert should have failed!")
Christian Heimes529525f2018-05-23 22:24:45 +02003185
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003186 def test_rude_shutdown(self):
3187 """A brutal shutdown of an SSL server should raise an OSError
3188 in the client when attempting handshake.
3189 """
3190 listener_ready = threading.Event()
3191 listener_gone = threading.Event()
3192
3193 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003194 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003195
3196 # `listener` runs in a thread. It sits in an accept() until
3197 # the main thread connects. Then it rudely closes the socket,
3198 # and sets Event `listener_gone` to let the main thread know
3199 # the socket is gone.
3200 def listener():
3201 s.listen()
3202 listener_ready.set()
3203 newsock, addr = s.accept()
3204 newsock.close()
3205 s.close()
3206 listener_gone.set()
3207
3208 def connector():
3209 listener_ready.wait()
3210 with socket.socket() as c:
3211 c.connect((HOST, port))
3212 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003213 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003214 ssl_sock = test_wrap_socket(c)
3215 except OSError:
3216 pass
3217 else:
3218 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003219
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003220 t = threading.Thread(target=listener)
3221 t.start()
3222 try:
3223 connector()
3224 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003225 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003226
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003227 def test_ssl_cert_verify_error(self):
3228 if support.verbose:
3229 sys.stdout.write("\n")
3230
3231 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3232 server_context.load_cert_chain(SIGNED_CERTFILE)
3233
3234 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3235
3236 server = ThreadedEchoServer(context=server_context, chatty=True)
3237 with server:
3238 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003239 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003240 try:
3241 s.connect((HOST, server.port))
3242 except ssl.SSLError as e:
3243 msg = 'unable to get local issuer certificate'
3244 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3245 self.assertEqual(e.verify_code, 20)
3246 self.assertEqual(e.verify_message, msg)
3247 self.assertIn(msg, repr(e))
3248 self.assertIn('certificate verify failed', repr(e))
3249
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003250 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003251 def test_protocol_sslv2(self):
3252 """Connecting to an SSLv2 server with various client options"""
3253 if support.verbose:
3254 sys.stdout.write("\n")
3255 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3256 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3257 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003258 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003259 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003260 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3261 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3262 # SSLv23 client with specific SSL options
Christian Heimesa170fa12017-09-15 20:27:30 +02003263 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003264 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003265 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003266 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003267
Christian Heimesa170fa12017-09-15 20:27:30 +02003268 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003269 """Connecting to an SSLv23 server with various client options"""
3270 if support.verbose:
3271 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003272 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003273 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003274 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003275 except OSError as x:
3276 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3277 if support.verbose:
3278 sys.stdout.write(
3279 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3280 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003281 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003282 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3283 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003284 if has_tls_version('TLSv1'):
3285 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003286
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003287 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003288 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3289 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003290 if has_tls_version('TLSv1'):
3291 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003292
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003293 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003294 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3295 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003296 if has_tls_version('TLSv1'):
3297 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003298
3299 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003300 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003301 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003302 server_options=ssl.OP_NO_SSLv3)
3303 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003304 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003305 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003306 if has_tls_version('TLSv1'):
3307 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3308 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003309
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003310 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003311 def test_protocol_sslv3(self):
3312 """Connecting to an SSLv3 server with various client options"""
3313 if support.verbose:
3314 sys.stdout.write("\n")
3315 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3316 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3317 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003318 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003319 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003320 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003321 client_options=ssl.OP_NO_SSLv3)
3322 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003323
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003324 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003325 def test_protocol_tlsv1(self):
3326 """Connecting to a TLSv1 server with various client options"""
3327 if support.verbose:
3328 sys.stdout.write("\n")
3329 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3330 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3331 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', 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_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003334 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003335 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003336 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003337 client_options=ssl.OP_NO_TLSv1)
3338
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003339 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003340 def test_protocol_tlsv1_1(self):
3341 """Connecting to a TLSv1.1 server with various client options.
3342 Testing against older TLS versions."""
3343 if support.verbose:
3344 sys.stdout.write("\n")
3345 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003346 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003347 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003348 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003349 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003350 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003351 client_options=ssl.OP_NO_TLSv1_1)
3352
Christian Heimesa170fa12017-09-15 20:27:30 +02003353 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003354 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3355 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003356
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003357 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003358 def test_protocol_tlsv1_2(self):
3359 """Connecting to a TLSv1.2 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_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3364 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3365 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003366 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003367 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003368 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003369 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003370 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003371 client_options=ssl.OP_NO_TLSv1_2)
3372
Christian Heimesa170fa12017-09-15 20:27:30 +02003373 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003374 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3375 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3376 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3377 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3378
3379 def test_starttls(self):
3380 """Switching from clear text to encrypted and back again."""
3381 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3382
3383 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003384 starttls_server=True,
3385 chatty=True,
3386 connectionchatty=True)
3387 wrapped = False
3388 with server:
3389 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003390 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003391 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003392 if support.verbose:
3393 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003394 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003395 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003396 sys.stdout.write(
3397 " client: sending %r...\n" % indata)
3398 if wrapped:
3399 conn.write(indata)
3400 outdata = conn.read()
3401 else:
3402 s.send(indata)
3403 outdata = s.recv(1024)
3404 msg = outdata.strip().lower()
3405 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3406 # STARTTLS ok, switch to secure mode
3407 if support.verbose:
3408 sys.stdout.write(
3409 " client: read %r from server, starting TLS...\n"
3410 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003411 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003412 wrapped = True
3413 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3414 # ENDTLS ok, switch back to clear text
3415 if support.verbose:
3416 sys.stdout.write(
3417 " client: read %r from server, ending TLS...\n"
3418 % msg)
3419 s = conn.unwrap()
3420 wrapped = False
3421 else:
3422 if support.verbose:
3423 sys.stdout.write(
3424 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003425 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003426 sys.stdout.write(" client: closing connection.\n")
3427 if wrapped:
3428 conn.write(b"over\n")
3429 else:
3430 s.send(b"over\n")
3431 if wrapped:
3432 conn.close()
3433 else:
3434 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003435
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003436 def test_socketserver(self):
3437 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003438 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003439 # try to connect
3440 if support.verbose:
3441 sys.stdout.write('\n')
3442 with open(CERTFILE, 'rb') as f:
3443 d1 = f.read()
3444 d2 = ''
3445 # now fetch the same data from the HTTPS server
3446 url = 'https://localhost:%d/%s' % (
3447 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003448 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003449 f = urllib.request.urlopen(url, context=context)
3450 try:
3451 dlen = f.info().get("content-length")
3452 if dlen and (int(dlen) > 0):
3453 d2 = f.read(int(dlen))
3454 if support.verbose:
3455 sys.stdout.write(
3456 " client: read %d bytes from remote server '%s'\n"
3457 % (len(d2), server))
3458 finally:
3459 f.close()
3460 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003461
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003462 def test_asyncore_server(self):
3463 """Check the example asyncore integration."""
3464 if support.verbose:
3465 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003466
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003467 indata = b"FOO\n"
3468 server = AsyncoreEchoServer(CERTFILE)
3469 with server:
3470 s = test_wrap_socket(socket.socket())
3471 s.connect(('127.0.0.1', server.port))
3472 if support.verbose:
3473 sys.stdout.write(
3474 " client: sending %r...\n" % indata)
3475 s.write(indata)
3476 outdata = s.read()
3477 if support.verbose:
3478 sys.stdout.write(" client: read %r\n" % outdata)
3479 if outdata != indata.lower():
3480 self.fail(
3481 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3482 % (outdata[:20], len(outdata),
3483 indata[:20].lower(), len(indata)))
3484 s.write(b"over\n")
3485 if support.verbose:
3486 sys.stdout.write(" client: closing connection.\n")
3487 s.close()
3488 if support.verbose:
3489 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003490
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003491 def test_recv_send(self):
3492 """Test recv(), send() and friends."""
3493 if support.verbose:
3494 sys.stdout.write("\n")
3495
3496 server = ThreadedEchoServer(CERTFILE,
3497 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003498 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003499 cacerts=CERTFILE,
3500 chatty=True,
3501 connectionchatty=False)
3502 with server:
3503 s = test_wrap_socket(socket.socket(),
3504 server_side=False,
3505 certfile=CERTFILE,
3506 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003507 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003508 s.connect((HOST, server.port))
3509 # helper methods for standardising recv* method signatures
3510 def _recv_into():
3511 b = bytearray(b"\0"*100)
3512 count = s.recv_into(b)
3513 return b[:count]
3514
3515 def _recvfrom_into():
3516 b = bytearray(b"\0"*100)
3517 count, addr = s.recvfrom_into(b)
3518 return b[:count]
3519
3520 # (name, method, expect success?, *args, return value func)
3521 send_methods = [
3522 ('send', s.send, True, [], len),
3523 ('sendto', s.sendto, False, ["some.address"], len),
3524 ('sendall', s.sendall, True, [], lambda x: None),
3525 ]
3526 # (name, method, whether to expect success, *args)
3527 recv_methods = [
3528 ('recv', s.recv, True, []),
3529 ('recvfrom', s.recvfrom, False, ["some.address"]),
3530 ('recv_into', _recv_into, True, []),
3531 ('recvfrom_into', _recvfrom_into, False, []),
3532 ]
3533 data_prefix = "PREFIX_"
3534
3535 for (meth_name, send_meth, expect_success, args,
3536 ret_val_meth) in send_methods:
3537 indata = (data_prefix + meth_name).encode('ascii')
3538 try:
3539 ret = send_meth(indata, *args)
3540 msg = "sending with {}".format(meth_name)
3541 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3542 outdata = s.read()
3543 if outdata != indata.lower():
3544 self.fail(
3545 "While sending with <<{name:s}>> bad data "
3546 "<<{outdata:r}>> ({nout:d}) received; "
3547 "expected <<{indata:r}>> ({nin:d})\n".format(
3548 name=meth_name, outdata=outdata[:20],
3549 nout=len(outdata),
3550 indata=indata[:20], nin=len(indata)
3551 )
3552 )
3553 except ValueError as e:
3554 if expect_success:
3555 self.fail(
3556 "Failed to send with method <<{name:s}>>; "
3557 "expected to succeed.\n".format(name=meth_name)
3558 )
3559 if not str(e).startswith(meth_name):
3560 self.fail(
3561 "Method <<{name:s}>> failed with unexpected "
3562 "exception message: {exp:s}\n".format(
3563 name=meth_name, exp=e
3564 )
3565 )
3566
3567 for meth_name, recv_meth, expect_success, args in recv_methods:
3568 indata = (data_prefix + meth_name).encode('ascii')
3569 try:
3570 s.send(indata)
3571 outdata = recv_meth(*args)
3572 if outdata != indata.lower():
3573 self.fail(
3574 "While receiving with <<{name:s}>> bad data "
3575 "<<{outdata:r}>> ({nout:d}) received; "
3576 "expected <<{indata:r}>> ({nin:d})\n".format(
3577 name=meth_name, outdata=outdata[:20],
3578 nout=len(outdata),
3579 indata=indata[:20], nin=len(indata)
3580 )
3581 )
3582 except ValueError as e:
3583 if expect_success:
3584 self.fail(
3585 "Failed to receive with method <<{name:s}>>; "
3586 "expected to succeed.\n".format(name=meth_name)
3587 )
3588 if not str(e).startswith(meth_name):
3589 self.fail(
3590 "Method <<{name:s}>> failed with unexpected "
3591 "exception message: {exp:s}\n".format(
3592 name=meth_name, exp=e
3593 )
3594 )
3595 # consume data
3596 s.read()
3597
3598 # read(-1, buffer) is supported, even though read(-1) is not
3599 data = b"data"
3600 s.send(data)
3601 buffer = bytearray(len(data))
3602 self.assertEqual(s.read(-1, buffer), len(data))
3603 self.assertEqual(buffer, data)
3604
Christian Heimes888bbdc2017-09-07 14:18:21 -07003605 # sendall accepts bytes-like objects
3606 if ctypes is not None:
3607 ubyte = ctypes.c_ubyte * len(data)
3608 byteslike = ubyte.from_buffer_copy(data)
3609 s.sendall(byteslike)
3610 self.assertEqual(s.read(), data)
3611
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003612 # Make sure sendmsg et al are disallowed to avoid
3613 # inadvertent disclosure of data and/or corruption
3614 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003615 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003616 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3617 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3618 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003619 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003620 s.write(b"over\n")
3621
3622 self.assertRaises(ValueError, s.recv, -1)
3623 self.assertRaises(ValueError, s.read, -1)
3624
3625 s.close()
3626
3627 def test_recv_zero(self):
3628 server = ThreadedEchoServer(CERTFILE)
3629 server.__enter__()
3630 self.addCleanup(server.__exit__, None, None)
3631 s = socket.create_connection((HOST, server.port))
3632 self.addCleanup(s.close)
3633 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3634 self.addCleanup(s.close)
3635
3636 # recv/read(0) should return no data
3637 s.send(b"data")
3638 self.assertEqual(s.recv(0), b"")
3639 self.assertEqual(s.read(0), b"")
3640 self.assertEqual(s.read(), b"data")
3641
3642 # Should not block if the other end sends no data
3643 s.setblocking(False)
3644 self.assertEqual(s.recv(0), b"")
3645 self.assertEqual(s.recv_into(bytearray()), 0)
3646
3647 def test_nonblocking_send(self):
3648 server = ThreadedEchoServer(CERTFILE,
3649 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003650 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003651 cacerts=CERTFILE,
3652 chatty=True,
3653 connectionchatty=False)
3654 with server:
3655 s = test_wrap_socket(socket.socket(),
3656 server_side=False,
3657 certfile=CERTFILE,
3658 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003659 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003660 s.connect((HOST, server.port))
3661 s.setblocking(False)
3662
3663 # If we keep sending data, at some point the buffers
3664 # will be full and the call will block
3665 buf = bytearray(8192)
3666 def fill_buffer():
3667 while True:
3668 s.send(buf)
3669 self.assertRaises((ssl.SSLWantWriteError,
3670 ssl.SSLWantReadError), fill_buffer)
3671
3672 # Now read all the output and discard it
3673 s.setblocking(True)
3674 s.close()
3675
3676 def test_handshake_timeout(self):
3677 # Issue #5103: SSL handshake must respect the socket timeout
3678 server = socket.socket(socket.AF_INET)
3679 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003680 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003681 started = threading.Event()
3682 finish = False
3683
3684 def serve():
3685 server.listen()
3686 started.set()
3687 conns = []
3688 while not finish:
3689 r, w, e = select.select([server], [], [], 0.1)
3690 if server in r:
3691 # Let the socket hang around rather than having
3692 # it closed by garbage collection.
3693 conns.append(server.accept()[0])
3694 for sock in conns:
3695 sock.close()
3696
3697 t = threading.Thread(target=serve)
3698 t.start()
3699 started.wait()
3700
3701 try:
3702 try:
3703 c = socket.socket(socket.AF_INET)
3704 c.settimeout(0.2)
3705 c.connect((host, port))
3706 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003707 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003708 test_wrap_socket, c)
3709 finally:
3710 c.close()
3711 try:
3712 c = socket.socket(socket.AF_INET)
3713 c = test_wrap_socket(c)
3714 c.settimeout(0.2)
3715 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003716 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003717 c.connect, (host, port))
3718 finally:
3719 c.close()
3720 finally:
3721 finish = True
3722 t.join()
3723 server.close()
3724
3725 def test_server_accept(self):
3726 # Issue #16357: accept() on a SSLSocket created through
3727 # SSLContext.wrap_socket().
Christian Heimes2875c602021-04-19 07:27:10 +02003728 client_ctx, server_ctx, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003729 server = socket.socket(socket.AF_INET)
3730 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003731 port = socket_helper.bind_port(server)
Christian Heimes2875c602021-04-19 07:27:10 +02003732 server = server_ctx.wrap_socket(server, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003733 self.assertTrue(server.server_side)
3734
3735 evt = threading.Event()
3736 remote = None
3737 peer = None
3738 def serve():
3739 nonlocal remote, peer
3740 server.listen()
3741 # Block on the accept and wait on the connection to close.
3742 evt.set()
3743 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003744 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003745
3746 t = threading.Thread(target=serve)
3747 t.start()
3748 # Client wait until server setup and perform a connect.
3749 evt.wait()
Christian Heimes2875c602021-04-19 07:27:10 +02003750 client = client_ctx.wrap_socket(
3751 socket.socket(), server_hostname=hostname
3752 )
3753 client.connect((hostname, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003754 client.send(b'data')
3755 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003756 client_addr = client.getsockname()
3757 client.close()
3758 t.join()
3759 remote.close()
3760 server.close()
3761 # Sanity checks.
3762 self.assertIsInstance(remote, ssl.SSLSocket)
3763 self.assertEqual(peer, client_addr)
3764
3765 def test_getpeercert_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003766 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3767 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003768 with context.wrap_socket(socket.socket()) as sock:
3769 with self.assertRaises(OSError) as cm:
3770 sock.getpeercert()
3771 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3772
3773 def test_do_handshake_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003774 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3775 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003776 with context.wrap_socket(socket.socket()) as sock:
3777 with self.assertRaises(OSError) as cm:
3778 sock.do_handshake()
3779 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3780
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003781 def test_no_shared_ciphers(self):
3782 client_context, server_context, hostname = testing_context()
3783 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3784 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003785 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003786 client_context.set_ciphers("AES128")
3787 server_context.set_ciphers("AES256")
3788 with ThreadedEchoServer(context=server_context) as server:
3789 with client_context.wrap_socket(socket.socket(),
3790 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003791 with self.assertRaises(OSError):
3792 s.connect((HOST, server.port))
3793 self.assertIn("no shared cipher", server.conn_errors[0])
3794
3795 def test_version_basic(self):
3796 """
3797 Basic tests for SSLSocket.version().
3798 More tests are done in the test_protocol_*() methods.
3799 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003800 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3801 context.check_hostname = False
3802 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003803 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003804 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003805 chatty=False) as server:
3806 with context.wrap_socket(socket.socket()) as s:
3807 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003808 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003809 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003810 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003811 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003812 self.assertIs(s.version(), None)
3813
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003814 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003815 def test_tls1_3(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003816 client_context, server_context, hostname = testing_context()
3817 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3818 with ThreadedEchoServer(context=server_context) as server:
3819 with client_context.wrap_socket(socket.socket(),
3820 server_hostname=hostname) as s:
Christian Heimescb5b68a2017-09-07 18:07:00 -07003821 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003822 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003823 'TLS_AES_256_GCM_SHA384',
3824 'TLS_CHACHA20_POLY1305_SHA256',
3825 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003826 })
3827 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003828
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003829 @requires_tls_version('TLSv1_2')
Christian Heimes2875c602021-04-19 07:27:10 +02003830 @requires_tls_version('TLSv1')
3831 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003832 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003833 client_context, server_context, hostname = testing_context()
3834 # client TLSv1.0 to 1.2
3835 client_context.minimum_version = ssl.TLSVersion.TLSv1
3836 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3837 # server only TLSv1.2
3838 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3839 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3840
3841 with ThreadedEchoServer(context=server_context) as server:
3842 with client_context.wrap_socket(socket.socket(),
3843 server_hostname=hostname) as s:
3844 s.connect((HOST, server.port))
3845 self.assertEqual(s.version(), 'TLSv1.2')
3846
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003847 @requires_tls_version('TLSv1_1')
Christian Heimes2875c602021-04-19 07:27:10 +02003848 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003849 def test_min_max_version_tlsv1_1(self):
3850 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003851 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003852 client_context.minimum_version = ssl.TLSVersion.TLSv1
3853 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003854 server_context.minimum_version = ssl.TLSVersion.TLSv1
3855 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003856 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003857
3858 with ThreadedEchoServer(context=server_context) as server:
3859 with client_context.wrap_socket(socket.socket(),
3860 server_hostname=hostname) as s:
3861 s.connect((HOST, server.port))
3862 self.assertEqual(s.version(), 'TLSv1.1')
3863
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003864 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003865 @requires_tls_version('TLSv1')
Christian Heimes2875c602021-04-19 07:27:10 +02003866 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003867 def test_min_max_version_mismatch(self):
3868 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003869 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003870 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003871 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003872 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003873 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003874 seclevel_workaround(client_context, server_context)
3875
Christian Heimes698dde12018-02-27 11:54:43 +01003876 with ThreadedEchoServer(context=server_context) as server:
3877 with client_context.wrap_socket(socket.socket(),
3878 server_hostname=hostname) as s:
3879 with self.assertRaises(ssl.SSLError) as e:
3880 s.connect((HOST, server.port))
3881 self.assertIn("alert", str(e.exception))
3882
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003883 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003884 def test_min_max_version_sslv3(self):
3885 client_context, server_context, hostname = testing_context()
3886 server_context.minimum_version = ssl.TLSVersion.SSLv3
3887 client_context.minimum_version = ssl.TLSVersion.SSLv3
3888 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003889 seclevel_workaround(client_context, server_context)
3890
Christian Heimes698dde12018-02-27 11:54:43 +01003891 with ThreadedEchoServer(context=server_context) as server:
3892 with client_context.wrap_socket(socket.socket(),
3893 server_hostname=hostname) as s:
3894 s.connect((HOST, server.port))
3895 self.assertEqual(s.version(), 'SSLv3')
3896
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003897 def test_default_ecdh_curve(self):
3898 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3899 # should be enabled by default on SSL contexts.
Christian Heimes2875c602021-04-19 07:27:10 +02003900 client_context, server_context, hostname = testing_context()
Christian Heimescb5b68a2017-09-07 18:07:00 -07003901 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3902 # cipher name.
Christian Heimes2875c602021-04-19 07:27:10 +02003903 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003904 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3905 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3906 # our default cipher list should prefer ECDH-based ciphers
3907 # automatically.
Christian Heimes2875c602021-04-19 07:27:10 +02003908 with ThreadedEchoServer(context=server_context) as server:
3909 with client_context.wrap_socket(socket.socket(),
3910 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003911 s.connect((HOST, server.port))
3912 self.assertIn("ECDH", s.cipher()[0])
3913
3914 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3915 "'tls-unique' channel binding not available")
3916 def test_tls_unique_channel_binding(self):
3917 """Test tls-unique channel binding."""
3918 if support.verbose:
3919 sys.stdout.write("\n")
3920
Christian Heimes05d9fe32018-02-27 08:55:39 +01003921 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003922
3923 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003924 chatty=True,
3925 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003926
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003927 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003928 with client_context.wrap_socket(
3929 socket.socket(),
3930 server_hostname=hostname) as s:
3931 s.connect((HOST, server.port))
3932 # get the data
3933 cb_data = s.get_channel_binding("tls-unique")
3934 if support.verbose:
3935 sys.stdout.write(
3936 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003937
Christian Heimes05d9fe32018-02-27 08:55:39 +01003938 # check if it is sane
3939 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003940 if s.version() == 'TLSv1.3':
3941 self.assertEqual(len(cb_data), 48)
3942 else:
3943 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003944
Christian Heimes05d9fe32018-02-27 08:55:39 +01003945 # and compare with the peers version
3946 s.write(b"CB tls-unique\n")
3947 peer_data_repr = s.read().strip()
3948 self.assertEqual(peer_data_repr,
3949 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003950
3951 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003952 with client_context.wrap_socket(
3953 socket.socket(),
3954 server_hostname=hostname) as s:
3955 s.connect((HOST, server.port))
3956 new_cb_data = s.get_channel_binding("tls-unique")
3957 if support.verbose:
3958 sys.stdout.write(
3959 "got another channel binding data: {0!r}\n".format(
3960 new_cb_data)
3961 )
3962 # is it really unique
3963 self.assertNotEqual(cb_data, new_cb_data)
3964 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003965 if s.version() == 'TLSv1.3':
3966 self.assertEqual(len(cb_data), 48)
3967 else:
3968 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003969 s.write(b"CB tls-unique\n")
3970 peer_data_repr = s.read().strip()
3971 self.assertEqual(peer_data_repr,
3972 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003973
3974 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003975 client_context, server_context, hostname = testing_context()
3976 stats = server_params_test(client_context, server_context,
3977 chatty=True, connectionchatty=True,
3978 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003979 if support.verbose:
3980 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
3981 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
3982
3983 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
3984 "ssl.OP_NO_COMPRESSION needed for this test")
3985 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003986 client_context, server_context, hostname = testing_context()
3987 client_context.options |= ssl.OP_NO_COMPRESSION
3988 server_context.options |= ssl.OP_NO_COMPRESSION
3989 stats = server_params_test(client_context, server_context,
3990 chatty=True, connectionchatty=True,
3991 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003992 self.assertIs(stats['compression'], None)
3993
Paul Monsonf3550692019-06-19 13:09:54 -07003994 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003995 def test_dh_params(self):
3996 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02003997 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003998 # test scenario needs TLS <= 1.2
3999 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004000 server_context.load_dh_params(DHFILE)
4001 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004002 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004003 stats = server_params_test(client_context, server_context,
4004 chatty=True, connectionchatty=True,
4005 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004006 cipher = stats["cipher"][0]
4007 parts = cipher.split("-")
4008 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4009 self.fail("Non-DH cipher: " + cipher[0])
4010
Christian Heimesb7b92252018-02-25 09:49:31 +01004011 def test_ecdh_curve(self):
4012 # server secp384r1, client auto
4013 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004014
Christian Heimesb7b92252018-02-25 09:49:31 +01004015 server_context.set_ecdh_curve("secp384r1")
4016 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004017 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004018 stats = server_params_test(client_context, server_context,
4019 chatty=True, connectionchatty=True,
4020 sni_name=hostname)
4021
4022 # server auto, client secp384r1
4023 client_context, server_context, hostname = testing_context()
4024 client_context.set_ecdh_curve("secp384r1")
4025 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004026 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004027 stats = server_params_test(client_context, server_context,
4028 chatty=True, connectionchatty=True,
4029 sni_name=hostname)
4030
4031 # server / client curve mismatch
4032 client_context, server_context, hostname = testing_context()
4033 client_context.set_ecdh_curve("prime256v1")
4034 server_context.set_ecdh_curve("secp384r1")
4035 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004036 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
4037 with self.assertRaises(ssl.SSLError):
Christian Heimes39258d32021-04-17 11:36:35 +02004038 server_params_test(client_context, server_context,
4039 chatty=True, connectionchatty=True,
4040 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004041
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004042 def test_selected_alpn_protocol(self):
4043 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004044 client_context, server_context, hostname = testing_context()
4045 stats = server_params_test(client_context, server_context,
4046 chatty=True, connectionchatty=True,
4047 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004048 self.assertIs(stats['client_alpn_protocol'], None)
4049
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004050 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4051 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004052 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004053 server_context.set_alpn_protocols(['foo', 'bar'])
4054 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004055 chatty=True, connectionchatty=True,
4056 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004057 self.assertIs(stats['client_alpn_protocol'], None)
4058
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004059 def test_alpn_protocols(self):
4060 server_protocols = ['foo', 'bar', 'milkshake']
4061 protocol_tests = [
4062 (['foo', 'bar'], 'foo'),
4063 (['bar', 'foo'], 'foo'),
4064 (['milkshake'], 'milkshake'),
4065 (['http/3.0', 'http/4.0'], None)
4066 ]
4067 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004068 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004069 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004070 client_context.set_alpn_protocols(client_protocols)
4071
4072 try:
4073 stats = server_params_test(client_context,
4074 server_context,
4075 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004076 connectionchatty=True,
4077 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004078 except ssl.SSLError as e:
4079 stats = e
4080
Christian Heimes39258d32021-04-17 11:36:35 +02004081 msg = "failed trying %s (s) and %s (c).\n" \
4082 "was expecting %s, but got %%s from the %%s" \
4083 % (str(server_protocols), str(client_protocols),
4084 str(expected))
4085 client_result = stats['client_alpn_protocol']
4086 self.assertEqual(client_result, expected,
4087 msg % (client_result, "client"))
4088 server_result = stats['server_alpn_protocols'][-1] \
4089 if len(stats['server_alpn_protocols']) else 'nothing'
4090 self.assertEqual(server_result, expected,
4091 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004092
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004093 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004094 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004095
4096 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004097 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004098 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004099 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004100 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004101 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004102 client_context.load_verify_locations(SIGNING_CA)
4103 return server_context, other_context, client_context
4104
4105 def check_common_name(self, stats, name):
4106 cert = stats['peercert']
4107 self.assertIn((('commonName', name),), cert['subject'])
4108
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004109 def test_sni_callback(self):
4110 calls = []
4111 server_context, other_context, client_context = self.sni_contexts()
4112
Christian Heimesa170fa12017-09-15 20:27:30 +02004113 client_context.check_hostname = False
4114
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004115 def servername_cb(ssl_sock, server_name, initial_context):
4116 calls.append((server_name, initial_context))
4117 if server_name is not None:
4118 ssl_sock.context = other_context
4119 server_context.set_servername_callback(servername_cb)
4120
4121 stats = server_params_test(client_context, server_context,
4122 chatty=True,
4123 sni_name='supermessage')
4124 # The hostname was fetched properly, and the certificate was
4125 # changed for the connection.
4126 self.assertEqual(calls, [("supermessage", server_context)])
4127 # CERTFILE4 was selected
4128 self.check_common_name(stats, 'fakehostname')
4129
4130 calls = []
4131 # The callback is called with server_name=None
4132 stats = server_params_test(client_context, server_context,
4133 chatty=True,
4134 sni_name=None)
4135 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004136 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004137
4138 # Check disabling the callback
4139 calls = []
4140 server_context.set_servername_callback(None)
4141
4142 stats = server_params_test(client_context, server_context,
4143 chatty=True,
4144 sni_name='notfunny')
4145 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004146 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004147 self.assertEqual(calls, [])
4148
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004149 def test_sni_callback_alert(self):
4150 # Returning a TLS alert is reflected to the connecting client
4151 server_context, other_context, client_context = self.sni_contexts()
4152
4153 def cb_returning_alert(ssl_sock, server_name, initial_context):
4154 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4155 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004156 with self.assertRaises(ssl.SSLError) as cm:
4157 stats = server_params_test(client_context, server_context,
4158 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004159 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004160 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004161
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004162 def test_sni_callback_raising(self):
4163 # Raising fails the connection with a TLS handshake failure alert.
4164 server_context, other_context, client_context = self.sni_contexts()
4165
4166 def cb_raising(ssl_sock, server_name, initial_context):
4167 1/0
4168 server_context.set_servername_callback(cb_raising)
4169
Victor Stinner00253502019-06-03 03:51:43 +02004170 with support.catch_unraisable_exception() as catch:
4171 with self.assertRaises(ssl.SSLError) as cm:
4172 stats = server_params_test(client_context, server_context,
4173 chatty=False,
4174 sni_name='supermessage')
4175
4176 self.assertEqual(cm.exception.reason,
4177 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4178 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004179
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004180 def test_sni_callback_wrong_return_type(self):
4181 # Returning the wrong return type terminates the TLS connection
4182 # with an internal error alert.
4183 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004184
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004185 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4186 return "foo"
4187 server_context.set_servername_callback(cb_wrong_return_type)
4188
Victor Stinner00253502019-06-03 03:51:43 +02004189 with support.catch_unraisable_exception() as catch:
4190 with self.assertRaises(ssl.SSLError) as cm:
4191 stats = server_params_test(client_context, server_context,
4192 chatty=False,
4193 sni_name='supermessage')
4194
4195
4196 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4197 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004198
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004199 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004200 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004201 client_context.set_ciphers("AES128:AES256")
4202 server_context.set_ciphers("AES256")
4203 expected_algs = [
4204 "AES256", "AES-256",
4205 # TLS 1.3 ciphers are always enabled
4206 "TLS_CHACHA20", "TLS_AES",
4207 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004208
Christian Heimesa170fa12017-09-15 20:27:30 +02004209 stats = server_params_test(client_context, server_context,
4210 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004211 ciphers = stats['server_shared_ciphers'][0]
4212 self.assertGreater(len(ciphers), 0)
4213 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004214 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004215 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004216
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004217 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004218 client_context, server_context, hostname = testing_context()
4219 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004220
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004221 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004222 s = client_context.wrap_socket(socket.socket(),
4223 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004224 s.connect((HOST, server.port))
4225 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004226
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004227 self.assertRaises(ValueError, s.read, 1024)
4228 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004229
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004230 def test_sendfile(self):
4231 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004232 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004233 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004234 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimes2875c602021-04-19 07:27:10 +02004235 client_context, server_context, hostname = testing_context()
4236 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004237 with server:
Christian Heimes2875c602021-04-19 07:27:10 +02004238 with client_context.wrap_socket(socket.socket(),
4239 server_hostname=hostname) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004240 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004241 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004242 s.sendfile(file)
4243 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004244
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004245 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004246 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004247 # TODO: sessions aren't compatible with TLSv1.3 yet
4248 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004249
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004250 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004251 stats = server_params_test(client_context, server_context,
4252 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004253 session = stats['session']
4254 self.assertTrue(session.id)
4255 self.assertGreater(session.time, 0)
4256 self.assertGreater(session.timeout, 0)
4257 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004258 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004259 self.assertFalse(stats['session_reused'])
4260 sess_stat = server_context.session_stats()
4261 self.assertEqual(sess_stat['accept'], 1)
4262 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004263
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004264 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004265 stats = server_params_test(client_context, server_context,
4266 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004267 sess_stat = server_context.session_stats()
4268 self.assertEqual(sess_stat['accept'], 2)
4269 self.assertEqual(sess_stat['hits'], 1)
4270 self.assertTrue(stats['session_reused'])
4271 session2 = stats['session']
4272 self.assertEqual(session2.id, session.id)
4273 self.assertEqual(session2, session)
4274 self.assertIsNot(session2, session)
4275 self.assertGreaterEqual(session2.time, session.time)
4276 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004277
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004278 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004279 stats = server_params_test(client_context, server_context,
4280 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004281 self.assertFalse(stats['session_reused'])
4282 session3 = stats['session']
4283 self.assertNotEqual(session3.id, session.id)
4284 self.assertNotEqual(session3, session)
4285 sess_stat = server_context.session_stats()
4286 self.assertEqual(sess_stat['accept'], 3)
4287 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004288
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004289 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004290 stats = server_params_test(client_context, server_context,
4291 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004292 self.assertTrue(stats['session_reused'])
4293 session4 = stats['session']
4294 self.assertEqual(session4.id, session.id)
4295 self.assertEqual(session4, session)
4296 self.assertGreaterEqual(session4.time, session.time)
4297 self.assertGreaterEqual(session4.timeout, session.timeout)
4298 sess_stat = server_context.session_stats()
4299 self.assertEqual(sess_stat['accept'], 4)
4300 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004301
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004302 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004303 client_context, server_context, hostname = testing_context()
4304 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004305
Christian Heimes05d9fe32018-02-27 08:55:39 +01004306 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004307 client_context.options |= ssl.OP_NO_TLSv1_3
4308 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004309
Christian Heimesa170fa12017-09-15 20:27:30 +02004310 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004311 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004312 with client_context.wrap_socket(socket.socket(),
4313 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004314 # session is None before handshake
4315 self.assertEqual(s.session, None)
4316 self.assertEqual(s.session_reused, None)
4317 s.connect((HOST, server.port))
4318 session = s.session
4319 self.assertTrue(session)
4320 with self.assertRaises(TypeError) as e:
4321 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004322 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004323
Christian Heimesa170fa12017-09-15 20:27:30 +02004324 with client_context.wrap_socket(socket.socket(),
4325 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004326 s.connect((HOST, server.port))
4327 # cannot set session after handshake
4328 with self.assertRaises(ValueError) as e:
4329 s.session = session
4330 self.assertEqual(str(e.exception),
4331 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004332
Christian Heimesa170fa12017-09-15 20:27:30 +02004333 with client_context.wrap_socket(socket.socket(),
4334 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004335 # can set session before handshake and before the
4336 # connection was established
4337 s.session = session
4338 s.connect((HOST, server.port))
4339 self.assertEqual(s.session.id, session.id)
4340 self.assertEqual(s.session, session)
4341 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004342
Christian Heimesa170fa12017-09-15 20:27:30 +02004343 with client_context2.wrap_socket(socket.socket(),
4344 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004345 # cannot re-use session with a different SSLContext
4346 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004347 s.session = session
4348 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004349 self.assertEqual(str(e.exception),
4350 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004351
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004352
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004353@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004354class TestPostHandshakeAuth(unittest.TestCase):
4355 def test_pha_setter(self):
4356 protocols = [
Christian Heimes2875c602021-04-19 07:27:10 +02004357 ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
Christian Heimes9fb051f2018-09-23 08:32:31 +02004358 ]
4359 for protocol in protocols:
4360 ctx = ssl.SSLContext(protocol)
4361 self.assertEqual(ctx.post_handshake_auth, False)
4362
4363 ctx.post_handshake_auth = True
4364 self.assertEqual(ctx.post_handshake_auth, True)
4365
4366 ctx.verify_mode = ssl.CERT_REQUIRED
4367 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4368 self.assertEqual(ctx.post_handshake_auth, True)
4369
4370 ctx.post_handshake_auth = False
4371 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4372 self.assertEqual(ctx.post_handshake_auth, False)
4373
4374 ctx.verify_mode = ssl.CERT_OPTIONAL
4375 ctx.post_handshake_auth = True
4376 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4377 self.assertEqual(ctx.post_handshake_auth, True)
4378
4379 def test_pha_required(self):
4380 client_context, server_context, hostname = testing_context()
4381 server_context.post_handshake_auth = True
4382 server_context.verify_mode = ssl.CERT_REQUIRED
4383 client_context.post_handshake_auth = True
4384 client_context.load_cert_chain(SIGNED_CERTFILE)
4385
4386 server = ThreadedEchoServer(context=server_context, chatty=False)
4387 with server:
4388 with client_context.wrap_socket(socket.socket(),
4389 server_hostname=hostname) as s:
4390 s.connect((HOST, server.port))
4391 s.write(b'HASCERT')
4392 self.assertEqual(s.recv(1024), b'FALSE\n')
4393 s.write(b'PHA')
4394 self.assertEqual(s.recv(1024), b'OK\n')
4395 s.write(b'HASCERT')
4396 self.assertEqual(s.recv(1024), b'TRUE\n')
4397 # PHA method just returns true when cert is already available
4398 s.write(b'PHA')
4399 self.assertEqual(s.recv(1024), b'OK\n')
4400 s.write(b'GETCERT')
4401 cert_text = s.recv(4096).decode('us-ascii')
4402 self.assertIn('Python Software Foundation CA', cert_text)
4403
4404 def test_pha_required_nocert(self):
4405 client_context, server_context, hostname = testing_context()
4406 server_context.post_handshake_auth = True
4407 server_context.verify_mode = ssl.CERT_REQUIRED
4408 client_context.post_handshake_auth = True
4409
Victor Stinner73ea5462019-07-09 14:33:49 +02004410 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4411 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004412 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004413 server = ThreadedEchoServer(context=server_context, chatty=False)
4414 with server:
4415 with client_context.wrap_socket(socket.socket(),
4416 server_hostname=hostname) as s:
4417 s.connect((HOST, server.port))
4418 s.write(b'PHA')
4419 # receive CertificateRequest
4420 self.assertEqual(s.recv(1024), b'OK\n')
4421 # send empty Certificate + Finish
4422 s.write(b'HASCERT')
4423 # receive alert
4424 with self.assertRaisesRegex(
4425 ssl.SSLError,
4426 'tlsv13 alert certificate required'):
4427 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004428
4429 def test_pha_optional(self):
4430 if support.verbose:
4431 sys.stdout.write("\n")
4432
4433 client_context, server_context, hostname = testing_context()
4434 server_context.post_handshake_auth = True
4435 server_context.verify_mode = ssl.CERT_REQUIRED
4436 client_context.post_handshake_auth = True
4437 client_context.load_cert_chain(SIGNED_CERTFILE)
4438
4439 # check CERT_OPTIONAL
4440 server_context.verify_mode = ssl.CERT_OPTIONAL
4441 server = ThreadedEchoServer(context=server_context, chatty=False)
4442 with server:
4443 with client_context.wrap_socket(socket.socket(),
4444 server_hostname=hostname) as s:
4445 s.connect((HOST, server.port))
4446 s.write(b'HASCERT')
4447 self.assertEqual(s.recv(1024), b'FALSE\n')
4448 s.write(b'PHA')
4449 self.assertEqual(s.recv(1024), b'OK\n')
4450 s.write(b'HASCERT')
4451 self.assertEqual(s.recv(1024), b'TRUE\n')
4452
4453 def test_pha_optional_nocert(self):
4454 if support.verbose:
4455 sys.stdout.write("\n")
4456
4457 client_context, server_context, hostname = testing_context()
4458 server_context.post_handshake_auth = True
4459 server_context.verify_mode = ssl.CERT_OPTIONAL
4460 client_context.post_handshake_auth = True
4461
4462 server = ThreadedEchoServer(context=server_context, chatty=False)
4463 with server:
4464 with client_context.wrap_socket(socket.socket(),
4465 server_hostname=hostname) as s:
4466 s.connect((HOST, server.port))
4467 s.write(b'HASCERT')
4468 self.assertEqual(s.recv(1024), b'FALSE\n')
4469 s.write(b'PHA')
4470 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004471 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004472 s.write(b'HASCERT')
4473 self.assertEqual(s.recv(1024), b'FALSE\n')
4474
4475 def test_pha_no_pha_client(self):
4476 client_context, server_context, hostname = testing_context()
4477 server_context.post_handshake_auth = True
4478 server_context.verify_mode = ssl.CERT_REQUIRED
4479 client_context.load_cert_chain(SIGNED_CERTFILE)
4480
4481 server = ThreadedEchoServer(context=server_context, chatty=False)
4482 with server:
4483 with client_context.wrap_socket(socket.socket(),
4484 server_hostname=hostname) as s:
4485 s.connect((HOST, server.port))
4486 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4487 s.verify_client_post_handshake()
4488 s.write(b'PHA')
4489 self.assertIn(b'extension not received', s.recv(1024))
4490
4491 def test_pha_no_pha_server(self):
4492 # server doesn't have PHA enabled, cert is requested in handshake
4493 client_context, server_context, hostname = testing_context()
4494 server_context.verify_mode = ssl.CERT_REQUIRED
4495 client_context.post_handshake_auth = True
4496 client_context.load_cert_chain(SIGNED_CERTFILE)
4497
4498 server = ThreadedEchoServer(context=server_context, chatty=False)
4499 with server:
4500 with client_context.wrap_socket(socket.socket(),
4501 server_hostname=hostname) as s:
4502 s.connect((HOST, server.port))
4503 s.write(b'HASCERT')
4504 self.assertEqual(s.recv(1024), b'TRUE\n')
4505 # PHA doesn't fail if there is already a cert
4506 s.write(b'PHA')
4507 self.assertEqual(s.recv(1024), b'OK\n')
4508 s.write(b'HASCERT')
4509 self.assertEqual(s.recv(1024), b'TRUE\n')
4510
4511 def test_pha_not_tls13(self):
4512 # TLS 1.2
4513 client_context, server_context, hostname = testing_context()
4514 server_context.verify_mode = ssl.CERT_REQUIRED
4515 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4516 client_context.post_handshake_auth = True
4517 client_context.load_cert_chain(SIGNED_CERTFILE)
4518
4519 server = ThreadedEchoServer(context=server_context, chatty=False)
4520 with server:
4521 with client_context.wrap_socket(socket.socket(),
4522 server_hostname=hostname) as s:
4523 s.connect((HOST, server.port))
4524 # PHA fails for TLS != 1.3
4525 s.write(b'PHA')
4526 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4527
Christian Heimesf0f59302019-07-01 08:29:17 +02004528 def test_bpo37428_pha_cert_none(self):
4529 # verify that post_handshake_auth does not implicitly enable cert
4530 # validation.
4531 hostname = SIGNED_CERTFILE_HOSTNAME
4532 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4533 client_context.post_handshake_auth = True
4534 client_context.load_cert_chain(SIGNED_CERTFILE)
4535 # no cert validation and CA on client side
4536 client_context.check_hostname = False
4537 client_context.verify_mode = ssl.CERT_NONE
4538
4539 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4540 server_context.load_cert_chain(SIGNED_CERTFILE)
4541 server_context.load_verify_locations(SIGNING_CA)
4542 server_context.post_handshake_auth = True
4543 server_context.verify_mode = ssl.CERT_REQUIRED
4544
4545 server = ThreadedEchoServer(context=server_context, chatty=False)
4546 with server:
4547 with client_context.wrap_socket(socket.socket(),
4548 server_hostname=hostname) as s:
4549 s.connect((HOST, server.port))
4550 s.write(b'HASCERT')
4551 self.assertEqual(s.recv(1024), b'FALSE\n')
4552 s.write(b'PHA')
4553 self.assertEqual(s.recv(1024), b'OK\n')
4554 s.write(b'HASCERT')
4555 self.assertEqual(s.recv(1024), b'TRUE\n')
4556 # server cert has not been validated
4557 self.assertEqual(s.getpeercert(), {})
4558
Christian Heimes9fb051f2018-09-23 08:32:31 +02004559
Christian Heimesc7f70692019-05-31 11:44:05 +02004560HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4561requires_keylog = unittest.skipUnless(
4562 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4563
4564class TestSSLDebug(unittest.TestCase):
4565
Hai Shia7f5d932020-08-04 00:41:24 +08004566 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004567 with open(fname) as f:
4568 return len(list(f))
4569
4570 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004571 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004572 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004573 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004574 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4575 self.assertEqual(ctx.keylog_filename, None)
4576
Hai Shia7f5d932020-08-04 00:41:24 +08004577 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4578 ctx.keylog_filename = os_helper.TESTFN
4579 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4580 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004581 self.assertEqual(self.keylog_lines(), 1)
4582
4583 ctx.keylog_filename = None
4584 self.assertEqual(ctx.keylog_filename, None)
4585
4586 with self.assertRaises((IsADirectoryError, PermissionError)):
4587 # Windows raises PermissionError
4588 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004589 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004590
4591 with self.assertRaises(TypeError):
4592 ctx.keylog_filename = 1
4593
4594 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004595 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004596 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004597 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004598 client_context, server_context, hostname = testing_context()
4599
Hai Shia7f5d932020-08-04 00:41:24 +08004600 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004601 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 # header, 5 lines for TLS 1.3
4607 self.assertEqual(self.keylog_lines(), 6)
4608
4609 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004610 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004611 server = ThreadedEchoServer(context=server_context, chatty=False)
4612 with server:
4613 with client_context.wrap_socket(socket.socket(),
4614 server_hostname=hostname) as s:
4615 s.connect((HOST, server.port))
4616 self.assertGreaterEqual(self.keylog_lines(), 11)
4617
Hai Shia7f5d932020-08-04 00:41:24 +08004618 client_context.keylog_filename = os_helper.TESTFN
4619 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004620 server = ThreadedEchoServer(context=server_context, chatty=False)
4621 with server:
4622 with client_context.wrap_socket(socket.socket(),
4623 server_hostname=hostname) as s:
4624 s.connect((HOST, server.port))
4625 self.assertGreaterEqual(self.keylog_lines(), 21)
4626
4627 client_context.keylog_filename = None
4628 server_context.keylog_filename = None
4629
4630 @requires_keylog
4631 @unittest.skipIf(sys.flags.ignore_environment,
4632 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004633 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004634 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004635 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004636 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004637 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4638 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004639
4640 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4641 self.assertEqual(ctx.keylog_filename, None)
4642
4643 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004644 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004645
4646 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004647 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004648
4649 def test_msg_callback(self):
4650 client_context, server_context, hostname = testing_context()
4651
4652 def msg_cb(conn, direction, version, content_type, msg_type, data):
4653 pass
4654
4655 self.assertIs(client_context._msg_callback, None)
4656 client_context._msg_callback = msg_cb
4657 self.assertIs(client_context._msg_callback, msg_cb)
4658 with self.assertRaises(TypeError):
4659 client_context._msg_callback = object()
4660
4661 def test_msg_callback_tls12(self):
4662 client_context, server_context, hostname = testing_context()
4663 client_context.options |= ssl.OP_NO_TLSv1_3
4664
4665 msg = []
4666
4667 def msg_cb(conn, direction, version, content_type, msg_type, data):
4668 self.assertIsInstance(conn, ssl.SSLSocket)
4669 self.assertIsInstance(data, bytes)
4670 self.assertIn(direction, {'read', 'write'})
4671 msg.append((direction, version, content_type, msg_type))
4672
4673 client_context._msg_callback = msg_cb
4674
4675 server = ThreadedEchoServer(context=server_context, chatty=False)
4676 with server:
4677 with client_context.wrap_socket(socket.socket(),
4678 server_hostname=hostname) as s:
4679 s.connect((HOST, server.port))
4680
Christian Heimese35d1ba2019-06-03 20:40:15 +02004681 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004682 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4683 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004684 msg
4685 )
4686 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004687 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4688 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004689 msg
4690 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004691
Christian Heimes77cde502021-03-21 16:13:09 +01004692 def test_msg_callback_deadlock_bpo43577(self):
4693 client_context, server_context, hostname = testing_context()
4694 server_context2 = testing_context()[1]
4695
4696 def msg_cb(conn, direction, version, content_type, msg_type, data):
4697 pass
4698
4699 def sni_cb(sock, servername, ctx):
4700 sock.context = server_context2
4701
4702 server_context._msg_callback = msg_cb
4703 server_context.sni_callback = sni_cb
4704
4705 server = ThreadedEchoServer(context=server_context, chatty=False)
4706 with server:
4707 with client_context.wrap_socket(socket.socket(),
4708 server_hostname=hostname) as s:
4709 s.connect((HOST, server.port))
4710 with client_context.wrap_socket(socket.socket(),
4711 server_hostname=hostname) as s:
4712 s.connect((HOST, server.port))
4713
Christian Heimesc7f70692019-05-31 11:44:05 +02004714
Ethan Furmana02cb472021-04-21 10:20:44 -07004715class TestEnumerations(unittest.TestCase):
4716
4717 def test_tlsversion(self):
4718 class CheckedTLSVersion(enum.IntEnum):
4719 MINIMUM_SUPPORTED = _ssl.PROTO_MINIMUM_SUPPORTED
4720 SSLv3 = _ssl.PROTO_SSLv3
4721 TLSv1 = _ssl.PROTO_TLSv1
4722 TLSv1_1 = _ssl.PROTO_TLSv1_1
4723 TLSv1_2 = _ssl.PROTO_TLSv1_2
4724 TLSv1_3 = _ssl.PROTO_TLSv1_3
4725 MAXIMUM_SUPPORTED = _ssl.PROTO_MAXIMUM_SUPPORTED
4726 enum._test_simple_enum(CheckedTLSVersion, TLSVersion)
4727
4728 def test_tlscontenttype(self):
4729 class Checked_TLSContentType(enum.IntEnum):
4730 """Content types (record layer)
4731
4732 See RFC 8446, section B.1
4733 """
4734 CHANGE_CIPHER_SPEC = 20
4735 ALERT = 21
4736 HANDSHAKE = 22
4737 APPLICATION_DATA = 23
4738 # pseudo content types
4739 HEADER = 0x100
4740 INNER_CONTENT_TYPE = 0x101
4741 enum._test_simple_enum(Checked_TLSContentType, _TLSContentType)
4742
4743 def test_tlsalerttype(self):
4744 class Checked_TLSAlertType(enum.IntEnum):
4745 """Alert types for TLSContentType.ALERT messages
4746
4747 See RFC 8466, section B.2
4748 """
4749 CLOSE_NOTIFY = 0
4750 UNEXPECTED_MESSAGE = 10
4751 BAD_RECORD_MAC = 20
4752 DECRYPTION_FAILED = 21
4753 RECORD_OVERFLOW = 22
4754 DECOMPRESSION_FAILURE = 30
4755 HANDSHAKE_FAILURE = 40
4756 NO_CERTIFICATE = 41
4757 BAD_CERTIFICATE = 42
4758 UNSUPPORTED_CERTIFICATE = 43
4759 CERTIFICATE_REVOKED = 44
4760 CERTIFICATE_EXPIRED = 45
4761 CERTIFICATE_UNKNOWN = 46
4762 ILLEGAL_PARAMETER = 47
4763 UNKNOWN_CA = 48
4764 ACCESS_DENIED = 49
4765 DECODE_ERROR = 50
4766 DECRYPT_ERROR = 51
4767 EXPORT_RESTRICTION = 60
4768 PROTOCOL_VERSION = 70
4769 INSUFFICIENT_SECURITY = 71
4770 INTERNAL_ERROR = 80
4771 INAPPROPRIATE_FALLBACK = 86
4772 USER_CANCELED = 90
4773 NO_RENEGOTIATION = 100
4774 MISSING_EXTENSION = 109
4775 UNSUPPORTED_EXTENSION = 110
4776 CERTIFICATE_UNOBTAINABLE = 111
4777 UNRECOGNIZED_NAME = 112
4778 BAD_CERTIFICATE_STATUS_RESPONSE = 113
4779 BAD_CERTIFICATE_HASH_VALUE = 114
4780 UNKNOWN_PSK_IDENTITY = 115
4781 CERTIFICATE_REQUIRED = 116
4782 NO_APPLICATION_PROTOCOL = 120
4783 enum._test_simple_enum(Checked_TLSAlertType, _TLSAlertType)
4784
4785 def test_tlsmessagetype(self):
4786 class Checked_TLSMessageType(enum.IntEnum):
4787 """Message types (handshake protocol)
4788
4789 See RFC 8446, section B.3
4790 """
4791 HELLO_REQUEST = 0
4792 CLIENT_HELLO = 1
4793 SERVER_HELLO = 2
4794 HELLO_VERIFY_REQUEST = 3
4795 NEWSESSION_TICKET = 4
4796 END_OF_EARLY_DATA = 5
4797 HELLO_RETRY_REQUEST = 6
4798 ENCRYPTED_EXTENSIONS = 8
4799 CERTIFICATE = 11
4800 SERVER_KEY_EXCHANGE = 12
4801 CERTIFICATE_REQUEST = 13
4802 SERVER_DONE = 14
4803 CERTIFICATE_VERIFY = 15
4804 CLIENT_KEY_EXCHANGE = 16
4805 FINISHED = 20
4806 CERTIFICATE_URL = 21
4807 CERTIFICATE_STATUS = 22
4808 SUPPLEMENTAL_DATA = 23
4809 KEY_UPDATE = 24
4810 NEXT_PROTO = 67
4811 MESSAGE_HASH = 254
4812 CHANGE_CIPHER_SPEC = 0x0101
4813 enum._test_simple_enum(Checked_TLSMessageType, _TLSMessageType)
4814
4815 def test_sslmethod(self):
4816 Checked_SSLMethod = enum._old_convert_(
4817 enum.IntEnum, '_SSLMethod', 'ssl',
4818 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4819 source=ssl._ssl,
4820 )
4821 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
4822
4823 def test_options(self):
4824 CheckedOptions = enum._old_convert_(
4825 enum.FlagEnum, 'Options', 'ssl',
4826 lambda name: name.startswith('OP_'),
4827 source=ssl._ssl,
4828 )
4829 enum._test_simple_enum(CheckedOptions, ssl.Options)
4830
4831
4832 def test_alertdescription(self):
4833 CheckedAlertDescription = enum._old_convert_(
4834 enum.IntEnum, 'AlertDescription', 'ssl',
4835 lambda name: name.startswith('ALERT_DESCRIPTION_'),
4836 source=ssl._ssl,
4837 )
4838 enum._test_simple_enum(CheckedAlertDescription, ssl.AlertDescription)
4839
4840 def test_sslerrornumber(self):
4841 Checked_SSLMethod = enum._old_convert_(
4842 enum.IntEnum, '_SSLMethod', 'ssl',
4843 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4844 source=ssl._ssl,
4845 )
4846 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
4847
4848 def test_verifyflags(self):
4849 CheckedVerifyFlags = enum._old_convert_(
4850 enum.FlagEnum, 'VerifyFlags', 'ssl',
4851 lambda name: name.startswith('VERIFY_'),
4852 source=ssl._ssl,
4853 )
4854 enum._test_simple_enum(CheckedVerifyFlags, ssl.VerifyFlags)
4855
4856 def test_verifymode(self):
4857 CheckedVerifyMode = enum._old_convert_(
4858 enum.IntEnum, 'VerifyMode', 'ssl',
4859 lambda name: name.startswith('CERT_'),
4860 source=ssl._ssl,
4861 )
4862 enum._test_simple_enum(CheckedVerifyMode, ssl.VerifyMode)
4863
Thomas Woutersed03b412007-08-28 21:37:11 +00004864def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004865 if support.verbose:
4866 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004867 'Mac': platform.mac_ver,
4868 'Windows': platform.win32_ver,
4869 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004870 for name, func in plats.items():
4871 plat = func()
4872 if plat and plat[0]:
4873 plat = '%s %r' % (name, plat)
4874 break
4875 else:
4876 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004877 print("test_ssl: testing with %r %r" %
4878 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4879 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004880 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004881 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4882 try:
4883 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4884 except AttributeError:
4885 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004886
Antoine Pitrou152efa22010-05-16 18:19:27 +00004887 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004888 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004889 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004890 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004891 BADCERT, BADKEY, EMPTYCERT]:
4892 if not os.path.exists(filename):
4893 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004894
Martin Panter3840b2a2016-03-27 01:53:46 +00004895 tests = [
4896 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004897 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004898 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004899 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004900
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004901 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004902 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004903
Hai Shie80697d2020-05-28 06:10:27 +08004904 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004905 try:
4906 support.run_unittest(*tests)
4907 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004908 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004909
4910if __name__ == "__main__":
4911 test_main()