blob: f2b26c4b1405ef6d3874b04735cd80e547cf313a [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")
Christian Heimes666991f2021-04-26 15:01:40 +020035import _ssl
Antoine Pitrou05d936d2010-10-13 11:38:36 +000036
Ethan Furmana02cb472021-04-21 10:20:44 -070037from ssl import TLSVersion, _TLSContentType, _TLSMessageType, _TLSAlertType
Martin Panter3840b2a2016-03-27 01:53:46 +000038
Paul Monsonf3550692019-06-19 13:09:54 -070039Py_DEBUG = hasattr(sys, 'gettotalrefcount')
40Py_DEBUG_WIN32 = Py_DEBUG and sys.platform == 'win32'
41
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010042PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Serhiy Storchaka16994912020-04-25 10:06:29 +030043HOST = socket_helper.HOST
Christian Heimesd37b74f2021-04-19 08:31:29 +020044IS_OPENSSL_3_0_0 = ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
Christian Heimes892d66e2018-01-29 14:10:18 +010045PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
Antoine Pitrou152efa22010-05-16 18:19:27 +000046
Victor Stinner3ef63442019-02-19 18:06:03 +010047PROTOCOL_TO_TLS_VERSION = {}
48for proto, ver in (
49 ("PROTOCOL_SSLv23", "SSLv3"),
50 ("PROTOCOL_TLSv1", "TLSv1"),
51 ("PROTOCOL_TLSv1_1", "TLSv1_1"),
52):
53 try:
54 proto = getattr(ssl, proto)
55 ver = getattr(ssl.TLSVersion, ver)
56 except AttributeError:
57 continue
58 PROTOCOL_TO_TLS_VERSION[proto] = ver
59
Christian Heimesefff7062013-11-21 03:35:02 +010060def data_file(*name):
61 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000062
Antoine Pitrou81564092010-10-08 23:06:24 +000063# The custom key and certificate files used in test_ssl are generated
64# using Lib/test/make_ssl_certs.py.
65# Other certificates are simply fetched from the Internet servers they
66# are meant to authenticate.
67
Antoine Pitrou152efa22010-05-16 18:19:27 +000068CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000069BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000070ONLYCERT = data_file("ssl_cert.pem")
71ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000072BYTES_ONLYCERT = os.fsencode(ONLYCERT)
73BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020074CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
75ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
76KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000077CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000078BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010079CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
80CAFILE_CACERT = data_file("capath", "5ed36f99.0")
81
Christian Heimesbd5c7d22018-01-20 15:16:30 +010082CERTFILE_INFO = {
83 'issuer': ((('countryName', 'XY'),),
84 (('localityName', 'Castle Anthrax'),),
85 (('organizationName', 'Python Software Foundation'),),
86 (('commonName', 'localhost'),)),
Christian Heimese6dac002018-08-30 07:25:49 +020087 'notAfter': 'Aug 26 14:23:15 2028 GMT',
88 'notBefore': 'Aug 29 14:23:15 2018 GMT',
89 'serialNumber': '98A7CF88C74A32ED',
Christian Heimesbd5c7d22018-01-20 15:16:30 +010090 'subject': ((('countryName', 'XY'),),
91 (('localityName', 'Castle Anthrax'),),
92 (('organizationName', 'Python Software Foundation'),),
93 (('commonName', 'localhost'),)),
94 'subjectAltName': (('DNS', 'localhost'),),
95 'version': 3
96}
Antoine Pitrou152efa22010-05-16 18:19:27 +000097
Christian Heimes22587792013-11-21 23:56:13 +010098# empty CRL
99CRLFILE = data_file("revocation.crl")
100
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100101# Two keys and certs signed by the same CA (for SNI tests)
102SIGNED_CERTFILE = data_file("keycert3.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200103SIGNED_CERTFILE_HOSTNAME = 'localhost'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100104
105SIGNED_CERTFILE_INFO = {
106 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
107 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
108 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
109 'issuer': ((('countryName', 'XY'),),
110 (('organizationName', 'Python Software Foundation CA'),),
111 (('commonName', 'our-ca-server'),)),
Christian Heimesb467d9a2021-04-17 10:07:19 +0200112 'notAfter': 'Oct 28 14:23:16 2037 GMT',
Christian Heimese6dac002018-08-30 07:25:49 +0200113 'notBefore': 'Aug 29 14:23:16 2018 GMT',
114 'serialNumber': 'CB2D80995A69525C',
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100115 'subject': ((('countryName', 'XY'),),
116 (('localityName', 'Castle Anthrax'),),
117 (('organizationName', 'Python Software Foundation'),),
118 (('commonName', 'localhost'),)),
119 'subjectAltName': (('DNS', 'localhost'),),
120 'version': 3
121}
122
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100123SIGNED_CERTFILE2 = data_file("keycert4.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200124SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100125SIGNED_CERTFILE_ECC = data_file("keycertecc.pem")
126SIGNED_CERTFILE_ECC_HOSTNAME = 'localhost-ecc'
127
Martin Panter3840b2a2016-03-27 01:53:46 +0000128# Same certificate as pycacert.pem, but without extra text in file
129SIGNING_CA = data_file("capath", "ceff1710.0")
Christian Heimes1c03abd2016-09-06 23:25:35 +0200130# cert with all kinds of subject alt names
131ALLSANFILE = data_file("allsans.pem")
Christian Heimes66e57422018-01-29 14:25:13 +0100132IDNSANSFILE = data_file("idnsans.pem")
Christian Heimesb467d9a2021-04-17 10:07:19 +0200133NOSANFILE = data_file("nosan.pem")
134NOSAN_HOSTNAME = 'localhost'
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100135
Martin Panter3d81d932016-01-14 09:36:00 +0000136REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +0000137
138EMPTYCERT = data_file("nullcert.pem")
139BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +0000140NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000141BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200142NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +0200143NULLBYTECERT = data_file("nullbytecert.pem")
Christian Heimesa37f5242019-01-15 23:47:42 +0100144TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000145
Christian Heimes88bfd0b2018-08-14 12:54:19 +0200146DHFILE = data_file("ffdh3072.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100147BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +0000148
Christian Heimes358cfd42016-09-10 22:43:48 +0200149# Not defined in all versions of OpenSSL
150OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
151OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
152OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
153OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
Christian Heimes05d9fe32018-02-27 08:55:39 +0100154OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
Christian Heimes6f37ebc2021-04-09 17:59:21 +0200155OP_IGNORE_UNEXPECTED_EOF = getattr(ssl, "OP_IGNORE_UNEXPECTED_EOF", 0)
Christian Heimes358cfd42016-09-10 22:43:48 +0200156
Christian Heimesf6c6b582021-03-18 23:06:50 +0100157# Ubuntu has patched OpenSSL and changed behavior of security level 2
158# see https://bugs.python.org/issue41561#msg389003
159def is_ubuntu():
160 try:
161 # Assume that any references of "ubuntu" implies Ubuntu-like distro
162 # The workaround is not required for 18.04, but doesn't hurt either.
163 with open("/etc/os-release", encoding="utf-8") as f:
164 return "ubuntu" in f.read()
165 except FileNotFoundError:
166 return False
167
168if is_ubuntu():
169 def seclevel_workaround(*ctxs):
170 """"Lower security level to '1' and allow all ciphers for TLS 1.0/1"""
171 for ctx in ctxs:
Christian Heimes34477502021-04-12 12:00:38 +0200172 if (
173 hasattr(ctx, "minimum_version") and
174 ctx.minimum_version <= ssl.TLSVersion.TLSv1_1
175 ):
Christian Heimesf6c6b582021-03-18 23:06:50 +0100176 ctx.set_ciphers("@SECLEVEL=1:ALL")
177else:
178 def seclevel_workaround(*ctxs):
179 pass
180
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100181
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200182def has_tls_protocol(protocol):
183 """Check if a TLS protocol is available and enabled
184
185 :param protocol: enum ssl._SSLMethod member or name
186 :return: bool
187 """
188 if isinstance(protocol, str):
189 assert protocol.startswith('PROTOCOL_')
190 protocol = getattr(ssl, protocol, None)
191 if protocol is None:
192 return False
193 if protocol in {
194 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
195 ssl.PROTOCOL_TLS_CLIENT
196 }:
197 # auto-negotiate protocols are always available
198 return True
199 name = protocol.name
200 return has_tls_version(name[len('PROTOCOL_'):])
201
202
203@functools.lru_cache
204def has_tls_version(version):
205 """Check if a TLS/SSL version is enabled
206
207 :param version: TLS version name or ssl.TLSVersion member
208 :return: bool
209 """
210 if version == "SSLv2":
211 # never supported and not even in TLSVersion enum
212 return False
213
214 if isinstance(version, str):
215 version = ssl.TLSVersion.__members__[version]
216
217 # check compile time flags like ssl.HAS_TLSv1_2
218 if not getattr(ssl, f'HAS_{version.name}'):
219 return False
220
Christian Heimes5151d642021-04-09 15:43:06 +0200221 if IS_OPENSSL_3_0_0 and version < ssl.TLSVersion.TLSv1_2:
222 # bpo43791: 3.0.0-alpha14 fails with TLSV1_ALERT_INTERNAL_ERROR
223 return False
224
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200225 # check runtime and dynamic crypto policy settings. A TLS version may
226 # be compiled in but disabled by a policy or config option.
Christian Heimes2875c602021-04-19 07:27:10 +0200227 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200228 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200229 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200230 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
231 version < ctx.minimum_version
232 ):
233 return False
234 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200235 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200236 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
237 version > ctx.maximum_version
238 ):
239 return False
240
241 return True
242
243
244def requires_tls_version(version):
245 """Decorator to skip tests when a required TLS version is not available
246
247 :param version: TLS version name or ssl.TLSVersion member
248 :return:
249 """
250 def decorator(func):
251 @functools.wraps(func)
252 def wrapper(*args, **kw):
253 if not has_tls_version(version):
254 raise unittest.SkipTest(f"{version} is not available.")
255 else:
256 return func(*args, **kw)
257 return wrapper
258 return decorator
259
260
Thomas Woutersed03b412007-08-28 21:37:11 +0000261def handle_error(prefix):
262 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000263 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000264 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000265
Christian Heimesb7b92252018-02-25 09:49:31 +0100266
Antoine Pitrouc695c952014-04-28 20:57:36 +0200267def utc_offset(): #NOTE: ignore issues like #1647654
268 # local time = utc time + utc offset
269 if time.daylight and time.localtime().tm_isdst > 0:
270 return -time.altzone # seconds
271 return -time.timezone
272
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100273
Christian Heimes2875c602021-04-19 07:27:10 +0200274ignore_deprecation = warnings_helper.ignore_warnings(
275 category=DeprecationWarning
276)
Antoine Pitrou23df4832010-08-04 17:14:06 +0000277
Christian Heimes2875c602021-04-19 07:27:10 +0200278
279def test_wrap_socket(sock, *,
Christian Heimesd0486372016-09-10 23:23:33 +0200280 cert_reqs=ssl.CERT_NONE, ca_certs=None,
281 ciphers=None, certfile=None, keyfile=None,
282 **kwargs):
Christian Heimes2875c602021-04-19 07:27:10 +0200283 if not kwargs.get("server_side"):
284 kwargs["server_hostname"] = SIGNED_CERTFILE_HOSTNAME
285 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
286 else:
287 context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimesd0486372016-09-10 23:23:33 +0200288 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200289 if cert_reqs == ssl.CERT_NONE:
290 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200291 context.verify_mode = cert_reqs
292 if ca_certs is not None:
293 context.load_verify_locations(ca_certs)
294 if certfile is not None or keyfile is not None:
295 context.load_cert_chain(certfile, keyfile)
296 if ciphers is not None:
297 context.set_ciphers(ciphers)
298 return context.wrap_socket(sock, **kwargs)
299
Christian Heimesa170fa12017-09-15 20:27:30 +0200300
Christian Heimes666991f2021-04-26 15:01:40 +0200301def testing_context(server_cert=SIGNED_CERTFILE, *, server_chain=True):
Christian Heimesa170fa12017-09-15 20:27:30 +0200302 """Create context
303
304 client_context, server_context, hostname = testing_context()
305 """
306 if server_cert == SIGNED_CERTFILE:
307 hostname = SIGNED_CERTFILE_HOSTNAME
308 elif server_cert == SIGNED_CERTFILE2:
309 hostname = SIGNED_CERTFILE2_HOSTNAME
Christian Heimesb467d9a2021-04-17 10:07:19 +0200310 elif server_cert == NOSANFILE:
311 hostname = NOSAN_HOSTNAME
Christian Heimesa170fa12017-09-15 20:27:30 +0200312 else:
313 raise ValueError(server_cert)
314
315 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
316 client_context.load_verify_locations(SIGNING_CA)
317
318 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
319 server_context.load_cert_chain(server_cert)
Christian Heimes666991f2021-04-26 15:01:40 +0200320 if server_chain:
321 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200322
323 return client_context, server_context, hostname
324
325
Antoine Pitrou152efa22010-05-16 18:19:27 +0000326class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000327
Antoine Pitrou480a1242010-04-28 21:37:09 +0000328 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000329 ssl.CERT_NONE
330 ssl.CERT_OPTIONAL
331 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100332 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100333 ssl.OP_SINGLE_DH_USE
Christian Heimesd37b74f2021-04-19 08:31:29 +0200334 ssl.OP_SINGLE_ECDH_USE
Christian Heimes39258d32021-04-17 11:36:35 +0200335 ssl.OP_NO_COMPRESSION
Christian Heimesd37b74f2021-04-19 08:31:29 +0200336 self.assertEqual(ssl.HAS_SNI, True)
337 self.assertEqual(ssl.HAS_ECDH, True)
338 self.assertEqual(ssl.HAS_TLSv1_2, True)
339 self.assertEqual(ssl.HAS_TLSv1_3, True)
Christian Heimescb5b68a2017-09-07 18:07:00 -0700340 ssl.OP_NO_SSLv2
341 ssl.OP_NO_SSLv3
342 ssl.OP_NO_TLSv1
343 ssl.OP_NO_TLSv1_3
Christian Heimes39258d32021-04-17 11:36:35 +0200344 ssl.OP_NO_TLSv1_1
345 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200346 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000347
Christian Heimes9d50ab52018-02-27 10:17:30 +0100348 def test_private_init(self):
349 with self.assertRaisesRegex(TypeError, "public constructor"):
350 with socket.socket() as s:
351 ssl.SSLSocket(s)
352
Antoine Pitrou172f0252014-04-18 20:33:08 +0200353 def test_str_for_enums(self):
354 # Make sure that the PROTOCOL_* constants have enum-like string
355 # reprs.
Christian Heimes2875c602021-04-19 07:27:10 +0200356 proto = ssl.PROTOCOL_TLS_CLIENT
357 self.assertEqual(str(proto), 'PROTOCOL_TLS_CLIENT')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200358 ctx = ssl.SSLContext(proto)
359 self.assertIs(ctx.protocol, proto)
360
Antoine Pitrou480a1242010-04-28 21:37:09 +0000361 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000362 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000363 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000364 sys.stdout.write("\n RAND_status is %d (%s)\n"
365 % (v, (v and "sufficient randomness") or
366 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200367
Christian Heimes2875c602021-04-19 07:27:10 +0200368 with warnings_helper.check_warnings():
369 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200370 self.assertEqual(len(data), 16)
371 self.assertEqual(is_cryptographic, v == 1)
372 if v:
373 data = ssl.RAND_bytes(16)
374 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200375 else:
376 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200377
Victor Stinner1e81a392013-12-19 16:47:04 +0100378 # negative num is invalid
379 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
Christian Heimes2875c602021-04-19 07:27:10 +0200380 with warnings_helper.check_warnings():
381 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
Victor Stinner1e81a392013-12-19 16:47:04 +0100382
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000383 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200384 ssl.RAND_add(b"this is a random bytes object", 75.0)
385 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000386
Antoine Pitrou480a1242010-04-28 21:37:09 +0000387 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000388 # note that this uses an 'unofficial' function in _ssl.c,
389 # provided solely for this test, to exercise the certificate
390 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100391 self.assertEqual(
392 ssl._ssl._test_decode_cert(CERTFILE),
393 CERTFILE_INFO
394 )
395 self.assertEqual(
396 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
397 SIGNED_CERTFILE_INFO
398 )
399
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200400 # Issue #13034: the subjectAltName in some certificates
401 # (notably projects.developer.nokia.com:443) wasn't parsed
402 p = ssl._ssl._test_decode_cert(NOKIACERT)
403 if support.verbose:
404 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
405 self.assertEqual(p['subjectAltName'],
406 (('DNS', 'projects.developer.nokia.com'),
407 ('DNS', 'projects.forum.nokia.com'))
408 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100409 # extra OCSP and AIA fields
410 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
411 self.assertEqual(p['caIssuers'],
412 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
413 self.assertEqual(p['crlDistributionPoints'],
414 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000415
Christian Heimesa37f5242019-01-15 23:47:42 +0100416 def test_parse_cert_CVE_2019_5010(self):
417 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
418 if support.verbose:
419 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
420 self.assertEqual(
421 p,
422 {
423 'issuer': (
424 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
425 'notAfter': 'Jun 14 18:00:58 2028 GMT',
426 'notBefore': 'Jun 18 18:00:58 2018 GMT',
427 'serialNumber': '02',
428 'subject': ((('countryName', 'UK'),),
429 (('commonName',
430 'codenomicon-vm-2.test.lal.cisco.com'),)),
431 'subjectAltName': (
432 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
433 'version': 3
434 }
435 )
436
Christian Heimes824f7f32013-08-17 00:54:47 +0200437 def test_parse_cert_CVE_2013_4238(self):
438 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
439 if support.verbose:
440 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
441 subject = ((('countryName', 'US'),),
442 (('stateOrProvinceName', 'Oregon'),),
443 (('localityName', 'Beaverton'),),
444 (('organizationName', 'Python Software Foundation'),),
445 (('organizationalUnitName', 'Python Core Development'),),
446 (('commonName', 'null.python.org\x00example.org'),),
447 (('emailAddress', 'python-dev@python.org'),))
448 self.assertEqual(p['subject'], subject)
449 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200450 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
451 san = (('DNS', 'altnull.python.org\x00example.com'),
452 ('email', 'null@python.org\x00user@example.org'),
453 ('URI', 'http://null.python.org\x00http://example.org'),
454 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100455 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200456 else:
457 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
458 san = (('DNS', 'altnull.python.org\x00example.com'),
459 ('email', 'null@python.org\x00user@example.org'),
460 ('URI', 'http://null.python.org\x00http://example.org'),
461 ('IP Address', '192.0.2.1'),
462 ('IP Address', '<invalid>'))
463
464 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200465
Christian Heimes1c03abd2016-09-06 23:25:35 +0200466 def test_parse_all_sans(self):
467 p = ssl._ssl._test_decode_cert(ALLSANFILE)
468 self.assertEqual(p['subjectAltName'],
469 (
470 ('DNS', 'allsans'),
471 ('othername', '<unsupported>'),
472 ('othername', '<unsupported>'),
473 ('email', 'user@example.org'),
474 ('DNS', 'www.example.org'),
475 ('DirName',
476 ((('countryName', 'XY'),),
477 (('localityName', 'Castle Anthrax'),),
478 (('organizationName', 'Python Software Foundation'),),
479 (('commonName', 'dirname example'),))),
480 ('URI', 'https://www.python.org/'),
481 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100482 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200483 ('Registered ID', '1.2.3.4.5')
484 )
485 )
486
Antoine Pitrou480a1242010-04-28 21:37:09 +0000487 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000488 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000489 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000490 d1 = ssl.PEM_cert_to_DER_cert(pem)
491 p2 = ssl.DER_cert_to_PEM_cert(d1)
492 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000493 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000494 if not p2.startswith(ssl.PEM_HEADER + '\n'):
495 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
496 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
497 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000498
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000499 def test_openssl_version(self):
500 n = ssl.OPENSSL_VERSION_NUMBER
501 t = ssl.OPENSSL_VERSION_INFO
502 s = ssl.OPENSSL_VERSION
503 self.assertIsInstance(n, int)
504 self.assertIsInstance(t, tuple)
505 self.assertIsInstance(s, str)
506 # Some sanity checks follow
Christian Heimesd37b74f2021-04-19 08:31:29 +0200507 # >= 1.1.1
508 self.assertGreaterEqual(n, 0x10101000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100509 # < 4.0
510 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000511 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100512 self.assertGreaterEqual(major, 1)
513 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000514 self.assertGreaterEqual(minor, 0)
515 self.assertLess(minor, 256)
516 self.assertGreaterEqual(fix, 0)
517 self.assertLess(fix, 256)
518 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100519 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000520 self.assertGreaterEqual(status, 0)
521 self.assertLessEqual(status, 15)
Christian Heimesd37b74f2021-04-19 08:31:29 +0200522
523 libressl_ver = f"LibreSSL {major:d}"
524 openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}"
525 self.assertTrue(
526 s.startswith((openssl_ver, libressl_ver)),
527 (s, t, hex(n))
528 )
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000529
Antoine Pitrou9d543662010-04-23 23:10:32 +0000530 @support.cpython_only
531 def test_refcycle(self):
532 # Issue #7943: an SSL object doesn't create reference cycles with
533 # itself.
534 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200535 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000536 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800537 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100538 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100539 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000540
Antoine Pitroua468adc2010-09-14 14:43:44 +0000541 def test_wrapped_unconnected(self):
542 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200543 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000544 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200545 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100546 self.assertRaises(OSError, ss.recv, 1)
547 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
548 self.assertRaises(OSError, ss.recvfrom, 1)
549 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
550 self.assertRaises(OSError, ss.send, b'x')
551 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200552 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100553 self.assertRaises(NotImplementedError, ss.sendmsg,
554 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200555 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
556 self.assertRaises(NotImplementedError, ss.recvmsg_into,
557 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000558
Antoine Pitrou40f08742010-04-24 22:04:40 +0000559 def test_timeout(self):
560 # Issue #8524: when creating an SSL socket, the timeout of the
561 # original socket should be retained.
562 for timeout in (None, 0.0, 5.0):
563 s = socket.socket(socket.AF_INET)
564 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200565 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100566 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000567
Christian Heimes2875c602021-04-19 07:27:10 +0200568 @ignore_deprecation
Christian Heimesd0486372016-09-10 23:23:33 +0200569 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000570 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000571 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000572 "certfile must be specified",
573 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000574 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000575 "certfile must be specified for server-side operations",
576 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000577 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000578 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200579 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100580 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
581 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200582 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200583 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000584 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000585 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000586 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200587 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000588 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000589 ssl.wrap_socket(sock,
590 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000591 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200592 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000593 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000594 ssl.wrap_socket(sock,
595 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000596 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000597
Martin Panter3464ea22016-02-01 21:58:11 +0000598 def bad_cert_test(self, certfile):
599 """Check that trying to use the given client certificate fails"""
600 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
601 certfile)
602 sock = socket.socket()
603 self.addCleanup(sock.close)
604 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200605 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200606 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000607
608 def test_empty_cert(self):
609 """Wrapping with an empty cert file"""
610 self.bad_cert_test("nullcert.pem")
611
612 def test_malformed_cert(self):
613 """Wrapping with a badly formatted certificate (syntax error)"""
614 self.bad_cert_test("badcert.pem")
615
616 def test_malformed_key(self):
617 """Wrapping with a badly formatted key (syntax error)"""
618 self.bad_cert_test("badkey.pem")
619
Christian Heimes2875c602021-04-19 07:27:10 +0200620 @ignore_deprecation
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000621 def test_match_hostname(self):
622 def ok(cert, hostname):
623 ssl.match_hostname(cert, hostname)
624 def fail(cert, hostname):
625 self.assertRaises(ssl.CertificateError,
626 ssl.match_hostname, cert, hostname)
627
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100628 # -- Hostname matching --
629
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000630 cert = {'subject': ((('commonName', 'example.com'),),)}
631 ok(cert, 'example.com')
632 ok(cert, 'ExAmple.cOm')
633 fail(cert, 'www.example.com')
634 fail(cert, '.example.com')
635 fail(cert, 'example.org')
636 fail(cert, 'exampleXcom')
637
638 cert = {'subject': ((('commonName', '*.a.com'),),)}
639 ok(cert, 'foo.a.com')
640 fail(cert, 'bar.foo.a.com')
641 fail(cert, 'a.com')
642 fail(cert, 'Xa.com')
643 fail(cert, '.a.com')
644
Mandeep Singhede2ac92017-11-27 04:01:27 +0530645 # only match wildcards when they are the only thing
646 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000647 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530648 fail(cert, 'foo.com')
649 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000650 fail(cert, 'bar.com')
651 fail(cert, 'foo.a.com')
652 fail(cert, 'bar.foo.com')
653
Christian Heimes824f7f32013-08-17 00:54:47 +0200654 # NULL bytes are bad, CVE-2013-4073
655 cert = {'subject': ((('commonName',
656 'null.python.org\x00example.org'),),)}
657 ok(cert, 'null.python.org\x00example.org') # or raise an error?
658 fail(cert, 'example.org')
659 fail(cert, 'null.python.org')
660
Georg Brandl72c98d32013-10-27 07:16:53 +0100661 # error cases with wildcards
662 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
663 fail(cert, 'bar.foo.a.com')
664 fail(cert, 'a.com')
665 fail(cert, 'Xa.com')
666 fail(cert, '.a.com')
667
668 cert = {'subject': ((('commonName', 'a.*.com'),),)}
669 fail(cert, 'a.foo.com')
670 fail(cert, 'a..com')
671 fail(cert, 'a.com')
672
673 # wildcard doesn't match IDNA prefix 'xn--'
674 idna = 'püthon.python.org'.encode("idna").decode("ascii")
675 cert = {'subject': ((('commonName', idna),),)}
676 ok(cert, idna)
677 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
678 fail(cert, idna)
679 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
680 fail(cert, idna)
681
682 # wildcard in first fragment and IDNA A-labels in sequent fragments
683 # are supported.
684 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
685 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530686 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
687 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100688 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
689 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
690
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000691 # Slightly fake real-world example
692 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
693 'subject': ((('commonName', 'linuxfrz.org'),),),
694 'subjectAltName': (('DNS', 'linuxfr.org'),
695 ('DNS', 'linuxfr.com'),
696 ('othername', '<unsupported>'))}
697 ok(cert, 'linuxfr.org')
698 ok(cert, 'linuxfr.com')
699 # Not a "DNS" entry
700 fail(cert, '<unsupported>')
701 # When there is a subjectAltName, commonName isn't used
702 fail(cert, 'linuxfrz.org')
703
704 # A pristine real-world example
705 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
706 'subject': ((('countryName', 'US'),),
707 (('stateOrProvinceName', 'California'),),
708 (('localityName', 'Mountain View'),),
709 (('organizationName', 'Google Inc'),),
710 (('commonName', 'mail.google.com'),))}
711 ok(cert, 'mail.google.com')
712 fail(cert, 'gmail.com')
713 # Only commonName is considered
714 fail(cert, 'California')
715
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100716 # -- IPv4 matching --
717 cert = {'subject': ((('commonName', 'example.com'),),),
718 'subjectAltName': (('DNS', 'example.com'),
719 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200720 ('IP Address', '14.15.16.17'),
721 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100722 ok(cert, '10.11.12.13')
723 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200724 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
725 fail(cert, '127.1')
726 fail(cert, '14.15.16.17 ')
727 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100728 fail(cert, '14.15.16.18')
729 fail(cert, 'example.net')
730
731 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300732 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100733 cert = {'subject': ((('commonName', 'example.com'),),),
734 'subjectAltName': (
735 ('DNS', 'example.com'),
736 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
737 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
738 ok(cert, '2001::cafe')
739 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200740 fail(cert, '2003::baba ')
741 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100742 fail(cert, '2003::bebe')
743 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100744
745 # -- Miscellaneous --
746
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000747 # Neither commonName nor subjectAltName
748 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
749 'subject': ((('countryName', 'US'),),
750 (('stateOrProvinceName', 'California'),),
751 (('localityName', 'Mountain View'),),
752 (('organizationName', 'Google Inc'),))}
753 fail(cert, 'mail.google.com')
754
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200755 # No DNS entry in subjectAltName but a commonName
756 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
757 'subject': ((('countryName', 'US'),),
758 (('stateOrProvinceName', 'California'),),
759 (('localityName', 'Mountain View'),),
760 (('commonName', 'mail.google.com'),)),
761 'subjectAltName': (('othername', 'blabla'), )}
762 ok(cert, 'mail.google.com')
763
764 # No DNS entry subjectAltName and no commonName
765 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
766 'subject': ((('countryName', 'US'),),
767 (('stateOrProvinceName', 'California'),),
768 (('localityName', 'Mountain View'),),
769 (('organizationName', 'Google Inc'),)),
770 'subjectAltName': (('othername', 'blabla'),)}
771 fail(cert, 'google.com')
772
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000773 # Empty cert / no cert
774 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
775 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
776
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200777 # Issue #17980: avoid denials of service by refusing more than one
778 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100779 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
780 with self.assertRaisesRegex(
781 ssl.CertificateError,
782 "partial wildcards in leftmost label are not supported"):
783 ssl.match_hostname(cert, 'axxb.example.com')
784
785 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
786 with self.assertRaisesRegex(
787 ssl.CertificateError,
788 "wildcard can only be present in the leftmost label"):
789 ssl.match_hostname(cert, 'www.sub.example.com')
790
791 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
792 with self.assertRaisesRegex(
793 ssl.CertificateError,
794 "too many wildcards"):
795 ssl.match_hostname(cert, 'axxbxxc.example.com')
796
797 cert = {'subject': ((('commonName', '*'),),)}
798 with self.assertRaisesRegex(
799 ssl.CertificateError,
800 "sole wildcard without additional labels are not support"):
801 ssl.match_hostname(cert, 'host')
802
803 cert = {'subject': ((('commonName', '*.com'),),)}
804 with self.assertRaisesRegex(
805 ssl.CertificateError,
806 r"hostname 'com' doesn't match '\*.com'"):
807 ssl.match_hostname(cert, 'com')
808
809 # extra checks for _inet_paton()
810 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
811 with self.assertRaises(ValueError):
812 ssl._inet_paton(invalid)
813 for ipaddr in ['127.0.0.1', '192.168.0.1']:
814 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300815 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100816 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
817 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200818
Antoine Pitroud5323212010-10-22 18:19:07 +0000819 def test_server_side(self):
820 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200821 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000822 with socket.socket() as sock:
823 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
824 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000825
Antoine Pitroud6494802011-07-21 01:11:30 +0200826 def test_unknown_channel_binding(self):
827 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200828 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200829 c = socket.socket(socket.AF_INET)
830 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200831 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100832 with self.assertRaises(ValueError):
833 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200834 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200835
836 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
837 "'tls-unique' channel binding not available")
838 def test_tls_unique_channel_binding(self):
839 # unconnected should return None for known type
840 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200841 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100842 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200843 # the same for server-side
844 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200845 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100846 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200847
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600848 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200849 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600850 r = repr(ss)
851 with self.assertWarns(ResourceWarning) as cm:
852 ss = None
853 support.gc_collect()
854 self.assertIn(r, str(cm.warning.args[0]))
855
Christian Heimes6d7ad132013-06-09 18:02:55 +0200856 def test_get_default_verify_paths(self):
857 paths = ssl.get_default_verify_paths()
858 self.assertEqual(len(paths), 6)
859 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
860
Hai Shia7f5d932020-08-04 00:41:24 +0800861 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200862 env["SSL_CERT_DIR"] = CAPATH
863 env["SSL_CERT_FILE"] = CERTFILE
864 paths = ssl.get_default_verify_paths()
865 self.assertEqual(paths.cafile, CERTFILE)
866 self.assertEqual(paths.capath, CAPATH)
867
Christian Heimes44109d72013-11-22 01:51:30 +0100868 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
869 def test_enum_certificates(self):
870 self.assertTrue(ssl.enum_certificates("CA"))
871 self.assertTrue(ssl.enum_certificates("ROOT"))
872
873 self.assertRaises(TypeError, ssl.enum_certificates)
874 self.assertRaises(WindowsError, ssl.enum_certificates, "")
875
Christian Heimesc2d65e12013-11-22 16:13:55 +0100876 trust_oids = set()
877 for storename in ("CA", "ROOT"):
878 store = ssl.enum_certificates(storename)
879 self.assertIsInstance(store, list)
880 for element in store:
881 self.assertIsInstance(element, tuple)
882 self.assertEqual(len(element), 3)
883 cert, enc, trust = element
884 self.assertIsInstance(cert, bytes)
885 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200886 self.assertIsInstance(trust, (frozenset, set, bool))
887 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100888 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100889
890 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100891 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200892
Christian Heimes46bebee2013-06-09 19:03:31 +0200893 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100894 def test_enum_crls(self):
895 self.assertTrue(ssl.enum_crls("CA"))
896 self.assertRaises(TypeError, ssl.enum_crls)
897 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200898
Christian Heimes44109d72013-11-22 01:51:30 +0100899 crls = ssl.enum_crls("CA")
900 self.assertIsInstance(crls, list)
901 for element in crls:
902 self.assertIsInstance(element, tuple)
903 self.assertEqual(len(element), 2)
904 self.assertIsInstance(element[0], bytes)
905 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200906
Christian Heimes46bebee2013-06-09 19:03:31 +0200907
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100908 def test_asn1object(self):
909 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
910 '1.3.6.1.5.5.7.3.1')
911
912 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
913 self.assertEqual(val, expected)
914 self.assertEqual(val.nid, 129)
915 self.assertEqual(val.shortname, 'serverAuth')
916 self.assertEqual(val.longname, 'TLS Web Server Authentication')
917 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
918 self.assertIsInstance(val, ssl._ASN1Object)
919 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
920
921 val = ssl._ASN1Object.fromnid(129)
922 self.assertEqual(val, expected)
923 self.assertIsInstance(val, ssl._ASN1Object)
924 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100925 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
926 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100927 for i in range(1000):
928 try:
929 obj = ssl._ASN1Object.fromnid(i)
930 except ValueError:
931 pass
932 else:
933 self.assertIsInstance(obj.nid, int)
934 self.assertIsInstance(obj.shortname, str)
935 self.assertIsInstance(obj.longname, str)
936 self.assertIsInstance(obj.oid, (str, type(None)))
937
938 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
939 self.assertEqual(val, expected)
940 self.assertIsInstance(val, ssl._ASN1Object)
941 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
942 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
943 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100944 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
945 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100946
Christian Heimes72d28502013-11-23 13:56:58 +0100947 def test_purpose_enum(self):
948 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
949 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
950 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
951 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
952 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
953 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
954 '1.3.6.1.5.5.7.3.1')
955
956 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
957 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
958 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
959 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
960 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
961 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
962 '1.3.6.1.5.5.7.3.2')
963
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100964 def test_unsupported_dtls(self):
965 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
966 self.addCleanup(s.close)
967 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +0200968 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100969 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +0200970 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100971 with self.assertRaises(NotImplementedError) as cx:
972 ctx.wrap_socket(s)
973 self.assertEqual(str(cx.exception), "only stream sockets are supported")
974
Antoine Pitrouc695c952014-04-28 20:57:36 +0200975 def cert_time_ok(self, timestring, timestamp):
976 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
977
978 def cert_time_fail(self, timestring):
979 with self.assertRaises(ValueError):
980 ssl.cert_time_to_seconds(timestring)
981
982 @unittest.skipUnless(utc_offset(),
983 'local time needs to be different from UTC')
984 def test_cert_time_to_seconds_timezone(self):
985 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
986 # results if local timezone is not UTC
987 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
988 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
989
990 def test_cert_time_to_seconds(self):
991 timestring = "Jan 5 09:34:43 2018 GMT"
992 ts = 1515144883.0
993 self.cert_time_ok(timestring, ts)
994 # accept keyword parameter, assert its name
995 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
996 # accept both %e and %d (space or zero generated by strftime)
997 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
998 # case-insensitive
999 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
1000 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
1001 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1002 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1003 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1004 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1005 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1006 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1007
1008 newyear_ts = 1230768000.0
1009 # leap seconds
1010 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1011 # same timestamp
1012 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1013
1014 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1015 # allow 60th second (even if it is not a leap second)
1016 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1017 # allow 2nd leap second for compatibility with time.strptime()
1018 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1019 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1020
Mike53f7a7c2017-12-14 14:04:53 +03001021 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001022 # 99991231235959Z (rfc 5280)
1023 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1024
1025 @support.run_with_locale('LC_ALL', '')
1026 def test_cert_time_to_seconds_locale(self):
1027 # `cert_time_to_seconds()` should be locale independent
1028
1029 def local_february_name():
1030 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1031
1032 if local_february_name().lower() == 'feb':
1033 self.skipTest("locale-specific month name needs to be "
1034 "different from C locale")
1035
1036 # locale-independent
1037 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1038 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1039
Martin Panter3840b2a2016-03-27 01:53:46 +00001040 def test_connect_ex_error(self):
1041 server = socket.socket(socket.AF_INET)
1042 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001043 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001044 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001045 cert_reqs=ssl.CERT_REQUIRED)
1046 self.addCleanup(s.close)
1047 rc = s.connect_ex((HOST, port))
1048 # Issue #19919: Windows machines or VMs hosted on Windows
1049 # machines sometimes return EWOULDBLOCK.
1050 errors = (
1051 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1052 errno.EWOULDBLOCK,
1053 )
1054 self.assertIn(rc, errors)
1055
Christian Heimes89d15502021-04-19 06:55:30 +02001056 def test_read_write_zero(self):
1057 # empty reads and writes now work, bpo-42854, bpo-31711
1058 client_context, server_context, hostname = testing_context()
1059 server = ThreadedEchoServer(context=server_context)
1060 with server:
1061 with client_context.wrap_socket(socket.socket(),
1062 server_hostname=hostname) as s:
1063 s.connect((HOST, server.port))
1064 self.assertEqual(s.recv(0), b"")
1065 self.assertEqual(s.send(b""), 0)
1066
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001067
Antoine Pitrou152efa22010-05-16 18:19:27 +00001068class ContextTests(unittest.TestCase):
1069
1070 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001071 for protocol in PROTOCOLS:
Christian Heimes2875c602021-04-19 07:27:10 +02001072 with warnings_helper.check_warnings():
1073 ctx = ssl.SSLContext(protocol)
1074 self.assertEqual(ctx.protocol, protocol)
1075 with warnings_helper.check_warnings():
1076 ctx = ssl.SSLContext()
Christian Heimes598894f2016-09-05 23:19:05 +02001077 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001078 self.assertRaises(ValueError, ssl.SSLContext, -1)
1079 self.assertRaises(ValueError, ssl.SSLContext, 42)
1080
Antoine Pitrou152efa22010-05-16 18:19:27 +00001081 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001082 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001083 ctx.set_ciphers("ALL")
1084 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001085 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001086 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001087
Christian Heimes892d66e2018-01-29 14:10:18 +01001088 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1089 "Test applies only to Python default ciphers")
1090 def test_python_ciphers(self):
1091 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1092 ciphers = ctx.get_ciphers()
1093 for suite in ciphers:
1094 name = suite['name']
1095 self.assertNotIn("PSK", name)
1096 self.assertNotIn("SRP", name)
1097 self.assertNotIn("MD5", name)
1098 self.assertNotIn("RC4", name)
1099 self.assertNotIn("3DES", name)
1100
Christian Heimes25bfcd52016-09-06 00:04:45 +02001101 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001102 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001103 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001104 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001105 self.assertIn('AES256-GCM-SHA384', names)
1106 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001107
Antoine Pitroub5218772010-05-21 09:56:06 +00001108 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001109 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001110 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001111 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001112 # SSLContext also enables these by default
1113 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001114 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001115 OP_ENABLE_MIDDLEBOX_COMPAT |
1116 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001117 self.assertEqual(default, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001118 with warnings_helper.check_warnings():
1119 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001120 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001121 with warnings_helper.check_warnings():
1122 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
Christian Heimes39258d32021-04-17 11:36:35 +02001123 self.assertEqual(default, ctx.options)
1124 ctx.options = 0
1125 # Ubuntu has OP_NO_SSLv3 forced on by default
1126 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001127
Christian Heimesa170fa12017-09-15 20:27:30 +02001128 def test_verify_mode_protocol(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001129 with warnings_helper.check_warnings():
1130 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001131 # Default value
1132 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1133 ctx.verify_mode = ssl.CERT_OPTIONAL
1134 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1135 ctx.verify_mode = ssl.CERT_REQUIRED
1136 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1137 ctx.verify_mode = ssl.CERT_NONE
1138 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1139 with self.assertRaises(TypeError):
1140 ctx.verify_mode = None
1141 with self.assertRaises(ValueError):
1142 ctx.verify_mode = 42
1143
Christian Heimesa170fa12017-09-15 20:27:30 +02001144 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1145 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1146 self.assertFalse(ctx.check_hostname)
1147
1148 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1149 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1150 self.assertTrue(ctx.check_hostname)
1151
Christian Heimes61d478c2018-01-27 15:51:38 +01001152 def test_hostname_checks_common_name(self):
1153 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1154 self.assertTrue(ctx.hostname_checks_common_name)
1155 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1156 ctx.hostname_checks_common_name = True
1157 self.assertTrue(ctx.hostname_checks_common_name)
1158 ctx.hostname_checks_common_name = False
1159 self.assertFalse(ctx.hostname_checks_common_name)
1160 ctx.hostname_checks_common_name = True
1161 self.assertTrue(ctx.hostname_checks_common_name)
1162 else:
1163 with self.assertRaises(AttributeError):
1164 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001165
Christian Heimes2875c602021-04-19 07:27:10 +02001166 @ignore_deprecation
Christian Heimes698dde12018-02-27 11:54:43 +01001167 def test_min_max_version(self):
1168 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001169 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1170 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001171 minimum_range = {
1172 # stock OpenSSL
1173 ssl.TLSVersion.MINIMUM_SUPPORTED,
1174 # Fedora 29 uses TLS 1.0 by default
1175 ssl.TLSVersion.TLSv1,
1176 # RHEL 8 uses TLS 1.2 by default
1177 ssl.TLSVersion.TLSv1_2
1178 }
torsava34864d12019-12-02 17:15:42 +01001179 maximum_range = {
1180 # stock OpenSSL
1181 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1182 # Fedora 32 uses TLS 1.3 by default
1183 ssl.TLSVersion.TLSv1_3
1184 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001185
Christian Heimes34de2d32019-01-18 16:09:30 +01001186 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001187 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001188 )
torsava34864d12019-12-02 17:15:42 +01001189 self.assertIn(
1190 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001191 )
1192
1193 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1194 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1195 self.assertEqual(
1196 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1197 )
1198 self.assertEqual(
1199 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1200 )
1201
1202 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1203 ctx.maximum_version = ssl.TLSVersion.TLSv1
1204 self.assertEqual(
1205 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1206 )
1207 self.assertEqual(
1208 ctx.maximum_version, ssl.TLSVersion.TLSv1
1209 )
1210
1211 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1212 self.assertEqual(
1213 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1214 )
1215
1216 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1217 self.assertIn(
1218 ctx.maximum_version,
1219 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1220 )
1221
1222 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1223 self.assertIn(
1224 ctx.minimum_version,
1225 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1226 )
1227
1228 with self.assertRaises(ValueError):
1229 ctx.minimum_version = 42
1230
1231 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1232
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001233 self.assertIn(
1234 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001235 )
1236 self.assertEqual(
1237 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1238 )
1239 with self.assertRaises(ValueError):
1240 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1241 with self.assertRaises(ValueError):
1242 ctx.maximum_version = ssl.TLSVersion.TLSv1
1243
1244
matthewhughes9348e836bb2020-07-17 09:59:15 +01001245 @unittest.skipUnless(
1246 hasattr(ssl.SSLContext, 'security_level'),
1247 "requires OpenSSL >= 1.1.0"
1248 )
1249 def test_security_level(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001250 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
matthewhughes9348e836bb2020-07-17 09:59:15 +01001251 # The default security callback allows for levels between 0-5
1252 # with OpenSSL defaulting to 1, however some vendors override the
1253 # default value (e.g. Debian defaults to 2)
1254 security_level_range = {
1255 0,
1256 1, # OpenSSL default
1257 2, # Debian
1258 3,
1259 4,
1260 5,
1261 }
1262 self.assertIn(ctx.security_level, security_level_range)
1263
Christian Heimes22587792013-11-21 23:56:13 +01001264 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001265 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001266 # default value
1267 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1268 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001269 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1270 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1271 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1272 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1273 ctx.verify_flags = ssl.VERIFY_DEFAULT
1274 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001275 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1276 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001277 # supports any value
1278 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1279 self.assertEqual(ctx.verify_flags,
1280 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1281 with self.assertRaises(TypeError):
1282 ctx.verify_flags = None
1283
Antoine Pitrou152efa22010-05-16 18:19:27 +00001284 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001285 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001286 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001287 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001288 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1289 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001290 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001291 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001292 self.assertEqual(cm.exception.errno, errno.ENOENT)
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(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001295 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001296 ctx.load_cert_chain(EMPTYCERT)
1297 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001298 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001299 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1300 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1301 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
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(ONLYCERT)
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(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001306 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001307 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1308 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001309 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001310 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001311 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001312 # Password protected key and cert
1313 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1314 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1315 ctx.load_cert_chain(CERTFILE_PROTECTED,
1316 password=bytearray(KEY_PASSWORD.encode()))
1317 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1318 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1319 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1320 bytearray(KEY_PASSWORD.encode()))
1321 with self.assertRaisesRegex(TypeError, "should be a string"):
1322 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1323 with self.assertRaises(ssl.SSLError):
1324 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1325 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1326 # openssl has a fixed limit on the password buffer.
1327 # PEM_BUFSIZE is generally set to 1kb.
1328 # Return a string larger than this.
1329 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1330 # Password callback
1331 def getpass_unicode():
1332 return KEY_PASSWORD
1333 def getpass_bytes():
1334 return KEY_PASSWORD.encode()
1335 def getpass_bytearray():
1336 return bytearray(KEY_PASSWORD.encode())
1337 def getpass_badpass():
1338 return "badpass"
1339 def getpass_huge():
1340 return b'a' * (1024 * 1024)
1341 def getpass_bad_type():
1342 return 9
1343 def getpass_exception():
1344 raise Exception('getpass error')
1345 class GetPassCallable:
1346 def __call__(self):
1347 return KEY_PASSWORD
1348 def getpass(self):
1349 return KEY_PASSWORD
1350 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1351 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1352 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1353 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1354 ctx.load_cert_chain(CERTFILE_PROTECTED,
1355 password=GetPassCallable().getpass)
1356 with self.assertRaises(ssl.SSLError):
1357 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1358 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1359 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1360 with self.assertRaisesRegex(TypeError, "must return a string"):
1361 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1362 with self.assertRaisesRegex(Exception, "getpass error"):
1363 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1364 # Make sure the password function isn't called if it isn't needed
1365 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001366
1367 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001368 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001369 ctx.load_verify_locations(CERTFILE)
1370 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1371 ctx.load_verify_locations(BYTES_CERTFILE)
1372 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1373 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001374 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001375 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001376 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001377 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001378 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001379 ctx.load_verify_locations(BADCERT)
1380 ctx.load_verify_locations(CERTFILE, CAPATH)
1381 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1382
Victor Stinner80f75e62011-01-29 11:31:20 +00001383 # Issue #10989: crash if the second argument type is invalid
1384 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1385
Christian Heimesefff7062013-11-21 03:35:02 +01001386 def test_load_verify_cadata(self):
1387 # test cadata
1388 with open(CAFILE_CACERT) as f:
1389 cacert_pem = f.read()
1390 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1391 with open(CAFILE_NEURONIO) as f:
1392 neuronio_pem = f.read()
1393 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1394
1395 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001396 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001397 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1398 ctx.load_verify_locations(cadata=cacert_pem)
1399 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1400 ctx.load_verify_locations(cadata=neuronio_pem)
1401 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1402 # cert already in hash table
1403 ctx.load_verify_locations(cadata=neuronio_pem)
1404 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1405
1406 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001407 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001408 combined = "\n".join((cacert_pem, neuronio_pem))
1409 ctx.load_verify_locations(cadata=combined)
1410 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1411
1412 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001413 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001414 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1415 neuronio_pem, "tail"]
1416 ctx.load_verify_locations(cadata="\n".join(combined))
1417 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1418
1419 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001420 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001421 ctx.load_verify_locations(cadata=cacert_der)
1422 ctx.load_verify_locations(cadata=neuronio_der)
1423 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1424 # cert already in hash table
1425 ctx.load_verify_locations(cadata=cacert_der)
1426 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1427
1428 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001429 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001430 combined = b"".join((cacert_der, neuronio_der))
1431 ctx.load_verify_locations(cadata=combined)
1432 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1433
1434 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001435 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001436 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1437
Christian Heimesb9ad88b2021-04-23 13:51:40 +02001438 with self.assertRaisesRegex(
1439 ssl.SSLError,
1440 "no start line: cadata does not contain a certificate"
1441 ):
Christian Heimesefff7062013-11-21 03:35:02 +01001442 ctx.load_verify_locations(cadata="broken")
Christian Heimesb9ad88b2021-04-23 13:51:40 +02001443 with self.assertRaisesRegex(
1444 ssl.SSLError,
1445 "not enough data: cadata does not contain a certificate"
1446 ):
Christian Heimesefff7062013-11-21 03:35:02 +01001447 ctx.load_verify_locations(cadata=b"broken")
1448
Paul Monsonf3550692019-06-19 13:09:54 -07001449 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001450 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001451 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001452 ctx.load_dh_params(DHFILE)
1453 if os.name != 'nt':
1454 ctx.load_dh_params(BYTES_DHFILE)
1455 self.assertRaises(TypeError, ctx.load_dh_params)
1456 self.assertRaises(TypeError, ctx.load_dh_params, None)
1457 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001458 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001459 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001460 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001461 ctx.load_dh_params(CERTFILE)
1462
Antoine Pitroub0182c82010-10-12 20:09:02 +00001463 def test_session_stats(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001464 for proto in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
Antoine Pitroub0182c82010-10-12 20:09:02 +00001465 ctx = ssl.SSLContext(proto)
1466 self.assertEqual(ctx.session_stats(), {
1467 'number': 0,
1468 'connect': 0,
1469 'connect_good': 0,
1470 'connect_renegotiate': 0,
1471 'accept': 0,
1472 'accept_good': 0,
1473 'accept_renegotiate': 0,
1474 'hits': 0,
1475 'misses': 0,
1476 'timeouts': 0,
1477 'cache_full': 0,
1478 })
1479
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001480 def test_set_default_verify_paths(self):
1481 # There's not much we can do to test that it acts as expected,
1482 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001483 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001484 ctx.set_default_verify_paths()
1485
Antoine Pitrou501da612011-12-21 09:27:41 +01001486 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001487 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001488 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001489 ctx.set_ecdh_curve("prime256v1")
1490 ctx.set_ecdh_curve(b"prime256v1")
1491 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1492 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1493 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1494 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1495
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001496 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001497 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001498
1499 # set_servername_callback expects a callable, or None
1500 self.assertRaises(TypeError, ctx.set_servername_callback)
1501 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1502 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1503 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1504
1505 def dummycallback(sock, servername, ctx):
1506 pass
1507 ctx.set_servername_callback(None)
1508 ctx.set_servername_callback(dummycallback)
1509
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001510 def test_sni_callback_refcycle(self):
1511 # Reference cycles through the servername callback are detected
1512 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001513 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001514 def dummycallback(sock, servername, ctx, cycle=ctx):
1515 pass
1516 ctx.set_servername_callback(dummycallback)
1517 wr = weakref.ref(ctx)
1518 del ctx, dummycallback
1519 gc.collect()
1520 self.assertIs(wr(), None)
1521
Christian Heimes9a5395a2013-06-17 15:44:12 +02001522 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001523 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001524 self.assertEqual(ctx.cert_store_stats(),
1525 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1526 ctx.load_cert_chain(CERTFILE)
1527 self.assertEqual(ctx.cert_store_stats(),
1528 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1529 ctx.load_verify_locations(CERTFILE)
1530 self.assertEqual(ctx.cert_store_stats(),
1531 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001532 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001533 self.assertEqual(ctx.cert_store_stats(),
1534 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1535
1536 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001537 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001538 self.assertEqual(ctx.get_ca_certs(), [])
1539 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1540 ctx.load_verify_locations(CERTFILE)
1541 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001542 # but CAFILE_CACERT is a CA cert
1543 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001544 self.assertEqual(ctx.get_ca_certs(),
1545 [{'issuer': ((('organizationName', 'Root CA'),),
1546 (('organizationalUnitName', 'http://www.cacert.org'),),
1547 (('commonName', 'CA Cert Signing Authority'),),
1548 (('emailAddress', 'support@cacert.org'),)),
Christian Heimesd37b74f2021-04-19 08:31:29 +02001549 'notAfter': 'Mar 29 12:29:49 2033 GMT',
1550 'notBefore': 'Mar 30 12:29:49 2003 GMT',
Christian Heimes9a5395a2013-06-17 15:44:12 +02001551 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001552 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001553 'subject': ((('organizationName', 'Root CA'),),
1554 (('organizationalUnitName', 'http://www.cacert.org'),),
1555 (('commonName', 'CA Cert Signing Authority'),),
1556 (('emailAddress', 'support@cacert.org'),)),
1557 'version': 3}])
1558
Martin Panterb55f8b72016-01-14 12:53:56 +00001559 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001560 pem = f.read()
1561 der = ssl.PEM_cert_to_DER_cert(pem)
1562 self.assertEqual(ctx.get_ca_certs(True), [der])
1563
Christian Heimes72d28502013-11-23 13:56:58 +01001564 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001565 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001566 ctx.load_default_certs()
1567
Christian Heimesa170fa12017-09-15 20:27:30 +02001568 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001569 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1570 ctx.load_default_certs()
1571
Christian Heimesa170fa12017-09-15 20:27:30 +02001572 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001573 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1574
Christian Heimesa170fa12017-09-15 20:27:30 +02001575 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001576 self.assertRaises(TypeError, ctx.load_default_certs, None)
1577 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1578
Benjamin Peterson91244e02014-10-03 18:17:15 -04001579 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001580 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001581 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001582 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001583 env["SSL_CERT_DIR"] = CAPATH
1584 env["SSL_CERT_FILE"] = CERTFILE
1585 ctx.load_default_certs()
1586 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1587
Benjamin Peterson91244e02014-10-03 18:17:15 -04001588 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001589 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001590 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001591 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001592 ctx.load_default_certs()
1593 stats = ctx.cert_store_stats()
1594
Christian Heimesa170fa12017-09-15 20:27:30 +02001595 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001596 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001597 env["SSL_CERT_DIR"] = CAPATH
1598 env["SSL_CERT_FILE"] = CERTFILE
1599 ctx.load_default_certs()
1600 stats["x509"] += 1
1601 self.assertEqual(ctx.cert_store_stats(), stats)
1602
Christian Heimes358cfd42016-09-10 22:43:48 +02001603 def _assert_context_options(self, ctx):
1604 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1605 if OP_NO_COMPRESSION != 0:
1606 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1607 OP_NO_COMPRESSION)
1608 if OP_SINGLE_DH_USE != 0:
1609 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1610 OP_SINGLE_DH_USE)
1611 if OP_SINGLE_ECDH_USE != 0:
1612 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1613 OP_SINGLE_ECDH_USE)
1614 if OP_CIPHER_SERVER_PREFERENCE != 0:
1615 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1616 OP_CIPHER_SERVER_PREFERENCE)
1617
Christian Heimes4c05b472013-11-23 15:58:30 +01001618 def test_create_default_context(self):
1619 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001620
Christian Heimes2875c602021-04-19 07:27:10 +02001621 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001622 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001623 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001624 self._assert_context_options(ctx)
1625
Christian Heimes4c05b472013-11-23 15:58:30 +01001626 with open(SIGNING_CA) as f:
1627 cadata = f.read()
1628 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1629 cadata=cadata)
Christian Heimes2875c602021-04-19 07:27:10 +02001630 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001631 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001632 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001633
1634 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001635 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes4c05b472013-11-23 15:58:30 +01001636 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001637 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001638
Christian Heimes2875c602021-04-19 07:27:10 +02001639
1640
Christian Heimes67986f92013-11-23 22:43:47 +01001641 def test__create_stdlib_context(self):
1642 ctx = ssl._create_stdlib_context()
Christian Heimes2875c602021-04-19 07:27:10 +02001643 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes67986f92013-11-23 22:43:47 +01001644 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001645 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001646 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001647
Christian Heimes2875c602021-04-19 07:27:10 +02001648 with warnings_helper.check_warnings():
1649 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
Christian Heimes67986f92013-11-23 22:43:47 +01001650 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1651 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001652 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001653
Christian Heimes2875c602021-04-19 07:27:10 +02001654 with warnings_helper.check_warnings():
1655 ctx = ssl._create_stdlib_context(
1656 ssl.PROTOCOL_TLSv1_2,
1657 cert_reqs=ssl.CERT_REQUIRED,
1658 check_hostname=True
1659 )
1660 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
Christian Heimes67986f92013-11-23 22:43:47 +01001661 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001662 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001663 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001664
1665 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001666 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes67986f92013-11-23 22:43:47 +01001667 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001668 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001669
Christian Heimes1aa9a752013-12-02 02:41:19 +01001670 def test_check_hostname(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001671 with warnings_helper.check_warnings():
1672 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001673 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001674 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001675
Christian Heimese82c0342017-09-15 20:29:57 +02001676 # Auto set CERT_REQUIRED
1677 ctx.check_hostname = True
1678 self.assertTrue(ctx.check_hostname)
1679 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1680 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001681 ctx.verify_mode = ssl.CERT_REQUIRED
1682 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001683 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001684
Christian Heimese82c0342017-09-15 20:29:57 +02001685 # Changing verify_mode does not affect check_hostname
1686 ctx.check_hostname = False
1687 ctx.verify_mode = ssl.CERT_NONE
1688 ctx.check_hostname = False
1689 self.assertFalse(ctx.check_hostname)
1690 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1691 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001692 ctx.check_hostname = True
1693 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001694 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1695
1696 ctx.check_hostname = False
1697 ctx.verify_mode = ssl.CERT_OPTIONAL
1698 ctx.check_hostname = False
1699 self.assertFalse(ctx.check_hostname)
1700 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1701 # keep CERT_OPTIONAL
1702 ctx.check_hostname = True
1703 self.assertTrue(ctx.check_hostname)
1704 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001705
1706 # Cannot set CERT_NONE with check_hostname enabled
1707 with self.assertRaises(ValueError):
1708 ctx.verify_mode = ssl.CERT_NONE
1709 ctx.check_hostname = False
1710 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001711 ctx.verify_mode = ssl.CERT_NONE
1712 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001713
Christian Heimes5fe668c2016-09-12 00:01:11 +02001714 def test_context_client_server(self):
1715 # PROTOCOL_TLS_CLIENT has sane defaults
1716 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1717 self.assertTrue(ctx.check_hostname)
1718 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1719
1720 # PROTOCOL_TLS_SERVER has different but also sane defaults
1721 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1722 self.assertFalse(ctx.check_hostname)
1723 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1724
Christian Heimes4df60f12017-09-15 20:26:05 +02001725 def test_context_custom_class(self):
1726 class MySSLSocket(ssl.SSLSocket):
1727 pass
1728
1729 class MySSLObject(ssl.SSLObject):
1730 pass
1731
1732 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1733 ctx.sslsocket_class = MySSLSocket
1734 ctx.sslobject_class = MySSLObject
1735
1736 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1737 self.assertIsInstance(sock, MySSLSocket)
1738 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1739 self.assertIsInstance(obj, MySSLObject)
1740
Christian Heimes78c7d522019-06-03 21:00:10 +02001741 def test_num_tickest(self):
1742 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1743 self.assertEqual(ctx.num_tickets, 2)
1744 ctx.num_tickets = 1
1745 self.assertEqual(ctx.num_tickets, 1)
1746 ctx.num_tickets = 0
1747 self.assertEqual(ctx.num_tickets, 0)
1748 with self.assertRaises(ValueError):
1749 ctx.num_tickets = -1
1750 with self.assertRaises(TypeError):
1751 ctx.num_tickets = None
1752
1753 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1754 self.assertEqual(ctx.num_tickets, 2)
1755 with self.assertRaises(ValueError):
1756 ctx.num_tickets = 1
1757
Antoine Pitrou152efa22010-05-16 18:19:27 +00001758
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001759class SSLErrorTests(unittest.TestCase):
1760
1761 def test_str(self):
1762 # The str() of a SSLError doesn't include the errno
1763 e = ssl.SSLError(1, "foo")
1764 self.assertEqual(str(e), "foo")
1765 self.assertEqual(e.errno, 1)
1766 # Same for a subclass
1767 e = ssl.SSLZeroReturnError(1, "foo")
1768 self.assertEqual(str(e), "foo")
1769 self.assertEqual(e.errno, 1)
1770
Paul Monsonf3550692019-06-19 13:09:54 -07001771 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001772 def test_lib_reason(self):
1773 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001774 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001775 with self.assertRaises(ssl.SSLError) as cm:
1776 ctx.load_dh_params(CERTFILE)
1777 self.assertEqual(cm.exception.library, 'PEM')
1778 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1779 s = str(cm.exception)
1780 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1781
1782 def test_subclass(self):
1783 # Check that the appropriate SSLError subclass is raised
1784 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001785 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1786 ctx.check_hostname = False
1787 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001788 with socket.create_server(("127.0.0.1", 0)) as s:
1789 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001790 c.setblocking(False)
1791 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001792 with self.assertRaises(ssl.SSLWantReadError) as cm:
1793 c.do_handshake()
1794 s = str(cm.exception)
1795 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1796 # For compatibility
1797 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1798
1799
Christian Heimes61d478c2018-01-27 15:51:38 +01001800 def test_bad_server_hostname(self):
1801 ctx = ssl.create_default_context()
1802 with self.assertRaises(ValueError):
1803 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1804 server_hostname="")
1805 with self.assertRaises(ValueError):
1806 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1807 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001808 with self.assertRaises(TypeError):
1809 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1810 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001811
1812
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001813class MemoryBIOTests(unittest.TestCase):
1814
1815 def test_read_write(self):
1816 bio = ssl.MemoryBIO()
1817 bio.write(b'foo')
1818 self.assertEqual(bio.read(), b'foo')
1819 self.assertEqual(bio.read(), b'')
1820 bio.write(b'foo')
1821 bio.write(b'bar')
1822 self.assertEqual(bio.read(), b'foobar')
1823 self.assertEqual(bio.read(), b'')
1824 bio.write(b'baz')
1825 self.assertEqual(bio.read(2), b'ba')
1826 self.assertEqual(bio.read(1), b'z')
1827 self.assertEqual(bio.read(1), b'')
1828
1829 def test_eof(self):
1830 bio = ssl.MemoryBIO()
1831 self.assertFalse(bio.eof)
1832 self.assertEqual(bio.read(), b'')
1833 self.assertFalse(bio.eof)
1834 bio.write(b'foo')
1835 self.assertFalse(bio.eof)
1836 bio.write_eof()
1837 self.assertFalse(bio.eof)
1838 self.assertEqual(bio.read(2), b'fo')
1839 self.assertFalse(bio.eof)
1840 self.assertEqual(bio.read(1), b'o')
1841 self.assertTrue(bio.eof)
1842 self.assertEqual(bio.read(), b'')
1843 self.assertTrue(bio.eof)
1844
1845 def test_pending(self):
1846 bio = ssl.MemoryBIO()
1847 self.assertEqual(bio.pending, 0)
1848 bio.write(b'foo')
1849 self.assertEqual(bio.pending, 3)
1850 for i in range(3):
1851 bio.read(1)
1852 self.assertEqual(bio.pending, 3-i-1)
1853 for i in range(3):
1854 bio.write(b'x')
1855 self.assertEqual(bio.pending, i+1)
1856 bio.read()
1857 self.assertEqual(bio.pending, 0)
1858
1859 def test_buffer_types(self):
1860 bio = ssl.MemoryBIO()
1861 bio.write(b'foo')
1862 self.assertEqual(bio.read(), b'foo')
1863 bio.write(bytearray(b'bar'))
1864 self.assertEqual(bio.read(), b'bar')
1865 bio.write(memoryview(b'baz'))
1866 self.assertEqual(bio.read(), b'baz')
1867
1868 def test_error_types(self):
1869 bio = ssl.MemoryBIO()
1870 self.assertRaises(TypeError, bio.write, 'foo')
1871 self.assertRaises(TypeError, bio.write, None)
1872 self.assertRaises(TypeError, bio.write, True)
1873 self.assertRaises(TypeError, bio.write, 1)
1874
1875
Christian Heimes9d50ab52018-02-27 10:17:30 +01001876class SSLObjectTests(unittest.TestCase):
1877 def test_private_init(self):
1878 bio = ssl.MemoryBIO()
1879 with self.assertRaisesRegex(TypeError, "public constructor"):
1880 ssl.SSLObject(bio, bio)
1881
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001882 def test_unwrap(self):
1883 client_ctx, server_ctx, hostname = testing_context()
1884 c_in = ssl.MemoryBIO()
1885 c_out = ssl.MemoryBIO()
1886 s_in = ssl.MemoryBIO()
1887 s_out = ssl.MemoryBIO()
1888 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1889 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1890
1891 # Loop on the handshake for a bit to get it settled
1892 for _ in range(5):
1893 try:
1894 client.do_handshake()
1895 except ssl.SSLWantReadError:
1896 pass
1897 if c_out.pending:
1898 s_in.write(c_out.read())
1899 try:
1900 server.do_handshake()
1901 except ssl.SSLWantReadError:
1902 pass
1903 if s_out.pending:
1904 c_in.write(s_out.read())
1905 # Now the handshakes should be complete (don't raise WantReadError)
1906 client.do_handshake()
1907 server.do_handshake()
1908
1909 # Now if we unwrap one side unilaterally, it should send close-notify
1910 # and raise WantReadError:
1911 with self.assertRaises(ssl.SSLWantReadError):
1912 client.unwrap()
1913
1914 # But server.unwrap() does not raise, because it reads the client's
1915 # close-notify:
1916 s_in.write(c_out.read())
1917 server.unwrap()
1918
1919 # And now that the client gets the server's close-notify, it doesn't
1920 # raise either.
1921 c_in.write(s_out.read())
1922 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001923
Martin Panter3840b2a2016-03-27 01:53:46 +00001924class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001925 """Tests that connect to a simple server running in the background"""
1926
1927 def setUp(self):
juhovh49fdf112021-04-18 21:11:48 +10001928 self.server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1929 self.server_context.load_cert_chain(SIGNED_CERTFILE)
1930 server = ThreadedEchoServer(context=self.server_context)
Martin Panter3840b2a2016-03-27 01:53:46 +00001931 self.server_addr = (HOST, server.port)
1932 server.__enter__()
1933 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001934
Antoine Pitrou480a1242010-04-28 21:37:09 +00001935 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001936 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001937 cert_reqs=ssl.CERT_NONE) as s:
1938 s.connect(self.server_addr)
1939 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001940 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001941
Martin Panter3840b2a2016-03-27 01:53:46 +00001942 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001943 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001944 cert_reqs=ssl.CERT_REQUIRED,
1945 ca_certs=SIGNING_CA) as s:
1946 s.connect(self.server_addr)
1947 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001948 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001949
Martin Panter3840b2a2016-03-27 01:53:46 +00001950 def test_connect_fail(self):
1951 # This should fail because we have no verification certs. Connection
1952 # failure crashes ThreadedEchoServer, so run this in an independent
1953 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001954 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001955 cert_reqs=ssl.CERT_REQUIRED)
1956 self.addCleanup(s.close)
1957 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1958 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001959
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001960 def test_connect_ex(self):
1961 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02001962 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001963 cert_reqs=ssl.CERT_REQUIRED,
1964 ca_certs=SIGNING_CA)
1965 self.addCleanup(s.close)
1966 self.assertEqual(0, s.connect_ex(self.server_addr))
1967 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001968
1969 def test_non_blocking_connect_ex(self):
1970 # Issue #11326: non-blocking connect_ex() should allow handshake
1971 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02001972 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001973 cert_reqs=ssl.CERT_REQUIRED,
1974 ca_certs=SIGNING_CA,
1975 do_handshake_on_connect=False)
1976 self.addCleanup(s.close)
1977 s.setblocking(False)
1978 rc = s.connect_ex(self.server_addr)
1979 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1980 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
1981 # Wait for connect to finish
1982 select.select([], [s], [], 5.0)
1983 # Non-blocking handshake
1984 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001985 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00001986 s.do_handshake()
1987 break
1988 except ssl.SSLWantReadError:
1989 select.select([s], [], [], 5.0)
1990 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001991 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00001992 # SSL established
1993 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001994
Antoine Pitrou152efa22010-05-16 18:19:27 +00001995 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001996 # Same as test_connect, but with a separately created context
Christian Heimes2875c602021-04-19 07:27:10 +02001997 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1998 ctx.check_hostname = False
1999 ctx.verify_mode = ssl.CERT_NONE
Martin Panter3840b2a2016-03-27 01:53:46 +00002000 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2001 s.connect(self.server_addr)
2002 self.assertEqual({}, s.getpeercert())
2003 # Same with a server hostname
2004 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2005 server_hostname="dummy") as s:
2006 s.connect(self.server_addr)
2007 ctx.verify_mode = ssl.CERT_REQUIRED
2008 # This should succeed because we specify the root cert
2009 ctx.load_verify_locations(SIGNING_CA)
2010 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2011 s.connect(self.server_addr)
2012 cert = s.getpeercert()
2013 self.assertTrue(cert)
2014
2015 def test_connect_with_context_fail(self):
2016 # This should fail because we have no verification certs. Connection
2017 # failure crashes ThreadedEchoServer, so run this in an independent
2018 # test method.
Christian Heimes2875c602021-04-19 07:27:10 +02002019 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2020 s = ctx.wrap_socket(
2021 socket.socket(socket.AF_INET),
2022 server_hostname=SIGNED_CERTFILE_HOSTNAME
2023 )
Martin Panter3840b2a2016-03-27 01:53:46 +00002024 self.addCleanup(s.close)
2025 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2026 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002027
2028 def test_connect_capath(self):
2029 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002030 # NOTE: the subject hashing algorithm has been changed between
2031 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2032 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002033 # filename) for this test to be portable across OpenSSL releases.
Christian Heimes2875c602021-04-19 07:27:10 +02002034 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002035 ctx.load_verify_locations(capath=CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002036 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2037 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002038 s.connect(self.server_addr)
2039 cert = s.getpeercert()
2040 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002041
Martin Panter3840b2a2016-03-27 01:53:46 +00002042 # Same with a bytes `capath` argument
Christian Heimes2875c602021-04-19 07:27:10 +02002043 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002044 ctx.load_verify_locations(capath=BYTES_CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002045 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2046 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002047 s.connect(self.server_addr)
2048 cert = s.getpeercert()
2049 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002050
Christian Heimesefff7062013-11-21 03:35:02 +01002051 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002052 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002053 pem = f.read()
2054 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002055 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002056 ctx.load_verify_locations(cadata=pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002057 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2058 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002059 s.connect(self.server_addr)
2060 cert = s.getpeercert()
2061 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002062
Martin Panter3840b2a2016-03-27 01:53:46 +00002063 # same with DER
Christian Heimes2875c602021-04-19 07:27:10 +02002064 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002065 ctx.load_verify_locations(cadata=der)
Christian Heimes2875c602021-04-19 07:27:10 +02002066 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2067 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002068 s.connect(self.server_addr)
2069 cert = s.getpeercert()
2070 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002071
Antoine Pitroue3220242010-04-24 11:13:53 +00002072 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2073 def test_makefile_close(self):
2074 # Issue #5238: creating a file-like object with makefile() shouldn't
2075 # delay closing the underlying "real socket" (here tested with its
2076 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002077 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002078 ss.connect(self.server_addr)
2079 fd = ss.fileno()
2080 f = ss.makefile()
2081 f.close()
2082 # The fd is still open
2083 os.read(fd, 0)
2084 # Closing the SSL socket should close the fd too
2085 ss.close()
2086 gc.collect()
2087 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002088 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002089 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002090
Antoine Pitrou480a1242010-04-28 21:37:09 +00002091 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002092 s = socket.socket(socket.AF_INET)
2093 s.connect(self.server_addr)
2094 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002095 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002096 cert_reqs=ssl.CERT_NONE,
2097 do_handshake_on_connect=False)
2098 self.addCleanup(s.close)
2099 count = 0
2100 while True:
2101 try:
2102 count += 1
2103 s.do_handshake()
2104 break
2105 except ssl.SSLWantReadError:
2106 select.select([s], [], [])
2107 except ssl.SSLWantWriteError:
2108 select.select([], [s], [])
2109 if support.verbose:
2110 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002111
Antoine Pitrou480a1242010-04-28 21:37:09 +00002112 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002113 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002114
juhovh49fdf112021-04-18 21:11:48 +10002115 def test_get_server_certificate_sni(self):
2116 host, port = self.server_addr
2117 server_names = []
2118
2119 # We store servername_cb arguments to make sure they match the host
2120 def servername_cb(ssl_sock, server_name, initial_context):
2121 server_names.append(server_name)
2122 self.server_context.set_servername_callback(servername_cb)
2123
2124 pem = ssl.get_server_certificate((host, port))
2125 if not pem:
2126 self.fail("No server certificate on %s:%s!" % (host, port))
2127
2128 pem = ssl.get_server_certificate((host, port), ca_certs=SIGNING_CA)
2129 if not pem:
2130 self.fail("No server certificate on %s:%s!" % (host, port))
2131 if support.verbose:
2132 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port, pem))
2133
2134 self.assertEqual(server_names, [host, host])
2135
Martin Panter3840b2a2016-03-27 01:53:46 +00002136 def test_get_server_certificate_fail(self):
2137 # Connection failure crashes ThreadedEchoServer, so run this in an
2138 # independent test method
2139 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002140
Zackery Spytzb2fac1a2021-04-23 22:46:01 -06002141 def test_get_server_certificate_timeout(self):
Christian Heimesf05c2ae2021-04-24 07:54:08 +02002142 def servername_cb(ssl_sock, server_name, initial_context):
2143 time.sleep(0.2)
2144 self.server_context.set_servername_callback(servername_cb)
2145
Zackery Spytzb2fac1a2021-04-23 22:46:01 -06002146 with self.assertRaises(socket.timeout):
2147 ssl.get_server_certificate(self.server_addr, ca_certs=SIGNING_CA,
Christian Heimesf05c2ae2021-04-24 07:54:08 +02002148 timeout=0.1)
Zackery Spytzb2fac1a2021-04-23 22:46:01 -06002149
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002150 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002151 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002152 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2153 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002154 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002155 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2156 s.connect(self.server_addr)
2157 # Error checking can happen at instantiation or when connecting
2158 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2159 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002160 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002161 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2162 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002163
Christian Heimes9a5395a2013-06-17 15:44:12 +02002164 def test_get_ca_certs_capath(self):
2165 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002166 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002167 ctx.load_verify_locations(capath=CAPATH)
2168 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002169 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2170 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002171 s.connect(self.server_addr)
2172 cert = s.getpeercert()
2173 self.assertTrue(cert)
2174 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002175
Christian Heimes8e7f3942013-12-05 07:41:08 +01002176 def test_context_setget(self):
2177 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002178 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2179 ctx1.load_verify_locations(capath=CAPATH)
2180 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2181 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002182 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002183 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002184 ss.connect(self.server_addr)
2185 self.assertIs(ss.context, ctx1)
2186 self.assertIs(ss._sslobj.context, ctx1)
2187 ss.context = ctx2
2188 self.assertIs(ss.context, ctx2)
2189 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002190
2191 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2192 # A simple IO loop. Call func(*args) depending on the error we get
2193 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002194 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002195 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002196 count = 0
2197 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002198 if time.monotonic() > deadline:
2199 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002200 errno = None
2201 count += 1
2202 try:
2203 ret = func(*args)
2204 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002205 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002206 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002207 raise
2208 errno = e.errno
2209 # Get any data from the outgoing BIO irrespective of any error, and
2210 # send it to the socket.
2211 buf = outgoing.read()
2212 sock.sendall(buf)
2213 # If there's no error, we're done. For WANT_READ, we need to get
2214 # data from the socket and put it in the incoming BIO.
2215 if errno is None:
2216 break
2217 elif errno == ssl.SSL_ERROR_WANT_READ:
2218 buf = sock.recv(32768)
2219 if buf:
2220 incoming.write(buf)
2221 else:
2222 incoming.write_eof()
2223 if support.verbose:
2224 sys.stdout.write("Needed %d calls to complete %s().\n"
2225 % (count, func.__name__))
2226 return ret
2227
Martin Panter3840b2a2016-03-27 01:53:46 +00002228 def test_bio_handshake(self):
2229 sock = socket.socket(socket.AF_INET)
2230 self.addCleanup(sock.close)
2231 sock.connect(self.server_addr)
2232 incoming = ssl.MemoryBIO()
2233 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002234 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2235 self.assertTrue(ctx.check_hostname)
2236 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002237 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002238 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2239 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002240 self.assertIs(sslobj._sslobj.owner, sslobj)
2241 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002242 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002243 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002244 self.assertRaises(ValueError, sslobj.getpeercert)
2245 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2246 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2247 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2248 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002249 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002250 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002251 self.assertTrue(sslobj.getpeercert())
2252 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2253 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2254 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002255 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002256 except ssl.SSLSyscallError:
2257 # If the server shuts down the TCP connection without sending a
2258 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2259 pass
2260 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2261
2262 def test_bio_read_write_data(self):
2263 sock = socket.socket(socket.AF_INET)
2264 self.addCleanup(sock.close)
2265 sock.connect(self.server_addr)
2266 incoming = ssl.MemoryBIO()
2267 outgoing = ssl.MemoryBIO()
Christian Heimes2875c602021-04-19 07:27:10 +02002268 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2269 ctx.check_hostname = False
Martin Panter3840b2a2016-03-27 01:53:46 +00002270 ctx.verify_mode = ssl.CERT_NONE
2271 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2272 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2273 req = b'FOO\n'
2274 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2275 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2276 self.assertEqual(buf, b'foo\n')
2277 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002278
2279
Martin Panter3840b2a2016-03-27 01:53:46 +00002280class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002281
Martin Panter3840b2a2016-03-27 01:53:46 +00002282 def test_timeout_connect_ex(self):
2283 # Issue #12065: on a timeout, connect_ex() should return the original
2284 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002285 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002286 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002287 cert_reqs=ssl.CERT_REQUIRED,
2288 do_handshake_on_connect=False)
2289 self.addCleanup(s.close)
2290 s.settimeout(0.0000001)
2291 rc = s.connect_ex((REMOTE_HOST, 443))
2292 if rc == 0:
2293 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002294 elif rc == errno.ENETUNREACH:
2295 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002296 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2297
Serhiy Storchaka16994912020-04-25 10:06:29 +03002298 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002299 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002300 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002301 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2302 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2303
Martin Panter3840b2a2016-03-27 01:53:46 +00002304
2305def _test_get_server_certificate(test, host, port, cert=None):
2306 pem = ssl.get_server_certificate((host, port))
2307 if not pem:
2308 test.fail("No server certificate on %s:%s!" % (host, port))
2309
2310 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2311 if not pem:
2312 test.fail("No server certificate on %s:%s!" % (host, port))
2313 if support.verbose:
2314 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2315
2316def _test_get_server_certificate_fail(test, host, port):
2317 try:
2318 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2319 except ssl.SSLError as x:
2320 #should fail
2321 if support.verbose:
2322 sys.stdout.write("%s\n" % x)
2323 else:
2324 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2325
2326
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002327from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002328
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002329class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002330
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002331 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002332
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002333 """A mildly complicated class, because we want it to work both
2334 with and without the SSL wrapper around the socket connection, so
2335 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002336
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002337 def __init__(self, server, connsock, addr):
2338 self.server = server
2339 self.running = False
2340 self.sock = connsock
2341 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002342 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002343 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002344 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002345 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002346
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002347 def wrap_conn(self):
2348 try:
2349 self.sslconn = self.server.context.wrap_socket(
2350 self.sock, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002351 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002352 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002353 # We treat ConnectionResetError as though it were an
2354 # SSLError - OpenSSL on Ubuntu abruptly closes the
2355 # connection when asked to use an unsupported protocol.
2356 #
Christian Heimes529525f2018-05-23 22:24:45 +02002357 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2358 # tries to send session tickets after handshake.
2359 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002360 #
2361 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2362 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002363 self.server.conn_errors.append(str(e))
2364 if self.server.chatty:
2365 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2366 self.running = False
2367 self.close()
2368 return False
2369 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002370 # OSError may occur with wrong protocols, e.g. both
2371 # sides use PROTOCOL_TLS_SERVER.
2372 #
2373 # XXX Various errors can have happened here, for example
2374 # a mismatching protocol version, an invalid certificate,
2375 # or a low-level bug. This should be made more discriminating.
2376 #
2377 # bpo-31323: Store the exception as string to prevent
2378 # a reference leak: server -> conn_errors -> exception
2379 # -> traceback -> self (ConnectionHandler) -> server
2380 self.server.conn_errors.append(str(e))
2381 if self.server.chatty:
2382 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2383 self.running = False
2384 self.server.stop()
2385 self.close()
2386 return False
2387 else:
2388 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2389 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2390 cert = self.sslconn.getpeercert()
2391 if support.verbose and self.server.chatty:
2392 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2393 cert_binary = self.sslconn.getpeercert(True)
2394 if support.verbose and self.server.chatty:
Christian Heimesc8666cf2021-04-24 09:17:54 +02002395 if cert_binary is None:
2396 sys.stdout.write(" client did not provide a cert\n")
2397 else:
2398 sys.stdout.write(f" cert binary is {len(cert_binary)}b\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002399 cipher = self.sslconn.cipher()
2400 if support.verbose and self.server.chatty:
2401 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002402 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002403
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002404 def read(self):
2405 if self.sslconn:
2406 return self.sslconn.read()
2407 else:
2408 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002409
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002410 def write(self, bytes):
2411 if self.sslconn:
2412 return self.sslconn.write(bytes)
2413 else:
2414 return self.sock.send(bytes)
2415
2416 def close(self):
2417 if self.sslconn:
2418 self.sslconn.close()
2419 else:
2420 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002421
Antoine Pitrou480a1242010-04-28 21:37:09 +00002422 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002423 self.running = True
2424 if not self.server.starttls_server:
2425 if not self.wrap_conn():
2426 return
2427 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002428 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002429 msg = self.read()
2430 stripped = msg.strip()
2431 if not stripped:
2432 # eof, so quit this handler
2433 self.running = False
2434 try:
2435 self.sock = self.sslconn.unwrap()
2436 except OSError:
2437 # Many tests shut the TCP connection down
2438 # without an SSL shutdown. This causes
2439 # unwrap() to raise OSError with errno=0!
2440 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002441 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002442 self.sslconn = None
2443 self.close()
2444 elif stripped == b'over':
2445 if support.verbose and self.server.connectionchatty:
2446 sys.stdout.write(" server: client closed connection\n")
2447 self.close()
2448 return
2449 elif (self.server.starttls_server and
2450 stripped == b'STARTTLS'):
2451 if support.verbose and self.server.connectionchatty:
2452 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2453 self.write(b"OK\n")
2454 if not self.wrap_conn():
2455 return
2456 elif (self.server.starttls_server and self.sslconn
2457 and stripped == b'ENDTLS'):
2458 if support.verbose and self.server.connectionchatty:
2459 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2460 self.write(b"OK\n")
2461 self.sock = self.sslconn.unwrap()
2462 self.sslconn = None
2463 if support.verbose and self.server.connectionchatty:
2464 sys.stdout.write(" server: connection is now unencrypted...\n")
2465 elif stripped == b'CB tls-unique':
2466 if support.verbose and self.server.connectionchatty:
2467 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2468 data = self.sslconn.get_channel_binding("tls-unique")
2469 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002470 elif stripped == b'PHA':
2471 if support.verbose and self.server.connectionchatty:
2472 sys.stdout.write(" server: initiating post handshake auth\n")
2473 try:
2474 self.sslconn.verify_client_post_handshake()
2475 except ssl.SSLError as e:
2476 self.write(repr(e).encode("us-ascii") + b"\n")
2477 else:
2478 self.write(b"OK\n")
2479 elif stripped == b'HASCERT':
2480 if self.sslconn.getpeercert() is not None:
2481 self.write(b'TRUE\n')
2482 else:
2483 self.write(b'FALSE\n')
2484 elif stripped == b'GETCERT':
2485 cert = self.sslconn.getpeercert()
2486 self.write(repr(cert).encode("us-ascii") + b"\n")
Christian Heimes666991f2021-04-26 15:01:40 +02002487 elif stripped == b'VERIFIEDCHAIN':
2488 certs = self.sslconn._sslobj.get_verified_chain()
2489 self.write(len(certs).to_bytes(1, "big") + b"\n")
2490 elif stripped == b'UNVERIFIEDCHAIN':
2491 certs = self.sslconn._sslobj.get_unverified_chain()
2492 self.write(len(certs).to_bytes(1, "big") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002493 else:
2494 if (support.verbose and
2495 self.server.connectionchatty):
2496 ctype = (self.sslconn and "encrypted") or "unencrypted"
2497 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2498 % (msg, ctype, msg.lower(), ctype))
2499 self.write(msg.lower())
Christian Heimesc8666cf2021-04-24 09:17:54 +02002500 except OSError as e:
2501 # handles SSLError and socket errors
Christian Heimes529525f2018-05-23 22:24:45 +02002502 if self.server.chatty and support.verbose:
Christian Heimesc8666cf2021-04-24 09:17:54 +02002503 if isinstance(e, ConnectionError):
2504 # OpenSSL 1.1.1 sometimes raises
2505 # ConnectionResetError when connection is not
2506 # shut down gracefully.
2507 print(
2508 f" Connection reset by peer: {self.addr}"
2509 )
2510 else:
2511 handle_error("Test server failure:\n")
2512 try:
2513 self.write(b"ERROR\n")
2514 except OSError:
2515 pass
Bill Janssen2f5799b2008-06-29 00:08:12 +00002516 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002517 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002518
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002519 # normally, we'd just stop here, but for the test
2520 # harness, we want to stop the server
2521 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002522
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002523 def __init__(self, certificate=None, ssl_version=None,
2524 certreqs=None, cacerts=None,
2525 chatty=True, connectionchatty=False, starttls_server=False,
Christian Heimes2875c602021-04-19 07:27:10 +02002526 alpn_protocols=None,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002527 ciphers=None, context=None):
2528 if context:
2529 self.context = context
2530 else:
2531 self.context = ssl.SSLContext(ssl_version
2532 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002533 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002534 self.context.verify_mode = (certreqs if certreqs is not None
2535 else ssl.CERT_NONE)
2536 if cacerts:
2537 self.context.load_verify_locations(cacerts)
2538 if certificate:
2539 self.context.load_cert_chain(certificate)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002540 if alpn_protocols:
2541 self.context.set_alpn_protocols(alpn_protocols)
2542 if ciphers:
2543 self.context.set_ciphers(ciphers)
2544 self.chatty = chatty
2545 self.connectionchatty = connectionchatty
2546 self.starttls_server = starttls_server
2547 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002548 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002549 self.flag = None
2550 self.active = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002551 self.selected_alpn_protocols = []
2552 self.shared_ciphers = []
2553 self.conn_errors = []
2554 threading.Thread.__init__(self)
2555 self.daemon = True
2556
2557 def __enter__(self):
2558 self.start(threading.Event())
2559 self.flag.wait()
2560 return self
2561
2562 def __exit__(self, *args):
2563 self.stop()
2564 self.join()
2565
2566 def start(self, flag=None):
2567 self.flag = flag
2568 threading.Thread.start(self)
2569
2570 def run(self):
2571 self.sock.settimeout(0.05)
2572 self.sock.listen()
2573 self.active = True
2574 if self.flag:
2575 # signal an event
2576 self.flag.set()
2577 while self.active:
2578 try:
2579 newconn, connaddr = self.sock.accept()
2580 if support.verbose and self.chatty:
2581 sys.stdout.write(' server: new connection from '
2582 + repr(connaddr) + '\n')
2583 handler = self.ConnectionHandler(self, newconn, connaddr)
2584 handler.start()
2585 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002586 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002587 pass
2588 except KeyboardInterrupt:
2589 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002590 except BaseException as e:
2591 if support.verbose and self.chatty:
2592 sys.stdout.write(
2593 ' connection handling failed: ' + repr(e) + '\n')
2594
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002595 self.sock.close()
2596
2597 def stop(self):
2598 self.active = False
2599
2600class AsyncoreEchoServer(threading.Thread):
2601
2602 # this one's based on asyncore.dispatcher
2603
2604 class EchoServer (asyncore.dispatcher):
2605
2606 class ConnectionHandler(asyncore.dispatcher_with_send):
2607
2608 def __init__(self, conn, certfile):
2609 self.socket = test_wrap_socket(conn, server_side=True,
2610 certfile=certfile,
2611 do_handshake_on_connect=False)
2612 asyncore.dispatcher_with_send.__init__(self, self.socket)
2613 self._ssl_accepting = True
2614 self._do_ssl_handshake()
2615
2616 def readable(self):
2617 if isinstance(self.socket, ssl.SSLSocket):
2618 while self.socket.pending() > 0:
2619 self.handle_read_event()
2620 return True
2621
2622 def _do_ssl_handshake(self):
2623 try:
2624 self.socket.do_handshake()
2625 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2626 return
2627 except ssl.SSLEOFError:
2628 return self.handle_close()
2629 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002630 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002631 except OSError as err:
2632 if err.args[0] == errno.ECONNABORTED:
2633 return self.handle_close()
2634 else:
2635 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002636
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002637 def handle_read(self):
2638 if self._ssl_accepting:
2639 self._do_ssl_handshake()
2640 else:
2641 data = self.recv(1024)
2642 if support.verbose:
2643 sys.stdout.write(" server: read %s from client\n" % repr(data))
2644 if not data:
2645 self.close()
2646 else:
2647 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002648
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002649 def handle_close(self):
2650 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002651 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002652 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002653
2654 def handle_error(self):
2655 raise
2656
Trent Nelson78520002008-04-10 20:54:35 +00002657 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002658 self.certfile = certfile
2659 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002660 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002661 asyncore.dispatcher.__init__(self, sock)
2662 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002663
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002664 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002665 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002666 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2667 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002668
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002669 def handle_error(self):
2670 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002671
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002672 def __init__(self, certfile):
2673 self.flag = None
2674 self.active = False
2675 self.server = self.EchoServer(certfile)
2676 self.port = self.server.port
2677 threading.Thread.__init__(self)
2678 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002679
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002680 def __str__(self):
2681 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002682
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002683 def __enter__(self):
2684 self.start(threading.Event())
2685 self.flag.wait()
2686 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002687
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002688 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002689 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002690 sys.stdout.write(" cleanup: stopping server.\n")
2691 self.stop()
2692 if support.verbose:
2693 sys.stdout.write(" cleanup: joining server thread.\n")
2694 self.join()
2695 if support.verbose:
2696 sys.stdout.write(" cleanup: successfully joined.\n")
2697 # make sure that ConnectionHandler is removed from socket_map
2698 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002699
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002700 def start (self, flag=None):
2701 self.flag = flag
2702 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002703
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002704 def run(self):
2705 self.active = True
2706 if self.flag:
2707 self.flag.set()
2708 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002709 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002710 asyncore.loop(1)
2711 except:
2712 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002713
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002714 def stop(self):
2715 self.active = False
2716 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002717
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002718def server_params_test(client_context, server_context, indata=b"FOO\n",
2719 chatty=True, connectionchatty=False, sni_name=None,
2720 session=None):
2721 """
2722 Launch a server, connect a client to it and try various reads
2723 and writes.
2724 """
2725 stats = {}
2726 server = ThreadedEchoServer(context=server_context,
2727 chatty=chatty,
2728 connectionchatty=False)
2729 with server:
2730 with client_context.wrap_socket(socket.socket(),
2731 server_hostname=sni_name, session=session) as s:
2732 s.connect((HOST, server.port))
2733 for arg in [indata, bytearray(indata), memoryview(indata)]:
2734 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002735 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002736 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002737 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002738 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002739 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002740 if connectionchatty:
2741 if support.verbose:
2742 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002743 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002744 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002745 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2746 % (outdata[:20], len(outdata),
2747 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002748 s.write(b"over\n")
2749 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002750 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002751 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002752 stats.update({
2753 'compression': s.compression(),
2754 'cipher': s.cipher(),
2755 'peercert': s.getpeercert(),
2756 'client_alpn_protocol': s.selected_alpn_protocol(),
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002757 'version': s.version(),
2758 'session_reused': s.session_reused,
2759 'session': s.session,
2760 })
2761 s.close()
2762 stats['server_alpn_protocols'] = server.selected_alpn_protocols
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002763 stats['server_shared_ciphers'] = server.shared_ciphers
2764 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002765
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002766def try_protocol_combo(server_protocol, client_protocol, expect_success,
2767 certsreqs=None, server_options=0, client_options=0):
2768 """
2769 Try to SSL-connect using *client_protocol* to *server_protocol*.
2770 If *expect_success* is true, assert that the connection succeeds,
2771 if it's false, assert that the connection fails.
2772 Also, if *expect_success* is a string, assert that it is the protocol
2773 version actually used by the connection.
2774 """
2775 if certsreqs is None:
2776 certsreqs = ssl.CERT_NONE
2777 certtype = {
2778 ssl.CERT_NONE: "CERT_NONE",
2779 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2780 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2781 }[certsreqs]
2782 if support.verbose:
2783 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2784 sys.stdout.write(formatstr %
2785 (ssl.get_protocol_name(client_protocol),
2786 ssl.get_protocol_name(server_protocol),
2787 certtype))
Christian Heimes2875c602021-04-19 07:27:10 +02002788
2789 with warnings_helper.check_warnings():
2790 # ignore Deprecation warnings
2791 client_context = ssl.SSLContext(client_protocol)
2792 client_context.options |= client_options
2793 server_context = ssl.SSLContext(server_protocol)
2794 server_context.options |= server_options
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002795
Victor Stinner3ef63442019-02-19 18:06:03 +01002796 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2797 if (min_version is not None
Christian Heimes2875c602021-04-19 07:27:10 +02002798 # SSLContext.minimum_version is only available on recent OpenSSL
2799 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2800 and hasattr(server_context, 'minimum_version')
2801 and server_protocol == ssl.PROTOCOL_TLS
2802 and server_context.minimum_version > min_version
2803 ):
Victor Stinner3ef63442019-02-19 18:06:03 +01002804 # If OpenSSL configuration is strict and requires more recent TLS
2805 # version, we have to change the minimum to test old TLS versions.
Christian Heimes2875c602021-04-19 07:27:10 +02002806 with warnings_helper.check_warnings():
2807 server_context.minimum_version = min_version
Victor Stinner3ef63442019-02-19 18:06:03 +01002808
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002809 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2810 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2811 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002812 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002813 client_context.set_ciphers("ALL")
2814
Christian Heimesf6c6b582021-03-18 23:06:50 +01002815 seclevel_workaround(server_context, client_context)
2816
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002817 for ctx in (client_context, server_context):
2818 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002819 ctx.load_cert_chain(SIGNED_CERTFILE)
2820 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002821 try:
2822 stats = server_params_test(client_context, server_context,
2823 chatty=False, connectionchatty=False)
2824 # Protocol mismatch can result in either an SSLError, or a
2825 # "Connection reset by peer" error.
2826 except ssl.SSLError:
2827 if expect_success:
2828 raise
2829 except OSError as e:
2830 if expect_success or e.errno != errno.ECONNRESET:
2831 raise
2832 else:
2833 if not expect_success:
2834 raise AssertionError(
2835 "Client protocol %s succeeded with server protocol %s!"
2836 % (ssl.get_protocol_name(client_protocol),
2837 ssl.get_protocol_name(server_protocol)))
2838 elif (expect_success is not True
2839 and expect_success != stats['version']):
2840 raise AssertionError("version mismatch: expected %r, got %r"
2841 % (expect_success, stats['version']))
2842
2843
2844class ThreadedTests(unittest.TestCase):
2845
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002846 def test_echo(self):
2847 """Basic test of an SSL client connecting to a server"""
2848 if support.verbose:
2849 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002850
Christian Heimesa170fa12017-09-15 20:27:30 +02002851 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002852
2853 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2854 server_params_test(client_context=client_context,
2855 server_context=server_context,
2856 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002857 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002858
2859 client_context.check_hostname = False
2860 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2861 with self.assertRaises(ssl.SSLError) as e:
2862 server_params_test(client_context=server_context,
2863 server_context=client_context,
2864 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002865 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002866 self.assertIn('called a function you should not call',
2867 str(e.exception))
2868
2869 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2870 with self.assertRaises(ssl.SSLError) as e:
2871 server_params_test(client_context=server_context,
2872 server_context=server_context,
2873 chatty=True, connectionchatty=True)
2874 self.assertIn('called a function you should not call',
2875 str(e.exception))
2876
2877 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2878 with self.assertRaises(ssl.SSLError) as e:
2879 server_params_test(client_context=server_context,
2880 server_context=client_context,
2881 chatty=True, connectionchatty=True)
2882 self.assertIn('called a function you should not call',
2883 str(e.exception))
2884
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002885 def test_getpeercert(self):
2886 if support.verbose:
2887 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002888
2889 client_context, server_context, hostname = testing_context()
2890 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002891 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002892 with client_context.wrap_socket(socket.socket(),
2893 do_handshake_on_connect=False,
2894 server_hostname=hostname) as s:
2895 s.connect((HOST, server.port))
2896 # getpeercert() raise ValueError while the handshake isn't
2897 # done.
2898 with self.assertRaises(ValueError):
2899 s.getpeercert()
2900 s.do_handshake()
2901 cert = s.getpeercert()
2902 self.assertTrue(cert, "Can't get peer certificate.")
2903 cipher = s.cipher()
2904 if support.verbose:
2905 sys.stdout.write(pprint.pformat(cert) + '\n')
2906 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2907 if 'subject' not in cert:
2908 self.fail("No subject field in certificate: %s." %
2909 pprint.pformat(cert))
2910 if ((('organizationName', 'Python Software Foundation'),)
2911 not in cert['subject']):
2912 self.fail(
2913 "Missing or invalid 'organizationName' field in certificate subject; "
2914 "should be 'Python Software Foundation'.")
2915 self.assertIn('notBefore', cert)
2916 self.assertIn('notAfter', cert)
2917 before = ssl.cert_time_to_seconds(cert['notBefore'])
2918 after = ssl.cert_time_to_seconds(cert['notAfter'])
2919 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002920
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002921 def test_crl_check(self):
2922 if support.verbose:
2923 sys.stdout.write("\n")
2924
Christian Heimesa170fa12017-09-15 20:27:30 +02002925 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002926
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002927 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002928 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002929
2930 # VERIFY_DEFAULT should pass
2931 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 Pitrou65a3f4b2011-12-21 16:52:40 +01002935 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002936 cert = s.getpeercert()
2937 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002938
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002939 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002940 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
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 Pitroua6a4dc82017-09-07 18:56:24 +02002946 with self.assertRaisesRegex(ssl.SSLError,
2947 "certificate verify failed"):
2948 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002949
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002950 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002951 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002952
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002953 server = ThreadedEchoServer(context=server_context, chatty=True)
2954 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002955 with client_context.wrap_socket(socket.socket(),
2956 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002957 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002958 cert = s.getpeercert()
2959 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002960
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002961 def test_check_hostname(self):
2962 if support.verbose:
2963 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002964
Christian Heimesa170fa12017-09-15 20:27:30 +02002965 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002966
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002967 # correct hostname should verify
2968 server = ThreadedEchoServer(context=server_context, chatty=True)
2969 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002970 with client_context.wrap_socket(socket.socket(),
2971 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002972 s.connect((HOST, server.port))
2973 cert = s.getpeercert()
2974 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002975
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002976 # incorrect hostname should raise an exception
2977 server = ThreadedEchoServer(context=server_context, chatty=True)
2978 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002979 with client_context.wrap_socket(socket.socket(),
2980 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01002981 with self.assertRaisesRegex(
2982 ssl.CertificateError,
2983 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002984 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002985
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002986 # missing server_hostname arg should cause an exception, too
2987 server = ThreadedEchoServer(context=server_context, chatty=True)
2988 with server:
2989 with socket.socket() as s:
2990 with self.assertRaisesRegex(ValueError,
2991 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02002992 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002993
Christian Heimesb467d9a2021-04-17 10:07:19 +02002994 @unittest.skipUnless(
2995 ssl.HAS_NEVER_CHECK_COMMON_NAME, "test requires hostname_checks_common_name"
2996 )
2997 def test_hostname_checks_common_name(self):
2998 client_context, server_context, hostname = testing_context()
2999 assert client_context.hostname_checks_common_name
3000 client_context.hostname_checks_common_name = False
3001
3002 # default cert has a SAN
3003 server = ThreadedEchoServer(context=server_context, chatty=True)
3004 with server:
3005 with client_context.wrap_socket(socket.socket(),
3006 server_hostname=hostname) as s:
3007 s.connect((HOST, server.port))
3008
3009 client_context, server_context, hostname = testing_context(NOSANFILE)
3010 client_context.hostname_checks_common_name = False
3011 server = ThreadedEchoServer(context=server_context, chatty=True)
3012 with server:
3013 with client_context.wrap_socket(socket.socket(),
3014 server_hostname=hostname) as s:
3015 with self.assertRaises(ssl.SSLCertVerificationError):
3016 s.connect((HOST, server.port))
3017
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003018 def test_ecc_cert(self):
3019 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3020 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003021 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003022 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3023
3024 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3025 # load ECC cert
3026 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3027
3028 # correct hostname should verify
3029 server = ThreadedEchoServer(context=server_context, chatty=True)
3030 with server:
3031 with client_context.wrap_socket(socket.socket(),
3032 server_hostname=hostname) as s:
3033 s.connect((HOST, server.port))
3034 cert = s.getpeercert()
3035 self.assertTrue(cert, "Can't get peer certificate.")
3036 cipher = s.cipher()[0].split('-')
3037 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3038
3039 def test_dual_rsa_ecc(self):
3040 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3041 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003042 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3043 # algorithms.
3044 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003045 # only ECDSA certs
3046 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3047 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3048
3049 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3050 # load ECC and RSA key/cert pairs
3051 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3052 server_context.load_cert_chain(SIGNED_CERTFILE)
3053
3054 # correct hostname should verify
3055 server = ThreadedEchoServer(context=server_context, chatty=True)
3056 with server:
3057 with client_context.wrap_socket(socket.socket(),
3058 server_hostname=hostname) as s:
3059 s.connect((HOST, server.port))
3060 cert = s.getpeercert()
3061 self.assertTrue(cert, "Can't get peer certificate.")
3062 cipher = s.cipher()[0].split('-')
3063 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3064
Christian Heimes66e57422018-01-29 14:25:13 +01003065 def test_check_hostname_idn(self):
3066 if support.verbose:
3067 sys.stdout.write("\n")
3068
Christian Heimes11a14932018-02-24 02:35:08 +01003069 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003070 server_context.load_cert_chain(IDNSANSFILE)
3071
Christian Heimes11a14932018-02-24 02:35:08 +01003072 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003073 context.verify_mode = ssl.CERT_REQUIRED
3074 context.check_hostname = True
3075 context.load_verify_locations(SIGNING_CA)
3076
3077 # correct hostname should verify, when specified in several
3078 # different ways
3079 idn_hostnames = [
3080 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003081 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003082 ('xn--knig-5qa.idn.pythontest.net',
3083 'xn--knig-5qa.idn.pythontest.net'),
3084 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003085 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003086
3087 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003088 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003089 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3090 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3091 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003092 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3093
3094 # ('königsgäßchen.idna2008.pythontest.net',
3095 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3096 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3097 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3098 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3099 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3100
Christian Heimes66e57422018-01-29 14:25:13 +01003101 ]
3102 for server_hostname, expected_hostname in idn_hostnames:
3103 server = ThreadedEchoServer(context=server_context, chatty=True)
3104 with server:
3105 with context.wrap_socket(socket.socket(),
3106 server_hostname=server_hostname) as s:
3107 self.assertEqual(s.server_hostname, expected_hostname)
3108 s.connect((HOST, server.port))
3109 cert = s.getpeercert()
3110 self.assertEqual(s.server_hostname, expected_hostname)
3111 self.assertTrue(cert, "Can't get peer certificate.")
3112
Christian Heimes66e57422018-01-29 14:25:13 +01003113 # incorrect hostname should raise an exception
3114 server = ThreadedEchoServer(context=server_context, chatty=True)
3115 with server:
3116 with context.wrap_socket(socket.socket(),
3117 server_hostname="python.example.org") as s:
3118 with self.assertRaises(ssl.CertificateError):
3119 s.connect((HOST, server.port))
3120
Christian Heimes529525f2018-05-23 22:24:45 +02003121 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003122 """Connecting when the server rejects the client's certificate
3123
3124 Launch a server with CERT_REQUIRED, and check that trying to
3125 connect to it with a wrong client certificate fails.
3126 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003127 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003128 # load client cert that is not signed by trusted CA
3129 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003130 # require TLS client authentication
3131 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003132 # TLS 1.3 has different handshake
3133 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003134
3135 server = ThreadedEchoServer(
3136 context=server_context, chatty=True, connectionchatty=True,
3137 )
3138
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003139 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003140 client_context.wrap_socket(socket.socket(),
3141 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003142 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003143 # Expect either an SSL error about the server rejecting
3144 # the connection, or a low-level connection reset (which
3145 # sometimes happens on Windows)
3146 s.connect((HOST, server.port))
3147 except ssl.SSLError as e:
3148 if support.verbose:
3149 sys.stdout.write("\nSSLError is %r\n" % e)
3150 except OSError as e:
3151 if e.errno != errno.ECONNRESET:
3152 raise
3153 if support.verbose:
3154 sys.stdout.write("\nsocket.error is %r\n" % e)
3155 else:
3156 self.fail("Use of invalid cert should have failed!")
3157
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003158 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003159 def test_wrong_cert_tls13(self):
3160 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003161 # load client cert that is not signed by trusted CA
3162 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003163 server_context.verify_mode = ssl.CERT_REQUIRED
3164 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3165 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3166
3167 server = ThreadedEchoServer(
3168 context=server_context, chatty=True, connectionchatty=True,
3169 )
3170 with server, \
3171 client_context.wrap_socket(socket.socket(),
3172 server_hostname=hostname) as s:
3173 # TLS 1.3 perform client cert exchange after handshake
3174 s.connect((HOST, server.port))
3175 try:
3176 s.write(b'data')
Christian Heimese0472392021-04-23 20:03:25 +02003177 s.read(1000)
3178 s.write(b'should have failed already')
3179 s.read(1000)
Christian Heimes529525f2018-05-23 22:24:45 +02003180 except ssl.SSLError as e:
3181 if support.verbose:
3182 sys.stdout.write("\nSSLError is %r\n" % e)
3183 except OSError as e:
3184 if e.errno != errno.ECONNRESET:
3185 raise
3186 if support.verbose:
3187 sys.stdout.write("\nsocket.error is %r\n" % e)
3188 else:
Christian Heimese0472392021-04-23 20:03:25 +02003189 if sys.platform == "win32":
3190 self.skipTest(
3191 "Ignoring failed test_wrong_cert_tls13 test case. "
3192 "The test is flaky on Windows, see bpo-43921."
3193 )
3194 else:
3195 self.fail("Use of invalid cert should have failed!")
Christian Heimes529525f2018-05-23 22:24:45 +02003196
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003197 def test_rude_shutdown(self):
3198 """A brutal shutdown of an SSL server should raise an OSError
3199 in the client when attempting handshake.
3200 """
3201 listener_ready = threading.Event()
3202 listener_gone = threading.Event()
3203
3204 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003205 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003206
3207 # `listener` runs in a thread. It sits in an accept() until
3208 # the main thread connects. Then it rudely closes the socket,
3209 # and sets Event `listener_gone` to let the main thread know
3210 # the socket is gone.
3211 def listener():
3212 s.listen()
3213 listener_ready.set()
3214 newsock, addr = s.accept()
3215 newsock.close()
3216 s.close()
3217 listener_gone.set()
3218
3219 def connector():
3220 listener_ready.wait()
3221 with socket.socket() as c:
3222 c.connect((HOST, port))
3223 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003224 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003225 ssl_sock = test_wrap_socket(c)
3226 except OSError:
3227 pass
3228 else:
3229 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003230
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003231 t = threading.Thread(target=listener)
3232 t.start()
3233 try:
3234 connector()
3235 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003236 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003237
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003238 def test_ssl_cert_verify_error(self):
3239 if support.verbose:
3240 sys.stdout.write("\n")
3241
3242 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3243 server_context.load_cert_chain(SIGNED_CERTFILE)
3244
3245 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3246
3247 server = ThreadedEchoServer(context=server_context, chatty=True)
3248 with server:
3249 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003250 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003251 try:
3252 s.connect((HOST, server.port))
3253 except ssl.SSLError as e:
3254 msg = 'unable to get local issuer certificate'
3255 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3256 self.assertEqual(e.verify_code, 20)
3257 self.assertEqual(e.verify_message, msg)
3258 self.assertIn(msg, repr(e))
3259 self.assertIn('certificate verify failed', repr(e))
3260
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003261 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003262 def test_protocol_sslv2(self):
3263 """Connecting to an SSLv2 server with various client options"""
3264 if support.verbose:
3265 sys.stdout.write("\n")
3266 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3267 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3268 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003269 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003270 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003271 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3272 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3273 # SSLv23 client with specific SSL options
Christian Heimesa170fa12017-09-15 20:27:30 +02003274 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003275 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003276 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003277 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003278
Christian Heimesa170fa12017-09-15 20:27:30 +02003279 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003280 """Connecting to an SSLv23 server with various client options"""
3281 if support.verbose:
3282 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003283 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003284 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003285 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003286 except OSError as x:
3287 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3288 if support.verbose:
3289 sys.stdout.write(
3290 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3291 % str(x))
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)
3294 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003295 if has_tls_version('TLSv1'):
3296 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003297
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003298 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003299 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3300 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003301 if has_tls_version('TLSv1'):
3302 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003303
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003304 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003305 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3306 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003307 if has_tls_version('TLSv1'):
3308 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003309
3310 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003311 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003312 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003313 server_options=ssl.OP_NO_SSLv3)
3314 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003315 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003316 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003317 if has_tls_version('TLSv1'):
3318 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3319 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003320
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003321 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003322 def test_protocol_sslv3(self):
3323 """Connecting to an SSLv3 server with various client options"""
3324 if support.verbose:
3325 sys.stdout.write("\n")
3326 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3327 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3328 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003329 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003330 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003331 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003332 client_options=ssl.OP_NO_SSLv3)
3333 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003334
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003335 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003336 def test_protocol_tlsv1(self):
3337 """Connecting to a TLSv1 server with various client options"""
3338 if support.verbose:
3339 sys.stdout.write("\n")
3340 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3341 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3342 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003343 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003344 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003345 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003346 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003347 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003348 client_options=ssl.OP_NO_TLSv1)
3349
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003350 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003351 def test_protocol_tlsv1_1(self):
3352 """Connecting to a TLSv1.1 server with various client options.
3353 Testing against older TLS versions."""
3354 if support.verbose:
3355 sys.stdout.write("\n")
3356 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003357 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003358 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003359 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003360 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003361 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003362 client_options=ssl.OP_NO_TLSv1_1)
3363
Christian Heimesa170fa12017-09-15 20:27:30 +02003364 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003365 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3366 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003367
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003368 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003369 def test_protocol_tlsv1_2(self):
3370 """Connecting to a TLSv1.2 server with various client options.
3371 Testing against older TLS versions."""
3372 if support.verbose:
3373 sys.stdout.write("\n")
3374 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3375 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3376 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003377 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003378 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003379 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003380 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003381 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003382 client_options=ssl.OP_NO_TLSv1_2)
3383
Christian Heimesa170fa12017-09-15 20:27:30 +02003384 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003385 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3386 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3387 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3388 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3389
3390 def test_starttls(self):
3391 """Switching from clear text to encrypted and back again."""
3392 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3393
3394 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003395 starttls_server=True,
3396 chatty=True,
3397 connectionchatty=True)
3398 wrapped = False
3399 with server:
3400 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003401 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003402 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003403 if support.verbose:
3404 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003405 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003406 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003407 sys.stdout.write(
3408 " client: sending %r...\n" % indata)
3409 if wrapped:
3410 conn.write(indata)
3411 outdata = conn.read()
3412 else:
3413 s.send(indata)
3414 outdata = s.recv(1024)
3415 msg = outdata.strip().lower()
3416 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3417 # STARTTLS ok, switch to secure mode
3418 if support.verbose:
3419 sys.stdout.write(
3420 " client: read %r from server, starting TLS...\n"
3421 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003422 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003423 wrapped = True
3424 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3425 # ENDTLS ok, switch back to clear text
3426 if support.verbose:
3427 sys.stdout.write(
3428 " client: read %r from server, ending TLS...\n"
3429 % msg)
3430 s = conn.unwrap()
3431 wrapped = False
3432 else:
3433 if support.verbose:
3434 sys.stdout.write(
3435 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003436 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003437 sys.stdout.write(" client: closing connection.\n")
3438 if wrapped:
3439 conn.write(b"over\n")
3440 else:
3441 s.send(b"over\n")
3442 if wrapped:
3443 conn.close()
3444 else:
3445 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003446
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003447 def test_socketserver(self):
3448 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003449 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003450 # try to connect
3451 if support.verbose:
3452 sys.stdout.write('\n')
3453 with open(CERTFILE, 'rb') as f:
3454 d1 = f.read()
3455 d2 = ''
3456 # now fetch the same data from the HTTPS server
3457 url = 'https://localhost:%d/%s' % (
3458 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003459 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003460 f = urllib.request.urlopen(url, context=context)
3461 try:
3462 dlen = f.info().get("content-length")
3463 if dlen and (int(dlen) > 0):
3464 d2 = f.read(int(dlen))
3465 if support.verbose:
3466 sys.stdout.write(
3467 " client: read %d bytes from remote server '%s'\n"
3468 % (len(d2), server))
3469 finally:
3470 f.close()
3471 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003472
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003473 def test_asyncore_server(self):
3474 """Check the example asyncore integration."""
3475 if support.verbose:
3476 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003477
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003478 indata = b"FOO\n"
3479 server = AsyncoreEchoServer(CERTFILE)
3480 with server:
3481 s = test_wrap_socket(socket.socket())
3482 s.connect(('127.0.0.1', server.port))
3483 if support.verbose:
3484 sys.stdout.write(
3485 " client: sending %r...\n" % indata)
3486 s.write(indata)
3487 outdata = s.read()
3488 if support.verbose:
3489 sys.stdout.write(" client: read %r\n" % outdata)
3490 if outdata != indata.lower():
3491 self.fail(
3492 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3493 % (outdata[:20], len(outdata),
3494 indata[:20].lower(), len(indata)))
3495 s.write(b"over\n")
3496 if support.verbose:
3497 sys.stdout.write(" client: closing connection.\n")
3498 s.close()
3499 if support.verbose:
3500 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003501
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003502 def test_recv_send(self):
3503 """Test recv(), send() and friends."""
3504 if support.verbose:
3505 sys.stdout.write("\n")
3506
3507 server = ThreadedEchoServer(CERTFILE,
3508 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003509 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003510 cacerts=CERTFILE,
3511 chatty=True,
3512 connectionchatty=False)
3513 with server:
3514 s = test_wrap_socket(socket.socket(),
3515 server_side=False,
3516 certfile=CERTFILE,
3517 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003518 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003519 s.connect((HOST, server.port))
3520 # helper methods for standardising recv* method signatures
3521 def _recv_into():
3522 b = bytearray(b"\0"*100)
3523 count = s.recv_into(b)
3524 return b[:count]
3525
3526 def _recvfrom_into():
3527 b = bytearray(b"\0"*100)
3528 count, addr = s.recvfrom_into(b)
3529 return b[:count]
3530
3531 # (name, method, expect success?, *args, return value func)
3532 send_methods = [
3533 ('send', s.send, True, [], len),
3534 ('sendto', s.sendto, False, ["some.address"], len),
3535 ('sendall', s.sendall, True, [], lambda x: None),
3536 ]
3537 # (name, method, whether to expect success, *args)
3538 recv_methods = [
3539 ('recv', s.recv, True, []),
3540 ('recvfrom', s.recvfrom, False, ["some.address"]),
3541 ('recv_into', _recv_into, True, []),
3542 ('recvfrom_into', _recvfrom_into, False, []),
3543 ]
3544 data_prefix = "PREFIX_"
3545
3546 for (meth_name, send_meth, expect_success, args,
3547 ret_val_meth) in send_methods:
3548 indata = (data_prefix + meth_name).encode('ascii')
3549 try:
3550 ret = send_meth(indata, *args)
3551 msg = "sending with {}".format(meth_name)
3552 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3553 outdata = s.read()
3554 if outdata != indata.lower():
3555 self.fail(
3556 "While sending with <<{name:s}>> bad data "
3557 "<<{outdata:r}>> ({nout:d}) received; "
3558 "expected <<{indata:r}>> ({nin:d})\n".format(
3559 name=meth_name, outdata=outdata[:20],
3560 nout=len(outdata),
3561 indata=indata[:20], nin=len(indata)
3562 )
3563 )
3564 except ValueError as e:
3565 if expect_success:
3566 self.fail(
3567 "Failed to send with method <<{name:s}>>; "
3568 "expected to succeed.\n".format(name=meth_name)
3569 )
3570 if not str(e).startswith(meth_name):
3571 self.fail(
3572 "Method <<{name:s}>> failed with unexpected "
3573 "exception message: {exp:s}\n".format(
3574 name=meth_name, exp=e
3575 )
3576 )
3577
3578 for meth_name, recv_meth, expect_success, args in recv_methods:
3579 indata = (data_prefix + meth_name).encode('ascii')
3580 try:
3581 s.send(indata)
3582 outdata = recv_meth(*args)
3583 if outdata != indata.lower():
3584 self.fail(
3585 "While receiving with <<{name:s}>> bad data "
3586 "<<{outdata:r}>> ({nout:d}) received; "
3587 "expected <<{indata:r}>> ({nin:d})\n".format(
3588 name=meth_name, outdata=outdata[:20],
3589 nout=len(outdata),
3590 indata=indata[:20], nin=len(indata)
3591 )
3592 )
3593 except ValueError as e:
3594 if expect_success:
3595 self.fail(
3596 "Failed to receive with method <<{name:s}>>; "
3597 "expected to succeed.\n".format(name=meth_name)
3598 )
3599 if not str(e).startswith(meth_name):
3600 self.fail(
3601 "Method <<{name:s}>> failed with unexpected "
3602 "exception message: {exp:s}\n".format(
3603 name=meth_name, exp=e
3604 )
3605 )
3606 # consume data
3607 s.read()
3608
3609 # read(-1, buffer) is supported, even though read(-1) is not
3610 data = b"data"
3611 s.send(data)
3612 buffer = bytearray(len(data))
3613 self.assertEqual(s.read(-1, buffer), len(data))
3614 self.assertEqual(buffer, data)
3615
Christian Heimes888bbdc2017-09-07 14:18:21 -07003616 # sendall accepts bytes-like objects
3617 if ctypes is not None:
3618 ubyte = ctypes.c_ubyte * len(data)
3619 byteslike = ubyte.from_buffer_copy(data)
3620 s.sendall(byteslike)
3621 self.assertEqual(s.read(), data)
3622
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003623 # Make sure sendmsg et al are disallowed to avoid
3624 # inadvertent disclosure of data and/or corruption
3625 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003626 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003627 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3628 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3629 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003630 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003631 s.write(b"over\n")
3632
3633 self.assertRaises(ValueError, s.recv, -1)
3634 self.assertRaises(ValueError, s.read, -1)
3635
3636 s.close()
3637
3638 def test_recv_zero(self):
3639 server = ThreadedEchoServer(CERTFILE)
3640 server.__enter__()
3641 self.addCleanup(server.__exit__, None, None)
3642 s = socket.create_connection((HOST, server.port))
3643 self.addCleanup(s.close)
3644 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3645 self.addCleanup(s.close)
3646
3647 # recv/read(0) should return no data
3648 s.send(b"data")
3649 self.assertEqual(s.recv(0), b"")
3650 self.assertEqual(s.read(0), b"")
3651 self.assertEqual(s.read(), b"data")
3652
3653 # Should not block if the other end sends no data
3654 s.setblocking(False)
3655 self.assertEqual(s.recv(0), b"")
3656 self.assertEqual(s.recv_into(bytearray()), 0)
3657
3658 def test_nonblocking_send(self):
3659 server = ThreadedEchoServer(CERTFILE,
3660 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003661 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003662 cacerts=CERTFILE,
3663 chatty=True,
3664 connectionchatty=False)
3665 with server:
3666 s = test_wrap_socket(socket.socket(),
3667 server_side=False,
3668 certfile=CERTFILE,
3669 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003670 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003671 s.connect((HOST, server.port))
3672 s.setblocking(False)
3673
3674 # If we keep sending data, at some point the buffers
3675 # will be full and the call will block
3676 buf = bytearray(8192)
3677 def fill_buffer():
3678 while True:
3679 s.send(buf)
3680 self.assertRaises((ssl.SSLWantWriteError,
3681 ssl.SSLWantReadError), fill_buffer)
3682
3683 # Now read all the output and discard it
3684 s.setblocking(True)
3685 s.close()
3686
3687 def test_handshake_timeout(self):
3688 # Issue #5103: SSL handshake must respect the socket timeout
3689 server = socket.socket(socket.AF_INET)
3690 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003691 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003692 started = threading.Event()
3693 finish = False
3694
3695 def serve():
3696 server.listen()
3697 started.set()
3698 conns = []
3699 while not finish:
3700 r, w, e = select.select([server], [], [], 0.1)
3701 if server in r:
3702 # Let the socket hang around rather than having
3703 # it closed by garbage collection.
3704 conns.append(server.accept()[0])
3705 for sock in conns:
3706 sock.close()
3707
3708 t = threading.Thread(target=serve)
3709 t.start()
3710 started.wait()
3711
3712 try:
3713 try:
3714 c = socket.socket(socket.AF_INET)
3715 c.settimeout(0.2)
3716 c.connect((host, port))
3717 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003718 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003719 test_wrap_socket, c)
3720 finally:
3721 c.close()
3722 try:
3723 c = socket.socket(socket.AF_INET)
3724 c = test_wrap_socket(c)
3725 c.settimeout(0.2)
3726 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003727 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003728 c.connect, (host, port))
3729 finally:
3730 c.close()
3731 finally:
3732 finish = True
3733 t.join()
3734 server.close()
3735
3736 def test_server_accept(self):
3737 # Issue #16357: accept() on a SSLSocket created through
3738 # SSLContext.wrap_socket().
Christian Heimes2875c602021-04-19 07:27:10 +02003739 client_ctx, server_ctx, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003740 server = socket.socket(socket.AF_INET)
3741 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003742 port = socket_helper.bind_port(server)
Christian Heimes2875c602021-04-19 07:27:10 +02003743 server = server_ctx.wrap_socket(server, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003744 self.assertTrue(server.server_side)
3745
3746 evt = threading.Event()
3747 remote = None
3748 peer = None
3749 def serve():
3750 nonlocal remote, peer
3751 server.listen()
3752 # Block on the accept and wait on the connection to close.
3753 evt.set()
3754 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003755 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003756
3757 t = threading.Thread(target=serve)
3758 t.start()
3759 # Client wait until server setup and perform a connect.
3760 evt.wait()
Christian Heimes2875c602021-04-19 07:27:10 +02003761 client = client_ctx.wrap_socket(
3762 socket.socket(), server_hostname=hostname
3763 )
3764 client.connect((hostname, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003765 client.send(b'data')
3766 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003767 client_addr = client.getsockname()
3768 client.close()
3769 t.join()
3770 remote.close()
3771 server.close()
3772 # Sanity checks.
3773 self.assertIsInstance(remote, ssl.SSLSocket)
3774 self.assertEqual(peer, client_addr)
3775
3776 def test_getpeercert_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003777 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3778 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003779 with context.wrap_socket(socket.socket()) as sock:
3780 with self.assertRaises(OSError) as cm:
3781 sock.getpeercert()
3782 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3783
3784 def test_do_handshake_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003785 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3786 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003787 with context.wrap_socket(socket.socket()) as sock:
3788 with self.assertRaises(OSError) as cm:
3789 sock.do_handshake()
3790 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3791
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003792 def test_no_shared_ciphers(self):
3793 client_context, server_context, hostname = testing_context()
3794 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3795 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003796 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003797 client_context.set_ciphers("AES128")
3798 server_context.set_ciphers("AES256")
3799 with ThreadedEchoServer(context=server_context) as server:
3800 with client_context.wrap_socket(socket.socket(),
3801 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003802 with self.assertRaises(OSError):
3803 s.connect((HOST, server.port))
3804 self.assertIn("no shared cipher", server.conn_errors[0])
3805
3806 def test_version_basic(self):
3807 """
3808 Basic tests for SSLSocket.version().
3809 More tests are done in the test_protocol_*() methods.
3810 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003811 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3812 context.check_hostname = False
3813 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003814 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003815 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003816 chatty=False) as server:
3817 with context.wrap_socket(socket.socket()) as s:
3818 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003819 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003820 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003821 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003822 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003823 self.assertIs(s.version(), None)
3824
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003825 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003826 def test_tls1_3(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003827 client_context, server_context, hostname = testing_context()
3828 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3829 with ThreadedEchoServer(context=server_context) as server:
3830 with client_context.wrap_socket(socket.socket(),
3831 server_hostname=hostname) as s:
Christian Heimescb5b68a2017-09-07 18:07:00 -07003832 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003833 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003834 'TLS_AES_256_GCM_SHA384',
3835 'TLS_CHACHA20_POLY1305_SHA256',
3836 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003837 })
3838 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003839
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003840 @requires_tls_version('TLSv1_2')
Christian Heimes2875c602021-04-19 07:27:10 +02003841 @requires_tls_version('TLSv1')
3842 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003843 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003844 client_context, server_context, hostname = testing_context()
3845 # client TLSv1.0 to 1.2
3846 client_context.minimum_version = ssl.TLSVersion.TLSv1
3847 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3848 # server only TLSv1.2
3849 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3850 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3851
3852 with ThreadedEchoServer(context=server_context) as server:
3853 with client_context.wrap_socket(socket.socket(),
3854 server_hostname=hostname) as s:
3855 s.connect((HOST, server.port))
3856 self.assertEqual(s.version(), 'TLSv1.2')
3857
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003858 @requires_tls_version('TLSv1_1')
Christian Heimes2875c602021-04-19 07:27:10 +02003859 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003860 def test_min_max_version_tlsv1_1(self):
3861 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003862 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003863 client_context.minimum_version = ssl.TLSVersion.TLSv1
3864 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003865 server_context.minimum_version = ssl.TLSVersion.TLSv1
3866 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003867 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003868
3869 with ThreadedEchoServer(context=server_context) as server:
3870 with client_context.wrap_socket(socket.socket(),
3871 server_hostname=hostname) as s:
3872 s.connect((HOST, server.port))
3873 self.assertEqual(s.version(), 'TLSv1.1')
3874
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003875 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003876 @requires_tls_version('TLSv1')
Christian Heimes2875c602021-04-19 07:27:10 +02003877 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003878 def test_min_max_version_mismatch(self):
3879 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003880 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003881 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003882 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003883 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003884 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003885 seclevel_workaround(client_context, server_context)
3886
Christian Heimes698dde12018-02-27 11:54:43 +01003887 with ThreadedEchoServer(context=server_context) as server:
3888 with client_context.wrap_socket(socket.socket(),
3889 server_hostname=hostname) as s:
3890 with self.assertRaises(ssl.SSLError) as e:
3891 s.connect((HOST, server.port))
3892 self.assertIn("alert", str(e.exception))
3893
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003894 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003895 def test_min_max_version_sslv3(self):
3896 client_context, server_context, hostname = testing_context()
3897 server_context.minimum_version = ssl.TLSVersion.SSLv3
3898 client_context.minimum_version = ssl.TLSVersion.SSLv3
3899 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003900 seclevel_workaround(client_context, server_context)
3901
Christian Heimes698dde12018-02-27 11:54:43 +01003902 with ThreadedEchoServer(context=server_context) as server:
3903 with client_context.wrap_socket(socket.socket(),
3904 server_hostname=hostname) as s:
3905 s.connect((HOST, server.port))
3906 self.assertEqual(s.version(), 'SSLv3')
3907
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003908 def test_default_ecdh_curve(self):
3909 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3910 # should be enabled by default on SSL contexts.
Christian Heimes2875c602021-04-19 07:27:10 +02003911 client_context, server_context, hostname = testing_context()
Christian Heimescb5b68a2017-09-07 18:07:00 -07003912 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3913 # cipher name.
Christian Heimes2875c602021-04-19 07:27:10 +02003914 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003915 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3916 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3917 # our default cipher list should prefer ECDH-based ciphers
3918 # automatically.
Christian Heimes2875c602021-04-19 07:27:10 +02003919 with ThreadedEchoServer(context=server_context) as server:
3920 with client_context.wrap_socket(socket.socket(),
3921 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003922 s.connect((HOST, server.port))
3923 self.assertIn("ECDH", s.cipher()[0])
3924
3925 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3926 "'tls-unique' channel binding not available")
3927 def test_tls_unique_channel_binding(self):
3928 """Test tls-unique channel binding."""
3929 if support.verbose:
3930 sys.stdout.write("\n")
3931
Christian Heimes05d9fe32018-02-27 08:55:39 +01003932 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003933
3934 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003935 chatty=True,
3936 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003937
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003938 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003939 with client_context.wrap_socket(
3940 socket.socket(),
3941 server_hostname=hostname) as s:
3942 s.connect((HOST, server.port))
3943 # get the data
3944 cb_data = s.get_channel_binding("tls-unique")
3945 if support.verbose:
3946 sys.stdout.write(
3947 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003948
Christian Heimes05d9fe32018-02-27 08:55:39 +01003949 # check if it is sane
3950 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003951 if s.version() == 'TLSv1.3':
3952 self.assertEqual(len(cb_data), 48)
3953 else:
3954 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003955
Christian Heimes05d9fe32018-02-27 08:55:39 +01003956 # and compare with the peers version
3957 s.write(b"CB tls-unique\n")
3958 peer_data_repr = s.read().strip()
3959 self.assertEqual(peer_data_repr,
3960 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003961
3962 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003963 with client_context.wrap_socket(
3964 socket.socket(),
3965 server_hostname=hostname) as s:
3966 s.connect((HOST, server.port))
3967 new_cb_data = s.get_channel_binding("tls-unique")
3968 if support.verbose:
3969 sys.stdout.write(
3970 "got another channel binding data: {0!r}\n".format(
3971 new_cb_data)
3972 )
3973 # is it really unique
3974 self.assertNotEqual(cb_data, new_cb_data)
3975 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003976 if s.version() == 'TLSv1.3':
3977 self.assertEqual(len(cb_data), 48)
3978 else:
3979 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003980 s.write(b"CB tls-unique\n")
3981 peer_data_repr = s.read().strip()
3982 self.assertEqual(peer_data_repr,
3983 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003984
3985 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003986 client_context, server_context, hostname = testing_context()
3987 stats = server_params_test(client_context, server_context,
3988 chatty=True, connectionchatty=True,
3989 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003990 if support.verbose:
3991 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
3992 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
3993
3994 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
3995 "ssl.OP_NO_COMPRESSION needed for this test")
3996 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003997 client_context, server_context, hostname = testing_context()
3998 client_context.options |= ssl.OP_NO_COMPRESSION
3999 server_context.options |= ssl.OP_NO_COMPRESSION
4000 stats = server_params_test(client_context, server_context,
4001 chatty=True, connectionchatty=True,
4002 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004003 self.assertIs(stats['compression'], None)
4004
Paul Monsonf3550692019-06-19 13:09:54 -07004005 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004006 def test_dh_params(self):
4007 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02004008 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004009 # test scenario needs TLS <= 1.2
4010 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004011 server_context.load_dh_params(DHFILE)
4012 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004013 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02004014 stats = server_params_test(client_context, server_context,
4015 chatty=True, connectionchatty=True,
4016 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004017 cipher = stats["cipher"][0]
4018 parts = cipher.split("-")
4019 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4020 self.fail("Non-DH cipher: " + cipher[0])
4021
Christian Heimesb7b92252018-02-25 09:49:31 +01004022 def test_ecdh_curve(self):
4023 # server secp384r1, client auto
4024 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004025
Christian Heimesb7b92252018-02-25 09:49:31 +01004026 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
Christian Heimesb7b92252018-02-25 09:49:31 +01004029 stats = server_params_test(client_context, server_context,
4030 chatty=True, connectionchatty=True,
4031 sni_name=hostname)
4032
4033 # server auto, client secp384r1
4034 client_context, server_context, hostname = testing_context()
4035 client_context.set_ecdh_curve("secp384r1")
4036 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004037 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004038 stats = server_params_test(client_context, server_context,
4039 chatty=True, connectionchatty=True,
4040 sni_name=hostname)
4041
4042 # server / client curve mismatch
4043 client_context, server_context, hostname = testing_context()
4044 client_context.set_ecdh_curve("prime256v1")
4045 server_context.set_ecdh_curve("secp384r1")
4046 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004047 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
4048 with self.assertRaises(ssl.SSLError):
Christian Heimes39258d32021-04-17 11:36:35 +02004049 server_params_test(client_context, server_context,
4050 chatty=True, connectionchatty=True,
4051 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004052
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004053 def test_selected_alpn_protocol(self):
4054 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004055 client_context, server_context, hostname = testing_context()
4056 stats = server_params_test(client_context, server_context,
4057 chatty=True, connectionchatty=True,
4058 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004059 self.assertIs(stats['client_alpn_protocol'], None)
4060
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004061 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4062 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004063 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004064 server_context.set_alpn_protocols(['foo', 'bar'])
4065 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004066 chatty=True, connectionchatty=True,
4067 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004068 self.assertIs(stats['client_alpn_protocol'], None)
4069
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004070 def test_alpn_protocols(self):
4071 server_protocols = ['foo', 'bar', 'milkshake']
4072 protocol_tests = [
4073 (['foo', 'bar'], 'foo'),
4074 (['bar', 'foo'], 'foo'),
4075 (['milkshake'], 'milkshake'),
4076 (['http/3.0', 'http/4.0'], None)
4077 ]
4078 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004079 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004080 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004081 client_context.set_alpn_protocols(client_protocols)
4082
4083 try:
4084 stats = server_params_test(client_context,
4085 server_context,
4086 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004087 connectionchatty=True,
4088 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004089 except ssl.SSLError as e:
4090 stats = e
4091
Christian Heimes39258d32021-04-17 11:36:35 +02004092 msg = "failed trying %s (s) and %s (c).\n" \
4093 "was expecting %s, but got %%s from the %%s" \
4094 % (str(server_protocols), str(client_protocols),
4095 str(expected))
4096 client_result = stats['client_alpn_protocol']
4097 self.assertEqual(client_result, expected,
4098 msg % (client_result, "client"))
4099 server_result = stats['server_alpn_protocols'][-1] \
4100 if len(stats['server_alpn_protocols']) else 'nothing'
4101 self.assertEqual(server_result, expected,
4102 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004103
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004104 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004105 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004106
4107 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004108 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004109 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004110 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004111 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004112 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004113 client_context.load_verify_locations(SIGNING_CA)
4114 return server_context, other_context, client_context
4115
4116 def check_common_name(self, stats, name):
4117 cert = stats['peercert']
4118 self.assertIn((('commonName', name),), cert['subject'])
4119
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004120 def test_sni_callback(self):
4121 calls = []
4122 server_context, other_context, client_context = self.sni_contexts()
4123
Christian Heimesa170fa12017-09-15 20:27:30 +02004124 client_context.check_hostname = False
4125
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004126 def servername_cb(ssl_sock, server_name, initial_context):
4127 calls.append((server_name, initial_context))
4128 if server_name is not None:
4129 ssl_sock.context = other_context
4130 server_context.set_servername_callback(servername_cb)
4131
4132 stats = server_params_test(client_context, server_context,
4133 chatty=True,
4134 sni_name='supermessage')
4135 # The hostname was fetched properly, and the certificate was
4136 # changed for the connection.
4137 self.assertEqual(calls, [("supermessage", server_context)])
4138 # CERTFILE4 was selected
4139 self.check_common_name(stats, 'fakehostname')
4140
4141 calls = []
4142 # The callback is called with server_name=None
4143 stats = server_params_test(client_context, server_context,
4144 chatty=True,
4145 sni_name=None)
4146 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004147 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004148
4149 # Check disabling the callback
4150 calls = []
4151 server_context.set_servername_callback(None)
4152
4153 stats = server_params_test(client_context, server_context,
4154 chatty=True,
4155 sni_name='notfunny')
4156 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004157 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004158 self.assertEqual(calls, [])
4159
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004160 def test_sni_callback_alert(self):
4161 # Returning a TLS alert is reflected to the connecting client
4162 server_context, other_context, client_context = self.sni_contexts()
4163
4164 def cb_returning_alert(ssl_sock, server_name, initial_context):
4165 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4166 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004167 with self.assertRaises(ssl.SSLError) as cm:
4168 stats = server_params_test(client_context, server_context,
4169 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004170 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004171 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004172
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004173 def test_sni_callback_raising(self):
4174 # Raising fails the connection with a TLS handshake failure alert.
4175 server_context, other_context, client_context = self.sni_contexts()
4176
4177 def cb_raising(ssl_sock, server_name, initial_context):
4178 1/0
4179 server_context.set_servername_callback(cb_raising)
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 self.assertEqual(cm.exception.reason,
4188 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4189 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004190
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004191 def test_sni_callback_wrong_return_type(self):
4192 # Returning the wrong return type terminates the TLS connection
4193 # with an internal error alert.
4194 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004195
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004196 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4197 return "foo"
4198 server_context.set_servername_callback(cb_wrong_return_type)
4199
Victor Stinner00253502019-06-03 03:51:43 +02004200 with support.catch_unraisable_exception() as catch:
4201 with self.assertRaises(ssl.SSLError) as cm:
4202 stats = server_params_test(client_context, server_context,
4203 chatty=False,
4204 sni_name='supermessage')
4205
4206
4207 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4208 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004209
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004210 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004211 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004212 client_context.set_ciphers("AES128:AES256")
4213 server_context.set_ciphers("AES256")
4214 expected_algs = [
4215 "AES256", "AES-256",
4216 # TLS 1.3 ciphers are always enabled
4217 "TLS_CHACHA20", "TLS_AES",
4218 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004219
Christian Heimesa170fa12017-09-15 20:27:30 +02004220 stats = server_params_test(client_context, server_context,
4221 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004222 ciphers = stats['server_shared_ciphers'][0]
4223 self.assertGreater(len(ciphers), 0)
4224 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004225 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004226 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004227
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004228 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004229 client_context, server_context, hostname = testing_context()
4230 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004231
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004232 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004233 s = client_context.wrap_socket(socket.socket(),
4234 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004235 s.connect((HOST, server.port))
4236 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004237
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004238 self.assertRaises(ValueError, s.read, 1024)
4239 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004240
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004241 def test_sendfile(self):
4242 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004243 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004244 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004245 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimes2875c602021-04-19 07:27:10 +02004246 client_context, server_context, hostname = testing_context()
4247 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004248 with server:
Christian Heimes2875c602021-04-19 07:27:10 +02004249 with client_context.wrap_socket(socket.socket(),
4250 server_hostname=hostname) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004251 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004252 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004253 s.sendfile(file)
4254 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004255
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004256 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004257 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004258 # TODO: sessions aren't compatible with TLSv1.3 yet
4259 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004260
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004261 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004262 stats = server_params_test(client_context, server_context,
4263 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004264 session = stats['session']
4265 self.assertTrue(session.id)
4266 self.assertGreater(session.time, 0)
4267 self.assertGreater(session.timeout, 0)
4268 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004269 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004270 self.assertFalse(stats['session_reused'])
4271 sess_stat = server_context.session_stats()
4272 self.assertEqual(sess_stat['accept'], 1)
4273 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004274
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004275 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004276 stats = server_params_test(client_context, server_context,
4277 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004278 sess_stat = server_context.session_stats()
4279 self.assertEqual(sess_stat['accept'], 2)
4280 self.assertEqual(sess_stat['hits'], 1)
4281 self.assertTrue(stats['session_reused'])
4282 session2 = stats['session']
4283 self.assertEqual(session2.id, session.id)
4284 self.assertEqual(session2, session)
4285 self.assertIsNot(session2, session)
4286 self.assertGreaterEqual(session2.time, session.time)
4287 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004288
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004289 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004290 stats = server_params_test(client_context, server_context,
4291 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004292 self.assertFalse(stats['session_reused'])
4293 session3 = stats['session']
4294 self.assertNotEqual(session3.id, session.id)
4295 self.assertNotEqual(session3, session)
4296 sess_stat = server_context.session_stats()
4297 self.assertEqual(sess_stat['accept'], 3)
4298 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004299
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004300 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004301 stats = server_params_test(client_context, server_context,
4302 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004303 self.assertTrue(stats['session_reused'])
4304 session4 = stats['session']
4305 self.assertEqual(session4.id, session.id)
4306 self.assertEqual(session4, session)
4307 self.assertGreaterEqual(session4.time, session.time)
4308 self.assertGreaterEqual(session4.timeout, session.timeout)
4309 sess_stat = server_context.session_stats()
4310 self.assertEqual(sess_stat['accept'], 4)
4311 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004312
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004313 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004314 client_context, server_context, hostname = testing_context()
4315 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004316
Christian Heimes05d9fe32018-02-27 08:55:39 +01004317 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004318 client_context.options |= ssl.OP_NO_TLSv1_3
4319 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004320
Christian Heimesa170fa12017-09-15 20:27:30 +02004321 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004322 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004323 with client_context.wrap_socket(socket.socket(),
4324 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004325 # session is None before handshake
4326 self.assertEqual(s.session, None)
4327 self.assertEqual(s.session_reused, None)
4328 s.connect((HOST, server.port))
4329 session = s.session
4330 self.assertTrue(session)
4331 with self.assertRaises(TypeError) as e:
4332 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004333 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004334
Christian Heimesa170fa12017-09-15 20:27:30 +02004335 with client_context.wrap_socket(socket.socket(),
4336 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004337 s.connect((HOST, server.port))
4338 # cannot set session after handshake
4339 with self.assertRaises(ValueError) as e:
4340 s.session = session
4341 self.assertEqual(str(e.exception),
4342 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004343
Christian Heimesa170fa12017-09-15 20:27:30 +02004344 with client_context.wrap_socket(socket.socket(),
4345 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004346 # can set session before handshake and before the
4347 # connection was established
4348 s.session = session
4349 s.connect((HOST, server.port))
4350 self.assertEqual(s.session.id, session.id)
4351 self.assertEqual(s.session, session)
4352 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004353
Christian Heimesa170fa12017-09-15 20:27:30 +02004354 with client_context2.wrap_socket(socket.socket(),
4355 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004356 # cannot re-use session with a different SSLContext
4357 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004358 s.session = session
4359 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004360 self.assertEqual(str(e.exception),
4361 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004362
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004363
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004364@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004365class TestPostHandshakeAuth(unittest.TestCase):
4366 def test_pha_setter(self):
4367 protocols = [
Christian Heimes2875c602021-04-19 07:27:10 +02004368 ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
Christian Heimes9fb051f2018-09-23 08:32:31 +02004369 ]
4370 for protocol in protocols:
4371 ctx = ssl.SSLContext(protocol)
4372 self.assertEqual(ctx.post_handshake_auth, False)
4373
4374 ctx.post_handshake_auth = True
4375 self.assertEqual(ctx.post_handshake_auth, True)
4376
4377 ctx.verify_mode = ssl.CERT_REQUIRED
4378 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4379 self.assertEqual(ctx.post_handshake_auth, True)
4380
4381 ctx.post_handshake_auth = False
4382 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4383 self.assertEqual(ctx.post_handshake_auth, False)
4384
4385 ctx.verify_mode = ssl.CERT_OPTIONAL
4386 ctx.post_handshake_auth = True
4387 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4388 self.assertEqual(ctx.post_handshake_auth, True)
4389
4390 def test_pha_required(self):
4391 client_context, server_context, hostname = testing_context()
4392 server_context.post_handshake_auth = True
4393 server_context.verify_mode = ssl.CERT_REQUIRED
4394 client_context.post_handshake_auth = True
4395 client_context.load_cert_chain(SIGNED_CERTFILE)
4396
4397 server = ThreadedEchoServer(context=server_context, chatty=False)
4398 with server:
4399 with client_context.wrap_socket(socket.socket(),
4400 server_hostname=hostname) as s:
4401 s.connect((HOST, server.port))
4402 s.write(b'HASCERT')
4403 self.assertEqual(s.recv(1024), b'FALSE\n')
4404 s.write(b'PHA')
4405 self.assertEqual(s.recv(1024), b'OK\n')
4406 s.write(b'HASCERT')
4407 self.assertEqual(s.recv(1024), b'TRUE\n')
4408 # PHA method just returns true when cert is already available
4409 s.write(b'PHA')
4410 self.assertEqual(s.recv(1024), b'OK\n')
4411 s.write(b'GETCERT')
4412 cert_text = s.recv(4096).decode('us-ascii')
4413 self.assertIn('Python Software Foundation CA', cert_text)
4414
4415 def test_pha_required_nocert(self):
4416 client_context, server_context, hostname = testing_context()
4417 server_context.post_handshake_auth = True
4418 server_context.verify_mode = ssl.CERT_REQUIRED
4419 client_context.post_handshake_auth = True
4420
Christian Heimesc8666cf2021-04-24 09:17:54 +02004421 def msg_cb(conn, direction, version, content_type, msg_type, data):
4422 if support.verbose and content_type == _TLSContentType.ALERT:
4423 info = (conn, direction, version, content_type, msg_type, data)
4424 sys.stdout.write(f"TLS: {info!r}\n")
4425
4426 server_context._msg_callback = msg_cb
4427 client_context._msg_callback = msg_cb
4428
4429 server = ThreadedEchoServer(context=server_context, chatty=True)
4430 with server:
4431 with client_context.wrap_socket(socket.socket(),
4432 server_hostname=hostname) as s:
4433 s.connect((HOST, server.port))
4434 s.write(b'PHA')
Christian Heimesce9a0642021-04-24 15:08:13 +02004435 # test sometimes fails with EOF error. Test passes as long as
4436 # server aborts connection with an error.
Christian Heimesc8666cf2021-04-24 09:17:54 +02004437 with self.assertRaisesRegex(
4438 ssl.SSLError,
Christian Heimesce9a0642021-04-24 15:08:13 +02004439 '(certificate required|EOF occurred)'
Christian Heimesc8666cf2021-04-24 09:17:54 +02004440 ):
Victor Stinner73ea5462019-07-09 14:33:49 +02004441 # receive CertificateRequest
4442 self.assertEqual(s.recv(1024), b'OK\n')
4443 # send empty Certificate + Finish
4444 s.write(b'HASCERT')
4445 # receive alert
Christian Heimesc8666cf2021-04-24 09:17:54 +02004446 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004447
4448 def test_pha_optional(self):
4449 if support.verbose:
4450 sys.stdout.write("\n")
4451
4452 client_context, server_context, hostname = testing_context()
4453 server_context.post_handshake_auth = True
4454 server_context.verify_mode = ssl.CERT_REQUIRED
4455 client_context.post_handshake_auth = True
4456 client_context.load_cert_chain(SIGNED_CERTFILE)
4457
4458 # check CERT_OPTIONAL
4459 server_context.verify_mode = ssl.CERT_OPTIONAL
4460 server = ThreadedEchoServer(context=server_context, chatty=False)
4461 with server:
4462 with client_context.wrap_socket(socket.socket(),
4463 server_hostname=hostname) as s:
4464 s.connect((HOST, server.port))
4465 s.write(b'HASCERT')
4466 self.assertEqual(s.recv(1024), b'FALSE\n')
4467 s.write(b'PHA')
4468 self.assertEqual(s.recv(1024), b'OK\n')
4469 s.write(b'HASCERT')
4470 self.assertEqual(s.recv(1024), b'TRUE\n')
4471
4472 def test_pha_optional_nocert(self):
4473 if support.verbose:
4474 sys.stdout.write("\n")
4475
4476 client_context, server_context, hostname = testing_context()
4477 server_context.post_handshake_auth = True
4478 server_context.verify_mode = ssl.CERT_OPTIONAL
4479 client_context.post_handshake_auth = True
4480
4481 server = ThreadedEchoServer(context=server_context, chatty=False)
4482 with server:
4483 with client_context.wrap_socket(socket.socket(),
4484 server_hostname=hostname) as s:
4485 s.connect((HOST, server.port))
4486 s.write(b'HASCERT')
4487 self.assertEqual(s.recv(1024), b'FALSE\n')
4488 s.write(b'PHA')
4489 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004490 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004491 s.write(b'HASCERT')
4492 self.assertEqual(s.recv(1024), b'FALSE\n')
4493
4494 def test_pha_no_pha_client(self):
4495 client_context, server_context, hostname = testing_context()
4496 server_context.post_handshake_auth = True
4497 server_context.verify_mode = ssl.CERT_REQUIRED
4498 client_context.load_cert_chain(SIGNED_CERTFILE)
4499
4500 server = ThreadedEchoServer(context=server_context, chatty=False)
4501 with server:
4502 with client_context.wrap_socket(socket.socket(),
4503 server_hostname=hostname) as s:
4504 s.connect((HOST, server.port))
4505 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4506 s.verify_client_post_handshake()
4507 s.write(b'PHA')
4508 self.assertIn(b'extension not received', s.recv(1024))
4509
4510 def test_pha_no_pha_server(self):
4511 # server doesn't have PHA enabled, cert is requested in handshake
4512 client_context, server_context, hostname = testing_context()
4513 server_context.verify_mode = ssl.CERT_REQUIRED
4514 client_context.post_handshake_auth = True
4515 client_context.load_cert_chain(SIGNED_CERTFILE)
4516
4517 server = ThreadedEchoServer(context=server_context, chatty=False)
4518 with server:
4519 with client_context.wrap_socket(socket.socket(),
4520 server_hostname=hostname) as s:
4521 s.connect((HOST, server.port))
4522 s.write(b'HASCERT')
4523 self.assertEqual(s.recv(1024), b'TRUE\n')
4524 # PHA doesn't fail if there is already a cert
4525 s.write(b'PHA')
4526 self.assertEqual(s.recv(1024), b'OK\n')
4527 s.write(b'HASCERT')
4528 self.assertEqual(s.recv(1024), b'TRUE\n')
4529
4530 def test_pha_not_tls13(self):
4531 # TLS 1.2
4532 client_context, server_context, hostname = testing_context()
4533 server_context.verify_mode = ssl.CERT_REQUIRED
4534 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4535 client_context.post_handshake_auth = True
4536 client_context.load_cert_chain(SIGNED_CERTFILE)
4537
4538 server = ThreadedEchoServer(context=server_context, chatty=False)
4539 with server:
4540 with client_context.wrap_socket(socket.socket(),
4541 server_hostname=hostname) as s:
4542 s.connect((HOST, server.port))
4543 # PHA fails for TLS != 1.3
4544 s.write(b'PHA')
4545 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4546
Christian Heimesf0f59302019-07-01 08:29:17 +02004547 def test_bpo37428_pha_cert_none(self):
4548 # verify that post_handshake_auth does not implicitly enable cert
4549 # validation.
4550 hostname = SIGNED_CERTFILE_HOSTNAME
4551 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4552 client_context.post_handshake_auth = True
4553 client_context.load_cert_chain(SIGNED_CERTFILE)
4554 # no cert validation and CA on client side
4555 client_context.check_hostname = False
4556 client_context.verify_mode = ssl.CERT_NONE
4557
4558 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4559 server_context.load_cert_chain(SIGNED_CERTFILE)
4560 server_context.load_verify_locations(SIGNING_CA)
4561 server_context.post_handshake_auth = True
4562 server_context.verify_mode = ssl.CERT_REQUIRED
4563
4564 server = ThreadedEchoServer(context=server_context, chatty=False)
4565 with server:
4566 with client_context.wrap_socket(socket.socket(),
4567 server_hostname=hostname) as s:
4568 s.connect((HOST, server.port))
4569 s.write(b'HASCERT')
4570 self.assertEqual(s.recv(1024), b'FALSE\n')
4571 s.write(b'PHA')
4572 self.assertEqual(s.recv(1024), b'OK\n')
4573 s.write(b'HASCERT')
4574 self.assertEqual(s.recv(1024), b'TRUE\n')
4575 # server cert has not been validated
4576 self.assertEqual(s.getpeercert(), {})
4577
Christian Heimes666991f2021-04-26 15:01:40 +02004578 def test_internal_chain_client(self):
4579 client_context, server_context, hostname = testing_context(
4580 server_chain=False
4581 )
4582 server = ThreadedEchoServer(context=server_context, chatty=False)
4583 with server:
4584 with client_context.wrap_socket(
4585 socket.socket(),
4586 server_hostname=hostname
4587 ) as s:
4588 s.connect((HOST, server.port))
4589 vc = s._sslobj.get_verified_chain()
4590 self.assertEqual(len(vc), 2)
4591 ee, ca = vc
4592 uvc = s._sslobj.get_unverified_chain()
4593 self.assertEqual(len(uvc), 1)
4594
4595 self.assertEqual(ee, uvc[0])
4596 self.assertEqual(hash(ee), hash(uvc[0]))
4597 self.assertEqual(repr(ee), repr(uvc[0]))
4598
4599 self.assertNotEqual(ee, ca)
4600 self.assertNotEqual(hash(ee), hash(ca))
4601 self.assertNotEqual(repr(ee), repr(ca))
4602 self.assertNotEqual(ee.get_info(), ca.get_info())
4603 self.assertIn("CN=localhost", repr(ee))
4604 self.assertIn("CN=our-ca-server", repr(ca))
4605
4606 pem = ee.public_bytes(_ssl.ENCODING_PEM)
4607 der = ee.public_bytes(_ssl.ENCODING_DER)
4608 self.assertIsInstance(pem, str)
4609 self.assertIn("-----BEGIN CERTIFICATE-----", pem)
4610 self.assertIsInstance(der, bytes)
4611 self.assertEqual(
4612 ssl.PEM_cert_to_DER_cert(pem), der
4613 )
4614
4615 def test_internal_chain_server(self):
4616 client_context, server_context, hostname = testing_context()
4617 client_context.load_cert_chain(SIGNED_CERTFILE)
4618 server_context.verify_mode = ssl.CERT_REQUIRED
4619 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
4620
4621 server = ThreadedEchoServer(context=server_context, chatty=False)
4622 with server:
4623 with client_context.wrap_socket(
4624 socket.socket(),
4625 server_hostname=hostname
4626 ) as s:
4627 s.connect((HOST, server.port))
4628 s.write(b'VERIFIEDCHAIN\n')
4629 res = s.recv(1024)
4630 self.assertEqual(res, b'\x02\n')
4631 s.write(b'UNVERIFIEDCHAIN\n')
4632 res = s.recv(1024)
4633 self.assertEqual(res, b'\x02\n')
4634
Christian Heimes9fb051f2018-09-23 08:32:31 +02004635
Christian Heimesc7f70692019-05-31 11:44:05 +02004636HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4637requires_keylog = unittest.skipUnless(
4638 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4639
4640class TestSSLDebug(unittest.TestCase):
4641
Hai Shia7f5d932020-08-04 00:41:24 +08004642 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004643 with open(fname) as f:
4644 return len(list(f))
4645
4646 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004647 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004648 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004649 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004650 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4651 self.assertEqual(ctx.keylog_filename, None)
4652
Hai Shia7f5d932020-08-04 00:41:24 +08004653 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4654 ctx.keylog_filename = os_helper.TESTFN
4655 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4656 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004657 self.assertEqual(self.keylog_lines(), 1)
4658
4659 ctx.keylog_filename = None
4660 self.assertEqual(ctx.keylog_filename, None)
4661
4662 with self.assertRaises((IsADirectoryError, PermissionError)):
4663 # Windows raises PermissionError
4664 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004665 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004666
4667 with self.assertRaises(TypeError):
4668 ctx.keylog_filename = 1
4669
4670 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004671 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004672 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004673 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004674 client_context, server_context, hostname = testing_context()
4675
Hai Shia7f5d932020-08-04 00:41:24 +08004676 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004677 server = ThreadedEchoServer(context=server_context, chatty=False)
4678 with server:
4679 with client_context.wrap_socket(socket.socket(),
4680 server_hostname=hostname) as s:
4681 s.connect((HOST, server.port))
4682 # header, 5 lines for TLS 1.3
4683 self.assertEqual(self.keylog_lines(), 6)
4684
4685 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004686 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004687 server = ThreadedEchoServer(context=server_context, chatty=False)
4688 with server:
4689 with client_context.wrap_socket(socket.socket(),
4690 server_hostname=hostname) as s:
4691 s.connect((HOST, server.port))
4692 self.assertGreaterEqual(self.keylog_lines(), 11)
4693
Hai Shia7f5d932020-08-04 00:41:24 +08004694 client_context.keylog_filename = os_helper.TESTFN
4695 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004696 server = ThreadedEchoServer(context=server_context, chatty=False)
4697 with server:
4698 with client_context.wrap_socket(socket.socket(),
4699 server_hostname=hostname) as s:
4700 s.connect((HOST, server.port))
4701 self.assertGreaterEqual(self.keylog_lines(), 21)
4702
4703 client_context.keylog_filename = None
4704 server_context.keylog_filename = None
4705
4706 @requires_keylog
4707 @unittest.skipIf(sys.flags.ignore_environment,
4708 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004709 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004710 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004711 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004712 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004713 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4714 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004715
4716 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4717 self.assertEqual(ctx.keylog_filename, None)
4718
4719 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004720 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004721
4722 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004723 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004724
4725 def test_msg_callback(self):
4726 client_context, server_context, hostname = testing_context()
4727
4728 def msg_cb(conn, direction, version, content_type, msg_type, data):
4729 pass
4730
4731 self.assertIs(client_context._msg_callback, None)
4732 client_context._msg_callback = msg_cb
4733 self.assertIs(client_context._msg_callback, msg_cb)
4734 with self.assertRaises(TypeError):
4735 client_context._msg_callback = object()
4736
4737 def test_msg_callback_tls12(self):
4738 client_context, server_context, hostname = testing_context()
4739 client_context.options |= ssl.OP_NO_TLSv1_3
4740
4741 msg = []
4742
4743 def msg_cb(conn, direction, version, content_type, msg_type, data):
4744 self.assertIsInstance(conn, ssl.SSLSocket)
4745 self.assertIsInstance(data, bytes)
4746 self.assertIn(direction, {'read', 'write'})
4747 msg.append((direction, version, content_type, msg_type))
4748
4749 client_context._msg_callback = msg_cb
4750
4751 server = ThreadedEchoServer(context=server_context, chatty=False)
4752 with server:
4753 with client_context.wrap_socket(socket.socket(),
4754 server_hostname=hostname) as s:
4755 s.connect((HOST, server.port))
4756
Christian Heimese35d1ba2019-06-03 20:40:15 +02004757 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004758 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4759 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004760 msg
4761 )
4762 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004763 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4764 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004765 msg
4766 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004767
Christian Heimes77cde502021-03-21 16:13:09 +01004768 def test_msg_callback_deadlock_bpo43577(self):
4769 client_context, server_context, hostname = testing_context()
4770 server_context2 = testing_context()[1]
4771
4772 def msg_cb(conn, direction, version, content_type, msg_type, data):
4773 pass
4774
4775 def sni_cb(sock, servername, ctx):
4776 sock.context = server_context2
4777
4778 server_context._msg_callback = msg_cb
4779 server_context.sni_callback = sni_cb
4780
4781 server = ThreadedEchoServer(context=server_context, chatty=False)
4782 with server:
4783 with client_context.wrap_socket(socket.socket(),
4784 server_hostname=hostname) as s:
4785 s.connect((HOST, server.port))
4786 with client_context.wrap_socket(socket.socket(),
4787 server_hostname=hostname) as s:
4788 s.connect((HOST, server.port))
4789
Christian Heimesc7f70692019-05-31 11:44:05 +02004790
Ethan Furmana02cb472021-04-21 10:20:44 -07004791class TestEnumerations(unittest.TestCase):
4792
4793 def test_tlsversion(self):
4794 class CheckedTLSVersion(enum.IntEnum):
4795 MINIMUM_SUPPORTED = _ssl.PROTO_MINIMUM_SUPPORTED
4796 SSLv3 = _ssl.PROTO_SSLv3
4797 TLSv1 = _ssl.PROTO_TLSv1
4798 TLSv1_1 = _ssl.PROTO_TLSv1_1
4799 TLSv1_2 = _ssl.PROTO_TLSv1_2
4800 TLSv1_3 = _ssl.PROTO_TLSv1_3
4801 MAXIMUM_SUPPORTED = _ssl.PROTO_MAXIMUM_SUPPORTED
4802 enum._test_simple_enum(CheckedTLSVersion, TLSVersion)
4803
4804 def test_tlscontenttype(self):
4805 class Checked_TLSContentType(enum.IntEnum):
4806 """Content types (record layer)
4807
4808 See RFC 8446, section B.1
4809 """
4810 CHANGE_CIPHER_SPEC = 20
4811 ALERT = 21
4812 HANDSHAKE = 22
4813 APPLICATION_DATA = 23
4814 # pseudo content types
4815 HEADER = 0x100
4816 INNER_CONTENT_TYPE = 0x101
4817 enum._test_simple_enum(Checked_TLSContentType, _TLSContentType)
4818
4819 def test_tlsalerttype(self):
4820 class Checked_TLSAlertType(enum.IntEnum):
4821 """Alert types for TLSContentType.ALERT messages
4822
4823 See RFC 8466, section B.2
4824 """
4825 CLOSE_NOTIFY = 0
4826 UNEXPECTED_MESSAGE = 10
4827 BAD_RECORD_MAC = 20
4828 DECRYPTION_FAILED = 21
4829 RECORD_OVERFLOW = 22
4830 DECOMPRESSION_FAILURE = 30
4831 HANDSHAKE_FAILURE = 40
4832 NO_CERTIFICATE = 41
4833 BAD_CERTIFICATE = 42
4834 UNSUPPORTED_CERTIFICATE = 43
4835 CERTIFICATE_REVOKED = 44
4836 CERTIFICATE_EXPIRED = 45
4837 CERTIFICATE_UNKNOWN = 46
4838 ILLEGAL_PARAMETER = 47
4839 UNKNOWN_CA = 48
4840 ACCESS_DENIED = 49
4841 DECODE_ERROR = 50
4842 DECRYPT_ERROR = 51
4843 EXPORT_RESTRICTION = 60
4844 PROTOCOL_VERSION = 70
4845 INSUFFICIENT_SECURITY = 71
4846 INTERNAL_ERROR = 80
4847 INAPPROPRIATE_FALLBACK = 86
4848 USER_CANCELED = 90
4849 NO_RENEGOTIATION = 100
4850 MISSING_EXTENSION = 109
4851 UNSUPPORTED_EXTENSION = 110
4852 CERTIFICATE_UNOBTAINABLE = 111
4853 UNRECOGNIZED_NAME = 112
4854 BAD_CERTIFICATE_STATUS_RESPONSE = 113
4855 BAD_CERTIFICATE_HASH_VALUE = 114
4856 UNKNOWN_PSK_IDENTITY = 115
4857 CERTIFICATE_REQUIRED = 116
4858 NO_APPLICATION_PROTOCOL = 120
4859 enum._test_simple_enum(Checked_TLSAlertType, _TLSAlertType)
4860
4861 def test_tlsmessagetype(self):
4862 class Checked_TLSMessageType(enum.IntEnum):
4863 """Message types (handshake protocol)
4864
4865 See RFC 8446, section B.3
4866 """
4867 HELLO_REQUEST = 0
4868 CLIENT_HELLO = 1
4869 SERVER_HELLO = 2
4870 HELLO_VERIFY_REQUEST = 3
4871 NEWSESSION_TICKET = 4
4872 END_OF_EARLY_DATA = 5
4873 HELLO_RETRY_REQUEST = 6
4874 ENCRYPTED_EXTENSIONS = 8
4875 CERTIFICATE = 11
4876 SERVER_KEY_EXCHANGE = 12
4877 CERTIFICATE_REQUEST = 13
4878 SERVER_DONE = 14
4879 CERTIFICATE_VERIFY = 15
4880 CLIENT_KEY_EXCHANGE = 16
4881 FINISHED = 20
4882 CERTIFICATE_URL = 21
4883 CERTIFICATE_STATUS = 22
4884 SUPPLEMENTAL_DATA = 23
4885 KEY_UPDATE = 24
4886 NEXT_PROTO = 67
4887 MESSAGE_HASH = 254
4888 CHANGE_CIPHER_SPEC = 0x0101
4889 enum._test_simple_enum(Checked_TLSMessageType, _TLSMessageType)
4890
4891 def test_sslmethod(self):
4892 Checked_SSLMethod = enum._old_convert_(
4893 enum.IntEnum, '_SSLMethod', 'ssl',
4894 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4895 source=ssl._ssl,
4896 )
4897 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
4898
4899 def test_options(self):
4900 CheckedOptions = enum._old_convert_(
4901 enum.FlagEnum, 'Options', 'ssl',
4902 lambda name: name.startswith('OP_'),
4903 source=ssl._ssl,
4904 )
4905 enum._test_simple_enum(CheckedOptions, ssl.Options)
4906
4907
4908 def test_alertdescription(self):
4909 CheckedAlertDescription = enum._old_convert_(
4910 enum.IntEnum, 'AlertDescription', 'ssl',
4911 lambda name: name.startswith('ALERT_DESCRIPTION_'),
4912 source=ssl._ssl,
4913 )
4914 enum._test_simple_enum(CheckedAlertDescription, ssl.AlertDescription)
4915
4916 def test_sslerrornumber(self):
4917 Checked_SSLMethod = enum._old_convert_(
4918 enum.IntEnum, '_SSLMethod', 'ssl',
4919 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4920 source=ssl._ssl,
4921 )
4922 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
4923
4924 def test_verifyflags(self):
4925 CheckedVerifyFlags = enum._old_convert_(
4926 enum.FlagEnum, 'VerifyFlags', 'ssl',
4927 lambda name: name.startswith('VERIFY_'),
4928 source=ssl._ssl,
4929 )
4930 enum._test_simple_enum(CheckedVerifyFlags, ssl.VerifyFlags)
4931
4932 def test_verifymode(self):
4933 CheckedVerifyMode = enum._old_convert_(
4934 enum.IntEnum, 'VerifyMode', 'ssl',
4935 lambda name: name.startswith('CERT_'),
4936 source=ssl._ssl,
4937 )
4938 enum._test_simple_enum(CheckedVerifyMode, ssl.VerifyMode)
4939
Thomas Woutersed03b412007-08-28 21:37:11 +00004940def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004941 if support.verbose:
4942 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004943 'Mac': platform.mac_ver,
4944 'Windows': platform.win32_ver,
4945 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004946 for name, func in plats.items():
4947 plat = func()
4948 if plat and plat[0]:
4949 plat = '%s %r' % (name, plat)
4950 break
4951 else:
4952 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004953 print("test_ssl: testing with %r %r" %
4954 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4955 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004956 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004957 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4958 try:
4959 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4960 except AttributeError:
4961 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004962
Antoine Pitrou152efa22010-05-16 18:19:27 +00004963 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004964 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004965 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004966 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004967 BADCERT, BADKEY, EMPTYCERT]:
4968 if not os.path.exists(filename):
4969 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004970
Martin Panter3840b2a2016-03-27 01:53:46 +00004971 tests = [
4972 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004973 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004974 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004975 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004976
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004977 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004978 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004979
Hai Shie80697d2020-05-28 06:10:27 +08004980 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004981 try:
4982 support.run_unittest(*tests)
4983 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004984 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004985
4986if __name__ == "__main__":
4987 test_main()