blob: 8c846574e1ab43d69ecf85426e28cfa69a1d03b6 [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')
3166 s.read(4)
3167 except ssl.SSLError as e:
3168 if support.verbose:
3169 sys.stdout.write("\nSSLError is %r\n" % e)
3170 except OSError as e:
3171 if e.errno != errno.ECONNRESET:
3172 raise
3173 if support.verbose:
3174 sys.stdout.write("\nsocket.error is %r\n" % e)
3175 else:
3176 self.fail("Use of invalid cert should have failed!")
3177
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003178 def test_rude_shutdown(self):
3179 """A brutal shutdown of an SSL server should raise an OSError
3180 in the client when attempting handshake.
3181 """
3182 listener_ready = threading.Event()
3183 listener_gone = threading.Event()
3184
3185 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003186 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003187
3188 # `listener` runs in a thread. It sits in an accept() until
3189 # the main thread connects. Then it rudely closes the socket,
3190 # and sets Event `listener_gone` to let the main thread know
3191 # the socket is gone.
3192 def listener():
3193 s.listen()
3194 listener_ready.set()
3195 newsock, addr = s.accept()
3196 newsock.close()
3197 s.close()
3198 listener_gone.set()
3199
3200 def connector():
3201 listener_ready.wait()
3202 with socket.socket() as c:
3203 c.connect((HOST, port))
3204 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003205 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003206 ssl_sock = test_wrap_socket(c)
3207 except OSError:
3208 pass
3209 else:
3210 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003211
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003212 t = threading.Thread(target=listener)
3213 t.start()
3214 try:
3215 connector()
3216 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003217 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003218
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003219 def test_ssl_cert_verify_error(self):
3220 if support.verbose:
3221 sys.stdout.write("\n")
3222
3223 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3224 server_context.load_cert_chain(SIGNED_CERTFILE)
3225
3226 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3227
3228 server = ThreadedEchoServer(context=server_context, chatty=True)
3229 with server:
3230 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003231 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003232 try:
3233 s.connect((HOST, server.port))
3234 except ssl.SSLError as e:
3235 msg = 'unable to get local issuer certificate'
3236 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3237 self.assertEqual(e.verify_code, 20)
3238 self.assertEqual(e.verify_message, msg)
3239 self.assertIn(msg, repr(e))
3240 self.assertIn('certificate verify failed', repr(e))
3241
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003242 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003243 def test_protocol_sslv2(self):
3244 """Connecting to an SSLv2 server with various client options"""
3245 if support.verbose:
3246 sys.stdout.write("\n")
3247 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3248 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3249 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003250 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003251 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003252 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3253 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3254 # SSLv23 client with specific SSL options
Christian Heimesa170fa12017-09-15 20:27:30 +02003255 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003256 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003257 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003258 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003259
Christian Heimesa170fa12017-09-15 20:27:30 +02003260 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003261 """Connecting to an SSLv23 server with various client options"""
3262 if support.verbose:
3263 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003264 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003265 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003266 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003267 except OSError as x:
3268 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3269 if support.verbose:
3270 sys.stdout.write(
3271 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3272 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003273 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003274 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3275 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003276 if has_tls_version('TLSv1'):
3277 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003278
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003279 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003280 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3281 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003282 if has_tls_version('TLSv1'):
3283 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003284
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003285 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003286 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3287 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003288 if has_tls_version('TLSv1'):
3289 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003290
3291 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003292 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003293 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003294 server_options=ssl.OP_NO_SSLv3)
3295 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003296 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003297 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003298 if has_tls_version('TLSv1'):
3299 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3300 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003301
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003302 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003303 def test_protocol_sslv3(self):
3304 """Connecting to an SSLv3 server with various client options"""
3305 if support.verbose:
3306 sys.stdout.write("\n")
3307 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3308 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3309 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003310 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003311 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003312 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003313 client_options=ssl.OP_NO_SSLv3)
3314 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003315
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003316 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003317 def test_protocol_tlsv1(self):
3318 """Connecting to a TLSv1 server with various client options"""
3319 if support.verbose:
3320 sys.stdout.write("\n")
3321 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3322 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3323 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003324 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003325 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003326 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003327 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003328 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003329 client_options=ssl.OP_NO_TLSv1)
3330
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003331 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003332 def test_protocol_tlsv1_1(self):
3333 """Connecting to a TLSv1.1 server with various client options.
3334 Testing against older TLS versions."""
3335 if support.verbose:
3336 sys.stdout.write("\n")
3337 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003338 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003339 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003340 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003341 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003342 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003343 client_options=ssl.OP_NO_TLSv1_1)
3344
Christian Heimesa170fa12017-09-15 20:27:30 +02003345 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003346 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3347 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003348
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003349 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003350 def test_protocol_tlsv1_2(self):
3351 """Connecting to a TLSv1.2 server with various client options.
3352 Testing against older TLS versions."""
3353 if support.verbose:
3354 sys.stdout.write("\n")
3355 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3356 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3357 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003358 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003359 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003360 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003361 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003362 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003363 client_options=ssl.OP_NO_TLSv1_2)
3364
Christian Heimesa170fa12017-09-15 20:27:30 +02003365 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003366 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3367 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3368 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3369 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3370
3371 def test_starttls(self):
3372 """Switching from clear text to encrypted and back again."""
3373 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3374
3375 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003376 starttls_server=True,
3377 chatty=True,
3378 connectionchatty=True)
3379 wrapped = False
3380 with server:
3381 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003382 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003383 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003384 if support.verbose:
3385 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003386 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003387 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003388 sys.stdout.write(
3389 " client: sending %r...\n" % indata)
3390 if wrapped:
3391 conn.write(indata)
3392 outdata = conn.read()
3393 else:
3394 s.send(indata)
3395 outdata = s.recv(1024)
3396 msg = outdata.strip().lower()
3397 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3398 # STARTTLS ok, switch to secure mode
3399 if support.verbose:
3400 sys.stdout.write(
3401 " client: read %r from server, starting TLS...\n"
3402 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003403 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003404 wrapped = True
3405 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3406 # ENDTLS ok, switch back to clear text
3407 if support.verbose:
3408 sys.stdout.write(
3409 " client: read %r from server, ending TLS...\n"
3410 % msg)
3411 s = conn.unwrap()
3412 wrapped = False
3413 else:
3414 if support.verbose:
3415 sys.stdout.write(
3416 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003417 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003418 sys.stdout.write(" client: closing connection.\n")
3419 if wrapped:
3420 conn.write(b"over\n")
3421 else:
3422 s.send(b"over\n")
3423 if wrapped:
3424 conn.close()
3425 else:
3426 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003427
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003428 def test_socketserver(self):
3429 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003430 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003431 # try to connect
3432 if support.verbose:
3433 sys.stdout.write('\n')
3434 with open(CERTFILE, 'rb') as f:
3435 d1 = f.read()
3436 d2 = ''
3437 # now fetch the same data from the HTTPS server
3438 url = 'https://localhost:%d/%s' % (
3439 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003440 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003441 f = urllib.request.urlopen(url, context=context)
3442 try:
3443 dlen = f.info().get("content-length")
3444 if dlen and (int(dlen) > 0):
3445 d2 = f.read(int(dlen))
3446 if support.verbose:
3447 sys.stdout.write(
3448 " client: read %d bytes from remote server '%s'\n"
3449 % (len(d2), server))
3450 finally:
3451 f.close()
3452 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003453
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003454 def test_asyncore_server(self):
3455 """Check the example asyncore integration."""
3456 if support.verbose:
3457 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003458
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003459 indata = b"FOO\n"
3460 server = AsyncoreEchoServer(CERTFILE)
3461 with server:
3462 s = test_wrap_socket(socket.socket())
3463 s.connect(('127.0.0.1', server.port))
3464 if support.verbose:
3465 sys.stdout.write(
3466 " client: sending %r...\n" % indata)
3467 s.write(indata)
3468 outdata = s.read()
3469 if support.verbose:
3470 sys.stdout.write(" client: read %r\n" % outdata)
3471 if outdata != indata.lower():
3472 self.fail(
3473 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3474 % (outdata[:20], len(outdata),
3475 indata[:20].lower(), len(indata)))
3476 s.write(b"over\n")
3477 if support.verbose:
3478 sys.stdout.write(" client: closing connection.\n")
3479 s.close()
3480 if support.verbose:
3481 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003482
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003483 def test_recv_send(self):
3484 """Test recv(), send() and friends."""
3485 if support.verbose:
3486 sys.stdout.write("\n")
3487
3488 server = ThreadedEchoServer(CERTFILE,
3489 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003490 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003491 cacerts=CERTFILE,
3492 chatty=True,
3493 connectionchatty=False)
3494 with server:
3495 s = test_wrap_socket(socket.socket(),
3496 server_side=False,
3497 certfile=CERTFILE,
3498 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003499 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003500 s.connect((HOST, server.port))
3501 # helper methods for standardising recv* method signatures
3502 def _recv_into():
3503 b = bytearray(b"\0"*100)
3504 count = s.recv_into(b)
3505 return b[:count]
3506
3507 def _recvfrom_into():
3508 b = bytearray(b"\0"*100)
3509 count, addr = s.recvfrom_into(b)
3510 return b[:count]
3511
3512 # (name, method, expect success?, *args, return value func)
3513 send_methods = [
3514 ('send', s.send, True, [], len),
3515 ('sendto', s.sendto, False, ["some.address"], len),
3516 ('sendall', s.sendall, True, [], lambda x: None),
3517 ]
3518 # (name, method, whether to expect success, *args)
3519 recv_methods = [
3520 ('recv', s.recv, True, []),
3521 ('recvfrom', s.recvfrom, False, ["some.address"]),
3522 ('recv_into', _recv_into, True, []),
3523 ('recvfrom_into', _recvfrom_into, False, []),
3524 ]
3525 data_prefix = "PREFIX_"
3526
3527 for (meth_name, send_meth, expect_success, args,
3528 ret_val_meth) in send_methods:
3529 indata = (data_prefix + meth_name).encode('ascii')
3530 try:
3531 ret = send_meth(indata, *args)
3532 msg = "sending with {}".format(meth_name)
3533 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3534 outdata = s.read()
3535 if outdata != indata.lower():
3536 self.fail(
3537 "While sending with <<{name:s}>> bad data "
3538 "<<{outdata:r}>> ({nout:d}) received; "
3539 "expected <<{indata:r}>> ({nin:d})\n".format(
3540 name=meth_name, outdata=outdata[:20],
3541 nout=len(outdata),
3542 indata=indata[:20], nin=len(indata)
3543 )
3544 )
3545 except ValueError as e:
3546 if expect_success:
3547 self.fail(
3548 "Failed to send with method <<{name:s}>>; "
3549 "expected to succeed.\n".format(name=meth_name)
3550 )
3551 if not str(e).startswith(meth_name):
3552 self.fail(
3553 "Method <<{name:s}>> failed with unexpected "
3554 "exception message: {exp:s}\n".format(
3555 name=meth_name, exp=e
3556 )
3557 )
3558
3559 for meth_name, recv_meth, expect_success, args in recv_methods:
3560 indata = (data_prefix + meth_name).encode('ascii')
3561 try:
3562 s.send(indata)
3563 outdata = recv_meth(*args)
3564 if outdata != indata.lower():
3565 self.fail(
3566 "While receiving with <<{name:s}>> bad data "
3567 "<<{outdata:r}>> ({nout:d}) received; "
3568 "expected <<{indata:r}>> ({nin:d})\n".format(
3569 name=meth_name, outdata=outdata[:20],
3570 nout=len(outdata),
3571 indata=indata[:20], nin=len(indata)
3572 )
3573 )
3574 except ValueError as e:
3575 if expect_success:
3576 self.fail(
3577 "Failed to receive with method <<{name:s}>>; "
3578 "expected to succeed.\n".format(name=meth_name)
3579 )
3580 if not str(e).startswith(meth_name):
3581 self.fail(
3582 "Method <<{name:s}>> failed with unexpected "
3583 "exception message: {exp:s}\n".format(
3584 name=meth_name, exp=e
3585 )
3586 )
3587 # consume data
3588 s.read()
3589
3590 # read(-1, buffer) is supported, even though read(-1) is not
3591 data = b"data"
3592 s.send(data)
3593 buffer = bytearray(len(data))
3594 self.assertEqual(s.read(-1, buffer), len(data))
3595 self.assertEqual(buffer, data)
3596
Christian Heimes888bbdc2017-09-07 14:18:21 -07003597 # sendall accepts bytes-like objects
3598 if ctypes is not None:
3599 ubyte = ctypes.c_ubyte * len(data)
3600 byteslike = ubyte.from_buffer_copy(data)
3601 s.sendall(byteslike)
3602 self.assertEqual(s.read(), data)
3603
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003604 # Make sure sendmsg et al are disallowed to avoid
3605 # inadvertent disclosure of data and/or corruption
3606 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003607 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003608 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3609 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3610 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003611 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003612 s.write(b"over\n")
3613
3614 self.assertRaises(ValueError, s.recv, -1)
3615 self.assertRaises(ValueError, s.read, -1)
3616
3617 s.close()
3618
3619 def test_recv_zero(self):
3620 server = ThreadedEchoServer(CERTFILE)
3621 server.__enter__()
3622 self.addCleanup(server.__exit__, None, None)
3623 s = socket.create_connection((HOST, server.port))
3624 self.addCleanup(s.close)
3625 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3626 self.addCleanup(s.close)
3627
3628 # recv/read(0) should return no data
3629 s.send(b"data")
3630 self.assertEqual(s.recv(0), b"")
3631 self.assertEqual(s.read(0), b"")
3632 self.assertEqual(s.read(), b"data")
3633
3634 # Should not block if the other end sends no data
3635 s.setblocking(False)
3636 self.assertEqual(s.recv(0), b"")
3637 self.assertEqual(s.recv_into(bytearray()), 0)
3638
3639 def test_nonblocking_send(self):
3640 server = ThreadedEchoServer(CERTFILE,
3641 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003642 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003643 cacerts=CERTFILE,
3644 chatty=True,
3645 connectionchatty=False)
3646 with server:
3647 s = test_wrap_socket(socket.socket(),
3648 server_side=False,
3649 certfile=CERTFILE,
3650 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003651 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003652 s.connect((HOST, server.port))
3653 s.setblocking(False)
3654
3655 # If we keep sending data, at some point the buffers
3656 # will be full and the call will block
3657 buf = bytearray(8192)
3658 def fill_buffer():
3659 while True:
3660 s.send(buf)
3661 self.assertRaises((ssl.SSLWantWriteError,
3662 ssl.SSLWantReadError), fill_buffer)
3663
3664 # Now read all the output and discard it
3665 s.setblocking(True)
3666 s.close()
3667
3668 def test_handshake_timeout(self):
3669 # Issue #5103: SSL handshake must respect the socket timeout
3670 server = socket.socket(socket.AF_INET)
3671 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003672 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003673 started = threading.Event()
3674 finish = False
3675
3676 def serve():
3677 server.listen()
3678 started.set()
3679 conns = []
3680 while not finish:
3681 r, w, e = select.select([server], [], [], 0.1)
3682 if server in r:
3683 # Let the socket hang around rather than having
3684 # it closed by garbage collection.
3685 conns.append(server.accept()[0])
3686 for sock in conns:
3687 sock.close()
3688
3689 t = threading.Thread(target=serve)
3690 t.start()
3691 started.wait()
3692
3693 try:
3694 try:
3695 c = socket.socket(socket.AF_INET)
3696 c.settimeout(0.2)
3697 c.connect((host, port))
3698 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003699 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003700 test_wrap_socket, c)
3701 finally:
3702 c.close()
3703 try:
3704 c = socket.socket(socket.AF_INET)
3705 c = test_wrap_socket(c)
3706 c.settimeout(0.2)
3707 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003708 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003709 c.connect, (host, port))
3710 finally:
3711 c.close()
3712 finally:
3713 finish = True
3714 t.join()
3715 server.close()
3716
3717 def test_server_accept(self):
3718 # Issue #16357: accept() on a SSLSocket created through
3719 # SSLContext.wrap_socket().
Christian Heimes2875c602021-04-19 07:27:10 +02003720 client_ctx, server_ctx, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003721 server = socket.socket(socket.AF_INET)
3722 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003723 port = socket_helper.bind_port(server)
Christian Heimes2875c602021-04-19 07:27:10 +02003724 server = server_ctx.wrap_socket(server, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003725 self.assertTrue(server.server_side)
3726
3727 evt = threading.Event()
3728 remote = None
3729 peer = None
3730 def serve():
3731 nonlocal remote, peer
3732 server.listen()
3733 # Block on the accept and wait on the connection to close.
3734 evt.set()
3735 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003736 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003737
3738 t = threading.Thread(target=serve)
3739 t.start()
3740 # Client wait until server setup and perform a connect.
3741 evt.wait()
Christian Heimes2875c602021-04-19 07:27:10 +02003742 client = client_ctx.wrap_socket(
3743 socket.socket(), server_hostname=hostname
3744 )
3745 client.connect((hostname, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003746 client.send(b'data')
3747 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003748 client_addr = client.getsockname()
3749 client.close()
3750 t.join()
3751 remote.close()
3752 server.close()
3753 # Sanity checks.
3754 self.assertIsInstance(remote, ssl.SSLSocket)
3755 self.assertEqual(peer, client_addr)
3756
3757 def test_getpeercert_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003758 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3759 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003760 with context.wrap_socket(socket.socket()) as sock:
3761 with self.assertRaises(OSError) as cm:
3762 sock.getpeercert()
3763 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3764
3765 def test_do_handshake_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.do_handshake()
3771 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3772
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003773 def test_no_shared_ciphers(self):
3774 client_context, server_context, hostname = testing_context()
3775 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3776 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003777 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003778 client_context.set_ciphers("AES128")
3779 server_context.set_ciphers("AES256")
3780 with ThreadedEchoServer(context=server_context) as server:
3781 with client_context.wrap_socket(socket.socket(),
3782 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003783 with self.assertRaises(OSError):
3784 s.connect((HOST, server.port))
3785 self.assertIn("no shared cipher", server.conn_errors[0])
3786
3787 def test_version_basic(self):
3788 """
3789 Basic tests for SSLSocket.version().
3790 More tests are done in the test_protocol_*() methods.
3791 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003792 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3793 context.check_hostname = False
3794 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003795 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003796 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003797 chatty=False) as server:
3798 with context.wrap_socket(socket.socket()) as s:
3799 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003800 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003801 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003802 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003803 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003804 self.assertIs(s.version(), None)
3805
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003806 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003807 def test_tls1_3(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003808 client_context, server_context, hostname = testing_context()
3809 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3810 with ThreadedEchoServer(context=server_context) as server:
3811 with client_context.wrap_socket(socket.socket(),
3812 server_hostname=hostname) as s:
Christian Heimescb5b68a2017-09-07 18:07:00 -07003813 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003814 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003815 'TLS_AES_256_GCM_SHA384',
3816 'TLS_CHACHA20_POLY1305_SHA256',
3817 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003818 })
3819 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003820
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003821 @requires_tls_version('TLSv1_2')
Christian Heimes2875c602021-04-19 07:27:10 +02003822 @requires_tls_version('TLSv1')
3823 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003824 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003825 client_context, server_context, hostname = testing_context()
3826 # client TLSv1.0 to 1.2
3827 client_context.minimum_version = ssl.TLSVersion.TLSv1
3828 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3829 # server only TLSv1.2
3830 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3831 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3832
3833 with ThreadedEchoServer(context=server_context) as server:
3834 with client_context.wrap_socket(socket.socket(),
3835 server_hostname=hostname) as s:
3836 s.connect((HOST, server.port))
3837 self.assertEqual(s.version(), 'TLSv1.2')
3838
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003839 @requires_tls_version('TLSv1_1')
Christian Heimes2875c602021-04-19 07:27:10 +02003840 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003841 def test_min_max_version_tlsv1_1(self):
3842 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003843 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003844 client_context.minimum_version = ssl.TLSVersion.TLSv1
3845 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003846 server_context.minimum_version = ssl.TLSVersion.TLSv1
3847 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003848 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003849
3850 with ThreadedEchoServer(context=server_context) as server:
3851 with client_context.wrap_socket(socket.socket(),
3852 server_hostname=hostname) as s:
3853 s.connect((HOST, server.port))
3854 self.assertEqual(s.version(), 'TLSv1.1')
3855
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003856 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003857 @requires_tls_version('TLSv1')
Christian Heimes2875c602021-04-19 07:27:10 +02003858 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003859 def test_min_max_version_mismatch(self):
3860 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003861 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003862 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003863 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003864 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003865 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003866 seclevel_workaround(client_context, server_context)
3867
Christian Heimes698dde12018-02-27 11:54:43 +01003868 with ThreadedEchoServer(context=server_context) as server:
3869 with client_context.wrap_socket(socket.socket(),
3870 server_hostname=hostname) as s:
3871 with self.assertRaises(ssl.SSLError) as e:
3872 s.connect((HOST, server.port))
3873 self.assertIn("alert", str(e.exception))
3874
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003875 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003876 def test_min_max_version_sslv3(self):
3877 client_context, server_context, hostname = testing_context()
3878 server_context.minimum_version = ssl.TLSVersion.SSLv3
3879 client_context.minimum_version = ssl.TLSVersion.SSLv3
3880 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003881 seclevel_workaround(client_context, server_context)
3882
Christian Heimes698dde12018-02-27 11:54:43 +01003883 with ThreadedEchoServer(context=server_context) as server:
3884 with client_context.wrap_socket(socket.socket(),
3885 server_hostname=hostname) as s:
3886 s.connect((HOST, server.port))
3887 self.assertEqual(s.version(), 'SSLv3')
3888
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003889 def test_default_ecdh_curve(self):
3890 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3891 # should be enabled by default on SSL contexts.
Christian Heimes2875c602021-04-19 07:27:10 +02003892 client_context, server_context, hostname = testing_context()
Christian Heimescb5b68a2017-09-07 18:07:00 -07003893 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3894 # cipher name.
Christian Heimes2875c602021-04-19 07:27:10 +02003895 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003896 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3897 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3898 # our default cipher list should prefer ECDH-based ciphers
3899 # automatically.
Christian Heimes2875c602021-04-19 07:27:10 +02003900 with ThreadedEchoServer(context=server_context) as server:
3901 with client_context.wrap_socket(socket.socket(),
3902 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003903 s.connect((HOST, server.port))
3904 self.assertIn("ECDH", s.cipher()[0])
3905
3906 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3907 "'tls-unique' channel binding not available")
3908 def test_tls_unique_channel_binding(self):
3909 """Test tls-unique channel binding."""
3910 if support.verbose:
3911 sys.stdout.write("\n")
3912
Christian Heimes05d9fe32018-02-27 08:55:39 +01003913 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003914
3915 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003916 chatty=True,
3917 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003918
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003919 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003920 with client_context.wrap_socket(
3921 socket.socket(),
3922 server_hostname=hostname) as s:
3923 s.connect((HOST, server.port))
3924 # get the data
3925 cb_data = s.get_channel_binding("tls-unique")
3926 if support.verbose:
3927 sys.stdout.write(
3928 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003929
Christian Heimes05d9fe32018-02-27 08:55:39 +01003930 # check if it is sane
3931 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003932 if s.version() == 'TLSv1.3':
3933 self.assertEqual(len(cb_data), 48)
3934 else:
3935 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003936
Christian Heimes05d9fe32018-02-27 08:55:39 +01003937 # and compare with the peers version
3938 s.write(b"CB tls-unique\n")
3939 peer_data_repr = s.read().strip()
3940 self.assertEqual(peer_data_repr,
3941 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003942
3943 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003944 with client_context.wrap_socket(
3945 socket.socket(),
3946 server_hostname=hostname) as s:
3947 s.connect((HOST, server.port))
3948 new_cb_data = s.get_channel_binding("tls-unique")
3949 if support.verbose:
3950 sys.stdout.write(
3951 "got another channel binding data: {0!r}\n".format(
3952 new_cb_data)
3953 )
3954 # is it really unique
3955 self.assertNotEqual(cb_data, new_cb_data)
3956 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003957 if s.version() == 'TLSv1.3':
3958 self.assertEqual(len(cb_data), 48)
3959 else:
3960 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003961 s.write(b"CB tls-unique\n")
3962 peer_data_repr = s.read().strip()
3963 self.assertEqual(peer_data_repr,
3964 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003965
3966 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003967 client_context, server_context, hostname = testing_context()
3968 stats = server_params_test(client_context, server_context,
3969 chatty=True, connectionchatty=True,
3970 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003971 if support.verbose:
3972 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
3973 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
3974
3975 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
3976 "ssl.OP_NO_COMPRESSION needed for this test")
3977 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003978 client_context, server_context, hostname = testing_context()
3979 client_context.options |= ssl.OP_NO_COMPRESSION
3980 server_context.options |= ssl.OP_NO_COMPRESSION
3981 stats = server_params_test(client_context, server_context,
3982 chatty=True, connectionchatty=True,
3983 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003984 self.assertIs(stats['compression'], None)
3985
Paul Monsonf3550692019-06-19 13:09:54 -07003986 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003987 def test_dh_params(self):
3988 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02003989 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003990 # test scenario needs TLS <= 1.2
3991 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02003992 server_context.load_dh_params(DHFILE)
3993 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01003994 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02003995 stats = server_params_test(client_context, server_context,
3996 chatty=True, connectionchatty=True,
3997 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003998 cipher = stats["cipher"][0]
3999 parts = cipher.split("-")
4000 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4001 self.fail("Non-DH cipher: " + cipher[0])
4002
Christian Heimesb7b92252018-02-25 09:49:31 +01004003 def test_ecdh_curve(self):
4004 # server secp384r1, client auto
4005 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004006
Christian Heimesb7b92252018-02-25 09:49:31 +01004007 server_context.set_ecdh_curve("secp384r1")
4008 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004009 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004010 stats = server_params_test(client_context, server_context,
4011 chatty=True, connectionchatty=True,
4012 sni_name=hostname)
4013
4014 # server auto, client secp384r1
4015 client_context, server_context, hostname = testing_context()
4016 client_context.set_ecdh_curve("secp384r1")
4017 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004018 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004019 stats = server_params_test(client_context, server_context,
4020 chatty=True, connectionchatty=True,
4021 sni_name=hostname)
4022
4023 # server / client curve mismatch
4024 client_context, server_context, hostname = testing_context()
4025 client_context.set_ecdh_curve("prime256v1")
4026 server_context.set_ecdh_curve("secp384r1")
4027 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004028 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
4029 with self.assertRaises(ssl.SSLError):
Christian Heimes39258d32021-04-17 11:36:35 +02004030 server_params_test(client_context, server_context,
4031 chatty=True, connectionchatty=True,
4032 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004033
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004034 def test_selected_alpn_protocol(self):
4035 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004036 client_context, server_context, hostname = testing_context()
4037 stats = server_params_test(client_context, server_context,
4038 chatty=True, connectionchatty=True,
4039 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004040 self.assertIs(stats['client_alpn_protocol'], None)
4041
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004042 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4043 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004044 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004045 server_context.set_alpn_protocols(['foo', 'bar'])
4046 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004047 chatty=True, connectionchatty=True,
4048 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004049 self.assertIs(stats['client_alpn_protocol'], None)
4050
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004051 def test_alpn_protocols(self):
4052 server_protocols = ['foo', 'bar', 'milkshake']
4053 protocol_tests = [
4054 (['foo', 'bar'], 'foo'),
4055 (['bar', 'foo'], 'foo'),
4056 (['milkshake'], 'milkshake'),
4057 (['http/3.0', 'http/4.0'], None)
4058 ]
4059 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004060 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004061 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004062 client_context.set_alpn_protocols(client_protocols)
4063
4064 try:
4065 stats = server_params_test(client_context,
4066 server_context,
4067 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004068 connectionchatty=True,
4069 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004070 except ssl.SSLError as e:
4071 stats = e
4072
Christian Heimes39258d32021-04-17 11:36:35 +02004073 msg = "failed trying %s (s) and %s (c).\n" \
4074 "was expecting %s, but got %%s from the %%s" \
4075 % (str(server_protocols), str(client_protocols),
4076 str(expected))
4077 client_result = stats['client_alpn_protocol']
4078 self.assertEqual(client_result, expected,
4079 msg % (client_result, "client"))
4080 server_result = stats['server_alpn_protocols'][-1] \
4081 if len(stats['server_alpn_protocols']) else 'nothing'
4082 self.assertEqual(server_result, expected,
4083 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004084
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004085 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004086 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004087
4088 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004089 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004090 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004091 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004092 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004093 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004094 client_context.load_verify_locations(SIGNING_CA)
4095 return server_context, other_context, client_context
4096
4097 def check_common_name(self, stats, name):
4098 cert = stats['peercert']
4099 self.assertIn((('commonName', name),), cert['subject'])
4100
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004101 def test_sni_callback(self):
4102 calls = []
4103 server_context, other_context, client_context = self.sni_contexts()
4104
Christian Heimesa170fa12017-09-15 20:27:30 +02004105 client_context.check_hostname = False
4106
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004107 def servername_cb(ssl_sock, server_name, initial_context):
4108 calls.append((server_name, initial_context))
4109 if server_name is not None:
4110 ssl_sock.context = other_context
4111 server_context.set_servername_callback(servername_cb)
4112
4113 stats = server_params_test(client_context, server_context,
4114 chatty=True,
4115 sni_name='supermessage')
4116 # The hostname was fetched properly, and the certificate was
4117 # changed for the connection.
4118 self.assertEqual(calls, [("supermessage", server_context)])
4119 # CERTFILE4 was selected
4120 self.check_common_name(stats, 'fakehostname')
4121
4122 calls = []
4123 # The callback is called with server_name=None
4124 stats = server_params_test(client_context, server_context,
4125 chatty=True,
4126 sni_name=None)
4127 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004128 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004129
4130 # Check disabling the callback
4131 calls = []
4132 server_context.set_servername_callback(None)
4133
4134 stats = server_params_test(client_context, server_context,
4135 chatty=True,
4136 sni_name='notfunny')
4137 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004138 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004139 self.assertEqual(calls, [])
4140
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004141 def test_sni_callback_alert(self):
4142 # Returning a TLS alert is reflected to the connecting client
4143 server_context, other_context, client_context = self.sni_contexts()
4144
4145 def cb_returning_alert(ssl_sock, server_name, initial_context):
4146 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4147 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004148 with self.assertRaises(ssl.SSLError) as cm:
4149 stats = server_params_test(client_context, server_context,
4150 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004151 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004152 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004153
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004154 def test_sni_callback_raising(self):
4155 # Raising fails the connection with a TLS handshake failure alert.
4156 server_context, other_context, client_context = self.sni_contexts()
4157
4158 def cb_raising(ssl_sock, server_name, initial_context):
4159 1/0
4160 server_context.set_servername_callback(cb_raising)
4161
Victor Stinner00253502019-06-03 03:51:43 +02004162 with support.catch_unraisable_exception() as catch:
4163 with self.assertRaises(ssl.SSLError) as cm:
4164 stats = server_params_test(client_context, server_context,
4165 chatty=False,
4166 sni_name='supermessage')
4167
4168 self.assertEqual(cm.exception.reason,
4169 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4170 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004171
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004172 def test_sni_callback_wrong_return_type(self):
4173 # Returning the wrong return type terminates the TLS connection
4174 # with an internal error alert.
4175 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004176
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004177 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4178 return "foo"
4179 server_context.set_servername_callback(cb_wrong_return_type)
4180
Victor Stinner00253502019-06-03 03:51:43 +02004181 with support.catch_unraisable_exception() as catch:
4182 with self.assertRaises(ssl.SSLError) as cm:
4183 stats = server_params_test(client_context, server_context,
4184 chatty=False,
4185 sni_name='supermessage')
4186
4187
4188 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4189 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004190
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004191 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004192 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004193 client_context.set_ciphers("AES128:AES256")
4194 server_context.set_ciphers("AES256")
4195 expected_algs = [
4196 "AES256", "AES-256",
4197 # TLS 1.3 ciphers are always enabled
4198 "TLS_CHACHA20", "TLS_AES",
4199 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004200
Christian Heimesa170fa12017-09-15 20:27:30 +02004201 stats = server_params_test(client_context, server_context,
4202 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004203 ciphers = stats['server_shared_ciphers'][0]
4204 self.assertGreater(len(ciphers), 0)
4205 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004206 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004207 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004208
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004209 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004210 client_context, server_context, hostname = testing_context()
4211 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004212
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004213 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004214 s = client_context.wrap_socket(socket.socket(),
4215 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004216 s.connect((HOST, server.port))
4217 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004218
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004219 self.assertRaises(ValueError, s.read, 1024)
4220 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004221
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004222 def test_sendfile(self):
4223 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004224 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004225 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004226 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimes2875c602021-04-19 07:27:10 +02004227 client_context, server_context, hostname = testing_context()
4228 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004229 with server:
Christian Heimes2875c602021-04-19 07:27:10 +02004230 with client_context.wrap_socket(socket.socket(),
4231 server_hostname=hostname) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004232 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004233 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004234 s.sendfile(file)
4235 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004236
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004237 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004238 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004239 # TODO: sessions aren't compatible with TLSv1.3 yet
4240 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004241
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004242 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004243 stats = server_params_test(client_context, server_context,
4244 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004245 session = stats['session']
4246 self.assertTrue(session.id)
4247 self.assertGreater(session.time, 0)
4248 self.assertGreater(session.timeout, 0)
4249 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004250 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004251 self.assertFalse(stats['session_reused'])
4252 sess_stat = server_context.session_stats()
4253 self.assertEqual(sess_stat['accept'], 1)
4254 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004255
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004256 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004257 stats = server_params_test(client_context, server_context,
4258 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004259 sess_stat = server_context.session_stats()
4260 self.assertEqual(sess_stat['accept'], 2)
4261 self.assertEqual(sess_stat['hits'], 1)
4262 self.assertTrue(stats['session_reused'])
4263 session2 = stats['session']
4264 self.assertEqual(session2.id, session.id)
4265 self.assertEqual(session2, session)
4266 self.assertIsNot(session2, session)
4267 self.assertGreaterEqual(session2.time, session.time)
4268 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004269
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004270 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004271 stats = server_params_test(client_context, server_context,
4272 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004273 self.assertFalse(stats['session_reused'])
4274 session3 = stats['session']
4275 self.assertNotEqual(session3.id, session.id)
4276 self.assertNotEqual(session3, session)
4277 sess_stat = server_context.session_stats()
4278 self.assertEqual(sess_stat['accept'], 3)
4279 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004280
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004281 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004282 stats = server_params_test(client_context, server_context,
4283 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004284 self.assertTrue(stats['session_reused'])
4285 session4 = stats['session']
4286 self.assertEqual(session4.id, session.id)
4287 self.assertEqual(session4, session)
4288 self.assertGreaterEqual(session4.time, session.time)
4289 self.assertGreaterEqual(session4.timeout, session.timeout)
4290 sess_stat = server_context.session_stats()
4291 self.assertEqual(sess_stat['accept'], 4)
4292 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004293
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004294 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004295 client_context, server_context, hostname = testing_context()
4296 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004297
Christian Heimes05d9fe32018-02-27 08:55:39 +01004298 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004299 client_context.options |= ssl.OP_NO_TLSv1_3
4300 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004301
Christian Heimesa170fa12017-09-15 20:27:30 +02004302 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004303 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004304 with client_context.wrap_socket(socket.socket(),
4305 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004306 # session is None before handshake
4307 self.assertEqual(s.session, None)
4308 self.assertEqual(s.session_reused, None)
4309 s.connect((HOST, server.port))
4310 session = s.session
4311 self.assertTrue(session)
4312 with self.assertRaises(TypeError) as e:
4313 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004314 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004315
Christian Heimesa170fa12017-09-15 20:27:30 +02004316 with client_context.wrap_socket(socket.socket(),
4317 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004318 s.connect((HOST, server.port))
4319 # cannot set session after handshake
4320 with self.assertRaises(ValueError) as e:
4321 s.session = session
4322 self.assertEqual(str(e.exception),
4323 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004324
Christian Heimesa170fa12017-09-15 20:27:30 +02004325 with client_context.wrap_socket(socket.socket(),
4326 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004327 # can set session before handshake and before the
4328 # connection was established
4329 s.session = session
4330 s.connect((HOST, server.port))
4331 self.assertEqual(s.session.id, session.id)
4332 self.assertEqual(s.session, session)
4333 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004334
Christian Heimesa170fa12017-09-15 20:27:30 +02004335 with client_context2.wrap_socket(socket.socket(),
4336 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004337 # cannot re-use session with a different SSLContext
4338 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004339 s.session = session
4340 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004341 self.assertEqual(str(e.exception),
4342 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004343
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004344
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004345@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004346class TestPostHandshakeAuth(unittest.TestCase):
4347 def test_pha_setter(self):
4348 protocols = [
Christian Heimes2875c602021-04-19 07:27:10 +02004349 ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
Christian Heimes9fb051f2018-09-23 08:32:31 +02004350 ]
4351 for protocol in protocols:
4352 ctx = ssl.SSLContext(protocol)
4353 self.assertEqual(ctx.post_handshake_auth, False)
4354
4355 ctx.post_handshake_auth = True
4356 self.assertEqual(ctx.post_handshake_auth, True)
4357
4358 ctx.verify_mode = ssl.CERT_REQUIRED
4359 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4360 self.assertEqual(ctx.post_handshake_auth, True)
4361
4362 ctx.post_handshake_auth = False
4363 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4364 self.assertEqual(ctx.post_handshake_auth, False)
4365
4366 ctx.verify_mode = ssl.CERT_OPTIONAL
4367 ctx.post_handshake_auth = True
4368 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4369 self.assertEqual(ctx.post_handshake_auth, True)
4370
4371 def test_pha_required(self):
4372 client_context, server_context, hostname = testing_context()
4373 server_context.post_handshake_auth = True
4374 server_context.verify_mode = ssl.CERT_REQUIRED
4375 client_context.post_handshake_auth = True
4376 client_context.load_cert_chain(SIGNED_CERTFILE)
4377
4378 server = ThreadedEchoServer(context=server_context, chatty=False)
4379 with server:
4380 with client_context.wrap_socket(socket.socket(),
4381 server_hostname=hostname) as s:
4382 s.connect((HOST, server.port))
4383 s.write(b'HASCERT')
4384 self.assertEqual(s.recv(1024), b'FALSE\n')
4385 s.write(b'PHA')
4386 self.assertEqual(s.recv(1024), b'OK\n')
4387 s.write(b'HASCERT')
4388 self.assertEqual(s.recv(1024), b'TRUE\n')
4389 # PHA method just returns true when cert is already available
4390 s.write(b'PHA')
4391 self.assertEqual(s.recv(1024), b'OK\n')
4392 s.write(b'GETCERT')
4393 cert_text = s.recv(4096).decode('us-ascii')
4394 self.assertIn('Python Software Foundation CA', cert_text)
4395
4396 def test_pha_required_nocert(self):
4397 client_context, server_context, hostname = testing_context()
4398 server_context.post_handshake_auth = True
4399 server_context.verify_mode = ssl.CERT_REQUIRED
4400 client_context.post_handshake_auth = True
4401
Victor Stinner73ea5462019-07-09 14:33:49 +02004402 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4403 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004404 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004405 server = ThreadedEchoServer(context=server_context, chatty=False)
4406 with server:
4407 with client_context.wrap_socket(socket.socket(),
4408 server_hostname=hostname) as s:
4409 s.connect((HOST, server.port))
4410 s.write(b'PHA')
4411 # receive CertificateRequest
4412 self.assertEqual(s.recv(1024), b'OK\n')
4413 # send empty Certificate + Finish
4414 s.write(b'HASCERT')
4415 # receive alert
4416 with self.assertRaisesRegex(
4417 ssl.SSLError,
4418 'tlsv13 alert certificate required'):
4419 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004420
4421 def test_pha_optional(self):
4422 if support.verbose:
4423 sys.stdout.write("\n")
4424
4425 client_context, server_context, hostname = testing_context()
4426 server_context.post_handshake_auth = True
4427 server_context.verify_mode = ssl.CERT_REQUIRED
4428 client_context.post_handshake_auth = True
4429 client_context.load_cert_chain(SIGNED_CERTFILE)
4430
4431 # check CERT_OPTIONAL
4432 server_context.verify_mode = ssl.CERT_OPTIONAL
4433 server = ThreadedEchoServer(context=server_context, chatty=False)
4434 with server:
4435 with client_context.wrap_socket(socket.socket(),
4436 server_hostname=hostname) as s:
4437 s.connect((HOST, server.port))
4438 s.write(b'HASCERT')
4439 self.assertEqual(s.recv(1024), b'FALSE\n')
4440 s.write(b'PHA')
4441 self.assertEqual(s.recv(1024), b'OK\n')
4442 s.write(b'HASCERT')
4443 self.assertEqual(s.recv(1024), b'TRUE\n')
4444
4445 def test_pha_optional_nocert(self):
4446 if support.verbose:
4447 sys.stdout.write("\n")
4448
4449 client_context, server_context, hostname = testing_context()
4450 server_context.post_handshake_auth = True
4451 server_context.verify_mode = ssl.CERT_OPTIONAL
4452 client_context.post_handshake_auth = True
4453
4454 server = ThreadedEchoServer(context=server_context, chatty=False)
4455 with server:
4456 with client_context.wrap_socket(socket.socket(),
4457 server_hostname=hostname) as s:
4458 s.connect((HOST, server.port))
4459 s.write(b'HASCERT')
4460 self.assertEqual(s.recv(1024), b'FALSE\n')
4461 s.write(b'PHA')
4462 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004463 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004464 s.write(b'HASCERT')
4465 self.assertEqual(s.recv(1024), b'FALSE\n')
4466
4467 def test_pha_no_pha_client(self):
4468 client_context, server_context, hostname = testing_context()
4469 server_context.post_handshake_auth = True
4470 server_context.verify_mode = ssl.CERT_REQUIRED
4471 client_context.load_cert_chain(SIGNED_CERTFILE)
4472
4473 server = ThreadedEchoServer(context=server_context, chatty=False)
4474 with server:
4475 with client_context.wrap_socket(socket.socket(),
4476 server_hostname=hostname) as s:
4477 s.connect((HOST, server.port))
4478 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4479 s.verify_client_post_handshake()
4480 s.write(b'PHA')
4481 self.assertIn(b'extension not received', s.recv(1024))
4482
4483 def test_pha_no_pha_server(self):
4484 # server doesn't have PHA enabled, cert is requested in handshake
4485 client_context, server_context, hostname = testing_context()
4486 server_context.verify_mode = ssl.CERT_REQUIRED
4487 client_context.post_handshake_auth = True
4488 client_context.load_cert_chain(SIGNED_CERTFILE)
4489
4490 server = ThreadedEchoServer(context=server_context, chatty=False)
4491 with server:
4492 with client_context.wrap_socket(socket.socket(),
4493 server_hostname=hostname) as s:
4494 s.connect((HOST, server.port))
4495 s.write(b'HASCERT')
4496 self.assertEqual(s.recv(1024), b'TRUE\n')
4497 # PHA doesn't fail if there is already a cert
4498 s.write(b'PHA')
4499 self.assertEqual(s.recv(1024), b'OK\n')
4500 s.write(b'HASCERT')
4501 self.assertEqual(s.recv(1024), b'TRUE\n')
4502
4503 def test_pha_not_tls13(self):
4504 # TLS 1.2
4505 client_context, server_context, hostname = testing_context()
4506 server_context.verify_mode = ssl.CERT_REQUIRED
4507 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4508 client_context.post_handshake_auth = True
4509 client_context.load_cert_chain(SIGNED_CERTFILE)
4510
4511 server = ThreadedEchoServer(context=server_context, chatty=False)
4512 with server:
4513 with client_context.wrap_socket(socket.socket(),
4514 server_hostname=hostname) as s:
4515 s.connect((HOST, server.port))
4516 # PHA fails for TLS != 1.3
4517 s.write(b'PHA')
4518 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4519
Christian Heimesf0f59302019-07-01 08:29:17 +02004520 def test_bpo37428_pha_cert_none(self):
4521 # verify that post_handshake_auth does not implicitly enable cert
4522 # validation.
4523 hostname = SIGNED_CERTFILE_HOSTNAME
4524 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4525 client_context.post_handshake_auth = True
4526 client_context.load_cert_chain(SIGNED_CERTFILE)
4527 # no cert validation and CA on client side
4528 client_context.check_hostname = False
4529 client_context.verify_mode = ssl.CERT_NONE
4530
4531 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4532 server_context.load_cert_chain(SIGNED_CERTFILE)
4533 server_context.load_verify_locations(SIGNING_CA)
4534 server_context.post_handshake_auth = True
4535 server_context.verify_mode = ssl.CERT_REQUIRED
4536
4537 server = ThreadedEchoServer(context=server_context, chatty=False)
4538 with server:
4539 with client_context.wrap_socket(socket.socket(),
4540 server_hostname=hostname) as s:
4541 s.connect((HOST, server.port))
4542 s.write(b'HASCERT')
4543 self.assertEqual(s.recv(1024), b'FALSE\n')
4544 s.write(b'PHA')
4545 self.assertEqual(s.recv(1024), b'OK\n')
4546 s.write(b'HASCERT')
4547 self.assertEqual(s.recv(1024), b'TRUE\n')
4548 # server cert has not been validated
4549 self.assertEqual(s.getpeercert(), {})
4550
Christian Heimes9fb051f2018-09-23 08:32:31 +02004551
Christian Heimesc7f70692019-05-31 11:44:05 +02004552HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4553requires_keylog = unittest.skipUnless(
4554 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4555
4556class TestSSLDebug(unittest.TestCase):
4557
Hai Shia7f5d932020-08-04 00:41:24 +08004558 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004559 with open(fname) as f:
4560 return len(list(f))
4561
4562 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004563 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004564 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004565 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004566 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4567 self.assertEqual(ctx.keylog_filename, None)
4568
Hai Shia7f5d932020-08-04 00:41:24 +08004569 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4570 ctx.keylog_filename = os_helper.TESTFN
4571 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4572 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004573 self.assertEqual(self.keylog_lines(), 1)
4574
4575 ctx.keylog_filename = None
4576 self.assertEqual(ctx.keylog_filename, None)
4577
4578 with self.assertRaises((IsADirectoryError, PermissionError)):
4579 # Windows raises PermissionError
4580 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004581 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004582
4583 with self.assertRaises(TypeError):
4584 ctx.keylog_filename = 1
4585
4586 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004587 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004588 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004589 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004590 client_context, server_context, hostname = testing_context()
4591
Hai Shia7f5d932020-08-04 00:41:24 +08004592 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004593 server = ThreadedEchoServer(context=server_context, chatty=False)
4594 with server:
4595 with client_context.wrap_socket(socket.socket(),
4596 server_hostname=hostname) as s:
4597 s.connect((HOST, server.port))
4598 # header, 5 lines for TLS 1.3
4599 self.assertEqual(self.keylog_lines(), 6)
4600
4601 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004602 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004603 server = ThreadedEchoServer(context=server_context, chatty=False)
4604 with server:
4605 with client_context.wrap_socket(socket.socket(),
4606 server_hostname=hostname) as s:
4607 s.connect((HOST, server.port))
4608 self.assertGreaterEqual(self.keylog_lines(), 11)
4609
Hai Shia7f5d932020-08-04 00:41:24 +08004610 client_context.keylog_filename = os_helper.TESTFN
4611 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004612 server = ThreadedEchoServer(context=server_context, chatty=False)
4613 with server:
4614 with client_context.wrap_socket(socket.socket(),
4615 server_hostname=hostname) as s:
4616 s.connect((HOST, server.port))
4617 self.assertGreaterEqual(self.keylog_lines(), 21)
4618
4619 client_context.keylog_filename = None
4620 server_context.keylog_filename = None
4621
4622 @requires_keylog
4623 @unittest.skipIf(sys.flags.ignore_environment,
4624 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004625 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004626 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004627 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004628 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004629 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4630 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004631
4632 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4633 self.assertEqual(ctx.keylog_filename, None)
4634
4635 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004636 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004637
4638 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004639 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004640
4641 def test_msg_callback(self):
4642 client_context, server_context, hostname = testing_context()
4643
4644 def msg_cb(conn, direction, version, content_type, msg_type, data):
4645 pass
4646
4647 self.assertIs(client_context._msg_callback, None)
4648 client_context._msg_callback = msg_cb
4649 self.assertIs(client_context._msg_callback, msg_cb)
4650 with self.assertRaises(TypeError):
4651 client_context._msg_callback = object()
4652
4653 def test_msg_callback_tls12(self):
4654 client_context, server_context, hostname = testing_context()
4655 client_context.options |= ssl.OP_NO_TLSv1_3
4656
4657 msg = []
4658
4659 def msg_cb(conn, direction, version, content_type, msg_type, data):
4660 self.assertIsInstance(conn, ssl.SSLSocket)
4661 self.assertIsInstance(data, bytes)
4662 self.assertIn(direction, {'read', 'write'})
4663 msg.append((direction, version, content_type, msg_type))
4664
4665 client_context._msg_callback = msg_cb
4666
4667 server = ThreadedEchoServer(context=server_context, chatty=False)
4668 with server:
4669 with client_context.wrap_socket(socket.socket(),
4670 server_hostname=hostname) as s:
4671 s.connect((HOST, server.port))
4672
Christian Heimese35d1ba2019-06-03 20:40:15 +02004673 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004674 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4675 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004676 msg
4677 )
4678 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004679 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4680 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004681 msg
4682 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004683
Christian Heimes77cde502021-03-21 16:13:09 +01004684 def test_msg_callback_deadlock_bpo43577(self):
4685 client_context, server_context, hostname = testing_context()
4686 server_context2 = testing_context()[1]
4687
4688 def msg_cb(conn, direction, version, content_type, msg_type, data):
4689 pass
4690
4691 def sni_cb(sock, servername, ctx):
4692 sock.context = server_context2
4693
4694 server_context._msg_callback = msg_cb
4695 server_context.sni_callback = sni_cb
4696
4697 server = ThreadedEchoServer(context=server_context, chatty=False)
4698 with server:
4699 with client_context.wrap_socket(socket.socket(),
4700 server_hostname=hostname) as s:
4701 s.connect((HOST, server.port))
4702 with client_context.wrap_socket(socket.socket(),
4703 server_hostname=hostname) as s:
4704 s.connect((HOST, server.port))
4705
Christian Heimesc7f70692019-05-31 11:44:05 +02004706
Ethan Furmana02cb472021-04-21 10:20:44 -07004707class TestEnumerations(unittest.TestCase):
4708
4709 def test_tlsversion(self):
4710 class CheckedTLSVersion(enum.IntEnum):
4711 MINIMUM_SUPPORTED = _ssl.PROTO_MINIMUM_SUPPORTED
4712 SSLv3 = _ssl.PROTO_SSLv3
4713 TLSv1 = _ssl.PROTO_TLSv1
4714 TLSv1_1 = _ssl.PROTO_TLSv1_1
4715 TLSv1_2 = _ssl.PROTO_TLSv1_2
4716 TLSv1_3 = _ssl.PROTO_TLSv1_3
4717 MAXIMUM_SUPPORTED = _ssl.PROTO_MAXIMUM_SUPPORTED
4718 enum._test_simple_enum(CheckedTLSVersion, TLSVersion)
4719
4720 def test_tlscontenttype(self):
4721 class Checked_TLSContentType(enum.IntEnum):
4722 """Content types (record layer)
4723
4724 See RFC 8446, section B.1
4725 """
4726 CHANGE_CIPHER_SPEC = 20
4727 ALERT = 21
4728 HANDSHAKE = 22
4729 APPLICATION_DATA = 23
4730 # pseudo content types
4731 HEADER = 0x100
4732 INNER_CONTENT_TYPE = 0x101
4733 enum._test_simple_enum(Checked_TLSContentType, _TLSContentType)
4734
4735 def test_tlsalerttype(self):
4736 class Checked_TLSAlertType(enum.IntEnum):
4737 """Alert types for TLSContentType.ALERT messages
4738
4739 See RFC 8466, section B.2
4740 """
4741 CLOSE_NOTIFY = 0
4742 UNEXPECTED_MESSAGE = 10
4743 BAD_RECORD_MAC = 20
4744 DECRYPTION_FAILED = 21
4745 RECORD_OVERFLOW = 22
4746 DECOMPRESSION_FAILURE = 30
4747 HANDSHAKE_FAILURE = 40
4748 NO_CERTIFICATE = 41
4749 BAD_CERTIFICATE = 42
4750 UNSUPPORTED_CERTIFICATE = 43
4751 CERTIFICATE_REVOKED = 44
4752 CERTIFICATE_EXPIRED = 45
4753 CERTIFICATE_UNKNOWN = 46
4754 ILLEGAL_PARAMETER = 47
4755 UNKNOWN_CA = 48
4756 ACCESS_DENIED = 49
4757 DECODE_ERROR = 50
4758 DECRYPT_ERROR = 51
4759 EXPORT_RESTRICTION = 60
4760 PROTOCOL_VERSION = 70
4761 INSUFFICIENT_SECURITY = 71
4762 INTERNAL_ERROR = 80
4763 INAPPROPRIATE_FALLBACK = 86
4764 USER_CANCELED = 90
4765 NO_RENEGOTIATION = 100
4766 MISSING_EXTENSION = 109
4767 UNSUPPORTED_EXTENSION = 110
4768 CERTIFICATE_UNOBTAINABLE = 111
4769 UNRECOGNIZED_NAME = 112
4770 BAD_CERTIFICATE_STATUS_RESPONSE = 113
4771 BAD_CERTIFICATE_HASH_VALUE = 114
4772 UNKNOWN_PSK_IDENTITY = 115
4773 CERTIFICATE_REQUIRED = 116
4774 NO_APPLICATION_PROTOCOL = 120
4775 enum._test_simple_enum(Checked_TLSAlertType, _TLSAlertType)
4776
4777 def test_tlsmessagetype(self):
4778 class Checked_TLSMessageType(enum.IntEnum):
4779 """Message types (handshake protocol)
4780
4781 See RFC 8446, section B.3
4782 """
4783 HELLO_REQUEST = 0
4784 CLIENT_HELLO = 1
4785 SERVER_HELLO = 2
4786 HELLO_VERIFY_REQUEST = 3
4787 NEWSESSION_TICKET = 4
4788 END_OF_EARLY_DATA = 5
4789 HELLO_RETRY_REQUEST = 6
4790 ENCRYPTED_EXTENSIONS = 8
4791 CERTIFICATE = 11
4792 SERVER_KEY_EXCHANGE = 12
4793 CERTIFICATE_REQUEST = 13
4794 SERVER_DONE = 14
4795 CERTIFICATE_VERIFY = 15
4796 CLIENT_KEY_EXCHANGE = 16
4797 FINISHED = 20
4798 CERTIFICATE_URL = 21
4799 CERTIFICATE_STATUS = 22
4800 SUPPLEMENTAL_DATA = 23
4801 KEY_UPDATE = 24
4802 NEXT_PROTO = 67
4803 MESSAGE_HASH = 254
4804 CHANGE_CIPHER_SPEC = 0x0101
4805 enum._test_simple_enum(Checked_TLSMessageType, _TLSMessageType)
4806
4807 def test_sslmethod(self):
4808 Checked_SSLMethod = enum._old_convert_(
4809 enum.IntEnum, '_SSLMethod', 'ssl',
4810 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4811 source=ssl._ssl,
4812 )
4813 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
4814
4815 def test_options(self):
4816 CheckedOptions = enum._old_convert_(
4817 enum.FlagEnum, 'Options', 'ssl',
4818 lambda name: name.startswith('OP_'),
4819 source=ssl._ssl,
4820 )
4821 enum._test_simple_enum(CheckedOptions, ssl.Options)
4822
4823
4824 def test_alertdescription(self):
4825 CheckedAlertDescription = enum._old_convert_(
4826 enum.IntEnum, 'AlertDescription', 'ssl',
4827 lambda name: name.startswith('ALERT_DESCRIPTION_'),
4828 source=ssl._ssl,
4829 )
4830 enum._test_simple_enum(CheckedAlertDescription, ssl.AlertDescription)
4831
4832 def test_sslerrornumber(self):
4833 Checked_SSLMethod = enum._old_convert_(
4834 enum.IntEnum, '_SSLMethod', 'ssl',
4835 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4836 source=ssl._ssl,
4837 )
4838 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
4839
4840 def test_verifyflags(self):
4841 CheckedVerifyFlags = enum._old_convert_(
4842 enum.FlagEnum, 'VerifyFlags', 'ssl',
4843 lambda name: name.startswith('VERIFY_'),
4844 source=ssl._ssl,
4845 )
4846 enum._test_simple_enum(CheckedVerifyFlags, ssl.VerifyFlags)
4847
4848 def test_verifymode(self):
4849 CheckedVerifyMode = enum._old_convert_(
4850 enum.IntEnum, 'VerifyMode', 'ssl',
4851 lambda name: name.startswith('CERT_'),
4852 source=ssl._ssl,
4853 )
4854 enum._test_simple_enum(CheckedVerifyMode, ssl.VerifyMode)
4855
Thomas Woutersed03b412007-08-28 21:37:11 +00004856def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004857 if support.verbose:
4858 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004859 'Mac': platform.mac_ver,
4860 'Windows': platform.win32_ver,
4861 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004862 for name, func in plats.items():
4863 plat = func()
4864 if plat and plat[0]:
4865 plat = '%s %r' % (name, plat)
4866 break
4867 else:
4868 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004869 print("test_ssl: testing with %r %r" %
4870 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4871 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004872 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004873 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4874 try:
4875 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4876 except AttributeError:
4877 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004878
Antoine Pitrou152efa22010-05-16 18:19:27 +00004879 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004880 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004881 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004882 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004883 BADCERT, BADKEY, EMPTYCERT]:
4884 if not os.path.exists(filename):
4885 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004886
Martin Panter3840b2a2016-03-27 01:53:46 +00004887 tests = [
4888 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004889 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004890 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004891 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004892
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004893 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004894 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004895
Hai Shie80697d2020-05-28 06:10:27 +08004896 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004897 try:
4898 support.run_unittest(*tests)
4899 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004900 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004901
4902if __name__ == "__main__":
4903 test_main()