blob: 26eec969a82e0d75f90d06da5fc438f164a6a522 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Christian Heimesc7f70692019-05-31 11:44:05 +02005import unittest.mock
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Hai Shia7f5d932020-08-04 00:41:24 +08007from test.support import import_helper
8from test.support import os_helper
Serhiy Storchaka16994912020-04-25 10:06:29 +03009from test.support import socket_helper
Hai Shie80697d2020-05-28 06:10:27 +080010from test.support import threading_helper
Hai Shia7f5d932020-08-04 00:41:24 +080011from test.support import warnings_helper
Thomas Woutersed03b412007-08-28 21:37:11 +000012import socket
Bill Janssen6e027db2007-11-15 22:23:56 +000013import select
Thomas Woutersed03b412007-08-28 21:37:11 +000014import time
Christian Heimes9424bb42013-06-17 15:32:57 +020015import datetime
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000016import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000017import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000018import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000019import pprint
Antoine Pitrou803e6d62010-10-13 10:36:15 +000020import urllib.request
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020021import threading
Thomas Woutersed03b412007-08-28 21:37:11 +000022import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000023import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000024import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000025import platform
Christian Heimes892d66e2018-01-29 14:10:18 +010026import sysconfig
Christian Heimesdf6ac7e2019-09-26 17:02:59 +020027import functools
Christian Heimes888bbdc2017-09-07 14:18:21 -070028try:
29 import ctypes
30except ImportError:
31 ctypes = None
Thomas Woutersed03b412007-08-28 21:37:11 +000032
Hai Shia7f5d932020-08-04 00:41:24 +080033ssl = import_helper.import_module("ssl")
Antoine Pitrou05d936d2010-10-13 11:38:36 +000034
Victor Stinner8f4ef3b2019-07-01 18:28:25 +020035from ssl import TLSVersion, _TLSContentType, _TLSMessageType
Martin Panter3840b2a2016-03-27 01:53:46 +000036
Paul Monsonf3550692019-06-19 13:09:54 -070037Py_DEBUG = hasattr(sys, 'gettotalrefcount')
38Py_DEBUG_WIN32 = Py_DEBUG and sys.platform == 'win32'
39
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010040PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Serhiy Storchaka16994912020-04-25 10:06:29 +030041HOST = socket_helper.HOST
Christian Heimes598894f2016-09-05 23:19:05 +020042IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
Christian Heimes05d9fe32018-02-27 08:55:39 +010043IS_OPENSSL_1_1_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0)
44IS_OPENSSL_1_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1)
Christian Heimes892d66e2018-01-29 14:10:18 +010045PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
Antoine Pitrou152efa22010-05-16 18:19:27 +000046
Victor Stinner3ef63442019-02-19 18:06:03 +010047PROTOCOL_TO_TLS_VERSION = {}
48for proto, ver in (
49 ("PROTOCOL_SSLv23", "SSLv3"),
50 ("PROTOCOL_TLSv1", "TLSv1"),
51 ("PROTOCOL_TLSv1_1", "TLSv1_1"),
52):
53 try:
54 proto = getattr(ssl, proto)
55 ver = getattr(ssl.TLSVersion, ver)
56 except AttributeError:
57 continue
58 PROTOCOL_TO_TLS_VERSION[proto] = ver
59
Christian Heimesefff7062013-11-21 03:35:02 +010060def data_file(*name):
61 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000062
Antoine Pitrou81564092010-10-08 23:06:24 +000063# The custom key and certificate files used in test_ssl are generated
64# using Lib/test/make_ssl_certs.py.
65# Other certificates are simply fetched from the Internet servers they
66# are meant to authenticate.
67
Antoine Pitrou152efa22010-05-16 18:19:27 +000068CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000069BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000070ONLYCERT = data_file("ssl_cert.pem")
71ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000072BYTES_ONLYCERT = os.fsencode(ONLYCERT)
73BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020074CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
75ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
76KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000077CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000078BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010079CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
80CAFILE_CACERT = data_file("capath", "5ed36f99.0")
81
Christian Heimesbd5c7d22018-01-20 15:16:30 +010082CERTFILE_INFO = {
83 'issuer': ((('countryName', 'XY'),),
84 (('localityName', 'Castle Anthrax'),),
85 (('organizationName', 'Python Software Foundation'),),
86 (('commonName', 'localhost'),)),
Christian Heimese6dac002018-08-30 07:25:49 +020087 'notAfter': 'Aug 26 14:23:15 2028 GMT',
88 'notBefore': 'Aug 29 14:23:15 2018 GMT',
89 'serialNumber': '98A7CF88C74A32ED',
Christian Heimesbd5c7d22018-01-20 15:16:30 +010090 'subject': ((('countryName', 'XY'),),
91 (('localityName', 'Castle Anthrax'),),
92 (('organizationName', 'Python Software Foundation'),),
93 (('commonName', 'localhost'),)),
94 'subjectAltName': (('DNS', 'localhost'),),
95 'version': 3
96}
Antoine Pitrou152efa22010-05-16 18:19:27 +000097
Christian Heimes22587792013-11-21 23:56:13 +010098# empty CRL
99CRLFILE = data_file("revocation.crl")
100
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100101# Two keys and certs signed by the same CA (for SNI tests)
102SIGNED_CERTFILE = data_file("keycert3.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200103SIGNED_CERTFILE_HOSTNAME = 'localhost'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100104
105SIGNED_CERTFILE_INFO = {
106 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
107 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
108 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
109 'issuer': ((('countryName', 'XY'),),
110 (('organizationName', 'Python Software Foundation CA'),),
111 (('commonName', 'our-ca-server'),)),
Christian Heimese6dac002018-08-30 07:25:49 +0200112 'notAfter': 'Jul 7 14:23:16 2028 GMT',
113 'notBefore': 'Aug 29 14:23:16 2018 GMT',
114 'serialNumber': 'CB2D80995A69525C',
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100115 'subject': ((('countryName', 'XY'),),
116 (('localityName', 'Castle Anthrax'),),
117 (('organizationName', 'Python Software Foundation'),),
118 (('commonName', 'localhost'),)),
119 'subjectAltName': (('DNS', 'localhost'),),
120 'version': 3
121}
122
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100123SIGNED_CERTFILE2 = data_file("keycert4.pem")
Christian Heimesa170fa12017-09-15 20:27:30 +0200124SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100125SIGNED_CERTFILE_ECC = data_file("keycertecc.pem")
126SIGNED_CERTFILE_ECC_HOSTNAME = 'localhost-ecc'
127
Martin Panter3840b2a2016-03-27 01:53:46 +0000128# Same certificate as pycacert.pem, but without extra text in file
129SIGNING_CA = data_file("capath", "ceff1710.0")
Christian Heimes1c03abd2016-09-06 23:25:35 +0200130# cert with all kinds of subject alt names
131ALLSANFILE = data_file("allsans.pem")
Christian Heimes66e57422018-01-29 14:25:13 +0100132IDNSANSFILE = data_file("idnsans.pem")
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100133
Martin Panter3d81d932016-01-14 09:36:00 +0000134REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +0000135
136EMPTYCERT = data_file("nullcert.pem")
137BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +0000138NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000139BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200140NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +0200141NULLBYTECERT = data_file("nullbytecert.pem")
Christian Heimesa37f5242019-01-15 23:47:42 +0100142TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000143
Christian Heimes88bfd0b2018-08-14 12:54:19 +0200144DHFILE = data_file("ffdh3072.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100145BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +0000146
Christian Heimes358cfd42016-09-10 22:43:48 +0200147# Not defined in all versions of OpenSSL
148OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
149OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
150OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
151OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
Christian Heimes05d9fe32018-02-27 08:55:39 +0100152OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
Christian Heimes358cfd42016-09-10 22:43:48 +0200153
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100154
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200155def has_tls_protocol(protocol):
156 """Check if a TLS protocol is available and enabled
157
158 :param protocol: enum ssl._SSLMethod member or name
159 :return: bool
160 """
161 if isinstance(protocol, str):
162 assert protocol.startswith('PROTOCOL_')
163 protocol = getattr(ssl, protocol, None)
164 if protocol is None:
165 return False
166 if protocol in {
167 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
168 ssl.PROTOCOL_TLS_CLIENT
169 }:
170 # auto-negotiate protocols are always available
171 return True
172 name = protocol.name
173 return has_tls_version(name[len('PROTOCOL_'):])
174
175
176@functools.lru_cache
177def has_tls_version(version):
178 """Check if a TLS/SSL version is enabled
179
180 :param version: TLS version name or ssl.TLSVersion member
181 :return: bool
182 """
183 if version == "SSLv2":
184 # never supported and not even in TLSVersion enum
185 return False
186
187 if isinstance(version, str):
188 version = ssl.TLSVersion.__members__[version]
189
190 # check compile time flags like ssl.HAS_TLSv1_2
191 if not getattr(ssl, f'HAS_{version.name}'):
192 return False
193
194 # check runtime and dynamic crypto policy settings. A TLS version may
195 # be compiled in but disabled by a policy or config option.
196 ctx = ssl.SSLContext()
197 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200198 hasattr(ctx, 'minimum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200199 ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
200 version < ctx.minimum_version
201 ):
202 return False
203 if (
Christian Heimes9f772682019-09-26 18:23:17 +0200204 hasattr(ctx, 'maximum_version') and
Christian Heimesdf6ac7e2019-09-26 17:02:59 +0200205 ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
206 version > ctx.maximum_version
207 ):
208 return False
209
210 return True
211
212
213def requires_tls_version(version):
214 """Decorator to skip tests when a required TLS version is not available
215
216 :param version: TLS version name or ssl.TLSVersion member
217 :return:
218 """
219 def decorator(func):
220 @functools.wraps(func)
221 def wrapper(*args, **kw):
222 if not has_tls_version(version):
223 raise unittest.SkipTest(f"{version} is not available.")
224 else:
225 return func(*args, **kw)
226 return wrapper
227 return decorator
228
229
230requires_minimum_version = unittest.skipUnless(
231 hasattr(ssl.SSLContext, 'minimum_version'),
232 "required OpenSSL >= 1.1.0g"
233)
234
235
Thomas Woutersed03b412007-08-28 21:37:11 +0000236def handle_error(prefix):
237 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000238 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000239 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +0000240
Antoine Pitroub5218772010-05-21 09:56:06 +0000241def can_clear_options():
242 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +0200243 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +0000244
245def no_sslv2_implies_sslv3_hello():
246 # 0.9.7h or higher
247 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
248
Christian Heimes2427b502013-11-23 11:24:32 +0100249def have_verify_flags():
250 # 0.9.8 or higher
251 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
252
Christian Heimesb7b92252018-02-25 09:49:31 +0100253def _have_secp_curves():
254 if not ssl.HAS_ECDH:
255 return False
256 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
257 try:
258 ctx.set_ecdh_curve("secp384r1")
259 except ValueError:
260 return False
261 else:
262 return True
263
264
265HAVE_SECP_CURVES = _have_secp_curves()
266
267
Antoine Pitrouc695c952014-04-28 20:57:36 +0200268def utc_offset(): #NOTE: ignore issues like #1647654
269 # local time = utc time + utc offset
270 if time.daylight and time.localtime().tm_isdst > 0:
271 return -time.altzone # seconds
272 return -time.timezone
273
Christian Heimes9424bb42013-06-17 15:32:57 +0200274def asn1time(cert_time):
275 # Some versions of OpenSSL ignore seconds, see #18207
276 # 0.9.8.i
277 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
278 fmt = "%b %d %H:%M:%S %Y GMT"
279 dt = datetime.datetime.strptime(cert_time, fmt)
280 dt = dt.replace(second=0)
281 cert_time = dt.strftime(fmt)
282 # %d adds leading zero but ASN1_TIME_print() uses leading space
283 if cert_time[4] == "0":
284 cert_time = cert_time[:4] + " " + cert_time[5:]
285
286 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000287
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100288needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
289
Antoine Pitrou23df4832010-08-04 17:14:06 +0000290
Christian Heimesd0486372016-09-10 23:23:33 +0200291def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLS, *,
292 cert_reqs=ssl.CERT_NONE, ca_certs=None,
293 ciphers=None, certfile=None, keyfile=None,
294 **kwargs):
295 context = ssl.SSLContext(ssl_version)
296 if cert_reqs is not None:
Christian Heimesa170fa12017-09-15 20:27:30 +0200297 if cert_reqs == ssl.CERT_NONE:
298 context.check_hostname = False
Christian Heimesd0486372016-09-10 23:23:33 +0200299 context.verify_mode = cert_reqs
300 if ca_certs is not None:
301 context.load_verify_locations(ca_certs)
302 if certfile is not None or keyfile is not None:
303 context.load_cert_chain(certfile, keyfile)
304 if ciphers is not None:
305 context.set_ciphers(ciphers)
306 return context.wrap_socket(sock, **kwargs)
307
Christian Heimesa170fa12017-09-15 20:27:30 +0200308
309def testing_context(server_cert=SIGNED_CERTFILE):
310 """Create context
311
312 client_context, server_context, hostname = testing_context()
313 """
314 if server_cert == SIGNED_CERTFILE:
315 hostname = SIGNED_CERTFILE_HOSTNAME
316 elif server_cert == SIGNED_CERTFILE2:
317 hostname = SIGNED_CERTFILE2_HOSTNAME
318 else:
319 raise ValueError(server_cert)
320
321 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
322 client_context.load_verify_locations(SIGNING_CA)
323
324 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
325 server_context.load_cert_chain(server_cert)
Christian Heimes9fb051f2018-09-23 08:32:31 +0200326 server_context.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +0200327
328 return client_context, server_context, hostname
329
330
Antoine Pitrou152efa22010-05-16 18:19:27 +0000331class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000332
Antoine Pitrou480a1242010-04-28 21:37:09 +0000333 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000334 ssl.CERT_NONE
335 ssl.CERT_OPTIONAL
336 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100337 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100338 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100339 if ssl.HAS_ECDH:
340 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100341 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
342 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000343 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100344 self.assertIn(ssl.HAS_ECDH, {True, False})
Christian Heimescb5b68a2017-09-07 18:07:00 -0700345 ssl.OP_NO_SSLv2
346 ssl.OP_NO_SSLv3
347 ssl.OP_NO_TLSv1
348 ssl.OP_NO_TLSv1_3
349 if ssl.OPENSSL_VERSION_INFO >= (1, 0, 1):
350 ssl.OP_NO_TLSv1_1
351 ssl.OP_NO_TLSv1_2
Christian Heimesa170fa12017-09-15 20:27:30 +0200352 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
Thomas Woutersed03b412007-08-28 21:37:11 +0000353
Christian Heimes9d50ab52018-02-27 10:17:30 +0100354 def test_private_init(self):
355 with self.assertRaisesRegex(TypeError, "public constructor"):
356 with socket.socket() as s:
357 ssl.SSLSocket(s)
358
Antoine Pitrou172f0252014-04-18 20:33:08 +0200359 def test_str_for_enums(self):
360 # Make sure that the PROTOCOL_* constants have enum-like string
361 # reprs.
Christian Heimes598894f2016-09-05 23:19:05 +0200362 proto = ssl.PROTOCOL_TLS
363 self.assertEqual(str(proto), '_SSLMethod.PROTOCOL_TLS')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200364 ctx = ssl.SSLContext(proto)
365 self.assertIs(ctx.protocol, proto)
366
Antoine Pitrou480a1242010-04-28 21:37:09 +0000367 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000368 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000369 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000370 sys.stdout.write("\n RAND_status is %d (%s)\n"
371 % (v, (v and "sufficient randomness") or
372 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200373
374 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
375 self.assertEqual(len(data), 16)
376 self.assertEqual(is_cryptographic, v == 1)
377 if v:
378 data = ssl.RAND_bytes(16)
379 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200380 else:
381 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200382
Victor Stinner1e81a392013-12-19 16:47:04 +0100383 # negative num is invalid
384 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
385 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
386
Victor Stinnerbeeb5122014-11-28 13:28:25 +0100387 if hasattr(ssl, 'RAND_egd'):
388 self.assertRaises(TypeError, ssl.RAND_egd, 1)
389 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000390 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200391 ssl.RAND_add(b"this is a random bytes object", 75.0)
392 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000393
Christian Heimesf77b4b22013-08-21 13:26:05 +0200394 @unittest.skipUnless(os.name == 'posix', 'requires posix')
395 def test_random_fork(self):
396 status = ssl.RAND_status()
397 if not status:
398 self.fail("OpenSSL's PRNG has insufficient randomness")
399
400 rfd, wfd = os.pipe()
401 pid = os.fork()
402 if pid == 0:
403 try:
404 os.close(rfd)
405 child_random = ssl.RAND_pseudo_bytes(16)[0]
406 self.assertEqual(len(child_random), 16)
407 os.write(wfd, child_random)
408 os.close(wfd)
409 except BaseException:
410 os._exit(1)
411 else:
412 os._exit(0)
413 else:
414 os.close(wfd)
415 self.addCleanup(os.close, rfd)
Victor Stinner278c1e12020-03-31 20:08:12 +0200416 support.wait_process(pid, exitcode=0)
Christian Heimesf77b4b22013-08-21 13:26:05 +0200417
418 child_random = os.read(rfd, 16)
419 self.assertEqual(len(child_random), 16)
420 parent_random = ssl.RAND_pseudo_bytes(16)[0]
421 self.assertEqual(len(parent_random), 16)
422
423 self.assertNotEqual(child_random, parent_random)
424
Christian Heimese6dac002018-08-30 07:25:49 +0200425 maxDiff = None
426
Antoine Pitrou480a1242010-04-28 21:37:09 +0000427 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000428 # note that this uses an 'unofficial' function in _ssl.c,
429 # provided solely for this test, to exercise the certificate
430 # parsing code
Christian Heimesbd5c7d22018-01-20 15:16:30 +0100431 self.assertEqual(
432 ssl._ssl._test_decode_cert(CERTFILE),
433 CERTFILE_INFO
434 )
435 self.assertEqual(
436 ssl._ssl._test_decode_cert(SIGNED_CERTFILE),
437 SIGNED_CERTFILE_INFO
438 )
439
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200440 # Issue #13034: the subjectAltName in some certificates
441 # (notably projects.developer.nokia.com:443) wasn't parsed
442 p = ssl._ssl._test_decode_cert(NOKIACERT)
443 if support.verbose:
444 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
445 self.assertEqual(p['subjectAltName'],
446 (('DNS', 'projects.developer.nokia.com'),
447 ('DNS', 'projects.forum.nokia.com'))
448 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100449 # extra OCSP and AIA fields
450 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
451 self.assertEqual(p['caIssuers'],
452 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
453 self.assertEqual(p['crlDistributionPoints'],
454 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000455
Christian Heimesa37f5242019-01-15 23:47:42 +0100456 def test_parse_cert_CVE_2019_5010(self):
457 p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
458 if support.verbose:
459 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
460 self.assertEqual(
461 p,
462 {
463 'issuer': (
464 (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
465 'notAfter': 'Jun 14 18:00:58 2028 GMT',
466 'notBefore': 'Jun 18 18:00:58 2018 GMT',
467 'serialNumber': '02',
468 'subject': ((('countryName', 'UK'),),
469 (('commonName',
470 'codenomicon-vm-2.test.lal.cisco.com'),)),
471 'subjectAltName': (
472 ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
473 'version': 3
474 }
475 )
476
Christian Heimes824f7f32013-08-17 00:54:47 +0200477 def test_parse_cert_CVE_2013_4238(self):
478 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
479 if support.verbose:
480 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
481 subject = ((('countryName', 'US'),),
482 (('stateOrProvinceName', 'Oregon'),),
483 (('localityName', 'Beaverton'),),
484 (('organizationName', 'Python Software Foundation'),),
485 (('organizationalUnitName', 'Python Core Development'),),
486 (('commonName', 'null.python.org\x00example.org'),),
487 (('emailAddress', 'python-dev@python.org'),))
488 self.assertEqual(p['subject'], subject)
489 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200490 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
491 san = (('DNS', 'altnull.python.org\x00example.com'),
492 ('email', 'null@python.org\x00user@example.org'),
493 ('URI', 'http://null.python.org\x00http://example.org'),
494 ('IP Address', '192.0.2.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100495 ('IP Address', '2001:DB8:0:0:0:0:0:1'))
Christian Heimes157c9832013-08-25 14:12:41 +0200496 else:
497 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
498 san = (('DNS', 'altnull.python.org\x00example.com'),
499 ('email', 'null@python.org\x00user@example.org'),
500 ('URI', 'http://null.python.org\x00http://example.org'),
501 ('IP Address', '192.0.2.1'),
502 ('IP Address', '<invalid>'))
503
504 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200505
Christian Heimes1c03abd2016-09-06 23:25:35 +0200506 def test_parse_all_sans(self):
507 p = ssl._ssl._test_decode_cert(ALLSANFILE)
508 self.assertEqual(p['subjectAltName'],
509 (
510 ('DNS', 'allsans'),
511 ('othername', '<unsupported>'),
512 ('othername', '<unsupported>'),
513 ('email', 'user@example.org'),
514 ('DNS', 'www.example.org'),
515 ('DirName',
516 ((('countryName', 'XY'),),
517 (('localityName', 'Castle Anthrax'),),
518 (('organizationName', 'Python Software Foundation'),),
519 (('commonName', 'dirname example'),))),
520 ('URI', 'https://www.python.org/'),
521 ('IP Address', '127.0.0.1'),
Christian Heimes2b7de662019-12-07 17:59:36 +0100522 ('IP Address', '0:0:0:0:0:0:0:1'),
Christian Heimes1c03abd2016-09-06 23:25:35 +0200523 ('Registered ID', '1.2.3.4.5')
524 )
525 )
526
Antoine Pitrou480a1242010-04-28 21:37:09 +0000527 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000528 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000529 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000530 d1 = ssl.PEM_cert_to_DER_cert(pem)
531 p2 = ssl.DER_cert_to_PEM_cert(d1)
532 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000533 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000534 if not p2.startswith(ssl.PEM_HEADER + '\n'):
535 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
536 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
537 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000538
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000539 def test_openssl_version(self):
540 n = ssl.OPENSSL_VERSION_NUMBER
541 t = ssl.OPENSSL_VERSION_INFO
542 s = ssl.OPENSSL_VERSION
543 self.assertIsInstance(n, int)
544 self.assertIsInstance(t, tuple)
545 self.assertIsInstance(s, str)
546 # Some sanity checks follow
547 # >= 0.9
548 self.assertGreaterEqual(n, 0x900000)
Christian Heimes2b7de662019-12-07 17:59:36 +0100549 # < 4.0
550 self.assertLess(n, 0x40000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000551 major, minor, fix, patch, status = t
Christian Heimes2b7de662019-12-07 17:59:36 +0100552 self.assertGreaterEqual(major, 1)
553 self.assertLess(major, 4)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000554 self.assertGreaterEqual(minor, 0)
555 self.assertLess(minor, 256)
556 self.assertGreaterEqual(fix, 0)
557 self.assertLess(fix, 256)
558 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100559 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000560 self.assertGreaterEqual(status, 0)
561 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400562 # Version string as returned by {Open,Libre}SSL, the format might change
Christian Heimes598894f2016-09-05 23:19:05 +0200563 if IS_LIBRESSL:
564 self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
Victor Stinner789b8052015-01-06 11:51:06 +0100565 (s, t, hex(n)))
Antoine Pitroudfab9352014-07-21 18:35:01 -0400566 else:
567 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
Victor Stinner789b8052015-01-06 11:51:06 +0100568 (s, t, hex(n)))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000569
Antoine Pitrou9d543662010-04-23 23:10:32 +0000570 @support.cpython_only
571 def test_refcycle(self):
572 # Issue #7943: an SSL object doesn't create reference cycles with
573 # itself.
574 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200575 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000576 wr = weakref.ref(ss)
Hai Shia7f5d932020-08-04 00:41:24 +0800577 with warnings_helper.check_warnings(("", ResourceWarning)):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100578 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100579 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000580
Antoine Pitroua468adc2010-09-14 14:43:44 +0000581 def test_wrapped_unconnected(self):
582 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200583 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000584 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200585 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100586 self.assertRaises(OSError, ss.recv, 1)
587 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
588 self.assertRaises(OSError, ss.recvfrom, 1)
589 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
590 self.assertRaises(OSError, ss.send, b'x')
591 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200592 self.assertRaises(NotImplementedError, ss.dup)
Christian Heimes141c5e82018-02-24 21:10:57 +0100593 self.assertRaises(NotImplementedError, ss.sendmsg,
594 [b'x'], (), 0, ('0.0.0.0', 0))
Serhiy Storchaka42b1d612018-12-06 22:36:55 +0200595 self.assertRaises(NotImplementedError, ss.recvmsg, 100)
596 self.assertRaises(NotImplementedError, ss.recvmsg_into,
597 [bytearray(100)])
Antoine Pitroua468adc2010-09-14 14:43:44 +0000598
Antoine Pitrou40f08742010-04-24 22:04:40 +0000599 def test_timeout(self):
600 # Issue #8524: when creating an SSL socket, the timeout of the
601 # original socket should be retained.
602 for timeout in (None, 0.0, 5.0):
603 s = socket.socket(socket.AF_INET)
604 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200605 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100606 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000607
Christian Heimesd0486372016-09-10 23:23:33 +0200608 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000609 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000610 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000611 "certfile must be specified",
612 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000613 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000614 "certfile must be specified for server-side operations",
615 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000616 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000617 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200618 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100619 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
620 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200621 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200622 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000623 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000624 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000625 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200626 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000627 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000628 ssl.wrap_socket(sock,
629 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000630 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200631 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000632 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000633 ssl.wrap_socket(sock,
634 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000635 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000636
Martin Panter3464ea22016-02-01 21:58:11 +0000637 def bad_cert_test(self, certfile):
638 """Check that trying to use the given client certificate fails"""
639 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
640 certfile)
641 sock = socket.socket()
642 self.addCleanup(sock.close)
643 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200644 test_wrap_socket(sock,
Christian Heimesa170fa12017-09-15 20:27:30 +0200645 certfile=certfile)
Martin Panter3464ea22016-02-01 21:58:11 +0000646
647 def test_empty_cert(self):
648 """Wrapping with an empty cert file"""
649 self.bad_cert_test("nullcert.pem")
650
651 def test_malformed_cert(self):
652 """Wrapping with a badly formatted certificate (syntax error)"""
653 self.bad_cert_test("badcert.pem")
654
655 def test_malformed_key(self):
656 """Wrapping with a badly formatted key (syntax error)"""
657 self.bad_cert_test("badkey.pem")
658
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000659 def test_match_hostname(self):
660 def ok(cert, hostname):
661 ssl.match_hostname(cert, hostname)
662 def fail(cert, hostname):
663 self.assertRaises(ssl.CertificateError,
664 ssl.match_hostname, cert, hostname)
665
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100666 # -- Hostname matching --
667
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000668 cert = {'subject': ((('commonName', 'example.com'),),)}
669 ok(cert, 'example.com')
670 ok(cert, 'ExAmple.cOm')
671 fail(cert, 'www.example.com')
672 fail(cert, '.example.com')
673 fail(cert, 'example.org')
674 fail(cert, 'exampleXcom')
675
676 cert = {'subject': ((('commonName', '*.a.com'),),)}
677 ok(cert, 'foo.a.com')
678 fail(cert, 'bar.foo.a.com')
679 fail(cert, 'a.com')
680 fail(cert, 'Xa.com')
681 fail(cert, '.a.com')
682
Mandeep Singhede2ac92017-11-27 04:01:27 +0530683 # only match wildcards when they are the only thing
684 # in left-most segment
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000685 cert = {'subject': ((('commonName', 'f*.com'),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530686 fail(cert, 'foo.com')
687 fail(cert, 'f.com')
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000688 fail(cert, 'bar.com')
689 fail(cert, 'foo.a.com')
690 fail(cert, 'bar.foo.com')
691
Christian Heimes824f7f32013-08-17 00:54:47 +0200692 # NULL bytes are bad, CVE-2013-4073
693 cert = {'subject': ((('commonName',
694 'null.python.org\x00example.org'),),)}
695 ok(cert, 'null.python.org\x00example.org') # or raise an error?
696 fail(cert, 'example.org')
697 fail(cert, 'null.python.org')
698
Georg Brandl72c98d32013-10-27 07:16:53 +0100699 # error cases with wildcards
700 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
701 fail(cert, 'bar.foo.a.com')
702 fail(cert, 'a.com')
703 fail(cert, 'Xa.com')
704 fail(cert, '.a.com')
705
706 cert = {'subject': ((('commonName', 'a.*.com'),),)}
707 fail(cert, 'a.foo.com')
708 fail(cert, 'a..com')
709 fail(cert, 'a.com')
710
711 # wildcard doesn't match IDNA prefix 'xn--'
712 idna = 'püthon.python.org'.encode("idna").decode("ascii")
713 cert = {'subject': ((('commonName', idna),),)}
714 ok(cert, idna)
715 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
716 fail(cert, idna)
717 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
718 fail(cert, idna)
719
720 # wildcard in first fragment and IDNA A-labels in sequent fragments
721 # are supported.
722 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
723 cert = {'subject': ((('commonName', idna),),)}
Mandeep Singhede2ac92017-11-27 04:01:27 +0530724 fail(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
725 fail(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
Georg Brandl72c98d32013-10-27 07:16:53 +0100726 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
727 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
728
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000729 # Slightly fake real-world example
730 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
731 'subject': ((('commonName', 'linuxfrz.org'),),),
732 'subjectAltName': (('DNS', 'linuxfr.org'),
733 ('DNS', 'linuxfr.com'),
734 ('othername', '<unsupported>'))}
735 ok(cert, 'linuxfr.org')
736 ok(cert, 'linuxfr.com')
737 # Not a "DNS" entry
738 fail(cert, '<unsupported>')
739 # When there is a subjectAltName, commonName isn't used
740 fail(cert, 'linuxfrz.org')
741
742 # A pristine real-world example
743 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
744 'subject': ((('countryName', 'US'),),
745 (('stateOrProvinceName', 'California'),),
746 (('localityName', 'Mountain View'),),
747 (('organizationName', 'Google Inc'),),
748 (('commonName', 'mail.google.com'),))}
749 ok(cert, 'mail.google.com')
750 fail(cert, 'gmail.com')
751 # Only commonName is considered
752 fail(cert, 'California')
753
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100754 # -- IPv4 matching --
755 cert = {'subject': ((('commonName', 'example.com'),),),
756 'subjectAltName': (('DNS', 'example.com'),
757 ('IP Address', '10.11.12.13'),
Christian Heimes477b1b22019-07-02 20:39:42 +0200758 ('IP Address', '14.15.16.17'),
759 ('IP Address', '127.0.0.1'))}
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100760 ok(cert, '10.11.12.13')
761 ok(cert, '14.15.16.17')
Christian Heimes477b1b22019-07-02 20:39:42 +0200762 # socket.inet_ntoa(socket.inet_aton('127.1')) == '127.0.0.1'
763 fail(cert, '127.1')
764 fail(cert, '14.15.16.17 ')
765 fail(cert, '14.15.16.17 extra data')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100766 fail(cert, '14.15.16.18')
767 fail(cert, 'example.net')
768
769 # -- IPv6 matching --
Serhiy Storchaka16994912020-04-25 10:06:29 +0300770 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100771 cert = {'subject': ((('commonName', 'example.com'),),),
772 'subjectAltName': (
773 ('DNS', 'example.com'),
774 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
775 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
776 ok(cert, '2001::cafe')
777 ok(cert, '2003::baba')
Christian Heimes477b1b22019-07-02 20:39:42 +0200778 fail(cert, '2003::baba ')
779 fail(cert, '2003::baba extra data')
Christian Heimesaef12832018-02-24 14:35:56 +0100780 fail(cert, '2003::bebe')
781 fail(cert, 'example.net')
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100782
783 # -- Miscellaneous --
784
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000785 # Neither commonName nor subjectAltName
786 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
787 'subject': ((('countryName', 'US'),),
788 (('stateOrProvinceName', 'California'),),
789 (('localityName', 'Mountain View'),),
790 (('organizationName', 'Google Inc'),))}
791 fail(cert, 'mail.google.com')
792
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200793 # No DNS entry in subjectAltName but a commonName
794 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
795 'subject': ((('countryName', 'US'),),
796 (('stateOrProvinceName', 'California'),),
797 (('localityName', 'Mountain View'),),
798 (('commonName', 'mail.google.com'),)),
799 'subjectAltName': (('othername', 'blabla'), )}
800 ok(cert, 'mail.google.com')
801
802 # No DNS entry subjectAltName and no commonName
803 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
804 'subject': ((('countryName', 'US'),),
805 (('stateOrProvinceName', 'California'),),
806 (('localityName', 'Mountain View'),),
807 (('organizationName', 'Google Inc'),)),
808 'subjectAltName': (('othername', 'blabla'),)}
809 fail(cert, 'google.com')
810
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000811 # Empty cert / no cert
812 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
813 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
814
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200815 # Issue #17980: avoid denials of service by refusing more than one
816 # wildcard per fragment.
Christian Heimesaef12832018-02-24 14:35:56 +0100817 cert = {'subject': ((('commonName', 'a*b.example.com'),),)}
818 with self.assertRaisesRegex(
819 ssl.CertificateError,
820 "partial wildcards in leftmost label are not supported"):
821 ssl.match_hostname(cert, 'axxb.example.com')
822
823 cert = {'subject': ((('commonName', 'www.*.example.com'),),)}
824 with self.assertRaisesRegex(
825 ssl.CertificateError,
826 "wildcard can only be present in the leftmost label"):
827 ssl.match_hostname(cert, 'www.sub.example.com')
828
829 cert = {'subject': ((('commonName', 'a*b*.example.com'),),)}
830 with self.assertRaisesRegex(
831 ssl.CertificateError,
832 "too many wildcards"):
833 ssl.match_hostname(cert, 'axxbxxc.example.com')
834
835 cert = {'subject': ((('commonName', '*'),),)}
836 with self.assertRaisesRegex(
837 ssl.CertificateError,
838 "sole wildcard without additional labels are not support"):
839 ssl.match_hostname(cert, 'host')
840
841 cert = {'subject': ((('commonName', '*.com'),),)}
842 with self.assertRaisesRegex(
843 ssl.CertificateError,
844 r"hostname 'com' doesn't match '\*.com'"):
845 ssl.match_hostname(cert, 'com')
846
847 # extra checks for _inet_paton()
848 for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']:
849 with self.assertRaises(ValueError):
850 ssl._inet_paton(invalid)
851 for ipaddr in ['127.0.0.1', '192.168.0.1']:
852 self.assertTrue(ssl._inet_paton(ipaddr))
Serhiy Storchaka16994912020-04-25 10:06:29 +0300853 if socket_helper.IPV6_ENABLED:
Christian Heimesaef12832018-02-24 14:35:56 +0100854 for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']:
855 self.assertTrue(ssl._inet_paton(ipaddr))
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200856
Antoine Pitroud5323212010-10-22 18:19:07 +0000857 def test_server_side(self):
858 # server_hostname doesn't work for server sockets
Christian Heimesa170fa12017-09-15 20:27:30 +0200859 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000860 with socket.socket() as sock:
861 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
862 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000863
Antoine Pitroud6494802011-07-21 01:11:30 +0200864 def test_unknown_channel_binding(self):
865 # should raise ValueError for unknown type
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +0200866 s = socket.create_server(('127.0.0.1', 0))
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200867 c = socket.socket(socket.AF_INET)
868 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200869 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100870 with self.assertRaises(ValueError):
871 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200872 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200873
874 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
875 "'tls-unique' channel binding not available")
876 def test_tls_unique_channel_binding(self):
877 # unconnected should return None for known type
878 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200879 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100880 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200881 # the same for server-side
882 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200883 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100884 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200885
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600886 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200887 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600888 r = repr(ss)
889 with self.assertWarns(ResourceWarning) as cm:
890 ss = None
891 support.gc_collect()
892 self.assertIn(r, str(cm.warning.args[0]))
893
Christian Heimes6d7ad132013-06-09 18:02:55 +0200894 def test_get_default_verify_paths(self):
895 paths = ssl.get_default_verify_paths()
896 self.assertEqual(len(paths), 6)
897 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
898
Hai Shia7f5d932020-08-04 00:41:24 +0800899 with os_helper.EnvironmentVarGuard() as env:
Christian Heimes6d7ad132013-06-09 18:02:55 +0200900 env["SSL_CERT_DIR"] = CAPATH
901 env["SSL_CERT_FILE"] = CERTFILE
902 paths = ssl.get_default_verify_paths()
903 self.assertEqual(paths.cafile, CERTFILE)
904 self.assertEqual(paths.capath, CAPATH)
905
Christian Heimes44109d72013-11-22 01:51:30 +0100906 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
907 def test_enum_certificates(self):
908 self.assertTrue(ssl.enum_certificates("CA"))
909 self.assertTrue(ssl.enum_certificates("ROOT"))
910
911 self.assertRaises(TypeError, ssl.enum_certificates)
912 self.assertRaises(WindowsError, ssl.enum_certificates, "")
913
Christian Heimesc2d65e12013-11-22 16:13:55 +0100914 trust_oids = set()
915 for storename in ("CA", "ROOT"):
916 store = ssl.enum_certificates(storename)
917 self.assertIsInstance(store, list)
918 for element in store:
919 self.assertIsInstance(element, tuple)
920 self.assertEqual(len(element), 3)
921 cert, enc, trust = element
922 self.assertIsInstance(cert, bytes)
923 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
Christian Heimes915cd3f2019-09-09 18:06:55 +0200924 self.assertIsInstance(trust, (frozenset, set, bool))
925 if isinstance(trust, (frozenset, set)):
Christian Heimesc2d65e12013-11-22 16:13:55 +0100926 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100927
928 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100929 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200930
Christian Heimes46bebee2013-06-09 19:03:31 +0200931 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100932 def test_enum_crls(self):
933 self.assertTrue(ssl.enum_crls("CA"))
934 self.assertRaises(TypeError, ssl.enum_crls)
935 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200936
Christian Heimes44109d72013-11-22 01:51:30 +0100937 crls = ssl.enum_crls("CA")
938 self.assertIsInstance(crls, list)
939 for element in crls:
940 self.assertIsInstance(element, tuple)
941 self.assertEqual(len(element), 2)
942 self.assertIsInstance(element[0], bytes)
943 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200944
Christian Heimes46bebee2013-06-09 19:03:31 +0200945
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100946 def test_asn1object(self):
947 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
948 '1.3.6.1.5.5.7.3.1')
949
950 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
951 self.assertEqual(val, expected)
952 self.assertEqual(val.nid, 129)
953 self.assertEqual(val.shortname, 'serverAuth')
954 self.assertEqual(val.longname, 'TLS Web Server Authentication')
955 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
956 self.assertIsInstance(val, ssl._ASN1Object)
957 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
958
959 val = ssl._ASN1Object.fromnid(129)
960 self.assertEqual(val, expected)
961 self.assertIsInstance(val, ssl._ASN1Object)
962 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100963 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
964 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100965 for i in range(1000):
966 try:
967 obj = ssl._ASN1Object.fromnid(i)
968 except ValueError:
969 pass
970 else:
971 self.assertIsInstance(obj.nid, int)
972 self.assertIsInstance(obj.shortname, str)
973 self.assertIsInstance(obj.longname, str)
974 self.assertIsInstance(obj.oid, (str, type(None)))
975
976 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
977 self.assertEqual(val, expected)
978 self.assertIsInstance(val, ssl._ASN1Object)
979 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
980 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
981 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100982 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
983 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100984
Christian Heimes72d28502013-11-23 13:56:58 +0100985 def test_purpose_enum(self):
986 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
987 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
988 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
989 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
990 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
991 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
992 '1.3.6.1.5.5.7.3.1')
993
994 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
995 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
996 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
997 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
998 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
999 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
1000 '1.3.6.1.5.5.7.3.2')
1001
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001002 def test_unsupported_dtls(self):
1003 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1004 self.addCleanup(s.close)
1005 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +02001006 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001007 self.assertEqual(str(cx.exception), "only stream sockets are supported")
Christian Heimesa170fa12017-09-15 20:27:30 +02001008 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +01001009 with self.assertRaises(NotImplementedError) as cx:
1010 ctx.wrap_socket(s)
1011 self.assertEqual(str(cx.exception), "only stream sockets are supported")
1012
Antoine Pitrouc695c952014-04-28 20:57:36 +02001013 def cert_time_ok(self, timestring, timestamp):
1014 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
1015
1016 def cert_time_fail(self, timestring):
1017 with self.assertRaises(ValueError):
1018 ssl.cert_time_to_seconds(timestring)
1019
1020 @unittest.skipUnless(utc_offset(),
1021 'local time needs to be different from UTC')
1022 def test_cert_time_to_seconds_timezone(self):
1023 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
1024 # results if local timezone is not UTC
1025 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
1026 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
1027
1028 def test_cert_time_to_seconds(self):
1029 timestring = "Jan 5 09:34:43 2018 GMT"
1030 ts = 1515144883.0
1031 self.cert_time_ok(timestring, ts)
1032 # accept keyword parameter, assert its name
1033 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
1034 # accept both %e and %d (space or zero generated by strftime)
1035 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
1036 # case-insensitive
1037 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
1038 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
1039 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
1040 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
1041 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
1042 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
1043 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
1044 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
1045
1046 newyear_ts = 1230768000.0
1047 # leap seconds
1048 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
1049 # same timestamp
1050 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
1051
1052 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
1053 # allow 60th second (even if it is not a leap second)
1054 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
1055 # allow 2nd leap second for compatibility with time.strptime()
1056 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
1057 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
1058
Mike53f7a7c2017-12-14 14:04:53 +03001059 # no special treatment for the special value:
Antoine Pitrouc695c952014-04-28 20:57:36 +02001060 # 99991231235959Z (rfc 5280)
1061 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
1062
1063 @support.run_with_locale('LC_ALL', '')
1064 def test_cert_time_to_seconds_locale(self):
1065 # `cert_time_to_seconds()` should be locale independent
1066
1067 def local_february_name():
1068 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
1069
1070 if local_february_name().lower() == 'feb':
1071 self.skipTest("locale-specific month name needs to be "
1072 "different from C locale")
1073
1074 # locale-independent
1075 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
1076 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
1077
Martin Panter3840b2a2016-03-27 01:53:46 +00001078 def test_connect_ex_error(self):
1079 server = socket.socket(socket.AF_INET)
1080 self.addCleanup(server.close)
Serhiy Storchaka16994912020-04-25 10:06:29 +03001081 port = socket_helper.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +02001082 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001083 cert_reqs=ssl.CERT_REQUIRED)
1084 self.addCleanup(s.close)
1085 rc = s.connect_ex((HOST, port))
1086 # Issue #19919: Windows machines or VMs hosted on Windows
1087 # machines sometimes return EWOULDBLOCK.
1088 errors = (
1089 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
1090 errno.EWOULDBLOCK,
1091 )
1092 self.assertIn(rc, errors)
1093
Christian Heimesa6bc95a2013-11-17 19:59:14 +01001094
Antoine Pitrou152efa22010-05-16 18:19:27 +00001095class ContextTests(unittest.TestCase):
1096
1097 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001098 for protocol in PROTOCOLS:
1099 ssl.SSLContext(protocol)
Christian Heimes598894f2016-09-05 23:19:05 +02001100 ctx = ssl.SSLContext()
1101 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001102 self.assertRaises(ValueError, ssl.SSLContext, -1)
1103 self.assertRaises(ValueError, ssl.SSLContext, 42)
1104
1105 def test_protocol(self):
1106 for proto in PROTOCOLS:
1107 ctx = ssl.SSLContext(proto)
1108 self.assertEqual(ctx.protocol, proto)
1109
1110 def test_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001111 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001112 ctx.set_ciphers("ALL")
1113 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +00001114 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +00001115 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +00001116
Christian Heimes892d66e2018-01-29 14:10:18 +01001117 @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1,
1118 "Test applies only to Python default ciphers")
1119 def test_python_ciphers(self):
1120 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1121 ciphers = ctx.get_ciphers()
1122 for suite in ciphers:
1123 name = suite['name']
1124 self.assertNotIn("PSK", name)
1125 self.assertNotIn("SRP", name)
1126 self.assertNotIn("MD5", name)
1127 self.assertNotIn("RC4", name)
1128 self.assertNotIn("3DES", name)
1129
Christian Heimes25bfcd52016-09-06 00:04:45 +02001130 @unittest.skipIf(ssl.OPENSSL_VERSION_INFO < (1, 0, 2, 0, 0), 'OpenSSL too old')
1131 def test_get_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001132 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesea9b2dc2016-09-06 10:45:44 +02001133 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +02001134 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +02001135 self.assertIn('AES256-GCM-SHA384', names)
1136 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +02001137
Antoine Pitroub5218772010-05-21 09:56:06 +00001138 def test_options(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001139 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001140 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +02001141 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +02001142 # SSLContext also enables these by default
1143 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
Christian Heimes05d9fe32018-02-27 08:55:39 +01001144 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
1145 OP_ENABLE_MIDDLEBOX_COMPAT)
Christian Heimes598894f2016-09-05 23:19:05 +02001146 self.assertEqual(default, ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08001147 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +02001148 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +00001149 if can_clear_options():
Christian Heimes598894f2016-09-05 23:19:05 +02001150 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
1151 self.assertEqual(default, ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +00001152 ctx.options = 0
Matthias Klosef7c56242016-06-12 23:40:00 -07001153 # Ubuntu has OP_NO_SSLv3 forced on by default
1154 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +00001155 else:
1156 with self.assertRaises(ValueError):
1157 ctx.options = 0
1158
Christian Heimesa170fa12017-09-15 20:27:30 +02001159 def test_verify_mode_protocol(self):
1160 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001161 # Default value
1162 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1163 ctx.verify_mode = ssl.CERT_OPTIONAL
1164 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1165 ctx.verify_mode = ssl.CERT_REQUIRED
1166 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1167 ctx.verify_mode = ssl.CERT_NONE
1168 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1169 with self.assertRaises(TypeError):
1170 ctx.verify_mode = None
1171 with self.assertRaises(ValueError):
1172 ctx.verify_mode = 42
1173
Christian Heimesa170fa12017-09-15 20:27:30 +02001174 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1175 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1176 self.assertFalse(ctx.check_hostname)
1177
1178 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1179 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1180 self.assertTrue(ctx.check_hostname)
1181
Christian Heimes61d478c2018-01-27 15:51:38 +01001182 def test_hostname_checks_common_name(self):
1183 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1184 self.assertTrue(ctx.hostname_checks_common_name)
1185 if ssl.HAS_NEVER_CHECK_COMMON_NAME:
1186 ctx.hostname_checks_common_name = True
1187 self.assertTrue(ctx.hostname_checks_common_name)
1188 ctx.hostname_checks_common_name = False
1189 self.assertFalse(ctx.hostname_checks_common_name)
1190 ctx.hostname_checks_common_name = True
1191 self.assertTrue(ctx.hostname_checks_common_name)
1192 else:
1193 with self.assertRaises(AttributeError):
1194 ctx.hostname_checks_common_name = True
Christian Heimesa170fa12017-09-15 20:27:30 +02001195
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001196 @requires_minimum_version
Christian Heimesc9bc49c2019-09-11 19:24:47 +02001197 @unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
Christian Heimes698dde12018-02-27 11:54:43 +01001198 def test_min_max_version(self):
1199 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes34de2d32019-01-18 16:09:30 +01001200 # OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
1201 # Fedora override the setting to TLS 1.0.
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001202 minimum_range = {
1203 # stock OpenSSL
1204 ssl.TLSVersion.MINIMUM_SUPPORTED,
1205 # Fedora 29 uses TLS 1.0 by default
1206 ssl.TLSVersion.TLSv1,
1207 # RHEL 8 uses TLS 1.2 by default
1208 ssl.TLSVersion.TLSv1_2
1209 }
torsava34864d12019-12-02 17:15:42 +01001210 maximum_range = {
1211 # stock OpenSSL
1212 ssl.TLSVersion.MAXIMUM_SUPPORTED,
1213 # Fedora 32 uses TLS 1.3 by default
1214 ssl.TLSVersion.TLSv1_3
1215 }
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001216
Christian Heimes34de2d32019-01-18 16:09:30 +01001217 self.assertIn(
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001218 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001219 )
torsava34864d12019-12-02 17:15:42 +01001220 self.assertIn(
1221 ctx.maximum_version, maximum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001222 )
1223
1224 ctx.minimum_version = ssl.TLSVersion.TLSv1_1
1225 ctx.maximum_version = ssl.TLSVersion.TLSv1_2
1226 self.assertEqual(
1227 ctx.minimum_version, ssl.TLSVersion.TLSv1_1
1228 )
1229 self.assertEqual(
1230 ctx.maximum_version, ssl.TLSVersion.TLSv1_2
1231 )
1232
1233 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1234 ctx.maximum_version = ssl.TLSVersion.TLSv1
1235 self.assertEqual(
1236 ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
1237 )
1238 self.assertEqual(
1239 ctx.maximum_version, ssl.TLSVersion.TLSv1
1240 )
1241
1242 ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1243 self.assertEqual(
1244 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1245 )
1246
1247 ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1248 self.assertIn(
1249 ctx.maximum_version,
1250 {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3}
1251 )
1252
1253 ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED
1254 self.assertIn(
1255 ctx.minimum_version,
1256 {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3}
1257 )
1258
1259 with self.assertRaises(ValueError):
1260 ctx.minimum_version = 42
1261
1262 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
1263
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02001264 self.assertIn(
1265 ctx.minimum_version, minimum_range
Christian Heimes698dde12018-02-27 11:54:43 +01001266 )
1267 self.assertEqual(
1268 ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
1269 )
1270 with self.assertRaises(ValueError):
1271 ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED
1272 with self.assertRaises(ValueError):
1273 ctx.maximum_version = ssl.TLSVersion.TLSv1
1274
1275
matthewhughes9348e836bb2020-07-17 09:59:15 +01001276 @unittest.skipUnless(
1277 hasattr(ssl.SSLContext, 'security_level'),
1278 "requires OpenSSL >= 1.1.0"
1279 )
1280 def test_security_level(self):
1281 ctx = ssl.SSLContext()
1282 # The default security callback allows for levels between 0-5
1283 # with OpenSSL defaulting to 1, however some vendors override the
1284 # default value (e.g. Debian defaults to 2)
1285 security_level_range = {
1286 0,
1287 1, # OpenSSL default
1288 2, # Debian
1289 3,
1290 4,
1291 5,
1292 }
1293 self.assertIn(ctx.security_level, security_level_range)
1294
Christian Heimes2427b502013-11-23 11:24:32 +01001295 @unittest.skipUnless(have_verify_flags(),
1296 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01001297 def test_verify_flags(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001298 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -05001299 # default value
1300 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
1301 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01001302 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
1303 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
1304 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
1305 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
1306 ctx.verify_flags = ssl.VERIFY_DEFAULT
1307 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
1308 # supports any value
1309 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1310 self.assertEqual(ctx.verify_flags,
1311 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1312 with self.assertRaises(TypeError):
1313 ctx.verify_flags = None
1314
Antoine Pitrou152efa22010-05-16 18:19:27 +00001315 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001316 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001317 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001318 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001319 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1320 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001321 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001322 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001323 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001324 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001325 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001326 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001327 ctx.load_cert_chain(EMPTYCERT)
1328 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001329 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001330 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1331 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1332 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001333 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001334 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001335 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001336 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001337 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001338 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1339 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001340 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001341 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001342 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001343 # Password protected key and cert
1344 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1345 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1346 ctx.load_cert_chain(CERTFILE_PROTECTED,
1347 password=bytearray(KEY_PASSWORD.encode()))
1348 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1349 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1350 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1351 bytearray(KEY_PASSWORD.encode()))
1352 with self.assertRaisesRegex(TypeError, "should be a string"):
1353 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1354 with self.assertRaises(ssl.SSLError):
1355 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1356 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1357 # openssl has a fixed limit on the password buffer.
1358 # PEM_BUFSIZE is generally set to 1kb.
1359 # Return a string larger than this.
1360 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1361 # Password callback
1362 def getpass_unicode():
1363 return KEY_PASSWORD
1364 def getpass_bytes():
1365 return KEY_PASSWORD.encode()
1366 def getpass_bytearray():
1367 return bytearray(KEY_PASSWORD.encode())
1368 def getpass_badpass():
1369 return "badpass"
1370 def getpass_huge():
1371 return b'a' * (1024 * 1024)
1372 def getpass_bad_type():
1373 return 9
1374 def getpass_exception():
1375 raise Exception('getpass error')
1376 class GetPassCallable:
1377 def __call__(self):
1378 return KEY_PASSWORD
1379 def getpass(self):
1380 return KEY_PASSWORD
1381 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1382 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1383 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1384 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1385 ctx.load_cert_chain(CERTFILE_PROTECTED,
1386 password=GetPassCallable().getpass)
1387 with self.assertRaises(ssl.SSLError):
1388 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1389 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1390 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1391 with self.assertRaisesRegex(TypeError, "must return a string"):
1392 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1393 with self.assertRaisesRegex(Exception, "getpass error"):
1394 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1395 # Make sure the password function isn't called if it isn't needed
1396 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001397
1398 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001399 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001400 ctx.load_verify_locations(CERTFILE)
1401 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1402 ctx.load_verify_locations(BYTES_CERTFILE)
1403 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1404 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001405 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001406 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001407 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001408 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001409 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001410 ctx.load_verify_locations(BADCERT)
1411 ctx.load_verify_locations(CERTFILE, CAPATH)
1412 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1413
Victor Stinner80f75e62011-01-29 11:31:20 +00001414 # Issue #10989: crash if the second argument type is invalid
1415 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1416
Christian Heimesefff7062013-11-21 03:35:02 +01001417 def test_load_verify_cadata(self):
1418 # test cadata
1419 with open(CAFILE_CACERT) as f:
1420 cacert_pem = f.read()
1421 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1422 with open(CAFILE_NEURONIO) as f:
1423 neuronio_pem = f.read()
1424 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1425
1426 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001427 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001428 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1429 ctx.load_verify_locations(cadata=cacert_pem)
1430 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1431 ctx.load_verify_locations(cadata=neuronio_pem)
1432 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1433 # cert already in hash table
1434 ctx.load_verify_locations(cadata=neuronio_pem)
1435 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1436
1437 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001438 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001439 combined = "\n".join((cacert_pem, neuronio_pem))
1440 ctx.load_verify_locations(cadata=combined)
1441 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1442
1443 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001444 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001445 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1446 neuronio_pem, "tail"]
1447 ctx.load_verify_locations(cadata="\n".join(combined))
1448 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1449
1450 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001451 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001452 ctx.load_verify_locations(cadata=cacert_der)
1453 ctx.load_verify_locations(cadata=neuronio_der)
1454 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1455 # cert already in hash table
1456 ctx.load_verify_locations(cadata=cacert_der)
1457 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1458
1459 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001460 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001461 combined = b"".join((cacert_der, neuronio_der))
1462 ctx.load_verify_locations(cadata=combined)
1463 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1464
1465 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001466 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001467 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1468
1469 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1470 ctx.load_verify_locations(cadata="broken")
1471 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1472 ctx.load_verify_locations(cadata=b"broken")
1473
1474
Paul Monsonf3550692019-06-19 13:09:54 -07001475 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001476 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001477 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001478 ctx.load_dh_params(DHFILE)
1479 if os.name != 'nt':
1480 ctx.load_dh_params(BYTES_DHFILE)
1481 self.assertRaises(TypeError, ctx.load_dh_params)
1482 self.assertRaises(TypeError, ctx.load_dh_params, None)
1483 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001484 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001485 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001486 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001487 ctx.load_dh_params(CERTFILE)
1488
Antoine Pitroub0182c82010-10-12 20:09:02 +00001489 def test_session_stats(self):
1490 for proto in PROTOCOLS:
1491 ctx = ssl.SSLContext(proto)
1492 self.assertEqual(ctx.session_stats(), {
1493 'number': 0,
1494 'connect': 0,
1495 'connect_good': 0,
1496 'connect_renegotiate': 0,
1497 'accept': 0,
1498 'accept_good': 0,
1499 'accept_renegotiate': 0,
1500 'hits': 0,
1501 'misses': 0,
1502 'timeouts': 0,
1503 'cache_full': 0,
1504 })
1505
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001506 def test_set_default_verify_paths(self):
1507 # There's not much we can do to test that it acts as expected,
1508 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001509 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001510 ctx.set_default_verify_paths()
1511
Antoine Pitrou501da612011-12-21 09:27:41 +01001512 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001513 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001514 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001515 ctx.set_ecdh_curve("prime256v1")
1516 ctx.set_ecdh_curve(b"prime256v1")
1517 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1518 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1519 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1520 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1521
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001522 @needs_sni
1523 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001524 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001525
1526 # set_servername_callback expects a callable, or None
1527 self.assertRaises(TypeError, ctx.set_servername_callback)
1528 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1529 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1530 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1531
1532 def dummycallback(sock, servername, ctx):
1533 pass
1534 ctx.set_servername_callback(None)
1535 ctx.set_servername_callback(dummycallback)
1536
1537 @needs_sni
1538 def test_sni_callback_refcycle(self):
1539 # Reference cycles through the servername callback are detected
1540 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001541 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001542 def dummycallback(sock, servername, ctx, cycle=ctx):
1543 pass
1544 ctx.set_servername_callback(dummycallback)
1545 wr = weakref.ref(ctx)
1546 del ctx, dummycallback
1547 gc.collect()
1548 self.assertIs(wr(), None)
1549
Christian Heimes9a5395a2013-06-17 15:44:12 +02001550 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001551 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001552 self.assertEqual(ctx.cert_store_stats(),
1553 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1554 ctx.load_cert_chain(CERTFILE)
1555 self.assertEqual(ctx.cert_store_stats(),
1556 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1557 ctx.load_verify_locations(CERTFILE)
1558 self.assertEqual(ctx.cert_store_stats(),
1559 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001560 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001561 self.assertEqual(ctx.cert_store_stats(),
1562 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1563
1564 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001565 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001566 self.assertEqual(ctx.get_ca_certs(), [])
1567 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1568 ctx.load_verify_locations(CERTFILE)
1569 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001570 # but CAFILE_CACERT is a CA cert
1571 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001572 self.assertEqual(ctx.get_ca_certs(),
1573 [{'issuer': ((('organizationName', 'Root CA'),),
1574 (('organizationalUnitName', 'http://www.cacert.org'),),
1575 (('commonName', 'CA Cert Signing Authority'),),
1576 (('emailAddress', 'support@cacert.org'),)),
1577 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1578 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1579 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001580 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001581 'subject': ((('organizationName', 'Root CA'),),
1582 (('organizationalUnitName', 'http://www.cacert.org'),),
1583 (('commonName', 'CA Cert Signing Authority'),),
1584 (('emailAddress', 'support@cacert.org'),)),
1585 'version': 3}])
1586
Martin Panterb55f8b72016-01-14 12:53:56 +00001587 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001588 pem = f.read()
1589 der = ssl.PEM_cert_to_DER_cert(pem)
1590 self.assertEqual(ctx.get_ca_certs(True), [der])
1591
Christian Heimes72d28502013-11-23 13:56:58 +01001592 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001593 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001594 ctx.load_default_certs()
1595
Christian Heimesa170fa12017-09-15 20:27:30 +02001596 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001597 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1598 ctx.load_default_certs()
1599
Christian Heimesa170fa12017-09-15 20:27:30 +02001600 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001601 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1602
Christian Heimesa170fa12017-09-15 20:27:30 +02001603 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001604 self.assertRaises(TypeError, ctx.load_default_certs, None)
1605 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1606
Benjamin Peterson91244e02014-10-03 18:17:15 -04001607 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimes598894f2016-09-05 23:19:05 +02001608 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001609 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001610 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001611 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001612 env["SSL_CERT_DIR"] = CAPATH
1613 env["SSL_CERT_FILE"] = CERTFILE
1614 ctx.load_default_certs()
1615 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1616
Benjamin Peterson91244e02014-10-03 18:17:15 -04001617 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001618 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001619 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001620 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001621 ctx.load_default_certs()
1622 stats = ctx.cert_store_stats()
1623
Christian Heimesa170fa12017-09-15 20:27:30 +02001624 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001625 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001626 env["SSL_CERT_DIR"] = CAPATH
1627 env["SSL_CERT_FILE"] = CERTFILE
1628 ctx.load_default_certs()
1629 stats["x509"] += 1
1630 self.assertEqual(ctx.cert_store_stats(), stats)
1631
Christian Heimes358cfd42016-09-10 22:43:48 +02001632 def _assert_context_options(self, ctx):
1633 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1634 if OP_NO_COMPRESSION != 0:
1635 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1636 OP_NO_COMPRESSION)
1637 if OP_SINGLE_DH_USE != 0:
1638 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1639 OP_SINGLE_DH_USE)
1640 if OP_SINGLE_ECDH_USE != 0:
1641 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1642 OP_SINGLE_ECDH_USE)
1643 if OP_CIPHER_SERVER_PREFERENCE != 0:
1644 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1645 OP_CIPHER_SERVER_PREFERENCE)
1646
Christian Heimes4c05b472013-11-23 15:58:30 +01001647 def test_create_default_context(self):
1648 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001649
Christian Heimesa170fa12017-09-15 20:27:30 +02001650 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001651 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001652 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001653 self._assert_context_options(ctx)
1654
Christian Heimes4c05b472013-11-23 15:58:30 +01001655 with open(SIGNING_CA) as f:
1656 cadata = f.read()
1657 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1658 cadata=cadata)
Christian Heimesa170fa12017-09-15 20:27:30 +02001659 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001660 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001661 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001662
1663 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001664 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001665 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001666 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001667
Christian Heimes67986f92013-11-23 22:43:47 +01001668 def test__create_stdlib_context(self):
1669 ctx = ssl._create_stdlib_context()
Christian Heimesa170fa12017-09-15 20:27:30 +02001670 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001671 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001672 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001673 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001674
1675 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1676 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1677 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001678 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001679
1680 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001681 cert_reqs=ssl.CERT_REQUIRED,
1682 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001683 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1684 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001685 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001686 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001687
1688 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001689 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001690 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001691 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001692
Christian Heimes1aa9a752013-12-02 02:41:19 +01001693 def test_check_hostname(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001694 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001695 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001696 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001697
Christian Heimese82c0342017-09-15 20:29:57 +02001698 # Auto set CERT_REQUIRED
1699 ctx.check_hostname = True
1700 self.assertTrue(ctx.check_hostname)
1701 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1702 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001703 ctx.verify_mode = ssl.CERT_REQUIRED
1704 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001705 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001706
Christian Heimese82c0342017-09-15 20:29:57 +02001707 # Changing verify_mode does not affect check_hostname
1708 ctx.check_hostname = False
1709 ctx.verify_mode = ssl.CERT_NONE
1710 ctx.check_hostname = False
1711 self.assertFalse(ctx.check_hostname)
1712 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1713 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001714 ctx.check_hostname = True
1715 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001716 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1717
1718 ctx.check_hostname = False
1719 ctx.verify_mode = ssl.CERT_OPTIONAL
1720 ctx.check_hostname = False
1721 self.assertFalse(ctx.check_hostname)
1722 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1723 # keep CERT_OPTIONAL
1724 ctx.check_hostname = True
1725 self.assertTrue(ctx.check_hostname)
1726 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001727
1728 # Cannot set CERT_NONE with check_hostname enabled
1729 with self.assertRaises(ValueError):
1730 ctx.verify_mode = ssl.CERT_NONE
1731 ctx.check_hostname = False
1732 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001733 ctx.verify_mode = ssl.CERT_NONE
1734 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001735
Christian Heimes5fe668c2016-09-12 00:01:11 +02001736 def test_context_client_server(self):
1737 # PROTOCOL_TLS_CLIENT has sane defaults
1738 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1739 self.assertTrue(ctx.check_hostname)
1740 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1741
1742 # PROTOCOL_TLS_SERVER has different but also sane defaults
1743 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1744 self.assertFalse(ctx.check_hostname)
1745 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1746
Christian Heimes4df60f12017-09-15 20:26:05 +02001747 def test_context_custom_class(self):
1748 class MySSLSocket(ssl.SSLSocket):
1749 pass
1750
1751 class MySSLObject(ssl.SSLObject):
1752 pass
1753
1754 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1755 ctx.sslsocket_class = MySSLSocket
1756 ctx.sslobject_class = MySSLObject
1757
1758 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1759 self.assertIsInstance(sock, MySSLSocket)
1760 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1761 self.assertIsInstance(obj, MySSLObject)
1762
Christian Heimes78c7d522019-06-03 21:00:10 +02001763 @unittest.skipUnless(IS_OPENSSL_1_1_1, "Test requires OpenSSL 1.1.1")
1764 def test_num_tickest(self):
1765 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1766 self.assertEqual(ctx.num_tickets, 2)
1767 ctx.num_tickets = 1
1768 self.assertEqual(ctx.num_tickets, 1)
1769 ctx.num_tickets = 0
1770 self.assertEqual(ctx.num_tickets, 0)
1771 with self.assertRaises(ValueError):
1772 ctx.num_tickets = -1
1773 with self.assertRaises(TypeError):
1774 ctx.num_tickets = None
1775
1776 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1777 self.assertEqual(ctx.num_tickets, 2)
1778 with self.assertRaises(ValueError):
1779 ctx.num_tickets = 1
1780
Antoine Pitrou152efa22010-05-16 18:19:27 +00001781
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001782class SSLErrorTests(unittest.TestCase):
1783
1784 def test_str(self):
1785 # The str() of a SSLError doesn't include the errno
1786 e = ssl.SSLError(1, "foo")
1787 self.assertEqual(str(e), "foo")
1788 self.assertEqual(e.errno, 1)
1789 # Same for a subclass
1790 e = ssl.SSLZeroReturnError(1, "foo")
1791 self.assertEqual(str(e), "foo")
1792 self.assertEqual(e.errno, 1)
1793
Paul Monsonf3550692019-06-19 13:09:54 -07001794 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001795 def test_lib_reason(self):
1796 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001797 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001798 with self.assertRaises(ssl.SSLError) as cm:
1799 ctx.load_dh_params(CERTFILE)
1800 self.assertEqual(cm.exception.library, 'PEM')
1801 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1802 s = str(cm.exception)
1803 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1804
1805 def test_subclass(self):
1806 # Check that the appropriate SSLError subclass is raised
1807 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001808 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1809 ctx.check_hostname = False
1810 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001811 with socket.create_server(("127.0.0.1", 0)) as s:
1812 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001813 c.setblocking(False)
1814 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001815 with self.assertRaises(ssl.SSLWantReadError) as cm:
1816 c.do_handshake()
1817 s = str(cm.exception)
1818 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1819 # For compatibility
1820 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1821
1822
Christian Heimes61d478c2018-01-27 15:51:38 +01001823 def test_bad_server_hostname(self):
1824 ctx = ssl.create_default_context()
1825 with self.assertRaises(ValueError):
1826 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1827 server_hostname="")
1828 with self.assertRaises(ValueError):
1829 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1830 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001831 with self.assertRaises(TypeError):
1832 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1833 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001834
1835
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001836class MemoryBIOTests(unittest.TestCase):
1837
1838 def test_read_write(self):
1839 bio = ssl.MemoryBIO()
1840 bio.write(b'foo')
1841 self.assertEqual(bio.read(), b'foo')
1842 self.assertEqual(bio.read(), b'')
1843 bio.write(b'foo')
1844 bio.write(b'bar')
1845 self.assertEqual(bio.read(), b'foobar')
1846 self.assertEqual(bio.read(), b'')
1847 bio.write(b'baz')
1848 self.assertEqual(bio.read(2), b'ba')
1849 self.assertEqual(bio.read(1), b'z')
1850 self.assertEqual(bio.read(1), b'')
1851
1852 def test_eof(self):
1853 bio = ssl.MemoryBIO()
1854 self.assertFalse(bio.eof)
1855 self.assertEqual(bio.read(), b'')
1856 self.assertFalse(bio.eof)
1857 bio.write(b'foo')
1858 self.assertFalse(bio.eof)
1859 bio.write_eof()
1860 self.assertFalse(bio.eof)
1861 self.assertEqual(bio.read(2), b'fo')
1862 self.assertFalse(bio.eof)
1863 self.assertEqual(bio.read(1), b'o')
1864 self.assertTrue(bio.eof)
1865 self.assertEqual(bio.read(), b'')
1866 self.assertTrue(bio.eof)
1867
1868 def test_pending(self):
1869 bio = ssl.MemoryBIO()
1870 self.assertEqual(bio.pending, 0)
1871 bio.write(b'foo')
1872 self.assertEqual(bio.pending, 3)
1873 for i in range(3):
1874 bio.read(1)
1875 self.assertEqual(bio.pending, 3-i-1)
1876 for i in range(3):
1877 bio.write(b'x')
1878 self.assertEqual(bio.pending, i+1)
1879 bio.read()
1880 self.assertEqual(bio.pending, 0)
1881
1882 def test_buffer_types(self):
1883 bio = ssl.MemoryBIO()
1884 bio.write(b'foo')
1885 self.assertEqual(bio.read(), b'foo')
1886 bio.write(bytearray(b'bar'))
1887 self.assertEqual(bio.read(), b'bar')
1888 bio.write(memoryview(b'baz'))
1889 self.assertEqual(bio.read(), b'baz')
1890
1891 def test_error_types(self):
1892 bio = ssl.MemoryBIO()
1893 self.assertRaises(TypeError, bio.write, 'foo')
1894 self.assertRaises(TypeError, bio.write, None)
1895 self.assertRaises(TypeError, bio.write, True)
1896 self.assertRaises(TypeError, bio.write, 1)
1897
1898
Christian Heimes9d50ab52018-02-27 10:17:30 +01001899class SSLObjectTests(unittest.TestCase):
1900 def test_private_init(self):
1901 bio = ssl.MemoryBIO()
1902 with self.assertRaisesRegex(TypeError, "public constructor"):
1903 ssl.SSLObject(bio, bio)
1904
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001905 def test_unwrap(self):
1906 client_ctx, server_ctx, hostname = testing_context()
1907 c_in = ssl.MemoryBIO()
1908 c_out = ssl.MemoryBIO()
1909 s_in = ssl.MemoryBIO()
1910 s_out = ssl.MemoryBIO()
1911 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1912 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1913
1914 # Loop on the handshake for a bit to get it settled
1915 for _ in range(5):
1916 try:
1917 client.do_handshake()
1918 except ssl.SSLWantReadError:
1919 pass
1920 if c_out.pending:
1921 s_in.write(c_out.read())
1922 try:
1923 server.do_handshake()
1924 except ssl.SSLWantReadError:
1925 pass
1926 if s_out.pending:
1927 c_in.write(s_out.read())
1928 # Now the handshakes should be complete (don't raise WantReadError)
1929 client.do_handshake()
1930 server.do_handshake()
1931
1932 # Now if we unwrap one side unilaterally, it should send close-notify
1933 # and raise WantReadError:
1934 with self.assertRaises(ssl.SSLWantReadError):
1935 client.unwrap()
1936
1937 # But server.unwrap() does not raise, because it reads the client's
1938 # close-notify:
1939 s_in.write(c_out.read())
1940 server.unwrap()
1941
1942 # And now that the client gets the server's close-notify, it doesn't
1943 # raise either.
1944 c_in.write(s_out.read())
1945 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001946
Martin Panter3840b2a2016-03-27 01:53:46 +00001947class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001948 """Tests that connect to a simple server running in the background"""
1949
1950 def setUp(self):
1951 server = ThreadedEchoServer(SIGNED_CERTFILE)
1952 self.server_addr = (HOST, server.port)
1953 server.__enter__()
1954 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001955
Antoine Pitrou480a1242010-04-28 21:37:09 +00001956 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001957 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001958 cert_reqs=ssl.CERT_NONE) as s:
1959 s.connect(self.server_addr)
1960 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001961 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001962
Martin Panter3840b2a2016-03-27 01:53:46 +00001963 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001964 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001965 cert_reqs=ssl.CERT_REQUIRED,
1966 ca_certs=SIGNING_CA) as s:
1967 s.connect(self.server_addr)
1968 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001969 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001970
Martin Panter3840b2a2016-03-27 01:53:46 +00001971 def test_connect_fail(self):
1972 # This should fail because we have no verification certs. Connection
1973 # failure crashes ThreadedEchoServer, so run this in an independent
1974 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001975 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001976 cert_reqs=ssl.CERT_REQUIRED)
1977 self.addCleanup(s.close)
1978 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1979 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001980
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001981 def test_connect_ex(self):
1982 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02001983 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001984 cert_reqs=ssl.CERT_REQUIRED,
1985 ca_certs=SIGNING_CA)
1986 self.addCleanup(s.close)
1987 self.assertEqual(0, s.connect_ex(self.server_addr))
1988 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001989
1990 def test_non_blocking_connect_ex(self):
1991 # Issue #11326: non-blocking connect_ex() should allow handshake
1992 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02001993 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001994 cert_reqs=ssl.CERT_REQUIRED,
1995 ca_certs=SIGNING_CA,
1996 do_handshake_on_connect=False)
1997 self.addCleanup(s.close)
1998 s.setblocking(False)
1999 rc = s.connect_ex(self.server_addr)
2000 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2001 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2002 # Wait for connect to finish
2003 select.select([], [s], [], 5.0)
2004 # Non-blocking handshake
2005 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002006 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002007 s.do_handshake()
2008 break
2009 except ssl.SSLWantReadError:
2010 select.select([s], [], [], 5.0)
2011 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002012 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002013 # SSL established
2014 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002015
Antoine Pitrou152efa22010-05-16 18:19:27 +00002016 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002017 # Same as test_connect, but with a separately created context
Christian Heimesa170fa12017-09-15 20:27:30 +02002018 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002019 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2020 s.connect(self.server_addr)
2021 self.assertEqual({}, s.getpeercert())
2022 # Same with a server hostname
2023 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2024 server_hostname="dummy") as s:
2025 s.connect(self.server_addr)
2026 ctx.verify_mode = ssl.CERT_REQUIRED
2027 # This should succeed because we specify the root cert
2028 ctx.load_verify_locations(SIGNING_CA)
2029 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2030 s.connect(self.server_addr)
2031 cert = s.getpeercert()
2032 self.assertTrue(cert)
2033
2034 def test_connect_with_context_fail(self):
2035 # This should fail because we have no verification certs. Connection
2036 # failure crashes ThreadedEchoServer, so run this in an independent
2037 # test method.
Christian Heimesa170fa12017-09-15 20:27:30 +02002038 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002039 ctx.verify_mode = ssl.CERT_REQUIRED
2040 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
2041 self.addCleanup(s.close)
2042 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2043 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002044
2045 def test_connect_capath(self):
2046 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002047 # NOTE: the subject hashing algorithm has been changed between
2048 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2049 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002050 # filename) for this test to be portable across OpenSSL releases.
Christian Heimesa170fa12017-09-15 20:27:30 +02002051 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002052 ctx.verify_mode = ssl.CERT_REQUIRED
2053 ctx.load_verify_locations(capath=CAPATH)
2054 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2055 s.connect(self.server_addr)
2056 cert = s.getpeercert()
2057 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002058
Martin Panter3840b2a2016-03-27 01:53:46 +00002059 # Same with a bytes `capath` argument
Christian Heimesa170fa12017-09-15 20:27:30 +02002060 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002061 ctx.verify_mode = ssl.CERT_REQUIRED
2062 ctx.load_verify_locations(capath=BYTES_CAPATH)
2063 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2064 s.connect(self.server_addr)
2065 cert = s.getpeercert()
2066 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002067
Christian Heimesefff7062013-11-21 03:35:02 +01002068 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002069 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002070 pem = f.read()
2071 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimesa170fa12017-09-15 20:27:30 +02002072 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002073 ctx.verify_mode = ssl.CERT_REQUIRED
2074 ctx.load_verify_locations(cadata=pem)
2075 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2076 s.connect(self.server_addr)
2077 cert = s.getpeercert()
2078 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002079
Martin Panter3840b2a2016-03-27 01:53:46 +00002080 # same with DER
Christian Heimesa170fa12017-09-15 20:27:30 +02002081 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002082 ctx.verify_mode = ssl.CERT_REQUIRED
2083 ctx.load_verify_locations(cadata=der)
2084 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2085 s.connect(self.server_addr)
2086 cert = s.getpeercert()
2087 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002088
Antoine Pitroue3220242010-04-24 11:13:53 +00002089 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2090 def test_makefile_close(self):
2091 # Issue #5238: creating a file-like object with makefile() shouldn't
2092 # delay closing the underlying "real socket" (here tested with its
2093 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002094 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002095 ss.connect(self.server_addr)
2096 fd = ss.fileno()
2097 f = ss.makefile()
2098 f.close()
2099 # The fd is still open
2100 os.read(fd, 0)
2101 # Closing the SSL socket should close the fd too
2102 ss.close()
2103 gc.collect()
2104 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002105 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002106 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002107
Antoine Pitrou480a1242010-04-28 21:37:09 +00002108 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002109 s = socket.socket(socket.AF_INET)
2110 s.connect(self.server_addr)
2111 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002112 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002113 cert_reqs=ssl.CERT_NONE,
2114 do_handshake_on_connect=False)
2115 self.addCleanup(s.close)
2116 count = 0
2117 while True:
2118 try:
2119 count += 1
2120 s.do_handshake()
2121 break
2122 except ssl.SSLWantReadError:
2123 select.select([s], [], [])
2124 except ssl.SSLWantWriteError:
2125 select.select([], [s], [])
2126 if support.verbose:
2127 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002128
Antoine Pitrou480a1242010-04-28 21:37:09 +00002129 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002130 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002131
Martin Panter3840b2a2016-03-27 01:53:46 +00002132 def test_get_server_certificate_fail(self):
2133 # Connection failure crashes ThreadedEchoServer, so run this in an
2134 # independent test method
2135 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002136
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002137 def test_ciphers(self):
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="ALL") as s:
2140 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002141 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002142 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2143 s.connect(self.server_addr)
2144 # Error checking can happen at instantiation or when connecting
2145 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2146 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002147 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002148 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2149 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002150
Christian Heimes9a5395a2013-06-17 15:44:12 +02002151 def test_get_ca_certs_capath(self):
2152 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002153 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002154 ctx.load_verify_locations(capath=CAPATH)
2155 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002156 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2157 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002158 s.connect(self.server_addr)
2159 cert = s.getpeercert()
2160 self.assertTrue(cert)
2161 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002162
Christian Heimes575596e2013-12-15 21:49:17 +01002163 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01002164 def test_context_setget(self):
2165 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002166 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2167 ctx1.load_verify_locations(capath=CAPATH)
2168 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2169 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002170 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002171 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002172 ss.connect(self.server_addr)
2173 self.assertIs(ss.context, ctx1)
2174 self.assertIs(ss._sslobj.context, ctx1)
2175 ss.context = ctx2
2176 self.assertIs(ss.context, ctx2)
2177 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002178
2179 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2180 # A simple IO loop. Call func(*args) depending on the error we get
2181 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002182 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002183 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002184 count = 0
2185 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002186 if time.monotonic() > deadline:
2187 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002188 errno = None
2189 count += 1
2190 try:
2191 ret = func(*args)
2192 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002193 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002194 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002195 raise
2196 errno = e.errno
2197 # Get any data from the outgoing BIO irrespective of any error, and
2198 # send it to the socket.
2199 buf = outgoing.read()
2200 sock.sendall(buf)
2201 # If there's no error, we're done. For WANT_READ, we need to get
2202 # data from the socket and put it in the incoming BIO.
2203 if errno is None:
2204 break
2205 elif errno == ssl.SSL_ERROR_WANT_READ:
2206 buf = sock.recv(32768)
2207 if buf:
2208 incoming.write(buf)
2209 else:
2210 incoming.write_eof()
2211 if support.verbose:
2212 sys.stdout.write("Needed %d calls to complete %s().\n"
2213 % (count, func.__name__))
2214 return ret
2215
Martin Panter3840b2a2016-03-27 01:53:46 +00002216 def test_bio_handshake(self):
2217 sock = socket.socket(socket.AF_INET)
2218 self.addCleanup(sock.close)
2219 sock.connect(self.server_addr)
2220 incoming = ssl.MemoryBIO()
2221 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002222 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2223 self.assertTrue(ctx.check_hostname)
2224 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002225 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002226 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2227 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002228 self.assertIs(sslobj._sslobj.owner, sslobj)
2229 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002230 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002231 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002232 self.assertRaises(ValueError, sslobj.getpeercert)
2233 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2234 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2235 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2236 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002237 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002238 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002239 self.assertTrue(sslobj.getpeercert())
2240 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2241 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2242 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002243 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002244 except ssl.SSLSyscallError:
2245 # If the server shuts down the TCP connection without sending a
2246 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2247 pass
2248 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2249
2250 def test_bio_read_write_data(self):
2251 sock = socket.socket(socket.AF_INET)
2252 self.addCleanup(sock.close)
2253 sock.connect(self.server_addr)
2254 incoming = ssl.MemoryBIO()
2255 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002256 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002257 ctx.verify_mode = ssl.CERT_NONE
2258 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2259 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2260 req = b'FOO\n'
2261 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2262 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2263 self.assertEqual(buf, b'foo\n')
2264 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002265
2266
Martin Panter3840b2a2016-03-27 01:53:46 +00002267class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002268
Martin Panter3840b2a2016-03-27 01:53:46 +00002269 def test_timeout_connect_ex(self):
2270 # Issue #12065: on a timeout, connect_ex() should return the original
2271 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002272 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002273 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002274 cert_reqs=ssl.CERT_REQUIRED,
2275 do_handshake_on_connect=False)
2276 self.addCleanup(s.close)
2277 s.settimeout(0.0000001)
2278 rc = s.connect_ex((REMOTE_HOST, 443))
2279 if rc == 0:
2280 self.skipTest("REMOTE_HOST responded too quickly")
2281 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2282
Serhiy Storchaka16994912020-04-25 10:06:29 +03002283 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002284 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002285 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002286 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2287 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2288
Martin Panter3840b2a2016-03-27 01:53:46 +00002289
2290def _test_get_server_certificate(test, host, port, cert=None):
2291 pem = ssl.get_server_certificate((host, port))
2292 if not pem:
2293 test.fail("No server certificate on %s:%s!" % (host, port))
2294
2295 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2296 if not pem:
2297 test.fail("No server certificate on %s:%s!" % (host, port))
2298 if support.verbose:
2299 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2300
2301def _test_get_server_certificate_fail(test, host, port):
2302 try:
2303 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2304 except ssl.SSLError as x:
2305 #should fail
2306 if support.verbose:
2307 sys.stdout.write("%s\n" % x)
2308 else:
2309 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2310
2311
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002312from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002313
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002314class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002315
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002316 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002317
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002318 """A mildly complicated class, because we want it to work both
2319 with and without the SSL wrapper around the socket connection, so
2320 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002321
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002322 def __init__(self, server, connsock, addr):
2323 self.server = server
2324 self.running = False
2325 self.sock = connsock
2326 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002327 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002328 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002329 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002330 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002331
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002332 def wrap_conn(self):
2333 try:
2334 self.sslconn = self.server.context.wrap_socket(
2335 self.sock, server_side=True)
2336 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
2337 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002338 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002339 # We treat ConnectionResetError as though it were an
2340 # SSLError - OpenSSL on Ubuntu abruptly closes the
2341 # connection when asked to use an unsupported protocol.
2342 #
Christian Heimes529525f2018-05-23 22:24:45 +02002343 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2344 # tries to send session tickets after handshake.
2345 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002346 #
2347 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2348 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002349 self.server.conn_errors.append(str(e))
2350 if self.server.chatty:
2351 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2352 self.running = False
2353 self.close()
2354 return False
2355 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002356 # OSError may occur with wrong protocols, e.g. both
2357 # sides use PROTOCOL_TLS_SERVER.
2358 #
2359 # XXX Various errors can have happened here, for example
2360 # a mismatching protocol version, an invalid certificate,
2361 # or a low-level bug. This should be made more discriminating.
2362 #
2363 # bpo-31323: Store the exception as string to prevent
2364 # a reference leak: server -> conn_errors -> exception
2365 # -> traceback -> self (ConnectionHandler) -> server
2366 self.server.conn_errors.append(str(e))
2367 if self.server.chatty:
2368 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2369 self.running = False
2370 self.server.stop()
2371 self.close()
2372 return False
2373 else:
2374 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2375 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2376 cert = self.sslconn.getpeercert()
2377 if support.verbose and self.server.chatty:
2378 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2379 cert_binary = self.sslconn.getpeercert(True)
2380 if support.verbose and self.server.chatty:
2381 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2382 cipher = self.sslconn.cipher()
2383 if support.verbose and self.server.chatty:
2384 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
2385 sys.stdout.write(" server: selected protocol is now "
2386 + str(self.sslconn.selected_npn_protocol()) + "\n")
2387 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002388
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002389 def read(self):
2390 if self.sslconn:
2391 return self.sslconn.read()
2392 else:
2393 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002394
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002395 def write(self, bytes):
2396 if self.sslconn:
2397 return self.sslconn.write(bytes)
2398 else:
2399 return self.sock.send(bytes)
2400
2401 def close(self):
2402 if self.sslconn:
2403 self.sslconn.close()
2404 else:
2405 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002406
Antoine Pitrou480a1242010-04-28 21:37:09 +00002407 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002408 self.running = True
2409 if not self.server.starttls_server:
2410 if not self.wrap_conn():
2411 return
2412 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002413 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002414 msg = self.read()
2415 stripped = msg.strip()
2416 if not stripped:
2417 # eof, so quit this handler
2418 self.running = False
2419 try:
2420 self.sock = self.sslconn.unwrap()
2421 except OSError:
2422 # Many tests shut the TCP connection down
2423 # without an SSL shutdown. This causes
2424 # unwrap() to raise OSError with errno=0!
2425 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002426 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002427 self.sslconn = None
2428 self.close()
2429 elif stripped == b'over':
2430 if support.verbose and self.server.connectionchatty:
2431 sys.stdout.write(" server: client closed connection\n")
2432 self.close()
2433 return
2434 elif (self.server.starttls_server and
2435 stripped == b'STARTTLS'):
2436 if support.verbose and self.server.connectionchatty:
2437 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2438 self.write(b"OK\n")
2439 if not self.wrap_conn():
2440 return
2441 elif (self.server.starttls_server and self.sslconn
2442 and stripped == b'ENDTLS'):
2443 if support.verbose and self.server.connectionchatty:
2444 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2445 self.write(b"OK\n")
2446 self.sock = self.sslconn.unwrap()
2447 self.sslconn = None
2448 if support.verbose and self.server.connectionchatty:
2449 sys.stdout.write(" server: connection is now unencrypted...\n")
2450 elif stripped == b'CB tls-unique':
2451 if support.verbose and self.server.connectionchatty:
2452 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2453 data = self.sslconn.get_channel_binding("tls-unique")
2454 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002455 elif stripped == b'PHA':
2456 if support.verbose and self.server.connectionchatty:
2457 sys.stdout.write(" server: initiating post handshake auth\n")
2458 try:
2459 self.sslconn.verify_client_post_handshake()
2460 except ssl.SSLError as e:
2461 self.write(repr(e).encode("us-ascii") + b"\n")
2462 else:
2463 self.write(b"OK\n")
2464 elif stripped == b'HASCERT':
2465 if self.sslconn.getpeercert() is not None:
2466 self.write(b'TRUE\n')
2467 else:
2468 self.write(b'FALSE\n')
2469 elif stripped == b'GETCERT':
2470 cert = self.sslconn.getpeercert()
2471 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002472 else:
2473 if (support.verbose and
2474 self.server.connectionchatty):
2475 ctype = (self.sslconn and "encrypted") or "unencrypted"
2476 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2477 % (msg, ctype, msg.lower(), ctype))
2478 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002479 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002480 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2481 # when connection is not shut down gracefully.
2482 if self.server.chatty and support.verbose:
2483 sys.stdout.write(
2484 " Connection reset by peer: {}\n".format(
2485 self.addr)
2486 )
2487 self.close()
2488 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002489 except ssl.SSLError as err:
2490 # On Windows sometimes test_pha_required_nocert receives the
2491 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2492 # before the 'tlsv13 alert certificate required' exception.
2493 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2494 # is received test_pha_required_nocert fails with ConnectionResetError
2495 # because the underlying socket is closed
2496 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2497 if self.server.chatty and support.verbose:
2498 sys.stdout.write(err.args[1])
2499 # test_pha_required_nocert is expecting this exception
2500 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002501 except OSError:
2502 if self.server.chatty:
2503 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002504 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002505 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002506
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002507 # normally, we'd just stop here, but for the test
2508 # harness, we want to stop the server
2509 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002510
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002511 def __init__(self, certificate=None, ssl_version=None,
2512 certreqs=None, cacerts=None,
2513 chatty=True, connectionchatty=False, starttls_server=False,
2514 npn_protocols=None, alpn_protocols=None,
2515 ciphers=None, context=None):
2516 if context:
2517 self.context = context
2518 else:
2519 self.context = ssl.SSLContext(ssl_version
2520 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002521 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002522 self.context.verify_mode = (certreqs if certreqs is not None
2523 else ssl.CERT_NONE)
2524 if cacerts:
2525 self.context.load_verify_locations(cacerts)
2526 if certificate:
2527 self.context.load_cert_chain(certificate)
2528 if npn_protocols:
2529 self.context.set_npn_protocols(npn_protocols)
2530 if alpn_protocols:
2531 self.context.set_alpn_protocols(alpn_protocols)
2532 if ciphers:
2533 self.context.set_ciphers(ciphers)
2534 self.chatty = chatty
2535 self.connectionchatty = connectionchatty
2536 self.starttls_server = starttls_server
2537 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002538 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002539 self.flag = None
2540 self.active = False
2541 self.selected_npn_protocols = []
2542 self.selected_alpn_protocols = []
2543 self.shared_ciphers = []
2544 self.conn_errors = []
2545 threading.Thread.__init__(self)
2546 self.daemon = True
2547
2548 def __enter__(self):
2549 self.start(threading.Event())
2550 self.flag.wait()
2551 return self
2552
2553 def __exit__(self, *args):
2554 self.stop()
2555 self.join()
2556
2557 def start(self, flag=None):
2558 self.flag = flag
2559 threading.Thread.start(self)
2560
2561 def run(self):
2562 self.sock.settimeout(0.05)
2563 self.sock.listen()
2564 self.active = True
2565 if self.flag:
2566 # signal an event
2567 self.flag.set()
2568 while self.active:
2569 try:
2570 newconn, connaddr = self.sock.accept()
2571 if support.verbose and self.chatty:
2572 sys.stdout.write(' server: new connection from '
2573 + repr(connaddr) + '\n')
2574 handler = self.ConnectionHandler(self, newconn, connaddr)
2575 handler.start()
2576 handler.join()
2577 except socket.timeout:
2578 pass
2579 except KeyboardInterrupt:
2580 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002581 except BaseException as e:
2582 if support.verbose and self.chatty:
2583 sys.stdout.write(
2584 ' connection handling failed: ' + repr(e) + '\n')
2585
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002586 self.sock.close()
2587
2588 def stop(self):
2589 self.active = False
2590
2591class AsyncoreEchoServer(threading.Thread):
2592
2593 # this one's based on asyncore.dispatcher
2594
2595 class EchoServer (asyncore.dispatcher):
2596
2597 class ConnectionHandler(asyncore.dispatcher_with_send):
2598
2599 def __init__(self, conn, certfile):
2600 self.socket = test_wrap_socket(conn, server_side=True,
2601 certfile=certfile,
2602 do_handshake_on_connect=False)
2603 asyncore.dispatcher_with_send.__init__(self, self.socket)
2604 self._ssl_accepting = True
2605 self._do_ssl_handshake()
2606
2607 def readable(self):
2608 if isinstance(self.socket, ssl.SSLSocket):
2609 while self.socket.pending() > 0:
2610 self.handle_read_event()
2611 return True
2612
2613 def _do_ssl_handshake(self):
2614 try:
2615 self.socket.do_handshake()
2616 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2617 return
2618 except ssl.SSLEOFError:
2619 return self.handle_close()
2620 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002621 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002622 except OSError as err:
2623 if err.args[0] == errno.ECONNABORTED:
2624 return self.handle_close()
2625 else:
2626 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002627
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002628 def handle_read(self):
2629 if self._ssl_accepting:
2630 self._do_ssl_handshake()
2631 else:
2632 data = self.recv(1024)
2633 if support.verbose:
2634 sys.stdout.write(" server: read %s from client\n" % repr(data))
2635 if not data:
2636 self.close()
2637 else:
2638 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002639
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002640 def handle_close(self):
2641 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002642 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002643 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002644
2645 def handle_error(self):
2646 raise
2647
Trent Nelson78520002008-04-10 20:54:35 +00002648 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002649 self.certfile = certfile
2650 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002651 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002652 asyncore.dispatcher.__init__(self, sock)
2653 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002654
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002655 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002656 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002657 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2658 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002659
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002660 def handle_error(self):
2661 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002662
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002663 def __init__(self, certfile):
2664 self.flag = None
2665 self.active = False
2666 self.server = self.EchoServer(certfile)
2667 self.port = self.server.port
2668 threading.Thread.__init__(self)
2669 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002670
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002671 def __str__(self):
2672 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002673
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002674 def __enter__(self):
2675 self.start(threading.Event())
2676 self.flag.wait()
2677 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002678
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002679 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002680 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002681 sys.stdout.write(" cleanup: stopping server.\n")
2682 self.stop()
2683 if support.verbose:
2684 sys.stdout.write(" cleanup: joining server thread.\n")
2685 self.join()
2686 if support.verbose:
2687 sys.stdout.write(" cleanup: successfully joined.\n")
2688 # make sure that ConnectionHandler is removed from socket_map
2689 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002690
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002691 def start (self, flag=None):
2692 self.flag = flag
2693 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002694
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002695 def run(self):
2696 self.active = True
2697 if self.flag:
2698 self.flag.set()
2699 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002700 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002701 asyncore.loop(1)
2702 except:
2703 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002704
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002705 def stop(self):
2706 self.active = False
2707 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002708
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002709def server_params_test(client_context, server_context, indata=b"FOO\n",
2710 chatty=True, connectionchatty=False, sni_name=None,
2711 session=None):
2712 """
2713 Launch a server, connect a client to it and try various reads
2714 and writes.
2715 """
2716 stats = {}
2717 server = ThreadedEchoServer(context=server_context,
2718 chatty=chatty,
2719 connectionchatty=False)
2720 with server:
2721 with client_context.wrap_socket(socket.socket(),
2722 server_hostname=sni_name, session=session) as s:
2723 s.connect((HOST, server.port))
2724 for arg in [indata, bytearray(indata), memoryview(indata)]:
2725 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002726 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002727 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002728 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002729 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002730 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002731 if connectionchatty:
2732 if support.verbose:
2733 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002734 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002735 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002736 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2737 % (outdata[:20], len(outdata),
2738 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002739 s.write(b"over\n")
2740 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002741 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002742 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002743 stats.update({
2744 'compression': s.compression(),
2745 'cipher': s.cipher(),
2746 'peercert': s.getpeercert(),
2747 'client_alpn_protocol': s.selected_alpn_protocol(),
2748 'client_npn_protocol': s.selected_npn_protocol(),
2749 'version': s.version(),
2750 'session_reused': s.session_reused,
2751 'session': s.session,
2752 })
2753 s.close()
2754 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2755 stats['server_npn_protocols'] = server.selected_npn_protocols
2756 stats['server_shared_ciphers'] = server.shared_ciphers
2757 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002758
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002759def try_protocol_combo(server_protocol, client_protocol, expect_success,
2760 certsreqs=None, server_options=0, client_options=0):
2761 """
2762 Try to SSL-connect using *client_protocol* to *server_protocol*.
2763 If *expect_success* is true, assert that the connection succeeds,
2764 if it's false, assert that the connection fails.
2765 Also, if *expect_success* is a string, assert that it is the protocol
2766 version actually used by the connection.
2767 """
2768 if certsreqs is None:
2769 certsreqs = ssl.CERT_NONE
2770 certtype = {
2771 ssl.CERT_NONE: "CERT_NONE",
2772 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2773 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2774 }[certsreqs]
2775 if support.verbose:
2776 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2777 sys.stdout.write(formatstr %
2778 (ssl.get_protocol_name(client_protocol),
2779 ssl.get_protocol_name(server_protocol),
2780 certtype))
2781 client_context = ssl.SSLContext(client_protocol)
2782 client_context.options |= client_options
2783 server_context = ssl.SSLContext(server_protocol)
2784 server_context.options |= server_options
2785
Victor Stinner3ef63442019-02-19 18:06:03 +01002786 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2787 if (min_version is not None
2788 # SSLContext.minimum_version is only available on recent OpenSSL
2789 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2790 and hasattr(server_context, 'minimum_version')
2791 and server_protocol == ssl.PROTOCOL_TLS
2792 and server_context.minimum_version > min_version):
2793 # If OpenSSL configuration is strict and requires more recent TLS
2794 # version, we have to change the minimum to test old TLS versions.
2795 server_context.minimum_version = min_version
2796
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002797 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2798 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2799 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002800 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002801 client_context.set_ciphers("ALL")
2802
2803 for ctx in (client_context, server_context):
2804 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002805 ctx.load_cert_chain(SIGNED_CERTFILE)
2806 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002807 try:
2808 stats = server_params_test(client_context, server_context,
2809 chatty=False, connectionchatty=False)
2810 # Protocol mismatch can result in either an SSLError, or a
2811 # "Connection reset by peer" error.
2812 except ssl.SSLError:
2813 if expect_success:
2814 raise
2815 except OSError as e:
2816 if expect_success or e.errno != errno.ECONNRESET:
2817 raise
2818 else:
2819 if not expect_success:
2820 raise AssertionError(
2821 "Client protocol %s succeeded with server protocol %s!"
2822 % (ssl.get_protocol_name(client_protocol),
2823 ssl.get_protocol_name(server_protocol)))
2824 elif (expect_success is not True
2825 and expect_success != stats['version']):
2826 raise AssertionError("version mismatch: expected %r, got %r"
2827 % (expect_success, stats['version']))
2828
2829
2830class ThreadedTests(unittest.TestCase):
2831
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002832 def test_echo(self):
2833 """Basic test of an SSL client connecting to a server"""
2834 if support.verbose:
2835 sys.stdout.write("\n")
2836 for protocol in PROTOCOLS:
2837 if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
2838 continue
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02002839 if not has_tls_protocol(protocol):
2840 continue
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002841 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2842 context = ssl.SSLContext(protocol)
2843 context.load_cert_chain(CERTFILE)
2844 server_params_test(context, context,
2845 chatty=True, connectionchatty=True)
2846
Christian Heimesa170fa12017-09-15 20:27:30 +02002847 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002848
2849 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2850 server_params_test(client_context=client_context,
2851 server_context=server_context,
2852 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002853 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002854
2855 client_context.check_hostname = False
2856 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2857 with self.assertRaises(ssl.SSLError) as e:
2858 server_params_test(client_context=server_context,
2859 server_context=client_context,
2860 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002861 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002862 self.assertIn('called a function you should not call',
2863 str(e.exception))
2864
2865 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2866 with self.assertRaises(ssl.SSLError) as e:
2867 server_params_test(client_context=server_context,
2868 server_context=server_context,
2869 chatty=True, connectionchatty=True)
2870 self.assertIn('called a function you should not call',
2871 str(e.exception))
2872
2873 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2874 with self.assertRaises(ssl.SSLError) as e:
2875 server_params_test(client_context=server_context,
2876 server_context=client_context,
2877 chatty=True, connectionchatty=True)
2878 self.assertIn('called a function you should not call',
2879 str(e.exception))
2880
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002881 def test_getpeercert(self):
2882 if support.verbose:
2883 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002884
2885 client_context, server_context, hostname = testing_context()
2886 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002887 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002888 with client_context.wrap_socket(socket.socket(),
2889 do_handshake_on_connect=False,
2890 server_hostname=hostname) as s:
2891 s.connect((HOST, server.port))
2892 # getpeercert() raise ValueError while the handshake isn't
2893 # done.
2894 with self.assertRaises(ValueError):
2895 s.getpeercert()
2896 s.do_handshake()
2897 cert = s.getpeercert()
2898 self.assertTrue(cert, "Can't get peer certificate.")
2899 cipher = s.cipher()
2900 if support.verbose:
2901 sys.stdout.write(pprint.pformat(cert) + '\n')
2902 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2903 if 'subject' not in cert:
2904 self.fail("No subject field in certificate: %s." %
2905 pprint.pformat(cert))
2906 if ((('organizationName', 'Python Software Foundation'),)
2907 not in cert['subject']):
2908 self.fail(
2909 "Missing or invalid 'organizationName' field in certificate subject; "
2910 "should be 'Python Software Foundation'.")
2911 self.assertIn('notBefore', cert)
2912 self.assertIn('notAfter', cert)
2913 before = ssl.cert_time_to_seconds(cert['notBefore'])
2914 after = ssl.cert_time_to_seconds(cert['notAfter'])
2915 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002916
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002917 @unittest.skipUnless(have_verify_flags(),
2918 "verify_flags need OpenSSL > 0.9.8")
2919 def test_crl_check(self):
2920 if support.verbose:
2921 sys.stdout.write("\n")
2922
Christian Heimesa170fa12017-09-15 20:27:30 +02002923 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002924
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002925 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002926 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002927
2928 # VERIFY_DEFAULT should pass
2929 server = ThreadedEchoServer(context=server_context, chatty=True)
2930 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002931 with client_context.wrap_socket(socket.socket(),
2932 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002933 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002934 cert = s.getpeercert()
2935 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002936
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002937 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002938 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002939
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002940 server = ThreadedEchoServer(context=server_context, chatty=True)
2941 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002942 with client_context.wrap_socket(socket.socket(),
2943 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002944 with self.assertRaisesRegex(ssl.SSLError,
2945 "certificate verify failed"):
2946 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002947
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002948 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002949 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002950
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002951 server = ThreadedEchoServer(context=server_context, chatty=True)
2952 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002953 with client_context.wrap_socket(socket.socket(),
2954 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002955 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002956 cert = s.getpeercert()
2957 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002958
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002959 def test_check_hostname(self):
2960 if support.verbose:
2961 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002962
Christian Heimesa170fa12017-09-15 20:27:30 +02002963 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002964
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002965 # correct hostname should verify
2966 server = ThreadedEchoServer(context=server_context, chatty=True)
2967 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002968 with client_context.wrap_socket(socket.socket(),
2969 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002970 s.connect((HOST, server.port))
2971 cert = s.getpeercert()
2972 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002973
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002974 # incorrect hostname should raise an exception
2975 server = ThreadedEchoServer(context=server_context, chatty=True)
2976 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002977 with client_context.wrap_socket(socket.socket(),
2978 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01002979 with self.assertRaisesRegex(
2980 ssl.CertificateError,
2981 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002982 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002983
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002984 # missing server_hostname arg should cause an exception, too
2985 server = ThreadedEchoServer(context=server_context, chatty=True)
2986 with server:
2987 with socket.socket() as s:
2988 with self.assertRaisesRegex(ValueError,
2989 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02002990 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002991
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002992 def test_ecc_cert(self):
2993 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2994 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02002995 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002996 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
2997
2998 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
2999 # load ECC cert
3000 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3001
3002 # correct hostname should verify
3003 server = ThreadedEchoServer(context=server_context, chatty=True)
3004 with server:
3005 with client_context.wrap_socket(socket.socket(),
3006 server_hostname=hostname) as s:
3007 s.connect((HOST, server.port))
3008 cert = s.getpeercert()
3009 self.assertTrue(cert, "Can't get peer certificate.")
3010 cipher = s.cipher()[0].split('-')
3011 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3012
3013 def test_dual_rsa_ecc(self):
3014 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3015 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003016 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3017 # algorithms.
3018 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003019 # only ECDSA certs
3020 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3021 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3022
3023 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3024 # load ECC and RSA key/cert pairs
3025 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3026 server_context.load_cert_chain(SIGNED_CERTFILE)
3027
3028 # correct hostname should verify
3029 server = ThreadedEchoServer(context=server_context, chatty=True)
3030 with server:
3031 with client_context.wrap_socket(socket.socket(),
3032 server_hostname=hostname) as s:
3033 s.connect((HOST, server.port))
3034 cert = s.getpeercert()
3035 self.assertTrue(cert, "Can't get peer certificate.")
3036 cipher = s.cipher()[0].split('-')
3037 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3038
Christian Heimes66e57422018-01-29 14:25:13 +01003039 def test_check_hostname_idn(self):
3040 if support.verbose:
3041 sys.stdout.write("\n")
3042
Christian Heimes11a14932018-02-24 02:35:08 +01003043 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003044 server_context.load_cert_chain(IDNSANSFILE)
3045
Christian Heimes11a14932018-02-24 02:35:08 +01003046 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003047 context.verify_mode = ssl.CERT_REQUIRED
3048 context.check_hostname = True
3049 context.load_verify_locations(SIGNING_CA)
3050
3051 # correct hostname should verify, when specified in several
3052 # different ways
3053 idn_hostnames = [
3054 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003055 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003056 ('xn--knig-5qa.idn.pythontest.net',
3057 'xn--knig-5qa.idn.pythontest.net'),
3058 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003059 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003060
3061 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003062 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003063 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3064 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3065 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003066 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3067
3068 # ('königsgäßchen.idna2008.pythontest.net',
3069 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3070 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3071 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3072 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3073 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3074
Christian Heimes66e57422018-01-29 14:25:13 +01003075 ]
3076 for server_hostname, expected_hostname in idn_hostnames:
3077 server = ThreadedEchoServer(context=server_context, chatty=True)
3078 with server:
3079 with context.wrap_socket(socket.socket(),
3080 server_hostname=server_hostname) as s:
3081 self.assertEqual(s.server_hostname, expected_hostname)
3082 s.connect((HOST, server.port))
3083 cert = s.getpeercert()
3084 self.assertEqual(s.server_hostname, expected_hostname)
3085 self.assertTrue(cert, "Can't get peer certificate.")
3086
Christian Heimes66e57422018-01-29 14:25:13 +01003087 # incorrect hostname should raise an exception
3088 server = ThreadedEchoServer(context=server_context, chatty=True)
3089 with server:
3090 with context.wrap_socket(socket.socket(),
3091 server_hostname="python.example.org") as s:
3092 with self.assertRaises(ssl.CertificateError):
3093 s.connect((HOST, server.port))
3094
Christian Heimes529525f2018-05-23 22:24:45 +02003095 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003096 """Connecting when the server rejects the client's certificate
3097
3098 Launch a server with CERT_REQUIRED, and check that trying to
3099 connect to it with a wrong client certificate fails.
3100 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003101 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003102 # load client cert that is not signed by trusted CA
3103 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003104 # require TLS client authentication
3105 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003106 # TLS 1.3 has different handshake
3107 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003108
3109 server = ThreadedEchoServer(
3110 context=server_context, chatty=True, connectionchatty=True,
3111 )
3112
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003113 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003114 client_context.wrap_socket(socket.socket(),
3115 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003116 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003117 # Expect either an SSL error about the server rejecting
3118 # the connection, or a low-level connection reset (which
3119 # sometimes happens on Windows)
3120 s.connect((HOST, server.port))
3121 except ssl.SSLError as e:
3122 if support.verbose:
3123 sys.stdout.write("\nSSLError is %r\n" % e)
3124 except OSError as e:
3125 if e.errno != errno.ECONNRESET:
3126 raise
3127 if support.verbose:
3128 sys.stdout.write("\nsocket.error is %r\n" % e)
3129 else:
3130 self.fail("Use of invalid cert should have failed!")
3131
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003132 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003133 def test_wrong_cert_tls13(self):
3134 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003135 # load client cert that is not signed by trusted CA
3136 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003137 server_context.verify_mode = ssl.CERT_REQUIRED
3138 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3139 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3140
3141 server = ThreadedEchoServer(
3142 context=server_context, chatty=True, connectionchatty=True,
3143 )
3144 with server, \
3145 client_context.wrap_socket(socket.socket(),
3146 server_hostname=hostname) as s:
3147 # TLS 1.3 perform client cert exchange after handshake
3148 s.connect((HOST, server.port))
3149 try:
3150 s.write(b'data')
3151 s.read(4)
3152 except ssl.SSLError as e:
3153 if support.verbose:
3154 sys.stdout.write("\nSSLError is %r\n" % e)
3155 except OSError as e:
3156 if e.errno != errno.ECONNRESET:
3157 raise
3158 if support.verbose:
3159 sys.stdout.write("\nsocket.error is %r\n" % e)
3160 else:
3161 self.fail("Use of invalid cert should have failed!")
3162
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003163 def test_rude_shutdown(self):
3164 """A brutal shutdown of an SSL server should raise an OSError
3165 in the client when attempting handshake.
3166 """
3167 listener_ready = threading.Event()
3168 listener_gone = threading.Event()
3169
3170 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003171 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003172
3173 # `listener` runs in a thread. It sits in an accept() until
3174 # the main thread connects. Then it rudely closes the socket,
3175 # and sets Event `listener_gone` to let the main thread know
3176 # the socket is gone.
3177 def listener():
3178 s.listen()
3179 listener_ready.set()
3180 newsock, addr = s.accept()
3181 newsock.close()
3182 s.close()
3183 listener_gone.set()
3184
3185 def connector():
3186 listener_ready.wait()
3187 with socket.socket() as c:
3188 c.connect((HOST, port))
3189 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003190 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003191 ssl_sock = test_wrap_socket(c)
3192 except OSError:
3193 pass
3194 else:
3195 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003196
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003197 t = threading.Thread(target=listener)
3198 t.start()
3199 try:
3200 connector()
3201 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003202 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003203
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003204 def test_ssl_cert_verify_error(self):
3205 if support.verbose:
3206 sys.stdout.write("\n")
3207
3208 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3209 server_context.load_cert_chain(SIGNED_CERTFILE)
3210
3211 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3212
3213 server = ThreadedEchoServer(context=server_context, chatty=True)
3214 with server:
3215 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003216 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003217 try:
3218 s.connect((HOST, server.port))
3219 except ssl.SSLError as e:
3220 msg = 'unable to get local issuer certificate'
3221 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3222 self.assertEqual(e.verify_code, 20)
3223 self.assertEqual(e.verify_message, msg)
3224 self.assertIn(msg, repr(e))
3225 self.assertIn('certificate verify failed', repr(e))
3226
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003227 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003228 def test_protocol_sslv2(self):
3229 """Connecting to an SSLv2 server with various client options"""
3230 if support.verbose:
3231 sys.stdout.write("\n")
3232 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3233 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3234 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003235 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003236 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003237 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3238 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3239 # SSLv23 client with specific SSL options
3240 if no_sslv2_implies_sslv3_hello():
3241 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003242 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003243 client_options=ssl.OP_NO_SSLv2)
Christian Heimesa170fa12017-09-15 20:27:30 +02003244 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003245 client_options=ssl.OP_NO_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003246 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003247 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003248
Christian Heimesa170fa12017-09-15 20:27:30 +02003249 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003250 """Connecting to an SSLv23 server with various client options"""
3251 if support.verbose:
3252 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003253 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003254 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003255 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003256 except OSError as x:
3257 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3258 if support.verbose:
3259 sys.stdout.write(
3260 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3261 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003262 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003263 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3264 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003265 if has_tls_version('TLSv1'):
3266 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003267
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, ssl.CERT_OPTIONAL)
3270 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003271 if has_tls_version('TLSv1'):
3272 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003273
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_REQUIRED)
3276 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
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_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003279
3280 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003281 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003282 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003283 server_options=ssl.OP_NO_SSLv3)
3284 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003285 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003286 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003287 if has_tls_version('TLSv1'):
3288 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3289 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003290
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003291 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003292 def test_protocol_sslv3(self):
3293 """Connecting to an SSLv3 server with various client options"""
3294 if support.verbose:
3295 sys.stdout.write("\n")
3296 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3297 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3298 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003299 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003300 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003301 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003302 client_options=ssl.OP_NO_SSLv3)
3303 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3304 if no_sslv2_implies_sslv3_hello():
3305 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003306 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003307 False, client_options=ssl.OP_NO_SSLv2)
3308
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003309 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003310 def test_protocol_tlsv1(self):
3311 """Connecting to a TLSv1 server with various client options"""
3312 if support.verbose:
3313 sys.stdout.write("\n")
3314 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3315 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3316 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003317 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003318 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003319 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003320 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003321 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003322 client_options=ssl.OP_NO_TLSv1)
3323
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003324 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003325 def test_protocol_tlsv1_1(self):
3326 """Connecting to a TLSv1.1 server with various client options.
3327 Testing against older TLS versions."""
3328 if support.verbose:
3329 sys.stdout.write("\n")
3330 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003331 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003332 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003333 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003334 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003335 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003336 client_options=ssl.OP_NO_TLSv1_1)
3337
Christian Heimesa170fa12017-09-15 20:27:30 +02003338 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003339 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3340 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003341
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003342 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003343 def test_protocol_tlsv1_2(self):
3344 """Connecting to a TLSv1.2 server with various client options.
3345 Testing against older TLS versions."""
3346 if support.verbose:
3347 sys.stdout.write("\n")
3348 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3349 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3350 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003351 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003352 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003353 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003354 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003355 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003356 client_options=ssl.OP_NO_TLSv1_2)
3357
Christian Heimesa170fa12017-09-15 20:27:30 +02003358 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003359 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3360 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3361 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3362 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3363
3364 def test_starttls(self):
3365 """Switching from clear text to encrypted and back again."""
3366 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3367
3368 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003369 starttls_server=True,
3370 chatty=True,
3371 connectionchatty=True)
3372 wrapped = False
3373 with server:
3374 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003375 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003376 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003377 if support.verbose:
3378 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003379 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003380 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003381 sys.stdout.write(
3382 " client: sending %r...\n" % indata)
3383 if wrapped:
3384 conn.write(indata)
3385 outdata = conn.read()
3386 else:
3387 s.send(indata)
3388 outdata = s.recv(1024)
3389 msg = outdata.strip().lower()
3390 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3391 # STARTTLS ok, switch to secure mode
3392 if support.verbose:
3393 sys.stdout.write(
3394 " client: read %r from server, starting TLS...\n"
3395 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003396 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003397 wrapped = True
3398 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3399 # ENDTLS ok, switch back to clear text
3400 if support.verbose:
3401 sys.stdout.write(
3402 " client: read %r from server, ending TLS...\n"
3403 % msg)
3404 s = conn.unwrap()
3405 wrapped = False
3406 else:
3407 if support.verbose:
3408 sys.stdout.write(
3409 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003410 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003411 sys.stdout.write(" client: closing connection.\n")
3412 if wrapped:
3413 conn.write(b"over\n")
3414 else:
3415 s.send(b"over\n")
3416 if wrapped:
3417 conn.close()
3418 else:
3419 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003420
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003421 def test_socketserver(self):
3422 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003423 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003424 # try to connect
3425 if support.verbose:
3426 sys.stdout.write('\n')
3427 with open(CERTFILE, 'rb') as f:
3428 d1 = f.read()
3429 d2 = ''
3430 # now fetch the same data from the HTTPS server
3431 url = 'https://localhost:%d/%s' % (
3432 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003433 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003434 f = urllib.request.urlopen(url, context=context)
3435 try:
3436 dlen = f.info().get("content-length")
3437 if dlen and (int(dlen) > 0):
3438 d2 = f.read(int(dlen))
3439 if support.verbose:
3440 sys.stdout.write(
3441 " client: read %d bytes from remote server '%s'\n"
3442 % (len(d2), server))
3443 finally:
3444 f.close()
3445 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003446
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003447 def test_asyncore_server(self):
3448 """Check the example asyncore integration."""
3449 if support.verbose:
3450 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003451
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003452 indata = b"FOO\n"
3453 server = AsyncoreEchoServer(CERTFILE)
3454 with server:
3455 s = test_wrap_socket(socket.socket())
3456 s.connect(('127.0.0.1', server.port))
3457 if support.verbose:
3458 sys.stdout.write(
3459 " client: sending %r...\n" % indata)
3460 s.write(indata)
3461 outdata = s.read()
3462 if support.verbose:
3463 sys.stdout.write(" client: read %r\n" % outdata)
3464 if outdata != indata.lower():
3465 self.fail(
3466 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3467 % (outdata[:20], len(outdata),
3468 indata[:20].lower(), len(indata)))
3469 s.write(b"over\n")
3470 if support.verbose:
3471 sys.stdout.write(" client: closing connection.\n")
3472 s.close()
3473 if support.verbose:
3474 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003475
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003476 def test_recv_send(self):
3477 """Test recv(), send() and friends."""
3478 if support.verbose:
3479 sys.stdout.write("\n")
3480
3481 server = ThreadedEchoServer(CERTFILE,
3482 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003483 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003484 cacerts=CERTFILE,
3485 chatty=True,
3486 connectionchatty=False)
3487 with server:
3488 s = test_wrap_socket(socket.socket(),
3489 server_side=False,
3490 certfile=CERTFILE,
3491 ca_certs=CERTFILE,
3492 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003493 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003494 s.connect((HOST, server.port))
3495 # helper methods for standardising recv* method signatures
3496 def _recv_into():
3497 b = bytearray(b"\0"*100)
3498 count = s.recv_into(b)
3499 return b[:count]
3500
3501 def _recvfrom_into():
3502 b = bytearray(b"\0"*100)
3503 count, addr = s.recvfrom_into(b)
3504 return b[:count]
3505
3506 # (name, method, expect success?, *args, return value func)
3507 send_methods = [
3508 ('send', s.send, True, [], len),
3509 ('sendto', s.sendto, False, ["some.address"], len),
3510 ('sendall', s.sendall, True, [], lambda x: None),
3511 ]
3512 # (name, method, whether to expect success, *args)
3513 recv_methods = [
3514 ('recv', s.recv, True, []),
3515 ('recvfrom', s.recvfrom, False, ["some.address"]),
3516 ('recv_into', _recv_into, True, []),
3517 ('recvfrom_into', _recvfrom_into, False, []),
3518 ]
3519 data_prefix = "PREFIX_"
3520
3521 for (meth_name, send_meth, expect_success, args,
3522 ret_val_meth) in send_methods:
3523 indata = (data_prefix + meth_name).encode('ascii')
3524 try:
3525 ret = send_meth(indata, *args)
3526 msg = "sending with {}".format(meth_name)
3527 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3528 outdata = s.read()
3529 if outdata != indata.lower():
3530 self.fail(
3531 "While sending with <<{name:s}>> bad data "
3532 "<<{outdata:r}>> ({nout:d}) received; "
3533 "expected <<{indata:r}>> ({nin:d})\n".format(
3534 name=meth_name, outdata=outdata[:20],
3535 nout=len(outdata),
3536 indata=indata[:20], nin=len(indata)
3537 )
3538 )
3539 except ValueError as e:
3540 if expect_success:
3541 self.fail(
3542 "Failed to send with method <<{name:s}>>; "
3543 "expected to succeed.\n".format(name=meth_name)
3544 )
3545 if not str(e).startswith(meth_name):
3546 self.fail(
3547 "Method <<{name:s}>> failed with unexpected "
3548 "exception message: {exp:s}\n".format(
3549 name=meth_name, exp=e
3550 )
3551 )
3552
3553 for meth_name, recv_meth, expect_success, args in recv_methods:
3554 indata = (data_prefix + meth_name).encode('ascii')
3555 try:
3556 s.send(indata)
3557 outdata = recv_meth(*args)
3558 if outdata != indata.lower():
3559 self.fail(
3560 "While receiving with <<{name:s}>> bad data "
3561 "<<{outdata:r}>> ({nout:d}) received; "
3562 "expected <<{indata:r}>> ({nin:d})\n".format(
3563 name=meth_name, outdata=outdata[:20],
3564 nout=len(outdata),
3565 indata=indata[:20], nin=len(indata)
3566 )
3567 )
3568 except ValueError as e:
3569 if expect_success:
3570 self.fail(
3571 "Failed to receive with method <<{name:s}>>; "
3572 "expected to succeed.\n".format(name=meth_name)
3573 )
3574 if not str(e).startswith(meth_name):
3575 self.fail(
3576 "Method <<{name:s}>> failed with unexpected "
3577 "exception message: {exp:s}\n".format(
3578 name=meth_name, exp=e
3579 )
3580 )
3581 # consume data
3582 s.read()
3583
3584 # read(-1, buffer) is supported, even though read(-1) is not
3585 data = b"data"
3586 s.send(data)
3587 buffer = bytearray(len(data))
3588 self.assertEqual(s.read(-1, buffer), len(data))
3589 self.assertEqual(buffer, data)
3590
Christian Heimes888bbdc2017-09-07 14:18:21 -07003591 # sendall accepts bytes-like objects
3592 if ctypes is not None:
3593 ubyte = ctypes.c_ubyte * len(data)
3594 byteslike = ubyte.from_buffer_copy(data)
3595 s.sendall(byteslike)
3596 self.assertEqual(s.read(), data)
3597
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003598 # Make sure sendmsg et al are disallowed to avoid
3599 # inadvertent disclosure of data and/or corruption
3600 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003601 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003602 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3603 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3604 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003605 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003606 s.write(b"over\n")
3607
3608 self.assertRaises(ValueError, s.recv, -1)
3609 self.assertRaises(ValueError, s.read, -1)
3610
3611 s.close()
3612
3613 def test_recv_zero(self):
3614 server = ThreadedEchoServer(CERTFILE)
3615 server.__enter__()
3616 self.addCleanup(server.__exit__, None, None)
3617 s = socket.create_connection((HOST, server.port))
3618 self.addCleanup(s.close)
3619 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3620 self.addCleanup(s.close)
3621
3622 # recv/read(0) should return no data
3623 s.send(b"data")
3624 self.assertEqual(s.recv(0), b"")
3625 self.assertEqual(s.read(0), b"")
3626 self.assertEqual(s.read(), b"data")
3627
3628 # Should not block if the other end sends no data
3629 s.setblocking(False)
3630 self.assertEqual(s.recv(0), b"")
3631 self.assertEqual(s.recv_into(bytearray()), 0)
3632
3633 def test_nonblocking_send(self):
3634 server = ThreadedEchoServer(CERTFILE,
3635 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003636 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003637 cacerts=CERTFILE,
3638 chatty=True,
3639 connectionchatty=False)
3640 with server:
3641 s = test_wrap_socket(socket.socket(),
3642 server_side=False,
3643 certfile=CERTFILE,
3644 ca_certs=CERTFILE,
3645 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003646 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
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
3694 self.assertRaisesRegex(socket.timeout, "timed out",
3695 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
3703 self.assertRaisesRegex(socket.timeout, "timed out",
3704 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 Heimesa170fa12017-09-15 20:27:30 +02003715 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003716 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003717 context.load_verify_locations(SIGNING_CA)
3718 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003719 server = socket.socket(socket.AF_INET)
3720 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003721 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003722 server = context.wrap_socket(server, server_side=True)
3723 self.assertTrue(server.server_side)
3724
3725 evt = threading.Event()
3726 remote = None
3727 peer = None
3728 def serve():
3729 nonlocal remote, peer
3730 server.listen()
3731 # Block on the accept and wait on the connection to close.
3732 evt.set()
3733 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003734 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003735
3736 t = threading.Thread(target=serve)
3737 t.start()
3738 # Client wait until server setup and perform a connect.
3739 evt.wait()
3740 client = context.wrap_socket(socket.socket())
3741 client.connect((host, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003742 client.send(b'data')
3743 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003744 client_addr = client.getsockname()
3745 client.close()
3746 t.join()
3747 remote.close()
3748 server.close()
3749 # Sanity checks.
3750 self.assertIsInstance(remote, ssl.SSLSocket)
3751 self.assertEqual(peer, client_addr)
3752
3753 def test_getpeercert_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003754 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
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 Heimesa170fa12017-09-15 20:27:30 +02003761 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003762 with context.wrap_socket(socket.socket()) as sock:
3763 with self.assertRaises(OSError) as cm:
3764 sock.do_handshake()
3765 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3766
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003767 def test_no_shared_ciphers(self):
3768 client_context, server_context, hostname = testing_context()
3769 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3770 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003771 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003772 client_context.set_ciphers("AES128")
3773 server_context.set_ciphers("AES256")
3774 with ThreadedEchoServer(context=server_context) as server:
3775 with client_context.wrap_socket(socket.socket(),
3776 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003777 with self.assertRaises(OSError):
3778 s.connect((HOST, server.port))
3779 self.assertIn("no shared cipher", server.conn_errors[0])
3780
3781 def test_version_basic(self):
3782 """
3783 Basic tests for SSLSocket.version().
3784 More tests are done in the test_protocol_*() methods.
3785 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003786 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3787 context.check_hostname = False
3788 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003789 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003790 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003791 chatty=False) as server:
3792 with context.wrap_socket(socket.socket()) as s:
3793 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003794 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003795 s.connect((HOST, server.port))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003796 if IS_OPENSSL_1_1_1 and has_tls_version('TLSv1_3'):
Christian Heimes05d9fe32018-02-27 08:55:39 +01003797 self.assertEqual(s.version(), 'TLSv1.3')
3798 elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
Christian Heimesa170fa12017-09-15 20:27:30 +02003799 self.assertEqual(s.version(), 'TLSv1.2')
3800 else: # 0.9.8 to 1.0.1
3801 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2'))
Christian Heimes141c5e82018-02-24 21:10:57 +01003802 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003803 self.assertIs(s.version(), None)
3804
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003805 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003806 def test_tls1_3(self):
3807 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
3808 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003809 context.options |= (
3810 ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2
3811 )
3812 with ThreadedEchoServer(context=context) as server:
3813 with context.wrap_socket(socket.socket()) as s:
3814 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003815 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003816 'TLS_AES_256_GCM_SHA384',
3817 'TLS_CHACHA20_POLY1305_SHA256',
3818 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003819 })
3820 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003821
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003822 @requires_minimum_version
3823 @requires_tls_version('TLSv1_2')
3824 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003825 client_context, server_context, hostname = testing_context()
3826 # client TLSv1.0 to 1.2
3827 client_context.minimum_version = ssl.TLSVersion.TLSv1
3828 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3829 # server only TLSv1.2
3830 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3831 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3832
3833 with ThreadedEchoServer(context=server_context) as server:
3834 with client_context.wrap_socket(socket.socket(),
3835 server_hostname=hostname) as s:
3836 s.connect((HOST, server.port))
3837 self.assertEqual(s.version(), 'TLSv1.2')
3838
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003839 @requires_minimum_version
3840 @requires_tls_version('TLSv1_1')
3841 def test_min_max_version_tlsv1_1(self):
3842 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003843 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003844 client_context.minimum_version = ssl.TLSVersion.TLSv1
3845 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003846 server_context.minimum_version = ssl.TLSVersion.TLSv1
3847 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
3848
3849 with ThreadedEchoServer(context=server_context) as server:
3850 with client_context.wrap_socket(socket.socket(),
3851 server_hostname=hostname) as s:
3852 s.connect((HOST, server.port))
3853 self.assertEqual(s.version(), 'TLSv1.1')
3854
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003855 @requires_minimum_version
3856 @requires_tls_version('TLSv1_2')
3857 def test_min_max_version_mismatch(self):
3858 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003859 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003860 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003861 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003862 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003863 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimes698dde12018-02-27 11:54:43 +01003864 with ThreadedEchoServer(context=server_context) as server:
3865 with client_context.wrap_socket(socket.socket(),
3866 server_hostname=hostname) as s:
3867 with self.assertRaises(ssl.SSLError) as e:
3868 s.connect((HOST, server.port))
3869 self.assertIn("alert", str(e.exception))
3870
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003871 @requires_minimum_version
3872 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003873 def test_min_max_version_sslv3(self):
3874 client_context, server_context, hostname = testing_context()
3875 server_context.minimum_version = ssl.TLSVersion.SSLv3
3876 client_context.minimum_version = ssl.TLSVersion.SSLv3
3877 client_context.maximum_version = ssl.TLSVersion.SSLv3
3878 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 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3885 def test_default_ecdh_curve(self):
3886 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3887 # should be enabled by default on SSL contexts.
Christian Heimesa170fa12017-09-15 20:27:30 +02003888 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003889 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003890 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3891 # cipher name.
3892 context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003893 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3894 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3895 # our default cipher list should prefer ECDH-based ciphers
3896 # automatically.
3897 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
3898 context.set_ciphers("ECCdraft:ECDH")
3899 with ThreadedEchoServer(context=context) as server:
3900 with context.wrap_socket(socket.socket()) as s:
3901 s.connect((HOST, server.port))
3902 self.assertIn("ECDH", s.cipher()[0])
3903
3904 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3905 "'tls-unique' channel binding not available")
3906 def test_tls_unique_channel_binding(self):
3907 """Test tls-unique channel binding."""
3908 if support.verbose:
3909 sys.stdout.write("\n")
3910
Christian Heimes05d9fe32018-02-27 08:55:39 +01003911 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003912
3913 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003914 chatty=True,
3915 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003916
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003917 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003918 with client_context.wrap_socket(
3919 socket.socket(),
3920 server_hostname=hostname) as s:
3921 s.connect((HOST, server.port))
3922 # get the data
3923 cb_data = s.get_channel_binding("tls-unique")
3924 if support.verbose:
3925 sys.stdout.write(
3926 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003927
Christian Heimes05d9fe32018-02-27 08:55:39 +01003928 # check if it is sane
3929 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003930 if s.version() == 'TLSv1.3':
3931 self.assertEqual(len(cb_data), 48)
3932 else:
3933 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003934
Christian Heimes05d9fe32018-02-27 08:55:39 +01003935 # and compare with the peers version
3936 s.write(b"CB tls-unique\n")
3937 peer_data_repr = s.read().strip()
3938 self.assertEqual(peer_data_repr,
3939 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003940
3941 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003942 with client_context.wrap_socket(
3943 socket.socket(),
3944 server_hostname=hostname) as s:
3945 s.connect((HOST, server.port))
3946 new_cb_data = s.get_channel_binding("tls-unique")
3947 if support.verbose:
3948 sys.stdout.write(
3949 "got another channel binding data: {0!r}\n".format(
3950 new_cb_data)
3951 )
3952 # is it really unique
3953 self.assertNotEqual(cb_data, new_cb_data)
3954 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003955 if s.version() == 'TLSv1.3':
3956 self.assertEqual(len(cb_data), 48)
3957 else:
3958 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003959 s.write(b"CB tls-unique\n")
3960 peer_data_repr = s.read().strip()
3961 self.assertEqual(peer_data_repr,
3962 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003963
3964 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003965 client_context, server_context, hostname = testing_context()
3966 stats = server_params_test(client_context, server_context,
3967 chatty=True, connectionchatty=True,
3968 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003969 if support.verbose:
3970 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
3971 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
3972
3973 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
3974 "ssl.OP_NO_COMPRESSION needed for this test")
3975 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003976 client_context, server_context, hostname = testing_context()
3977 client_context.options |= ssl.OP_NO_COMPRESSION
3978 server_context.options |= ssl.OP_NO_COMPRESSION
3979 stats = server_params_test(client_context, server_context,
3980 chatty=True, connectionchatty=True,
3981 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003982 self.assertIs(stats['compression'], None)
3983
Paul Monsonf3550692019-06-19 13:09:54 -07003984 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003985 def test_dh_params(self):
3986 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02003987 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003988 # test scenario needs TLS <= 1.2
3989 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02003990 server_context.load_dh_params(DHFILE)
3991 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01003992 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02003993 stats = server_params_test(client_context, server_context,
3994 chatty=True, connectionchatty=True,
3995 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003996 cipher = stats["cipher"][0]
3997 parts = cipher.split("-")
3998 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
3999 self.fail("Non-DH cipher: " + cipher[0])
4000
Christian Heimesb7b92252018-02-25 09:49:31 +01004001 @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004002 @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
Christian Heimesb7b92252018-02-25 09:49:31 +01004003 def test_ecdh_curve(self):
4004 # server secp384r1, client auto
4005 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004006
Christian Heimesb7b92252018-02-25 09:49:31 +01004007 server_context.set_ecdh_curve("secp384r1")
4008 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4009 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4010 stats = server_params_test(client_context, server_context,
4011 chatty=True, connectionchatty=True,
4012 sni_name=hostname)
4013
4014 # server auto, client secp384r1
4015 client_context, server_context, hostname = testing_context()
4016 client_context.set_ecdh_curve("secp384r1")
4017 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4018 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4019 stats = server_params_test(client_context, server_context,
4020 chatty=True, connectionchatty=True,
4021 sni_name=hostname)
4022
4023 # server / client curve mismatch
4024 client_context, server_context, hostname = testing_context()
4025 client_context.set_ecdh_curve("prime256v1")
4026 server_context.set_ecdh_curve("secp384r1")
4027 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4028 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4029 try:
4030 stats = server_params_test(client_context, server_context,
4031 chatty=True, connectionchatty=True,
4032 sni_name=hostname)
4033 except ssl.SSLError:
4034 pass
4035 else:
4036 # OpenSSL 1.0.2 does not fail although it should.
Christian Heimes05d9fe32018-02-27 08:55:39 +01004037 if IS_OPENSSL_1_1_0:
Christian Heimesb7b92252018-02-25 09:49:31 +01004038 self.fail("mismatch curve did not fail")
4039
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004040 def test_selected_alpn_protocol(self):
4041 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004042 client_context, server_context, hostname = testing_context()
4043 stats = server_params_test(client_context, server_context,
4044 chatty=True, connectionchatty=True,
4045 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004046 self.assertIs(stats['client_alpn_protocol'], None)
4047
4048 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
4049 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4050 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004051 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004052 server_context.set_alpn_protocols(['foo', 'bar'])
4053 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004054 chatty=True, connectionchatty=True,
4055 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004056 self.assertIs(stats['client_alpn_protocol'], None)
4057
4058 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
4059 def test_alpn_protocols(self):
4060 server_protocols = ['foo', 'bar', 'milkshake']
4061 protocol_tests = [
4062 (['foo', 'bar'], 'foo'),
4063 (['bar', 'foo'], 'foo'),
4064 (['milkshake'], 'milkshake'),
4065 (['http/3.0', 'http/4.0'], None)
4066 ]
4067 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004068 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004069 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004070 client_context.set_alpn_protocols(client_protocols)
4071
4072 try:
4073 stats = server_params_test(client_context,
4074 server_context,
4075 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004076 connectionchatty=True,
4077 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004078 except ssl.SSLError as e:
4079 stats = e
4080
Christian Heimes05d9fe32018-02-27 08:55:39 +01004081 if (expected is None and IS_OPENSSL_1_1_0
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004082 and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)):
4083 # OpenSSL 1.1.0 to 1.1.0e raises handshake error
4084 self.assertIsInstance(stats, ssl.SSLError)
4085 else:
4086 msg = "failed trying %s (s) and %s (c).\n" \
4087 "was expecting %s, but got %%s from the %%s" \
4088 % (str(server_protocols), str(client_protocols),
4089 str(expected))
4090 client_result = stats['client_alpn_protocol']
4091 self.assertEqual(client_result, expected,
4092 msg % (client_result, "client"))
4093 server_result = stats['server_alpn_protocols'][-1] \
4094 if len(stats['server_alpn_protocols']) else 'nothing'
4095 self.assertEqual(server_result, expected,
4096 msg % (server_result, "server"))
4097
4098 def test_selected_npn_protocol(self):
4099 # selected_npn_protocol() is None unless NPN is used
Christian Heimesa170fa12017-09-15 20:27:30 +02004100 client_context, server_context, hostname = testing_context()
4101 stats = server_params_test(client_context, server_context,
4102 chatty=True, connectionchatty=True,
4103 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004104 self.assertIs(stats['client_npn_protocol'], None)
4105
4106 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
4107 def test_npn_protocols(self):
4108 server_protocols = ['http/1.1', 'spdy/2']
4109 protocol_tests = [
4110 (['http/1.1', 'spdy/2'], 'http/1.1'),
4111 (['spdy/2', 'http/1.1'], 'http/1.1'),
4112 (['spdy/2', 'test'], 'spdy/2'),
4113 (['abc', 'def'], 'abc')
4114 ]
4115 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004116 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004117 server_context.set_npn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004118 client_context.set_npn_protocols(client_protocols)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004119 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004120 chatty=True, connectionchatty=True,
4121 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004122 msg = "failed trying %s (s) and %s (c).\n" \
4123 "was expecting %s, but got %%s from the %%s" \
4124 % (str(server_protocols), str(client_protocols),
4125 str(expected))
4126 client_result = stats['client_npn_protocol']
4127 self.assertEqual(client_result, expected, msg % (client_result, "client"))
4128 server_result = stats['server_npn_protocols'][-1] \
4129 if len(stats['server_npn_protocols']) else 'nothing'
4130 self.assertEqual(server_result, expected, msg % (server_result, "server"))
4131
4132 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004133 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004134 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004135 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004136 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004137 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004138 client_context.load_verify_locations(SIGNING_CA)
4139 return server_context, other_context, client_context
4140
4141 def check_common_name(self, stats, name):
4142 cert = stats['peercert']
4143 self.assertIn((('commonName', name),), cert['subject'])
4144
4145 @needs_sni
4146 def test_sni_callback(self):
4147 calls = []
4148 server_context, other_context, client_context = self.sni_contexts()
4149
Christian Heimesa170fa12017-09-15 20:27:30 +02004150 client_context.check_hostname = False
4151
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004152 def servername_cb(ssl_sock, server_name, initial_context):
4153 calls.append((server_name, initial_context))
4154 if server_name is not None:
4155 ssl_sock.context = other_context
4156 server_context.set_servername_callback(servername_cb)
4157
4158 stats = server_params_test(client_context, server_context,
4159 chatty=True,
4160 sni_name='supermessage')
4161 # The hostname was fetched properly, and the certificate was
4162 # changed for the connection.
4163 self.assertEqual(calls, [("supermessage", server_context)])
4164 # CERTFILE4 was selected
4165 self.check_common_name(stats, 'fakehostname')
4166
4167 calls = []
4168 # The callback is called with server_name=None
4169 stats = server_params_test(client_context, server_context,
4170 chatty=True,
4171 sni_name=None)
4172 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004173 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004174
4175 # Check disabling the callback
4176 calls = []
4177 server_context.set_servername_callback(None)
4178
4179 stats = server_params_test(client_context, server_context,
4180 chatty=True,
4181 sni_name='notfunny')
4182 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004183 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004184 self.assertEqual(calls, [])
4185
4186 @needs_sni
4187 def test_sni_callback_alert(self):
4188 # Returning a TLS alert is reflected to the connecting client
4189 server_context, other_context, client_context = self.sni_contexts()
4190
4191 def cb_returning_alert(ssl_sock, server_name, initial_context):
4192 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4193 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004194 with self.assertRaises(ssl.SSLError) as cm:
4195 stats = server_params_test(client_context, server_context,
4196 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004197 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004198 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004199
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004200 @needs_sni
4201 def test_sni_callback_raising(self):
4202 # Raising fails the connection with a TLS handshake failure alert.
4203 server_context, other_context, client_context = self.sni_contexts()
4204
4205 def cb_raising(ssl_sock, server_name, initial_context):
4206 1/0
4207 server_context.set_servername_callback(cb_raising)
4208
Victor Stinner00253502019-06-03 03:51:43 +02004209 with support.catch_unraisable_exception() as catch:
4210 with self.assertRaises(ssl.SSLError) as cm:
4211 stats = server_params_test(client_context, server_context,
4212 chatty=False,
4213 sni_name='supermessage')
4214
4215 self.assertEqual(cm.exception.reason,
4216 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4217 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004218
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004219 @needs_sni
4220 def test_sni_callback_wrong_return_type(self):
4221 # Returning the wrong return type terminates the TLS connection
4222 # with an internal error alert.
4223 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004224
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004225 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4226 return "foo"
4227 server_context.set_servername_callback(cb_wrong_return_type)
4228
Victor Stinner00253502019-06-03 03:51:43 +02004229 with support.catch_unraisable_exception() as catch:
4230 with self.assertRaises(ssl.SSLError) as cm:
4231 stats = server_params_test(client_context, server_context,
4232 chatty=False,
4233 sni_name='supermessage')
4234
4235
4236 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4237 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004238
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004239 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004240 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004241 client_context.set_ciphers("AES128:AES256")
4242 server_context.set_ciphers("AES256")
4243 expected_algs = [
4244 "AES256", "AES-256",
4245 # TLS 1.3 ciphers are always enabled
4246 "TLS_CHACHA20", "TLS_AES",
4247 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004248
Christian Heimesa170fa12017-09-15 20:27:30 +02004249 stats = server_params_test(client_context, server_context,
4250 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004251 ciphers = stats['server_shared_ciphers'][0]
4252 self.assertGreater(len(ciphers), 0)
4253 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004254 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004255 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004256
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004257 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004258 client_context, server_context, hostname = testing_context()
4259 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004260
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004261 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004262 s = client_context.wrap_socket(socket.socket(),
4263 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004264 s.connect((HOST, server.port))
4265 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004266
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004267 self.assertRaises(ValueError, s.read, 1024)
4268 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004269
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004270 def test_sendfile(self):
4271 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004272 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004273 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004274 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesa170fa12017-09-15 20:27:30 +02004275 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004276 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01004277 context.load_verify_locations(SIGNING_CA)
4278 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004279 server = ThreadedEchoServer(context=context, chatty=False)
4280 with server:
4281 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004282 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004283 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004284 s.sendfile(file)
4285 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004286
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004287 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004288 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004289 # TODO: sessions aren't compatible with TLSv1.3 yet
4290 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004291
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004292 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004293 stats = server_params_test(client_context, server_context,
4294 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004295 session = stats['session']
4296 self.assertTrue(session.id)
4297 self.assertGreater(session.time, 0)
4298 self.assertGreater(session.timeout, 0)
4299 self.assertTrue(session.has_ticket)
4300 if ssl.OPENSSL_VERSION_INFO > (1, 0, 1):
4301 self.assertGreater(session.ticket_lifetime_hint, 0)
4302 self.assertFalse(stats['session_reused'])
4303 sess_stat = server_context.session_stats()
4304 self.assertEqual(sess_stat['accept'], 1)
4305 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004306
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004307 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004308 stats = server_params_test(client_context, server_context,
4309 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004310 sess_stat = server_context.session_stats()
4311 self.assertEqual(sess_stat['accept'], 2)
4312 self.assertEqual(sess_stat['hits'], 1)
4313 self.assertTrue(stats['session_reused'])
4314 session2 = stats['session']
4315 self.assertEqual(session2.id, session.id)
4316 self.assertEqual(session2, session)
4317 self.assertIsNot(session2, session)
4318 self.assertGreaterEqual(session2.time, session.time)
4319 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004320
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004321 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004322 stats = server_params_test(client_context, server_context,
4323 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004324 self.assertFalse(stats['session_reused'])
4325 session3 = stats['session']
4326 self.assertNotEqual(session3.id, session.id)
4327 self.assertNotEqual(session3, session)
4328 sess_stat = server_context.session_stats()
4329 self.assertEqual(sess_stat['accept'], 3)
4330 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004331
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004332 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004333 stats = server_params_test(client_context, server_context,
4334 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004335 self.assertTrue(stats['session_reused'])
4336 session4 = stats['session']
4337 self.assertEqual(session4.id, session.id)
4338 self.assertEqual(session4, session)
4339 self.assertGreaterEqual(session4.time, session.time)
4340 self.assertGreaterEqual(session4.timeout, session.timeout)
4341 sess_stat = server_context.session_stats()
4342 self.assertEqual(sess_stat['accept'], 4)
4343 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004344
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004345 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004346 client_context, server_context, hostname = testing_context()
4347 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004348
Christian Heimes05d9fe32018-02-27 08:55:39 +01004349 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004350 client_context.options |= ssl.OP_NO_TLSv1_3
4351 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004352
Christian Heimesa170fa12017-09-15 20:27:30 +02004353 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004354 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004355 with client_context.wrap_socket(socket.socket(),
4356 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004357 # session is None before handshake
4358 self.assertEqual(s.session, None)
4359 self.assertEqual(s.session_reused, None)
4360 s.connect((HOST, server.port))
4361 session = s.session
4362 self.assertTrue(session)
4363 with self.assertRaises(TypeError) as e:
4364 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004365 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004366
Christian Heimesa170fa12017-09-15 20:27:30 +02004367 with client_context.wrap_socket(socket.socket(),
4368 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004369 s.connect((HOST, server.port))
4370 # cannot set session after handshake
4371 with self.assertRaises(ValueError) as e:
4372 s.session = session
4373 self.assertEqual(str(e.exception),
4374 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004375
Christian Heimesa170fa12017-09-15 20:27:30 +02004376 with client_context.wrap_socket(socket.socket(),
4377 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004378 # can set session before handshake and before the
4379 # connection was established
4380 s.session = session
4381 s.connect((HOST, server.port))
4382 self.assertEqual(s.session.id, session.id)
4383 self.assertEqual(s.session, session)
4384 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004385
Christian Heimesa170fa12017-09-15 20:27:30 +02004386 with client_context2.wrap_socket(socket.socket(),
4387 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004388 # cannot re-use session with a different SSLContext
4389 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004390 s.session = session
4391 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004392 self.assertEqual(str(e.exception),
4393 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004394
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004395
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004396@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004397class TestPostHandshakeAuth(unittest.TestCase):
4398 def test_pha_setter(self):
4399 protocols = [
4400 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
4401 ]
4402 for protocol in protocols:
4403 ctx = ssl.SSLContext(protocol)
4404 self.assertEqual(ctx.post_handshake_auth, False)
4405
4406 ctx.post_handshake_auth = True
4407 self.assertEqual(ctx.post_handshake_auth, True)
4408
4409 ctx.verify_mode = ssl.CERT_REQUIRED
4410 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4411 self.assertEqual(ctx.post_handshake_auth, True)
4412
4413 ctx.post_handshake_auth = False
4414 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4415 self.assertEqual(ctx.post_handshake_auth, False)
4416
4417 ctx.verify_mode = ssl.CERT_OPTIONAL
4418 ctx.post_handshake_auth = True
4419 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4420 self.assertEqual(ctx.post_handshake_auth, True)
4421
4422 def test_pha_required(self):
4423 client_context, server_context, hostname = testing_context()
4424 server_context.post_handshake_auth = True
4425 server_context.verify_mode = ssl.CERT_REQUIRED
4426 client_context.post_handshake_auth = True
4427 client_context.load_cert_chain(SIGNED_CERTFILE)
4428
4429 server = ThreadedEchoServer(context=server_context, chatty=False)
4430 with server:
4431 with client_context.wrap_socket(socket.socket(),
4432 server_hostname=hostname) as s:
4433 s.connect((HOST, server.port))
4434 s.write(b'HASCERT')
4435 self.assertEqual(s.recv(1024), b'FALSE\n')
4436 s.write(b'PHA')
4437 self.assertEqual(s.recv(1024), b'OK\n')
4438 s.write(b'HASCERT')
4439 self.assertEqual(s.recv(1024), b'TRUE\n')
4440 # PHA method just returns true when cert is already available
4441 s.write(b'PHA')
4442 self.assertEqual(s.recv(1024), b'OK\n')
4443 s.write(b'GETCERT')
4444 cert_text = s.recv(4096).decode('us-ascii')
4445 self.assertIn('Python Software Foundation CA', cert_text)
4446
4447 def test_pha_required_nocert(self):
4448 client_context, server_context, hostname = testing_context()
4449 server_context.post_handshake_auth = True
4450 server_context.verify_mode = ssl.CERT_REQUIRED
4451 client_context.post_handshake_auth = True
4452
Victor Stinner73ea5462019-07-09 14:33:49 +02004453 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4454 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004455 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004456 server = ThreadedEchoServer(context=server_context, chatty=False)
4457 with server:
4458 with client_context.wrap_socket(socket.socket(),
4459 server_hostname=hostname) as s:
4460 s.connect((HOST, server.port))
4461 s.write(b'PHA')
4462 # receive CertificateRequest
4463 self.assertEqual(s.recv(1024), b'OK\n')
4464 # send empty Certificate + Finish
4465 s.write(b'HASCERT')
4466 # receive alert
4467 with self.assertRaisesRegex(
4468 ssl.SSLError,
4469 'tlsv13 alert certificate required'):
4470 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004471
4472 def test_pha_optional(self):
4473 if support.verbose:
4474 sys.stdout.write("\n")
4475
4476 client_context, server_context, hostname = testing_context()
4477 server_context.post_handshake_auth = True
4478 server_context.verify_mode = ssl.CERT_REQUIRED
4479 client_context.post_handshake_auth = True
4480 client_context.load_cert_chain(SIGNED_CERTFILE)
4481
4482 # check CERT_OPTIONAL
4483 server_context.verify_mode = ssl.CERT_OPTIONAL
4484 server = ThreadedEchoServer(context=server_context, chatty=False)
4485 with server:
4486 with client_context.wrap_socket(socket.socket(),
4487 server_hostname=hostname) as s:
4488 s.connect((HOST, server.port))
4489 s.write(b'HASCERT')
4490 self.assertEqual(s.recv(1024), b'FALSE\n')
4491 s.write(b'PHA')
4492 self.assertEqual(s.recv(1024), b'OK\n')
4493 s.write(b'HASCERT')
4494 self.assertEqual(s.recv(1024), b'TRUE\n')
4495
4496 def test_pha_optional_nocert(self):
4497 if support.verbose:
4498 sys.stdout.write("\n")
4499
4500 client_context, server_context, hostname = testing_context()
4501 server_context.post_handshake_auth = True
4502 server_context.verify_mode = ssl.CERT_OPTIONAL
4503 client_context.post_handshake_auth = True
4504
4505 server = ThreadedEchoServer(context=server_context, chatty=False)
4506 with server:
4507 with client_context.wrap_socket(socket.socket(),
4508 server_hostname=hostname) as s:
4509 s.connect((HOST, server.port))
4510 s.write(b'HASCERT')
4511 self.assertEqual(s.recv(1024), b'FALSE\n')
4512 s.write(b'PHA')
4513 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004514 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004515 s.write(b'HASCERT')
4516 self.assertEqual(s.recv(1024), b'FALSE\n')
4517
4518 def test_pha_no_pha_client(self):
4519 client_context, server_context, hostname = testing_context()
4520 server_context.post_handshake_auth = True
4521 server_context.verify_mode = ssl.CERT_REQUIRED
4522 client_context.load_cert_chain(SIGNED_CERTFILE)
4523
4524 server = ThreadedEchoServer(context=server_context, chatty=False)
4525 with server:
4526 with client_context.wrap_socket(socket.socket(),
4527 server_hostname=hostname) as s:
4528 s.connect((HOST, server.port))
4529 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4530 s.verify_client_post_handshake()
4531 s.write(b'PHA')
4532 self.assertIn(b'extension not received', s.recv(1024))
4533
4534 def test_pha_no_pha_server(self):
4535 # server doesn't have PHA enabled, cert is requested in handshake
4536 client_context, server_context, hostname = testing_context()
4537 server_context.verify_mode = ssl.CERT_REQUIRED
4538 client_context.post_handshake_auth = True
4539 client_context.load_cert_chain(SIGNED_CERTFILE)
4540
4541 server = ThreadedEchoServer(context=server_context, chatty=False)
4542 with server:
4543 with client_context.wrap_socket(socket.socket(),
4544 server_hostname=hostname) as s:
4545 s.connect((HOST, server.port))
4546 s.write(b'HASCERT')
4547 self.assertEqual(s.recv(1024), b'TRUE\n')
4548 # PHA doesn't fail if there is already a cert
4549 s.write(b'PHA')
4550 self.assertEqual(s.recv(1024), b'OK\n')
4551 s.write(b'HASCERT')
4552 self.assertEqual(s.recv(1024), b'TRUE\n')
4553
4554 def test_pha_not_tls13(self):
4555 # TLS 1.2
4556 client_context, server_context, hostname = testing_context()
4557 server_context.verify_mode = ssl.CERT_REQUIRED
4558 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4559 client_context.post_handshake_auth = True
4560 client_context.load_cert_chain(SIGNED_CERTFILE)
4561
4562 server = ThreadedEchoServer(context=server_context, chatty=False)
4563 with server:
4564 with client_context.wrap_socket(socket.socket(),
4565 server_hostname=hostname) as s:
4566 s.connect((HOST, server.port))
4567 # PHA fails for TLS != 1.3
4568 s.write(b'PHA')
4569 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4570
Christian Heimesf0f59302019-07-01 08:29:17 +02004571 def test_bpo37428_pha_cert_none(self):
4572 # verify that post_handshake_auth does not implicitly enable cert
4573 # validation.
4574 hostname = SIGNED_CERTFILE_HOSTNAME
4575 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4576 client_context.post_handshake_auth = True
4577 client_context.load_cert_chain(SIGNED_CERTFILE)
4578 # no cert validation and CA on client side
4579 client_context.check_hostname = False
4580 client_context.verify_mode = ssl.CERT_NONE
4581
4582 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4583 server_context.load_cert_chain(SIGNED_CERTFILE)
4584 server_context.load_verify_locations(SIGNING_CA)
4585 server_context.post_handshake_auth = True
4586 server_context.verify_mode = ssl.CERT_REQUIRED
4587
4588 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 s.write(b'HASCERT')
4594 self.assertEqual(s.recv(1024), b'FALSE\n')
4595 s.write(b'PHA')
4596 self.assertEqual(s.recv(1024), b'OK\n')
4597 s.write(b'HASCERT')
4598 self.assertEqual(s.recv(1024), b'TRUE\n')
4599 # server cert has not been validated
4600 self.assertEqual(s.getpeercert(), {})
4601
Christian Heimes9fb051f2018-09-23 08:32:31 +02004602
Christian Heimesc7f70692019-05-31 11:44:05 +02004603HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4604requires_keylog = unittest.skipUnless(
4605 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4606
4607class TestSSLDebug(unittest.TestCase):
4608
Hai Shia7f5d932020-08-04 00:41:24 +08004609 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004610 with open(fname) as f:
4611 return len(list(f))
4612
4613 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004614 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004615 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004616 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004617 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4618 self.assertEqual(ctx.keylog_filename, None)
4619
Hai Shia7f5d932020-08-04 00:41:24 +08004620 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4621 ctx.keylog_filename = os_helper.TESTFN
4622 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4623 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004624 self.assertEqual(self.keylog_lines(), 1)
4625
4626 ctx.keylog_filename = None
4627 self.assertEqual(ctx.keylog_filename, None)
4628
4629 with self.assertRaises((IsADirectoryError, PermissionError)):
4630 # Windows raises PermissionError
4631 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004632 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004633
4634 with self.assertRaises(TypeError):
4635 ctx.keylog_filename = 1
4636
4637 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004638 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004639 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004640 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004641 client_context, server_context, hostname = testing_context()
4642
Hai Shia7f5d932020-08-04 00:41:24 +08004643 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004644 server = ThreadedEchoServer(context=server_context, chatty=False)
4645 with server:
4646 with client_context.wrap_socket(socket.socket(),
4647 server_hostname=hostname) as s:
4648 s.connect((HOST, server.port))
4649 # header, 5 lines for TLS 1.3
4650 self.assertEqual(self.keylog_lines(), 6)
4651
4652 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004653 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004654 server = ThreadedEchoServer(context=server_context, chatty=False)
4655 with server:
4656 with client_context.wrap_socket(socket.socket(),
4657 server_hostname=hostname) as s:
4658 s.connect((HOST, server.port))
4659 self.assertGreaterEqual(self.keylog_lines(), 11)
4660
Hai Shia7f5d932020-08-04 00:41:24 +08004661 client_context.keylog_filename = os_helper.TESTFN
4662 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004663 server = ThreadedEchoServer(context=server_context, chatty=False)
4664 with server:
4665 with client_context.wrap_socket(socket.socket(),
4666 server_hostname=hostname) as s:
4667 s.connect((HOST, server.port))
4668 self.assertGreaterEqual(self.keylog_lines(), 21)
4669
4670 client_context.keylog_filename = None
4671 server_context.keylog_filename = None
4672
4673 @requires_keylog
4674 @unittest.skipIf(sys.flags.ignore_environment,
4675 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004676 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004677 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004678 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004679 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004680 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4681 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004682
4683 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4684 self.assertEqual(ctx.keylog_filename, None)
4685
4686 ctx = ssl.create_default_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004687 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004688
4689 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004690 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004691
4692 def test_msg_callback(self):
4693 client_context, server_context, hostname = testing_context()
4694
4695 def msg_cb(conn, direction, version, content_type, msg_type, data):
4696 pass
4697
4698 self.assertIs(client_context._msg_callback, None)
4699 client_context._msg_callback = msg_cb
4700 self.assertIs(client_context._msg_callback, msg_cb)
4701 with self.assertRaises(TypeError):
4702 client_context._msg_callback = object()
4703
4704 def test_msg_callback_tls12(self):
4705 client_context, server_context, hostname = testing_context()
4706 client_context.options |= ssl.OP_NO_TLSv1_3
4707
4708 msg = []
4709
4710 def msg_cb(conn, direction, version, content_type, msg_type, data):
4711 self.assertIsInstance(conn, ssl.SSLSocket)
4712 self.assertIsInstance(data, bytes)
4713 self.assertIn(direction, {'read', 'write'})
4714 msg.append((direction, version, content_type, msg_type))
4715
4716 client_context._msg_callback = msg_cb
4717
4718 server = ThreadedEchoServer(context=server_context, chatty=False)
4719 with server:
4720 with client_context.wrap_socket(socket.socket(),
4721 server_hostname=hostname) as s:
4722 s.connect((HOST, server.port))
4723
Christian Heimese35d1ba2019-06-03 20:40:15 +02004724 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004725 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4726 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004727 msg
4728 )
4729 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004730 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4731 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004732 msg
4733 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004734
4735
Thomas Woutersed03b412007-08-28 21:37:11 +00004736def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004737 if support.verbose:
4738 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004739 'Mac': platform.mac_ver,
4740 'Windows': platform.win32_ver,
4741 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004742 for name, func in plats.items():
4743 plat = func()
4744 if plat and plat[0]:
4745 plat = '%s %r' % (name, plat)
4746 break
4747 else:
4748 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004749 print("test_ssl: testing with %r %r" %
4750 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4751 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004752 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004753 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4754 try:
4755 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4756 except AttributeError:
4757 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004758
Antoine Pitrou152efa22010-05-16 18:19:27 +00004759 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004760 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004761 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004762 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004763 BADCERT, BADKEY, EMPTYCERT]:
4764 if not os.path.exists(filename):
4765 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004766
Martin Panter3840b2a2016-03-27 01:53:46 +00004767 tests = [
4768 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004769 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004770 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004771 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004772
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004773 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004774 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004775
Hai Shie80697d2020-05-28 06:10:27 +08004776 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004777 try:
4778 support.run_unittest(*tests)
4779 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004780 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004781
4782if __name__ == "__main__":
4783 test_main()