blob: 0b8cef639961cf315dc273579f9eff3451c75874 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Christian Heimesc7f70692019-05-31 11:44:05 +02005import unittest.mock
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Hai Shia7f5d932020-08-04 00:41:24 +08007from test.support import import_helper
8from test.support import os_helper
Serhiy Storchaka16994912020-04-25 10:06:29 +03009from test.support import socket_helper
Hai Shie80697d2020-05-28 06:10:27 +080010from test.support import threading_helper
Hai Shia7f5d932020-08-04 00:41:24 +080011from test.support import warnings_helper
Thomas Woutersed03b412007-08-28 21:37:11 +000012import socket
Bill Janssen6e027db2007-11-15 22:23:56 +000013import select
Thomas Woutersed03b412007-08-28 21:37:11 +000014import time
Ethan Furmana02cb472021-04-21 10:20:44 -070015import datetime
16import enum
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000017import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000018import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000019import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000020import pprint
Antoine Pitrou803e6d62010-10-13 10:36:15 +000021import urllib.request
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020022import threading
Thomas Woutersed03b412007-08-28 21:37:11 +000023import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000024import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000025import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000026import platform
Christian Heimes892d66e2018-01-29 14:10:18 +010027import sysconfig
Christian Heimesdf6ac7e2019-09-26 17:02:59 +020028import functools
Christian Heimes888bbdc2017-09-07 14:18:21 -070029try:
30 import ctypes
31except ImportError:
32 ctypes = None
Thomas Woutersed03b412007-08-28 21:37:11 +000033
Hai Shia7f5d932020-08-04 00:41:24 +080034ssl = import_helper.import_module("ssl")
Antoine Pitrou05d936d2010-10-13 11:38:36 +000035
Ethan Furmana02cb472021-04-21 10:20:44 -070036from ssl import TLSVersion, _TLSContentType, _TLSMessageType, _TLSAlertType
Martin Panter3840b2a2016-03-27 01:53:46 +000037
Paul Monsonf3550692019-06-19 13:09:54 -070038Py_DEBUG = hasattr(sys, 'gettotalrefcount')
39Py_DEBUG_WIN32 = Py_DEBUG and sys.platform == 'win32'
40
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010041PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Serhiy Storchaka16994912020-04-25 10:06:29 +030042HOST = socket_helper.HOST
Christian Heimesd37b74f2021-04-19 08:31:29 +020043IS_OPENSSL_3_0_0 = ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
Christian Heimes892d66e2018-01-29 14:10:18 +010044PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
Antoine Pitrou152efa22010-05-16 18:19:27 +000045
Victor Stinner3ef63442019-02-19 18:06:03 +010046PROTOCOL_TO_TLS_VERSION = {}
47for proto, ver in (
48 ("PROTOCOL_SSLv23", "SSLv3"),
49 ("PROTOCOL_TLSv1", "TLSv1"),
50 ("PROTOCOL_TLSv1_1", "TLSv1_1"),
51):
52 try:
53 proto = getattr(ssl, proto)
54 ver = getattr(ssl.TLSVersion, ver)
55 except AttributeError:
56 continue
57 PROTOCOL_TO_TLS_VERSION[proto] = ver
58
Christian Heimesefff7062013-11-21 03:35:02 +010059def data_file(*name):
60 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000061
Antoine Pitrou81564092010-10-08 23:06:24 +000062# The custom key and certificate files used in test_ssl are generated
63# using Lib/test/make_ssl_certs.py.
64# Other certificates are simply fetched from the Internet servers they
65# are meant to authenticate.
66
Antoine Pitrou152efa22010-05-16 18:19:27 +000067CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000068BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000069ONLYCERT = data_file("ssl_cert.pem")
70ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000071BYTES_ONLYCERT = os.fsencode(ONLYCERT)
72BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020073CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
74ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
75KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000076CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000077BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010078CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
79CAFILE_CACERT = data_file("capath", "5ed36f99.0")
80
Christian Heimesbd5c7d22018-01-20 15:16:30 +010081CERTFILE_INFO = {
82 'issuer': ((('countryName', 'XY'),),
83 (('localityName', 'Castle Anthrax'),),
84 (('organizationName', 'Python Software Foundation'),),
85 (('commonName', 'localhost'),)),
Christian Heimese6dac002018-08-30 07:25:49 +020086 'notAfter': 'Aug 26 14:23:15 2028 GMT',
87 'notBefore': 'Aug 29 14:23:15 2018 GMT',
88 'serialNumber': '98A7CF88C74A32ED',
Christian Heimesbd5c7d22018-01-20 15:16:30 +010089 'subject': ((('countryName', 'XY'),),
90 (('localityName', 'Castle Anthrax'),),
91 (('organizationName', 'Python Software Foundation'),),
92 (('commonName', 'localhost'),)),
93 'subjectAltName': (('DNS', 'localhost'),),
94 'version': 3
95}
Antoine Pitrou152efa22010-05-16 18:19:27 +000096
Christian Heimes22587792013-11-21 23:56:13 +010097# empty CRL
98CRLFILE = data_file("revocation.crl")
99
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100100# Two keys and certs signed by the same CA (for SNI tests)
101SIGNED_CERTFILE = data_file("keycert3.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200102SIGNED_CERTFILE_HOSTNAME = 'localhost'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100103
104SIGNED_CERTFILE_INFO = {
105 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
106 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
107 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
108 'issuer': ((('countryName', 'XY'),),
109 (('organizationName', 'Python Software Foundation CA'),),
110 (('commonName', 'our-ca-server'),)),
Christian Heimesb467d9a2021-04-17 10:07:19 +0200111 'notAfter': 'Oct 28 14:23:16 2037 GMT',
Christian Heimese6dac002018-08-30 07:25:49 +0200112 'notBefore': 'Aug 29 14:23:16 2018 GMT',
113 'serialNumber': 'CB2D80995A69525C',
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100114 'subject': ((('countryName', 'XY'),),
115 (('localityName', 'Castle Anthrax'),),
116 (('organizationName', 'Python Software Foundation'),),
117 (('commonName', 'localhost'),)),
118 'subjectAltName': (('DNS', 'localhost'),),
119 'version': 3
120}
121
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100122SIGNED_CERTFILE2 = data_file("keycert4.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200123SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100124SIGNED_CERTFILE_ECC = data_file("keycertecc.pem")
125SIGNED_CERTFILE_ECC_HOSTNAME = 'localhost-ecc'
126
Martin Panter3840b2a2016-03-27 01:53:46 +0000127# Same certificate as pycacert.pem, but without extra text in file
128SIGNING_CA = data_file("capath", "ceff1710.0")
Christian Heimes1c03abd2016-09-06 23:25:35 +0200129# cert with all kinds of subject alt names
130ALLSANFILE = data_file("allsans.pem")
Christian Heimes66e57422018-01-29 14:25:13 +0100131IDNSANSFILE = data_file("idnsans.pem")
Christian Heimesb467d9a2021-04-17 10:07:19 +0200132NOSANFILE = data_file("nosan.pem")
133NOSAN_HOSTNAME = 'localhost'
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100134
Martin Panter3d81d932016-01-14 09:36:00 +0000135REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +0000136
137EMPTYCERT = data_file("nullcert.pem")
138BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +0000139NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000140BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200141NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +0200142NULLBYTECERT = data_file("nullbytecert.pem")
Christian Heimesa37f5242019-01-15 23:47:42 +0100143TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000144
Christian Heimes88bfd0b2018-08-14 12:54:19 +0200145DHFILE = data_file("ffdh3072.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100146BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +0000147
Christian Heimes358cfd42016-09-10 22:43:48 +0200148# Not defined in all versions of OpenSSL
149OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
150OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
151OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
152OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
Christian Heimes05d9fe32018-02-27 08:55:39 +0100153OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
Christian Heimes6f37ebc2021-04-09 17:59:21 +0200154OP_IGNORE_UNEXPECTED_EOF = getattr(ssl, "OP_IGNORE_UNEXPECTED_EOF", 0)
Christian Heimes358cfd42016-09-10 22:43:48 +0200155
Christian Heimesf6c6b582021-03-18 23:06:50 +0100156# Ubuntu has patched OpenSSL and changed behavior of security level 2
157# see https://bugs.python.org/issue41561#msg389003
158def is_ubuntu():
159 try:
160 # Assume that any references of "ubuntu" implies Ubuntu-like distro
161 # The workaround is not required for 18.04, but doesn't hurt either.
162 with open("/etc/os-release", encoding="utf-8") as f:
163 return "ubuntu" in f.read()
164 except FileNotFoundError:
165 return False
166
167if is_ubuntu():
168 def seclevel_workaround(*ctxs):
169 """"Lower security level to '1' and allow all ciphers for TLS 1.0/1"""
170 for ctx in ctxs:
Christian Heimes34477502021-04-12 12:00:38 +0200171 if (
172 hasattr(ctx, "minimum_version") and
173 ctx.minimum_version <= ssl.TLSVersion.TLSv1_1
174 ):
Christian Heimesf6c6b582021-03-18 23:06:50 +0100175 ctx.set_ciphers("@SECLEVEL=1:ALL")
176else:
177 def seclevel_workaround(*ctxs):
178 pass
179
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100180
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200181def has_tls_protocol(protocol):
182 """Check if a TLS protocol is available and enabled
183
184 :param protocol: enum ssl._SSLMethod member or name
185 :return: bool
186 """
187 if isinstance(protocol, str):
188 assert protocol.startswith('PROTOCOL_')
189 protocol = getattr(ssl, protocol, None)
190 if protocol is None:
191 return False
192 if protocol in {
193 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
194 ssl.PROTOCOL_TLS_CLIENT
195 }:
196 # auto-negotiate protocols are always available
197 return True
198 name = protocol.name
199 return has_tls_version(name[len('PROTOCOL_'):])
200
201
202@functools.lru_cache
203def has_tls_version(version):
204 """Check if a TLS/SSL version is enabled
205
206 :param version: TLS version name or ssl.TLSVersion member
207 :return: bool
208 """
209 if version == "SSLv2":
210 # never supported and not even in TLSVersion enum
211 return False
212
213 if isinstance(version, str):
214 version = ssl.TLSVersion.__members__[version]
215
216 # check compile time flags like ssl.HAS_TLSv1_2
217 if not getattr(ssl, f'HAS_{version.name}'):
218 return False
219
Christian Heimes5151d642021-04-09 15:43:06 +0200220 if IS_OPENSSL_3_0_0 and version < ssl.TLSVersion.TLSv1_2:
221 # bpo43791: 3.0.0-alpha14 fails with TLSV1_ALERT_INTERNAL_ERROR
222 return False
223
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200224 # check runtime and dynamic crypto policy settings. A TLS version may
225 # be compiled in but disabled by a policy or config option.
Christian Heimes2875c602021-04-19 07:27:10 +0200226 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200227 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200228 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200229 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
230 version < ctx.minimum_version
231 ):
232 return False
233 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200234 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200235 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
236 version > ctx.maximum_version
237 ):
238 return False
239
240 return True
241
242
243def requires_tls_version(version):
244 """Decorator to skip tests when a required TLS version is not available
245
246 :param version: TLS version name or ssl.TLSVersion member
247 :return:
248 """
249 def decorator(func):
250 @functools.wraps(func)
251 def wrapper(*args, **kw):
252 if not has_tls_version(version):
253 raise unittest.SkipTest(f"{version} is not available.")
254 else:
255 return func(*args, **kw)
256 return wrapper
257 return decorator
258
259
Thomas Woutersed03b412007-08-28 21:37:11 +0000260def handle_error(prefix):
261 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000262 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000263 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000264
Christian Heimesb7b92252018-02-25 09:49:31 +0100265
Antoine Pitrouc695c952014-04-28 20:57:36 +0200266def utc_offset(): #NOTE: ignore issues like #1647654
267 # local time = utc time + utc offset
268 if time.daylight and time.localtime().tm_isdst > 0:
269 return -time.altzone # seconds
270 return -time.timezone
271
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100272
Christian Heimes2875c602021-04-19 07:27:10 +0200273ignore_deprecation = warnings_helper.ignore_warnings(
274 category=DeprecationWarning
275)
Antoine Pitrou23df4832010-08-04 17:14:06 +0000276
Christian Heimes2875c602021-04-19 07:27:10 +0200277
278def test_wrap_socket(sock, *,
Christian Heimesd0486372016-09-10 23:23:33 +0200279 cert_reqs=ssl.CERT_NONE, ca_certs=None,
280 ciphers=None, certfile=None, keyfile=None,
281 **kwargs):
Christian Heimes2875c602021-04-19 07:27:10 +0200282 if not kwargs.get("server_side"):
283 kwargs["server_hostname"] = SIGNED_CERTFILE_HOSTNAME
284 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
285 else:
286 context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimesd0486372016-09-10 23:23:33 +0200287 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200288 if cert_reqs == ssl.CERT_NONE:
289 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200290 context.verify_mode = cert_reqs
291 if ca_certs is not None:
292 context.load_verify_locations(ca_certs)
293 if certfile is not None or keyfile is not None:
294 context.load_cert_chain(certfile, keyfile)
295 if ciphers is not None:
296 context.set_ciphers(ciphers)
297 return context.wrap_socket(sock, **kwargs)
298
Christian Heimesa170fa12017-09-15 20:27:30 +0200299
300def testing_context(server_cert=SIGNED_CERTFILE):
301 """Create context
302
303 client_context, server_context, hostname = testing_context()
304 """
305 if server_cert == SIGNED_CERTFILE:
306 hostname = SIGNED_CERTFILE_HOSTNAME
307 elif server_cert == SIGNED_CERTFILE2:
308 hostname = SIGNED_CERTFILE2_HOSTNAME
Christian Heimesb467d9a2021-04-17 10:07:19 +0200309 elif server_cert == NOSANFILE:
310 hostname = NOSAN_HOSTNAME
Christian Heimesa170fa12017-09-15 20:27:30 +0200311 else:
312 raise ValueError(server_cert)
313
314 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
315 client_context.load_verify_locations(SIGNING_CA)
316
317 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
318 server_context.load_cert_chain(server_cert)
Christian Heimes9fb051f2018-09-23 08:32:31 +0200319 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200320
321 return client_context, server_context, hostname
322
323
Antoine Pitrou152efa22010-05-16 18:19:27 +0000324class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000325
Antoine Pitrou480a1242010-04-28 21:37:09 +0000326 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000327 ssl.CERT_NONE
328 ssl.CERT_OPTIONAL
329 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100330 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100331 ssl.OP_SINGLE_DH_USE
Christian Heimesd37b74f2021-04-19 08:31:29 +0200332 ssl.OP_SINGLE_ECDH_USE
Christian Heimes39258d32021-04-17 11:36:35 +0200333 ssl.OP_NO_COMPRESSION
Christian Heimesd37b74f2021-04-19 08:31:29 +0200334 self.assertEqual(ssl.HAS_SNI, True)
335 self.assertEqual(ssl.HAS_ECDH, True)
336 self.assertEqual(ssl.HAS_TLSv1_2, True)
337 self.assertEqual(ssl.HAS_TLSv1_3, True)
Christian Heimescb5b68a2017-09-07 18:07:00 -0700338 ssl.OP_NO_SSLv2
339 ssl.OP_NO_SSLv3
340 ssl.OP_NO_TLSv1
341 ssl.OP_NO_TLSv1_3
Christian Heimes39258d32021-04-17 11:36:35 +0200342 ssl.OP_NO_TLSv1_1
343 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200344 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000345
Christian Heimes9d50ab52018-02-27 10:17:30 +0100346 def test_private_init(self):
347 with self.assertRaisesRegex(TypeError, "public constructor"):
348 with socket.socket() as s:
349 ssl.SSLSocket(s)
350
Antoine Pitrou172f0252014-04-18 20:33:08 +0200351 def test_str_for_enums(self):
352 # Make sure that the PROTOCOL_* constants have enum-like string
353 # reprs.
Christian Heimes2875c602021-04-19 07:27:10 +0200354 proto = ssl.PROTOCOL_TLS_CLIENT
355 self.assertEqual(str(proto), 'PROTOCOL_TLS_CLIENT')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200356 ctx = ssl.SSLContext(proto)
357 self.assertIs(ctx.protocol, proto)
358
Antoine Pitrou480a1242010-04-28 21:37:09 +0000359 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000360 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000361 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000362 sys.stdout.write("\n RAND_status is %d (%s)\n"
363 % (v, (v and "sufficient randomness") or
364 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200365
Christian Heimes2875c602021-04-19 07:27:10 +0200366 with warnings_helper.check_warnings():
367 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200368 self.assertEqual(len(data), 16)
369 self.assertEqual(is_cryptographic, v == 1)
370 if v:
371 data = ssl.RAND_bytes(16)
372 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200373 else:
374 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200375
Victor Stinner1e81a392013-12-19 16:47:04 +0100376 # negative num is invalid
377 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
Christian Heimes2875c602021-04-19 07:27:10 +0200378 with warnings_helper.check_warnings():
379 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
Victor Stinner1e81a392013-12-19 16:47:04 +0100380
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000381 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200382 ssl.RAND_add(b"this is a random bytes object", 75.0)
383 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000384
Antoine Pitrou480a1242010-04-28 21:37:09 +0000385 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000386 # note that this uses an 'unofficial' function in _ssl.c,
387 # provided solely for this test, to exercise the certificate
388 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100389 self.assertEqual(
390 ssl._ssl._test_decode_cert(CERTFILE),
391 CERTFILE_INFO
392 )
393 self.assertEqual(
394 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
395 SIGNED_CERTFILE_INFO
396 )
397
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200398 # Issue #13034: the subjectAltName in some certificates
399 # (notably projects.developer.nokia.com:443) wasn't parsed
400 p = ssl._ssl._test_decode_cert(NOKIACERT)
401 if support.verbose:
402 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
403 self.assertEqual(p['subjectAltName'],
404 (('DNS', 'projects.developer.nokia.com'),
405 ('DNS', 'projects.forum.nokia.com'))
406 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100407 # extra OCSP and AIA fields
408 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
409 self.assertEqual(p['caIssuers'],
410 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
411 self.assertEqual(p['crlDistributionPoints'],
412 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000413
Christian Heimesa37f5242019-01-15 23:47:42 +0100414 def test_parse_cert_CVE_2019_5010(self):
415 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
416 if support.verbose:
417 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
418 self.assertEqual(
419 p,
420 {
421 'issuer': (
422 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
423 'notAfter': 'Jun 14 18:00:58 2028 GMT',
424 'notBefore': 'Jun 18 18:00:58 2018 GMT',
425 'serialNumber': '02',
426 'subject': ((('countryName', 'UK'),),
427 (('commonName',
428 'codenomicon-vm-2.test.lal.cisco.com'),)),
429 'subjectAltName': (
430 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
431 'version': 3
432 }
433 )
434
Christian Heimes824f7f32013-08-17 00:54:47 +0200435 def test_parse_cert_CVE_2013_4238(self):
436 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
437 if support.verbose:
438 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
439 subject = ((('countryName', 'US'),),
440 (('stateOrProvinceName', 'Oregon'),),
441 (('localityName', 'Beaverton'),),
442 (('organizationName', 'Python Software Foundation'),),
443 (('organizationalUnitName', 'Python Core Development'),),
444 (('commonName', 'null.python.org\x00example.org'),),
445 (('emailAddress', 'python-dev@python.org'),))
446 self.assertEqual(p['subject'], subject)
447 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200448 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
449 san = (('DNS', 'altnull.python.org\x00example.com'),
450 ('email', 'null@python.org\x00user@example.org'),
451 ('URI', 'http://null.python.org\x00http://example.org'),
452 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100453 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200454 else:
455 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
456 san = (('DNS', 'altnull.python.org\x00example.com'),
457 ('email', 'null@python.org\x00user@example.org'),
458 ('URI', 'http://null.python.org\x00http://example.org'),
459 ('IP Address', '192.0.2.1'),
460 ('IP Address', '<invalid>'))
461
462 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200463
Christian Heimes1c03abd2016-09-06 23:25:35 +0200464 def test_parse_all_sans(self):
465 p = ssl._ssl._test_decode_cert(ALLSANFILE)
466 self.assertEqual(p['subjectAltName'],
467 (
468 ('DNS', 'allsans'),
469 ('othername', '<unsupported>'),
470 ('othername', '<unsupported>'),
471 ('email', 'user@example.org'),
472 ('DNS', 'www.example.org'),
473 ('DirName',
474 ((('countryName', 'XY'),),
475 (('localityName', 'Castle Anthrax'),),
476 (('organizationName', 'Python Software Foundation'),),
477 (('commonName', 'dirname example'),))),
478 ('URI', 'https://www.python.org/'),
479 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100480 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200481 ('Registered ID', '1.2.3.4.5')
482 )
483 )
484
Antoine Pitrou480a1242010-04-28 21:37:09 +0000485 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000486 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000487 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000488 d1 = ssl.PEM_cert_to_DER_cert(pem)
489 p2 = ssl.DER_cert_to_PEM_cert(d1)
490 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000491 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000492 if not p2.startswith(ssl.PEM_HEADER + '\n'):
493 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
494 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
495 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000496
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000497 def test_openssl_version(self):
498 n = ssl.OPENSSL_VERSION_NUMBER
499 t = ssl.OPENSSL_VERSION_INFO
500 s = ssl.OPENSSL_VERSION
501 self.assertIsInstance(n, int)
502 self.assertIsInstance(t, tuple)
503 self.assertIsInstance(s, str)
504 # Some sanity checks follow
Christian Heimesd37b74f2021-04-19 08:31:29 +0200505 # >= 1.1.1
506 self.assertGreaterEqual(n, 0x10101000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100507 # < 4.0
508 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000509 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100510 self.assertGreaterEqual(major, 1)
511 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000512 self.assertGreaterEqual(minor, 0)
513 self.assertLess(minor, 256)
514 self.assertGreaterEqual(fix, 0)
515 self.assertLess(fix, 256)
516 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100517 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000518 self.assertGreaterEqual(status, 0)
519 self.assertLessEqual(status, 15)
Christian Heimesd37b74f2021-04-19 08:31:29 +0200520
521 libressl_ver = f"LibreSSL {major:d}"
522 openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}"
523 self.assertTrue(
524 s.startswith((openssl_ver, libressl_ver)),
525 (s, t, hex(n))
526 )
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000527
Antoine Pitrou9d543662010-04-23 23:10:32 +0000528 @support.cpython_only
529 def test_refcycle(self):
530 # Issue #7943: an SSL object doesn't create reference cycles with
531 # itself.
532 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200533 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000534 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800535 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100536 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100537 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000538
Antoine Pitroua468adc2010-09-14 14:43:44 +0000539 def test_wrapped_unconnected(self):
540 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200541 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000542 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200543 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100544 self.assertRaises(OSError, ss.recv, 1)
545 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
546 self.assertRaises(OSError, ss.recvfrom, 1)
547 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
548 self.assertRaises(OSError, ss.send, b'x')
549 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200550 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100551 self.assertRaises(NotImplementedError, ss.sendmsg,
552 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200553 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
554 self.assertRaises(NotImplementedError, ss.recvmsg_into,
555 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000556
Antoine Pitrou40f08742010-04-24 22:04:40 +0000557 def test_timeout(self):
558 # Issue #8524: when creating an SSL socket, the timeout of the
559 # original socket should be retained.
560 for timeout in (None, 0.0, 5.0):
561 s = socket.socket(socket.AF_INET)
562 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200563 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100564 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000565
Christian Heimes2875c602021-04-19 07:27:10 +0200566 @ignore_deprecation
Christian Heimesd0486372016-09-10 23:23:33 +0200567 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000568 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000569 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000570 "certfile must be specified",
571 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000572 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000573 "certfile must be specified for server-side operations",
574 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000575 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000576 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200577 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100578 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
579 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200580 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200581 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000582 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000583 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000584 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200585 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000586 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000587 ssl.wrap_socket(sock,
588 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000589 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200590 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000591 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000592 ssl.wrap_socket(sock,
593 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000594 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000595
Martin Panter3464ea22016-02-01 21:58:11 +0000596 def bad_cert_test(self, certfile):
597 """Check that trying to use the given client certificate fails"""
598 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
599 certfile)
600 sock = socket.socket()
601 self.addCleanup(sock.close)
602 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200603 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200604 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000605
606 def test_empty_cert(self):
607 """Wrapping with an empty cert file"""
608 self.bad_cert_test("nullcert.pem")
609
610 def test_malformed_cert(self):
611 """Wrapping with a badly formatted certificate (syntax error)"""
612 self.bad_cert_test("badcert.pem")
613
614 def test_malformed_key(self):
615 """Wrapping with a badly formatted key (syntax error)"""
616 self.bad_cert_test("badkey.pem")
617
Christian Heimes2875c602021-04-19 07:27:10 +0200618 @ignore_deprecation
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000619 def test_match_hostname(self):
620 def ok(cert, hostname):
621 ssl.match_hostname(cert, hostname)
622 def fail(cert, hostname):
623 self.assertRaises(ssl.CertificateError,
624 ssl.match_hostname, cert, hostname)
625
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100626 # -- Hostname matching --
627
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000628 cert = {'subject': ((('commonName', 'example.com'),),)}
629 ok(cert, 'example.com')
630 ok(cert, 'ExAmple.cOm')
631 fail(cert, 'www.example.com')
632 fail(cert, '.example.com')
633 fail(cert, 'example.org')
634 fail(cert, 'exampleXcom')
635
636 cert = {'subject': ((('commonName', '*.a.com'),),)}
637 ok(cert, 'foo.a.com')
638 fail(cert, 'bar.foo.a.com')
639 fail(cert, 'a.com')
640 fail(cert, 'Xa.com')
641 fail(cert, '.a.com')
642
Mandeep Singhede2ac92017-11-27 04:01:27 +0530643 # only match wildcards when they are the only thing
644 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000645 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530646 fail(cert, 'foo.com')
647 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000648 fail(cert, 'bar.com')
649 fail(cert, 'foo.a.com')
650 fail(cert, 'bar.foo.com')
651
Christian Heimes824f7f32013-08-17 00:54:47 +0200652 # NULL bytes are bad, CVE-2013-4073
653 cert = {'subject': ((('commonName',
654 'null.python.org\x00example.org'),),)}
655 ok(cert, 'null.python.org\x00example.org') # or raise an error?
656 fail(cert, 'example.org')
657 fail(cert, 'null.python.org')
658
Georg Brandl72c98d32013-10-27 07:16:53 +0100659 # error cases with wildcards
660 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
661 fail(cert, 'bar.foo.a.com')
662 fail(cert, 'a.com')
663 fail(cert, 'Xa.com')
664 fail(cert, '.a.com')
665
666 cert = {'subject': ((('commonName', 'a.*.com'),),)}
667 fail(cert, 'a.foo.com')
668 fail(cert, 'a..com')
669 fail(cert, 'a.com')
670
671 # wildcard doesn't match IDNA prefix 'xn--'
672 idna = 'püthon.python.org'.encode("idna").decode("ascii")
673 cert = {'subject': ((('commonName', idna),),)}
674 ok(cert, idna)
675 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
676 fail(cert, idna)
677 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
678 fail(cert, idna)
679
680 # wildcard in first fragment and IDNA A-labels in sequent fragments
681 # are supported.
682 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
683 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530684 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
685 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100686 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
687 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
688
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000689 # Slightly fake real-world example
690 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
691 'subject': ((('commonName', 'linuxfrz.org'),),),
692 'subjectAltName': (('DNS', 'linuxfr.org'),
693 ('DNS', 'linuxfr.com'),
694 ('othername', '<unsupported>'))}
695 ok(cert, 'linuxfr.org')
696 ok(cert, 'linuxfr.com')
697 # Not a "DNS" entry
698 fail(cert, '<unsupported>')
699 # When there is a subjectAltName, commonName isn't used
700 fail(cert, 'linuxfrz.org')
701
702 # A pristine real-world example
703 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
704 'subject': ((('countryName', 'US'),),
705 (('stateOrProvinceName', 'California'),),
706 (('localityName', 'Mountain View'),),
707 (('organizationName', 'Google Inc'),),
708 (('commonName', 'mail.google.com'),))}
709 ok(cert, 'mail.google.com')
710 fail(cert, 'gmail.com')
711 # Only commonName is considered
712 fail(cert, 'California')
713
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100714 # -- IPv4 matching --
715 cert = {'subject': ((('commonName', 'example.com'),),),
716 'subjectAltName': (('DNS', 'example.com'),
717 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200718 ('IP Address', '14.15.16.17'),
719 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100720 ok(cert, '10.11.12.13')
721 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200722 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
723 fail(cert, '127.1')
724 fail(cert, '14.15.16.17 ')
725 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100726 fail(cert, '14.15.16.18')
727 fail(cert, 'example.net')
728
729 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300730 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100731 cert = {'subject': ((('commonName', 'example.com'),),),
732 'subjectAltName': (
733 ('DNS', 'example.com'),
734 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
735 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
736 ok(cert, '2001::cafe')
737 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200738 fail(cert, '2003::baba ')
739 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100740 fail(cert, '2003::bebe')
741 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100742
743 # -- Miscellaneous --
744
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000745 # Neither commonName nor subjectAltName
746 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
747 'subject': ((('countryName', 'US'),),
748 (('stateOrProvinceName', 'California'),),
749 (('localityName', 'Mountain View'),),
750 (('organizationName', 'Google Inc'),))}
751 fail(cert, 'mail.google.com')
752
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200753 # No DNS entry in subjectAltName but a commonName
754 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
755 'subject': ((('countryName', 'US'),),
756 (('stateOrProvinceName', 'California'),),
757 (('localityName', 'Mountain View'),),
758 (('commonName', 'mail.google.com'),)),
759 'subjectAltName': (('othername', 'blabla'), )}
760 ok(cert, 'mail.google.com')
761
762 # No DNS entry subjectAltName and no commonName
763 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
764 'subject': ((('countryName', 'US'),),
765 (('stateOrProvinceName', 'California'),),
766 (('localityName', 'Mountain View'),),
767 (('organizationName', 'Google Inc'),)),
768 'subjectAltName': (('othername', 'blabla'),)}
769 fail(cert, 'google.com')
770
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000771 # Empty cert / no cert
772 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
773 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
774
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200775 # Issue #17980: avoid denials of service by refusing more than one
776 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100777 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
778 with self.assertRaisesRegex(
779 ssl.CertificateError,
780 "partial wildcards in leftmost label are not supported"):
781 ssl.match_hostname(cert, 'axxb.example.com')
782
783 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
784 with self.assertRaisesRegex(
785 ssl.CertificateError,
786 "wildcard can only be present in the leftmost label"):
787 ssl.match_hostname(cert, 'www.sub.example.com')
788
789 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
790 with self.assertRaisesRegex(
791 ssl.CertificateError,
792 "too many wildcards"):
793 ssl.match_hostname(cert, 'axxbxxc.example.com')
794
795 cert = {'subject': ((('commonName', '*'),),)}
796 with self.assertRaisesRegex(
797 ssl.CertificateError,
798 "sole wildcard without additional labels are not support"):
799 ssl.match_hostname(cert, 'host')
800
801 cert = {'subject': ((('commonName', '*.com'),),)}
802 with self.assertRaisesRegex(
803 ssl.CertificateError,
804 r"hostname 'com' doesn't match '\*.com'"):
805 ssl.match_hostname(cert, 'com')
806
807 # extra checks for _inet_paton()
808 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
809 with self.assertRaises(ValueError):
810 ssl._inet_paton(invalid)
811 for ipaddr in ['127.0.0.1', '192.168.0.1']:
812 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300813 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100814 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
815 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200816
Antoine Pitroud5323212010-10-22 18:19:07 +0000817 def test_server_side(self):
818 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200819 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000820 with socket.socket() as sock:
821 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
822 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000823
Antoine Pitroud6494802011-07-21 01:11:30 +0200824 def test_unknown_channel_binding(self):
825 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200826 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200827 c = socket.socket(socket.AF_INET)
828 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200829 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100830 with self.assertRaises(ValueError):
831 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200832 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200833
834 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
835 "'tls-unique' channel binding not available")
836 def test_tls_unique_channel_binding(self):
837 # unconnected should return None for known type
838 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200839 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100840 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200841 # the same for server-side
842 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200843 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100844 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200845
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600846 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200847 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600848 r = repr(ss)
849 with self.assertWarns(ResourceWarning) as cm:
850 ss = None
851 support.gc_collect()
852 self.assertIn(r, str(cm.warning.args[0]))
853
Christian Heimes6d7ad132013-06-09 18:02:55 +0200854 def test_get_default_verify_paths(self):
855 paths = ssl.get_default_verify_paths()
856 self.assertEqual(len(paths), 6)
857 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
858
Hai Shia7f5d932020-08-04 00:41:24 +0800859 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200860 env["SSL_CERT_DIR"] = CAPATH
861 env["SSL_CERT_FILE"] = CERTFILE
862 paths = ssl.get_default_verify_paths()
863 self.assertEqual(paths.cafile, CERTFILE)
864 self.assertEqual(paths.capath, CAPATH)
865
Christian Heimes44109d72013-11-22 01:51:30 +0100866 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
867 def test_enum_certificates(self):
868 self.assertTrue(ssl.enum_certificates("CA"))
869 self.assertTrue(ssl.enum_certificates("ROOT"))
870
871 self.assertRaises(TypeError, ssl.enum_certificates)
872 self.assertRaises(WindowsError, ssl.enum_certificates, "")
873
Christian Heimesc2d65e12013-11-22 16:13:55 +0100874 trust_oids = set()
875 for storename in ("CA", "ROOT"):
876 store = ssl.enum_certificates(storename)
877 self.assertIsInstance(store, list)
878 for element in store:
879 self.assertIsInstance(element, tuple)
880 self.assertEqual(len(element), 3)
881 cert, enc, trust = element
882 self.assertIsInstance(cert, bytes)
883 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200884 self.assertIsInstance(trust, (frozenset, set, bool))
885 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100886 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100887
888 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100889 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200890
Christian Heimes46bebee2013-06-09 19:03:31 +0200891 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100892 def test_enum_crls(self):
893 self.assertTrue(ssl.enum_crls("CA"))
894 self.assertRaises(TypeError, ssl.enum_crls)
895 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200896
Christian Heimes44109d72013-11-22 01:51:30 +0100897 crls = ssl.enum_crls("CA")
898 self.assertIsInstance(crls, list)
899 for element in crls:
900 self.assertIsInstance(element, tuple)
901 self.assertEqual(len(element), 2)
902 self.assertIsInstance(element[0], bytes)
903 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200904
Christian Heimes46bebee2013-06-09 19:03:31 +0200905
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100906 def test_asn1object(self):
907 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
908 '1.3.6.1.5.5.7.3.1')
909
910 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
911 self.assertEqual(val, expected)
912 self.assertEqual(val.nid, 129)
913 self.assertEqual(val.shortname, 'serverAuth')
914 self.assertEqual(val.longname, 'TLS Web Server Authentication')
915 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
916 self.assertIsInstance(val, ssl._ASN1Object)
917 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
918
919 val = ssl._ASN1Object.fromnid(129)
920 self.assertEqual(val, expected)
921 self.assertIsInstance(val, ssl._ASN1Object)
922 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100923 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
924 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100925 for i in range(1000):
926 try:
927 obj = ssl._ASN1Object.fromnid(i)
928 except ValueError:
929 pass
930 else:
931 self.assertIsInstance(obj.nid, int)
932 self.assertIsInstance(obj.shortname, str)
933 self.assertIsInstance(obj.longname, str)
934 self.assertIsInstance(obj.oid, (str, type(None)))
935
936 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
937 self.assertEqual(val, expected)
938 self.assertIsInstance(val, ssl._ASN1Object)
939 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
940 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
941 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100942 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
943 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100944
Christian Heimes72d28502013-11-23 13:56:58 +0100945 def test_purpose_enum(self):
946 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
947 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
948 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
949 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
950 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
951 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
952 '1.3.6.1.5.5.7.3.1')
953
954 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
955 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
956 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
957 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
958 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
959 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
960 '1.3.6.1.5.5.7.3.2')
961
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100962 def test_unsupported_dtls(self):
963 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
964 self.addCleanup(s.close)
965 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +0200966 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100967 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +0200968 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100969 with self.assertRaises(NotImplementedError) as cx:
970 ctx.wrap_socket(s)
971 self.assertEqual(str(cx.exception), "only stream sockets are supported")
972
Antoine Pitrouc695c952014-04-28 20:57:36 +0200973 def cert_time_ok(self, timestring, timestamp):
974 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
975
976 def cert_time_fail(self, timestring):
977 with self.assertRaises(ValueError):
978 ssl.cert_time_to_seconds(timestring)
979
980 @unittest.skipUnless(utc_offset(),
981 'local time needs to be different from UTC')
982 def test_cert_time_to_seconds_timezone(self):
983 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
984 # results if local timezone is not UTC
985 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
986 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
987
988 def test_cert_time_to_seconds(self):
989 timestring = "Jan 5 09:34:43 2018 GMT"
990 ts = 1515144883.0
991 self.cert_time_ok(timestring, ts)
992 # accept keyword parameter, assert its name
993 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
994 # accept both %e and %d (space or zero generated by strftime)
995 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
996 # case-insensitive
997 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
998 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
999 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1000 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1001 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1002 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1003 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1004 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1005
1006 newyear_ts = 1230768000.0
1007 # leap seconds
1008 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1009 # same timestamp
1010 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1011
1012 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1013 # allow 60th second (even if it is not a leap second)
1014 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1015 # allow 2nd leap second for compatibility with time.strptime()
1016 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1017 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1018
Mike53f7a7c2017-12-14 14:04:53 +03001019 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001020 # 99991231235959Z (rfc 5280)
1021 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1022
1023 @support.run_with_locale('LC_ALL', '')
1024 def test_cert_time_to_seconds_locale(self):
1025 # `cert_time_to_seconds()` should be locale independent
1026
1027 def local_february_name():
1028 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1029
1030 if local_february_name().lower() == 'feb':
1031 self.skipTest("locale-specific month name needs to be "
1032 "different from C locale")
1033
1034 # locale-independent
1035 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1036 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1037
Martin Panter3840b2a2016-03-27 01:53:46 +00001038 def test_connect_ex_error(self):
1039 server = socket.socket(socket.AF_INET)
1040 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001041 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001042 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001043 cert_reqs=ssl.CERT_REQUIRED)
1044 self.addCleanup(s.close)
1045 rc = s.connect_ex((HOST, port))
1046 # Issue #19919: Windows machines or VMs hosted on Windows
1047 # machines sometimes return EWOULDBLOCK.
1048 errors = (
1049 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1050 errno.EWOULDBLOCK,
1051 )
1052 self.assertIn(rc, errors)
1053
Christian Heimes89d15502021-04-19 06:55:30 +02001054 def test_read_write_zero(self):
1055 # empty reads and writes now work, bpo-42854, bpo-31711
1056 client_context, server_context, hostname = testing_context()
1057 server = ThreadedEchoServer(context=server_context)
1058 with server:
1059 with client_context.wrap_socket(socket.socket(),
1060 server_hostname=hostname) as s:
1061 s.connect((HOST, server.port))
1062 self.assertEqual(s.recv(0), b"")
1063 self.assertEqual(s.send(b""), 0)
1064
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001065
Antoine Pitrou152efa22010-05-16 18:19:27 +00001066class ContextTests(unittest.TestCase):
1067
1068 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001069 for protocol in PROTOCOLS:
Christian Heimes2875c602021-04-19 07:27:10 +02001070 with warnings_helper.check_warnings():
1071 ctx = ssl.SSLContext(protocol)
1072 self.assertEqual(ctx.protocol, protocol)
1073 with warnings_helper.check_warnings():
1074 ctx = ssl.SSLContext()
Christian Heimes598894f2016-09-05 23:19:05 +02001075 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001076 self.assertRaises(ValueError, ssl.SSLContext, -1)
1077 self.assertRaises(ValueError, ssl.SSLContext, 42)
1078
Antoine Pitrou152efa22010-05-16 18:19:27 +00001079 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001080 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001081 ctx.set_ciphers("ALL")
1082 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001083 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001084 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001085
Christian Heimes892d66e2018-01-29 14:10:18 +01001086 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1087 "Test applies only to Python default ciphers")
1088 def test_python_ciphers(self):
1089 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1090 ciphers = ctx.get_ciphers()
1091 for suite in ciphers:
1092 name = suite['name']
1093 self.assertNotIn("PSK", name)
1094 self.assertNotIn("SRP", name)
1095 self.assertNotIn("MD5", name)
1096 self.assertNotIn("RC4", name)
1097 self.assertNotIn("3DES", name)
1098
Christian Heimes25bfcd52016-09-06 00:04:45 +02001099 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001100 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001101 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001102 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001103 self.assertIn('AES256-GCM-SHA384', names)
1104 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001105
Antoine Pitroub5218772010-05-21 09:56:06 +00001106 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001107 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001108 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001109 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001110 # SSLContext also enables these by default
1111 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001112 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
Christian Heimes6f37ebc2021-04-09 17:59:21 +02001113 OP_ENABLE_MIDDLEBOX_COMPAT |
1114 OP_IGNORE_UNEXPECTED_EOF)
Christian Heimes598894f2016-09-05 23:19:05 +02001115 self.assertEqual(default, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001116 with warnings_helper.check_warnings():
1117 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001118 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Christian Heimes2875c602021-04-19 07:27:10 +02001119 with warnings_helper.check_warnings():
1120 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
Christian Heimes39258d32021-04-17 11:36:35 +02001121 self.assertEqual(default, ctx.options)
1122 ctx.options = 0
1123 # Ubuntu has OP_NO_SSLv3 forced on by default
1124 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001125
Christian Heimesa170fa12017-09-15 20:27:30 +02001126 def test_verify_mode_protocol(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001127 with warnings_helper.check_warnings():
1128 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001129 # Default value
1130 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1131 ctx.verify_mode = ssl.CERT_OPTIONAL
1132 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1133 ctx.verify_mode = ssl.CERT_REQUIRED
1134 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1135 ctx.verify_mode = ssl.CERT_NONE
1136 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1137 with self.assertRaises(TypeError):
1138 ctx.verify_mode = None
1139 with self.assertRaises(ValueError):
1140 ctx.verify_mode = 42
1141
Christian Heimesa170fa12017-09-15 20:27:30 +02001142 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1143 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1144 self.assertFalse(ctx.check_hostname)
1145
1146 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1147 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1148 self.assertTrue(ctx.check_hostname)
1149
Christian Heimes61d478c2018-01-27 15:51:38 +01001150 def test_hostname_checks_common_name(self):
1151 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1152 self.assertTrue(ctx.hostname_checks_common_name)
1153 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1154 ctx.hostname_checks_common_name = True
1155 self.assertTrue(ctx.hostname_checks_common_name)
1156 ctx.hostname_checks_common_name = False
1157 self.assertFalse(ctx.hostname_checks_common_name)
1158 ctx.hostname_checks_common_name = True
1159 self.assertTrue(ctx.hostname_checks_common_name)
1160 else:
1161 with self.assertRaises(AttributeError):
1162 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001163
Christian Heimes2875c602021-04-19 07:27:10 +02001164 @ignore_deprecation
Christian Heimes698dde12018-02-27 11:54:43 +01001165 def test_min_max_version(self):
1166 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001167 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1168 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001169 minimum_range = {
1170 # stock OpenSSL
1171 ssl.TLSVersion.MINIMUM_SUPPORTED,
1172 # Fedora 29 uses TLS 1.0 by default
1173 ssl.TLSVersion.TLSv1,
1174 # RHEL 8 uses TLS 1.2 by default
1175 ssl.TLSVersion.TLSv1_2
1176 }
torsava34864d12019-12-02 17:15:42 +01001177 maximum_range = {
1178 # stock OpenSSL
1179 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1180 # Fedora 32 uses TLS 1.3 by default
1181 ssl.TLSVersion.TLSv1_3
1182 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001183
Christian Heimes34de2d32019-01-18 16:09:30 +01001184 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001185 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001186 )
torsava34864d12019-12-02 17:15:42 +01001187 self.assertIn(
1188 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001189 )
1190
1191 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1192 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1193 self.assertEqual(
1194 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1195 )
1196 self.assertEqual(
1197 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1198 )
1199
1200 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1201 ctx.maximum_version = ssl.TLSVersion.TLSv1
1202 self.assertEqual(
1203 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1204 )
1205 self.assertEqual(
1206 ctx.maximum_version, ssl.TLSVersion.TLSv1
1207 )
1208
1209 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1210 self.assertEqual(
1211 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1212 )
1213
1214 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1215 self.assertIn(
1216 ctx.maximum_version,
1217 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1218 )
1219
1220 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1221 self.assertIn(
1222 ctx.minimum_version,
1223 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1224 )
1225
1226 with self.assertRaises(ValueError):
1227 ctx.minimum_version = 42
1228
1229 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1230
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001231 self.assertIn(
1232 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001233 )
1234 self.assertEqual(
1235 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1236 )
1237 with self.assertRaises(ValueError):
1238 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1239 with self.assertRaises(ValueError):
1240 ctx.maximum_version = ssl.TLSVersion.TLSv1
1241
1242
matthewhughes9348e836bb2020-07-17 09:59:15 +01001243 @unittest.skipUnless(
1244 hasattr(ssl.SSLContext, 'security_level'),
1245 "requires OpenSSL >= 1.1.0"
1246 )
1247 def test_security_level(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001248 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
matthewhughes9348e836bb2020-07-17 09:59:15 +01001249 # The default security callback allows for levels between 0-5
1250 # with OpenSSL defaulting to 1, however some vendors override the
1251 # default value (e.g. Debian defaults to 2)
1252 security_level_range = {
1253 0,
1254 1, # OpenSSL default
1255 2, # Debian
1256 3,
1257 4,
1258 5,
1259 }
1260 self.assertIn(ctx.security_level, security_level_range)
1261
Christian Heimes22587792013-11-21 23:56:13 +01001262 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001263 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001264 # default value
1265 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1266 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001267 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1268 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1269 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1270 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1271 ctx.verify_flags = ssl.VERIFY_DEFAULT
1272 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
Chris Burre0b4aa02021-03-18 09:24:01 +01001273 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1274 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001275 # supports any value
1276 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1277 self.assertEqual(ctx.verify_flags,
1278 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1279 with self.assertRaises(TypeError):
1280 ctx.verify_flags = None
1281
Antoine Pitrou152efa22010-05-16 18:19:27 +00001282 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001283 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001284 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001285 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001286 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1287 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001288 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001289 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001290 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001291 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001292 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001293 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001294 ctx.load_cert_chain(EMPTYCERT)
1295 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001296 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001297 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1298 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1299 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001300 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001301 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001302 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001303 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001304 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001305 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1306 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001307 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001308 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001309 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001310 # Password protected key and cert
1311 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1312 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1313 ctx.load_cert_chain(CERTFILE_PROTECTED,
1314 password=bytearray(KEY_PASSWORD.encode()))
1315 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1316 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1317 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1318 bytearray(KEY_PASSWORD.encode()))
1319 with self.assertRaisesRegex(TypeError, "should be a string"):
1320 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1321 with self.assertRaises(ssl.SSLError):
1322 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1323 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1324 # openssl has a fixed limit on the password buffer.
1325 # PEM_BUFSIZE is generally set to 1kb.
1326 # Return a string larger than this.
1327 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1328 # Password callback
1329 def getpass_unicode():
1330 return KEY_PASSWORD
1331 def getpass_bytes():
1332 return KEY_PASSWORD.encode()
1333 def getpass_bytearray():
1334 return bytearray(KEY_PASSWORD.encode())
1335 def getpass_badpass():
1336 return "badpass"
1337 def getpass_huge():
1338 return b'a' * (1024 * 1024)
1339 def getpass_bad_type():
1340 return 9
1341 def getpass_exception():
1342 raise Exception('getpass error')
1343 class GetPassCallable:
1344 def __call__(self):
1345 return KEY_PASSWORD
1346 def getpass(self):
1347 return KEY_PASSWORD
1348 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1349 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1350 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1351 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1352 ctx.load_cert_chain(CERTFILE_PROTECTED,
1353 password=GetPassCallable().getpass)
1354 with self.assertRaises(ssl.SSLError):
1355 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1356 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1357 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1358 with self.assertRaisesRegex(TypeError, "must return a string"):
1359 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1360 with self.assertRaisesRegex(Exception, "getpass error"):
1361 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1362 # Make sure the password function isn't called if it isn't needed
1363 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001364
1365 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001366 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001367 ctx.load_verify_locations(CERTFILE)
1368 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1369 ctx.load_verify_locations(BYTES_CERTFILE)
1370 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1371 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001372 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001373 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001374 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001375 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001376 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001377 ctx.load_verify_locations(BADCERT)
1378 ctx.load_verify_locations(CERTFILE, CAPATH)
1379 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1380
Victor Stinner80f75e62011-01-29 11:31:20 +00001381 # Issue #10989: crash if the second argument type is invalid
1382 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1383
Christian Heimesefff7062013-11-21 03:35:02 +01001384 def test_load_verify_cadata(self):
1385 # test cadata
1386 with open(CAFILE_CACERT) as f:
1387 cacert_pem = f.read()
1388 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1389 with open(CAFILE_NEURONIO) as f:
1390 neuronio_pem = f.read()
1391 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1392
1393 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001394 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001395 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1396 ctx.load_verify_locations(cadata=cacert_pem)
1397 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1398 ctx.load_verify_locations(cadata=neuronio_pem)
1399 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1400 # cert already in hash table
1401 ctx.load_verify_locations(cadata=neuronio_pem)
1402 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1403
1404 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001405 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001406 combined = "\n".join((cacert_pem, neuronio_pem))
1407 ctx.load_verify_locations(cadata=combined)
1408 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1409
1410 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001411 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001412 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1413 neuronio_pem, "tail"]
1414 ctx.load_verify_locations(cadata="\n".join(combined))
1415 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1416
1417 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001418 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001419 ctx.load_verify_locations(cadata=cacert_der)
1420 ctx.load_verify_locations(cadata=neuronio_der)
1421 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1422 # cert already in hash table
1423 ctx.load_verify_locations(cadata=cacert_der)
1424 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1425
1426 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001427 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001428 combined = b"".join((cacert_der, neuronio_der))
1429 ctx.load_verify_locations(cadata=combined)
1430 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1431
1432 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001433 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001434 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1435
1436 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1437 ctx.load_verify_locations(cadata="broken")
1438 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1439 ctx.load_verify_locations(cadata=b"broken")
1440
1441
Paul Monsonf3550692019-06-19 13:09:54 -07001442 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001443 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001444 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001445 ctx.load_dh_params(DHFILE)
1446 if os.name != 'nt':
1447 ctx.load_dh_params(BYTES_DHFILE)
1448 self.assertRaises(TypeError, ctx.load_dh_params)
1449 self.assertRaises(TypeError, ctx.load_dh_params, None)
1450 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001451 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001452 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001453 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001454 ctx.load_dh_params(CERTFILE)
1455
Antoine Pitroub0182c82010-10-12 20:09:02 +00001456 def test_session_stats(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001457 for proto in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
Antoine Pitroub0182c82010-10-12 20:09:02 +00001458 ctx = ssl.SSLContext(proto)
1459 self.assertEqual(ctx.session_stats(), {
1460 'number': 0,
1461 'connect': 0,
1462 'connect_good': 0,
1463 'connect_renegotiate': 0,
1464 'accept': 0,
1465 'accept_good': 0,
1466 'accept_renegotiate': 0,
1467 'hits': 0,
1468 'misses': 0,
1469 'timeouts': 0,
1470 'cache_full': 0,
1471 })
1472
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001473 def test_set_default_verify_paths(self):
1474 # There's not much we can do to test that it acts as expected,
1475 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001476 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001477 ctx.set_default_verify_paths()
1478
Antoine Pitrou501da612011-12-21 09:27:41 +01001479 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001480 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001481 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001482 ctx.set_ecdh_curve("prime256v1")
1483 ctx.set_ecdh_curve(b"prime256v1")
1484 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1485 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1486 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1487 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1488
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001489 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001490 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001491
1492 # set_servername_callback expects a callable, or None
1493 self.assertRaises(TypeError, ctx.set_servername_callback)
1494 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1495 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1496 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1497
1498 def dummycallback(sock, servername, ctx):
1499 pass
1500 ctx.set_servername_callback(None)
1501 ctx.set_servername_callback(dummycallback)
1502
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001503 def test_sni_callback_refcycle(self):
1504 # Reference cycles through the servername callback are detected
1505 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001506 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001507 def dummycallback(sock, servername, ctx, cycle=ctx):
1508 pass
1509 ctx.set_servername_callback(dummycallback)
1510 wr = weakref.ref(ctx)
1511 del ctx, dummycallback
1512 gc.collect()
1513 self.assertIs(wr(), None)
1514
Christian Heimes9a5395a2013-06-17 15:44:12 +02001515 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001516 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001517 self.assertEqual(ctx.cert_store_stats(),
1518 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1519 ctx.load_cert_chain(CERTFILE)
1520 self.assertEqual(ctx.cert_store_stats(),
1521 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1522 ctx.load_verify_locations(CERTFILE)
1523 self.assertEqual(ctx.cert_store_stats(),
1524 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001525 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001526 self.assertEqual(ctx.cert_store_stats(),
1527 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1528
1529 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001530 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001531 self.assertEqual(ctx.get_ca_certs(), [])
1532 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1533 ctx.load_verify_locations(CERTFILE)
1534 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001535 # but CAFILE_CACERT is a CA cert
1536 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001537 self.assertEqual(ctx.get_ca_certs(),
1538 [{'issuer': ((('organizationName', 'Root CA'),),
1539 (('organizationalUnitName', 'http://www.cacert.org'),),
1540 (('commonName', 'CA Cert Signing Authority'),),
1541 (('emailAddress', 'support@cacert.org'),)),
Christian Heimesd37b74f2021-04-19 08:31:29 +02001542 'notAfter': 'Mar 29 12:29:49 2033 GMT',
1543 'notBefore': 'Mar 30 12:29:49 2003 GMT',
Christian Heimes9a5395a2013-06-17 15:44:12 +02001544 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001545 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001546 'subject': ((('organizationName', 'Root CA'),),
1547 (('organizationalUnitName', 'http://www.cacert.org'),),
1548 (('commonName', 'CA Cert Signing Authority'),),
1549 (('emailAddress', 'support@cacert.org'),)),
1550 'version': 3}])
1551
Martin Panterb55f8b72016-01-14 12:53:56 +00001552 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001553 pem = f.read()
1554 der = ssl.PEM_cert_to_DER_cert(pem)
1555 self.assertEqual(ctx.get_ca_certs(True), [der])
1556
Christian Heimes72d28502013-11-23 13:56:58 +01001557 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001558 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001559 ctx.load_default_certs()
1560
Christian Heimesa170fa12017-09-15 20:27:30 +02001561 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001562 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1563 ctx.load_default_certs()
1564
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(ssl.Purpose.CLIENT_AUTH)
1567
Christian Heimesa170fa12017-09-15 20:27:30 +02001568 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001569 self.assertRaises(TypeError, ctx.load_default_certs, None)
1570 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1571
Benjamin Peterson91244e02014-10-03 18:17:15 -04001572 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001573 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001574 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001575 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001576 env["SSL_CERT_DIR"] = CAPATH
1577 env["SSL_CERT_FILE"] = CERTFILE
1578 ctx.load_default_certs()
1579 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1580
Benjamin Peterson91244e02014-10-03 18:17:15 -04001581 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001582 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001583 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001584 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001585 ctx.load_default_certs()
1586 stats = ctx.cert_store_stats()
1587
Christian Heimesa170fa12017-09-15 20:27:30 +02001588 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001589 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001590 env["SSL_CERT_DIR"] = CAPATH
1591 env["SSL_CERT_FILE"] = CERTFILE
1592 ctx.load_default_certs()
1593 stats["x509"] += 1
1594 self.assertEqual(ctx.cert_store_stats(), stats)
1595
Christian Heimes358cfd42016-09-10 22:43:48 +02001596 def _assert_context_options(self, ctx):
1597 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1598 if OP_NO_COMPRESSION != 0:
1599 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1600 OP_NO_COMPRESSION)
1601 if OP_SINGLE_DH_USE != 0:
1602 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1603 OP_SINGLE_DH_USE)
1604 if OP_SINGLE_ECDH_USE != 0:
1605 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1606 OP_SINGLE_ECDH_USE)
1607 if OP_CIPHER_SERVER_PREFERENCE != 0:
1608 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1609 OP_CIPHER_SERVER_PREFERENCE)
1610
Christian Heimes4c05b472013-11-23 15:58:30 +01001611 def test_create_default_context(self):
1612 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001613
Christian Heimes2875c602021-04-19 07:27:10 +02001614 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001615 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001616 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001617 self._assert_context_options(ctx)
1618
Christian Heimes4c05b472013-11-23 15:58:30 +01001619 with open(SIGNING_CA) as f:
1620 cadata = f.read()
1621 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1622 cadata=cadata)
Christian Heimes2875c602021-04-19 07:27:10 +02001623 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes4c05b472013-11-23 15:58:30 +01001624 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001625 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001626
1627 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001628 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes4c05b472013-11-23 15:58:30 +01001629 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001630 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001631
Christian Heimes2875c602021-04-19 07:27:10 +02001632
1633
Christian Heimes67986f92013-11-23 22:43:47 +01001634 def test__create_stdlib_context(self):
1635 ctx = ssl._create_stdlib_context()
Christian Heimes2875c602021-04-19 07:27:10 +02001636 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes67986f92013-11-23 22:43:47 +01001637 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001638 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001639 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001640
Christian Heimes2875c602021-04-19 07:27:10 +02001641 with warnings_helper.check_warnings():
1642 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
Christian Heimes67986f92013-11-23 22:43:47 +01001643 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1644 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001645 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001646
Christian Heimes2875c602021-04-19 07:27:10 +02001647 with warnings_helper.check_warnings():
1648 ctx = ssl._create_stdlib_context(
1649 ssl.PROTOCOL_TLSv1_2,
1650 cert_reqs=ssl.CERT_REQUIRED,
1651 check_hostname=True
1652 )
1653 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
Christian Heimes67986f92013-11-23 22:43:47 +01001654 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001655 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001656 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001657
1658 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimes2875c602021-04-19 07:27:10 +02001659 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Christian Heimes67986f92013-11-23 22:43:47 +01001660 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001661 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001662
Christian Heimes1aa9a752013-12-02 02:41:19 +01001663 def test_check_hostname(self):
Christian Heimes2875c602021-04-19 07:27:10 +02001664 with warnings_helper.check_warnings():
1665 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001666 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001667 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001668
Christian Heimese82c0342017-09-15 20:29:57 +02001669 # Auto set CERT_REQUIRED
1670 ctx.check_hostname = True
1671 self.assertTrue(ctx.check_hostname)
1672 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1673 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001674 ctx.verify_mode = ssl.CERT_REQUIRED
1675 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001676 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001677
Christian Heimese82c0342017-09-15 20:29:57 +02001678 # Changing verify_mode does not affect check_hostname
1679 ctx.check_hostname = False
1680 ctx.verify_mode = ssl.CERT_NONE
1681 ctx.check_hostname = False
1682 self.assertFalse(ctx.check_hostname)
1683 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1684 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001685 ctx.check_hostname = True
1686 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001687 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1688
1689 ctx.check_hostname = False
1690 ctx.verify_mode = ssl.CERT_OPTIONAL
1691 ctx.check_hostname = False
1692 self.assertFalse(ctx.check_hostname)
1693 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1694 # keep CERT_OPTIONAL
1695 ctx.check_hostname = True
1696 self.assertTrue(ctx.check_hostname)
1697 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001698
1699 # Cannot set CERT_NONE with check_hostname enabled
1700 with self.assertRaises(ValueError):
1701 ctx.verify_mode = ssl.CERT_NONE
1702 ctx.check_hostname = False
1703 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001704 ctx.verify_mode = ssl.CERT_NONE
1705 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001706
Christian Heimes5fe668c2016-09-12 00:01:11 +02001707 def test_context_client_server(self):
1708 # PROTOCOL_TLS_CLIENT has sane defaults
1709 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1710 self.assertTrue(ctx.check_hostname)
1711 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1712
1713 # PROTOCOL_TLS_SERVER has different but also sane defaults
1714 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1715 self.assertFalse(ctx.check_hostname)
1716 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1717
Christian Heimes4df60f12017-09-15 20:26:05 +02001718 def test_context_custom_class(self):
1719 class MySSLSocket(ssl.SSLSocket):
1720 pass
1721
1722 class MySSLObject(ssl.SSLObject):
1723 pass
1724
1725 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1726 ctx.sslsocket_class = MySSLSocket
1727 ctx.sslobject_class = MySSLObject
1728
1729 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1730 self.assertIsInstance(sock, MySSLSocket)
1731 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1732 self.assertIsInstance(obj, MySSLObject)
1733
Christian Heimes78c7d522019-06-03 21:00:10 +02001734 def test_num_tickest(self):
1735 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1736 self.assertEqual(ctx.num_tickets, 2)
1737 ctx.num_tickets = 1
1738 self.assertEqual(ctx.num_tickets, 1)
1739 ctx.num_tickets = 0
1740 self.assertEqual(ctx.num_tickets, 0)
1741 with self.assertRaises(ValueError):
1742 ctx.num_tickets = -1
1743 with self.assertRaises(TypeError):
1744 ctx.num_tickets = None
1745
1746 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1747 self.assertEqual(ctx.num_tickets, 2)
1748 with self.assertRaises(ValueError):
1749 ctx.num_tickets = 1
1750
Antoine Pitrou152efa22010-05-16 18:19:27 +00001751
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001752class SSLErrorTests(unittest.TestCase):
1753
1754 def test_str(self):
1755 # The str() of a SSLError doesn't include the errno
1756 e = ssl.SSLError(1, "foo")
1757 self.assertEqual(str(e), "foo")
1758 self.assertEqual(e.errno, 1)
1759 # Same for a subclass
1760 e = ssl.SSLZeroReturnError(1, "foo")
1761 self.assertEqual(str(e), "foo")
1762 self.assertEqual(e.errno, 1)
1763
Paul Monsonf3550692019-06-19 13:09:54 -07001764 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001765 def test_lib_reason(self):
1766 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001767 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001768 with self.assertRaises(ssl.SSLError) as cm:
1769 ctx.load_dh_params(CERTFILE)
1770 self.assertEqual(cm.exception.library, 'PEM')
1771 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1772 s = str(cm.exception)
1773 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1774
1775 def test_subclass(self):
1776 # Check that the appropriate SSLError subclass is raised
1777 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001778 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1779 ctx.check_hostname = False
1780 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001781 with socket.create_server(("127.0.0.1", 0)) as s:
1782 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001783 c.setblocking(False)
1784 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001785 with self.assertRaises(ssl.SSLWantReadError) as cm:
1786 c.do_handshake()
1787 s = str(cm.exception)
1788 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1789 # For compatibility
1790 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1791
1792
Christian Heimes61d478c2018-01-27 15:51:38 +01001793 def test_bad_server_hostname(self):
1794 ctx = ssl.create_default_context()
1795 with self.assertRaises(ValueError):
1796 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1797 server_hostname="")
1798 with self.assertRaises(ValueError):
1799 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1800 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001801 with self.assertRaises(TypeError):
1802 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1803 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001804
1805
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001806class MemoryBIOTests(unittest.TestCase):
1807
1808 def test_read_write(self):
1809 bio = ssl.MemoryBIO()
1810 bio.write(b'foo')
1811 self.assertEqual(bio.read(), b'foo')
1812 self.assertEqual(bio.read(), b'')
1813 bio.write(b'foo')
1814 bio.write(b'bar')
1815 self.assertEqual(bio.read(), b'foobar')
1816 self.assertEqual(bio.read(), b'')
1817 bio.write(b'baz')
1818 self.assertEqual(bio.read(2), b'ba')
1819 self.assertEqual(bio.read(1), b'z')
1820 self.assertEqual(bio.read(1), b'')
1821
1822 def test_eof(self):
1823 bio = ssl.MemoryBIO()
1824 self.assertFalse(bio.eof)
1825 self.assertEqual(bio.read(), b'')
1826 self.assertFalse(bio.eof)
1827 bio.write(b'foo')
1828 self.assertFalse(bio.eof)
1829 bio.write_eof()
1830 self.assertFalse(bio.eof)
1831 self.assertEqual(bio.read(2), b'fo')
1832 self.assertFalse(bio.eof)
1833 self.assertEqual(bio.read(1), b'o')
1834 self.assertTrue(bio.eof)
1835 self.assertEqual(bio.read(), b'')
1836 self.assertTrue(bio.eof)
1837
1838 def test_pending(self):
1839 bio = ssl.MemoryBIO()
1840 self.assertEqual(bio.pending, 0)
1841 bio.write(b'foo')
1842 self.assertEqual(bio.pending, 3)
1843 for i in range(3):
1844 bio.read(1)
1845 self.assertEqual(bio.pending, 3-i-1)
1846 for i in range(3):
1847 bio.write(b'x')
1848 self.assertEqual(bio.pending, i+1)
1849 bio.read()
1850 self.assertEqual(bio.pending, 0)
1851
1852 def test_buffer_types(self):
1853 bio = ssl.MemoryBIO()
1854 bio.write(b'foo')
1855 self.assertEqual(bio.read(), b'foo')
1856 bio.write(bytearray(b'bar'))
1857 self.assertEqual(bio.read(), b'bar')
1858 bio.write(memoryview(b'baz'))
1859 self.assertEqual(bio.read(), b'baz')
1860
1861 def test_error_types(self):
1862 bio = ssl.MemoryBIO()
1863 self.assertRaises(TypeError, bio.write, 'foo')
1864 self.assertRaises(TypeError, bio.write, None)
1865 self.assertRaises(TypeError, bio.write, True)
1866 self.assertRaises(TypeError, bio.write, 1)
1867
1868
Christian Heimes9d50ab52018-02-27 10:17:30 +01001869class SSLObjectTests(unittest.TestCase):
1870 def test_private_init(self):
1871 bio = ssl.MemoryBIO()
1872 with self.assertRaisesRegex(TypeError, "public constructor"):
1873 ssl.SSLObject(bio, bio)
1874
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001875 def test_unwrap(self):
1876 client_ctx, server_ctx, hostname = testing_context()
1877 c_in = ssl.MemoryBIO()
1878 c_out = ssl.MemoryBIO()
1879 s_in = ssl.MemoryBIO()
1880 s_out = ssl.MemoryBIO()
1881 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1882 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1883
1884 # Loop on the handshake for a bit to get it settled
1885 for _ in range(5):
1886 try:
1887 client.do_handshake()
1888 except ssl.SSLWantReadError:
1889 pass
1890 if c_out.pending:
1891 s_in.write(c_out.read())
1892 try:
1893 server.do_handshake()
1894 except ssl.SSLWantReadError:
1895 pass
1896 if s_out.pending:
1897 c_in.write(s_out.read())
1898 # Now the handshakes should be complete (don't raise WantReadError)
1899 client.do_handshake()
1900 server.do_handshake()
1901
1902 # Now if we unwrap one side unilaterally, it should send close-notify
1903 # and raise WantReadError:
1904 with self.assertRaises(ssl.SSLWantReadError):
1905 client.unwrap()
1906
1907 # But server.unwrap() does not raise, because it reads the client's
1908 # close-notify:
1909 s_in.write(c_out.read())
1910 server.unwrap()
1911
1912 # And now that the client gets the server's close-notify, it doesn't
1913 # raise either.
1914 c_in.write(s_out.read())
1915 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001916
Martin Panter3840b2a2016-03-27 01:53:46 +00001917class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001918 """Tests that connect to a simple server running in the background"""
1919
1920 def setUp(self):
juhovh49fdf112021-04-18 21:11:48 +10001921 self.server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1922 self.server_context.load_cert_chain(SIGNED_CERTFILE)
1923 server = ThreadedEchoServer(context=self.server_context)
Martin Panter3840b2a2016-03-27 01:53:46 +00001924 self.server_addr = (HOST, server.port)
1925 server.__enter__()
1926 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001927
Antoine Pitrou480a1242010-04-28 21:37:09 +00001928 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001929 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001930 cert_reqs=ssl.CERT_NONE) as s:
1931 s.connect(self.server_addr)
1932 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001933 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001934
Martin Panter3840b2a2016-03-27 01:53:46 +00001935 # this should succeed because we specify the root cert
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_REQUIRED,
1938 ca_certs=SIGNING_CA) as s:
1939 s.connect(self.server_addr)
1940 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001941 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001942
Martin Panter3840b2a2016-03-27 01:53:46 +00001943 def test_connect_fail(self):
1944 # This should fail because we have no verification certs. Connection
1945 # failure crashes ThreadedEchoServer, so run this in an independent
1946 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001947 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001948 cert_reqs=ssl.CERT_REQUIRED)
1949 self.addCleanup(s.close)
1950 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1951 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001952
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001953 def test_connect_ex(self):
1954 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02001955 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001956 cert_reqs=ssl.CERT_REQUIRED,
1957 ca_certs=SIGNING_CA)
1958 self.addCleanup(s.close)
1959 self.assertEqual(0, s.connect_ex(self.server_addr))
1960 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001961
1962 def test_non_blocking_connect_ex(self):
1963 # Issue #11326: non-blocking connect_ex() should allow handshake
1964 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02001965 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001966 cert_reqs=ssl.CERT_REQUIRED,
1967 ca_certs=SIGNING_CA,
1968 do_handshake_on_connect=False)
1969 self.addCleanup(s.close)
1970 s.setblocking(False)
1971 rc = s.connect_ex(self.server_addr)
1972 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1973 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
1974 # Wait for connect to finish
1975 select.select([], [s], [], 5.0)
1976 # Non-blocking handshake
1977 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001978 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00001979 s.do_handshake()
1980 break
1981 except ssl.SSLWantReadError:
1982 select.select([s], [], [], 5.0)
1983 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001984 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00001985 # SSL established
1986 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001987
Antoine Pitrou152efa22010-05-16 18:19:27 +00001988 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001989 # Same as test_connect, but with a separately created context
Christian Heimes2875c602021-04-19 07:27:10 +02001990 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1991 ctx.check_hostname = False
1992 ctx.verify_mode = ssl.CERT_NONE
Martin Panter3840b2a2016-03-27 01:53:46 +00001993 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1994 s.connect(self.server_addr)
1995 self.assertEqual({}, s.getpeercert())
1996 # Same with a server hostname
1997 with ctx.wrap_socket(socket.socket(socket.AF_INET),
1998 server_hostname="dummy") as s:
1999 s.connect(self.server_addr)
2000 ctx.verify_mode = ssl.CERT_REQUIRED
2001 # This should succeed because we specify the root cert
2002 ctx.load_verify_locations(SIGNING_CA)
2003 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2004 s.connect(self.server_addr)
2005 cert = s.getpeercert()
2006 self.assertTrue(cert)
2007
2008 def test_connect_with_context_fail(self):
2009 # This should fail because we have no verification certs. Connection
2010 # failure crashes ThreadedEchoServer, so run this in an independent
2011 # test method.
Christian Heimes2875c602021-04-19 07:27:10 +02002012 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2013 s = ctx.wrap_socket(
2014 socket.socket(socket.AF_INET),
2015 server_hostname=SIGNED_CERTFILE_HOSTNAME
2016 )
Martin Panter3840b2a2016-03-27 01:53:46 +00002017 self.addCleanup(s.close)
2018 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2019 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002020
2021 def test_connect_capath(self):
2022 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002023 # NOTE: the subject hashing algorithm has been changed between
2024 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2025 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002026 # filename) for this test to be portable across OpenSSL releases.
Christian Heimes2875c602021-04-19 07:27:10 +02002027 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002028 ctx.load_verify_locations(capath=CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002029 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2030 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002031 s.connect(self.server_addr)
2032 cert = s.getpeercert()
2033 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002034
Martin Panter3840b2a2016-03-27 01:53:46 +00002035 # Same with a bytes `capath` argument
Christian Heimes2875c602021-04-19 07:27:10 +02002036 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002037 ctx.load_verify_locations(capath=BYTES_CAPATH)
Christian Heimes2875c602021-04-19 07:27:10 +02002038 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2039 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002040 s.connect(self.server_addr)
2041 cert = s.getpeercert()
2042 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002043
Christian Heimesefff7062013-11-21 03:35:02 +01002044 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002045 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002046 pem = f.read()
2047 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002048 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002049 ctx.load_verify_locations(cadata=pem)
Christian Heimes2875c602021-04-19 07:27:10 +02002050 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2051 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002052 s.connect(self.server_addr)
2053 cert = s.getpeercert()
2054 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002055
Martin Panter3840b2a2016-03-27 01:53:46 +00002056 # same with DER
Christian Heimes2875c602021-04-19 07:27:10 +02002057 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002058 ctx.load_verify_locations(cadata=der)
Christian Heimes2875c602021-04-19 07:27:10 +02002059 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2060 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002061 s.connect(self.server_addr)
2062 cert = s.getpeercert()
2063 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002064
Antoine Pitroue3220242010-04-24 11:13:53 +00002065 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2066 def test_makefile_close(self):
2067 # Issue #5238: creating a file-like object with makefile() shouldn't
2068 # delay closing the underlying "real socket" (here tested with its
2069 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002070 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002071 ss.connect(self.server_addr)
2072 fd = ss.fileno()
2073 f = ss.makefile()
2074 f.close()
2075 # The fd is still open
2076 os.read(fd, 0)
2077 # Closing the SSL socket should close the fd too
2078 ss.close()
2079 gc.collect()
2080 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002081 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002082 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002083
Antoine Pitrou480a1242010-04-28 21:37:09 +00002084 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002085 s = socket.socket(socket.AF_INET)
2086 s.connect(self.server_addr)
2087 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002088 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002089 cert_reqs=ssl.CERT_NONE,
2090 do_handshake_on_connect=False)
2091 self.addCleanup(s.close)
2092 count = 0
2093 while True:
2094 try:
2095 count += 1
2096 s.do_handshake()
2097 break
2098 except ssl.SSLWantReadError:
2099 select.select([s], [], [])
2100 except ssl.SSLWantWriteError:
2101 select.select([], [s], [])
2102 if support.verbose:
2103 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002104
Antoine Pitrou480a1242010-04-28 21:37:09 +00002105 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002106 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002107
juhovh49fdf112021-04-18 21:11:48 +10002108 def test_get_server_certificate_sni(self):
2109 host, port = self.server_addr
2110 server_names = []
2111
2112 # We store servername_cb arguments to make sure they match the host
2113 def servername_cb(ssl_sock, server_name, initial_context):
2114 server_names.append(server_name)
2115 self.server_context.set_servername_callback(servername_cb)
2116
2117 pem = ssl.get_server_certificate((host, port))
2118 if not pem:
2119 self.fail("No server certificate on %s:%s!" % (host, port))
2120
2121 pem = ssl.get_server_certificate((host, port), ca_certs=SIGNING_CA)
2122 if not pem:
2123 self.fail("No server certificate on %s:%s!" % (host, port))
2124 if support.verbose:
2125 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port, pem))
2126
2127 self.assertEqual(server_names, [host, host])
2128
Martin Panter3840b2a2016-03-27 01:53:46 +00002129 def test_get_server_certificate_fail(self):
2130 # Connection failure crashes ThreadedEchoServer, so run this in an
2131 # independent test method
2132 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002133
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002134 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002135 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002136 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2137 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002138 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002139 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2140 s.connect(self.server_addr)
2141 # Error checking can happen at instantiation or when connecting
2142 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2143 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002144 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002145 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2146 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002147
Christian Heimes9a5395a2013-06-17 15:44:12 +02002148 def test_get_ca_certs_capath(self):
2149 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002150 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002151 ctx.load_verify_locations(capath=CAPATH)
2152 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002153 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2154 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002155 s.connect(self.server_addr)
2156 cert = s.getpeercert()
2157 self.assertTrue(cert)
2158 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002159
Christian Heimes8e7f3942013-12-05 07:41:08 +01002160 def test_context_setget(self):
2161 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002162 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2163 ctx1.load_verify_locations(capath=CAPATH)
2164 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2165 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002166 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002167 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002168 ss.connect(self.server_addr)
2169 self.assertIs(ss.context, ctx1)
2170 self.assertIs(ss._sslobj.context, ctx1)
2171 ss.context = ctx2
2172 self.assertIs(ss.context, ctx2)
2173 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002174
2175 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2176 # A simple IO loop. Call func(*args) depending on the error we get
2177 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002178 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002179 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002180 count = 0
2181 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002182 if time.monotonic() > deadline:
2183 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002184 errno = None
2185 count += 1
2186 try:
2187 ret = func(*args)
2188 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002189 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002190 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002191 raise
2192 errno = e.errno
2193 # Get any data from the outgoing BIO irrespective of any error, and
2194 # send it to the socket.
2195 buf = outgoing.read()
2196 sock.sendall(buf)
2197 # If there's no error, we're done. For WANT_READ, we need to get
2198 # data from the socket and put it in the incoming BIO.
2199 if errno is None:
2200 break
2201 elif errno == ssl.SSL_ERROR_WANT_READ:
2202 buf = sock.recv(32768)
2203 if buf:
2204 incoming.write(buf)
2205 else:
2206 incoming.write_eof()
2207 if support.verbose:
2208 sys.stdout.write("Needed %d calls to complete %s().\n"
2209 % (count, func.__name__))
2210 return ret
2211
Martin Panter3840b2a2016-03-27 01:53:46 +00002212 def test_bio_handshake(self):
2213 sock = socket.socket(socket.AF_INET)
2214 self.addCleanup(sock.close)
2215 sock.connect(self.server_addr)
2216 incoming = ssl.MemoryBIO()
2217 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002218 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2219 self.assertTrue(ctx.check_hostname)
2220 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002221 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002222 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2223 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002224 self.assertIs(sslobj._sslobj.owner, sslobj)
2225 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002226 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002227 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002228 self.assertRaises(ValueError, sslobj.getpeercert)
2229 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2230 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2231 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2232 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002233 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002234 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002235 self.assertTrue(sslobj.getpeercert())
2236 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2237 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2238 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002239 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002240 except ssl.SSLSyscallError:
2241 # If the server shuts down the TCP connection without sending a
2242 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2243 pass
2244 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2245
2246 def test_bio_read_write_data(self):
2247 sock = socket.socket(socket.AF_INET)
2248 self.addCleanup(sock.close)
2249 sock.connect(self.server_addr)
2250 incoming = ssl.MemoryBIO()
2251 outgoing = ssl.MemoryBIO()
Christian Heimes2875c602021-04-19 07:27:10 +02002252 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2253 ctx.check_hostname = False
Martin Panter3840b2a2016-03-27 01:53:46 +00002254 ctx.verify_mode = ssl.CERT_NONE
2255 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2256 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2257 req = b'FOO\n'
2258 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2259 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2260 self.assertEqual(buf, b'foo\n')
2261 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002262
2263
Martin Panter3840b2a2016-03-27 01:53:46 +00002264class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002265
Martin Panter3840b2a2016-03-27 01:53:46 +00002266 def test_timeout_connect_ex(self):
2267 # Issue #12065: on a timeout, connect_ex() should return the original
2268 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002269 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002270 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002271 cert_reqs=ssl.CERT_REQUIRED,
2272 do_handshake_on_connect=False)
2273 self.addCleanup(s.close)
2274 s.settimeout(0.0000001)
2275 rc = s.connect_ex((REMOTE_HOST, 443))
2276 if rc == 0:
2277 self.skipTest("REMOTE_HOST responded too quickly")
Carl Meyer29c451c2021-03-27 15:52:28 -06002278 elif rc == errno.ENETUNREACH:
2279 self.skipTest("Network unreachable.")
Martin Panter3840b2a2016-03-27 01:53:46 +00002280 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2281
Serhiy Storchaka16994912020-04-25 10:06:29 +03002282 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002283 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002284 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002285 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2286 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2287
Martin Panter3840b2a2016-03-27 01:53:46 +00002288
2289def _test_get_server_certificate(test, host, port, cert=None):
2290 pem = ssl.get_server_certificate((host, port))
2291 if not pem:
2292 test.fail("No server certificate on %s:%s!" % (host, port))
2293
2294 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2295 if not pem:
2296 test.fail("No server certificate on %s:%s!" % (host, port))
2297 if support.verbose:
2298 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2299
2300def _test_get_server_certificate_fail(test, host, port):
2301 try:
2302 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2303 except ssl.SSLError as x:
2304 #should fail
2305 if support.verbose:
2306 sys.stdout.write("%s\n" % x)
2307 else:
2308 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2309
2310
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002311from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002312
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002313class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002314
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002315 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002316
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002317 """A mildly complicated class, because we want it to work both
2318 with and without the SSL wrapper around the socket connection, so
2319 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002320
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002321 def __init__(self, server, connsock, addr):
2322 self.server = server
2323 self.running = False
2324 self.sock = connsock
2325 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002326 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002327 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002328 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002329 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002330
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002331 def wrap_conn(self):
2332 try:
2333 self.sslconn = self.server.context.wrap_socket(
2334 self.sock, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002335 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002336 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002337 # We treat ConnectionResetError as though it were an
2338 # SSLError - OpenSSL on Ubuntu abruptly closes the
2339 # connection when asked to use an unsupported protocol.
2340 #
Christian Heimes529525f2018-05-23 22:24:45 +02002341 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2342 # tries to send session tickets after handshake.
2343 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002344 #
2345 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2346 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002347 self.server.conn_errors.append(str(e))
2348 if self.server.chatty:
2349 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2350 self.running = False
2351 self.close()
2352 return False
2353 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002354 # OSError may occur with wrong protocols, e.g. both
2355 # sides use PROTOCOL_TLS_SERVER.
2356 #
2357 # XXX Various errors can have happened here, for example
2358 # a mismatching protocol version, an invalid certificate,
2359 # or a low-level bug. This should be made more discriminating.
2360 #
2361 # bpo-31323: Store the exception as string to prevent
2362 # a reference leak: server -> conn_errors -> exception
2363 # -> traceback -> self (ConnectionHandler) -> server
2364 self.server.conn_errors.append(str(e))
2365 if self.server.chatty:
2366 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2367 self.running = False
2368 self.server.stop()
2369 self.close()
2370 return False
2371 else:
2372 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2373 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2374 cert = self.sslconn.getpeercert()
2375 if support.verbose and self.server.chatty:
2376 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2377 cert_binary = self.sslconn.getpeercert(True)
2378 if support.verbose and self.server.chatty:
2379 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2380 cipher = self.sslconn.cipher()
2381 if support.verbose and self.server.chatty:
2382 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002383 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002384
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002385 def read(self):
2386 if self.sslconn:
2387 return self.sslconn.read()
2388 else:
2389 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002390
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002391 def write(self, bytes):
2392 if self.sslconn:
2393 return self.sslconn.write(bytes)
2394 else:
2395 return self.sock.send(bytes)
2396
2397 def close(self):
2398 if self.sslconn:
2399 self.sslconn.close()
2400 else:
2401 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002402
Antoine Pitrou480a1242010-04-28 21:37:09 +00002403 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002404 self.running = True
2405 if not self.server.starttls_server:
2406 if not self.wrap_conn():
2407 return
2408 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002409 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002410 msg = self.read()
2411 stripped = msg.strip()
2412 if not stripped:
2413 # eof, so quit this handler
2414 self.running = False
2415 try:
2416 self.sock = self.sslconn.unwrap()
2417 except OSError:
2418 # Many tests shut the TCP connection down
2419 # without an SSL shutdown. This causes
2420 # unwrap() to raise OSError with errno=0!
2421 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002422 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002423 self.sslconn = None
2424 self.close()
2425 elif stripped == b'over':
2426 if support.verbose and self.server.connectionchatty:
2427 sys.stdout.write(" server: client closed connection\n")
2428 self.close()
2429 return
2430 elif (self.server.starttls_server and
2431 stripped == b'STARTTLS'):
2432 if support.verbose and self.server.connectionchatty:
2433 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2434 self.write(b"OK\n")
2435 if not self.wrap_conn():
2436 return
2437 elif (self.server.starttls_server and self.sslconn
2438 and stripped == b'ENDTLS'):
2439 if support.verbose and self.server.connectionchatty:
2440 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2441 self.write(b"OK\n")
2442 self.sock = self.sslconn.unwrap()
2443 self.sslconn = None
2444 if support.verbose and self.server.connectionchatty:
2445 sys.stdout.write(" server: connection is now unencrypted...\n")
2446 elif stripped == b'CB tls-unique':
2447 if support.verbose and self.server.connectionchatty:
2448 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2449 data = self.sslconn.get_channel_binding("tls-unique")
2450 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002451 elif stripped == b'PHA':
2452 if support.verbose and self.server.connectionchatty:
2453 sys.stdout.write(" server: initiating post handshake auth\n")
2454 try:
2455 self.sslconn.verify_client_post_handshake()
2456 except ssl.SSLError as e:
2457 self.write(repr(e).encode("us-ascii") + b"\n")
2458 else:
2459 self.write(b"OK\n")
2460 elif stripped == b'HASCERT':
2461 if self.sslconn.getpeercert() is not None:
2462 self.write(b'TRUE\n')
2463 else:
2464 self.write(b'FALSE\n')
2465 elif stripped == b'GETCERT':
2466 cert = self.sslconn.getpeercert()
2467 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002468 else:
2469 if (support.verbose and
2470 self.server.connectionchatty):
2471 ctype = (self.sslconn and "encrypted") or "unencrypted"
2472 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2473 % (msg, ctype, msg.lower(), ctype))
2474 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002475 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002476 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2477 # when connection is not shut down gracefully.
2478 if self.server.chatty and support.verbose:
2479 sys.stdout.write(
2480 " Connection reset by peer: {}\n".format(
2481 self.addr)
2482 )
2483 self.close()
2484 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002485 except ssl.SSLError as err:
2486 # On Windows sometimes test_pha_required_nocert receives the
2487 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2488 # before the 'tlsv13 alert certificate required' exception.
2489 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2490 # is received test_pha_required_nocert fails with ConnectionResetError
2491 # because the underlying socket is closed
2492 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2493 if self.server.chatty and support.verbose:
2494 sys.stdout.write(err.args[1])
2495 # test_pha_required_nocert is expecting this exception
2496 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002497 except OSError:
2498 if self.server.chatty:
2499 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002500 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002501 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002502
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002503 # normally, we'd just stop here, but for the test
2504 # harness, we want to stop the server
2505 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002506
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002507 def __init__(self, certificate=None, ssl_version=None,
2508 certreqs=None, cacerts=None,
2509 chatty=True, connectionchatty=False, starttls_server=False,
Christian Heimes2875c602021-04-19 07:27:10 +02002510 alpn_protocols=None,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002511 ciphers=None, context=None):
2512 if context:
2513 self.context = context
2514 else:
2515 self.context = ssl.SSLContext(ssl_version
2516 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002517 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002518 self.context.verify_mode = (certreqs if certreqs is not None
2519 else ssl.CERT_NONE)
2520 if cacerts:
2521 self.context.load_verify_locations(cacerts)
2522 if certificate:
2523 self.context.load_cert_chain(certificate)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002524 if alpn_protocols:
2525 self.context.set_alpn_protocols(alpn_protocols)
2526 if ciphers:
2527 self.context.set_ciphers(ciphers)
2528 self.chatty = chatty
2529 self.connectionchatty = connectionchatty
2530 self.starttls_server = starttls_server
2531 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002532 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002533 self.flag = None
2534 self.active = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002535 self.selected_alpn_protocols = []
2536 self.shared_ciphers = []
2537 self.conn_errors = []
2538 threading.Thread.__init__(self)
2539 self.daemon = True
2540
2541 def __enter__(self):
2542 self.start(threading.Event())
2543 self.flag.wait()
2544 return self
2545
2546 def __exit__(self, *args):
2547 self.stop()
2548 self.join()
2549
2550 def start(self, flag=None):
2551 self.flag = flag
2552 threading.Thread.start(self)
2553
2554 def run(self):
2555 self.sock.settimeout(0.05)
2556 self.sock.listen()
2557 self.active = True
2558 if self.flag:
2559 # signal an event
2560 self.flag.set()
2561 while self.active:
2562 try:
2563 newconn, connaddr = self.sock.accept()
2564 if support.verbose and self.chatty:
2565 sys.stdout.write(' server: new connection from '
2566 + repr(connaddr) + '\n')
2567 handler = self.ConnectionHandler(self, newconn, connaddr)
2568 handler.start()
2569 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002570 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002571 pass
2572 except KeyboardInterrupt:
2573 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002574 except BaseException as e:
2575 if support.verbose and self.chatty:
2576 sys.stdout.write(
2577 ' connection handling failed: ' + repr(e) + '\n')
2578
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002579 self.sock.close()
2580
2581 def stop(self):
2582 self.active = False
2583
2584class AsyncoreEchoServer(threading.Thread):
2585
2586 # this one's based on asyncore.dispatcher
2587
2588 class EchoServer (asyncore.dispatcher):
2589
2590 class ConnectionHandler(asyncore.dispatcher_with_send):
2591
2592 def __init__(self, conn, certfile):
2593 self.socket = test_wrap_socket(conn, server_side=True,
2594 certfile=certfile,
2595 do_handshake_on_connect=False)
2596 asyncore.dispatcher_with_send.__init__(self, self.socket)
2597 self._ssl_accepting = True
2598 self._do_ssl_handshake()
2599
2600 def readable(self):
2601 if isinstance(self.socket, ssl.SSLSocket):
2602 while self.socket.pending() > 0:
2603 self.handle_read_event()
2604 return True
2605
2606 def _do_ssl_handshake(self):
2607 try:
2608 self.socket.do_handshake()
2609 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2610 return
2611 except ssl.SSLEOFError:
2612 return self.handle_close()
2613 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002614 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002615 except OSError as err:
2616 if err.args[0] == errno.ECONNABORTED:
2617 return self.handle_close()
2618 else:
2619 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002620
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002621 def handle_read(self):
2622 if self._ssl_accepting:
2623 self._do_ssl_handshake()
2624 else:
2625 data = self.recv(1024)
2626 if support.verbose:
2627 sys.stdout.write(" server: read %s from client\n" % repr(data))
2628 if not data:
2629 self.close()
2630 else:
2631 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002632
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002633 def handle_close(self):
2634 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002635 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002636 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002637
2638 def handle_error(self):
2639 raise
2640
Trent Nelson78520002008-04-10 20:54:35 +00002641 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002642 self.certfile = certfile
2643 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002644 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002645 asyncore.dispatcher.__init__(self, sock)
2646 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002647
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002648 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002649 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002650 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2651 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002652
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002653 def handle_error(self):
2654 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002655
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002656 def __init__(self, certfile):
2657 self.flag = None
2658 self.active = False
2659 self.server = self.EchoServer(certfile)
2660 self.port = self.server.port
2661 threading.Thread.__init__(self)
2662 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002663
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002664 def __str__(self):
2665 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002666
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002667 def __enter__(self):
2668 self.start(threading.Event())
2669 self.flag.wait()
2670 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002671
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002672 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002673 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002674 sys.stdout.write(" cleanup: stopping server.\n")
2675 self.stop()
2676 if support.verbose:
2677 sys.stdout.write(" cleanup: joining server thread.\n")
2678 self.join()
2679 if support.verbose:
2680 sys.stdout.write(" cleanup: successfully joined.\n")
2681 # make sure that ConnectionHandler is removed from socket_map
2682 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002683
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002684 def start (self, flag=None):
2685 self.flag = flag
2686 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002687
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002688 def run(self):
2689 self.active = True
2690 if self.flag:
2691 self.flag.set()
2692 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002693 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002694 asyncore.loop(1)
2695 except:
2696 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002697
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002698 def stop(self):
2699 self.active = False
2700 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002701
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002702def server_params_test(client_context, server_context, indata=b"FOO\n",
2703 chatty=True, connectionchatty=False, sni_name=None,
2704 session=None):
2705 """
2706 Launch a server, connect a client to it and try various reads
2707 and writes.
2708 """
2709 stats = {}
2710 server = ThreadedEchoServer(context=server_context,
2711 chatty=chatty,
2712 connectionchatty=False)
2713 with server:
2714 with client_context.wrap_socket(socket.socket(),
2715 server_hostname=sni_name, session=session) as s:
2716 s.connect((HOST, server.port))
2717 for arg in [indata, bytearray(indata), memoryview(indata)]:
2718 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002719 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002720 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002721 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002722 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002723 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002724 if connectionchatty:
2725 if support.verbose:
2726 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002727 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002728 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002729 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2730 % (outdata[:20], len(outdata),
2731 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002732 s.write(b"over\n")
2733 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002734 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002735 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002736 stats.update({
2737 'compression': s.compression(),
2738 'cipher': s.cipher(),
2739 'peercert': s.getpeercert(),
2740 'client_alpn_protocol': s.selected_alpn_protocol(),
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002741 'version': s.version(),
2742 'session_reused': s.session_reused,
2743 'session': s.session,
2744 })
2745 s.close()
2746 stats['server_alpn_protocols'] = server.selected_alpn_protocols
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002747 stats['server_shared_ciphers'] = server.shared_ciphers
2748 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002749
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002750def try_protocol_combo(server_protocol, client_protocol, expect_success,
2751 certsreqs=None, server_options=0, client_options=0):
2752 """
2753 Try to SSL-connect using *client_protocol* to *server_protocol*.
2754 If *expect_success* is true, assert that the connection succeeds,
2755 if it's false, assert that the connection fails.
2756 Also, if *expect_success* is a string, assert that it is the protocol
2757 version actually used by the connection.
2758 """
2759 if certsreqs is None:
2760 certsreqs = ssl.CERT_NONE
2761 certtype = {
2762 ssl.CERT_NONE: "CERT_NONE",
2763 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2764 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2765 }[certsreqs]
2766 if support.verbose:
2767 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2768 sys.stdout.write(formatstr %
2769 (ssl.get_protocol_name(client_protocol),
2770 ssl.get_protocol_name(server_protocol),
2771 certtype))
Christian Heimes2875c602021-04-19 07:27:10 +02002772
2773 with warnings_helper.check_warnings():
2774 # ignore Deprecation warnings
2775 client_context = ssl.SSLContext(client_protocol)
2776 client_context.options |= client_options
2777 server_context = ssl.SSLContext(server_protocol)
2778 server_context.options |= server_options
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002779
Victor Stinner3ef63442019-02-19 18:06:03 +01002780 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2781 if (min_version is not None
Christian Heimes2875c602021-04-19 07:27:10 +02002782 # SSLContext.minimum_version is only available on recent OpenSSL
2783 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2784 and hasattr(server_context, 'minimum_version')
2785 and server_protocol == ssl.PROTOCOL_TLS
2786 and server_context.minimum_version > min_version
2787 ):
Victor Stinner3ef63442019-02-19 18:06:03 +01002788 # If OpenSSL configuration is strict and requires more recent TLS
2789 # version, we have to change the minimum to test old TLS versions.
Christian Heimes2875c602021-04-19 07:27:10 +02002790 with warnings_helper.check_warnings():
2791 server_context.minimum_version = min_version
Victor Stinner3ef63442019-02-19 18:06:03 +01002792
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002793 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2794 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2795 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002796 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002797 client_context.set_ciphers("ALL")
2798
Christian Heimesf6c6b582021-03-18 23:06:50 +01002799 seclevel_workaround(server_context, client_context)
2800
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002801 for ctx in (client_context, server_context):
2802 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002803 ctx.load_cert_chain(SIGNED_CERTFILE)
2804 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002805 try:
2806 stats = server_params_test(client_context, server_context,
2807 chatty=False, connectionchatty=False)
2808 # Protocol mismatch can result in either an SSLError, or a
2809 # "Connection reset by peer" error.
2810 except ssl.SSLError:
2811 if expect_success:
2812 raise
2813 except OSError as e:
2814 if expect_success or e.errno != errno.ECONNRESET:
2815 raise
2816 else:
2817 if not expect_success:
2818 raise AssertionError(
2819 "Client protocol %s succeeded with server protocol %s!"
2820 % (ssl.get_protocol_name(client_protocol),
2821 ssl.get_protocol_name(server_protocol)))
2822 elif (expect_success is not True
2823 and expect_success != stats['version']):
2824 raise AssertionError("version mismatch: expected %r, got %r"
2825 % (expect_success, stats['version']))
2826
2827
2828class ThreadedTests(unittest.TestCase):
2829
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002830 def test_echo(self):
2831 """Basic test of an SSL client connecting to a server"""
2832 if support.verbose:
2833 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002834
Christian Heimesa170fa12017-09-15 20:27:30 +02002835 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002836
2837 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2838 server_params_test(client_context=client_context,
2839 server_context=server_context,
2840 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002841 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002842
2843 client_context.check_hostname = False
2844 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2845 with self.assertRaises(ssl.SSLError) as e:
2846 server_params_test(client_context=server_context,
2847 server_context=client_context,
2848 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002849 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002850 self.assertIn('called a function you should not call',
2851 str(e.exception))
2852
2853 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2854 with self.assertRaises(ssl.SSLError) as e:
2855 server_params_test(client_context=server_context,
2856 server_context=server_context,
2857 chatty=True, connectionchatty=True)
2858 self.assertIn('called a function you should not call',
2859 str(e.exception))
2860
2861 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2862 with self.assertRaises(ssl.SSLError) as e:
2863 server_params_test(client_context=server_context,
2864 server_context=client_context,
2865 chatty=True, connectionchatty=True)
2866 self.assertIn('called a function you should not call',
2867 str(e.exception))
2868
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002869 def test_getpeercert(self):
2870 if support.verbose:
2871 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002872
2873 client_context, server_context, hostname = testing_context()
2874 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002875 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002876 with client_context.wrap_socket(socket.socket(),
2877 do_handshake_on_connect=False,
2878 server_hostname=hostname) as s:
2879 s.connect((HOST, server.port))
2880 # getpeercert() raise ValueError while the handshake isn't
2881 # done.
2882 with self.assertRaises(ValueError):
2883 s.getpeercert()
2884 s.do_handshake()
2885 cert = s.getpeercert()
2886 self.assertTrue(cert, "Can't get peer certificate.")
2887 cipher = s.cipher()
2888 if support.verbose:
2889 sys.stdout.write(pprint.pformat(cert) + '\n')
2890 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2891 if 'subject' not in cert:
2892 self.fail("No subject field in certificate: %s." %
2893 pprint.pformat(cert))
2894 if ((('organizationName', 'Python Software Foundation'),)
2895 not in cert['subject']):
2896 self.fail(
2897 "Missing or invalid 'organizationName' field in certificate subject; "
2898 "should be 'Python Software Foundation'.")
2899 self.assertIn('notBefore', cert)
2900 self.assertIn('notAfter', cert)
2901 before = ssl.cert_time_to_seconds(cert['notBefore'])
2902 after = ssl.cert_time_to_seconds(cert['notAfter'])
2903 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002904
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002905 def test_crl_check(self):
2906 if support.verbose:
2907 sys.stdout.write("\n")
2908
Christian Heimesa170fa12017-09-15 20:27:30 +02002909 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002910
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002911 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002912 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002913
2914 # VERIFY_DEFAULT should pass
2915 server = ThreadedEchoServer(context=server_context, chatty=True)
2916 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002917 with client_context.wrap_socket(socket.socket(),
2918 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002919 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002920 cert = s.getpeercert()
2921 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002922
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002923 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002924 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002925
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002926 server = ThreadedEchoServer(context=server_context, chatty=True)
2927 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002928 with client_context.wrap_socket(socket.socket(),
2929 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002930 with self.assertRaisesRegex(ssl.SSLError,
2931 "certificate verify failed"):
2932 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002933
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002934 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002935 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002936
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002937 server = ThreadedEchoServer(context=server_context, chatty=True)
2938 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002939 with client_context.wrap_socket(socket.socket(),
2940 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002941 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002942 cert = s.getpeercert()
2943 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002944
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002945 def test_check_hostname(self):
2946 if support.verbose:
2947 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002948
Christian Heimesa170fa12017-09-15 20:27:30 +02002949 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002950
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002951 # correct hostname should verify
2952 server = ThreadedEchoServer(context=server_context, chatty=True)
2953 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002954 with client_context.wrap_socket(socket.socket(),
2955 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002956 s.connect((HOST, server.port))
2957 cert = s.getpeercert()
2958 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002959
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002960 # incorrect hostname should raise an exception
2961 server = ThreadedEchoServer(context=server_context, chatty=True)
2962 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002963 with client_context.wrap_socket(socket.socket(),
2964 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01002965 with self.assertRaisesRegex(
2966 ssl.CertificateError,
2967 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002968 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002969
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002970 # missing server_hostname arg should cause an exception, too
2971 server = ThreadedEchoServer(context=server_context, chatty=True)
2972 with server:
2973 with socket.socket() as s:
2974 with self.assertRaisesRegex(ValueError,
2975 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02002976 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002977
Christian Heimesb467d9a2021-04-17 10:07:19 +02002978 @unittest.skipUnless(
2979 ssl.HAS_NEVER_CHECK_COMMON_NAME, "test requires hostname_checks_common_name"
2980 )
2981 def test_hostname_checks_common_name(self):
2982 client_context, server_context, hostname = testing_context()
2983 assert client_context.hostname_checks_common_name
2984 client_context.hostname_checks_common_name = False
2985
2986 # default cert has a SAN
2987 server = ThreadedEchoServer(context=server_context, chatty=True)
2988 with server:
2989 with client_context.wrap_socket(socket.socket(),
2990 server_hostname=hostname) as s:
2991 s.connect((HOST, server.port))
2992
2993 client_context, server_context, hostname = testing_context(NOSANFILE)
2994 client_context.hostname_checks_common_name = False
2995 server = ThreadedEchoServer(context=server_context, chatty=True)
2996 with server:
2997 with client_context.wrap_socket(socket.socket(),
2998 server_hostname=hostname) as s:
2999 with self.assertRaises(ssl.SSLCertVerificationError):
3000 s.connect((HOST, server.port))
3001
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003002 def test_ecc_cert(self):
3003 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3004 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003005 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003006 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3007
3008 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3009 # load ECC cert
3010 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3011
3012 # correct hostname should verify
3013 server = ThreadedEchoServer(context=server_context, chatty=True)
3014 with server:
3015 with client_context.wrap_socket(socket.socket(),
3016 server_hostname=hostname) as s:
3017 s.connect((HOST, server.port))
3018 cert = s.getpeercert()
3019 self.assertTrue(cert, "Can't get peer certificate.")
3020 cipher = s.cipher()[0].split('-')
3021 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3022
3023 def test_dual_rsa_ecc(self):
3024 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3025 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003026 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3027 # algorithms.
3028 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003029 # only ECDSA certs
3030 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3031 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3032
3033 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3034 # load ECC and RSA key/cert pairs
3035 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3036 server_context.load_cert_chain(SIGNED_CERTFILE)
3037
3038 # correct hostname should verify
3039 server = ThreadedEchoServer(context=server_context, chatty=True)
3040 with server:
3041 with client_context.wrap_socket(socket.socket(),
3042 server_hostname=hostname) as s:
3043 s.connect((HOST, server.port))
3044 cert = s.getpeercert()
3045 self.assertTrue(cert, "Can't get peer certificate.")
3046 cipher = s.cipher()[0].split('-')
3047 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3048
Christian Heimes66e57422018-01-29 14:25:13 +01003049 def test_check_hostname_idn(self):
3050 if support.verbose:
3051 sys.stdout.write("\n")
3052
Christian Heimes11a14932018-02-24 02:35:08 +01003053 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003054 server_context.load_cert_chain(IDNSANSFILE)
3055
Christian Heimes11a14932018-02-24 02:35:08 +01003056 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003057 context.verify_mode = ssl.CERT_REQUIRED
3058 context.check_hostname = True
3059 context.load_verify_locations(SIGNING_CA)
3060
3061 # correct hostname should verify, when specified in several
3062 # different ways
3063 idn_hostnames = [
3064 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003065 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003066 ('xn--knig-5qa.idn.pythontest.net',
3067 'xn--knig-5qa.idn.pythontest.net'),
3068 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003069 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003070
3071 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003072 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003073 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3074 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3075 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003076 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3077
3078 # ('königsgäßchen.idna2008.pythontest.net',
3079 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3080 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3081 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3082 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3083 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3084
Christian Heimes66e57422018-01-29 14:25:13 +01003085 ]
3086 for server_hostname, expected_hostname in idn_hostnames:
3087 server = ThreadedEchoServer(context=server_context, chatty=True)
3088 with server:
3089 with context.wrap_socket(socket.socket(),
3090 server_hostname=server_hostname) as s:
3091 self.assertEqual(s.server_hostname, expected_hostname)
3092 s.connect((HOST, server.port))
3093 cert = s.getpeercert()
3094 self.assertEqual(s.server_hostname, expected_hostname)
3095 self.assertTrue(cert, "Can't get peer certificate.")
3096
Christian Heimes66e57422018-01-29 14:25:13 +01003097 # incorrect hostname should raise an exception
3098 server = ThreadedEchoServer(context=server_context, chatty=True)
3099 with server:
3100 with context.wrap_socket(socket.socket(),
3101 server_hostname="python.example.org") as s:
3102 with self.assertRaises(ssl.CertificateError):
3103 s.connect((HOST, server.port))
3104
Christian Heimes529525f2018-05-23 22:24:45 +02003105 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003106 """Connecting when the server rejects the client's certificate
3107
3108 Launch a server with CERT_REQUIRED, and check that trying to
3109 connect to it with a wrong client certificate fails.
3110 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003111 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003112 # load client cert that is not signed by trusted CA
3113 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003114 # require TLS client authentication
3115 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003116 # TLS 1.3 has different handshake
3117 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003118
3119 server = ThreadedEchoServer(
3120 context=server_context, chatty=True, connectionchatty=True,
3121 )
3122
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003123 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003124 client_context.wrap_socket(socket.socket(),
3125 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003126 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003127 # Expect either an SSL error about the server rejecting
3128 # the connection, or a low-level connection reset (which
3129 # sometimes happens on Windows)
3130 s.connect((HOST, server.port))
3131 except ssl.SSLError as e:
3132 if support.verbose:
3133 sys.stdout.write("\nSSLError is %r\n" % e)
3134 except OSError as e:
3135 if e.errno != errno.ECONNRESET:
3136 raise
3137 if support.verbose:
3138 sys.stdout.write("\nsocket.error is %r\n" % e)
3139 else:
3140 self.fail("Use of invalid cert should have failed!")
3141
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003142 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003143 def test_wrong_cert_tls13(self):
3144 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003145 # load client cert that is not signed by trusted CA
3146 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003147 server_context.verify_mode = ssl.CERT_REQUIRED
3148 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3149 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3150
3151 server = ThreadedEchoServer(
3152 context=server_context, chatty=True, connectionchatty=True,
3153 )
3154 with server, \
3155 client_context.wrap_socket(socket.socket(),
3156 server_hostname=hostname) as s:
3157 # TLS 1.3 perform client cert exchange after handshake
3158 s.connect((HOST, server.port))
3159 try:
3160 s.write(b'data')
3161 s.read(4)
3162 except ssl.SSLError as e:
3163 if support.verbose:
3164 sys.stdout.write("\nSSLError is %r\n" % e)
3165 except OSError as e:
3166 if e.errno != errno.ECONNRESET:
3167 raise
3168 if support.verbose:
3169 sys.stdout.write("\nsocket.error is %r\n" % e)
3170 else:
3171 self.fail("Use of invalid cert should have failed!")
3172
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003173 def test_rude_shutdown(self):
3174 """A brutal shutdown of an SSL server should raise an OSError
3175 in the client when attempting handshake.
3176 """
3177 listener_ready = threading.Event()
3178 listener_gone = threading.Event()
3179
3180 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003181 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003182
3183 # `listener` runs in a thread. It sits in an accept() until
3184 # the main thread connects. Then it rudely closes the socket,
3185 # and sets Event `listener_gone` to let the main thread know
3186 # the socket is gone.
3187 def listener():
3188 s.listen()
3189 listener_ready.set()
3190 newsock, addr = s.accept()
3191 newsock.close()
3192 s.close()
3193 listener_gone.set()
3194
3195 def connector():
3196 listener_ready.wait()
3197 with socket.socket() as c:
3198 c.connect((HOST, port))
3199 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003200 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003201 ssl_sock = test_wrap_socket(c)
3202 except OSError:
3203 pass
3204 else:
3205 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003206
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003207 t = threading.Thread(target=listener)
3208 t.start()
3209 try:
3210 connector()
3211 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003212 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003213
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003214 def test_ssl_cert_verify_error(self):
3215 if support.verbose:
3216 sys.stdout.write("\n")
3217
3218 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3219 server_context.load_cert_chain(SIGNED_CERTFILE)
3220
3221 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3222
3223 server = ThreadedEchoServer(context=server_context, chatty=True)
3224 with server:
3225 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003226 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003227 try:
3228 s.connect((HOST, server.port))
3229 except ssl.SSLError as e:
3230 msg = 'unable to get local issuer certificate'
3231 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3232 self.assertEqual(e.verify_code, 20)
3233 self.assertEqual(e.verify_message, msg)
3234 self.assertIn(msg, repr(e))
3235 self.assertIn('certificate verify failed', repr(e))
3236
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003237 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003238 def test_protocol_sslv2(self):
3239 """Connecting to an SSLv2 server with various client options"""
3240 if support.verbose:
3241 sys.stdout.write("\n")
3242 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3243 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3244 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003245 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003246 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003247 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3248 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3249 # SSLv23 client with specific SSL options
Christian Heimesa170fa12017-09-15 20:27:30 +02003250 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003251 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003252 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003253 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003254
Christian Heimesa170fa12017-09-15 20:27:30 +02003255 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003256 """Connecting to an SSLv23 server with various client options"""
3257 if support.verbose:
3258 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003259 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003260 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003261 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003262 except OSError as x:
3263 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3264 if support.verbose:
3265 sys.stdout.write(
3266 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3267 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003268 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003269 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3270 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003271 if has_tls_version('TLSv1'):
3272 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003273
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003274 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003275 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3276 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003277 if has_tls_version('TLSv1'):
3278 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003279
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003280 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003281 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3282 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003283 if has_tls_version('TLSv1'):
3284 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003285
3286 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003287 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003288 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003289 server_options=ssl.OP_NO_SSLv3)
3290 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003291 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003292 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003293 if has_tls_version('TLSv1'):
3294 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3295 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003296
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003297 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003298 def test_protocol_sslv3(self):
3299 """Connecting to an SSLv3 server with various client options"""
3300 if support.verbose:
3301 sys.stdout.write("\n")
3302 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3303 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3304 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003305 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003306 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003307 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003308 client_options=ssl.OP_NO_SSLv3)
3309 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003310
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003311 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003312 def test_protocol_tlsv1(self):
3313 """Connecting to a TLSv1 server with various client options"""
3314 if support.verbose:
3315 sys.stdout.write("\n")
3316 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3317 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3318 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003319 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003320 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003321 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003322 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003323 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003324 client_options=ssl.OP_NO_TLSv1)
3325
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003326 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003327 def test_protocol_tlsv1_1(self):
3328 """Connecting to a TLSv1.1 server with various client options.
3329 Testing against older TLS versions."""
3330 if support.verbose:
3331 sys.stdout.write("\n")
3332 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003333 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003334 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003335 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003336 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003337 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003338 client_options=ssl.OP_NO_TLSv1_1)
3339
Christian Heimesa170fa12017-09-15 20:27:30 +02003340 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003341 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3342 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003343
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003344 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003345 def test_protocol_tlsv1_2(self):
3346 """Connecting to a TLSv1.2 server with various client options.
3347 Testing against older TLS versions."""
3348 if support.verbose:
3349 sys.stdout.write("\n")
3350 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3351 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3352 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003353 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003354 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003355 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003356 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003357 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003358 client_options=ssl.OP_NO_TLSv1_2)
3359
Christian Heimesa170fa12017-09-15 20:27:30 +02003360 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003361 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3362 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3363 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3364 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3365
3366 def test_starttls(self):
3367 """Switching from clear text to encrypted and back again."""
3368 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3369
3370 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003371 starttls_server=True,
3372 chatty=True,
3373 connectionchatty=True)
3374 wrapped = False
3375 with server:
3376 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003377 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003378 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003379 if support.verbose:
3380 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003381 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003382 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003383 sys.stdout.write(
3384 " client: sending %r...\n" % indata)
3385 if wrapped:
3386 conn.write(indata)
3387 outdata = conn.read()
3388 else:
3389 s.send(indata)
3390 outdata = s.recv(1024)
3391 msg = outdata.strip().lower()
3392 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3393 # STARTTLS ok, switch to secure mode
3394 if support.verbose:
3395 sys.stdout.write(
3396 " client: read %r from server, starting TLS...\n"
3397 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003398 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003399 wrapped = True
3400 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3401 # ENDTLS ok, switch back to clear text
3402 if support.verbose:
3403 sys.stdout.write(
3404 " client: read %r from server, ending TLS...\n"
3405 % msg)
3406 s = conn.unwrap()
3407 wrapped = False
3408 else:
3409 if support.verbose:
3410 sys.stdout.write(
3411 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003412 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003413 sys.stdout.write(" client: closing connection.\n")
3414 if wrapped:
3415 conn.write(b"over\n")
3416 else:
3417 s.send(b"over\n")
3418 if wrapped:
3419 conn.close()
3420 else:
3421 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003422
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003423 def test_socketserver(self):
3424 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003425 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003426 # try to connect
3427 if support.verbose:
3428 sys.stdout.write('\n')
3429 with open(CERTFILE, 'rb') as f:
3430 d1 = f.read()
3431 d2 = ''
3432 # now fetch the same data from the HTTPS server
3433 url = 'https://localhost:%d/%s' % (
3434 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003435 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003436 f = urllib.request.urlopen(url, context=context)
3437 try:
3438 dlen = f.info().get("content-length")
3439 if dlen and (int(dlen) > 0):
3440 d2 = f.read(int(dlen))
3441 if support.verbose:
3442 sys.stdout.write(
3443 " client: read %d bytes from remote server '%s'\n"
3444 % (len(d2), server))
3445 finally:
3446 f.close()
3447 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003448
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003449 def test_asyncore_server(self):
3450 """Check the example asyncore integration."""
3451 if support.verbose:
3452 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003453
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003454 indata = b"FOO\n"
3455 server = AsyncoreEchoServer(CERTFILE)
3456 with server:
3457 s = test_wrap_socket(socket.socket())
3458 s.connect(('127.0.0.1', server.port))
3459 if support.verbose:
3460 sys.stdout.write(
3461 " client: sending %r...\n" % indata)
3462 s.write(indata)
3463 outdata = s.read()
3464 if support.verbose:
3465 sys.stdout.write(" client: read %r\n" % outdata)
3466 if outdata != indata.lower():
3467 self.fail(
3468 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3469 % (outdata[:20], len(outdata),
3470 indata[:20].lower(), len(indata)))
3471 s.write(b"over\n")
3472 if support.verbose:
3473 sys.stdout.write(" client: closing connection.\n")
3474 s.close()
3475 if support.verbose:
3476 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003477
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003478 def test_recv_send(self):
3479 """Test recv(), send() and friends."""
3480 if support.verbose:
3481 sys.stdout.write("\n")
3482
3483 server = ThreadedEchoServer(CERTFILE,
3484 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003485 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003486 cacerts=CERTFILE,
3487 chatty=True,
3488 connectionchatty=False)
3489 with server:
3490 s = test_wrap_socket(socket.socket(),
3491 server_side=False,
3492 certfile=CERTFILE,
3493 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003494 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003495 s.connect((HOST, server.port))
3496 # helper methods for standardising recv* method signatures
3497 def _recv_into():
3498 b = bytearray(b"\0"*100)
3499 count = s.recv_into(b)
3500 return b[:count]
3501
3502 def _recvfrom_into():
3503 b = bytearray(b"\0"*100)
3504 count, addr = s.recvfrom_into(b)
3505 return b[:count]
3506
3507 # (name, method, expect success?, *args, return value func)
3508 send_methods = [
3509 ('send', s.send, True, [], len),
3510 ('sendto', s.sendto, False, ["some.address"], len),
3511 ('sendall', s.sendall, True, [], lambda x: None),
3512 ]
3513 # (name, method, whether to expect success, *args)
3514 recv_methods = [
3515 ('recv', s.recv, True, []),
3516 ('recvfrom', s.recvfrom, False, ["some.address"]),
3517 ('recv_into', _recv_into, True, []),
3518 ('recvfrom_into', _recvfrom_into, False, []),
3519 ]
3520 data_prefix = "PREFIX_"
3521
3522 for (meth_name, send_meth, expect_success, args,
3523 ret_val_meth) in send_methods:
3524 indata = (data_prefix + meth_name).encode('ascii')
3525 try:
3526 ret = send_meth(indata, *args)
3527 msg = "sending with {}".format(meth_name)
3528 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3529 outdata = s.read()
3530 if outdata != indata.lower():
3531 self.fail(
3532 "While sending with <<{name:s}>> bad data "
3533 "<<{outdata:r}>> ({nout:d}) received; "
3534 "expected <<{indata:r}>> ({nin:d})\n".format(
3535 name=meth_name, outdata=outdata[:20],
3536 nout=len(outdata),
3537 indata=indata[:20], nin=len(indata)
3538 )
3539 )
3540 except ValueError as e:
3541 if expect_success:
3542 self.fail(
3543 "Failed to send with method <<{name:s}>>; "
3544 "expected to succeed.\n".format(name=meth_name)
3545 )
3546 if not str(e).startswith(meth_name):
3547 self.fail(
3548 "Method <<{name:s}>> failed with unexpected "
3549 "exception message: {exp:s}\n".format(
3550 name=meth_name, exp=e
3551 )
3552 )
3553
3554 for meth_name, recv_meth, expect_success, args in recv_methods:
3555 indata = (data_prefix + meth_name).encode('ascii')
3556 try:
3557 s.send(indata)
3558 outdata = recv_meth(*args)
3559 if outdata != indata.lower():
3560 self.fail(
3561 "While receiving with <<{name:s}>> bad data "
3562 "<<{outdata:r}>> ({nout:d}) received; "
3563 "expected <<{indata:r}>> ({nin:d})\n".format(
3564 name=meth_name, outdata=outdata[:20],
3565 nout=len(outdata),
3566 indata=indata[:20], nin=len(indata)
3567 )
3568 )
3569 except ValueError as e:
3570 if expect_success:
3571 self.fail(
3572 "Failed to receive with method <<{name:s}>>; "
3573 "expected to succeed.\n".format(name=meth_name)
3574 )
3575 if not str(e).startswith(meth_name):
3576 self.fail(
3577 "Method <<{name:s}>> failed with unexpected "
3578 "exception message: {exp:s}\n".format(
3579 name=meth_name, exp=e
3580 )
3581 )
3582 # consume data
3583 s.read()
3584
3585 # read(-1, buffer) is supported, even though read(-1) is not
3586 data = b"data"
3587 s.send(data)
3588 buffer = bytearray(len(data))
3589 self.assertEqual(s.read(-1, buffer), len(data))
3590 self.assertEqual(buffer, data)
3591
Christian Heimes888bbdc2017-09-07 14:18:21 -07003592 # sendall accepts bytes-like objects
3593 if ctypes is not None:
3594 ubyte = ctypes.c_ubyte * len(data)
3595 byteslike = ubyte.from_buffer_copy(data)
3596 s.sendall(byteslike)
3597 self.assertEqual(s.read(), data)
3598
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003599 # Make sure sendmsg et al are disallowed to avoid
3600 # inadvertent disclosure of data and/or corruption
3601 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003602 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003603 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3604 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3605 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003606 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003607 s.write(b"over\n")
3608
3609 self.assertRaises(ValueError, s.recv, -1)
3610 self.assertRaises(ValueError, s.read, -1)
3611
3612 s.close()
3613
3614 def test_recv_zero(self):
3615 server = ThreadedEchoServer(CERTFILE)
3616 server.__enter__()
3617 self.addCleanup(server.__exit__, None, None)
3618 s = socket.create_connection((HOST, server.port))
3619 self.addCleanup(s.close)
3620 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3621 self.addCleanup(s.close)
3622
3623 # recv/read(0) should return no data
3624 s.send(b"data")
3625 self.assertEqual(s.recv(0), b"")
3626 self.assertEqual(s.read(0), b"")
3627 self.assertEqual(s.read(), b"data")
3628
3629 # Should not block if the other end sends no data
3630 s.setblocking(False)
3631 self.assertEqual(s.recv(0), b"")
3632 self.assertEqual(s.recv_into(bytearray()), 0)
3633
3634 def test_nonblocking_send(self):
3635 server = ThreadedEchoServer(CERTFILE,
3636 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003637 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003638 cacerts=CERTFILE,
3639 chatty=True,
3640 connectionchatty=False)
3641 with server:
3642 s = test_wrap_socket(socket.socket(),
3643 server_side=False,
3644 certfile=CERTFILE,
3645 ca_certs=CERTFILE,
Christian Heimes2875c602021-04-19 07:27:10 +02003646 cert_reqs=ssl.CERT_NONE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003647 s.connect((HOST, server.port))
3648 s.setblocking(False)
3649
3650 # If we keep sending data, at some point the buffers
3651 # will be full and the call will block
3652 buf = bytearray(8192)
3653 def fill_buffer():
3654 while True:
3655 s.send(buf)
3656 self.assertRaises((ssl.SSLWantWriteError,
3657 ssl.SSLWantReadError), fill_buffer)
3658
3659 # Now read all the output and discard it
3660 s.setblocking(True)
3661 s.close()
3662
3663 def test_handshake_timeout(self):
3664 # Issue #5103: SSL handshake must respect the socket timeout
3665 server = socket.socket(socket.AF_INET)
3666 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003667 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003668 started = threading.Event()
3669 finish = False
3670
3671 def serve():
3672 server.listen()
3673 started.set()
3674 conns = []
3675 while not finish:
3676 r, w, e = select.select([server], [], [], 0.1)
3677 if server in r:
3678 # Let the socket hang around rather than having
3679 # it closed by garbage collection.
3680 conns.append(server.accept()[0])
3681 for sock in conns:
3682 sock.close()
3683
3684 t = threading.Thread(target=serve)
3685 t.start()
3686 started.wait()
3687
3688 try:
3689 try:
3690 c = socket.socket(socket.AF_INET)
3691 c.settimeout(0.2)
3692 c.connect((host, port))
3693 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003694 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003695 test_wrap_socket, c)
3696 finally:
3697 c.close()
3698 try:
3699 c = socket.socket(socket.AF_INET)
3700 c = test_wrap_socket(c)
3701 c.settimeout(0.2)
3702 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003703 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003704 c.connect, (host, port))
3705 finally:
3706 c.close()
3707 finally:
3708 finish = True
3709 t.join()
3710 server.close()
3711
3712 def test_server_accept(self):
3713 # Issue #16357: accept() on a SSLSocket created through
3714 # SSLContext.wrap_socket().
Christian Heimes2875c602021-04-19 07:27:10 +02003715 client_ctx, server_ctx, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003716 server = socket.socket(socket.AF_INET)
3717 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003718 port = socket_helper.bind_port(server)
Christian Heimes2875c602021-04-19 07:27:10 +02003719 server = server_ctx.wrap_socket(server, server_side=True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003720 self.assertTrue(server.server_side)
3721
3722 evt = threading.Event()
3723 remote = None
3724 peer = None
3725 def serve():
3726 nonlocal remote, peer
3727 server.listen()
3728 # Block on the accept and wait on the connection to close.
3729 evt.set()
3730 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003731 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003732
3733 t = threading.Thread(target=serve)
3734 t.start()
3735 # Client wait until server setup and perform a connect.
3736 evt.wait()
Christian Heimes2875c602021-04-19 07:27:10 +02003737 client = client_ctx.wrap_socket(
3738 socket.socket(), server_hostname=hostname
3739 )
3740 client.connect((hostname, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003741 client.send(b'data')
3742 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003743 client_addr = client.getsockname()
3744 client.close()
3745 t.join()
3746 remote.close()
3747 server.close()
3748 # Sanity checks.
3749 self.assertIsInstance(remote, ssl.SSLSocket)
3750 self.assertEqual(peer, client_addr)
3751
3752 def test_getpeercert_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003753 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3754 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003755 with context.wrap_socket(socket.socket()) as sock:
3756 with self.assertRaises(OSError) as cm:
3757 sock.getpeercert()
3758 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3759
3760 def test_do_handshake_enotconn(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003761 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3762 context.check_hostname = False
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003763 with context.wrap_socket(socket.socket()) as sock:
3764 with self.assertRaises(OSError) as cm:
3765 sock.do_handshake()
3766 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3767
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003768 def test_no_shared_ciphers(self):
3769 client_context, server_context, hostname = testing_context()
3770 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3771 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003772 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003773 client_context.set_ciphers("AES128")
3774 server_context.set_ciphers("AES256")
3775 with ThreadedEchoServer(context=server_context) as server:
3776 with client_context.wrap_socket(socket.socket(),
3777 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003778 with self.assertRaises(OSError):
3779 s.connect((HOST, server.port))
3780 self.assertIn("no shared cipher", server.conn_errors[0])
3781
3782 def test_version_basic(self):
3783 """
3784 Basic tests for SSLSocket.version().
3785 More tests are done in the test_protocol_*() methods.
3786 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003787 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3788 context.check_hostname = False
3789 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003790 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003791 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003792 chatty=False) as server:
3793 with context.wrap_socket(socket.socket()) as s:
3794 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003795 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003796 s.connect((HOST, server.port))
Christian Heimes39258d32021-04-17 11:36:35 +02003797 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimes141c5e82018-02-24 21:10:57 +01003798 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003799 self.assertIs(s.version(), None)
3800
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003801 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003802 def test_tls1_3(self):
Christian Heimes2875c602021-04-19 07:27:10 +02003803 client_context, server_context, hostname = testing_context()
3804 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3805 with ThreadedEchoServer(context=server_context) as server:
3806 with client_context.wrap_socket(socket.socket(),
3807 server_hostname=hostname) as s:
Christian Heimescb5b68a2017-09-07 18:07:00 -07003808 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003809 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003810 'TLS_AES_256_GCM_SHA384',
3811 'TLS_CHACHA20_POLY1305_SHA256',
3812 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003813 })
3814 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003815
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003816 @requires_tls_version('TLSv1_2')
Christian Heimes2875c602021-04-19 07:27:10 +02003817 @requires_tls_version('TLSv1')
3818 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003819 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003820 client_context, server_context, hostname = testing_context()
3821 # client TLSv1.0 to 1.2
3822 client_context.minimum_version = ssl.TLSVersion.TLSv1
3823 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3824 # server only TLSv1.2
3825 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3826 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3827
3828 with ThreadedEchoServer(context=server_context) as server:
3829 with client_context.wrap_socket(socket.socket(),
3830 server_hostname=hostname) as s:
3831 s.connect((HOST, server.port))
3832 self.assertEqual(s.version(), 'TLSv1.2')
3833
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003834 @requires_tls_version('TLSv1_1')
Christian Heimes2875c602021-04-19 07:27:10 +02003835 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003836 def test_min_max_version_tlsv1_1(self):
3837 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003838 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003839 client_context.minimum_version = ssl.TLSVersion.TLSv1
3840 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003841 server_context.minimum_version = ssl.TLSVersion.TLSv1
3842 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003843 seclevel_workaround(client_context, server_context)
Christian Heimes698dde12018-02-27 11:54:43 +01003844
3845 with ThreadedEchoServer(context=server_context) as server:
3846 with client_context.wrap_socket(socket.socket(),
3847 server_hostname=hostname) as s:
3848 s.connect((HOST, server.port))
3849 self.assertEqual(s.version(), 'TLSv1.1')
3850
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003851 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003852 @requires_tls_version('TLSv1')
Christian Heimes2875c602021-04-19 07:27:10 +02003853 @ignore_deprecation
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003854 def test_min_max_version_mismatch(self):
3855 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003856 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003857 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003858 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003859 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003860 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimesf6c6b582021-03-18 23:06:50 +01003861 seclevel_workaround(client_context, server_context)
3862
Christian Heimes698dde12018-02-27 11:54:43 +01003863 with ThreadedEchoServer(context=server_context) as server:
3864 with client_context.wrap_socket(socket.socket(),
3865 server_hostname=hostname) as s:
3866 with self.assertRaises(ssl.SSLError) as e:
3867 s.connect((HOST, server.port))
3868 self.assertIn("alert", str(e.exception))
3869
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003870 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003871 def test_min_max_version_sslv3(self):
3872 client_context, server_context, hostname = testing_context()
3873 server_context.minimum_version = ssl.TLSVersion.SSLv3
3874 client_context.minimum_version = ssl.TLSVersion.SSLv3
3875 client_context.maximum_version = ssl.TLSVersion.SSLv3
Christian Heimesf6c6b582021-03-18 23:06:50 +01003876 seclevel_workaround(client_context, server_context)
3877
Christian Heimes698dde12018-02-27 11:54:43 +01003878 with ThreadedEchoServer(context=server_context) as server:
3879 with client_context.wrap_socket(socket.socket(),
3880 server_hostname=hostname) as s:
3881 s.connect((HOST, server.port))
3882 self.assertEqual(s.version(), 'SSLv3')
3883
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003884 def test_default_ecdh_curve(self):
3885 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3886 # should be enabled by default on SSL contexts.
Christian Heimes2875c602021-04-19 07:27:10 +02003887 client_context, server_context, hostname = testing_context()
Christian Heimescb5b68a2017-09-07 18:07:00 -07003888 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3889 # cipher name.
Christian Heimes2875c602021-04-19 07:27:10 +02003890 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003891 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3892 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3893 # our default cipher list should prefer ECDH-based ciphers
3894 # automatically.
Christian Heimes2875c602021-04-19 07:27:10 +02003895 with ThreadedEchoServer(context=server_context) as server:
3896 with client_context.wrap_socket(socket.socket(),
3897 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003898 s.connect((HOST, server.port))
3899 self.assertIn("ECDH", s.cipher()[0])
3900
3901 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3902 "'tls-unique' channel binding not available")
3903 def test_tls_unique_channel_binding(self):
3904 """Test tls-unique channel binding."""
3905 if support.verbose:
3906 sys.stdout.write("\n")
3907
Christian Heimes05d9fe32018-02-27 08:55:39 +01003908 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003909
3910 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003911 chatty=True,
3912 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003913
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003914 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003915 with client_context.wrap_socket(
3916 socket.socket(),
3917 server_hostname=hostname) as s:
3918 s.connect((HOST, server.port))
3919 # get the data
3920 cb_data = s.get_channel_binding("tls-unique")
3921 if support.verbose:
3922 sys.stdout.write(
3923 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003924
Christian Heimes05d9fe32018-02-27 08:55:39 +01003925 # check if it is sane
3926 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003927 if s.version() == 'TLSv1.3':
3928 self.assertEqual(len(cb_data), 48)
3929 else:
3930 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003931
Christian Heimes05d9fe32018-02-27 08:55:39 +01003932 # and compare with the peers version
3933 s.write(b"CB tls-unique\n")
3934 peer_data_repr = s.read().strip()
3935 self.assertEqual(peer_data_repr,
3936 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003937
3938 # now, again
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 new_cb_data = s.get_channel_binding("tls-unique")
3944 if support.verbose:
3945 sys.stdout.write(
3946 "got another channel binding data: {0!r}\n".format(
3947 new_cb_data)
3948 )
3949 # is it really unique
3950 self.assertNotEqual(cb_data, new_cb_data)
3951 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003952 if s.version() == 'TLSv1.3':
3953 self.assertEqual(len(cb_data), 48)
3954 else:
3955 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003956 s.write(b"CB tls-unique\n")
3957 peer_data_repr = s.read().strip()
3958 self.assertEqual(peer_data_repr,
3959 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003960
3961 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003962 client_context, server_context, hostname = testing_context()
3963 stats = server_params_test(client_context, server_context,
3964 chatty=True, connectionchatty=True,
3965 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003966 if support.verbose:
3967 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
3968 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
3969
3970 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
3971 "ssl.OP_NO_COMPRESSION needed for this test")
3972 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003973 client_context, server_context, hostname = testing_context()
3974 client_context.options |= ssl.OP_NO_COMPRESSION
3975 server_context.options |= ssl.OP_NO_COMPRESSION
3976 stats = server_params_test(client_context, server_context,
3977 chatty=True, connectionchatty=True,
3978 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003979 self.assertIs(stats['compression'], None)
3980
Paul Monsonf3550692019-06-19 13:09:54 -07003981 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003982 def test_dh_params(self):
3983 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02003984 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003985 # test scenario needs TLS <= 1.2
3986 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02003987 server_context.load_dh_params(DHFILE)
3988 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01003989 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02003990 stats = server_params_test(client_context, server_context,
3991 chatty=True, connectionchatty=True,
3992 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003993 cipher = stats["cipher"][0]
3994 parts = cipher.split("-")
3995 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
3996 self.fail("Non-DH cipher: " + cipher[0])
3997
Christian Heimesb7b92252018-02-25 09:49:31 +01003998 def test_ecdh_curve(self):
3999 # server secp384r1, client auto
4000 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004001
Christian Heimesb7b92252018-02-25 09:49:31 +01004002 server_context.set_ecdh_curve("secp384r1")
4003 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004004 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004005 stats = server_params_test(client_context, server_context,
4006 chatty=True, connectionchatty=True,
4007 sni_name=hostname)
4008
4009 # server auto, client secp384r1
4010 client_context, server_context, hostname = testing_context()
4011 client_context.set_ecdh_curve("secp384r1")
4012 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004013 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesb7b92252018-02-25 09:49:31 +01004014 stats = server_params_test(client_context, server_context,
4015 chatty=True, connectionchatty=True,
4016 sni_name=hostname)
4017
4018 # server / client curve mismatch
4019 client_context, server_context, hostname = testing_context()
4020 client_context.set_ecdh_curve("prime256v1")
4021 server_context.set_ecdh_curve("secp384r1")
4022 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
Christian Heimesd37b74f2021-04-19 08:31:29 +02004023 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
4024 with self.assertRaises(ssl.SSLError):
Christian Heimes39258d32021-04-17 11:36:35 +02004025 server_params_test(client_context, server_context,
4026 chatty=True, connectionchatty=True,
4027 sni_name=hostname)
Christian Heimesb7b92252018-02-25 09:49:31 +01004028
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004029 def test_selected_alpn_protocol(self):
4030 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004031 client_context, server_context, hostname = testing_context()
4032 stats = server_params_test(client_context, server_context,
4033 chatty=True, connectionchatty=True,
4034 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004035 self.assertIs(stats['client_alpn_protocol'], None)
4036
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004037 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4038 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004039 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004040 server_context.set_alpn_protocols(['foo', 'bar'])
4041 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004042 chatty=True, connectionchatty=True,
4043 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004044 self.assertIs(stats['client_alpn_protocol'], None)
4045
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004046 def test_alpn_protocols(self):
4047 server_protocols = ['foo', 'bar', 'milkshake']
4048 protocol_tests = [
4049 (['foo', 'bar'], 'foo'),
4050 (['bar', 'foo'], 'foo'),
4051 (['milkshake'], 'milkshake'),
4052 (['http/3.0', 'http/4.0'], None)
4053 ]
4054 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004055 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004056 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004057 client_context.set_alpn_protocols(client_protocols)
4058
4059 try:
4060 stats = server_params_test(client_context,
4061 server_context,
4062 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004063 connectionchatty=True,
4064 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004065 except ssl.SSLError as e:
4066 stats = e
4067
Christian Heimes39258d32021-04-17 11:36:35 +02004068 msg = "failed trying %s (s) and %s (c).\n" \
4069 "was expecting %s, but got %%s from the %%s" \
4070 % (str(server_protocols), str(client_protocols),
4071 str(expected))
4072 client_result = stats['client_alpn_protocol']
4073 self.assertEqual(client_result, expected,
4074 msg % (client_result, "client"))
4075 server_result = stats['server_alpn_protocols'][-1] \
4076 if len(stats['server_alpn_protocols']) else 'nothing'
4077 self.assertEqual(server_result, expected,
4078 msg % (server_result, "server"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004079
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004080 def test_npn_protocols(self):
Christian Heimes39258d32021-04-17 11:36:35 +02004081 assert not ssl.HAS_NPN
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004082
4083 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004084 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004085 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004086 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004087 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004088 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004089 client_context.load_verify_locations(SIGNING_CA)
4090 return server_context, other_context, client_context
4091
4092 def check_common_name(self, stats, name):
4093 cert = stats['peercert']
4094 self.assertIn((('commonName', name),), cert['subject'])
4095
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004096 def test_sni_callback(self):
4097 calls = []
4098 server_context, other_context, client_context = self.sni_contexts()
4099
Christian Heimesa170fa12017-09-15 20:27:30 +02004100 client_context.check_hostname = False
4101
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004102 def servername_cb(ssl_sock, server_name, initial_context):
4103 calls.append((server_name, initial_context))
4104 if server_name is not None:
4105 ssl_sock.context = other_context
4106 server_context.set_servername_callback(servername_cb)
4107
4108 stats = server_params_test(client_context, server_context,
4109 chatty=True,
4110 sni_name='supermessage')
4111 # The hostname was fetched properly, and the certificate was
4112 # changed for the connection.
4113 self.assertEqual(calls, [("supermessage", server_context)])
4114 # CERTFILE4 was selected
4115 self.check_common_name(stats, 'fakehostname')
4116
4117 calls = []
4118 # The callback is called with server_name=None
4119 stats = server_params_test(client_context, server_context,
4120 chatty=True,
4121 sni_name=None)
4122 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004123 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004124
4125 # Check disabling the callback
4126 calls = []
4127 server_context.set_servername_callback(None)
4128
4129 stats = server_params_test(client_context, server_context,
4130 chatty=True,
4131 sni_name='notfunny')
4132 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004133 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004134 self.assertEqual(calls, [])
4135
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004136 def test_sni_callback_alert(self):
4137 # Returning a TLS alert is reflected to the connecting client
4138 server_context, other_context, client_context = self.sni_contexts()
4139
4140 def cb_returning_alert(ssl_sock, server_name, initial_context):
4141 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4142 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004143 with self.assertRaises(ssl.SSLError) as cm:
4144 stats = server_params_test(client_context, server_context,
4145 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004146 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004147 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004148
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004149 def test_sni_callback_raising(self):
4150 # Raising fails the connection with a TLS handshake failure alert.
4151 server_context, other_context, client_context = self.sni_contexts()
4152
4153 def cb_raising(ssl_sock, server_name, initial_context):
4154 1/0
4155 server_context.set_servername_callback(cb_raising)
4156
Victor Stinner00253502019-06-03 03:51:43 +02004157 with support.catch_unraisable_exception() as catch:
4158 with self.assertRaises(ssl.SSLError) as cm:
4159 stats = server_params_test(client_context, server_context,
4160 chatty=False,
4161 sni_name='supermessage')
4162
4163 self.assertEqual(cm.exception.reason,
4164 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4165 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004166
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004167 def test_sni_callback_wrong_return_type(self):
4168 # Returning the wrong return type terminates the TLS connection
4169 # with an internal error alert.
4170 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004171
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004172 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4173 return "foo"
4174 server_context.set_servername_callback(cb_wrong_return_type)
4175
Victor Stinner00253502019-06-03 03:51:43 +02004176 with support.catch_unraisable_exception() as catch:
4177 with self.assertRaises(ssl.SSLError) as cm:
4178 stats = server_params_test(client_context, server_context,
4179 chatty=False,
4180 sni_name='supermessage')
4181
4182
4183 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4184 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004185
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004186 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004187 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004188 client_context.set_ciphers("AES128:AES256")
4189 server_context.set_ciphers("AES256")
4190 expected_algs = [
4191 "AES256", "AES-256",
4192 # TLS 1.3 ciphers are always enabled
4193 "TLS_CHACHA20", "TLS_AES",
4194 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004195
Christian Heimesa170fa12017-09-15 20:27:30 +02004196 stats = server_params_test(client_context, server_context,
4197 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004198 ciphers = stats['server_shared_ciphers'][0]
4199 self.assertGreater(len(ciphers), 0)
4200 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004201 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004202 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004203
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004204 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004205 client_context, server_context, hostname = testing_context()
4206 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004207
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004208 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004209 s = client_context.wrap_socket(socket.socket(),
4210 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004211 s.connect((HOST, server.port))
4212 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004213
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004214 self.assertRaises(ValueError, s.read, 1024)
4215 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004216
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004217 def test_sendfile(self):
4218 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004219 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004220 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004221 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimes2875c602021-04-19 07:27:10 +02004222 client_context, server_context, hostname = testing_context()
4223 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004224 with server:
Christian Heimes2875c602021-04-19 07:27:10 +02004225 with client_context.wrap_socket(socket.socket(),
4226 server_hostname=hostname) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004227 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004228 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004229 s.sendfile(file)
4230 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004231
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004232 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004233 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004234 # TODO: sessions aren't compatible with TLSv1.3 yet
4235 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004236
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004237 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004238 stats = server_params_test(client_context, server_context,
4239 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004240 session = stats['session']
4241 self.assertTrue(session.id)
4242 self.assertGreater(session.time, 0)
4243 self.assertGreater(session.timeout, 0)
4244 self.assertTrue(session.has_ticket)
Christian Heimes39258d32021-04-17 11:36:35 +02004245 self.assertGreater(session.ticket_lifetime_hint, 0)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004246 self.assertFalse(stats['session_reused'])
4247 sess_stat = server_context.session_stats()
4248 self.assertEqual(sess_stat['accept'], 1)
4249 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004250
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004251 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004252 stats = server_params_test(client_context, server_context,
4253 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004254 sess_stat = server_context.session_stats()
4255 self.assertEqual(sess_stat['accept'], 2)
4256 self.assertEqual(sess_stat['hits'], 1)
4257 self.assertTrue(stats['session_reused'])
4258 session2 = stats['session']
4259 self.assertEqual(session2.id, session.id)
4260 self.assertEqual(session2, session)
4261 self.assertIsNot(session2, session)
4262 self.assertGreaterEqual(session2.time, session.time)
4263 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004264
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004265 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004266 stats = server_params_test(client_context, server_context,
4267 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004268 self.assertFalse(stats['session_reused'])
4269 session3 = stats['session']
4270 self.assertNotEqual(session3.id, session.id)
4271 self.assertNotEqual(session3, session)
4272 sess_stat = server_context.session_stats()
4273 self.assertEqual(sess_stat['accept'], 3)
4274 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004275
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004276 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004277 stats = server_params_test(client_context, server_context,
4278 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004279 self.assertTrue(stats['session_reused'])
4280 session4 = stats['session']
4281 self.assertEqual(session4.id, session.id)
4282 self.assertEqual(session4, session)
4283 self.assertGreaterEqual(session4.time, session.time)
4284 self.assertGreaterEqual(session4.timeout, session.timeout)
4285 sess_stat = server_context.session_stats()
4286 self.assertEqual(sess_stat['accept'], 4)
4287 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004288
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004289 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004290 client_context, server_context, hostname = testing_context()
4291 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004292
Christian Heimes05d9fe32018-02-27 08:55:39 +01004293 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004294 client_context.options |= ssl.OP_NO_TLSv1_3
4295 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004296
Christian Heimesa170fa12017-09-15 20:27:30 +02004297 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004298 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004299 with client_context.wrap_socket(socket.socket(),
4300 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004301 # session is None before handshake
4302 self.assertEqual(s.session, None)
4303 self.assertEqual(s.session_reused, None)
4304 s.connect((HOST, server.port))
4305 session = s.session
4306 self.assertTrue(session)
4307 with self.assertRaises(TypeError) as e:
4308 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004309 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004310
Christian Heimesa170fa12017-09-15 20:27:30 +02004311 with client_context.wrap_socket(socket.socket(),
4312 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004313 s.connect((HOST, server.port))
4314 # cannot set session after handshake
4315 with self.assertRaises(ValueError) as e:
4316 s.session = session
4317 self.assertEqual(str(e.exception),
4318 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004319
Christian Heimesa170fa12017-09-15 20:27:30 +02004320 with client_context.wrap_socket(socket.socket(),
4321 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004322 # can set session before handshake and before the
4323 # connection was established
4324 s.session = session
4325 s.connect((HOST, server.port))
4326 self.assertEqual(s.session.id, session.id)
4327 self.assertEqual(s.session, session)
4328 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004329
Christian Heimesa170fa12017-09-15 20:27:30 +02004330 with client_context2.wrap_socket(socket.socket(),
4331 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004332 # cannot re-use session with a different SSLContext
4333 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004334 s.session = session
4335 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004336 self.assertEqual(str(e.exception),
4337 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004338
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004339
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004340@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004341class TestPostHandshakeAuth(unittest.TestCase):
4342 def test_pha_setter(self):
4343 protocols = [
Christian Heimes2875c602021-04-19 07:27:10 +02004344 ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
Christian Heimes9fb051f2018-09-23 08:32:31 +02004345 ]
4346 for protocol in protocols:
4347 ctx = ssl.SSLContext(protocol)
4348 self.assertEqual(ctx.post_handshake_auth, False)
4349
4350 ctx.post_handshake_auth = True
4351 self.assertEqual(ctx.post_handshake_auth, True)
4352
4353 ctx.verify_mode = ssl.CERT_REQUIRED
4354 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4355 self.assertEqual(ctx.post_handshake_auth, True)
4356
4357 ctx.post_handshake_auth = False
4358 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4359 self.assertEqual(ctx.post_handshake_auth, False)
4360
4361 ctx.verify_mode = ssl.CERT_OPTIONAL
4362 ctx.post_handshake_auth = True
4363 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4364 self.assertEqual(ctx.post_handshake_auth, True)
4365
4366 def test_pha_required(self):
4367 client_context, server_context, hostname = testing_context()
4368 server_context.post_handshake_auth = True
4369 server_context.verify_mode = ssl.CERT_REQUIRED
4370 client_context.post_handshake_auth = True
4371 client_context.load_cert_chain(SIGNED_CERTFILE)
4372
4373 server = ThreadedEchoServer(context=server_context, chatty=False)
4374 with server:
4375 with client_context.wrap_socket(socket.socket(),
4376 server_hostname=hostname) as s:
4377 s.connect((HOST, server.port))
4378 s.write(b'HASCERT')
4379 self.assertEqual(s.recv(1024), b'FALSE\n')
4380 s.write(b'PHA')
4381 self.assertEqual(s.recv(1024), b'OK\n')
4382 s.write(b'HASCERT')
4383 self.assertEqual(s.recv(1024), b'TRUE\n')
4384 # PHA method just returns true when cert is already available
4385 s.write(b'PHA')
4386 self.assertEqual(s.recv(1024), b'OK\n')
4387 s.write(b'GETCERT')
4388 cert_text = s.recv(4096).decode('us-ascii')
4389 self.assertIn('Python Software Foundation CA', cert_text)
4390
4391 def test_pha_required_nocert(self):
4392 client_context, server_context, hostname = testing_context()
4393 server_context.post_handshake_auth = True
4394 server_context.verify_mode = ssl.CERT_REQUIRED
4395 client_context.post_handshake_auth = True
4396
Victor Stinner73ea5462019-07-09 14:33:49 +02004397 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4398 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004399 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004400 server = ThreadedEchoServer(context=server_context, chatty=False)
4401 with server:
4402 with client_context.wrap_socket(socket.socket(),
4403 server_hostname=hostname) as s:
4404 s.connect((HOST, server.port))
4405 s.write(b'PHA')
4406 # receive CertificateRequest
4407 self.assertEqual(s.recv(1024), b'OK\n')
4408 # send empty Certificate + Finish
4409 s.write(b'HASCERT')
4410 # receive alert
4411 with self.assertRaisesRegex(
4412 ssl.SSLError,
4413 'tlsv13 alert certificate required'):
4414 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004415
4416 def test_pha_optional(self):
4417 if support.verbose:
4418 sys.stdout.write("\n")
4419
4420 client_context, server_context, hostname = testing_context()
4421 server_context.post_handshake_auth = True
4422 server_context.verify_mode = ssl.CERT_REQUIRED
4423 client_context.post_handshake_auth = True
4424 client_context.load_cert_chain(SIGNED_CERTFILE)
4425
4426 # check CERT_OPTIONAL
4427 server_context.verify_mode = ssl.CERT_OPTIONAL
4428 server = ThreadedEchoServer(context=server_context, chatty=False)
4429 with server:
4430 with client_context.wrap_socket(socket.socket(),
4431 server_hostname=hostname) as s:
4432 s.connect((HOST, server.port))
4433 s.write(b'HASCERT')
4434 self.assertEqual(s.recv(1024), b'FALSE\n')
4435 s.write(b'PHA')
4436 self.assertEqual(s.recv(1024), b'OK\n')
4437 s.write(b'HASCERT')
4438 self.assertEqual(s.recv(1024), b'TRUE\n')
4439
4440 def test_pha_optional_nocert(self):
4441 if support.verbose:
4442 sys.stdout.write("\n")
4443
4444 client_context, server_context, hostname = testing_context()
4445 server_context.post_handshake_auth = True
4446 server_context.verify_mode = ssl.CERT_OPTIONAL
4447 client_context.post_handshake_auth = True
4448
4449 server = ThreadedEchoServer(context=server_context, chatty=False)
4450 with server:
4451 with client_context.wrap_socket(socket.socket(),
4452 server_hostname=hostname) as s:
4453 s.connect((HOST, server.port))
4454 s.write(b'HASCERT')
4455 self.assertEqual(s.recv(1024), b'FALSE\n')
4456 s.write(b'PHA')
4457 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004458 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004459 s.write(b'HASCERT')
4460 self.assertEqual(s.recv(1024), b'FALSE\n')
4461
4462 def test_pha_no_pha_client(self):
4463 client_context, server_context, hostname = testing_context()
4464 server_context.post_handshake_auth = True
4465 server_context.verify_mode = ssl.CERT_REQUIRED
4466 client_context.load_cert_chain(SIGNED_CERTFILE)
4467
4468 server = ThreadedEchoServer(context=server_context, chatty=False)
4469 with server:
4470 with client_context.wrap_socket(socket.socket(),
4471 server_hostname=hostname) as s:
4472 s.connect((HOST, server.port))
4473 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4474 s.verify_client_post_handshake()
4475 s.write(b'PHA')
4476 self.assertIn(b'extension not received', s.recv(1024))
4477
4478 def test_pha_no_pha_server(self):
4479 # server doesn't have PHA enabled, cert is requested in handshake
4480 client_context, server_context, hostname = testing_context()
4481 server_context.verify_mode = ssl.CERT_REQUIRED
4482 client_context.post_handshake_auth = True
4483 client_context.load_cert_chain(SIGNED_CERTFILE)
4484
4485 server = ThreadedEchoServer(context=server_context, chatty=False)
4486 with server:
4487 with client_context.wrap_socket(socket.socket(),
4488 server_hostname=hostname) as s:
4489 s.connect((HOST, server.port))
4490 s.write(b'HASCERT')
4491 self.assertEqual(s.recv(1024), b'TRUE\n')
4492 # PHA doesn't fail if there is already a cert
4493 s.write(b'PHA')
4494 self.assertEqual(s.recv(1024), b'OK\n')
4495 s.write(b'HASCERT')
4496 self.assertEqual(s.recv(1024), b'TRUE\n')
4497
4498 def test_pha_not_tls13(self):
4499 # TLS 1.2
4500 client_context, server_context, hostname = testing_context()
4501 server_context.verify_mode = ssl.CERT_REQUIRED
4502 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4503 client_context.post_handshake_auth = True
4504 client_context.load_cert_chain(SIGNED_CERTFILE)
4505
4506 server = ThreadedEchoServer(context=server_context, chatty=False)
4507 with server:
4508 with client_context.wrap_socket(socket.socket(),
4509 server_hostname=hostname) as s:
4510 s.connect((HOST, server.port))
4511 # PHA fails for TLS != 1.3
4512 s.write(b'PHA')
4513 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4514
Christian Heimesf0f59302019-07-01 08:29:17 +02004515 def test_bpo37428_pha_cert_none(self):
4516 # verify that post_handshake_auth does not implicitly enable cert
4517 # validation.
4518 hostname = SIGNED_CERTFILE_HOSTNAME
4519 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4520 client_context.post_handshake_auth = True
4521 client_context.load_cert_chain(SIGNED_CERTFILE)
4522 # no cert validation and CA on client side
4523 client_context.check_hostname = False
4524 client_context.verify_mode = ssl.CERT_NONE
4525
4526 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4527 server_context.load_cert_chain(SIGNED_CERTFILE)
4528 server_context.load_verify_locations(SIGNING_CA)
4529 server_context.post_handshake_auth = True
4530 server_context.verify_mode = ssl.CERT_REQUIRED
4531
4532 server = ThreadedEchoServer(context=server_context, chatty=False)
4533 with server:
4534 with client_context.wrap_socket(socket.socket(),
4535 server_hostname=hostname) as s:
4536 s.connect((HOST, server.port))
4537 s.write(b'HASCERT')
4538 self.assertEqual(s.recv(1024), b'FALSE\n')
4539 s.write(b'PHA')
4540 self.assertEqual(s.recv(1024), b'OK\n')
4541 s.write(b'HASCERT')
4542 self.assertEqual(s.recv(1024), b'TRUE\n')
4543 # server cert has not been validated
4544 self.assertEqual(s.getpeercert(), {})
4545
Christian Heimes9fb051f2018-09-23 08:32:31 +02004546
Christian Heimesc7f70692019-05-31 11:44:05 +02004547HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4548requires_keylog = unittest.skipUnless(
4549 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4550
4551class TestSSLDebug(unittest.TestCase):
4552
Hai Shia7f5d932020-08-04 00:41:24 +08004553 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004554 with open(fname) as f:
4555 return len(list(f))
4556
4557 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004558 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004559 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004560 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004561 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4562 self.assertEqual(ctx.keylog_filename, None)
4563
Hai Shia7f5d932020-08-04 00:41:24 +08004564 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4565 ctx.keylog_filename = os_helper.TESTFN
4566 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4567 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004568 self.assertEqual(self.keylog_lines(), 1)
4569
4570 ctx.keylog_filename = None
4571 self.assertEqual(ctx.keylog_filename, None)
4572
4573 with self.assertRaises((IsADirectoryError, PermissionError)):
4574 # Windows raises PermissionError
4575 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004576 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004577
4578 with self.assertRaises(TypeError):
4579 ctx.keylog_filename = 1
4580
4581 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004582 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004583 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004584 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004585 client_context, server_context, hostname = testing_context()
4586
Hai Shia7f5d932020-08-04 00:41:24 +08004587 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004588 server = ThreadedEchoServer(context=server_context, chatty=False)
4589 with server:
4590 with client_context.wrap_socket(socket.socket(),
4591 server_hostname=hostname) as s:
4592 s.connect((HOST, server.port))
4593 # header, 5 lines for TLS 1.3
4594 self.assertEqual(self.keylog_lines(), 6)
4595
4596 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004597 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004598 server = ThreadedEchoServer(context=server_context, chatty=False)
4599 with server:
4600 with client_context.wrap_socket(socket.socket(),
4601 server_hostname=hostname) as s:
4602 s.connect((HOST, server.port))
4603 self.assertGreaterEqual(self.keylog_lines(), 11)
4604
Hai Shia7f5d932020-08-04 00:41:24 +08004605 client_context.keylog_filename = os_helper.TESTFN
4606 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004607 server = ThreadedEchoServer(context=server_context, chatty=False)
4608 with server:
4609 with client_context.wrap_socket(socket.socket(),
4610 server_hostname=hostname) as s:
4611 s.connect((HOST, server.port))
4612 self.assertGreaterEqual(self.keylog_lines(), 21)
4613
4614 client_context.keylog_filename = None
4615 server_context.keylog_filename = None
4616
4617 @requires_keylog
4618 @unittest.skipIf(sys.flags.ignore_environment,
4619 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004620 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004621 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004622 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004623 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004624 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4625 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004626
4627 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4628 self.assertEqual(ctx.keylog_filename, None)
4629
4630 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004631 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004632
4633 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004634 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004635
4636 def test_msg_callback(self):
4637 client_context, server_context, hostname = testing_context()
4638
4639 def msg_cb(conn, direction, version, content_type, msg_type, data):
4640 pass
4641
4642 self.assertIs(client_context._msg_callback, None)
4643 client_context._msg_callback = msg_cb
4644 self.assertIs(client_context._msg_callback, msg_cb)
4645 with self.assertRaises(TypeError):
4646 client_context._msg_callback = object()
4647
4648 def test_msg_callback_tls12(self):
4649 client_context, server_context, hostname = testing_context()
4650 client_context.options |= ssl.OP_NO_TLSv1_3
4651
4652 msg = []
4653
4654 def msg_cb(conn, direction, version, content_type, msg_type, data):
4655 self.assertIsInstance(conn, ssl.SSLSocket)
4656 self.assertIsInstance(data, bytes)
4657 self.assertIn(direction, {'read', 'write'})
4658 msg.append((direction, version, content_type, msg_type))
4659
4660 client_context._msg_callback = msg_cb
4661
4662 server = ThreadedEchoServer(context=server_context, chatty=False)
4663 with server:
4664 with client_context.wrap_socket(socket.socket(),
4665 server_hostname=hostname) as s:
4666 s.connect((HOST, server.port))
4667
Christian Heimese35d1ba2019-06-03 20:40:15 +02004668 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004669 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4670 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004671 msg
4672 )
4673 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004674 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4675 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004676 msg
4677 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004678
Christian Heimes77cde502021-03-21 16:13:09 +01004679 def test_msg_callback_deadlock_bpo43577(self):
4680 client_context, server_context, hostname = testing_context()
4681 server_context2 = testing_context()[1]
4682
4683 def msg_cb(conn, direction, version, content_type, msg_type, data):
4684 pass
4685
4686 def sni_cb(sock, servername, ctx):
4687 sock.context = server_context2
4688
4689 server_context._msg_callback = msg_cb
4690 server_context.sni_callback = sni_cb
4691
4692 server = ThreadedEchoServer(context=server_context, chatty=False)
4693 with server:
4694 with client_context.wrap_socket(socket.socket(),
4695 server_hostname=hostname) as s:
4696 s.connect((HOST, server.port))
4697 with client_context.wrap_socket(socket.socket(),
4698 server_hostname=hostname) as s:
4699 s.connect((HOST, server.port))
4700
Christian Heimesc7f70692019-05-31 11:44:05 +02004701
Ethan Furmana02cb472021-04-21 10:20:44 -07004702class TestEnumerations(unittest.TestCase):
4703
4704 def test_tlsversion(self):
4705 class CheckedTLSVersion(enum.IntEnum):
4706 MINIMUM_SUPPORTED = _ssl.PROTO_MINIMUM_SUPPORTED
4707 SSLv3 = _ssl.PROTO_SSLv3
4708 TLSv1 = _ssl.PROTO_TLSv1
4709 TLSv1_1 = _ssl.PROTO_TLSv1_1
4710 TLSv1_2 = _ssl.PROTO_TLSv1_2
4711 TLSv1_3 = _ssl.PROTO_TLSv1_3
4712 MAXIMUM_SUPPORTED = _ssl.PROTO_MAXIMUM_SUPPORTED
4713 enum._test_simple_enum(CheckedTLSVersion, TLSVersion)
4714
4715 def test_tlscontenttype(self):
4716 class Checked_TLSContentType(enum.IntEnum):
4717 """Content types (record layer)
4718
4719 See RFC 8446, section B.1
4720 """
4721 CHANGE_CIPHER_SPEC = 20
4722 ALERT = 21
4723 HANDSHAKE = 22
4724 APPLICATION_DATA = 23
4725 # pseudo content types
4726 HEADER = 0x100
4727 INNER_CONTENT_TYPE = 0x101
4728 enum._test_simple_enum(Checked_TLSContentType, _TLSContentType)
4729
4730 def test_tlsalerttype(self):
4731 class Checked_TLSAlertType(enum.IntEnum):
4732 """Alert types for TLSContentType.ALERT messages
4733
4734 See RFC 8466, section B.2
4735 """
4736 CLOSE_NOTIFY = 0
4737 UNEXPECTED_MESSAGE = 10
4738 BAD_RECORD_MAC = 20
4739 DECRYPTION_FAILED = 21
4740 RECORD_OVERFLOW = 22
4741 DECOMPRESSION_FAILURE = 30
4742 HANDSHAKE_FAILURE = 40
4743 NO_CERTIFICATE = 41
4744 BAD_CERTIFICATE = 42
4745 UNSUPPORTED_CERTIFICATE = 43
4746 CERTIFICATE_REVOKED = 44
4747 CERTIFICATE_EXPIRED = 45
4748 CERTIFICATE_UNKNOWN = 46
4749 ILLEGAL_PARAMETER = 47
4750 UNKNOWN_CA = 48
4751 ACCESS_DENIED = 49
4752 DECODE_ERROR = 50
4753 DECRYPT_ERROR = 51
4754 EXPORT_RESTRICTION = 60
4755 PROTOCOL_VERSION = 70
4756 INSUFFICIENT_SECURITY = 71
4757 INTERNAL_ERROR = 80
4758 INAPPROPRIATE_FALLBACK = 86
4759 USER_CANCELED = 90
4760 NO_RENEGOTIATION = 100
4761 MISSING_EXTENSION = 109
4762 UNSUPPORTED_EXTENSION = 110
4763 CERTIFICATE_UNOBTAINABLE = 111
4764 UNRECOGNIZED_NAME = 112
4765 BAD_CERTIFICATE_STATUS_RESPONSE = 113
4766 BAD_CERTIFICATE_HASH_VALUE = 114
4767 UNKNOWN_PSK_IDENTITY = 115
4768 CERTIFICATE_REQUIRED = 116
4769 NO_APPLICATION_PROTOCOL = 120
4770 enum._test_simple_enum(Checked_TLSAlertType, _TLSAlertType)
4771
4772 def test_tlsmessagetype(self):
4773 class Checked_TLSMessageType(enum.IntEnum):
4774 """Message types (handshake protocol)
4775
4776 See RFC 8446, section B.3
4777 """
4778 HELLO_REQUEST = 0
4779 CLIENT_HELLO = 1
4780 SERVER_HELLO = 2
4781 HELLO_VERIFY_REQUEST = 3
4782 NEWSESSION_TICKET = 4
4783 END_OF_EARLY_DATA = 5
4784 HELLO_RETRY_REQUEST = 6
4785 ENCRYPTED_EXTENSIONS = 8
4786 CERTIFICATE = 11
4787 SERVER_KEY_EXCHANGE = 12
4788 CERTIFICATE_REQUEST = 13
4789 SERVER_DONE = 14
4790 CERTIFICATE_VERIFY = 15
4791 CLIENT_KEY_EXCHANGE = 16
4792 FINISHED = 20
4793 CERTIFICATE_URL = 21
4794 CERTIFICATE_STATUS = 22
4795 SUPPLEMENTAL_DATA = 23
4796 KEY_UPDATE = 24
4797 NEXT_PROTO = 67
4798 MESSAGE_HASH = 254
4799 CHANGE_CIPHER_SPEC = 0x0101
4800 enum._test_simple_enum(Checked_TLSMessageType, _TLSMessageType)
4801
4802 def test_sslmethod(self):
4803 Checked_SSLMethod = enum._old_convert_(
4804 enum.IntEnum, '_SSLMethod', 'ssl',
4805 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4806 source=ssl._ssl,
4807 )
4808 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
4809
4810 def test_options(self):
4811 CheckedOptions = enum._old_convert_(
4812 enum.FlagEnum, 'Options', 'ssl',
4813 lambda name: name.startswith('OP_'),
4814 source=ssl._ssl,
4815 )
4816 enum._test_simple_enum(CheckedOptions, ssl.Options)
4817
4818
4819 def test_alertdescription(self):
4820 CheckedAlertDescription = enum._old_convert_(
4821 enum.IntEnum, 'AlertDescription', 'ssl',
4822 lambda name: name.startswith('ALERT_DESCRIPTION_'),
4823 source=ssl._ssl,
4824 )
4825 enum._test_simple_enum(CheckedAlertDescription, ssl.AlertDescription)
4826
4827 def test_sslerrornumber(self):
4828 Checked_SSLMethod = enum._old_convert_(
4829 enum.IntEnum, '_SSLMethod', 'ssl',
4830 lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
4831 source=ssl._ssl,
4832 )
4833 enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
4834
4835 def test_verifyflags(self):
4836 CheckedVerifyFlags = enum._old_convert_(
4837 enum.FlagEnum, 'VerifyFlags', 'ssl',
4838 lambda name: name.startswith('VERIFY_'),
4839 source=ssl._ssl,
4840 )
4841 enum._test_simple_enum(CheckedVerifyFlags, ssl.VerifyFlags)
4842
4843 def test_verifymode(self):
4844 CheckedVerifyMode = enum._old_convert_(
4845 enum.IntEnum, 'VerifyMode', 'ssl',
4846 lambda name: name.startswith('CERT_'),
4847 source=ssl._ssl,
4848 )
4849 enum._test_simple_enum(CheckedVerifyMode, ssl.VerifyMode)
4850
Thomas Woutersed03b412007-08-28 21:37:11 +00004851def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004852 if support.verbose:
4853 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004854 'Mac': platform.mac_ver,
4855 'Windows': platform.win32_ver,
4856 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004857 for name, func in plats.items():
4858 plat = func()
4859 if plat and plat[0]:
4860 plat = '%s %r' % (name, plat)
4861 break
4862 else:
4863 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004864 print("test_ssl: testing with %r %r" %
4865 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4866 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004867 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004868 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4869 try:
4870 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4871 except AttributeError:
4872 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004873
Antoine Pitrou152efa22010-05-16 18:19:27 +00004874 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004875 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004876 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004877 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004878 BADCERT, BADKEY, EMPTYCERT]:
4879 if not os.path.exists(filename):
4880 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004881
Martin Panter3840b2a2016-03-27 01:53:46 +00004882 tests = [
4883 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004884 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004885 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004886 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004887
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004888 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004889 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004890
Hai Shie80697d2020-05-28 06:10:27 +08004891 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004892 try:
4893 support.run_unittest(*tests)
4894 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004895 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004896
4897if __name__ == "__main__":
4898 test_main()