blob: 1710dda4389a04dd9a191f93a7420661eae19c9e [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
pxinwr98a54172020-12-09 07:20:19 +0800394 @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
Christian Heimesf77b4b22013-08-21 13:26:05 +0200395 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)
Chris Burre0b4aa02021-03-18 09:24:01 +01001308 ctx.verify_flags = ssl.VERIFY_ALLOW_PROXY_CERTS
1309 self.assertEqual(ctx.verify_flags, ssl.VERIFY_ALLOW_PROXY_CERTS)
Christian Heimes22587792013-11-21 23:56:13 +01001310 # supports any value
1311 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
1312 self.assertEqual(ctx.verify_flags,
1313 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
1314 with self.assertRaises(TypeError):
1315 ctx.verify_flags = None
1316
Antoine Pitrou152efa22010-05-16 18:19:27 +00001317 def test_load_cert_chain(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001318 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001319 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -05001320 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001321 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
1322 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001323 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001324 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001325 self.assertEqual(cm.exception.errno, errno.ENOENT)
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(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001328 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001329 ctx.load_cert_chain(EMPTYCERT)
1330 # Separate key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001331 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001332 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
1333 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
1334 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
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(ONLYCERT)
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(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001339 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001340 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
1341 # Mismatching key and cert
Christian Heimesa170fa12017-09-15 20:27:30 +02001342 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001343 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +00001344 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +02001345 # Password protected key and cert
1346 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
1347 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
1348 ctx.load_cert_chain(CERTFILE_PROTECTED,
1349 password=bytearray(KEY_PASSWORD.encode()))
1350 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
1351 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
1352 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
1353 bytearray(KEY_PASSWORD.encode()))
1354 with self.assertRaisesRegex(TypeError, "should be a string"):
1355 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
1356 with self.assertRaises(ssl.SSLError):
1357 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
1358 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1359 # openssl has a fixed limit on the password buffer.
1360 # PEM_BUFSIZE is generally set to 1kb.
1361 # Return a string larger than this.
1362 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
1363 # Password callback
1364 def getpass_unicode():
1365 return KEY_PASSWORD
1366 def getpass_bytes():
1367 return KEY_PASSWORD.encode()
1368 def getpass_bytearray():
1369 return bytearray(KEY_PASSWORD.encode())
1370 def getpass_badpass():
1371 return "badpass"
1372 def getpass_huge():
1373 return b'a' * (1024 * 1024)
1374 def getpass_bad_type():
1375 return 9
1376 def getpass_exception():
1377 raise Exception('getpass error')
1378 class GetPassCallable:
1379 def __call__(self):
1380 return KEY_PASSWORD
1381 def getpass(self):
1382 return KEY_PASSWORD
1383 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1384 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1385 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1386 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1387 ctx.load_cert_chain(CERTFILE_PROTECTED,
1388 password=GetPassCallable().getpass)
1389 with self.assertRaises(ssl.SSLError):
1390 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1391 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1392 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1393 with self.assertRaisesRegex(TypeError, "must return a string"):
1394 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1395 with self.assertRaisesRegex(Exception, "getpass error"):
1396 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1397 # Make sure the password function isn't called if it isn't needed
1398 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001399
1400 def test_load_verify_locations(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001401 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001402 ctx.load_verify_locations(CERTFILE)
1403 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1404 ctx.load_verify_locations(BYTES_CERTFILE)
1405 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1406 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001407 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001408 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001409 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001410 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001411 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001412 ctx.load_verify_locations(BADCERT)
1413 ctx.load_verify_locations(CERTFILE, CAPATH)
1414 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1415
Victor Stinner80f75e62011-01-29 11:31:20 +00001416 # Issue #10989: crash if the second argument type is invalid
1417 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1418
Christian Heimesefff7062013-11-21 03:35:02 +01001419 def test_load_verify_cadata(self):
1420 # test cadata
1421 with open(CAFILE_CACERT) as f:
1422 cacert_pem = f.read()
1423 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1424 with open(CAFILE_NEURONIO) as f:
1425 neuronio_pem = f.read()
1426 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1427
1428 # test PEM
Christian Heimesa170fa12017-09-15 20:27:30 +02001429 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001430 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1431 ctx.load_verify_locations(cadata=cacert_pem)
1432 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1433 ctx.load_verify_locations(cadata=neuronio_pem)
1434 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1435 # cert already in hash table
1436 ctx.load_verify_locations(cadata=neuronio_pem)
1437 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1438
1439 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001440 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001441 combined = "\n".join((cacert_pem, neuronio_pem))
1442 ctx.load_verify_locations(cadata=combined)
1443 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1444
1445 # with junk around the certs
Christian Heimesa170fa12017-09-15 20:27:30 +02001446 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001447 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1448 neuronio_pem, "tail"]
1449 ctx.load_verify_locations(cadata="\n".join(combined))
1450 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1451
1452 # test DER
Christian Heimesa170fa12017-09-15 20:27:30 +02001453 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001454 ctx.load_verify_locations(cadata=cacert_der)
1455 ctx.load_verify_locations(cadata=neuronio_der)
1456 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1457 # cert already in hash table
1458 ctx.load_verify_locations(cadata=cacert_der)
1459 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1460
1461 # combined
Christian Heimesa170fa12017-09-15 20:27:30 +02001462 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001463 combined = b"".join((cacert_der, neuronio_der))
1464 ctx.load_verify_locations(cadata=combined)
1465 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1466
1467 # error cases
Christian Heimesa170fa12017-09-15 20:27:30 +02001468 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimesefff7062013-11-21 03:35:02 +01001469 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1470
1471 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1472 ctx.load_verify_locations(cadata="broken")
1473 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1474 ctx.load_verify_locations(cadata=b"broken")
1475
1476
Paul Monsonf3550692019-06-19 13:09:54 -07001477 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001478 def test_load_dh_params(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001479 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001480 ctx.load_dh_params(DHFILE)
1481 if os.name != 'nt':
1482 ctx.load_dh_params(BYTES_DHFILE)
1483 self.assertRaises(TypeError, ctx.load_dh_params)
1484 self.assertRaises(TypeError, ctx.load_dh_params, None)
1485 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001486 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001487 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001488 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001489 ctx.load_dh_params(CERTFILE)
1490
Antoine Pitroub0182c82010-10-12 20:09:02 +00001491 def test_session_stats(self):
1492 for proto in PROTOCOLS:
1493 ctx = ssl.SSLContext(proto)
1494 self.assertEqual(ctx.session_stats(), {
1495 'number': 0,
1496 'connect': 0,
1497 'connect_good': 0,
1498 'connect_renegotiate': 0,
1499 'accept': 0,
1500 'accept_good': 0,
1501 'accept_renegotiate': 0,
1502 'hits': 0,
1503 'misses': 0,
1504 'timeouts': 0,
1505 'cache_full': 0,
1506 })
1507
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001508 def test_set_default_verify_paths(self):
1509 # There's not much we can do to test that it acts as expected,
1510 # so just check it doesn't crash or raise an exception.
Christian Heimesa170fa12017-09-15 20:27:30 +02001511 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001512 ctx.set_default_verify_paths()
1513
Antoine Pitrou501da612011-12-21 09:27:41 +01001514 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001515 def test_set_ecdh_curve(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001516 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001517 ctx.set_ecdh_curve("prime256v1")
1518 ctx.set_ecdh_curve(b"prime256v1")
1519 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1520 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1521 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1522 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1523
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001524 @needs_sni
1525 def test_sni_callback(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001526 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001527
1528 # set_servername_callback expects a callable, or None
1529 self.assertRaises(TypeError, ctx.set_servername_callback)
1530 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1531 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1532 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1533
1534 def dummycallback(sock, servername, ctx):
1535 pass
1536 ctx.set_servername_callback(None)
1537 ctx.set_servername_callback(dummycallback)
1538
1539 @needs_sni
1540 def test_sni_callback_refcycle(self):
1541 # Reference cycles through the servername callback are detected
1542 # and cleared.
Christian Heimesa170fa12017-09-15 20:27:30 +02001543 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001544 def dummycallback(sock, servername, ctx, cycle=ctx):
1545 pass
1546 ctx.set_servername_callback(dummycallback)
1547 wr = weakref.ref(ctx)
1548 del ctx, dummycallback
1549 gc.collect()
1550 self.assertIs(wr(), None)
1551
Christian Heimes9a5395a2013-06-17 15:44:12 +02001552 def test_cert_store_stats(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001553 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001554 self.assertEqual(ctx.cert_store_stats(),
1555 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1556 ctx.load_cert_chain(CERTFILE)
1557 self.assertEqual(ctx.cert_store_stats(),
1558 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1559 ctx.load_verify_locations(CERTFILE)
1560 self.assertEqual(ctx.cert_store_stats(),
1561 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001562 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001563 self.assertEqual(ctx.cert_store_stats(),
1564 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1565
1566 def test_get_ca_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001567 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001568 self.assertEqual(ctx.get_ca_certs(), [])
1569 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1570 ctx.load_verify_locations(CERTFILE)
1571 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001572 # but CAFILE_CACERT is a CA cert
1573 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001574 self.assertEqual(ctx.get_ca_certs(),
1575 [{'issuer': ((('organizationName', 'Root CA'),),
1576 (('organizationalUnitName', 'http://www.cacert.org'),),
1577 (('commonName', 'CA Cert Signing Authority'),),
1578 (('emailAddress', 'support@cacert.org'),)),
1579 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1580 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1581 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001582 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001583 'subject': ((('organizationName', 'Root CA'),),
1584 (('organizationalUnitName', 'http://www.cacert.org'),),
1585 (('commonName', 'CA Cert Signing Authority'),),
1586 (('emailAddress', 'support@cacert.org'),)),
1587 'version': 3}])
1588
Martin Panterb55f8b72016-01-14 12:53:56 +00001589 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001590 pem = f.read()
1591 der = ssl.PEM_cert_to_DER_cert(pem)
1592 self.assertEqual(ctx.get_ca_certs(True), [der])
1593
Christian Heimes72d28502013-11-23 13:56:58 +01001594 def test_load_default_certs(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001595 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001596 ctx.load_default_certs()
1597
Christian Heimesa170fa12017-09-15 20:27:30 +02001598 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001599 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1600 ctx.load_default_certs()
1601
Christian Heimesa170fa12017-09-15 20:27:30 +02001602 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001603 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1604
Christian Heimesa170fa12017-09-15 20:27:30 +02001605 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes72d28502013-11-23 13:56:58 +01001606 self.assertRaises(TypeError, ctx.load_default_certs, None)
1607 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1608
Benjamin Peterson91244e02014-10-03 18:17:15 -04001609 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimes598894f2016-09-05 23:19:05 +02001610 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001611 def test_load_default_certs_env(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001612 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001613 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001614 env["SSL_CERT_DIR"] = CAPATH
1615 env["SSL_CERT_FILE"] = CERTFILE
1616 ctx.load_default_certs()
1617 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1618
Benjamin Peterson91244e02014-10-03 18:17:15 -04001619 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Steve Dower68d663c2017-07-17 11:15:48 +02001620 @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
Benjamin Peterson91244e02014-10-03 18:17:15 -04001621 def test_load_default_certs_env_windows(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001622 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Benjamin Peterson91244e02014-10-03 18:17:15 -04001623 ctx.load_default_certs()
1624 stats = ctx.cert_store_stats()
1625
Christian Heimesa170fa12017-09-15 20:27:30 +02001626 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Hai Shia7f5d932020-08-04 00:41:24 +08001627 with os_helper.EnvironmentVarGuard() as env:
Benjamin Peterson91244e02014-10-03 18:17:15 -04001628 env["SSL_CERT_DIR"] = CAPATH
1629 env["SSL_CERT_FILE"] = CERTFILE
1630 ctx.load_default_certs()
1631 stats["x509"] += 1
1632 self.assertEqual(ctx.cert_store_stats(), stats)
1633
Christian Heimes358cfd42016-09-10 22:43:48 +02001634 def _assert_context_options(self, ctx):
1635 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1636 if OP_NO_COMPRESSION != 0:
1637 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1638 OP_NO_COMPRESSION)
1639 if OP_SINGLE_DH_USE != 0:
1640 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1641 OP_SINGLE_DH_USE)
1642 if OP_SINGLE_ECDH_USE != 0:
1643 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1644 OP_SINGLE_ECDH_USE)
1645 if OP_CIPHER_SERVER_PREFERENCE != 0:
1646 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1647 OP_CIPHER_SERVER_PREFERENCE)
1648
Christian Heimes4c05b472013-11-23 15:58:30 +01001649 def test_create_default_context(self):
1650 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001651
Christian Heimesa170fa12017-09-15 20:27:30 +02001652 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001653 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001654 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001655 self._assert_context_options(ctx)
1656
Christian Heimes4c05b472013-11-23 15:58:30 +01001657 with open(SIGNING_CA) as f:
1658 cadata = f.read()
1659 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1660 cadata=cadata)
Christian Heimesa170fa12017-09-15 20:27:30 +02001661 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001662 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001663 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001664
1665 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001666 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes4c05b472013-11-23 15:58:30 +01001667 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001668 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001669
Christian Heimes67986f92013-11-23 22:43:47 +01001670 def test__create_stdlib_context(self):
1671 ctx = ssl._create_stdlib_context()
Christian Heimesa170fa12017-09-15 20:27:30 +02001672 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001673 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001674 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001675 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001676
1677 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1678 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1679 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001680 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001681
1682 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001683 cert_reqs=ssl.CERT_REQUIRED,
1684 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001685 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1686 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001687 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001688 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001689
1690 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
Christian Heimesa170fa12017-09-15 20:27:30 +02001691 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Christian Heimes67986f92013-11-23 22:43:47 +01001692 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001693 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001694
Christian Heimes1aa9a752013-12-02 02:41:19 +01001695 def test_check_hostname(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02001696 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001697 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001698 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001699
Christian Heimese82c0342017-09-15 20:29:57 +02001700 # Auto set CERT_REQUIRED
1701 ctx.check_hostname = True
1702 self.assertTrue(ctx.check_hostname)
1703 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1704 ctx.check_hostname = False
Christian Heimes1aa9a752013-12-02 02:41:19 +01001705 ctx.verify_mode = ssl.CERT_REQUIRED
1706 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001707 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001708
Christian Heimese82c0342017-09-15 20:29:57 +02001709 # Changing verify_mode does not affect check_hostname
1710 ctx.check_hostname = False
1711 ctx.verify_mode = ssl.CERT_NONE
1712 ctx.check_hostname = False
1713 self.assertFalse(ctx.check_hostname)
1714 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1715 # Auto set
Christian Heimes1aa9a752013-12-02 02:41:19 +01001716 ctx.check_hostname = True
1717 self.assertTrue(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001718 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1719
1720 ctx.check_hostname = False
1721 ctx.verify_mode = ssl.CERT_OPTIONAL
1722 ctx.check_hostname = False
1723 self.assertFalse(ctx.check_hostname)
1724 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
1725 # keep CERT_OPTIONAL
1726 ctx.check_hostname = True
1727 self.assertTrue(ctx.check_hostname)
1728 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001729
1730 # Cannot set CERT_NONE with check_hostname enabled
1731 with self.assertRaises(ValueError):
1732 ctx.verify_mode = ssl.CERT_NONE
1733 ctx.check_hostname = False
1734 self.assertFalse(ctx.check_hostname)
Christian Heimese82c0342017-09-15 20:29:57 +02001735 ctx.verify_mode = ssl.CERT_NONE
1736 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001737
Christian Heimes5fe668c2016-09-12 00:01:11 +02001738 def test_context_client_server(self):
1739 # PROTOCOL_TLS_CLIENT has sane defaults
1740 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1741 self.assertTrue(ctx.check_hostname)
1742 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1743
1744 # PROTOCOL_TLS_SERVER has different but also sane defaults
1745 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1746 self.assertFalse(ctx.check_hostname)
1747 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1748
Christian Heimes4df60f12017-09-15 20:26:05 +02001749 def test_context_custom_class(self):
1750 class MySSLSocket(ssl.SSLSocket):
1751 pass
1752
1753 class MySSLObject(ssl.SSLObject):
1754 pass
1755
1756 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1757 ctx.sslsocket_class = MySSLSocket
1758 ctx.sslobject_class = MySSLObject
1759
1760 with ctx.wrap_socket(socket.socket(), server_side=True) as sock:
1761 self.assertIsInstance(sock, MySSLSocket)
1762 obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
1763 self.assertIsInstance(obj, MySSLObject)
1764
Christian Heimes78c7d522019-06-03 21:00:10 +02001765 @unittest.skipUnless(IS_OPENSSL_1_1_1, "Test requires OpenSSL 1.1.1")
1766 def test_num_tickest(self):
1767 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1768 self.assertEqual(ctx.num_tickets, 2)
1769 ctx.num_tickets = 1
1770 self.assertEqual(ctx.num_tickets, 1)
1771 ctx.num_tickets = 0
1772 self.assertEqual(ctx.num_tickets, 0)
1773 with self.assertRaises(ValueError):
1774 ctx.num_tickets = -1
1775 with self.assertRaises(TypeError):
1776 ctx.num_tickets = None
1777
1778 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1779 self.assertEqual(ctx.num_tickets, 2)
1780 with self.assertRaises(ValueError):
1781 ctx.num_tickets = 1
1782
Antoine Pitrou152efa22010-05-16 18:19:27 +00001783
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001784class SSLErrorTests(unittest.TestCase):
1785
1786 def test_str(self):
1787 # The str() of a SSLError doesn't include the errno
1788 e = ssl.SSLError(1, "foo")
1789 self.assertEqual(str(e), "foo")
1790 self.assertEqual(e.errno, 1)
1791 # Same for a subclass
1792 e = ssl.SSLZeroReturnError(1, "foo")
1793 self.assertEqual(str(e), "foo")
1794 self.assertEqual(e.errno, 1)
1795
Paul Monsonf3550692019-06-19 13:09:54 -07001796 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001797 def test_lib_reason(self):
1798 # Test the library and reason attributes
Christian Heimesa170fa12017-09-15 20:27:30 +02001799 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001800 with self.assertRaises(ssl.SSLError) as cm:
1801 ctx.load_dh_params(CERTFILE)
1802 self.assertEqual(cm.exception.library, 'PEM')
1803 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1804 s = str(cm.exception)
1805 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1806
1807 def test_subclass(self):
1808 # Check that the appropriate SSLError subclass is raised
1809 # (this only tests one of them)
Christian Heimesa170fa12017-09-15 20:27:30 +02001810 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1811 ctx.check_hostname = False
1812 ctx.verify_mode = ssl.CERT_NONE
Giampaolo Rodolaeb7e29f2019-04-09 00:34:02 +02001813 with socket.create_server(("127.0.0.1", 0)) as s:
1814 c = socket.create_connection(s.getsockname())
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001815 c.setblocking(False)
1816 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001817 with self.assertRaises(ssl.SSLWantReadError) as cm:
1818 c.do_handshake()
1819 s = str(cm.exception)
1820 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1821 # For compatibility
1822 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1823
1824
Christian Heimes61d478c2018-01-27 15:51:38 +01001825 def test_bad_server_hostname(self):
1826 ctx = ssl.create_default_context()
1827 with self.assertRaises(ValueError):
1828 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1829 server_hostname="")
1830 with self.assertRaises(ValueError):
1831 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1832 server_hostname=".example.org")
Christian Heimesd02ac252018-03-25 12:36:13 +02001833 with self.assertRaises(TypeError):
1834 ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
1835 server_hostname="example.org\x00evil.com")
Christian Heimes61d478c2018-01-27 15:51:38 +01001836
1837
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001838class MemoryBIOTests(unittest.TestCase):
1839
1840 def test_read_write(self):
1841 bio = ssl.MemoryBIO()
1842 bio.write(b'foo')
1843 self.assertEqual(bio.read(), b'foo')
1844 self.assertEqual(bio.read(), b'')
1845 bio.write(b'foo')
1846 bio.write(b'bar')
1847 self.assertEqual(bio.read(), b'foobar')
1848 self.assertEqual(bio.read(), b'')
1849 bio.write(b'baz')
1850 self.assertEqual(bio.read(2), b'ba')
1851 self.assertEqual(bio.read(1), b'z')
1852 self.assertEqual(bio.read(1), b'')
1853
1854 def test_eof(self):
1855 bio = ssl.MemoryBIO()
1856 self.assertFalse(bio.eof)
1857 self.assertEqual(bio.read(), b'')
1858 self.assertFalse(bio.eof)
1859 bio.write(b'foo')
1860 self.assertFalse(bio.eof)
1861 bio.write_eof()
1862 self.assertFalse(bio.eof)
1863 self.assertEqual(bio.read(2), b'fo')
1864 self.assertFalse(bio.eof)
1865 self.assertEqual(bio.read(1), b'o')
1866 self.assertTrue(bio.eof)
1867 self.assertEqual(bio.read(), b'')
1868 self.assertTrue(bio.eof)
1869
1870 def test_pending(self):
1871 bio = ssl.MemoryBIO()
1872 self.assertEqual(bio.pending, 0)
1873 bio.write(b'foo')
1874 self.assertEqual(bio.pending, 3)
1875 for i in range(3):
1876 bio.read(1)
1877 self.assertEqual(bio.pending, 3-i-1)
1878 for i in range(3):
1879 bio.write(b'x')
1880 self.assertEqual(bio.pending, i+1)
1881 bio.read()
1882 self.assertEqual(bio.pending, 0)
1883
1884 def test_buffer_types(self):
1885 bio = ssl.MemoryBIO()
1886 bio.write(b'foo')
1887 self.assertEqual(bio.read(), b'foo')
1888 bio.write(bytearray(b'bar'))
1889 self.assertEqual(bio.read(), b'bar')
1890 bio.write(memoryview(b'baz'))
1891 self.assertEqual(bio.read(), b'baz')
1892
1893 def test_error_types(self):
1894 bio = ssl.MemoryBIO()
1895 self.assertRaises(TypeError, bio.write, 'foo')
1896 self.assertRaises(TypeError, bio.write, None)
1897 self.assertRaises(TypeError, bio.write, True)
1898 self.assertRaises(TypeError, bio.write, 1)
1899
1900
Christian Heimes9d50ab52018-02-27 10:17:30 +01001901class SSLObjectTests(unittest.TestCase):
1902 def test_private_init(self):
1903 bio = ssl.MemoryBIO()
1904 with self.assertRaisesRegex(TypeError, "public constructor"):
1905 ssl.SSLObject(bio, bio)
1906
Nathaniel J. Smithc0da5822018-09-21 21:44:12 -07001907 def test_unwrap(self):
1908 client_ctx, server_ctx, hostname = testing_context()
1909 c_in = ssl.MemoryBIO()
1910 c_out = ssl.MemoryBIO()
1911 s_in = ssl.MemoryBIO()
1912 s_out = ssl.MemoryBIO()
1913 client = client_ctx.wrap_bio(c_in, c_out, server_hostname=hostname)
1914 server = server_ctx.wrap_bio(s_in, s_out, server_side=True)
1915
1916 # Loop on the handshake for a bit to get it settled
1917 for _ in range(5):
1918 try:
1919 client.do_handshake()
1920 except ssl.SSLWantReadError:
1921 pass
1922 if c_out.pending:
1923 s_in.write(c_out.read())
1924 try:
1925 server.do_handshake()
1926 except ssl.SSLWantReadError:
1927 pass
1928 if s_out.pending:
1929 c_in.write(s_out.read())
1930 # Now the handshakes should be complete (don't raise WantReadError)
1931 client.do_handshake()
1932 server.do_handshake()
1933
1934 # Now if we unwrap one side unilaterally, it should send close-notify
1935 # and raise WantReadError:
1936 with self.assertRaises(ssl.SSLWantReadError):
1937 client.unwrap()
1938
1939 # But server.unwrap() does not raise, because it reads the client's
1940 # close-notify:
1941 s_in.write(c_out.read())
1942 server.unwrap()
1943
1944 # And now that the client gets the server's close-notify, it doesn't
1945 # raise either.
1946 c_in.write(s_out.read())
1947 client.unwrap()
Christian Heimes9d50ab52018-02-27 10:17:30 +01001948
Martin Panter3840b2a2016-03-27 01:53:46 +00001949class SimpleBackgroundTests(unittest.TestCase):
Martin Panter3840b2a2016-03-27 01:53:46 +00001950 """Tests that connect to a simple server running in the background"""
1951
1952 def setUp(self):
1953 server = ThreadedEchoServer(SIGNED_CERTFILE)
1954 self.server_addr = (HOST, server.port)
1955 server.__enter__()
1956 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001957
Antoine Pitrou480a1242010-04-28 21:37:09 +00001958 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001959 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001960 cert_reqs=ssl.CERT_NONE) as s:
1961 s.connect(self.server_addr)
1962 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001963 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001964
Martin Panter3840b2a2016-03-27 01:53:46 +00001965 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001966 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001967 cert_reqs=ssl.CERT_REQUIRED,
1968 ca_certs=SIGNING_CA) as s:
1969 s.connect(self.server_addr)
1970 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001971 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001972
Martin Panter3840b2a2016-03-27 01:53:46 +00001973 def test_connect_fail(self):
1974 # This should fail because we have no verification certs. Connection
1975 # failure crashes ThreadedEchoServer, so run this in an independent
1976 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001977 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001978 cert_reqs=ssl.CERT_REQUIRED)
1979 self.addCleanup(s.close)
1980 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1981 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001982
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001983 def test_connect_ex(self):
1984 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02001985 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001986 cert_reqs=ssl.CERT_REQUIRED,
1987 ca_certs=SIGNING_CA)
1988 self.addCleanup(s.close)
1989 self.assertEqual(0, s.connect_ex(self.server_addr))
1990 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001991
1992 def test_non_blocking_connect_ex(self):
1993 # Issue #11326: non-blocking connect_ex() should allow handshake
1994 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02001995 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001996 cert_reqs=ssl.CERT_REQUIRED,
1997 ca_certs=SIGNING_CA,
1998 do_handshake_on_connect=False)
1999 self.addCleanup(s.close)
2000 s.setblocking(False)
2001 rc = s.connect_ex(self.server_addr)
2002 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
2003 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
2004 # Wait for connect to finish
2005 select.select([], [s], [], 5.0)
2006 # Non-blocking handshake
2007 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002008 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00002009 s.do_handshake()
2010 break
2011 except ssl.SSLWantReadError:
2012 select.select([s], [], [], 5.0)
2013 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00002014 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002015 # SSL established
2016 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01002017
Antoine Pitrou152efa22010-05-16 18:19:27 +00002018 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002019 # Same as test_connect, but with a separately created context
Christian Heimesa170fa12017-09-15 20:27:30 +02002020 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002021 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2022 s.connect(self.server_addr)
2023 self.assertEqual({}, s.getpeercert())
2024 # Same with a server hostname
2025 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2026 server_hostname="dummy") as s:
2027 s.connect(self.server_addr)
2028 ctx.verify_mode = ssl.CERT_REQUIRED
2029 # This should succeed because we specify the root cert
2030 ctx.load_verify_locations(SIGNING_CA)
2031 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2032 s.connect(self.server_addr)
2033 cert = s.getpeercert()
2034 self.assertTrue(cert)
2035
2036 def test_connect_with_context_fail(self):
2037 # This should fail because we have no verification certs. Connection
2038 # failure crashes ThreadedEchoServer, so run this in an independent
2039 # test method.
Christian Heimesa170fa12017-09-15 20:27:30 +02002040 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002041 ctx.verify_mode = ssl.CERT_REQUIRED
2042 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
2043 self.addCleanup(s.close)
2044 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
2045 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00002046
2047 def test_connect_capath(self):
2048 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00002049 # NOTE: the subject hashing algorithm has been changed between
2050 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
2051 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00002052 # filename) for this test to be portable across OpenSSL releases.
Christian Heimesa170fa12017-09-15 20:27:30 +02002053 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002054 ctx.verify_mode = ssl.CERT_REQUIRED
2055 ctx.load_verify_locations(capath=CAPATH)
2056 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2057 s.connect(self.server_addr)
2058 cert = s.getpeercert()
2059 self.assertTrue(cert)
Christian Heimes529525f2018-05-23 22:24:45 +02002060
Martin Panter3840b2a2016-03-27 01:53:46 +00002061 # Same with a bytes `capath` argument
Christian Heimesa170fa12017-09-15 20:27:30 +02002062 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002063 ctx.verify_mode = ssl.CERT_REQUIRED
2064 ctx.load_verify_locations(capath=BYTES_CAPATH)
2065 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2066 s.connect(self.server_addr)
2067 cert = s.getpeercert()
2068 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002069
Christian Heimesefff7062013-11-21 03:35:02 +01002070 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002071 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01002072 pem = f.read()
2073 der = ssl.PEM_cert_to_DER_cert(pem)
Christian Heimesa170fa12017-09-15 20:27:30 +02002074 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002075 ctx.verify_mode = ssl.CERT_REQUIRED
2076 ctx.load_verify_locations(cadata=pem)
2077 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2078 s.connect(self.server_addr)
2079 cert = s.getpeercert()
2080 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002081
Martin Panter3840b2a2016-03-27 01:53:46 +00002082 # same with DER
Christian Heimesa170fa12017-09-15 20:27:30 +02002083 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002084 ctx.verify_mode = ssl.CERT_REQUIRED
2085 ctx.load_verify_locations(cadata=der)
2086 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
2087 s.connect(self.server_addr)
2088 cert = s.getpeercert()
2089 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01002090
Antoine Pitroue3220242010-04-24 11:13:53 +00002091 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
2092 def test_makefile_close(self):
2093 # Issue #5238: creating a file-like object with makefile() shouldn't
2094 # delay closing the underlying "real socket" (here tested with its
2095 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02002096 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00002097 ss.connect(self.server_addr)
2098 fd = ss.fileno()
2099 f = ss.makefile()
2100 f.close()
2101 # The fd is still open
2102 os.read(fd, 0)
2103 # Closing the SSL socket should close the fd too
2104 ss.close()
2105 gc.collect()
2106 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00002107 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00002108 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00002109
Antoine Pitrou480a1242010-04-28 21:37:09 +00002110 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002111 s = socket.socket(socket.AF_INET)
2112 s.connect(self.server_addr)
2113 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02002114 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00002115 cert_reqs=ssl.CERT_NONE,
2116 do_handshake_on_connect=False)
2117 self.addCleanup(s.close)
2118 count = 0
2119 while True:
2120 try:
2121 count += 1
2122 s.do_handshake()
2123 break
2124 except ssl.SSLWantReadError:
2125 select.select([s], [], [])
2126 except ssl.SSLWantWriteError:
2127 select.select([], [s], [])
2128 if support.verbose:
2129 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002130
Antoine Pitrou480a1242010-04-28 21:37:09 +00002131 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00002132 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02002133
Martin Panter3840b2a2016-03-27 01:53:46 +00002134 def test_get_server_certificate_fail(self):
2135 # Connection failure crashes ThreadedEchoServer, so run this in an
2136 # independent test method
2137 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002138
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00002139 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02002140 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002141 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
2142 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02002143 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002144 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
2145 s.connect(self.server_addr)
2146 # Error checking can happen at instantiation or when connecting
2147 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
2148 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02002149 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00002150 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
2151 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00002152
Christian Heimes9a5395a2013-06-17 15:44:12 +02002153 def test_get_ca_certs_capath(self):
2154 # capath certs are loaded on request
Christian Heimesa170fa12017-09-15 20:27:30 +02002155 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Martin Panter3840b2a2016-03-27 01:53:46 +00002156 ctx.load_verify_locations(capath=CAPATH)
2157 self.assertEqual(ctx.get_ca_certs(), [])
Christian Heimesa170fa12017-09-15 20:27:30 +02002158 with ctx.wrap_socket(socket.socket(socket.AF_INET),
2159 server_hostname='localhost') as s:
Martin Panter3840b2a2016-03-27 01:53:46 +00002160 s.connect(self.server_addr)
2161 cert = s.getpeercert()
2162 self.assertTrue(cert)
2163 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02002164
Christian Heimes575596e2013-12-15 21:49:17 +01002165 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01002166 def test_context_setget(self):
2167 # Check that the context of a connected socket can be replaced.
Christian Heimesa170fa12017-09-15 20:27:30 +02002168 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2169 ctx1.load_verify_locations(capath=CAPATH)
2170 ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2171 ctx2.load_verify_locations(capath=CAPATH)
Martin Panter3840b2a2016-03-27 01:53:46 +00002172 s = socket.socket(socket.AF_INET)
Christian Heimesa170fa12017-09-15 20:27:30 +02002173 with ctx1.wrap_socket(s, server_hostname='localhost') as ss:
Martin Panter3840b2a2016-03-27 01:53:46 +00002174 ss.connect(self.server_addr)
2175 self.assertIs(ss.context, ctx1)
2176 self.assertIs(ss._sslobj.context, ctx1)
2177 ss.context = ctx2
2178 self.assertIs(ss.context, ctx2)
2179 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002180
2181 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
2182 # A simple IO loop. Call func(*args) depending on the error we get
2183 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
Victor Stinner0d63bac2019-12-11 11:30:03 +01002184 timeout = kwargs.get('timeout', support.SHORT_TIMEOUT)
Victor Stinner50a72af2017-09-11 09:34:24 -07002185 deadline = time.monotonic() + timeout
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002186 count = 0
2187 while True:
Victor Stinner50a72af2017-09-11 09:34:24 -07002188 if time.monotonic() > deadline:
2189 self.fail("timeout")
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002190 errno = None
2191 count += 1
2192 try:
2193 ret = func(*args)
2194 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002195 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00002196 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002197 raise
2198 errno = e.errno
2199 # Get any data from the outgoing BIO irrespective of any error, and
2200 # send it to the socket.
2201 buf = outgoing.read()
2202 sock.sendall(buf)
2203 # If there's no error, we're done. For WANT_READ, we need to get
2204 # data from the socket and put it in the incoming BIO.
2205 if errno is None:
2206 break
2207 elif errno == ssl.SSL_ERROR_WANT_READ:
2208 buf = sock.recv(32768)
2209 if buf:
2210 incoming.write(buf)
2211 else:
2212 incoming.write_eof()
2213 if support.verbose:
2214 sys.stdout.write("Needed %d calls to complete %s().\n"
2215 % (count, func.__name__))
2216 return ret
2217
Martin Panter3840b2a2016-03-27 01:53:46 +00002218 def test_bio_handshake(self):
2219 sock = socket.socket(socket.AF_INET)
2220 self.addCleanup(sock.close)
2221 sock.connect(self.server_addr)
2222 incoming = ssl.MemoryBIO()
2223 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002224 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2225 self.assertTrue(ctx.check_hostname)
2226 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Martin Panter3840b2a2016-03-27 01:53:46 +00002227 ctx.load_verify_locations(SIGNING_CA)
Christian Heimesa170fa12017-09-15 20:27:30 +02002228 sslobj = ctx.wrap_bio(incoming, outgoing, False,
2229 SIGNED_CERTFILE_HOSTNAME)
Martin Panter3840b2a2016-03-27 01:53:46 +00002230 self.assertIs(sslobj._sslobj.owner, sslobj)
2231 self.assertIsNone(sslobj.cipher())
Christian Heimes68771112017-09-05 21:55:40 -07002232 self.assertIsNone(sslobj.version())
Christian Heimes01113fa2016-09-05 23:23:24 +02002233 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00002234 self.assertRaises(ValueError, sslobj.getpeercert)
2235 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2236 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
2237 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2238 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02002239 self.assertIsNotNone(sslobj.shared_ciphers())
Christian Heimes68771112017-09-05 21:55:40 -07002240 self.assertIsNotNone(sslobj.version())
Martin Panter3840b2a2016-03-27 01:53:46 +00002241 self.assertTrue(sslobj.getpeercert())
2242 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
2243 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
2244 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002245 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00002246 except ssl.SSLSyscallError:
2247 # If the server shuts down the TCP connection without sending a
2248 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
2249 pass
2250 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
2251
2252 def test_bio_read_write_data(self):
2253 sock = socket.socket(socket.AF_INET)
2254 self.addCleanup(sock.close)
2255 sock.connect(self.server_addr)
2256 incoming = ssl.MemoryBIO()
2257 outgoing = ssl.MemoryBIO()
Christian Heimesa170fa12017-09-15 20:27:30 +02002258 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
Martin Panter3840b2a2016-03-27 01:53:46 +00002259 ctx.verify_mode = ssl.CERT_NONE
2260 sslobj = ctx.wrap_bio(incoming, outgoing, False)
2261 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
2262 req = b'FOO\n'
2263 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
2264 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
2265 self.assertEqual(buf, b'foo\n')
2266 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02002267
2268
Martin Panter3840b2a2016-03-27 01:53:46 +00002269class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002270
Martin Panter3840b2a2016-03-27 01:53:46 +00002271 def test_timeout_connect_ex(self):
2272 # Issue #12065: on a timeout, connect_ex() should return the original
2273 # errno (mimicking the behaviour of non-SSL sockets).
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002274 with socket_helper.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02002275 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00002276 cert_reqs=ssl.CERT_REQUIRED,
2277 do_handshake_on_connect=False)
2278 self.addCleanup(s.close)
2279 s.settimeout(0.0000001)
2280 rc = s.connect_ex((REMOTE_HOST, 443))
2281 if rc == 0:
2282 self.skipTest("REMOTE_HOST responded too quickly")
2283 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
2284
Serhiy Storchaka16994912020-04-25 10:06:29 +03002285 @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'Needs IPv6')
Martin Panter3840b2a2016-03-27 01:53:46 +00002286 def test_get_server_certificate_ipv6(self):
Serhiy Storchakabfb1cf42020-04-29 10:36:20 +03002287 with socket_helper.transient_internet('ipv6.google.com'):
Martin Panter3840b2a2016-03-27 01:53:46 +00002288 _test_get_server_certificate(self, 'ipv6.google.com', 443)
2289 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
2290
Martin Panter3840b2a2016-03-27 01:53:46 +00002291
2292def _test_get_server_certificate(test, host, port, cert=None):
2293 pem = ssl.get_server_certificate((host, port))
2294 if not pem:
2295 test.fail("No server certificate on %s:%s!" % (host, port))
2296
2297 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
2298 if not pem:
2299 test.fail("No server certificate on %s:%s!" % (host, port))
2300 if support.verbose:
2301 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
2302
2303def _test_get_server_certificate_fail(test, host, port):
2304 try:
2305 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
2306 except ssl.SSLError as x:
2307 #should fail
2308 if support.verbose:
2309 sys.stdout.write("%s\n" % x)
2310 else:
2311 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
2312
2313
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002314from test.ssl_servers import make_https_server
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002315
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002316class ThreadedEchoServer(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002317
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002318 class ConnectionHandler(threading.Thread):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002319
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002320 """A mildly complicated class, because we want it to work both
2321 with and without the SSL wrapper around the socket connection, so
2322 that we can test the STARTTLS functionality."""
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002323
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002324 def __init__(self, server, connsock, addr):
2325 self.server = server
2326 self.running = False
2327 self.sock = connsock
2328 self.addr = addr
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03002329 self.sock.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002330 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002331 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002332 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002333
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002334 def wrap_conn(self):
2335 try:
2336 self.sslconn = self.server.context.wrap_socket(
2337 self.sock, server_side=True)
2338 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
2339 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002340 except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002341 # We treat ConnectionResetError as though it were an
2342 # SSLError - OpenSSL on Ubuntu abruptly closes the
2343 # connection when asked to use an unsupported protocol.
2344 #
Christian Heimes529525f2018-05-23 22:24:45 +02002345 # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL
2346 # tries to send session tickets after handshake.
2347 # https://github.com/openssl/openssl/issues/6342
Paul Monsonfb7e7502019-05-15 15:38:55 -07002348 #
2349 # ConnectionAbortedError is raised in TLS 1.3 mode, when OpenSSL
2350 # tries to send session tickets after handshake when using WinSock.
Christian Heimes529525f2018-05-23 22:24:45 +02002351 self.server.conn_errors.append(str(e))
2352 if self.server.chatty:
2353 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2354 self.running = False
2355 self.close()
2356 return False
2357 except (ssl.SSLError, OSError) as e:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002358 # OSError may occur with wrong protocols, e.g. both
2359 # sides use PROTOCOL_TLS_SERVER.
2360 #
2361 # XXX Various errors can have happened here, for example
2362 # a mismatching protocol version, an invalid certificate,
2363 # or a low-level bug. This should be made more discriminating.
2364 #
2365 # bpo-31323: Store the exception as string to prevent
2366 # a reference leak: server -> conn_errors -> exception
2367 # -> traceback -> self (ConnectionHandler) -> server
2368 self.server.conn_errors.append(str(e))
2369 if self.server.chatty:
2370 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
2371 self.running = False
2372 self.server.stop()
2373 self.close()
2374 return False
2375 else:
2376 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
2377 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
2378 cert = self.sslconn.getpeercert()
2379 if support.verbose and self.server.chatty:
2380 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
2381 cert_binary = self.sslconn.getpeercert(True)
2382 if support.verbose and self.server.chatty:
2383 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
2384 cipher = self.sslconn.cipher()
2385 if support.verbose and self.server.chatty:
2386 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
2387 sys.stdout.write(" server: selected protocol is now "
2388 + str(self.sslconn.selected_npn_protocol()) + "\n")
2389 return True
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002390
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002391 def read(self):
2392 if self.sslconn:
2393 return self.sslconn.read()
2394 else:
2395 return self.sock.recv(1024)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002396
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002397 def write(self, bytes):
2398 if self.sslconn:
2399 return self.sslconn.write(bytes)
2400 else:
2401 return self.sock.send(bytes)
2402
2403 def close(self):
2404 if self.sslconn:
2405 self.sslconn.close()
2406 else:
2407 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002408
Antoine Pitrou480a1242010-04-28 21:37:09 +00002409 def run(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002410 self.running = True
2411 if not self.server.starttls_server:
2412 if not self.wrap_conn():
2413 return
2414 while self.running:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002415 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002416 msg = self.read()
2417 stripped = msg.strip()
2418 if not stripped:
2419 # eof, so quit this handler
2420 self.running = False
2421 try:
2422 self.sock = self.sslconn.unwrap()
2423 except OSError:
2424 # Many tests shut the TCP connection down
2425 # without an SSL shutdown. This causes
2426 # unwrap() to raise OSError with errno=0!
2427 pass
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002428 else:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002429 self.sslconn = None
2430 self.close()
2431 elif stripped == b'over':
2432 if support.verbose and self.server.connectionchatty:
2433 sys.stdout.write(" server: client closed connection\n")
2434 self.close()
2435 return
2436 elif (self.server.starttls_server and
2437 stripped == b'STARTTLS'):
2438 if support.verbose and self.server.connectionchatty:
2439 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
2440 self.write(b"OK\n")
2441 if not self.wrap_conn():
2442 return
2443 elif (self.server.starttls_server and self.sslconn
2444 and stripped == b'ENDTLS'):
2445 if support.verbose and self.server.connectionchatty:
2446 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
2447 self.write(b"OK\n")
2448 self.sock = self.sslconn.unwrap()
2449 self.sslconn = None
2450 if support.verbose and self.server.connectionchatty:
2451 sys.stdout.write(" server: connection is now unencrypted...\n")
2452 elif stripped == b'CB tls-unique':
2453 if support.verbose and self.server.connectionchatty:
2454 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
2455 data = self.sslconn.get_channel_binding("tls-unique")
2456 self.write(repr(data).encode("us-ascii") + b"\n")
Christian Heimes9fb051f2018-09-23 08:32:31 +02002457 elif stripped == b'PHA':
2458 if support.verbose and self.server.connectionchatty:
2459 sys.stdout.write(" server: initiating post handshake auth\n")
2460 try:
2461 self.sslconn.verify_client_post_handshake()
2462 except ssl.SSLError as e:
2463 self.write(repr(e).encode("us-ascii") + b"\n")
2464 else:
2465 self.write(b"OK\n")
2466 elif stripped == b'HASCERT':
2467 if self.sslconn.getpeercert() is not None:
2468 self.write(b'TRUE\n')
2469 else:
2470 self.write(b'FALSE\n')
2471 elif stripped == b'GETCERT':
2472 cert = self.sslconn.getpeercert()
2473 self.write(repr(cert).encode("us-ascii") + b"\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002474 else:
2475 if (support.verbose and
2476 self.server.connectionchatty):
2477 ctype = (self.sslconn and "encrypted") or "unencrypted"
2478 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
2479 % (msg, ctype, msg.lower(), ctype))
2480 self.write(msg.lower())
Paul Monsonfb7e7502019-05-15 15:38:55 -07002481 except (ConnectionResetError, ConnectionAbortedError):
Christian Heimes529525f2018-05-23 22:24:45 +02002482 # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError
2483 # when connection is not shut down gracefully.
2484 if self.server.chatty and support.verbose:
2485 sys.stdout.write(
2486 " Connection reset by peer: {}\n".format(
2487 self.addr)
2488 )
2489 self.close()
2490 self.running = False
Paul Monsonfb7e7502019-05-15 15:38:55 -07002491 except ssl.SSLError as err:
2492 # On Windows sometimes test_pha_required_nocert receives the
2493 # PEER_DID_NOT_RETURN_A_CERTIFICATE exception
2494 # before the 'tlsv13 alert certificate required' exception.
2495 # If the server is stopped when PEER_DID_NOT_RETURN_A_CERTIFICATE
2496 # is received test_pha_required_nocert fails with ConnectionResetError
2497 # because the underlying socket is closed
2498 if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' == err.reason:
2499 if self.server.chatty and support.verbose:
2500 sys.stdout.write(err.args[1])
2501 # test_pha_required_nocert is expecting this exception
2502 raise ssl.SSLError('tlsv13 alert certificate required')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002503 except OSError:
2504 if self.server.chatty:
2505 handle_error("Test server failure:\n")
Bill Janssen2f5799b2008-06-29 00:08:12 +00002506 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002507 self.running = False
Christian Heimes529525f2018-05-23 22:24:45 +02002508
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002509 # normally, we'd just stop here, but for the test
2510 # harness, we want to stop the server
2511 self.server.stop()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002512
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002513 def __init__(self, certificate=None, ssl_version=None,
2514 certreqs=None, cacerts=None,
2515 chatty=True, connectionchatty=False, starttls_server=False,
2516 npn_protocols=None, alpn_protocols=None,
2517 ciphers=None, context=None):
2518 if context:
2519 self.context = context
2520 else:
2521 self.context = ssl.SSLContext(ssl_version
2522 if ssl_version is not None
Christian Heimesa170fa12017-09-15 20:27:30 +02002523 else ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002524 self.context.verify_mode = (certreqs if certreqs is not None
2525 else ssl.CERT_NONE)
2526 if cacerts:
2527 self.context.load_verify_locations(cacerts)
2528 if certificate:
2529 self.context.load_cert_chain(certificate)
2530 if npn_protocols:
2531 self.context.set_npn_protocols(npn_protocols)
2532 if alpn_protocols:
2533 self.context.set_alpn_protocols(alpn_protocols)
2534 if ciphers:
2535 self.context.set_ciphers(ciphers)
2536 self.chatty = chatty
2537 self.connectionchatty = connectionchatty
2538 self.starttls_server = starttls_server
2539 self.sock = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03002540 self.port = socket_helper.bind_port(self.sock)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002541 self.flag = None
2542 self.active = False
2543 self.selected_npn_protocols = []
2544 self.selected_alpn_protocols = []
2545 self.shared_ciphers = []
2546 self.conn_errors = []
2547 threading.Thread.__init__(self)
2548 self.daemon = True
2549
2550 def __enter__(self):
2551 self.start(threading.Event())
2552 self.flag.wait()
2553 return self
2554
2555 def __exit__(self, *args):
2556 self.stop()
2557 self.join()
2558
2559 def start(self, flag=None):
2560 self.flag = flag
2561 threading.Thread.start(self)
2562
2563 def run(self):
2564 self.sock.settimeout(0.05)
2565 self.sock.listen()
2566 self.active = True
2567 if self.flag:
2568 # signal an event
2569 self.flag.set()
2570 while self.active:
2571 try:
2572 newconn, connaddr = self.sock.accept()
2573 if support.verbose and self.chatty:
2574 sys.stdout.write(' server: new connection from '
2575 + repr(connaddr) + '\n')
2576 handler = self.ConnectionHandler(self, newconn, connaddr)
2577 handler.start()
2578 handler.join()
Christian Heimes03c8ddd2020-11-20 09:26:07 +01002579 except TimeoutError:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002580 pass
2581 except KeyboardInterrupt:
2582 self.stop()
Christian Heimes529525f2018-05-23 22:24:45 +02002583 except BaseException as e:
2584 if support.verbose and self.chatty:
2585 sys.stdout.write(
2586 ' connection handling failed: ' + repr(e) + '\n')
2587
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002588 self.sock.close()
2589
2590 def stop(self):
2591 self.active = False
2592
2593class AsyncoreEchoServer(threading.Thread):
2594
2595 # this one's based on asyncore.dispatcher
2596
2597 class EchoServer (asyncore.dispatcher):
2598
2599 class ConnectionHandler(asyncore.dispatcher_with_send):
2600
2601 def __init__(self, conn, certfile):
2602 self.socket = test_wrap_socket(conn, server_side=True,
2603 certfile=certfile,
2604 do_handshake_on_connect=False)
2605 asyncore.dispatcher_with_send.__init__(self, self.socket)
2606 self._ssl_accepting = True
2607 self._do_ssl_handshake()
2608
2609 def readable(self):
2610 if isinstance(self.socket, ssl.SSLSocket):
2611 while self.socket.pending() > 0:
2612 self.handle_read_event()
2613 return True
2614
2615 def _do_ssl_handshake(self):
2616 try:
2617 self.socket.do_handshake()
2618 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2619 return
2620 except ssl.SSLEOFError:
2621 return self.handle_close()
2622 except ssl.SSLError:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002623 raise
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002624 except OSError as err:
2625 if err.args[0] == errno.ECONNABORTED:
2626 return self.handle_close()
2627 else:
2628 self._ssl_accepting = False
Bill Janssen54cc54c2007-12-14 22:08:56 +00002629
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002630 def handle_read(self):
2631 if self._ssl_accepting:
2632 self._do_ssl_handshake()
2633 else:
2634 data = self.recv(1024)
2635 if support.verbose:
2636 sys.stdout.write(" server: read %s from client\n" % repr(data))
2637 if not data:
2638 self.close()
2639 else:
2640 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002641
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002642 def handle_close(self):
2643 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002644 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002645 sys.stdout.write(" server: closed connection %s\n" % self.socket)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002646
2647 def handle_error(self):
2648 raise
2649
Trent Nelson78520002008-04-10 20:54:35 +00002650 def __init__(self, certfile):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002651 self.certfile = certfile
2652 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Serhiy Storchaka16994912020-04-25 10:06:29 +03002653 self.port = socket_helper.bind_port(sock, '')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002654 asyncore.dispatcher.__init__(self, sock)
2655 self.listen(5)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002656
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002657 def handle_accepted(self, sock_obj, addr):
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002658 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002659 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2660 self.ConnectionHandler(sock_obj, self.certfile)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002661
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002662 def handle_error(self):
2663 raise
Bill Janssen54cc54c2007-12-14 22:08:56 +00002664
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002665 def __init__(self, certfile):
2666 self.flag = None
2667 self.active = False
2668 self.server = self.EchoServer(certfile)
2669 self.port = self.server.port
2670 threading.Thread.__init__(self)
2671 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002672
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002673 def __str__(self):
2674 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002675
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002676 def __enter__(self):
2677 self.start(threading.Event())
2678 self.flag.wait()
2679 return self
Thomas Woutersed03b412007-08-28 21:37:11 +00002680
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002681 def __exit__(self, *args):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002682 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002683 sys.stdout.write(" cleanup: stopping server.\n")
2684 self.stop()
2685 if support.verbose:
2686 sys.stdout.write(" cleanup: joining server thread.\n")
2687 self.join()
2688 if support.verbose:
2689 sys.stdout.write(" cleanup: successfully joined.\n")
2690 # make sure that ConnectionHandler is removed from socket_map
2691 asyncore.close_all(ignore_all=True)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002692
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002693 def start (self, flag=None):
2694 self.flag = flag
2695 threading.Thread.start(self)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002696
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002697 def run(self):
2698 self.active = True
2699 if self.flag:
2700 self.flag.set()
2701 while self.active:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002702 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002703 asyncore.loop(1)
2704 except:
2705 pass
Trent Nelson6b240cd2008-04-10 20:12:06 +00002706
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002707 def stop(self):
2708 self.active = False
2709 self.server.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002710
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002711def server_params_test(client_context, server_context, indata=b"FOO\n",
2712 chatty=True, connectionchatty=False, sni_name=None,
2713 session=None):
2714 """
2715 Launch a server, connect a client to it and try various reads
2716 and writes.
2717 """
2718 stats = {}
2719 server = ThreadedEchoServer(context=server_context,
2720 chatty=chatty,
2721 connectionchatty=False)
2722 with server:
2723 with client_context.wrap_socket(socket.socket(),
2724 server_hostname=sni_name, session=session) as s:
2725 s.connect((HOST, server.port))
2726 for arg in [indata, bytearray(indata), memoryview(indata)]:
2727 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002728 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002729 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002730 " client: sending %r...\n" % indata)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002731 s.write(arg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002732 outdata = s.read()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002733 if connectionchatty:
2734 if support.verbose:
2735 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002736 if outdata != indata.lower():
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002737 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002738 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2739 % (outdata[:20], len(outdata),
2740 indata[:20].lower(), len(indata)))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002741 s.write(b"over\n")
2742 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002743 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002744 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002745 stats.update({
2746 'compression': s.compression(),
2747 'cipher': s.cipher(),
2748 'peercert': s.getpeercert(),
2749 'client_alpn_protocol': s.selected_alpn_protocol(),
2750 'client_npn_protocol': s.selected_npn_protocol(),
2751 'version': s.version(),
2752 'session_reused': s.session_reused,
2753 'session': s.session,
2754 })
2755 s.close()
2756 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2757 stats['server_npn_protocols'] = server.selected_npn_protocols
2758 stats['server_shared_ciphers'] = server.shared_ciphers
2759 return stats
Trent Nelson6b240cd2008-04-10 20:12:06 +00002760
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002761def try_protocol_combo(server_protocol, client_protocol, expect_success,
2762 certsreqs=None, server_options=0, client_options=0):
2763 """
2764 Try to SSL-connect using *client_protocol* to *server_protocol*.
2765 If *expect_success* is true, assert that the connection succeeds,
2766 if it's false, assert that the connection fails.
2767 Also, if *expect_success* is a string, assert that it is the protocol
2768 version actually used by the connection.
2769 """
2770 if certsreqs is None:
2771 certsreqs = ssl.CERT_NONE
2772 certtype = {
2773 ssl.CERT_NONE: "CERT_NONE",
2774 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2775 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2776 }[certsreqs]
2777 if support.verbose:
2778 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
2779 sys.stdout.write(formatstr %
2780 (ssl.get_protocol_name(client_protocol),
2781 ssl.get_protocol_name(server_protocol),
2782 certtype))
2783 client_context = ssl.SSLContext(client_protocol)
2784 client_context.options |= client_options
2785 server_context = ssl.SSLContext(server_protocol)
2786 server_context.options |= server_options
2787
Victor Stinner3ef63442019-02-19 18:06:03 +01002788 min_version = PROTOCOL_TO_TLS_VERSION.get(client_protocol, None)
2789 if (min_version is not None
2790 # SSLContext.minimum_version is only available on recent OpenSSL
2791 # (setter added in OpenSSL 1.1.0, getter added in OpenSSL 1.1.1)
2792 and hasattr(server_context, 'minimum_version')
2793 and server_protocol == ssl.PROTOCOL_TLS
2794 and server_context.minimum_version > min_version):
2795 # If OpenSSL configuration is strict and requires more recent TLS
2796 # version, we have to change the minimum to test old TLS versions.
2797 server_context.minimum_version = min_version
2798
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002799 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2800 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2801 # starting from OpenSSL 1.0.0 (see issue #8322).
Christian Heimesa170fa12017-09-15 20:27:30 +02002802 if client_context.protocol == ssl.PROTOCOL_TLS:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002803 client_context.set_ciphers("ALL")
2804
2805 for ctx in (client_context, server_context):
2806 ctx.verify_mode = certsreqs
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002807 ctx.load_cert_chain(SIGNED_CERTFILE)
2808 ctx.load_verify_locations(SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002809 try:
2810 stats = server_params_test(client_context, server_context,
2811 chatty=False, connectionchatty=False)
2812 # Protocol mismatch can result in either an SSLError, or a
2813 # "Connection reset by peer" error.
2814 except ssl.SSLError:
2815 if expect_success:
2816 raise
2817 except OSError as e:
2818 if expect_success or e.errno != errno.ECONNRESET:
2819 raise
2820 else:
2821 if not expect_success:
2822 raise AssertionError(
2823 "Client protocol %s succeeded with server protocol %s!"
2824 % (ssl.get_protocol_name(client_protocol),
2825 ssl.get_protocol_name(server_protocol)))
2826 elif (expect_success is not True
2827 and expect_success != stats['version']):
2828 raise AssertionError("version mismatch: expected %r, got %r"
2829 % (expect_success, stats['version']))
2830
2831
2832class ThreadedTests(unittest.TestCase):
2833
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002834 def test_echo(self):
2835 """Basic test of an SSL client connecting to a server"""
2836 if support.verbose:
2837 sys.stdout.write("\n")
2838 for protocol in PROTOCOLS:
2839 if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
2840 continue
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02002841 if not has_tls_protocol(protocol):
2842 continue
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002843 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2844 context = ssl.SSLContext(protocol)
2845 context.load_cert_chain(CERTFILE)
2846 server_params_test(context, context,
2847 chatty=True, connectionchatty=True)
2848
Christian Heimesa170fa12017-09-15 20:27:30 +02002849 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002850
2851 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
2852 server_params_test(client_context=client_context,
2853 server_context=server_context,
2854 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002855 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002856
2857 client_context.check_hostname = False
2858 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2859 with self.assertRaises(ssl.SSLError) as e:
2860 server_params_test(client_context=server_context,
2861 server_context=client_context,
2862 chatty=True, connectionchatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02002863 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002864 self.assertIn('called a function you should not call',
2865 str(e.exception))
2866
2867 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2868 with self.assertRaises(ssl.SSLError) as e:
2869 server_params_test(client_context=server_context,
2870 server_context=server_context,
2871 chatty=True, connectionchatty=True)
2872 self.assertIn('called a function you should not call',
2873 str(e.exception))
2874
2875 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2876 with self.assertRaises(ssl.SSLError) as e:
2877 server_params_test(client_context=server_context,
2878 server_context=client_context,
2879 chatty=True, connectionchatty=True)
2880 self.assertIn('called a function you should not call',
2881 str(e.exception))
2882
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002883 def test_getpeercert(self):
2884 if support.verbose:
2885 sys.stdout.write("\n")
Christian Heimesa170fa12017-09-15 20:27:30 +02002886
2887 client_context, server_context, hostname = testing_context()
2888 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002889 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002890 with client_context.wrap_socket(socket.socket(),
2891 do_handshake_on_connect=False,
2892 server_hostname=hostname) as s:
2893 s.connect((HOST, server.port))
2894 # getpeercert() raise ValueError while the handshake isn't
2895 # done.
2896 with self.assertRaises(ValueError):
2897 s.getpeercert()
2898 s.do_handshake()
2899 cert = s.getpeercert()
2900 self.assertTrue(cert, "Can't get peer certificate.")
2901 cipher = s.cipher()
2902 if support.verbose:
2903 sys.stdout.write(pprint.pformat(cert) + '\n')
2904 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2905 if 'subject' not in cert:
2906 self.fail("No subject field in certificate: %s." %
2907 pprint.pformat(cert))
2908 if ((('organizationName', 'Python Software Foundation'),)
2909 not in cert['subject']):
2910 self.fail(
2911 "Missing or invalid 'organizationName' field in certificate subject; "
2912 "should be 'Python Software Foundation'.")
2913 self.assertIn('notBefore', cert)
2914 self.assertIn('notAfter', cert)
2915 before = ssl.cert_time_to_seconds(cert['notBefore'])
2916 after = ssl.cert_time_to_seconds(cert['notAfter'])
2917 self.assertLess(before, after)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002918
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002919 @unittest.skipUnless(have_verify_flags(),
2920 "verify_flags need OpenSSL > 0.9.8")
2921 def test_crl_check(self):
2922 if support.verbose:
2923 sys.stdout.write("\n")
2924
Christian Heimesa170fa12017-09-15 20:27:30 +02002925 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002926
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002927 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
Christian Heimesa170fa12017-09-15 20:27:30 +02002928 self.assertEqual(client_context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002929
2930 # VERIFY_DEFAULT should pass
2931 server = ThreadedEchoServer(context=server_context, chatty=True)
2932 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002933 with client_context.wrap_socket(socket.socket(),
2934 server_hostname=hostname) as s:
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002935 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002936 cert = s.getpeercert()
2937 self.assertTrue(cert, "Can't get peer certificate.")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002938
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002939 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimesa170fa12017-09-15 20:27:30 +02002940 client_context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Bill Janssen58afe4c2008-09-08 16:45:19 +00002941
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002942 server = ThreadedEchoServer(context=server_context, chatty=True)
2943 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002944 with client_context.wrap_socket(socket.socket(),
2945 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002946 with self.assertRaisesRegex(ssl.SSLError,
2947 "certificate verify failed"):
2948 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002949
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002950 # now load a CRL file. The CRL file is signed by the CA.
Christian Heimesa170fa12017-09-15 20:27:30 +02002951 client_context.load_verify_locations(CRLFILE)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002952
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002953 server = ThreadedEchoServer(context=server_context, chatty=True)
2954 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002955 with client_context.wrap_socket(socket.socket(),
2956 server_hostname=hostname) as s:
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002957 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002958 cert = s.getpeercert()
2959 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002960
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002961 def test_check_hostname(self):
2962 if support.verbose:
2963 sys.stdout.write("\n")
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002964
Christian Heimesa170fa12017-09-15 20:27:30 +02002965 client_context, server_context, hostname = testing_context()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002966
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002967 # correct hostname should verify
2968 server = ThreadedEchoServer(context=server_context, chatty=True)
2969 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002970 with client_context.wrap_socket(socket.socket(),
2971 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002972 s.connect((HOST, server.port))
2973 cert = s.getpeercert()
2974 self.assertTrue(cert, "Can't get peer certificate.")
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002975
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002976 # incorrect hostname should raise an exception
2977 server = ThreadedEchoServer(context=server_context, chatty=True)
2978 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02002979 with client_context.wrap_socket(socket.socket(),
2980 server_hostname="invalid") as s:
Christian Heimes61d478c2018-01-27 15:51:38 +01002981 with self.assertRaisesRegex(
2982 ssl.CertificateError,
2983 "Hostname mismatch, certificate is not valid for 'invalid'."):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002984 s.connect((HOST, server.port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002985
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002986 # missing server_hostname arg should cause an exception, too
2987 server = ThreadedEchoServer(context=server_context, chatty=True)
2988 with server:
2989 with socket.socket() as s:
2990 with self.assertRaisesRegex(ValueError,
2991 "check_hostname requires server_hostname"):
Christian Heimesa170fa12017-09-15 20:27:30 +02002992 client_context.wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02002993
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002994 def test_ecc_cert(self):
2995 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2996 client_context.load_verify_locations(SIGNING_CA)
Christian Heimese8eb6cb2018-05-22 22:50:12 +02002997 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
Christian Heimesbd5c7d22018-01-20 15:16:30 +01002998 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
2999
3000 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3001 # load ECC cert
3002 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3003
3004 # correct hostname should verify
3005 server = ThreadedEchoServer(context=server_context, chatty=True)
3006 with server:
3007 with client_context.wrap_socket(socket.socket(),
3008 server_hostname=hostname) as s:
3009 s.connect((HOST, server.port))
3010 cert = s.getpeercert()
3011 self.assertTrue(cert, "Can't get peer certificate.")
3012 cipher = s.cipher()[0].split('-')
3013 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3014
3015 def test_dual_rsa_ecc(self):
3016 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3017 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003018 # TODO: fix TLSv1.3 once SSLContext can restrict signature
3019 # algorithms.
3020 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003021 # only ECDSA certs
3022 client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA')
3023 hostname = SIGNED_CERTFILE_ECC_HOSTNAME
3024
3025 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3026 # load ECC and RSA key/cert pairs
3027 server_context.load_cert_chain(SIGNED_CERTFILE_ECC)
3028 server_context.load_cert_chain(SIGNED_CERTFILE)
3029
3030 # correct hostname should verify
3031 server = ThreadedEchoServer(context=server_context, chatty=True)
3032 with server:
3033 with client_context.wrap_socket(socket.socket(),
3034 server_hostname=hostname) as s:
3035 s.connect((HOST, server.port))
3036 cert = s.getpeercert()
3037 self.assertTrue(cert, "Can't get peer certificate.")
3038 cipher = s.cipher()[0].split('-')
3039 self.assertTrue(cipher[:2], ('ECDHE', 'ECDSA'))
3040
Christian Heimes66e57422018-01-29 14:25:13 +01003041 def test_check_hostname_idn(self):
3042 if support.verbose:
3043 sys.stdout.write("\n")
3044
Christian Heimes11a14932018-02-24 02:35:08 +01003045 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Christian Heimes66e57422018-01-29 14:25:13 +01003046 server_context.load_cert_chain(IDNSANSFILE)
3047
Christian Heimes11a14932018-02-24 02:35:08 +01003048 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Christian Heimes66e57422018-01-29 14:25:13 +01003049 context.verify_mode = ssl.CERT_REQUIRED
3050 context.check_hostname = True
3051 context.load_verify_locations(SIGNING_CA)
3052
3053 # correct hostname should verify, when specified in several
3054 # different ways
3055 idn_hostnames = [
3056 ('könig.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003057 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003058 ('xn--knig-5qa.idn.pythontest.net',
3059 'xn--knig-5qa.idn.pythontest.net'),
3060 (b'xn--knig-5qa.idn.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003061 'xn--knig-5qa.idn.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003062
3063 ('königsgäßchen.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003064 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
Christian Heimes66e57422018-01-29 14:25:13 +01003065 ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
3066 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3067 (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net',
Christian Heimes11a14932018-02-24 02:35:08 +01003068 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'),
3069
3070 # ('königsgäßchen.idna2008.pythontest.net',
3071 # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3072 ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3073 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3074 (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net',
3075 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'),
3076
Christian Heimes66e57422018-01-29 14:25:13 +01003077 ]
3078 for server_hostname, expected_hostname in idn_hostnames:
3079 server = ThreadedEchoServer(context=server_context, chatty=True)
3080 with server:
3081 with context.wrap_socket(socket.socket(),
3082 server_hostname=server_hostname) as s:
3083 self.assertEqual(s.server_hostname, expected_hostname)
3084 s.connect((HOST, server.port))
3085 cert = s.getpeercert()
3086 self.assertEqual(s.server_hostname, expected_hostname)
3087 self.assertTrue(cert, "Can't get peer certificate.")
3088
Christian Heimes66e57422018-01-29 14:25:13 +01003089 # incorrect hostname should raise an exception
3090 server = ThreadedEchoServer(context=server_context, chatty=True)
3091 with server:
3092 with context.wrap_socket(socket.socket(),
3093 server_hostname="python.example.org") as s:
3094 with self.assertRaises(ssl.CertificateError):
3095 s.connect((HOST, server.port))
3096
Christian Heimes529525f2018-05-23 22:24:45 +02003097 def test_wrong_cert_tls12(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003098 """Connecting when the server rejects the client's certificate
3099
3100 Launch a server with CERT_REQUIRED, and check that trying to
3101 connect to it with a wrong client certificate fails.
3102 """
Christian Heimes05d9fe32018-02-27 08:55:39 +01003103 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003104 # load client cert that is not signed by trusted CA
3105 client_context.load_cert_chain(CERTFILE)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003106 # require TLS client authentication
3107 server_context.verify_mode = ssl.CERT_REQUIRED
Christian Heimes529525f2018-05-23 22:24:45 +02003108 # TLS 1.3 has different handshake
3109 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes05d9fe32018-02-27 08:55:39 +01003110
3111 server = ThreadedEchoServer(
3112 context=server_context, chatty=True, connectionchatty=True,
3113 )
3114
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003115 with server, \
Christian Heimes05d9fe32018-02-27 08:55:39 +01003116 client_context.wrap_socket(socket.socket(),
3117 server_hostname=hostname) as s:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003118 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003119 # Expect either an SSL error about the server rejecting
3120 # the connection, or a low-level connection reset (which
3121 # sometimes happens on Windows)
3122 s.connect((HOST, server.port))
3123 except ssl.SSLError as e:
3124 if support.verbose:
3125 sys.stdout.write("\nSSLError is %r\n" % e)
3126 except OSError as e:
3127 if e.errno != errno.ECONNRESET:
3128 raise
3129 if support.verbose:
3130 sys.stdout.write("\nsocket.error is %r\n" % e)
3131 else:
3132 self.fail("Use of invalid cert should have failed!")
3133
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003134 @requires_tls_version('TLSv1_3')
Christian Heimes529525f2018-05-23 22:24:45 +02003135 def test_wrong_cert_tls13(self):
3136 client_context, server_context, hostname = testing_context()
Christian Heimes88bfd0b2018-08-14 12:54:19 +02003137 # load client cert that is not signed by trusted CA
3138 client_context.load_cert_chain(CERTFILE)
Christian Heimes529525f2018-05-23 22:24:45 +02003139 server_context.verify_mode = ssl.CERT_REQUIRED
3140 server_context.minimum_version = ssl.TLSVersion.TLSv1_3
3141 client_context.minimum_version = ssl.TLSVersion.TLSv1_3
3142
3143 server = ThreadedEchoServer(
3144 context=server_context, chatty=True, connectionchatty=True,
3145 )
3146 with server, \
3147 client_context.wrap_socket(socket.socket(),
3148 server_hostname=hostname) as s:
3149 # TLS 1.3 perform client cert exchange after handshake
3150 s.connect((HOST, server.port))
3151 try:
3152 s.write(b'data')
3153 s.read(4)
3154 except ssl.SSLError as e:
3155 if support.verbose:
3156 sys.stdout.write("\nSSLError is %r\n" % e)
3157 except OSError as e:
3158 if e.errno != errno.ECONNRESET:
3159 raise
3160 if support.verbose:
3161 sys.stdout.write("\nsocket.error is %r\n" % e)
3162 else:
3163 self.fail("Use of invalid cert should have failed!")
3164
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003165 def test_rude_shutdown(self):
3166 """A brutal shutdown of an SSL server should raise an OSError
3167 in the client when attempting handshake.
3168 """
3169 listener_ready = threading.Event()
3170 listener_gone = threading.Event()
3171
3172 s = socket.socket()
Serhiy Storchaka16994912020-04-25 10:06:29 +03003173 port = socket_helper.bind_port(s, HOST)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003174
3175 # `listener` runs in a thread. It sits in an accept() until
3176 # the main thread connects. Then it rudely closes the socket,
3177 # and sets Event `listener_gone` to let the main thread know
3178 # the socket is gone.
3179 def listener():
3180 s.listen()
3181 listener_ready.set()
3182 newsock, addr = s.accept()
3183 newsock.close()
3184 s.close()
3185 listener_gone.set()
3186
3187 def connector():
3188 listener_ready.wait()
3189 with socket.socket() as c:
3190 c.connect((HOST, port))
3191 listener_gone.wait()
Antoine Pitrou40f08742010-04-24 22:04:40 +00003192 try:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003193 ssl_sock = test_wrap_socket(c)
3194 except OSError:
3195 pass
3196 else:
3197 self.fail('connecting to closed SSL socket should have failed')
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003198
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003199 t = threading.Thread(target=listener)
3200 t.start()
3201 try:
3202 connector()
3203 finally:
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003204 t.join()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003205
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003206 def test_ssl_cert_verify_error(self):
3207 if support.verbose:
3208 sys.stdout.write("\n")
3209
3210 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
3211 server_context.load_cert_chain(SIGNED_CERTFILE)
3212
3213 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3214
3215 server = ThreadedEchoServer(context=server_context, chatty=True)
3216 with server:
3217 with context.wrap_socket(socket.socket(),
Christian Heimesa170fa12017-09-15 20:27:30 +02003218 server_hostname=SIGNED_CERTFILE_HOSTNAME) as s:
Christian Heimesb3ad0e52017-09-08 12:00:19 -07003219 try:
3220 s.connect((HOST, server.port))
3221 except ssl.SSLError as e:
3222 msg = 'unable to get local issuer certificate'
3223 self.assertIsInstance(e, ssl.SSLCertVerificationError)
3224 self.assertEqual(e.verify_code, 20)
3225 self.assertEqual(e.verify_message, msg)
3226 self.assertIn(msg, repr(e))
3227 self.assertIn('certificate verify failed', repr(e))
3228
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003229 @requires_tls_version('SSLv2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003230 def test_protocol_sslv2(self):
3231 """Connecting to an SSLv2 server with various client options"""
3232 if support.verbose:
3233 sys.stdout.write("\n")
3234 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
3235 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
3236 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Christian Heimesa170fa12017-09-15 20:27:30 +02003237 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003238 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003239 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
3240 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
3241 # SSLv23 client with specific SSL options
3242 if no_sslv2_implies_sslv3_hello():
3243 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
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_SSLv2)
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_SSLv3)
Christian Heimesa170fa12017-09-15 20:27:30 +02003248 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003249 client_options=ssl.OP_NO_TLSv1)
Antoine Pitrou242db722013-05-01 20:52:07 +02003250
Christian Heimesa170fa12017-09-15 20:27:30 +02003251 def test_PROTOCOL_TLS(self):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003252 """Connecting to an SSLv23 server with various client options"""
3253 if support.verbose:
3254 sys.stdout.write("\n")
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003255 if has_tls_version('SSLv2'):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003256 try:
Christian Heimesa170fa12017-09-15 20:27:30 +02003257 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003258 except OSError as x:
3259 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
3260 if support.verbose:
3261 sys.stdout.write(
3262 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
3263 % str(x))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003264 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003265 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
3266 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003267 if has_tls_version('TLSv1'):
3268 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003269
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003270 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003271 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
3272 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003273 if has_tls_version('TLSv1'):
3274 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003275
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003276 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003277 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
3278 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003279 if has_tls_version('TLSv1'):
3280 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003281
3282 # Server with specific SSL options
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003283 if has_tls_version('SSLv3'):
Christian Heimesa170fa12017-09-15 20:27:30 +02003284 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003285 server_options=ssl.OP_NO_SSLv3)
3286 # Will choose TLSv1
Christian Heimesa170fa12017-09-15 20:27:30 +02003287 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003288 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003289 if has_tls_version('TLSv1'):
3290 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
3291 server_options=ssl.OP_NO_TLSv1)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003292
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003293 @requires_tls_version('SSLv3')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003294 def test_protocol_sslv3(self):
3295 """Connecting to an SSLv3 server with various client options"""
3296 if support.verbose:
3297 sys.stdout.write("\n")
3298 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
3299 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
3300 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003301 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003302 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003303 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003304 client_options=ssl.OP_NO_SSLv3)
3305 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
3306 if no_sslv2_implies_sslv3_hello():
3307 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Christian Heimesa170fa12017-09-15 20:27:30 +02003308 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003309 False, client_options=ssl.OP_NO_SSLv2)
3310
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003311 @requires_tls_version('TLSv1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003312 def test_protocol_tlsv1(self):
3313 """Connecting to a TLSv1 server with various client options"""
3314 if support.verbose:
3315 sys.stdout.write("\n")
3316 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
3317 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
3318 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003319 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003320 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003321 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003322 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003323 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003324 client_options=ssl.OP_NO_TLSv1)
3325
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003326 @requires_tls_version('TLSv1_1')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003327 def test_protocol_tlsv1_1(self):
3328 """Connecting to a TLSv1.1 server with various client options.
3329 Testing against older TLS versions."""
3330 if support.verbose:
3331 sys.stdout.write("\n")
3332 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003333 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003334 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003335 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003336 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003337 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003338 client_options=ssl.OP_NO_TLSv1_1)
3339
Christian Heimesa170fa12017-09-15 20:27:30 +02003340 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003341 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3342 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003343
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003344 @requires_tls_version('TLSv1_2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003345 def test_protocol_tlsv1_2(self):
3346 """Connecting to a TLSv1.2 server with various client options.
3347 Testing against older TLS versions."""
3348 if support.verbose:
3349 sys.stdout.write("\n")
3350 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
3351 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
3352 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003353 if has_tls_version('SSLv2'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003354 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003355 if has_tls_version('SSLv3'):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003356 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Christian Heimesa170fa12017-09-15 20:27:30 +02003357 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003358 client_options=ssl.OP_NO_TLSv1_2)
3359
Christian Heimesa170fa12017-09-15 20:27:30 +02003360 try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003361 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
3362 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
3363 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
3364 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
3365
3366 def test_starttls(self):
3367 """Switching from clear text to encrypted and back again."""
3368 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
3369
3370 server = ThreadedEchoServer(CERTFILE,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003371 starttls_server=True,
3372 chatty=True,
3373 connectionchatty=True)
3374 wrapped = False
3375 with server:
3376 s = socket.socket()
Serhiy Storchaka5eca7f32019-09-01 12:12:52 +03003377 s.setblocking(True)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003378 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003379 if support.verbose:
3380 sys.stdout.write("\n")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003381 for indata in msgs:
Antoine Pitroud6494802011-07-21 01:11:30 +02003382 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003383 sys.stdout.write(
3384 " client: sending %r...\n" % indata)
3385 if wrapped:
3386 conn.write(indata)
3387 outdata = conn.read()
3388 else:
3389 s.send(indata)
3390 outdata = s.recv(1024)
3391 msg = outdata.strip().lower()
3392 if indata == b"STARTTLS" and msg.startswith(b"ok"):
3393 # STARTTLS ok, switch to secure mode
3394 if support.verbose:
3395 sys.stdout.write(
3396 " client: read %r from server, starting TLS...\n"
3397 % msg)
Christian Heimesa170fa12017-09-15 20:27:30 +02003398 conn = test_wrap_socket(s)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003399 wrapped = True
3400 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
3401 # ENDTLS ok, switch back to clear text
3402 if support.verbose:
3403 sys.stdout.write(
3404 " client: read %r from server, ending TLS...\n"
3405 % msg)
3406 s = conn.unwrap()
3407 wrapped = False
3408 else:
3409 if support.verbose:
3410 sys.stdout.write(
3411 " client: read %r from server\n" % msg)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003412 if support.verbose:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003413 sys.stdout.write(" client: closing connection.\n")
3414 if wrapped:
3415 conn.write(b"over\n")
3416 else:
3417 s.send(b"over\n")
3418 if wrapped:
3419 conn.close()
3420 else:
3421 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003422
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003423 def test_socketserver(self):
3424 """Using socketserver to create and manage SSL connections."""
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003425 server = make_https_server(self, certfile=SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003426 # try to connect
3427 if support.verbose:
3428 sys.stdout.write('\n')
3429 with open(CERTFILE, 'rb') as f:
3430 d1 = f.read()
3431 d2 = ''
3432 # now fetch the same data from the HTTPS server
3433 url = 'https://localhost:%d/%s' % (
3434 server.port, os.path.split(CERTFILE)[1])
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003435 context = ssl.create_default_context(cafile=SIGNING_CA)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003436 f = urllib.request.urlopen(url, context=context)
3437 try:
3438 dlen = f.info().get("content-length")
3439 if dlen and (int(dlen) > 0):
3440 d2 = f.read(int(dlen))
3441 if support.verbose:
3442 sys.stdout.write(
3443 " client: read %d bytes from remote server '%s'\n"
3444 % (len(d2), server))
3445 finally:
3446 f.close()
3447 self.assertEqual(d1, d2)
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003448
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003449 def test_asyncore_server(self):
3450 """Check the example asyncore integration."""
3451 if support.verbose:
3452 sys.stdout.write("\n")
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003453
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003454 indata = b"FOO\n"
3455 server = AsyncoreEchoServer(CERTFILE)
3456 with server:
3457 s = test_wrap_socket(socket.socket())
3458 s.connect(('127.0.0.1', server.port))
3459 if support.verbose:
3460 sys.stdout.write(
3461 " client: sending %r...\n" % indata)
3462 s.write(indata)
3463 outdata = s.read()
3464 if support.verbose:
3465 sys.stdout.write(" client: read %r\n" % outdata)
3466 if outdata != indata.lower():
3467 self.fail(
3468 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
3469 % (outdata[:20], len(outdata),
3470 indata[:20].lower(), len(indata)))
3471 s.write(b"over\n")
3472 if support.verbose:
3473 sys.stdout.write(" client: closing connection.\n")
3474 s.close()
3475 if support.verbose:
3476 sys.stdout.write(" client: connection closed.\n")
Benjamin Petersoncca27322015-01-23 16:35:37 -05003477
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003478 def test_recv_send(self):
3479 """Test recv(), send() and friends."""
3480 if support.verbose:
3481 sys.stdout.write("\n")
3482
3483 server = ThreadedEchoServer(CERTFILE,
3484 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003485 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003486 cacerts=CERTFILE,
3487 chatty=True,
3488 connectionchatty=False)
3489 with server:
3490 s = test_wrap_socket(socket.socket(),
3491 server_side=False,
3492 certfile=CERTFILE,
3493 ca_certs=CERTFILE,
3494 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003495 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003496 s.connect((HOST, server.port))
3497 # helper methods for standardising recv* method signatures
3498 def _recv_into():
3499 b = bytearray(b"\0"*100)
3500 count = s.recv_into(b)
3501 return b[:count]
3502
3503 def _recvfrom_into():
3504 b = bytearray(b"\0"*100)
3505 count, addr = s.recvfrom_into(b)
3506 return b[:count]
3507
3508 # (name, method, expect success?, *args, return value func)
3509 send_methods = [
3510 ('send', s.send, True, [], len),
3511 ('sendto', s.sendto, False, ["some.address"], len),
3512 ('sendall', s.sendall, True, [], lambda x: None),
3513 ]
3514 # (name, method, whether to expect success, *args)
3515 recv_methods = [
3516 ('recv', s.recv, True, []),
3517 ('recvfrom', s.recvfrom, False, ["some.address"]),
3518 ('recv_into', _recv_into, True, []),
3519 ('recvfrom_into', _recvfrom_into, False, []),
3520 ]
3521 data_prefix = "PREFIX_"
3522
3523 for (meth_name, send_meth, expect_success, args,
3524 ret_val_meth) in send_methods:
3525 indata = (data_prefix + meth_name).encode('ascii')
3526 try:
3527 ret = send_meth(indata, *args)
3528 msg = "sending with {}".format(meth_name)
3529 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
3530 outdata = s.read()
3531 if outdata != indata.lower():
3532 self.fail(
3533 "While sending with <<{name:s}>> bad data "
3534 "<<{outdata:r}>> ({nout:d}) received; "
3535 "expected <<{indata:r}>> ({nin:d})\n".format(
3536 name=meth_name, outdata=outdata[:20],
3537 nout=len(outdata),
3538 indata=indata[:20], nin=len(indata)
3539 )
3540 )
3541 except ValueError as e:
3542 if expect_success:
3543 self.fail(
3544 "Failed to send with method <<{name:s}>>; "
3545 "expected to succeed.\n".format(name=meth_name)
3546 )
3547 if not str(e).startswith(meth_name):
3548 self.fail(
3549 "Method <<{name:s}>> failed with unexpected "
3550 "exception message: {exp:s}\n".format(
3551 name=meth_name, exp=e
3552 )
3553 )
3554
3555 for meth_name, recv_meth, expect_success, args in recv_methods:
3556 indata = (data_prefix + meth_name).encode('ascii')
3557 try:
3558 s.send(indata)
3559 outdata = recv_meth(*args)
3560 if outdata != indata.lower():
3561 self.fail(
3562 "While receiving with <<{name:s}>> bad data "
3563 "<<{outdata:r}>> ({nout:d}) received; "
3564 "expected <<{indata:r}>> ({nin:d})\n".format(
3565 name=meth_name, outdata=outdata[:20],
3566 nout=len(outdata),
3567 indata=indata[:20], nin=len(indata)
3568 )
3569 )
3570 except ValueError as e:
3571 if expect_success:
3572 self.fail(
3573 "Failed to receive with method <<{name:s}>>; "
3574 "expected to succeed.\n".format(name=meth_name)
3575 )
3576 if not str(e).startswith(meth_name):
3577 self.fail(
3578 "Method <<{name:s}>> failed with unexpected "
3579 "exception message: {exp:s}\n".format(
3580 name=meth_name, exp=e
3581 )
3582 )
3583 # consume data
3584 s.read()
3585
3586 # read(-1, buffer) is supported, even though read(-1) is not
3587 data = b"data"
3588 s.send(data)
3589 buffer = bytearray(len(data))
3590 self.assertEqual(s.read(-1, buffer), len(data))
3591 self.assertEqual(buffer, data)
3592
Christian Heimes888bbdc2017-09-07 14:18:21 -07003593 # sendall accepts bytes-like objects
3594 if ctypes is not None:
3595 ubyte = ctypes.c_ubyte * len(data)
3596 byteslike = ubyte.from_buffer_copy(data)
3597 s.sendall(byteslike)
3598 self.assertEqual(s.read(), data)
3599
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003600 # Make sure sendmsg et al are disallowed to avoid
3601 # inadvertent disclosure of data and/or corruption
3602 # of the encrypted data stream
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003603 self.assertRaises(NotImplementedError, s.dup)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003604 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
3605 self.assertRaises(NotImplementedError, s.recvmsg, 100)
3606 self.assertRaises(NotImplementedError,
Serhiy Storchaka42b1d612018-12-06 22:36:55 +02003607 s.recvmsg_into, [bytearray(100)])
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003608 s.write(b"over\n")
3609
3610 self.assertRaises(ValueError, s.recv, -1)
3611 self.assertRaises(ValueError, s.read, -1)
3612
3613 s.close()
3614
3615 def test_recv_zero(self):
3616 server = ThreadedEchoServer(CERTFILE)
3617 server.__enter__()
3618 self.addCleanup(server.__exit__, None, None)
3619 s = socket.create_connection((HOST, server.port))
3620 self.addCleanup(s.close)
3621 s = test_wrap_socket(s, suppress_ragged_eofs=False)
3622 self.addCleanup(s.close)
3623
3624 # recv/read(0) should return no data
3625 s.send(b"data")
3626 self.assertEqual(s.recv(0), b"")
3627 self.assertEqual(s.read(0), b"")
3628 self.assertEqual(s.read(), b"data")
3629
3630 # Should not block if the other end sends no data
3631 s.setblocking(False)
3632 self.assertEqual(s.recv(0), b"")
3633 self.assertEqual(s.recv_into(bytearray()), 0)
3634
3635 def test_nonblocking_send(self):
3636 server = ThreadedEchoServer(CERTFILE,
3637 certreqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003638 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003639 cacerts=CERTFILE,
3640 chatty=True,
3641 connectionchatty=False)
3642 with server:
3643 s = test_wrap_socket(socket.socket(),
3644 server_side=False,
3645 certfile=CERTFILE,
3646 ca_certs=CERTFILE,
3647 cert_reqs=ssl.CERT_NONE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003648 ssl_version=ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003649 s.connect((HOST, server.port))
3650 s.setblocking(False)
3651
3652 # If we keep sending data, at some point the buffers
3653 # will be full and the call will block
3654 buf = bytearray(8192)
3655 def fill_buffer():
3656 while True:
3657 s.send(buf)
3658 self.assertRaises((ssl.SSLWantWriteError,
3659 ssl.SSLWantReadError), fill_buffer)
3660
3661 # Now read all the output and discard it
3662 s.setblocking(True)
3663 s.close()
3664
3665 def test_handshake_timeout(self):
3666 # Issue #5103: SSL handshake must respect the socket timeout
3667 server = socket.socket(socket.AF_INET)
3668 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003669 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003670 started = threading.Event()
3671 finish = False
3672
3673 def serve():
3674 server.listen()
3675 started.set()
3676 conns = []
3677 while not finish:
3678 r, w, e = select.select([server], [], [], 0.1)
3679 if server in r:
3680 # Let the socket hang around rather than having
3681 # it closed by garbage collection.
3682 conns.append(server.accept()[0])
3683 for sock in conns:
3684 sock.close()
3685
3686 t = threading.Thread(target=serve)
3687 t.start()
3688 started.wait()
3689
3690 try:
3691 try:
3692 c = socket.socket(socket.AF_INET)
3693 c.settimeout(0.2)
3694 c.connect((host, port))
3695 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003696 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003697 test_wrap_socket, c)
3698 finally:
3699 c.close()
3700 try:
3701 c = socket.socket(socket.AF_INET)
3702 c = test_wrap_socket(c)
3703 c.settimeout(0.2)
3704 # Will attempt handshake and time out
Christian Heimes03c8ddd2020-11-20 09:26:07 +01003705 self.assertRaisesRegex(TimeoutError, "timed out",
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003706 c.connect, (host, port))
3707 finally:
3708 c.close()
3709 finally:
3710 finish = True
3711 t.join()
3712 server.close()
3713
3714 def test_server_accept(self):
3715 # Issue #16357: accept() on a SSLSocket created through
3716 # SSLContext.wrap_socket().
Christian Heimesa170fa12017-09-15 20:27:30 +02003717 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003718 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01003719 context.load_verify_locations(SIGNING_CA)
3720 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003721 server = socket.socket(socket.AF_INET)
3722 host = "127.0.0.1"
Serhiy Storchaka16994912020-04-25 10:06:29 +03003723 port = socket_helper.bind_port(server)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003724 server = context.wrap_socket(server, server_side=True)
3725 self.assertTrue(server.server_side)
3726
3727 evt = threading.Event()
3728 remote = None
3729 peer = None
3730 def serve():
3731 nonlocal remote, peer
3732 server.listen()
3733 # Block on the accept and wait on the connection to close.
3734 evt.set()
3735 remote, peer = server.accept()
Christian Heimes529525f2018-05-23 22:24:45 +02003736 remote.send(remote.recv(4))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003737
3738 t = threading.Thread(target=serve)
3739 t.start()
3740 # Client wait until server setup and perform a connect.
3741 evt.wait()
3742 client = context.wrap_socket(socket.socket())
3743 client.connect((host, port))
Christian Heimes529525f2018-05-23 22:24:45 +02003744 client.send(b'data')
3745 client.recv()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003746 client_addr = client.getsockname()
3747 client.close()
3748 t.join()
3749 remote.close()
3750 server.close()
3751 # Sanity checks.
3752 self.assertIsInstance(remote, ssl.SSLSocket)
3753 self.assertEqual(peer, client_addr)
3754
3755 def test_getpeercert_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003756 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003757 with context.wrap_socket(socket.socket()) as sock:
3758 with self.assertRaises(OSError) as cm:
3759 sock.getpeercert()
3760 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3761
3762 def test_do_handshake_enotconn(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003763 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003764 with context.wrap_socket(socket.socket()) as sock:
3765 with self.assertRaises(OSError) as cm:
3766 sock.do_handshake()
3767 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3768
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003769 def test_no_shared_ciphers(self):
3770 client_context, server_context, hostname = testing_context()
3771 # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test
3772 client_context.options |= ssl.OP_NO_TLSv1_3
Victor Stinner5e922652018-09-07 17:30:33 +02003773 # Force different suites on client and server
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003774 client_context.set_ciphers("AES128")
3775 server_context.set_ciphers("AES256")
3776 with ThreadedEchoServer(context=server_context) as server:
3777 with client_context.wrap_socket(socket.socket(),
3778 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003779 with self.assertRaises(OSError):
3780 s.connect((HOST, server.port))
3781 self.assertIn("no shared cipher", server.conn_errors[0])
3782
3783 def test_version_basic(self):
3784 """
3785 Basic tests for SSLSocket.version().
3786 More tests are done in the test_protocol_*() methods.
3787 """
Christian Heimesa170fa12017-09-15 20:27:30 +02003788 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
3789 context.check_hostname = False
3790 context.verify_mode = ssl.CERT_NONE
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003791 with ThreadedEchoServer(CERTFILE,
Christian Heimesa170fa12017-09-15 20:27:30 +02003792 ssl_version=ssl.PROTOCOL_TLS_SERVER,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003793 chatty=False) as server:
3794 with context.wrap_socket(socket.socket()) as s:
3795 self.assertIs(s.version(), None)
Christian Heimes141c5e82018-02-24 21:10:57 +01003796 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003797 s.connect((HOST, server.port))
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003798 if IS_OPENSSL_1_1_1 and has_tls_version('TLSv1_3'):
Christian Heimes05d9fe32018-02-27 08:55:39 +01003799 self.assertEqual(s.version(), 'TLSv1.3')
3800 elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
Christian Heimesa170fa12017-09-15 20:27:30 +02003801 self.assertEqual(s.version(), 'TLSv1.2')
3802 else: # 0.9.8 to 1.0.1
3803 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2'))
Christian Heimes141c5e82018-02-24 21:10:57 +01003804 self.assertIs(s._sslobj, None)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003805 self.assertIs(s.version(), None)
3806
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003807 @requires_tls_version('TLSv1_3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003808 def test_tls1_3(self):
3809 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
3810 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003811 context.options |= (
3812 ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2
3813 )
3814 with ThreadedEchoServer(context=context) as server:
3815 with context.wrap_socket(socket.socket()) as s:
3816 s.connect((HOST, server.port))
Christian Heimes05d9fe32018-02-27 08:55:39 +01003817 self.assertIn(s.cipher()[0], {
Christian Heimese8eb6cb2018-05-22 22:50:12 +02003818 'TLS_AES_256_GCM_SHA384',
3819 'TLS_CHACHA20_POLY1305_SHA256',
3820 'TLS_AES_128_GCM_SHA256',
Christian Heimes05d9fe32018-02-27 08:55:39 +01003821 })
3822 self.assertEqual(s.version(), 'TLSv1.3')
Christian Heimescb5b68a2017-09-07 18:07:00 -07003823
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003824 @requires_minimum_version
3825 @requires_tls_version('TLSv1_2')
3826 def test_min_max_version_tlsv1_2(self):
Christian Heimes698dde12018-02-27 11:54:43 +01003827 client_context, server_context, hostname = testing_context()
3828 # client TLSv1.0 to 1.2
3829 client_context.minimum_version = ssl.TLSVersion.TLSv1
3830 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
3831 # server only TLSv1.2
3832 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
3833 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
3834
3835 with ThreadedEchoServer(context=server_context) as server:
3836 with client_context.wrap_socket(socket.socket(),
3837 server_hostname=hostname) as s:
3838 s.connect((HOST, server.port))
3839 self.assertEqual(s.version(), 'TLSv1.2')
3840
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003841 @requires_minimum_version
3842 @requires_tls_version('TLSv1_1')
3843 def test_min_max_version_tlsv1_1(self):
3844 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003845 # client 1.0 to 1.2, server 1.0 to 1.1
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003846 client_context.minimum_version = ssl.TLSVersion.TLSv1
3847 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimes698dde12018-02-27 11:54:43 +01003848 server_context.minimum_version = ssl.TLSVersion.TLSv1
3849 server_context.maximum_version = ssl.TLSVersion.TLSv1_1
3850
3851 with ThreadedEchoServer(context=server_context) as server:
3852 with client_context.wrap_socket(socket.socket(),
3853 server_hostname=hostname) as s:
3854 s.connect((HOST, server.port))
3855 self.assertEqual(s.version(), 'TLSv1.1')
3856
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003857 @requires_minimum_version
3858 @requires_tls_version('TLSv1_2')
Christian Heimesce04e712020-11-18 13:10:53 +01003859 @requires_tls_version('TLSv1')
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003860 def test_min_max_version_mismatch(self):
3861 client_context, server_context, hostname = testing_context()
Christian Heimes698dde12018-02-27 11:54:43 +01003862 # client 1.0, server 1.2 (mismatch)
Christian Heimes698dde12018-02-27 11:54:43 +01003863 server_context.maximum_version = ssl.TLSVersion.TLSv1_2
Christian Heimesc9bc49c2019-09-11 19:24:47 +02003864 server_context.minimum_version = ssl.TLSVersion.TLSv1_2
Christian Heimese35d1ba2019-06-03 20:40:15 +02003865 client_context.maximum_version = ssl.TLSVersion.TLSv1
Christian Heimesde606ea2019-09-11 19:48:58 +02003866 client_context.minimum_version = ssl.TLSVersion.TLSv1
Christian Heimes698dde12018-02-27 11:54:43 +01003867 with ThreadedEchoServer(context=server_context) as server:
3868 with client_context.wrap_socket(socket.socket(),
3869 server_hostname=hostname) as s:
3870 with self.assertRaises(ssl.SSLError) as e:
3871 s.connect((HOST, server.port))
3872 self.assertIn("alert", str(e.exception))
3873
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02003874 @requires_minimum_version
3875 @requires_tls_version('SSLv3')
Christian Heimes698dde12018-02-27 11:54:43 +01003876 def test_min_max_version_sslv3(self):
3877 client_context, server_context, hostname = testing_context()
3878 server_context.minimum_version = ssl.TLSVersion.SSLv3
3879 client_context.minimum_version = ssl.TLSVersion.SSLv3
3880 client_context.maximum_version = ssl.TLSVersion.SSLv3
3881 with ThreadedEchoServer(context=server_context) as server:
3882 with client_context.wrap_socket(socket.socket(),
3883 server_hostname=hostname) as s:
3884 s.connect((HOST, server.port))
3885 self.assertEqual(s.version(), 'SSLv3')
3886
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003887 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3888 def test_default_ecdh_curve(self):
3889 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3890 # should be enabled by default on SSL contexts.
Christian Heimesa170fa12017-09-15 20:27:30 +02003891 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003892 context.load_cert_chain(CERTFILE)
Christian Heimescb5b68a2017-09-07 18:07:00 -07003893 # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
3894 # cipher name.
3895 context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003896 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3897 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3898 # our default cipher list should prefer ECDH-based ciphers
3899 # automatically.
3900 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
3901 context.set_ciphers("ECCdraft:ECDH")
3902 with ThreadedEchoServer(context=context) as server:
3903 with context.wrap_socket(socket.socket()) as s:
3904 s.connect((HOST, server.port))
3905 self.assertIn("ECDH", s.cipher()[0])
3906
3907 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3908 "'tls-unique' channel binding not available")
3909 def test_tls_unique_channel_binding(self):
3910 """Test tls-unique channel binding."""
3911 if support.verbose:
3912 sys.stdout.write("\n")
3913
Christian Heimes05d9fe32018-02-27 08:55:39 +01003914 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003915
3916 server = ThreadedEchoServer(context=server_context,
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003917 chatty=True,
3918 connectionchatty=False)
Christian Heimes05d9fe32018-02-27 08:55:39 +01003919
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003920 with server:
Christian Heimes05d9fe32018-02-27 08:55:39 +01003921 with client_context.wrap_socket(
3922 socket.socket(),
3923 server_hostname=hostname) as s:
3924 s.connect((HOST, server.port))
3925 # get the data
3926 cb_data = s.get_channel_binding("tls-unique")
3927 if support.verbose:
3928 sys.stdout.write(
3929 " got channel binding data: {0!r}\n".format(cb_data))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003930
Christian Heimes05d9fe32018-02-27 08:55:39 +01003931 # check if it is sane
3932 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003933 if s.version() == 'TLSv1.3':
3934 self.assertEqual(len(cb_data), 48)
3935 else:
3936 self.assertEqual(len(cb_data), 12) # True for TLSv1
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003937
Christian Heimes05d9fe32018-02-27 08:55:39 +01003938 # and compare with the peers version
3939 s.write(b"CB tls-unique\n")
3940 peer_data_repr = s.read().strip()
3941 self.assertEqual(peer_data_repr,
3942 repr(cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003943
3944 # now, again
Christian Heimes05d9fe32018-02-27 08:55:39 +01003945 with client_context.wrap_socket(
3946 socket.socket(),
3947 server_hostname=hostname) as s:
3948 s.connect((HOST, server.port))
3949 new_cb_data = s.get_channel_binding("tls-unique")
3950 if support.verbose:
3951 sys.stdout.write(
3952 "got another channel binding data: {0!r}\n".format(
3953 new_cb_data)
3954 )
3955 # is it really unique
3956 self.assertNotEqual(cb_data, new_cb_data)
3957 self.assertIsNotNone(cb_data)
Christian Heimes529525f2018-05-23 22:24:45 +02003958 if s.version() == 'TLSv1.3':
3959 self.assertEqual(len(cb_data), 48)
3960 else:
3961 self.assertEqual(len(cb_data), 12) # True for TLSv1
Christian Heimes05d9fe32018-02-27 08:55:39 +01003962 s.write(b"CB tls-unique\n")
3963 peer_data_repr = s.read().strip()
3964 self.assertEqual(peer_data_repr,
3965 repr(new_cb_data).encode("us-ascii"))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003966
3967 def test_compression(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003968 client_context, server_context, hostname = testing_context()
3969 stats = server_params_test(client_context, server_context,
3970 chatty=True, connectionchatty=True,
3971 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003972 if support.verbose:
3973 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
3974 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
3975
3976 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
3977 "ssl.OP_NO_COMPRESSION needed for this test")
3978 def test_compression_disabled(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02003979 client_context, server_context, hostname = testing_context()
3980 client_context.options |= ssl.OP_NO_COMPRESSION
3981 server_context.options |= ssl.OP_NO_COMPRESSION
3982 stats = server_params_test(client_context, server_context,
3983 chatty=True, connectionchatty=True,
3984 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003985 self.assertIs(stats['compression'], None)
3986
Paul Monsonf3550692019-06-19 13:09:54 -07003987 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003988 def test_dh_params(self):
3989 # Check we can get a connection with ephemeral Diffie-Hellman
Christian Heimesa170fa12017-09-15 20:27:30 +02003990 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01003991 # test scenario needs TLS <= 1.2
3992 client_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02003993 server_context.load_dh_params(DHFILE)
3994 server_context.set_ciphers("kEDH")
Christian Heimes05d9fe32018-02-27 08:55:39 +01003995 server_context.options |= ssl.OP_NO_TLSv1_3
Christian Heimesa170fa12017-09-15 20:27:30 +02003996 stats = server_params_test(client_context, server_context,
3997 chatty=True, connectionchatty=True,
3998 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003999 cipher = stats["cipher"][0]
4000 parts = cipher.split("-")
4001 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4002 self.fail("Non-DH cipher: " + cipher[0])
4003
Christian Heimesb7b92252018-02-25 09:49:31 +01004004 @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support")
Christian Heimes05d9fe32018-02-27 08:55:39 +01004005 @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1")
Christian Heimesb7b92252018-02-25 09:49:31 +01004006 def test_ecdh_curve(self):
4007 # server secp384r1, client auto
4008 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004009
Christian Heimesb7b92252018-02-25 09:49:31 +01004010 server_context.set_ecdh_curve("secp384r1")
4011 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4012 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4013 stats = server_params_test(client_context, server_context,
4014 chatty=True, connectionchatty=True,
4015 sni_name=hostname)
4016
4017 # server auto, client secp384r1
4018 client_context, server_context, hostname = testing_context()
4019 client_context.set_ecdh_curve("secp384r1")
4020 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4021 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4022 stats = server_params_test(client_context, server_context,
4023 chatty=True, connectionchatty=True,
4024 sni_name=hostname)
4025
4026 # server / client curve mismatch
4027 client_context, server_context, hostname = testing_context()
4028 client_context.set_ecdh_curve("prime256v1")
4029 server_context.set_ecdh_curve("secp384r1")
4030 server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
4031 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
4032 try:
4033 stats = server_params_test(client_context, server_context,
4034 chatty=True, connectionchatty=True,
4035 sni_name=hostname)
4036 except ssl.SSLError:
4037 pass
4038 else:
4039 # OpenSSL 1.0.2 does not fail although it should.
Christian Heimes05d9fe32018-02-27 08:55:39 +01004040 if IS_OPENSSL_1_1_0:
Christian Heimesb7b92252018-02-25 09:49:31 +01004041 self.fail("mismatch curve did not fail")
4042
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004043 def test_selected_alpn_protocol(self):
4044 # selected_alpn_protocol() is None unless ALPN is used.
Christian Heimesa170fa12017-09-15 20:27:30 +02004045 client_context, server_context, hostname = testing_context()
4046 stats = server_params_test(client_context, server_context,
4047 chatty=True, connectionchatty=True,
4048 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004049 self.assertIs(stats['client_alpn_protocol'], None)
4050
4051 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
4052 def test_selected_alpn_protocol_if_server_uses_alpn(self):
4053 # selected_alpn_protocol() is None unless ALPN is used by the client.
Christian Heimesa170fa12017-09-15 20:27:30 +02004054 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004055 server_context.set_alpn_protocols(['foo', 'bar'])
4056 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004057 chatty=True, connectionchatty=True,
4058 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004059 self.assertIs(stats['client_alpn_protocol'], None)
4060
4061 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
4062 def test_alpn_protocols(self):
4063 server_protocols = ['foo', 'bar', 'milkshake']
4064 protocol_tests = [
4065 (['foo', 'bar'], 'foo'),
4066 (['bar', 'foo'], 'foo'),
4067 (['milkshake'], 'milkshake'),
4068 (['http/3.0', 'http/4.0'], None)
4069 ]
4070 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004071 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004072 server_context.set_alpn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004073 client_context.set_alpn_protocols(client_protocols)
4074
4075 try:
4076 stats = server_params_test(client_context,
4077 server_context,
4078 chatty=True,
Christian Heimesa170fa12017-09-15 20:27:30 +02004079 connectionchatty=True,
4080 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004081 except ssl.SSLError as e:
4082 stats = e
4083
Christian Heimes05d9fe32018-02-27 08:55:39 +01004084 if (expected is None and IS_OPENSSL_1_1_0
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004085 and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)):
4086 # OpenSSL 1.1.0 to 1.1.0e raises handshake error
4087 self.assertIsInstance(stats, ssl.SSLError)
4088 else:
4089 msg = "failed trying %s (s) and %s (c).\n" \
4090 "was expecting %s, but got %%s from the %%s" \
4091 % (str(server_protocols), str(client_protocols),
4092 str(expected))
4093 client_result = stats['client_alpn_protocol']
4094 self.assertEqual(client_result, expected,
4095 msg % (client_result, "client"))
4096 server_result = stats['server_alpn_protocols'][-1] \
4097 if len(stats['server_alpn_protocols']) else 'nothing'
4098 self.assertEqual(server_result, expected,
4099 msg % (server_result, "server"))
4100
4101 def test_selected_npn_protocol(self):
4102 # selected_npn_protocol() is None unless NPN is used
Christian Heimesa170fa12017-09-15 20:27:30 +02004103 client_context, server_context, hostname = testing_context()
4104 stats = server_params_test(client_context, server_context,
4105 chatty=True, connectionchatty=True,
4106 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004107 self.assertIs(stats['client_npn_protocol'], None)
4108
4109 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
4110 def test_npn_protocols(self):
4111 server_protocols = ['http/1.1', 'spdy/2']
4112 protocol_tests = [
4113 (['http/1.1', 'spdy/2'], 'http/1.1'),
4114 (['spdy/2', 'http/1.1'], 'http/1.1'),
4115 (['spdy/2', 'test'], 'spdy/2'),
4116 (['abc', 'def'], 'abc')
4117 ]
4118 for client_protocols, expected in protocol_tests:
Christian Heimesa170fa12017-09-15 20:27:30 +02004119 client_context, server_context, hostname = testing_context()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004120 server_context.set_npn_protocols(server_protocols)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004121 client_context.set_npn_protocols(client_protocols)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004122 stats = server_params_test(client_context, server_context,
Christian Heimesa170fa12017-09-15 20:27:30 +02004123 chatty=True, connectionchatty=True,
4124 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004125 msg = "failed trying %s (s) and %s (c).\n" \
4126 "was expecting %s, but got %%s from the %%s" \
4127 % (str(server_protocols), str(client_protocols),
4128 str(expected))
4129 client_result = stats['client_npn_protocol']
4130 self.assertEqual(client_result, expected, msg % (client_result, "client"))
4131 server_result = stats['server_npn_protocols'][-1] \
4132 if len(stats['server_npn_protocols']) else 'nothing'
4133 self.assertEqual(server_result, expected, msg % (server_result, "server"))
4134
4135 def sni_contexts(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004136 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004137 server_context.load_cert_chain(SIGNED_CERTFILE)
Christian Heimesa170fa12017-09-15 20:27:30 +02004138 other_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004139 other_context.load_cert_chain(SIGNED_CERTFILE2)
Christian Heimesa170fa12017-09-15 20:27:30 +02004140 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004141 client_context.load_verify_locations(SIGNING_CA)
4142 return server_context, other_context, client_context
4143
4144 def check_common_name(self, stats, name):
4145 cert = stats['peercert']
4146 self.assertIn((('commonName', name),), cert['subject'])
4147
4148 @needs_sni
4149 def test_sni_callback(self):
4150 calls = []
4151 server_context, other_context, client_context = self.sni_contexts()
4152
Christian Heimesa170fa12017-09-15 20:27:30 +02004153 client_context.check_hostname = False
4154
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004155 def servername_cb(ssl_sock, server_name, initial_context):
4156 calls.append((server_name, initial_context))
4157 if server_name is not None:
4158 ssl_sock.context = other_context
4159 server_context.set_servername_callback(servername_cb)
4160
4161 stats = server_params_test(client_context, server_context,
4162 chatty=True,
4163 sni_name='supermessage')
4164 # The hostname was fetched properly, and the certificate was
4165 # changed for the connection.
4166 self.assertEqual(calls, [("supermessage", server_context)])
4167 # CERTFILE4 was selected
4168 self.check_common_name(stats, 'fakehostname')
4169
4170 calls = []
4171 # The callback is called with server_name=None
4172 stats = server_params_test(client_context, server_context,
4173 chatty=True,
4174 sni_name=None)
4175 self.assertEqual(calls, [(None, server_context)])
Christian Heimesa170fa12017-09-15 20:27:30 +02004176 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004177
4178 # Check disabling the callback
4179 calls = []
4180 server_context.set_servername_callback(None)
4181
4182 stats = server_params_test(client_context, server_context,
4183 chatty=True,
4184 sni_name='notfunny')
4185 # Certificate didn't change
Christian Heimesa170fa12017-09-15 20:27:30 +02004186 self.check_common_name(stats, SIGNED_CERTFILE_HOSTNAME)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004187 self.assertEqual(calls, [])
4188
4189 @needs_sni
4190 def test_sni_callback_alert(self):
4191 # Returning a TLS alert is reflected to the connecting client
4192 server_context, other_context, client_context = self.sni_contexts()
4193
4194 def cb_returning_alert(ssl_sock, server_name, initial_context):
4195 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
4196 server_context.set_servername_callback(cb_returning_alert)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004197 with self.assertRaises(ssl.SSLError) as cm:
4198 stats = server_params_test(client_context, server_context,
4199 chatty=False,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004200 sni_name='supermessage')
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004201 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004202
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004203 @needs_sni
4204 def test_sni_callback_raising(self):
4205 # Raising fails the connection with a TLS handshake failure alert.
4206 server_context, other_context, client_context = self.sni_contexts()
4207
4208 def cb_raising(ssl_sock, server_name, initial_context):
4209 1/0
4210 server_context.set_servername_callback(cb_raising)
4211
Victor Stinner00253502019-06-03 03:51:43 +02004212 with support.catch_unraisable_exception() as catch:
4213 with self.assertRaises(ssl.SSLError) as cm:
4214 stats = server_params_test(client_context, server_context,
4215 chatty=False,
4216 sni_name='supermessage')
4217
4218 self.assertEqual(cm.exception.reason,
4219 'SSLV3_ALERT_HANDSHAKE_FAILURE')
4220 self.assertEqual(catch.unraisable.exc_type, ZeroDivisionError)
Antoine Pitrou50b24d02013-04-11 20:48:42 +02004221
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004222 @needs_sni
4223 def test_sni_callback_wrong_return_type(self):
4224 # Returning the wrong return type terminates the TLS connection
4225 # with an internal error alert.
4226 server_context, other_context, client_context = self.sni_contexts()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004227
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004228 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
4229 return "foo"
4230 server_context.set_servername_callback(cb_wrong_return_type)
4231
Victor Stinner00253502019-06-03 03:51:43 +02004232 with support.catch_unraisable_exception() as catch:
4233 with self.assertRaises(ssl.SSLError) as cm:
4234 stats = server_params_test(client_context, server_context,
4235 chatty=False,
4236 sni_name='supermessage')
4237
4238
4239 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
4240 self.assertEqual(catch.unraisable.exc_type, TypeError)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004241
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004242 def test_shared_ciphers(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004243 client_context, server_context, hostname = testing_context()
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004244 client_context.set_ciphers("AES128:AES256")
4245 server_context.set_ciphers("AES256")
4246 expected_algs = [
4247 "AES256", "AES-256",
4248 # TLS 1.3 ciphers are always enabled
4249 "TLS_CHACHA20", "TLS_AES",
4250 ]
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004251
Christian Heimesa170fa12017-09-15 20:27:30 +02004252 stats = server_params_test(client_context, server_context,
4253 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004254 ciphers = stats['server_shared_ciphers'][0]
4255 self.assertGreater(len(ciphers), 0)
4256 for name, tls_version, bits in ciphers:
Christian Heimese8eb6cb2018-05-22 22:50:12 +02004257 if not any(alg in name for alg in expected_algs):
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004258 self.fail(name)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004259
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004260 def test_read_write_after_close_raises_valuerror(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004261 client_context, server_context, hostname = testing_context()
4262 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004263
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004264 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004265 s = client_context.wrap_socket(socket.socket(),
4266 server_hostname=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004267 s.connect((HOST, server.port))
4268 s.close()
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004269
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004270 self.assertRaises(ValueError, s.read, 1024)
4271 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004272
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004273 def test_sendfile(self):
4274 TEST_DATA = b"x" * 512
Hai Shia7f5d932020-08-04 00:41:24 +08004275 with open(os_helper.TESTFN, 'wb') as f:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004276 f.write(TEST_DATA)
Hai Shia7f5d932020-08-04 00:41:24 +08004277 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesa170fa12017-09-15 20:27:30 +02004278 context = ssl.SSLContext(ssl.PROTOCOL_TLS)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004279 context.verify_mode = ssl.CERT_REQUIRED
Christian Heimesbd5c7d22018-01-20 15:16:30 +01004280 context.load_verify_locations(SIGNING_CA)
4281 context.load_cert_chain(SIGNED_CERTFILE)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004282 server = ThreadedEchoServer(context=context, chatty=False)
4283 with server:
4284 with context.wrap_socket(socket.socket()) as s:
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004285 s.connect((HOST, server.port))
Hai Shia7f5d932020-08-04 00:41:24 +08004286 with open(os_helper.TESTFN, 'rb') as file:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004287 s.sendfile(file)
4288 self.assertEqual(s.recv(1024), TEST_DATA)
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004289
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004290 def test_session(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004291 client_context, server_context, hostname = testing_context()
Christian Heimes05d9fe32018-02-27 08:55:39 +01004292 # TODO: sessions aren't compatible with TLSv1.3 yet
4293 client_context.options |= ssl.OP_NO_TLSv1_3
Antoine Pitrou60a26e02013-07-20 19:35:16 +02004294
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004295 # first connection without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004296 stats = server_params_test(client_context, server_context,
4297 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004298 session = stats['session']
4299 self.assertTrue(session.id)
4300 self.assertGreater(session.time, 0)
4301 self.assertGreater(session.timeout, 0)
4302 self.assertTrue(session.has_ticket)
4303 if ssl.OPENSSL_VERSION_INFO > (1, 0, 1):
4304 self.assertGreater(session.ticket_lifetime_hint, 0)
4305 self.assertFalse(stats['session_reused'])
4306 sess_stat = server_context.session_stats()
4307 self.assertEqual(sess_stat['accept'], 1)
4308 self.assertEqual(sess_stat['hits'], 0)
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02004309
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004310 # reuse session
Christian Heimesa170fa12017-09-15 20:27:30 +02004311 stats = server_params_test(client_context, server_context,
4312 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004313 sess_stat = server_context.session_stats()
4314 self.assertEqual(sess_stat['accept'], 2)
4315 self.assertEqual(sess_stat['hits'], 1)
4316 self.assertTrue(stats['session_reused'])
4317 session2 = stats['session']
4318 self.assertEqual(session2.id, session.id)
4319 self.assertEqual(session2, session)
4320 self.assertIsNot(session2, session)
4321 self.assertGreaterEqual(session2.time, session.time)
4322 self.assertGreaterEqual(session2.timeout, session.timeout)
Christian Heimes99a65702016-09-10 23:44:53 +02004323
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004324 # another one without session
Christian Heimesa170fa12017-09-15 20:27:30 +02004325 stats = server_params_test(client_context, server_context,
4326 sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004327 self.assertFalse(stats['session_reused'])
4328 session3 = stats['session']
4329 self.assertNotEqual(session3.id, session.id)
4330 self.assertNotEqual(session3, session)
4331 sess_stat = server_context.session_stats()
4332 self.assertEqual(sess_stat['accept'], 3)
4333 self.assertEqual(sess_stat['hits'], 1)
Christian Heimes99a65702016-09-10 23:44:53 +02004334
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004335 # reuse session again
Christian Heimesa170fa12017-09-15 20:27:30 +02004336 stats = server_params_test(client_context, server_context,
4337 session=session, sni_name=hostname)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004338 self.assertTrue(stats['session_reused'])
4339 session4 = stats['session']
4340 self.assertEqual(session4.id, session.id)
4341 self.assertEqual(session4, session)
4342 self.assertGreaterEqual(session4.time, session.time)
4343 self.assertGreaterEqual(session4.timeout, session.timeout)
4344 sess_stat = server_context.session_stats()
4345 self.assertEqual(sess_stat['accept'], 4)
4346 self.assertEqual(sess_stat['hits'], 2)
Christian Heimes99a65702016-09-10 23:44:53 +02004347
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004348 def test_session_handling(self):
Christian Heimesa170fa12017-09-15 20:27:30 +02004349 client_context, server_context, hostname = testing_context()
4350 client_context2, _, _ = testing_context()
Christian Heimes99a65702016-09-10 23:44:53 +02004351
Christian Heimes05d9fe32018-02-27 08:55:39 +01004352 # TODO: session reuse does not work with TLSv1.3
Christian Heimesa170fa12017-09-15 20:27:30 +02004353 client_context.options |= ssl.OP_NO_TLSv1_3
4354 client_context2.options |= ssl.OP_NO_TLSv1_3
Christian Heimescb5b68a2017-09-07 18:07:00 -07004355
Christian Heimesa170fa12017-09-15 20:27:30 +02004356 server = ThreadedEchoServer(context=server_context, chatty=False)
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004357 with server:
Christian Heimesa170fa12017-09-15 20:27:30 +02004358 with client_context.wrap_socket(socket.socket(),
4359 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004360 # session is None before handshake
4361 self.assertEqual(s.session, None)
4362 self.assertEqual(s.session_reused, None)
4363 s.connect((HOST, server.port))
4364 session = s.session
4365 self.assertTrue(session)
4366 with self.assertRaises(TypeError) as e:
4367 s.session = object
Ned Deily4531ec72018-06-11 20:26:28 -04004368 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
Christian Heimes99a65702016-09-10 23:44:53 +02004369
Christian Heimesa170fa12017-09-15 20:27:30 +02004370 with client_context.wrap_socket(socket.socket(),
4371 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004372 s.connect((HOST, server.port))
4373 # cannot set session after handshake
4374 with self.assertRaises(ValueError) as e:
4375 s.session = session
4376 self.assertEqual(str(e.exception),
4377 'Cannot set session after handshake.')
Christian Heimes99a65702016-09-10 23:44:53 +02004378
Christian Heimesa170fa12017-09-15 20:27:30 +02004379 with client_context.wrap_socket(socket.socket(),
4380 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004381 # can set session before handshake and before the
4382 # connection was established
4383 s.session = session
4384 s.connect((HOST, server.port))
4385 self.assertEqual(s.session.id, session.id)
4386 self.assertEqual(s.session, session)
4387 self.assertEqual(s.session_reused, True)
Christian Heimes99a65702016-09-10 23:44:53 +02004388
Christian Heimesa170fa12017-09-15 20:27:30 +02004389 with client_context2.wrap_socket(socket.socket(),
4390 server_hostname=hostname) as s:
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004391 # cannot re-use session with a different SSLContext
4392 with self.assertRaises(ValueError) as e:
Christian Heimes99a65702016-09-10 23:44:53 +02004393 s.session = session
4394 s.connect((HOST, server.port))
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02004395 self.assertEqual(str(e.exception),
4396 'Session refers to a different SSLContext.')
Christian Heimes99a65702016-09-10 23:44:53 +02004397
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01004398
Christian Heimesdf6ac7e2019-09-26 17:02:59 +02004399@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
Christian Heimes9fb051f2018-09-23 08:32:31 +02004400class TestPostHandshakeAuth(unittest.TestCase):
4401 def test_pha_setter(self):
4402 protocols = [
4403 ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER, ssl.PROTOCOL_TLS_CLIENT
4404 ]
4405 for protocol in protocols:
4406 ctx = ssl.SSLContext(protocol)
4407 self.assertEqual(ctx.post_handshake_auth, False)
4408
4409 ctx.post_handshake_auth = True
4410 self.assertEqual(ctx.post_handshake_auth, True)
4411
4412 ctx.verify_mode = ssl.CERT_REQUIRED
4413 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4414 self.assertEqual(ctx.post_handshake_auth, True)
4415
4416 ctx.post_handshake_auth = False
4417 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
4418 self.assertEqual(ctx.post_handshake_auth, False)
4419
4420 ctx.verify_mode = ssl.CERT_OPTIONAL
4421 ctx.post_handshake_auth = True
4422 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
4423 self.assertEqual(ctx.post_handshake_auth, True)
4424
4425 def test_pha_required(self):
4426 client_context, server_context, hostname = testing_context()
4427 server_context.post_handshake_auth = True
4428 server_context.verify_mode = ssl.CERT_REQUIRED
4429 client_context.post_handshake_auth = True
4430 client_context.load_cert_chain(SIGNED_CERTFILE)
4431
4432 server = ThreadedEchoServer(context=server_context, chatty=False)
4433 with server:
4434 with client_context.wrap_socket(socket.socket(),
4435 server_hostname=hostname) as s:
4436 s.connect((HOST, server.port))
4437 s.write(b'HASCERT')
4438 self.assertEqual(s.recv(1024), b'FALSE\n')
4439 s.write(b'PHA')
4440 self.assertEqual(s.recv(1024), b'OK\n')
4441 s.write(b'HASCERT')
4442 self.assertEqual(s.recv(1024), b'TRUE\n')
4443 # PHA method just returns true when cert is already available
4444 s.write(b'PHA')
4445 self.assertEqual(s.recv(1024), b'OK\n')
4446 s.write(b'GETCERT')
4447 cert_text = s.recv(4096).decode('us-ascii')
4448 self.assertIn('Python Software Foundation CA', cert_text)
4449
4450 def test_pha_required_nocert(self):
4451 client_context, server_context, hostname = testing_context()
4452 server_context.post_handshake_auth = True
4453 server_context.verify_mode = ssl.CERT_REQUIRED
4454 client_context.post_handshake_auth = True
4455
Victor Stinner73ea5462019-07-09 14:33:49 +02004456 # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer
4457 # (it is only raised sometimes on Windows)
Hai Shie80697d2020-05-28 06:10:27 +08004458 with threading_helper.catch_threading_exception() as cm:
Victor Stinner73ea5462019-07-09 14:33:49 +02004459 server = ThreadedEchoServer(context=server_context, chatty=False)
4460 with server:
4461 with client_context.wrap_socket(socket.socket(),
4462 server_hostname=hostname) as s:
4463 s.connect((HOST, server.port))
4464 s.write(b'PHA')
4465 # receive CertificateRequest
4466 self.assertEqual(s.recv(1024), b'OK\n')
4467 # send empty Certificate + Finish
4468 s.write(b'HASCERT')
4469 # receive alert
4470 with self.assertRaisesRegex(
4471 ssl.SSLError,
4472 'tlsv13 alert certificate required'):
4473 s.recv(1024)
Christian Heimes9fb051f2018-09-23 08:32:31 +02004474
4475 def test_pha_optional(self):
4476 if support.verbose:
4477 sys.stdout.write("\n")
4478
4479 client_context, server_context, hostname = testing_context()
4480 server_context.post_handshake_auth = True
4481 server_context.verify_mode = ssl.CERT_REQUIRED
4482 client_context.post_handshake_auth = True
4483 client_context.load_cert_chain(SIGNED_CERTFILE)
4484
4485 # check CERT_OPTIONAL
4486 server_context.verify_mode = ssl.CERT_OPTIONAL
4487 server = ThreadedEchoServer(context=server_context, chatty=False)
4488 with server:
4489 with client_context.wrap_socket(socket.socket(),
4490 server_hostname=hostname) as s:
4491 s.connect((HOST, server.port))
4492 s.write(b'HASCERT')
4493 self.assertEqual(s.recv(1024), b'FALSE\n')
4494 s.write(b'PHA')
4495 self.assertEqual(s.recv(1024), b'OK\n')
4496 s.write(b'HASCERT')
4497 self.assertEqual(s.recv(1024), b'TRUE\n')
4498
4499 def test_pha_optional_nocert(self):
4500 if support.verbose:
4501 sys.stdout.write("\n")
4502
4503 client_context, server_context, hostname = testing_context()
4504 server_context.post_handshake_auth = True
4505 server_context.verify_mode = ssl.CERT_OPTIONAL
4506 client_context.post_handshake_auth = True
4507
4508 server = ThreadedEchoServer(context=server_context, chatty=False)
4509 with server:
4510 with client_context.wrap_socket(socket.socket(),
4511 server_hostname=hostname) as s:
4512 s.connect((HOST, server.port))
4513 s.write(b'HASCERT')
4514 self.assertEqual(s.recv(1024), b'FALSE\n')
4515 s.write(b'PHA')
4516 self.assertEqual(s.recv(1024), b'OK\n')
penguindustin96466302019-05-06 14:57:17 -04004517 # optional doesn't fail when client does not have a cert
Christian Heimes9fb051f2018-09-23 08:32:31 +02004518 s.write(b'HASCERT')
4519 self.assertEqual(s.recv(1024), b'FALSE\n')
4520
4521 def test_pha_no_pha_client(self):
4522 client_context, server_context, hostname = testing_context()
4523 server_context.post_handshake_auth = True
4524 server_context.verify_mode = ssl.CERT_REQUIRED
4525 client_context.load_cert_chain(SIGNED_CERTFILE)
4526
4527 server = ThreadedEchoServer(context=server_context, chatty=False)
4528 with server:
4529 with client_context.wrap_socket(socket.socket(),
4530 server_hostname=hostname) as s:
4531 s.connect((HOST, server.port))
4532 with self.assertRaisesRegex(ssl.SSLError, 'not server'):
4533 s.verify_client_post_handshake()
4534 s.write(b'PHA')
4535 self.assertIn(b'extension not received', s.recv(1024))
4536
4537 def test_pha_no_pha_server(self):
4538 # server doesn't have PHA enabled, cert is requested in handshake
4539 client_context, server_context, hostname = testing_context()
4540 server_context.verify_mode = ssl.CERT_REQUIRED
4541 client_context.post_handshake_auth = True
4542 client_context.load_cert_chain(SIGNED_CERTFILE)
4543
4544 server = ThreadedEchoServer(context=server_context, chatty=False)
4545 with server:
4546 with client_context.wrap_socket(socket.socket(),
4547 server_hostname=hostname) as s:
4548 s.connect((HOST, server.port))
4549 s.write(b'HASCERT')
4550 self.assertEqual(s.recv(1024), b'TRUE\n')
4551 # PHA doesn't fail if there is already a cert
4552 s.write(b'PHA')
4553 self.assertEqual(s.recv(1024), b'OK\n')
4554 s.write(b'HASCERT')
4555 self.assertEqual(s.recv(1024), b'TRUE\n')
4556
4557 def test_pha_not_tls13(self):
4558 # TLS 1.2
4559 client_context, server_context, hostname = testing_context()
4560 server_context.verify_mode = ssl.CERT_REQUIRED
4561 client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4562 client_context.post_handshake_auth = True
4563 client_context.load_cert_chain(SIGNED_CERTFILE)
4564
4565 server = ThreadedEchoServer(context=server_context, chatty=False)
4566 with server:
4567 with client_context.wrap_socket(socket.socket(),
4568 server_hostname=hostname) as s:
4569 s.connect((HOST, server.port))
4570 # PHA fails for TLS != 1.3
4571 s.write(b'PHA')
4572 self.assertIn(b'WRONG_SSL_VERSION', s.recv(1024))
4573
Christian Heimesf0f59302019-07-01 08:29:17 +02004574 def test_bpo37428_pha_cert_none(self):
4575 # verify that post_handshake_auth does not implicitly enable cert
4576 # validation.
4577 hostname = SIGNED_CERTFILE_HOSTNAME
4578 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4579 client_context.post_handshake_auth = True
4580 client_context.load_cert_chain(SIGNED_CERTFILE)
4581 # no cert validation and CA on client side
4582 client_context.check_hostname = False
4583 client_context.verify_mode = ssl.CERT_NONE
4584
4585 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
4586 server_context.load_cert_chain(SIGNED_CERTFILE)
4587 server_context.load_verify_locations(SIGNING_CA)
4588 server_context.post_handshake_auth = True
4589 server_context.verify_mode = ssl.CERT_REQUIRED
4590
4591 server = ThreadedEchoServer(context=server_context, chatty=False)
4592 with server:
4593 with client_context.wrap_socket(socket.socket(),
4594 server_hostname=hostname) as s:
4595 s.connect((HOST, server.port))
4596 s.write(b'HASCERT')
4597 self.assertEqual(s.recv(1024), b'FALSE\n')
4598 s.write(b'PHA')
4599 self.assertEqual(s.recv(1024), b'OK\n')
4600 s.write(b'HASCERT')
4601 self.assertEqual(s.recv(1024), b'TRUE\n')
4602 # server cert has not been validated
4603 self.assertEqual(s.getpeercert(), {})
4604
Christian Heimes9fb051f2018-09-23 08:32:31 +02004605
Christian Heimesc7f70692019-05-31 11:44:05 +02004606HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename')
4607requires_keylog = unittest.skipUnless(
4608 HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback')
4609
4610class TestSSLDebug(unittest.TestCase):
4611
Hai Shia7f5d932020-08-04 00:41:24 +08004612 def keylog_lines(self, fname=os_helper.TESTFN):
Christian Heimesc7f70692019-05-31 11:44:05 +02004613 with open(fname) as f:
4614 return len(list(f))
4615
4616 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004617 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004618 def test_keylog_defaults(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004619 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004620 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4621 self.assertEqual(ctx.keylog_filename, None)
4622
Hai Shia7f5d932020-08-04 00:41:24 +08004623 self.assertFalse(os.path.isfile(os_helper.TESTFN))
4624 ctx.keylog_filename = os_helper.TESTFN
4625 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
4626 self.assertTrue(os.path.isfile(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004627 self.assertEqual(self.keylog_lines(), 1)
4628
4629 ctx.keylog_filename = None
4630 self.assertEqual(ctx.keylog_filename, None)
4631
4632 with self.assertRaises((IsADirectoryError, PermissionError)):
4633 # Windows raises PermissionError
4634 ctx.keylog_filename = os.path.dirname(
Hai Shia7f5d932020-08-04 00:41:24 +08004635 os.path.abspath(os_helper.TESTFN))
Christian Heimesc7f70692019-05-31 11:44:05 +02004636
4637 with self.assertRaises(TypeError):
4638 ctx.keylog_filename = 1
4639
4640 @requires_keylog
Paul Monsonf3550692019-06-19 13:09:54 -07004641 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004642 def test_keylog_filename(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004643 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004644 client_context, server_context, hostname = testing_context()
4645
Hai Shia7f5d932020-08-04 00:41:24 +08004646 client_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004647 server = ThreadedEchoServer(context=server_context, chatty=False)
4648 with server:
4649 with client_context.wrap_socket(socket.socket(),
4650 server_hostname=hostname) as s:
4651 s.connect((HOST, server.port))
4652 # header, 5 lines for TLS 1.3
4653 self.assertEqual(self.keylog_lines(), 6)
4654
4655 client_context.keylog_filename = None
Hai Shia7f5d932020-08-04 00:41:24 +08004656 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004657 server = ThreadedEchoServer(context=server_context, chatty=False)
4658 with server:
4659 with client_context.wrap_socket(socket.socket(),
4660 server_hostname=hostname) as s:
4661 s.connect((HOST, server.port))
4662 self.assertGreaterEqual(self.keylog_lines(), 11)
4663
Hai Shia7f5d932020-08-04 00:41:24 +08004664 client_context.keylog_filename = os_helper.TESTFN
4665 server_context.keylog_filename = os_helper.TESTFN
Christian Heimesc7f70692019-05-31 11:44:05 +02004666 server = ThreadedEchoServer(context=server_context, chatty=False)
4667 with server:
4668 with client_context.wrap_socket(socket.socket(),
4669 server_hostname=hostname) as s:
4670 s.connect((HOST, server.port))
4671 self.assertGreaterEqual(self.keylog_lines(), 21)
4672
4673 client_context.keylog_filename = None
4674 server_context.keylog_filename = None
4675
4676 @requires_keylog
4677 @unittest.skipIf(sys.flags.ignore_environment,
4678 "test is not compatible with ignore_environment")
Paul Monsonf3550692019-06-19 13:09:54 -07004679 @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
Christian Heimesc7f70692019-05-31 11:44:05 +02004680 def test_keylog_env(self):
Hai Shia7f5d932020-08-04 00:41:24 +08004681 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004682 with unittest.mock.patch.dict(os.environ):
Hai Shia7f5d932020-08-04 00:41:24 +08004683 os.environ['SSLKEYLOGFILE'] = os_helper.TESTFN
4684 self.assertEqual(os.environ['SSLKEYLOGFILE'], os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004685
4686 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
4687 self.assertEqual(ctx.keylog_filename, None)
4688
4689 ctx = ssl.create_default_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 ctx = ssl._create_stdlib_context()
Hai Shia7f5d932020-08-04 00:41:24 +08004693 self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
Christian Heimesc7f70692019-05-31 11:44:05 +02004694
4695 def test_msg_callback(self):
4696 client_context, server_context, hostname = testing_context()
4697
4698 def msg_cb(conn, direction, version, content_type, msg_type, data):
4699 pass
4700
4701 self.assertIs(client_context._msg_callback, None)
4702 client_context._msg_callback = msg_cb
4703 self.assertIs(client_context._msg_callback, msg_cb)
4704 with self.assertRaises(TypeError):
4705 client_context._msg_callback = object()
4706
4707 def test_msg_callback_tls12(self):
4708 client_context, server_context, hostname = testing_context()
4709 client_context.options |= ssl.OP_NO_TLSv1_3
4710
4711 msg = []
4712
4713 def msg_cb(conn, direction, version, content_type, msg_type, data):
4714 self.assertIsInstance(conn, ssl.SSLSocket)
4715 self.assertIsInstance(data, bytes)
4716 self.assertIn(direction, {'read', 'write'})
4717 msg.append((direction, version, content_type, msg_type))
4718
4719 client_context._msg_callback = msg_cb
4720
4721 server = ThreadedEchoServer(context=server_context, chatty=False)
4722 with server:
4723 with client_context.wrap_socket(socket.socket(),
4724 server_hostname=hostname) as s:
4725 s.connect((HOST, server.port))
4726
Christian Heimese35d1ba2019-06-03 20:40:15 +02004727 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004728 ("read", TLSVersion.TLSv1_2, _TLSContentType.HANDSHAKE,
4729 _TLSMessageType.SERVER_KEY_EXCHANGE),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004730 msg
4731 )
4732 self.assertIn(
Christian Heimesc7f70692019-05-31 11:44:05 +02004733 ("write", TLSVersion.TLSv1_2, _TLSContentType.CHANGE_CIPHER_SPEC,
4734 _TLSMessageType.CHANGE_CIPHER_SPEC),
Christian Heimese35d1ba2019-06-03 20:40:15 +02004735 msg
4736 )
Christian Heimesc7f70692019-05-31 11:44:05 +02004737
4738
Thomas Woutersed03b412007-08-28 21:37:11 +00004739def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00004740 if support.verbose:
4741 plats = {
Antoine Pitrou15cee622010-08-04 16:45:21 +00004742 'Mac': platform.mac_ver,
4743 'Windows': platform.win32_ver,
4744 }
Petr Viktorin8b94b412018-05-16 11:51:18 -04004745 for name, func in plats.items():
4746 plat = func()
4747 if plat and plat[0]:
4748 plat = '%s %r' % (name, plat)
4749 break
4750 else:
4751 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00004752 print("test_ssl: testing with %r %r" %
4753 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
4754 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00004755 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01004756 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
4757 try:
4758 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
4759 except AttributeError:
4760 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00004761
Antoine Pitrou152efa22010-05-16 18:19:27 +00004762 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00004763 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004764 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01004765 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00004766 BADCERT, BADKEY, EMPTYCERT]:
4767 if not os.path.exists(filename):
4768 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004769
Martin Panter3840b2a2016-03-27 01:53:46 +00004770 tests = [
4771 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
Christian Heimes9d50ab52018-02-27 10:17:30 +01004772 SSLObjectTests, SimpleBackgroundTests, ThreadedTests,
Christian Heimesc7f70692019-05-31 11:44:05 +02004773 TestPostHandshakeAuth, TestSSLDebug
Martin Panter3840b2a2016-03-27 01:53:46 +00004774 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00004775
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004776 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00004777 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00004778
Hai Shie80697d2020-05-28 06:10:27 +08004779 thread_info = threading_helper.threading_setup()
Antoine Pitrou480a1242010-04-28 21:37:09 +00004780 try:
4781 support.run_unittest(*tests)
4782 finally:
Hai Shie80697d2020-05-28 06:10:27 +08004783 threading_helper.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00004784
4785if __name__ == "__main__":
4786 test_main()