blob: 8dcd3b613dd30895a78a0f6b489450199febccbb [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Christian Heimes9424bb42013-06-17 15:32:57 +02009import datetime
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000010import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000011import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000012import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000013import pprint
Antoine Pitrou803e6d62010-10-13 10:36:15 +000014import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Antoine Pitrou05d936d2010-10-13 11:38:36 +000021ssl = support.import_module("ssl")
22
Martin Panter3840b2a2016-03-27 01:53:46 +000023try:
24 import threading
25except ImportError:
26 _have_threads = False
27else:
28 _have_threads = True
29
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010030PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000031HOST = support.HOST
Christian Heimes598894f2016-09-05 23:19:05 +020032IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
33IS_OPENSSL_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0)
34
Antoine Pitrou152efa22010-05-16 18:19:27 +000035
Christian Heimesefff7062013-11-21 03:35:02 +010036def data_file(*name):
37 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038
Antoine Pitrou81564092010-10-08 23:06:24 +000039# The custom key and certificate files used in test_ssl are generated
40# using Lib/test/make_ssl_certs.py.
41# Other certificates are simply fetched from the Internet servers they
42# are meant to authenticate.
43
Antoine Pitrou152efa22010-05-16 18:19:27 +000044CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000045BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000046ONLYCERT = data_file("ssl_cert.pem")
47ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000048BYTES_ONLYCERT = os.fsencode(ONLYCERT)
49BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020050CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
51ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
52KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000053CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000054BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010055CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
56CAFILE_CACERT = data_file("capath", "5ed36f99.0")
57
Antoine Pitrou152efa22010-05-16 18:19:27 +000058
Christian Heimes22587792013-11-21 23:56:13 +010059# empty CRL
60CRLFILE = data_file("revocation.crl")
61
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010062# Two keys and certs signed by the same CA (for SNI tests)
63SIGNED_CERTFILE = data_file("keycert3.pem")
64SIGNED_CERTFILE2 = data_file("keycert4.pem")
Martin Panter3840b2a2016-03-27 01:53:46 +000065# Same certificate as pycacert.pem, but without extra text in file
66SIGNING_CA = data_file("capath", "ceff1710.0")
Christian Heimes1c03abd2016-09-06 23:25:35 +020067# cert with all kinds of subject alt names
68ALLSANFILE = data_file("allsans.pem")
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010069
Martin Panter3d81d932016-01-14 09:36:00 +000070REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +000071
72EMPTYCERT = data_file("nullcert.pem")
73BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +000074NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000075BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020076NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020077NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000078
Benjamin Petersona7eaf562015-04-02 00:04:06 -040079DHFILE = data_file("dh1024.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +010080BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000081
Christian Heimes358cfd42016-09-10 22:43:48 +020082# Not defined in all versions of OpenSSL
83OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0)
84OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0)
85OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0)
86OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0)
87
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010088
Thomas Woutersed03b412007-08-28 21:37:11 +000089def handle_error(prefix):
90 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000091 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000092 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000093
Antoine Pitroub5218772010-05-21 09:56:06 +000094def can_clear_options():
95 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020096 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000097
98def no_sslv2_implies_sslv3_hello():
99 # 0.9.7h or higher
100 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
101
Christian Heimes2427b502013-11-23 11:24:32 +0100102def have_verify_flags():
103 # 0.9.8 or higher
104 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
105
Antoine Pitrouc695c952014-04-28 20:57:36 +0200106def utc_offset(): #NOTE: ignore issues like #1647654
107 # local time = utc time + utc offset
108 if time.daylight and time.localtime().tm_isdst > 0:
109 return -time.altzone # seconds
110 return -time.timezone
111
Christian Heimes9424bb42013-06-17 15:32:57 +0200112def asn1time(cert_time):
113 # Some versions of OpenSSL ignore seconds, see #18207
114 # 0.9.8.i
115 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
116 fmt = "%b %d %H:%M:%S %Y GMT"
117 dt = datetime.datetime.strptime(cert_time, fmt)
118 dt = dt.replace(second=0)
119 cert_time = dt.strftime(fmt)
120 # %d adds leading zero but ASN1_TIME_print() uses leading space
121 if cert_time[4] == "0":
122 cert_time = cert_time[:4] + " " + cert_time[5:]
123
124 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000125
Antoine Pitrou23df4832010-08-04 17:14:06 +0000126# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
127def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +0200128 if hasattr(ssl, 'PROTOCOL_SSLv2'):
129 @functools.wraps(func)
130 def f(*args, **kwargs):
131 try:
132 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
133 except ssl.SSLError:
134 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
135 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
136 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
137 return func(*args, **kwargs)
138 return f
139 else:
140 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +0000141
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100142needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
143
Antoine Pitrou23df4832010-08-04 17:14:06 +0000144
Christian Heimesd0486372016-09-10 23:23:33 +0200145def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLS, *,
146 cert_reqs=ssl.CERT_NONE, ca_certs=None,
147 ciphers=None, certfile=None, keyfile=None,
148 **kwargs):
149 context = ssl.SSLContext(ssl_version)
150 if cert_reqs is not None:
151 context.verify_mode = cert_reqs
152 if ca_certs is not None:
153 context.load_verify_locations(ca_certs)
154 if certfile is not None or keyfile is not None:
155 context.load_cert_chain(certfile, keyfile)
156 if ciphers is not None:
157 context.set_ciphers(ciphers)
158 return context.wrap_socket(sock, **kwargs)
159
Antoine Pitrou152efa22010-05-16 18:19:27 +0000160class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000161
Antoine Pitrou480a1242010-04-28 21:37:09 +0000162 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000163 ssl.CERT_NONE
164 ssl.CERT_OPTIONAL
165 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100166 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100167 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100168 if ssl.HAS_ECDH:
169 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100170 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
171 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000172 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100173 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000174
Antoine Pitrou172f0252014-04-18 20:33:08 +0200175 def test_str_for_enums(self):
176 # Make sure that the PROTOCOL_* constants have enum-like string
177 # reprs.
Christian Heimes598894f2016-09-05 23:19:05 +0200178 proto = ssl.PROTOCOL_TLS
179 self.assertEqual(str(proto), '_SSLMethod.PROTOCOL_TLS')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200180 ctx = ssl.SSLContext(proto)
181 self.assertIs(ctx.protocol, proto)
182
Antoine Pitrou480a1242010-04-28 21:37:09 +0000183 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000184 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000185 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000186 sys.stdout.write("\n RAND_status is %d (%s)\n"
187 % (v, (v and "sufficient randomness") or
188 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200189
190 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
191 self.assertEqual(len(data), 16)
192 self.assertEqual(is_cryptographic, v == 1)
193 if v:
194 data = ssl.RAND_bytes(16)
195 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200196 else:
197 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200198
Victor Stinner1e81a392013-12-19 16:47:04 +0100199 # negative num is invalid
200 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
201 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
202
Victor Stinnerbeeb5122014-11-28 13:28:25 +0100203 if hasattr(ssl, 'RAND_egd'):
204 self.assertRaises(TypeError, ssl.RAND_egd, 1)
205 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000206 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200207 ssl.RAND_add(b"this is a random bytes object", 75.0)
208 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000209
Christian Heimesf77b4b22013-08-21 13:26:05 +0200210 @unittest.skipUnless(os.name == 'posix', 'requires posix')
211 def test_random_fork(self):
212 status = ssl.RAND_status()
213 if not status:
214 self.fail("OpenSSL's PRNG has insufficient randomness")
215
216 rfd, wfd = os.pipe()
217 pid = os.fork()
218 if pid == 0:
219 try:
220 os.close(rfd)
221 child_random = ssl.RAND_pseudo_bytes(16)[0]
222 self.assertEqual(len(child_random), 16)
223 os.write(wfd, child_random)
224 os.close(wfd)
225 except BaseException:
226 os._exit(1)
227 else:
228 os._exit(0)
229 else:
230 os.close(wfd)
231 self.addCleanup(os.close, rfd)
232 _, status = os.waitpid(pid, 0)
233 self.assertEqual(status, 0)
234
235 child_random = os.read(rfd, 16)
236 self.assertEqual(len(child_random), 16)
237 parent_random = ssl.RAND_pseudo_bytes(16)[0]
238 self.assertEqual(len(parent_random), 16)
239
240 self.assertNotEqual(child_random, parent_random)
241
Antoine Pitrou480a1242010-04-28 21:37:09 +0000242 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000243 # note that this uses an 'unofficial' function in _ssl.c,
244 # provided solely for this test, to exercise the certificate
245 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000246 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000247 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000248 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200249 self.assertEqual(p['issuer'],
250 ((('countryName', 'XY'),),
251 (('localityName', 'Castle Anthrax'),),
252 (('organizationName', 'Python Software Foundation'),),
253 (('commonName', 'localhost'),))
254 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100255 # Note the next three asserts will fail if the keys are regenerated
Christian Heimes9424bb42013-06-17 15:32:57 +0200256 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
257 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200258 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
259 self.assertEqual(p['subject'],
260 ((('countryName', 'XY'),),
261 (('localityName', 'Castle Anthrax'),),
262 (('organizationName', 'Python Software Foundation'),),
263 (('commonName', 'localhost'),))
264 )
265 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
266 # Issue #13034: the subjectAltName in some certificates
267 # (notably projects.developer.nokia.com:443) wasn't parsed
268 p = ssl._ssl._test_decode_cert(NOKIACERT)
269 if support.verbose:
270 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
271 self.assertEqual(p['subjectAltName'],
272 (('DNS', 'projects.developer.nokia.com'),
273 ('DNS', 'projects.forum.nokia.com'))
274 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100275 # extra OCSP and AIA fields
276 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
277 self.assertEqual(p['caIssuers'],
278 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
279 self.assertEqual(p['crlDistributionPoints'],
280 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000281
Christian Heimes824f7f32013-08-17 00:54:47 +0200282 def test_parse_cert_CVE_2013_4238(self):
283 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
284 if support.verbose:
285 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
286 subject = ((('countryName', 'US'),),
287 (('stateOrProvinceName', 'Oregon'),),
288 (('localityName', 'Beaverton'),),
289 (('organizationName', 'Python Software Foundation'),),
290 (('organizationalUnitName', 'Python Core Development'),),
291 (('commonName', 'null.python.org\x00example.org'),),
292 (('emailAddress', 'python-dev@python.org'),))
293 self.assertEqual(p['subject'], subject)
294 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200295 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
296 san = (('DNS', 'altnull.python.org\x00example.com'),
297 ('email', 'null@python.org\x00user@example.org'),
298 ('URI', 'http://null.python.org\x00http://example.org'),
299 ('IP Address', '192.0.2.1'),
300 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
301 else:
302 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
303 san = (('DNS', 'altnull.python.org\x00example.com'),
304 ('email', 'null@python.org\x00user@example.org'),
305 ('URI', 'http://null.python.org\x00http://example.org'),
306 ('IP Address', '192.0.2.1'),
307 ('IP Address', '<invalid>'))
308
309 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200310
Christian Heimes1c03abd2016-09-06 23:25:35 +0200311 def test_parse_all_sans(self):
312 p = ssl._ssl._test_decode_cert(ALLSANFILE)
313 self.assertEqual(p['subjectAltName'],
314 (
315 ('DNS', 'allsans'),
316 ('othername', '<unsupported>'),
317 ('othername', '<unsupported>'),
318 ('email', 'user@example.org'),
319 ('DNS', 'www.example.org'),
320 ('DirName',
321 ((('countryName', 'XY'),),
322 (('localityName', 'Castle Anthrax'),),
323 (('organizationName', 'Python Software Foundation'),),
324 (('commonName', 'dirname example'),))),
325 ('URI', 'https://www.python.org/'),
326 ('IP Address', '127.0.0.1'),
327 ('IP Address', '0:0:0:0:0:0:0:1\n'),
328 ('Registered ID', '1.2.3.4.5')
329 )
330 )
331
Antoine Pitrou480a1242010-04-28 21:37:09 +0000332 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000333 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000334 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000335 d1 = ssl.PEM_cert_to_DER_cert(pem)
336 p2 = ssl.DER_cert_to_PEM_cert(d1)
337 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000338 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000339 if not p2.startswith(ssl.PEM_HEADER + '\n'):
340 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
341 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
342 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000343
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000344 def test_openssl_version(self):
345 n = ssl.OPENSSL_VERSION_NUMBER
346 t = ssl.OPENSSL_VERSION_INFO
347 s = ssl.OPENSSL_VERSION
348 self.assertIsInstance(n, int)
349 self.assertIsInstance(t, tuple)
350 self.assertIsInstance(s, str)
351 # Some sanity checks follow
352 # >= 0.9
353 self.assertGreaterEqual(n, 0x900000)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400354 # < 3.0
355 self.assertLess(n, 0x30000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000356 major, minor, fix, patch, status = t
357 self.assertGreaterEqual(major, 0)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400358 self.assertLess(major, 3)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000359 self.assertGreaterEqual(minor, 0)
360 self.assertLess(minor, 256)
361 self.assertGreaterEqual(fix, 0)
362 self.assertLess(fix, 256)
363 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100364 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000365 self.assertGreaterEqual(status, 0)
366 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400367 # Version string as returned by {Open,Libre}SSL, the format might change
Christian Heimes598894f2016-09-05 23:19:05 +0200368 if IS_LIBRESSL:
369 self.assertTrue(s.startswith("LibreSSL {:d}".format(major)),
Victor Stinner789b8052015-01-06 11:51:06 +0100370 (s, t, hex(n)))
Antoine Pitroudfab9352014-07-21 18:35:01 -0400371 else:
372 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
Victor Stinner789b8052015-01-06 11:51:06 +0100373 (s, t, hex(n)))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000374
Antoine Pitrou9d543662010-04-23 23:10:32 +0000375 @support.cpython_only
376 def test_refcycle(self):
377 # Issue #7943: an SSL object doesn't create reference cycles with
378 # itself.
379 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200380 ss = test_wrap_socket(s)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000381 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100382 with support.check_warnings(("", ResourceWarning)):
383 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100384 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000385
Antoine Pitroua468adc2010-09-14 14:43:44 +0000386 def test_wrapped_unconnected(self):
387 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200388 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000389 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200390 with test_wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100391 self.assertRaises(OSError, ss.recv, 1)
392 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
393 self.assertRaises(OSError, ss.recvfrom, 1)
394 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
395 self.assertRaises(OSError, ss.send, b'x')
396 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000397
Antoine Pitrou40f08742010-04-24 22:04:40 +0000398 def test_timeout(self):
399 # Issue #8524: when creating an SSL socket, the timeout of the
400 # original socket should be retained.
401 for timeout in (None, 0.0, 5.0):
402 s = socket.socket(socket.AF_INET)
403 s.settimeout(timeout)
Christian Heimesd0486372016-09-10 23:23:33 +0200404 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100405 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000406
Christian Heimesd0486372016-09-10 23:23:33 +0200407 def test_errors_sslwrap(self):
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000408 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000409 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000410 "certfile must be specified",
411 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000412 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000413 "certfile must be specified for server-side operations",
414 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000415 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000416 "certfile must be specified for server-side operations",
Christian Heimesd0486372016-09-10 23:23:33 +0200417 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100418 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
419 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Christian Heimesd0486372016-09-10 23:23:33 +0200420 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200421 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000422 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000423 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000424 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200425 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000426 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000427 ssl.wrap_socket(sock,
428 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000429 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200430 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000431 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000432 ssl.wrap_socket(sock,
433 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000434 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000435
Martin Panter3464ea22016-02-01 21:58:11 +0000436 def bad_cert_test(self, certfile):
437 """Check that trying to use the given client certificate fails"""
438 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
439 certfile)
440 sock = socket.socket()
441 self.addCleanup(sock.close)
442 with self.assertRaises(ssl.SSLError):
Christian Heimesd0486372016-09-10 23:23:33 +0200443 test_wrap_socket(sock,
Martin Panter3464ea22016-02-01 21:58:11 +0000444 certfile=certfile,
445 ssl_version=ssl.PROTOCOL_TLSv1)
446
447 def test_empty_cert(self):
448 """Wrapping with an empty cert file"""
449 self.bad_cert_test("nullcert.pem")
450
451 def test_malformed_cert(self):
452 """Wrapping with a badly formatted certificate (syntax error)"""
453 self.bad_cert_test("badcert.pem")
454
455 def test_malformed_key(self):
456 """Wrapping with a badly formatted key (syntax error)"""
457 self.bad_cert_test("badkey.pem")
458
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000459 def test_match_hostname(self):
460 def ok(cert, hostname):
461 ssl.match_hostname(cert, hostname)
462 def fail(cert, hostname):
463 self.assertRaises(ssl.CertificateError,
464 ssl.match_hostname, cert, hostname)
465
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100466 # -- Hostname matching --
467
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000468 cert = {'subject': ((('commonName', 'example.com'),),)}
469 ok(cert, 'example.com')
470 ok(cert, 'ExAmple.cOm')
471 fail(cert, 'www.example.com')
472 fail(cert, '.example.com')
473 fail(cert, 'example.org')
474 fail(cert, 'exampleXcom')
475
476 cert = {'subject': ((('commonName', '*.a.com'),),)}
477 ok(cert, 'foo.a.com')
478 fail(cert, 'bar.foo.a.com')
479 fail(cert, 'a.com')
480 fail(cert, 'Xa.com')
481 fail(cert, '.a.com')
482
Georg Brandl72c98d32013-10-27 07:16:53 +0100483 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000484 cert = {'subject': ((('commonName', 'f*.com'),),)}
485 ok(cert, 'foo.com')
486 ok(cert, 'f.com')
487 fail(cert, 'bar.com')
488 fail(cert, 'foo.a.com')
489 fail(cert, 'bar.foo.com')
490
Christian Heimes824f7f32013-08-17 00:54:47 +0200491 # NULL bytes are bad, CVE-2013-4073
492 cert = {'subject': ((('commonName',
493 'null.python.org\x00example.org'),),)}
494 ok(cert, 'null.python.org\x00example.org') # or raise an error?
495 fail(cert, 'example.org')
496 fail(cert, 'null.python.org')
497
Georg Brandl72c98d32013-10-27 07:16:53 +0100498 # error cases with wildcards
499 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
500 fail(cert, 'bar.foo.a.com')
501 fail(cert, 'a.com')
502 fail(cert, 'Xa.com')
503 fail(cert, '.a.com')
504
505 cert = {'subject': ((('commonName', 'a.*.com'),),)}
506 fail(cert, 'a.foo.com')
507 fail(cert, 'a..com')
508 fail(cert, 'a.com')
509
510 # wildcard doesn't match IDNA prefix 'xn--'
511 idna = 'püthon.python.org'.encode("idna").decode("ascii")
512 cert = {'subject': ((('commonName', idna),),)}
513 ok(cert, idna)
514 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
515 fail(cert, idna)
516 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
517 fail(cert, idna)
518
519 # wildcard in first fragment and IDNA A-labels in sequent fragments
520 # are supported.
521 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
522 cert = {'subject': ((('commonName', idna),),)}
523 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
524 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
525 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
526 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
527
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000528 # Slightly fake real-world example
529 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
530 'subject': ((('commonName', 'linuxfrz.org'),),),
531 'subjectAltName': (('DNS', 'linuxfr.org'),
532 ('DNS', 'linuxfr.com'),
533 ('othername', '<unsupported>'))}
534 ok(cert, 'linuxfr.org')
535 ok(cert, 'linuxfr.com')
536 # Not a "DNS" entry
537 fail(cert, '<unsupported>')
538 # When there is a subjectAltName, commonName isn't used
539 fail(cert, 'linuxfrz.org')
540
541 # A pristine real-world example
542 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
543 'subject': ((('countryName', 'US'),),
544 (('stateOrProvinceName', 'California'),),
545 (('localityName', 'Mountain View'),),
546 (('organizationName', 'Google Inc'),),
547 (('commonName', 'mail.google.com'),))}
548 ok(cert, 'mail.google.com')
549 fail(cert, 'gmail.com')
550 # Only commonName is considered
551 fail(cert, 'California')
552
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100553 # -- IPv4 matching --
554 cert = {'subject': ((('commonName', 'example.com'),),),
555 'subjectAltName': (('DNS', 'example.com'),
556 ('IP Address', '10.11.12.13'),
557 ('IP Address', '14.15.16.17'))}
558 ok(cert, '10.11.12.13')
559 ok(cert, '14.15.16.17')
560 fail(cert, '14.15.16.18')
561 fail(cert, 'example.net')
562
563 # -- IPv6 matching --
564 cert = {'subject': ((('commonName', 'example.com'),),),
565 'subjectAltName': (('DNS', 'example.com'),
566 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
567 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
568 ok(cert, '2001::cafe')
569 ok(cert, '2003::baba')
570 fail(cert, '2003::bebe')
571 fail(cert, 'example.net')
572
573 # -- Miscellaneous --
574
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000575 # Neither commonName nor subjectAltName
576 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
577 'subject': ((('countryName', 'US'),),
578 (('stateOrProvinceName', 'California'),),
579 (('localityName', 'Mountain View'),),
580 (('organizationName', 'Google Inc'),))}
581 fail(cert, 'mail.google.com')
582
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200583 # No DNS entry in subjectAltName but a commonName
584 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
585 'subject': ((('countryName', 'US'),),
586 (('stateOrProvinceName', 'California'),),
587 (('localityName', 'Mountain View'),),
588 (('commonName', 'mail.google.com'),)),
589 'subjectAltName': (('othername', 'blabla'), )}
590 ok(cert, 'mail.google.com')
591
592 # No DNS entry subjectAltName and no commonName
593 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
594 'subject': ((('countryName', 'US'),),
595 (('stateOrProvinceName', 'California'),),
596 (('localityName', 'Mountain View'),),
597 (('organizationName', 'Google Inc'),)),
598 'subjectAltName': (('othername', 'blabla'),)}
599 fail(cert, 'google.com')
600
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000601 # Empty cert / no cert
602 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
603 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
604
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200605 # Issue #17980: avoid denials of service by refusing more than one
606 # wildcard per fragment.
607 cert = {'subject': ((('commonName', 'a*b.com'),),)}
608 ok(cert, 'axxb.com')
609 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100610 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200611 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
612 with self.assertRaises(ssl.CertificateError) as cm:
613 ssl.match_hostname(cert, 'axxbxxc.com')
614 self.assertIn("too many wildcards", str(cm.exception))
615
Antoine Pitroud5323212010-10-22 18:19:07 +0000616 def test_server_side(self):
617 # server_hostname doesn't work for server sockets
618 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000619 with socket.socket() as sock:
620 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
621 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000622
Antoine Pitroud6494802011-07-21 01:11:30 +0200623 def test_unknown_channel_binding(self):
624 # should raise ValueError for unknown type
625 s = socket.socket(socket.AF_INET)
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200626 s.bind(('127.0.0.1', 0))
627 s.listen()
628 c = socket.socket(socket.AF_INET)
629 c.connect(s.getsockname())
Christian Heimesd0486372016-09-10 23:23:33 +0200630 with test_wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100631 with self.assertRaises(ValueError):
632 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200633 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200634
635 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
636 "'tls-unique' channel binding not available")
637 def test_tls_unique_channel_binding(self):
638 # unconnected should return None for known type
639 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200640 with test_wrap_socket(s) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100641 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200642 # the same for server-side
643 s = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +0200644 with test_wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100645 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200646
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600647 def test_dealloc_warn(self):
Christian Heimesd0486372016-09-10 23:23:33 +0200648 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600649 r = repr(ss)
650 with self.assertWarns(ResourceWarning) as cm:
651 ss = None
652 support.gc_collect()
653 self.assertIn(r, str(cm.warning.args[0]))
654
Christian Heimes6d7ad132013-06-09 18:02:55 +0200655 def test_get_default_verify_paths(self):
656 paths = ssl.get_default_verify_paths()
657 self.assertEqual(len(paths), 6)
658 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
659
660 with support.EnvironmentVarGuard() as env:
661 env["SSL_CERT_DIR"] = CAPATH
662 env["SSL_CERT_FILE"] = CERTFILE
663 paths = ssl.get_default_verify_paths()
664 self.assertEqual(paths.cafile, CERTFILE)
665 self.assertEqual(paths.capath, CAPATH)
666
Christian Heimes44109d72013-11-22 01:51:30 +0100667 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
668 def test_enum_certificates(self):
669 self.assertTrue(ssl.enum_certificates("CA"))
670 self.assertTrue(ssl.enum_certificates("ROOT"))
671
672 self.assertRaises(TypeError, ssl.enum_certificates)
673 self.assertRaises(WindowsError, ssl.enum_certificates, "")
674
Christian Heimesc2d65e12013-11-22 16:13:55 +0100675 trust_oids = set()
676 for storename in ("CA", "ROOT"):
677 store = ssl.enum_certificates(storename)
678 self.assertIsInstance(store, list)
679 for element in store:
680 self.assertIsInstance(element, tuple)
681 self.assertEqual(len(element), 3)
682 cert, enc, trust = element
683 self.assertIsInstance(cert, bytes)
684 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
685 self.assertIsInstance(trust, (set, bool))
686 if isinstance(trust, set):
687 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100688
689 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100690 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200691
Christian Heimes46bebee2013-06-09 19:03:31 +0200692 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100693 def test_enum_crls(self):
694 self.assertTrue(ssl.enum_crls("CA"))
695 self.assertRaises(TypeError, ssl.enum_crls)
696 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200697
Christian Heimes44109d72013-11-22 01:51:30 +0100698 crls = ssl.enum_crls("CA")
699 self.assertIsInstance(crls, list)
700 for element in crls:
701 self.assertIsInstance(element, tuple)
702 self.assertEqual(len(element), 2)
703 self.assertIsInstance(element[0], bytes)
704 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200705
Christian Heimes46bebee2013-06-09 19:03:31 +0200706
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100707 def test_asn1object(self):
708 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
709 '1.3.6.1.5.5.7.3.1')
710
711 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
712 self.assertEqual(val, expected)
713 self.assertEqual(val.nid, 129)
714 self.assertEqual(val.shortname, 'serverAuth')
715 self.assertEqual(val.longname, 'TLS Web Server Authentication')
716 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
717 self.assertIsInstance(val, ssl._ASN1Object)
718 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
719
720 val = ssl._ASN1Object.fromnid(129)
721 self.assertEqual(val, expected)
722 self.assertIsInstance(val, ssl._ASN1Object)
723 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100724 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
725 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100726 for i in range(1000):
727 try:
728 obj = ssl._ASN1Object.fromnid(i)
729 except ValueError:
730 pass
731 else:
732 self.assertIsInstance(obj.nid, int)
733 self.assertIsInstance(obj.shortname, str)
734 self.assertIsInstance(obj.longname, str)
735 self.assertIsInstance(obj.oid, (str, type(None)))
736
737 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
738 self.assertEqual(val, expected)
739 self.assertIsInstance(val, ssl._ASN1Object)
740 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
741 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
742 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100743 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
744 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100745
Christian Heimes72d28502013-11-23 13:56:58 +0100746 def test_purpose_enum(self):
747 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
748 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
749 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
750 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
751 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
752 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
753 '1.3.6.1.5.5.7.3.1')
754
755 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
756 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
757 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
758 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
759 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
760 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
761 '1.3.6.1.5.5.7.3.2')
762
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100763 def test_unsupported_dtls(self):
764 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
765 self.addCleanup(s.close)
766 with self.assertRaises(NotImplementedError) as cx:
Christian Heimesd0486372016-09-10 23:23:33 +0200767 test_wrap_socket(s, cert_reqs=ssl.CERT_NONE)
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100768 self.assertEqual(str(cx.exception), "only stream sockets are supported")
769 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
770 with self.assertRaises(NotImplementedError) as cx:
771 ctx.wrap_socket(s)
772 self.assertEqual(str(cx.exception), "only stream sockets are supported")
773
Antoine Pitrouc695c952014-04-28 20:57:36 +0200774 def cert_time_ok(self, timestring, timestamp):
775 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
776
777 def cert_time_fail(self, timestring):
778 with self.assertRaises(ValueError):
779 ssl.cert_time_to_seconds(timestring)
780
781 @unittest.skipUnless(utc_offset(),
782 'local time needs to be different from UTC')
783 def test_cert_time_to_seconds_timezone(self):
784 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
785 # results if local timezone is not UTC
786 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
787 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
788
789 def test_cert_time_to_seconds(self):
790 timestring = "Jan 5 09:34:43 2018 GMT"
791 ts = 1515144883.0
792 self.cert_time_ok(timestring, ts)
793 # accept keyword parameter, assert its name
794 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
795 # accept both %e and %d (space or zero generated by strftime)
796 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
797 # case-insensitive
798 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
799 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
800 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
801 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
802 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
803 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
804 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
805 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
806
807 newyear_ts = 1230768000.0
808 # leap seconds
809 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
810 # same timestamp
811 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
812
813 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
814 # allow 60th second (even if it is not a leap second)
815 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
816 # allow 2nd leap second for compatibility with time.strptime()
817 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
818 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
819
820 # no special treatement for the special value:
821 # 99991231235959Z (rfc 5280)
822 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
823
824 @support.run_with_locale('LC_ALL', '')
825 def test_cert_time_to_seconds_locale(self):
826 # `cert_time_to_seconds()` should be locale independent
827
828 def local_february_name():
829 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
830
831 if local_february_name().lower() == 'feb':
832 self.skipTest("locale-specific month name needs to be "
833 "different from C locale")
834
835 # locale-independent
836 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
837 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
838
Martin Panter3840b2a2016-03-27 01:53:46 +0000839 def test_connect_ex_error(self):
840 server = socket.socket(socket.AF_INET)
841 self.addCleanup(server.close)
842 port = support.bind_port(server) # Reserve port but don't listen
Christian Heimesd0486372016-09-10 23:23:33 +0200843 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +0000844 cert_reqs=ssl.CERT_REQUIRED)
845 self.addCleanup(s.close)
846 rc = s.connect_ex((HOST, port))
847 # Issue #19919: Windows machines or VMs hosted on Windows
848 # machines sometimes return EWOULDBLOCK.
849 errors = (
850 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
851 errno.EWOULDBLOCK,
852 )
853 self.assertIn(rc, errors)
854
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100855
Antoine Pitrou152efa22010-05-16 18:19:27 +0000856class ContextTests(unittest.TestCase):
857
Antoine Pitrou23df4832010-08-04 17:14:06 +0000858 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000859 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100860 for protocol in PROTOCOLS:
861 ssl.SSLContext(protocol)
Christian Heimes598894f2016-09-05 23:19:05 +0200862 ctx = ssl.SSLContext()
863 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000864 self.assertRaises(ValueError, ssl.SSLContext, -1)
865 self.assertRaises(ValueError, ssl.SSLContext, 42)
866
Antoine Pitrou23df4832010-08-04 17:14:06 +0000867 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000868 def test_protocol(self):
869 for proto in PROTOCOLS:
870 ctx = ssl.SSLContext(proto)
871 self.assertEqual(ctx.protocol, proto)
872
873 def test_ciphers(self):
874 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
875 ctx.set_ciphers("ALL")
876 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000877 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000878 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000879
Christian Heimes25bfcd52016-09-06 00:04:45 +0200880 @unittest.skipIf(ssl.OPENSSL_VERSION_INFO < (1, 0, 2, 0, 0), 'OpenSSL too old')
881 def test_get_ciphers(self):
882 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Christian Heimesea9b2dc2016-09-06 10:45:44 +0200883 ctx.set_ciphers('AESGCM')
Christian Heimes25bfcd52016-09-06 00:04:45 +0200884 names = set(d['name'] for d in ctx.get_ciphers())
Christian Heimes582282b2016-09-06 11:27:25 +0200885 self.assertIn('AES256-GCM-SHA384', names)
886 self.assertIn('AES128-GCM-SHA256', names)
Christian Heimes25bfcd52016-09-06 00:04:45 +0200887
Antoine Pitrou23df4832010-08-04 17:14:06 +0000888 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000889 def test_options(self):
890 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -0800891 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Christian Heimes598894f2016-09-05 23:19:05 +0200892 default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
Christian Heimes358cfd42016-09-10 22:43:48 +0200893 # SSLContext also enables these by default
894 default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE |
895 OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE)
Christian Heimes598894f2016-09-05 23:19:05 +0200896 self.assertEqual(default, ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -0800897 ctx.options |= ssl.OP_NO_TLSv1
Christian Heimes598894f2016-09-05 23:19:05 +0200898 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +0000899 if can_clear_options():
Christian Heimes598894f2016-09-05 23:19:05 +0200900 ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
901 self.assertEqual(default, ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +0000902 ctx.options = 0
Matthias Klosef7c56242016-06-12 23:40:00 -0700903 # Ubuntu has OP_NO_SSLv3 forced on by default
904 self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
Antoine Pitroub5218772010-05-21 09:56:06 +0000905 else:
906 with self.assertRaises(ValueError):
907 ctx.options = 0
908
Christian Heimes22587792013-11-21 23:56:13 +0100909 def test_verify_mode(self):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000910 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
911 # Default value
912 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
913 ctx.verify_mode = ssl.CERT_OPTIONAL
914 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
915 ctx.verify_mode = ssl.CERT_REQUIRED
916 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
917 ctx.verify_mode = ssl.CERT_NONE
918 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
919 with self.assertRaises(TypeError):
920 ctx.verify_mode = None
921 with self.assertRaises(ValueError):
922 ctx.verify_mode = 42
923
Christian Heimes2427b502013-11-23 11:24:32 +0100924 @unittest.skipUnless(have_verify_flags(),
925 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +0100926 def test_verify_flags(self):
927 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -0500928 # default value
929 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
930 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +0100931 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
932 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
933 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
934 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
935 ctx.verify_flags = ssl.VERIFY_DEFAULT
936 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
937 # supports any value
938 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
939 self.assertEqual(ctx.verify_flags,
940 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
941 with self.assertRaises(TypeError):
942 ctx.verify_flags = None
943
Antoine Pitrou152efa22010-05-16 18:19:27 +0000944 def test_load_cert_chain(self):
945 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
946 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -0500947 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000948 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
949 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200950 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +0000951 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000952 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000953 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000954 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000955 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000956 ctx.load_cert_chain(EMPTYCERT)
957 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000958 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000959 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
960 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
961 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000962 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000963 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000964 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000965 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000966 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000967 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
968 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000969 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000970 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +0000971 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200972 # Password protected key and cert
973 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
974 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
975 ctx.load_cert_chain(CERTFILE_PROTECTED,
976 password=bytearray(KEY_PASSWORD.encode()))
977 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
978 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
979 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
980 bytearray(KEY_PASSWORD.encode()))
981 with self.assertRaisesRegex(TypeError, "should be a string"):
982 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
983 with self.assertRaises(ssl.SSLError):
984 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
985 with self.assertRaisesRegex(ValueError, "cannot be longer"):
986 # openssl has a fixed limit on the password buffer.
987 # PEM_BUFSIZE is generally set to 1kb.
988 # Return a string larger than this.
989 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
990 # Password callback
991 def getpass_unicode():
992 return KEY_PASSWORD
993 def getpass_bytes():
994 return KEY_PASSWORD.encode()
995 def getpass_bytearray():
996 return bytearray(KEY_PASSWORD.encode())
997 def getpass_badpass():
998 return "badpass"
999 def getpass_huge():
1000 return b'a' * (1024 * 1024)
1001 def getpass_bad_type():
1002 return 9
1003 def getpass_exception():
1004 raise Exception('getpass error')
1005 class GetPassCallable:
1006 def __call__(self):
1007 return KEY_PASSWORD
1008 def getpass(self):
1009 return KEY_PASSWORD
1010 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
1011 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
1012 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
1013 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
1014 ctx.load_cert_chain(CERTFILE_PROTECTED,
1015 password=GetPassCallable().getpass)
1016 with self.assertRaises(ssl.SSLError):
1017 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
1018 with self.assertRaisesRegex(ValueError, "cannot be longer"):
1019 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
1020 with self.assertRaisesRegex(TypeError, "must return a string"):
1021 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
1022 with self.assertRaisesRegex(Exception, "getpass error"):
1023 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
1024 # Make sure the password function isn't called if it isn't needed
1025 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001026
1027 def test_load_verify_locations(self):
1028 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1029 ctx.load_verify_locations(CERTFILE)
1030 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
1031 ctx.load_verify_locations(BYTES_CERTFILE)
1032 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
1033 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +01001034 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001035 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001036 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +00001037 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001038 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +00001039 ctx.load_verify_locations(BADCERT)
1040 ctx.load_verify_locations(CERTFILE, CAPATH)
1041 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
1042
Victor Stinner80f75e62011-01-29 11:31:20 +00001043 # Issue #10989: crash if the second argument type is invalid
1044 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
1045
Christian Heimesefff7062013-11-21 03:35:02 +01001046 def test_load_verify_cadata(self):
1047 # test cadata
1048 with open(CAFILE_CACERT) as f:
1049 cacert_pem = f.read()
1050 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
1051 with open(CAFILE_NEURONIO) as f:
1052 neuronio_pem = f.read()
1053 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
1054
1055 # test PEM
1056 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1057 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1058 ctx.load_verify_locations(cadata=cacert_pem)
1059 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1060 ctx.load_verify_locations(cadata=neuronio_pem)
1061 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1062 # cert already in hash table
1063 ctx.load_verify_locations(cadata=neuronio_pem)
1064 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1065
1066 # combined
1067 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1068 combined = "\n".join((cacert_pem, neuronio_pem))
1069 ctx.load_verify_locations(cadata=combined)
1070 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1071
1072 # with junk around the certs
1073 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1074 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1075 neuronio_pem, "tail"]
1076 ctx.load_verify_locations(cadata="\n".join(combined))
1077 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1078
1079 # test DER
1080 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1081 ctx.load_verify_locations(cadata=cacert_der)
1082 ctx.load_verify_locations(cadata=neuronio_der)
1083 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1084 # cert already in hash table
1085 ctx.load_verify_locations(cadata=cacert_der)
1086 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1087
1088 # combined
1089 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1090 combined = b"".join((cacert_der, neuronio_der))
1091 ctx.load_verify_locations(cadata=combined)
1092 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1093
1094 # error cases
1095 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1096 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1097
1098 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1099 ctx.load_verify_locations(cadata="broken")
1100 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1101 ctx.load_verify_locations(cadata=b"broken")
1102
1103
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001104 def test_load_dh_params(self):
1105 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1106 ctx.load_dh_params(DHFILE)
1107 if os.name != 'nt':
1108 ctx.load_dh_params(BYTES_DHFILE)
1109 self.assertRaises(TypeError, ctx.load_dh_params)
1110 self.assertRaises(TypeError, ctx.load_dh_params, None)
1111 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001112 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001113 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001114 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001115 ctx.load_dh_params(CERTFILE)
1116
Antoine Pitroueb585ad2010-10-22 18:24:20 +00001117 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +00001118 def test_session_stats(self):
1119 for proto in PROTOCOLS:
1120 ctx = ssl.SSLContext(proto)
1121 self.assertEqual(ctx.session_stats(), {
1122 'number': 0,
1123 'connect': 0,
1124 'connect_good': 0,
1125 'connect_renegotiate': 0,
1126 'accept': 0,
1127 'accept_good': 0,
1128 'accept_renegotiate': 0,
1129 'hits': 0,
1130 'misses': 0,
1131 'timeouts': 0,
1132 'cache_full': 0,
1133 })
1134
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001135 def test_set_default_verify_paths(self):
1136 # There's not much we can do to test that it acts as expected,
1137 # so just check it doesn't crash or raise an exception.
1138 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1139 ctx.set_default_verify_paths()
1140
Antoine Pitrou501da612011-12-21 09:27:41 +01001141 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001142 def test_set_ecdh_curve(self):
1143 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1144 ctx.set_ecdh_curve("prime256v1")
1145 ctx.set_ecdh_curve(b"prime256v1")
1146 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1147 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1148 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1149 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1150
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001151 @needs_sni
1152 def test_sni_callback(self):
1153 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1154
1155 # set_servername_callback expects a callable, or None
1156 self.assertRaises(TypeError, ctx.set_servername_callback)
1157 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1158 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1159 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1160
1161 def dummycallback(sock, servername, ctx):
1162 pass
1163 ctx.set_servername_callback(None)
1164 ctx.set_servername_callback(dummycallback)
1165
1166 @needs_sni
1167 def test_sni_callback_refcycle(self):
1168 # Reference cycles through the servername callback are detected
1169 # and cleared.
1170 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1171 def dummycallback(sock, servername, ctx, cycle=ctx):
1172 pass
1173 ctx.set_servername_callback(dummycallback)
1174 wr = weakref.ref(ctx)
1175 del ctx, dummycallback
1176 gc.collect()
1177 self.assertIs(wr(), None)
1178
Christian Heimes9a5395a2013-06-17 15:44:12 +02001179 def test_cert_store_stats(self):
1180 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1181 self.assertEqual(ctx.cert_store_stats(),
1182 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1183 ctx.load_cert_chain(CERTFILE)
1184 self.assertEqual(ctx.cert_store_stats(),
1185 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1186 ctx.load_verify_locations(CERTFILE)
1187 self.assertEqual(ctx.cert_store_stats(),
1188 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001189 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001190 self.assertEqual(ctx.cert_store_stats(),
1191 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1192
1193 def test_get_ca_certs(self):
1194 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1195 self.assertEqual(ctx.get_ca_certs(), [])
1196 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1197 ctx.load_verify_locations(CERTFILE)
1198 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001199 # but CAFILE_CACERT is a CA cert
1200 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001201 self.assertEqual(ctx.get_ca_certs(),
1202 [{'issuer': ((('organizationName', 'Root CA'),),
1203 (('organizationalUnitName', 'http://www.cacert.org'),),
1204 (('commonName', 'CA Cert Signing Authority'),),
1205 (('emailAddress', 'support@cacert.org'),)),
1206 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1207 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1208 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001209 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001210 'subject': ((('organizationName', 'Root CA'),),
1211 (('organizationalUnitName', 'http://www.cacert.org'),),
1212 (('commonName', 'CA Cert Signing Authority'),),
1213 (('emailAddress', 'support@cacert.org'),)),
1214 'version': 3}])
1215
Martin Panterb55f8b72016-01-14 12:53:56 +00001216 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001217 pem = f.read()
1218 der = ssl.PEM_cert_to_DER_cert(pem)
1219 self.assertEqual(ctx.get_ca_certs(True), [der])
1220
Christian Heimes72d28502013-11-23 13:56:58 +01001221 def test_load_default_certs(self):
1222 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1223 ctx.load_default_certs()
1224
1225 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1226 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1227 ctx.load_default_certs()
1228
1229 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1230 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1231
1232 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1233 self.assertRaises(TypeError, ctx.load_default_certs, None)
1234 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1235
Benjamin Peterson91244e02014-10-03 18:17:15 -04001236 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Christian Heimes598894f2016-09-05 23:19:05 +02001237 @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001238 def test_load_default_certs_env(self):
1239 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1240 with support.EnvironmentVarGuard() as env:
1241 env["SSL_CERT_DIR"] = CAPATH
1242 env["SSL_CERT_FILE"] = CERTFILE
1243 ctx.load_default_certs()
1244 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1245
Benjamin Peterson91244e02014-10-03 18:17:15 -04001246 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1247 def test_load_default_certs_env_windows(self):
1248 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1249 ctx.load_default_certs()
1250 stats = ctx.cert_store_stats()
1251
1252 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1253 with support.EnvironmentVarGuard() as env:
1254 env["SSL_CERT_DIR"] = CAPATH
1255 env["SSL_CERT_FILE"] = CERTFILE
1256 ctx.load_default_certs()
1257 stats["x509"] += 1
1258 self.assertEqual(ctx.cert_store_stats(), stats)
1259
Christian Heimes358cfd42016-09-10 22:43:48 +02001260 def _assert_context_options(self, ctx):
1261 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1262 if OP_NO_COMPRESSION != 0:
1263 self.assertEqual(ctx.options & OP_NO_COMPRESSION,
1264 OP_NO_COMPRESSION)
1265 if OP_SINGLE_DH_USE != 0:
1266 self.assertEqual(ctx.options & OP_SINGLE_DH_USE,
1267 OP_SINGLE_DH_USE)
1268 if OP_SINGLE_ECDH_USE != 0:
1269 self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE,
1270 OP_SINGLE_ECDH_USE)
1271 if OP_CIPHER_SERVER_PREFERENCE != 0:
1272 self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE,
1273 OP_CIPHER_SERVER_PREFERENCE)
1274
Christian Heimes4c05b472013-11-23 15:58:30 +01001275 def test_create_default_context(self):
1276 ctx = ssl.create_default_context()
Christian Heimes358cfd42016-09-10 22:43:48 +02001277
Donald Stufft6a2ba942014-03-23 19:05:28 -04001278 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001279 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001280 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001281 self._assert_context_options(ctx)
1282
Christian Heimes4c05b472013-11-23 15:58:30 +01001283
1284 with open(SIGNING_CA) as f:
1285 cadata = f.read()
1286 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1287 cadata=cadata)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001288 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001289 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes358cfd42016-09-10 22:43:48 +02001290 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001291
1292 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001293 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001294 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001295 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001296
Christian Heimes67986f92013-11-23 22:43:47 +01001297 def test__create_stdlib_context(self):
1298 ctx = ssl._create_stdlib_context()
1299 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1300 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001301 self.assertFalse(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001302 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001303
1304 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1305 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1306 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001307 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001308
1309 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001310 cert_reqs=ssl.CERT_REQUIRED,
1311 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001312 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1313 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001314 self.assertTrue(ctx.check_hostname)
Christian Heimes358cfd42016-09-10 22:43:48 +02001315 self._assert_context_options(ctx)
Christian Heimes67986f92013-11-23 22:43:47 +01001316
1317 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1318 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1319 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes358cfd42016-09-10 22:43:48 +02001320 self._assert_context_options(ctx)
Christian Heimes4c05b472013-11-23 15:58:30 +01001321
Christian Heimes1aa9a752013-12-02 02:41:19 +01001322 def test_check_hostname(self):
1323 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1324 self.assertFalse(ctx.check_hostname)
1325
1326 # Requires CERT_REQUIRED or CERT_OPTIONAL
1327 with self.assertRaises(ValueError):
1328 ctx.check_hostname = True
1329 ctx.verify_mode = ssl.CERT_REQUIRED
1330 self.assertFalse(ctx.check_hostname)
1331 ctx.check_hostname = True
1332 self.assertTrue(ctx.check_hostname)
1333
1334 ctx.verify_mode = ssl.CERT_OPTIONAL
1335 ctx.check_hostname = True
1336 self.assertTrue(ctx.check_hostname)
1337
1338 # Cannot set CERT_NONE with check_hostname enabled
1339 with self.assertRaises(ValueError):
1340 ctx.verify_mode = ssl.CERT_NONE
1341 ctx.check_hostname = False
1342 self.assertFalse(ctx.check_hostname)
1343
Christian Heimes5fe668c2016-09-12 00:01:11 +02001344 def test_context_client_server(self):
1345 # PROTOCOL_TLS_CLIENT has sane defaults
1346 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1347 self.assertTrue(ctx.check_hostname)
1348 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1349
1350 # PROTOCOL_TLS_SERVER has different but also sane defaults
1351 ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1352 self.assertFalse(ctx.check_hostname)
1353 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1354
Antoine Pitrou152efa22010-05-16 18:19:27 +00001355
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001356class SSLErrorTests(unittest.TestCase):
1357
1358 def test_str(self):
1359 # The str() of a SSLError doesn't include the errno
1360 e = ssl.SSLError(1, "foo")
1361 self.assertEqual(str(e), "foo")
1362 self.assertEqual(e.errno, 1)
1363 # Same for a subclass
1364 e = ssl.SSLZeroReturnError(1, "foo")
1365 self.assertEqual(str(e), "foo")
1366 self.assertEqual(e.errno, 1)
1367
1368 def test_lib_reason(self):
1369 # Test the library and reason attributes
1370 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1371 with self.assertRaises(ssl.SSLError) as cm:
1372 ctx.load_dh_params(CERTFILE)
1373 self.assertEqual(cm.exception.library, 'PEM')
1374 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1375 s = str(cm.exception)
1376 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1377
1378 def test_subclass(self):
1379 # Check that the appropriate SSLError subclass is raised
1380 # (this only tests one of them)
1381 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1382 with socket.socket() as s:
1383 s.bind(("127.0.0.1", 0))
Charles-François Natali6e204602014-07-23 19:28:13 +01001384 s.listen()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001385 c = socket.socket()
1386 c.connect(s.getsockname())
1387 c.setblocking(False)
1388 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001389 with self.assertRaises(ssl.SSLWantReadError) as cm:
1390 c.do_handshake()
1391 s = str(cm.exception)
1392 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1393 # For compatibility
1394 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1395
1396
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001397class MemoryBIOTests(unittest.TestCase):
1398
1399 def test_read_write(self):
1400 bio = ssl.MemoryBIO()
1401 bio.write(b'foo')
1402 self.assertEqual(bio.read(), b'foo')
1403 self.assertEqual(bio.read(), b'')
1404 bio.write(b'foo')
1405 bio.write(b'bar')
1406 self.assertEqual(bio.read(), b'foobar')
1407 self.assertEqual(bio.read(), b'')
1408 bio.write(b'baz')
1409 self.assertEqual(bio.read(2), b'ba')
1410 self.assertEqual(bio.read(1), b'z')
1411 self.assertEqual(bio.read(1), b'')
1412
1413 def test_eof(self):
1414 bio = ssl.MemoryBIO()
1415 self.assertFalse(bio.eof)
1416 self.assertEqual(bio.read(), b'')
1417 self.assertFalse(bio.eof)
1418 bio.write(b'foo')
1419 self.assertFalse(bio.eof)
1420 bio.write_eof()
1421 self.assertFalse(bio.eof)
1422 self.assertEqual(bio.read(2), b'fo')
1423 self.assertFalse(bio.eof)
1424 self.assertEqual(bio.read(1), b'o')
1425 self.assertTrue(bio.eof)
1426 self.assertEqual(bio.read(), b'')
1427 self.assertTrue(bio.eof)
1428
1429 def test_pending(self):
1430 bio = ssl.MemoryBIO()
1431 self.assertEqual(bio.pending, 0)
1432 bio.write(b'foo')
1433 self.assertEqual(bio.pending, 3)
1434 for i in range(3):
1435 bio.read(1)
1436 self.assertEqual(bio.pending, 3-i-1)
1437 for i in range(3):
1438 bio.write(b'x')
1439 self.assertEqual(bio.pending, i+1)
1440 bio.read()
1441 self.assertEqual(bio.pending, 0)
1442
1443 def test_buffer_types(self):
1444 bio = ssl.MemoryBIO()
1445 bio.write(b'foo')
1446 self.assertEqual(bio.read(), b'foo')
1447 bio.write(bytearray(b'bar'))
1448 self.assertEqual(bio.read(), b'bar')
1449 bio.write(memoryview(b'baz'))
1450 self.assertEqual(bio.read(), b'baz')
1451
1452 def test_error_types(self):
1453 bio = ssl.MemoryBIO()
1454 self.assertRaises(TypeError, bio.write, 'foo')
1455 self.assertRaises(TypeError, bio.write, None)
1456 self.assertRaises(TypeError, bio.write, True)
1457 self.assertRaises(TypeError, bio.write, 1)
1458
1459
Martin Panter3840b2a2016-03-27 01:53:46 +00001460@unittest.skipUnless(_have_threads, "Needs threading module")
1461class SimpleBackgroundTests(unittest.TestCase):
1462
1463 """Tests that connect to a simple server running in the background"""
1464
1465 def setUp(self):
1466 server = ThreadedEchoServer(SIGNED_CERTFILE)
1467 self.server_addr = (HOST, server.port)
1468 server.__enter__()
1469 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001470
Antoine Pitrou480a1242010-04-28 21:37:09 +00001471 def test_connect(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001472 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001473 cert_reqs=ssl.CERT_NONE) as s:
1474 s.connect(self.server_addr)
1475 self.assertEqual({}, s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001476 self.assertFalse(s.server_side)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001477
Martin Panter3840b2a2016-03-27 01:53:46 +00001478 # this should succeed because we specify the root cert
Christian Heimesd0486372016-09-10 23:23:33 +02001479 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001480 cert_reqs=ssl.CERT_REQUIRED,
1481 ca_certs=SIGNING_CA) as s:
1482 s.connect(self.server_addr)
1483 self.assertTrue(s.getpeercert())
Christian Heimesa5d07652016-09-24 10:48:05 +02001484 self.assertFalse(s.server_side)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001485
Martin Panter3840b2a2016-03-27 01:53:46 +00001486 def test_connect_fail(self):
1487 # This should fail because we have no verification certs. Connection
1488 # failure crashes ThreadedEchoServer, so run this in an independent
1489 # test method.
Christian Heimesd0486372016-09-10 23:23:33 +02001490 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001491 cert_reqs=ssl.CERT_REQUIRED)
1492 self.addCleanup(s.close)
1493 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1494 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001495
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001496 def test_connect_ex(self):
1497 # Issue #11326: check connect_ex() implementation
Christian Heimesd0486372016-09-10 23:23:33 +02001498 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001499 cert_reqs=ssl.CERT_REQUIRED,
1500 ca_certs=SIGNING_CA)
1501 self.addCleanup(s.close)
1502 self.assertEqual(0, s.connect_ex(self.server_addr))
1503 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001504
1505 def test_non_blocking_connect_ex(self):
1506 # Issue #11326: non-blocking connect_ex() should allow handshake
1507 # to proceed after the socket gets ready.
Christian Heimesd0486372016-09-10 23:23:33 +02001508 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001509 cert_reqs=ssl.CERT_REQUIRED,
1510 ca_certs=SIGNING_CA,
1511 do_handshake_on_connect=False)
1512 self.addCleanup(s.close)
1513 s.setblocking(False)
1514 rc = s.connect_ex(self.server_addr)
1515 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1516 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
1517 # Wait for connect to finish
1518 select.select([], [s], [], 5.0)
1519 # Non-blocking handshake
1520 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001521 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00001522 s.do_handshake()
1523 break
1524 except ssl.SSLWantReadError:
1525 select.select([s], [], [], 5.0)
1526 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001527 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00001528 # SSL established
1529 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001530
Antoine Pitrou152efa22010-05-16 18:19:27 +00001531 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001532 # Same as test_connect, but with a separately created context
1533 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1534 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1535 s.connect(self.server_addr)
1536 self.assertEqual({}, s.getpeercert())
1537 # Same with a server hostname
1538 with ctx.wrap_socket(socket.socket(socket.AF_INET),
1539 server_hostname="dummy") as s:
1540 s.connect(self.server_addr)
1541 ctx.verify_mode = ssl.CERT_REQUIRED
1542 # This should succeed because we specify the root cert
1543 ctx.load_verify_locations(SIGNING_CA)
1544 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1545 s.connect(self.server_addr)
1546 cert = s.getpeercert()
1547 self.assertTrue(cert)
1548
1549 def test_connect_with_context_fail(self):
1550 # This should fail because we have no verification certs. Connection
1551 # failure crashes ThreadedEchoServer, so run this in an independent
1552 # test method.
1553 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1554 ctx.verify_mode = ssl.CERT_REQUIRED
1555 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1556 self.addCleanup(s.close)
1557 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1558 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001559
1560 def test_connect_capath(self):
1561 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00001562 # NOTE: the subject hashing algorithm has been changed between
1563 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1564 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00001565 # filename) for this test to be portable across OpenSSL releases.
Martin Panter3840b2a2016-03-27 01:53:46 +00001566 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1567 ctx.verify_mode = ssl.CERT_REQUIRED
1568 ctx.load_verify_locations(capath=CAPATH)
1569 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1570 s.connect(self.server_addr)
1571 cert = s.getpeercert()
1572 self.assertTrue(cert)
1573 # Same with a bytes `capath` argument
1574 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1575 ctx.verify_mode = ssl.CERT_REQUIRED
1576 ctx.load_verify_locations(capath=BYTES_CAPATH)
1577 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1578 s.connect(self.server_addr)
1579 cert = s.getpeercert()
1580 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001581
Christian Heimesefff7062013-11-21 03:35:02 +01001582 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001583 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01001584 pem = f.read()
1585 der = ssl.PEM_cert_to_DER_cert(pem)
Martin Panter3840b2a2016-03-27 01:53:46 +00001586 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1587 ctx.verify_mode = ssl.CERT_REQUIRED
1588 ctx.load_verify_locations(cadata=pem)
1589 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1590 s.connect(self.server_addr)
1591 cert = s.getpeercert()
1592 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01001593
Martin Panter3840b2a2016-03-27 01:53:46 +00001594 # same with DER
1595 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1596 ctx.verify_mode = ssl.CERT_REQUIRED
1597 ctx.load_verify_locations(cadata=der)
1598 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1599 s.connect(self.server_addr)
1600 cert = s.getpeercert()
1601 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01001602
Antoine Pitroue3220242010-04-24 11:13:53 +00001603 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1604 def test_makefile_close(self):
1605 # Issue #5238: creating a file-like object with makefile() shouldn't
1606 # delay closing the underlying "real socket" (here tested with its
1607 # file descriptor, hence skipping the test under Windows).
Christian Heimesd0486372016-09-10 23:23:33 +02001608 ss = test_wrap_socket(socket.socket(socket.AF_INET))
Martin Panter3840b2a2016-03-27 01:53:46 +00001609 ss.connect(self.server_addr)
1610 fd = ss.fileno()
1611 f = ss.makefile()
1612 f.close()
1613 # The fd is still open
1614 os.read(fd, 0)
1615 # Closing the SSL socket should close the fd too
1616 ss.close()
1617 gc.collect()
1618 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00001619 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00001620 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001621
Antoine Pitrou480a1242010-04-28 21:37:09 +00001622 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001623 s = socket.socket(socket.AF_INET)
1624 s.connect(self.server_addr)
1625 s.setblocking(False)
Christian Heimesd0486372016-09-10 23:23:33 +02001626 s = test_wrap_socket(s,
Martin Panter3840b2a2016-03-27 01:53:46 +00001627 cert_reqs=ssl.CERT_NONE,
1628 do_handshake_on_connect=False)
1629 self.addCleanup(s.close)
1630 count = 0
1631 while True:
1632 try:
1633 count += 1
1634 s.do_handshake()
1635 break
1636 except ssl.SSLWantReadError:
1637 select.select([s], [], [])
1638 except ssl.SSLWantWriteError:
1639 select.select([], [s], [])
1640 if support.verbose:
1641 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001642
Antoine Pitrou480a1242010-04-28 21:37:09 +00001643 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001644 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001645
Martin Panter3840b2a2016-03-27 01:53:46 +00001646 def test_get_server_certificate_fail(self):
1647 # Connection failure crashes ThreadedEchoServer, so run this in an
1648 # independent test method
1649 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001650
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001651 def test_ciphers(self):
Christian Heimesd0486372016-09-10 23:23:33 +02001652 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001653 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1654 s.connect(self.server_addr)
Christian Heimesd0486372016-09-10 23:23:33 +02001655 with test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001656 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1657 s.connect(self.server_addr)
1658 # Error checking can happen at instantiation or when connecting
1659 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
1660 with socket.socket(socket.AF_INET) as sock:
Christian Heimesd0486372016-09-10 23:23:33 +02001661 s = test_wrap_socket(sock,
Martin Panter3840b2a2016-03-27 01:53:46 +00001662 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1663 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001664
Christian Heimes9a5395a2013-06-17 15:44:12 +02001665 def test_get_ca_certs_capath(self):
1666 # capath certs are loaded on request
Martin Panter3840b2a2016-03-27 01:53:46 +00001667 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1668 ctx.verify_mode = ssl.CERT_REQUIRED
1669 ctx.load_verify_locations(capath=CAPATH)
1670 self.assertEqual(ctx.get_ca_certs(), [])
1671 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1672 s.connect(self.server_addr)
1673 cert = s.getpeercert()
1674 self.assertTrue(cert)
1675 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001676
Christian Heimes575596e2013-12-15 21:49:17 +01001677 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01001678 def test_context_setget(self):
1679 # Check that the context of a connected socket can be replaced.
Martin Panter3840b2a2016-03-27 01:53:46 +00001680 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1681 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1682 s = socket.socket(socket.AF_INET)
1683 with ctx1.wrap_socket(s) as ss:
1684 ss.connect(self.server_addr)
1685 self.assertIs(ss.context, ctx1)
1686 self.assertIs(ss._sslobj.context, ctx1)
1687 ss.context = ctx2
1688 self.assertIs(ss.context, ctx2)
1689 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001690
1691 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
1692 # A simple IO loop. Call func(*args) depending on the error we get
1693 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
1694 timeout = kwargs.get('timeout', 10)
1695 count = 0
1696 while True:
1697 errno = None
1698 count += 1
1699 try:
1700 ret = func(*args)
1701 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001702 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00001703 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001704 raise
1705 errno = e.errno
1706 # Get any data from the outgoing BIO irrespective of any error, and
1707 # send it to the socket.
1708 buf = outgoing.read()
1709 sock.sendall(buf)
1710 # If there's no error, we're done. For WANT_READ, we need to get
1711 # data from the socket and put it in the incoming BIO.
1712 if errno is None:
1713 break
1714 elif errno == ssl.SSL_ERROR_WANT_READ:
1715 buf = sock.recv(32768)
1716 if buf:
1717 incoming.write(buf)
1718 else:
1719 incoming.write_eof()
1720 if support.verbose:
1721 sys.stdout.write("Needed %d calls to complete %s().\n"
1722 % (count, func.__name__))
1723 return ret
1724
Martin Panter3840b2a2016-03-27 01:53:46 +00001725 def test_bio_handshake(self):
1726 sock = socket.socket(socket.AF_INET)
1727 self.addCleanup(sock.close)
1728 sock.connect(self.server_addr)
1729 incoming = ssl.MemoryBIO()
1730 outgoing = ssl.MemoryBIO()
1731 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1732 ctx.verify_mode = ssl.CERT_REQUIRED
1733 ctx.load_verify_locations(SIGNING_CA)
1734 ctx.check_hostname = True
1735 sslobj = ctx.wrap_bio(incoming, outgoing, False, 'localhost')
1736 self.assertIs(sslobj._sslobj.owner, sslobj)
1737 self.assertIsNone(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02001738 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00001739 self.assertRaises(ValueError, sslobj.getpeercert)
1740 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
1741 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
1742 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
1743 self.assertTrue(sslobj.cipher())
Christian Heimes01113fa2016-09-05 23:23:24 +02001744 self.assertIsNotNone(sslobj.shared_ciphers())
Martin Panter3840b2a2016-03-27 01:53:46 +00001745 self.assertTrue(sslobj.getpeercert())
1746 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
1747 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
1748 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001749 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00001750 except ssl.SSLSyscallError:
1751 # If the server shuts down the TCP connection without sending a
1752 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
1753 pass
1754 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
1755
1756 def test_bio_read_write_data(self):
1757 sock = socket.socket(socket.AF_INET)
1758 self.addCleanup(sock.close)
1759 sock.connect(self.server_addr)
1760 incoming = ssl.MemoryBIO()
1761 outgoing = ssl.MemoryBIO()
1762 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1763 ctx.verify_mode = ssl.CERT_NONE
1764 sslobj = ctx.wrap_bio(incoming, outgoing, False)
1765 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
1766 req = b'FOO\n'
1767 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
1768 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
1769 self.assertEqual(buf, b'foo\n')
1770 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001771
1772
Martin Panter3840b2a2016-03-27 01:53:46 +00001773class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001774
Martin Panter3840b2a2016-03-27 01:53:46 +00001775 def test_timeout_connect_ex(self):
1776 # Issue #12065: on a timeout, connect_ex() should return the original
1777 # errno (mimicking the behaviour of non-SSL sockets).
1778 with support.transient_internet(REMOTE_HOST):
Christian Heimesd0486372016-09-10 23:23:33 +02001779 s = test_wrap_socket(socket.socket(socket.AF_INET),
Martin Panter3840b2a2016-03-27 01:53:46 +00001780 cert_reqs=ssl.CERT_REQUIRED,
1781 do_handshake_on_connect=False)
1782 self.addCleanup(s.close)
1783 s.settimeout(0.0000001)
1784 rc = s.connect_ex((REMOTE_HOST, 443))
1785 if rc == 0:
1786 self.skipTest("REMOTE_HOST responded too quickly")
1787 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1788
1789 @unittest.skipUnless(support.IPV6_ENABLED, 'Needs IPv6')
1790 def test_get_server_certificate_ipv6(self):
1791 with support.transient_internet('ipv6.google.com'):
1792 _test_get_server_certificate(self, 'ipv6.google.com', 443)
1793 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
1794
1795 def test_algorithms(self):
1796 # Issue #8484: all algorithms should be available when verifying a
1797 # certificate.
1798 # SHA256 was added in OpenSSL 0.9.8
1799 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1800 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
1801 # sha256.tbs-internet.com needs SNI to use the correct certificate
1802 if not ssl.HAS_SNI:
1803 self.skipTest("SNI needed for this test")
1804 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1805 remote = ("sha256.tbs-internet.com", 443)
1806 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
1807 with support.transient_internet("sha256.tbs-internet.com"):
1808 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1809 ctx.verify_mode = ssl.CERT_REQUIRED
1810 ctx.load_verify_locations(sha256_cert)
1811 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1812 server_hostname="sha256.tbs-internet.com")
1813 try:
1814 s.connect(remote)
1815 if support.verbose:
1816 sys.stdout.write("\nCipher with %r is %r\n" %
1817 (remote, s.cipher()))
1818 sys.stdout.write("Certificate is:\n%s\n" %
1819 pprint.pformat(s.getpeercert()))
1820 finally:
1821 s.close()
1822
1823
1824def _test_get_server_certificate(test, host, port, cert=None):
1825 pem = ssl.get_server_certificate((host, port))
1826 if not pem:
1827 test.fail("No server certificate on %s:%s!" % (host, port))
1828
1829 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
1830 if not pem:
1831 test.fail("No server certificate on %s:%s!" % (host, port))
1832 if support.verbose:
1833 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
1834
1835def _test_get_server_certificate_fail(test, host, port):
1836 try:
1837 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
1838 except ssl.SSLError as x:
1839 #should fail
1840 if support.verbose:
1841 sys.stdout.write("%s\n" % x)
1842 else:
1843 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1844
1845
1846if _have_threads:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001847 from test.ssl_servers import make_https_server
1848
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001849 class ThreadedEchoServer(threading.Thread):
1850
1851 class ConnectionHandler(threading.Thread):
1852
1853 """A mildly complicated class, because we want it to work both
1854 with and without the SSL wrapper around the socket connection, so
1855 that we can test the STARTTLS functionality."""
1856
Bill Janssen6e027db2007-11-15 22:23:56 +00001857 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001858 self.server = server
1859 self.running = False
1860 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001861 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001862 self.sock.setblocking(1)
1863 self.sslconn = None
1864 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001865 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001866
Antoine Pitrou480a1242010-04-28 21:37:09 +00001867 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001868 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001869 self.sslconn = self.server.context.wrap_socket(
1870 self.sock, server_side=True)
Benjamin Petersoncca27322015-01-23 16:35:37 -05001871 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
1872 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001873 except (ssl.SSLError, ConnectionResetError) as e:
1874 # We treat ConnectionResetError as though it were an
1875 # SSLError - OpenSSL on Ubuntu abruptly closes the
1876 # connection when asked to use an unsupported protocol.
1877 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001878 # XXX Various errors can have happened here, for example
1879 # a mismatching protocol version, an invalid certificate,
1880 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001881 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001882 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001883 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001884 self.running = False
1885 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001886 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001887 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001888 else:
Benjamin Peterson4cb17812015-01-07 11:14:26 -06001889 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
Antoine Pitroub5218772010-05-21 09:56:06 +00001890 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001891 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001892 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001893 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1894 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001895 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001896 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1897 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001898 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001899 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001900 sys.stdout.write(" server: selected protocol is now "
1901 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001902 return True
1903
1904 def read(self):
1905 if self.sslconn:
1906 return self.sslconn.read()
1907 else:
1908 return self.sock.recv(1024)
1909
1910 def write(self, bytes):
1911 if self.sslconn:
1912 return self.sslconn.write(bytes)
1913 else:
1914 return self.sock.send(bytes)
1915
1916 def close(self):
1917 if self.sslconn:
1918 self.sslconn.close()
1919 else:
1920 self.sock.close()
1921
Antoine Pitrou480a1242010-04-28 21:37:09 +00001922 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001923 self.running = True
1924 if not self.server.starttls_server:
1925 if not self.wrap_conn():
1926 return
1927 while self.running:
1928 try:
1929 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001930 stripped = msg.strip()
1931 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001932 # eof, so quit this handler
1933 self.running = False
Martin Panter3840b2a2016-03-27 01:53:46 +00001934 try:
1935 self.sock = self.sslconn.unwrap()
1936 except OSError:
1937 # Many tests shut the TCP connection down
1938 # without an SSL shutdown. This causes
1939 # unwrap() to raise OSError with errno=0!
1940 pass
1941 else:
1942 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001943 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001944 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001945 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001946 sys.stdout.write(" server: client closed connection\n")
1947 self.close()
1948 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001949 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001950 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001951 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001952 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001953 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001954 if not self.wrap_conn():
1955 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001956 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001957 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001958 if support.verbose and self.server.connectionchatty:
1959 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001960 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001961 self.sock = self.sslconn.unwrap()
1962 self.sslconn = None
1963 if support.verbose and self.server.connectionchatty:
1964 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001965 elif stripped == b'CB tls-unique':
1966 if support.verbose and self.server.connectionchatty:
1967 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1968 data = self.sslconn.get_channel_binding("tls-unique")
1969 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001970 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001971 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001972 self.server.connectionchatty):
1973 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001974 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1975 % (msg, ctype, msg.lower(), ctype))
1976 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001977 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001978 if self.server.chatty:
1979 handle_error("Test server failure:\n")
1980 self.close()
1981 self.running = False
1982 # normally, we'd just stop here, but for the test
1983 # harness, we want to stop the server
1984 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001985
Antoine Pitroub5218772010-05-21 09:56:06 +00001986 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001987 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001988 chatty=True, connectionchatty=False, starttls_server=False,
Benjamin Petersoncca27322015-01-23 16:35:37 -05001989 npn_protocols=None, alpn_protocols=None,
1990 ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001991 if context:
1992 self.context = context
1993 else:
1994 self.context = ssl.SSLContext(ssl_version
1995 if ssl_version is not None
1996 else ssl.PROTOCOL_TLSv1)
1997 self.context.verify_mode = (certreqs if certreqs is not None
1998 else ssl.CERT_NONE)
1999 if cacerts:
2000 self.context.load_verify_locations(cacerts)
2001 if certificate:
2002 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002003 if npn_protocols:
2004 self.context.set_npn_protocols(npn_protocols)
Benjamin Petersoncca27322015-01-23 16:35:37 -05002005 if alpn_protocols:
2006 self.context.set_alpn_protocols(alpn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00002007 if ciphers:
2008 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002009 self.chatty = chatty
2010 self.connectionchatty = connectionchatty
2011 self.starttls_server = starttls_server
2012 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002013 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002014 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002015 self.active = False
Benjamin Petersoncca27322015-01-23 16:35:37 -05002016 self.selected_npn_protocols = []
2017 self.selected_alpn_protocols = []
Benjamin Peterson4cb17812015-01-07 11:14:26 -06002018 self.shared_ciphers = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002019 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002020 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002021 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002022
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002023 def __enter__(self):
2024 self.start(threading.Event())
2025 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002026 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002027
2028 def __exit__(self, *args):
2029 self.stop()
2030 self.join()
2031
Antoine Pitrou480a1242010-04-28 21:37:09 +00002032 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002033 self.flag = flag
2034 threading.Thread.start(self)
2035
Antoine Pitrou480a1242010-04-28 21:37:09 +00002036 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00002037 self.sock.settimeout(0.05)
Charles-François Natali6e204602014-07-23 19:28:13 +01002038 self.sock.listen()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002039 self.active = True
2040 if self.flag:
2041 # signal an event
2042 self.flag.set()
2043 while self.active:
2044 try:
2045 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002046 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002047 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00002048 + repr(connaddr) + '\n')
2049 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002050 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01002051 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002052 except socket.timeout:
2053 pass
2054 except KeyboardInterrupt:
2055 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00002056 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002057
Antoine Pitrou480a1242010-04-28 21:37:09 +00002058 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002059 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002060
Bill Janssen54cc54c2007-12-14 22:08:56 +00002061 class AsyncoreEchoServer(threading.Thread):
2062
2063 # this one's based on asyncore.dispatcher
2064
2065 class EchoServer (asyncore.dispatcher):
2066
Victor Stinner1dae7452017-05-02 13:12:02 +02002067 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002068
2069 def __init__(self, conn, certfile):
Christian Heimesd0486372016-09-10 23:23:33 +02002070 self.socket = test_wrap_socket(conn, server_side=True,
Bill Janssen54cc54c2007-12-14 22:08:56 +00002071 certfile=certfile,
2072 do_handshake_on_connect=False)
2073 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002074 self._ssl_accepting = True
2075 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002076
2077 def readable(self):
2078 if isinstance(self.socket, ssl.SSLSocket):
2079 while self.socket.pending() > 0:
2080 self.handle_read_event()
2081 return True
2082
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002083 def _do_ssl_handshake(self):
2084 try:
2085 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02002086 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2087 return
2088 except ssl.SSLEOFError:
2089 return self.handle_close()
2090 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002091 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02002092 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002093 if err.args[0] == errno.ECONNABORTED:
2094 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002095 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002096 self._ssl_accepting = False
2097
2098 def handle_read(self):
2099 if self._ssl_accepting:
2100 self._do_ssl_handshake()
2101 else:
2102 data = self.recv(1024)
2103 if support.verbose:
2104 sys.stdout.write(" server: read %s from client\n" % repr(data))
2105 if not data:
2106 self.close()
2107 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002108 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002109
2110 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00002111 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002112 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002113 sys.stdout.write(" server: closed connection %s\n" % self.socket)
2114
2115 def handle_error(self):
2116 raise
2117
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002118 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002119 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002120 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2121 self.port = support.bind_port(sock, '')
2122 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002123 self.listen(5)
2124
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00002125 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002126 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002127 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2128 self.ConnectionHandler(sock_obj, self.certfile)
2129
2130 def handle_error(self):
2131 raise
2132
Trent Nelson78520002008-04-10 20:54:35 +00002133 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002134 self.flag = None
2135 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002136 self.server = self.EchoServer(certfile)
2137 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00002138 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002139 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002140
2141 def __str__(self):
2142 return "<%s %s>" % (self.__class__.__name__, self.server)
2143
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002144 def __enter__(self):
2145 self.start(threading.Event())
2146 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002147 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002148
2149 def __exit__(self, *args):
2150 if support.verbose:
2151 sys.stdout.write(" cleanup: stopping server.\n")
2152 self.stop()
2153 if support.verbose:
2154 sys.stdout.write(" cleanup: joining server thread.\n")
2155 self.join()
2156 if support.verbose:
2157 sys.stdout.write(" cleanup: successfully joined.\n")
Victor Stinner1dae7452017-05-02 13:12:02 +02002158 # make sure that ConnectionHandler is removed from socket_map
2159 asyncore.close_all(ignore_all=True)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002160
Bill Janssen54cc54c2007-12-14 22:08:56 +00002161 def start (self, flag=None):
2162 self.flag = flag
2163 threading.Thread.start(self)
2164
Antoine Pitrou480a1242010-04-28 21:37:09 +00002165 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002166 self.active = True
2167 if self.flag:
2168 self.flag.set()
2169 while self.active:
2170 try:
2171 asyncore.loop(1)
2172 except:
2173 pass
2174
Antoine Pitrou480a1242010-04-28 21:37:09 +00002175 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002176 self.active = False
2177 self.server.close()
2178
Antoine Pitroub5218772010-05-21 09:56:06 +00002179 def server_params_test(client_context, server_context, indata=b"FOO\n",
Christian Heimes99a65702016-09-10 23:44:53 +02002180 chatty=True, connectionchatty=False, sni_name=None,
2181 session=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00002182 """
2183 Launch a server, connect a client to it and try various reads
2184 and writes.
2185 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002186 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00002187 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002188 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00002189 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002190 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002191 with client_context.wrap_socket(socket.socket(),
Christian Heimes99a65702016-09-10 23:44:53 +02002192 server_hostname=sni_name, session=session) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01002193 s.connect((HOST, server.port))
2194 for arg in [indata, bytearray(indata), memoryview(indata)]:
2195 if connectionchatty:
2196 if support.verbose:
2197 sys.stdout.write(
2198 " client: sending %r...\n" % indata)
2199 s.write(arg)
2200 outdata = s.read()
2201 if connectionchatty:
2202 if support.verbose:
2203 sys.stdout.write(" client: read %r\n" % outdata)
2204 if outdata != indata.lower():
2205 raise AssertionError(
2206 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2207 % (outdata[:20], len(outdata),
2208 indata[:20].lower(), len(indata)))
2209 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00002210 if connectionchatty:
2211 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01002212 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002213 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01002214 'compression': s.compression(),
2215 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002216 'peercert': s.getpeercert(),
Benjamin Petersoncca27322015-01-23 16:35:37 -05002217 'client_alpn_protocol': s.selected_alpn_protocol(),
Antoine Pitrou47e40422014-09-04 21:00:10 +02002218 'client_npn_protocol': s.selected_npn_protocol(),
2219 'version': s.version(),
Christian Heimes99a65702016-09-10 23:44:53 +02002220 'session_reused': s.session_reused,
2221 'session': s.session,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002222 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01002223 s.close()
Benjamin Petersoncca27322015-01-23 16:35:37 -05002224 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2225 stats['server_npn_protocols'] = server.selected_npn_protocols
Benjamin Peterson4cb17812015-01-07 11:14:26 -06002226 stats['server_shared_ciphers'] = server.shared_ciphers
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002227 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00002228
Antoine Pitroub5218772010-05-21 09:56:06 +00002229 def try_protocol_combo(server_protocol, client_protocol, expect_success,
2230 certsreqs=None, server_options=0, client_options=0):
Antoine Pitrou47e40422014-09-04 21:00:10 +02002231 """
2232 Try to SSL-connect using *client_protocol* to *server_protocol*.
2233 If *expect_success* is true, assert that the connection succeeds,
2234 if it's false, assert that the connection fails.
2235 Also, if *expect_success* is a string, assert that it is the protocol
2236 version actually used by the connection.
2237 """
Benjamin Peterson2a691a82008-03-31 01:51:45 +00002238 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002239 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00002240 certtype = {
2241 ssl.CERT_NONE: "CERT_NONE",
2242 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2243 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2244 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002245 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002246 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002247 sys.stdout.write(formatstr %
2248 (ssl.get_protocol_name(client_protocol),
2249 ssl.get_protocol_name(server_protocol),
2250 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00002251 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01002252 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00002253 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01002254 server_context.options |= server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002255
2256 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2257 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2258 # starting from OpenSSL 1.0.0 (see issue #8322).
2259 if client_context.protocol == ssl.PROTOCOL_SSLv23:
2260 client_context.set_ciphers("ALL")
2261
Antoine Pitroub5218772010-05-21 09:56:06 +00002262 for ctx in (client_context, server_context):
2263 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00002264 ctx.load_cert_chain(CERTFILE)
2265 ctx.load_verify_locations(CERTFILE)
2266 try:
Antoine Pitrou47e40422014-09-04 21:00:10 +02002267 stats = server_params_test(client_context, server_context,
2268 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002269 # Protocol mismatch can result in either an SSLError, or a
2270 # "Connection reset by peer" error.
2271 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002272 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002273 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02002274 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002275 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002276 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002277 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002278 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00002279 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002280 "Client protocol %s succeeded with server protocol %s!"
2281 % (ssl.get_protocol_name(client_protocol),
2282 ssl.get_protocol_name(server_protocol)))
Antoine Pitrou47e40422014-09-04 21:00:10 +02002283 elif (expect_success is not True
2284 and expect_success != stats['version']):
2285 raise AssertionError("version mismatch: expected %r, got %r"
2286 % (expect_success, stats['version']))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002287
2288
Bill Janssen6e027db2007-11-15 22:23:56 +00002289 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002290
Antoine Pitrou23df4832010-08-04 17:14:06 +00002291 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002292 def test_echo(self):
2293 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002294 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002295 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00002296 for protocol in PROTOCOLS:
Christian Heimes5fe668c2016-09-12 00:01:11 +02002297 if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
2298 continue
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01002299 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2300 context = ssl.SSLContext(protocol)
2301 context.load_cert_chain(CERTFILE)
2302 server_params_test(context, context,
2303 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002304
Christian Heimes5fe668c2016-09-12 00:01:11 +02002305 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
2306 client_context.load_verify_locations(SIGNING_CA)
2307 server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
2308 # server_context.load_verify_locations(SIGNING_CA)
2309 server_context.load_cert_chain(SIGNED_CERTFILE2)
2310
Christian Heimes9017ec12016-09-12 10:48:20 +02002311 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_SERVER):
Christian Heimes5fe668c2016-09-12 00:01:11 +02002312 server_params_test(client_context=client_context,
2313 server_context=server_context,
2314 chatty=True, connectionchatty=True,
2315 sni_name='fakehostname')
2316
Christian Heimes9017ec12016-09-12 10:48:20 +02002317 client_context.check_hostname = False
2318 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_CLIENT):
2319 with self.assertRaises(ssl.SSLError) as e:
Christian Heimes5fe668c2016-09-12 00:01:11 +02002320 server_params_test(client_context=server_context,
2321 server_context=client_context,
2322 chatty=True, connectionchatty=True,
2323 sni_name='fakehostname')
Christian Heimes9017ec12016-09-12 10:48:20 +02002324 self.assertIn('called a function you should not call',
2325 str(e.exception))
2326
2327 with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER):
2328 with self.assertRaises(ssl.SSLError) as e:
2329 server_params_test(client_context=server_context,
2330 server_context=server_context,
2331 chatty=True, connectionchatty=True)
2332 self.assertIn('called a function you should not call',
2333 str(e.exception))
2334
2335 with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT):
2336 with self.assertRaises(ssl.SSLError) as e:
2337 server_params_test(client_context=server_context,
2338 server_context=client_context,
2339 chatty=True, connectionchatty=True)
2340 self.assertIn('called a function you should not call',
2341 str(e.exception))
2342
Christian Heimes5fe668c2016-09-12 00:01:11 +02002343
Antoine Pitrou480a1242010-04-28 21:37:09 +00002344 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002345 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002346 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00002347 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2348 context.verify_mode = ssl.CERT_REQUIRED
2349 context.load_verify_locations(CERTFILE)
2350 context.load_cert_chain(CERTFILE)
2351 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002352 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02002353 s = context.wrap_socket(socket.socket(),
2354 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002355 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02002356 # getpeercert() raise ValueError while the handshake isn't
2357 # done.
2358 with self.assertRaises(ValueError):
2359 s.getpeercert()
2360 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002361 cert = s.getpeercert()
2362 self.assertTrue(cert, "Can't get peer certificate.")
2363 cipher = s.cipher()
2364 if support.verbose:
2365 sys.stdout.write(pprint.pformat(cert) + '\n')
2366 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2367 if 'subject' not in cert:
2368 self.fail("No subject field in certificate: %s." %
2369 pprint.pformat(cert))
2370 if ((('organizationName', 'Python Software Foundation'),)
2371 not in cert['subject']):
2372 self.fail(
2373 "Missing or invalid 'organizationName' field in certificate subject; "
2374 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00002375 self.assertIn('notBefore', cert)
2376 self.assertIn('notAfter', cert)
2377 before = ssl.cert_time_to_seconds(cert['notBefore'])
2378 after = ssl.cert_time_to_seconds(cert['notAfter'])
2379 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002380 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002381
Christian Heimes2427b502013-11-23 11:24:32 +01002382 @unittest.skipUnless(have_verify_flags(),
2383 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01002384 def test_crl_check(self):
2385 if support.verbose:
2386 sys.stdout.write("\n")
2387
2388 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2389 server_context.load_cert_chain(SIGNED_CERTFILE)
2390
2391 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2392 context.verify_mode = ssl.CERT_REQUIRED
2393 context.load_verify_locations(SIGNING_CA)
Benjamin Petersonc3d9c5c2015-03-04 23:18:48 -05002394 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
2395 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01002396
2397 # VERIFY_DEFAULT should pass
2398 server = ThreadedEchoServer(context=server_context, chatty=True)
2399 with server:
2400 with context.wrap_socket(socket.socket()) as s:
2401 s.connect((HOST, server.port))
2402 cert = s.getpeercert()
2403 self.assertTrue(cert, "Can't get peer certificate.")
2404
2405 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimes32f0c7a2013-11-22 03:43:48 +01002406 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Christian Heimes22587792013-11-21 23:56:13 +01002407
2408 server = ThreadedEchoServer(context=server_context, chatty=True)
2409 with server:
2410 with context.wrap_socket(socket.socket()) as s:
2411 with self.assertRaisesRegex(ssl.SSLError,
2412 "certificate verify failed"):
2413 s.connect((HOST, server.port))
2414
2415 # now load a CRL file. The CRL file is signed by the CA.
2416 context.load_verify_locations(CRLFILE)
2417
2418 server = ThreadedEchoServer(context=server_context, chatty=True)
2419 with server:
2420 with context.wrap_socket(socket.socket()) as s:
2421 s.connect((HOST, server.port))
2422 cert = s.getpeercert()
2423 self.assertTrue(cert, "Can't get peer certificate.")
2424
Christian Heimes1aa9a752013-12-02 02:41:19 +01002425 def test_check_hostname(self):
2426 if support.verbose:
2427 sys.stdout.write("\n")
2428
2429 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2430 server_context.load_cert_chain(SIGNED_CERTFILE)
2431
2432 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2433 context.verify_mode = ssl.CERT_REQUIRED
2434 context.check_hostname = True
2435 context.load_verify_locations(SIGNING_CA)
2436
2437 # correct hostname should verify
2438 server = ThreadedEchoServer(context=server_context, chatty=True)
2439 with server:
2440 with context.wrap_socket(socket.socket(),
2441 server_hostname="localhost") as s:
2442 s.connect((HOST, server.port))
2443 cert = s.getpeercert()
2444 self.assertTrue(cert, "Can't get peer certificate.")
2445
2446 # incorrect hostname should raise an exception
2447 server = ThreadedEchoServer(context=server_context, chatty=True)
2448 with server:
2449 with context.wrap_socket(socket.socket(),
2450 server_hostname="invalid") as s:
2451 with self.assertRaisesRegex(ssl.CertificateError,
2452 "hostname 'invalid' doesn't match 'localhost'"):
2453 s.connect((HOST, server.port))
2454
2455 # missing server_hostname arg should cause an exception, too
2456 server = ThreadedEchoServer(context=server_context, chatty=True)
2457 with server:
2458 with socket.socket() as s:
2459 with self.assertRaisesRegex(ValueError,
2460 "check_hostname requires server_hostname"):
2461 context.wrap_socket(s)
2462
Martin Panter407b62f2016-01-30 03:41:43 +00002463 def test_wrong_cert(self):
Martin Panter3464ea22016-02-01 21:58:11 +00002464 """Connecting when the server rejects the client's certificate
2465
2466 Launch a server with CERT_REQUIRED, and check that trying to
2467 connect to it with a wrong client certificate fails.
2468 """
2469 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
2470 "wrongcert.pem")
2471 server = ThreadedEchoServer(CERTFILE,
2472 certreqs=ssl.CERT_REQUIRED,
2473 cacerts=CERTFILE, chatty=False,
2474 connectionchatty=False)
2475 with server, \
2476 socket.socket() as sock, \
Christian Heimesd0486372016-09-10 23:23:33 +02002477 test_wrap_socket(sock,
Martin Panter3464ea22016-02-01 21:58:11 +00002478 certfile=certfile,
2479 ssl_version=ssl.PROTOCOL_TLSv1) as s:
2480 try:
2481 # Expect either an SSL error about the server rejecting
2482 # the connection, or a low-level connection reset (which
2483 # sometimes happens on Windows)
2484 s.connect((HOST, server.port))
2485 except ssl.SSLError as e:
2486 if support.verbose:
2487 sys.stdout.write("\nSSLError is %r\n" % e)
2488 except OSError as e:
2489 if e.errno != errno.ECONNRESET:
2490 raise
2491 if support.verbose:
2492 sys.stdout.write("\nsocket.error is %r\n" % e)
2493 else:
2494 self.fail("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002495
Antoine Pitrou480a1242010-04-28 21:37:09 +00002496 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002497 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00002498 in the client when attempting handshake.
2499 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00002500 listener_ready = threading.Event()
2501 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00002502
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002503 s = socket.socket()
2504 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002505
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002506 # `listener` runs in a thread. It sits in an accept() until
2507 # the main thread connects. Then it rudely closes the socket,
2508 # and sets Event `listener_gone` to let the main thread know
2509 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00002510 def listener():
Charles-François Natali6e204602014-07-23 19:28:13 +01002511 s.listen()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002512 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002513 newsock, addr = s.accept()
2514 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002515 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002516 listener_gone.set()
2517
2518 def connector():
2519 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002520 with socket.socket() as c:
2521 c.connect((HOST, port))
2522 listener_gone.wait()
2523 try:
Christian Heimesd0486372016-09-10 23:23:33 +02002524 ssl_sock = test_wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002525 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00002526 pass
2527 else:
2528 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00002529
2530 t = threading.Thread(target=listener)
2531 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002532 try:
2533 connector()
2534 finally:
2535 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002536
Antoine Pitrou23df4832010-08-04 17:14:06 +00002537 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02002538 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2539 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002540 def test_protocol_sslv2(self):
2541 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002542 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002543 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002544 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2545 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2546 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002547 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Victor Stinner648b8622014-12-12 12:23:59 +01002548 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2549 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002550 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002551 # SSLv23 client with specific SSL options
2552 if no_sslv2_implies_sslv3_hello():
2553 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2554 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2555 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002556 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002557 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002558 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002559 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002560
Antoine Pitrou23df4832010-08-04 17:14:06 +00002561 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002562 def test_protocol_sslv23(self):
2563 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002564 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002565 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02002566 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2567 try:
2568 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02002569 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02002570 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2571 if support.verbose:
2572 sys.stdout.write(
2573 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2574 % str(x))
Benjamin Petersone32467c2014-12-05 21:59:35 -05002575 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002576 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002577 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
Antoine Pitrou47e40422014-09-04 21:00:10 +02002578 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002579
Benjamin Petersone32467c2014-12-05 21:59:35 -05002580 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002581 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002582 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
Antoine Pitrou47e40422014-09-04 21:00:10 +02002583 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002584
Benjamin Petersone32467c2014-12-05 21:59:35 -05002585 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002586 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002587 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
Antoine Pitrou47e40422014-09-04 21:00:10 +02002588 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002589
Antoine Pitroub5218772010-05-21 09:56:06 +00002590 # Server with specific SSL options
Benjamin Petersone32467c2014-12-05 21:59:35 -05002591 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2592 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002593 server_options=ssl.OP_NO_SSLv3)
2594 # Will choose TLSv1
2595 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2596 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2597 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2598 server_options=ssl.OP_NO_TLSv1)
2599
2600
Antoine Pitrou23df4832010-08-04 17:14:06 +00002601 @skip_if_broken_ubuntu_ssl
Benjamin Petersone32467c2014-12-05 21:59:35 -05002602 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2603 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002604 def test_protocol_sslv3(self):
2605 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002606 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002607 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002608 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
2609 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
2610 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002611 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2612 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002613 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2614 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002615 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002616 if no_sslv2_implies_sslv3_hello():
2617 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002618 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23,
2619 False, client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002620
Antoine Pitrou23df4832010-08-04 17:14:06 +00002621 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002622 def test_protocol_tlsv1(self):
2623 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002624 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002625 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002626 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
2627 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
2628 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002629 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2630 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002631 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2632 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002633 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2634 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002635
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002636 @skip_if_broken_ubuntu_ssl
2637 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2638 "TLS version 1.1 not supported.")
2639 def test_protocol_tlsv1_1(self):
2640 """Connecting to a TLSv1.1 server with various client options.
2641 Testing against older TLS versions."""
2642 if support.verbose:
2643 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002644 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002645 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2646 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002647 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2648 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002649 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2650 client_options=ssl.OP_NO_TLSv1_1)
2651
Antoine Pitrou47e40422014-09-04 21:00:10 +02002652 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002653 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2654 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2655
2656
2657 @skip_if_broken_ubuntu_ssl
2658 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2659 "TLS version 1.2 not supported.")
2660 def test_protocol_tlsv1_2(self):
2661 """Connecting to a TLSv1.2 server with various client options.
2662 Testing against older TLS versions."""
2663 if support.verbose:
2664 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002665 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002666 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2667 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2668 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2669 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002670 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2671 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002672 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2673 client_options=ssl.OP_NO_TLSv1_2)
2674
Antoine Pitrou47e40422014-09-04 21:00:10 +02002675 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002676 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2677 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2678 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2679 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
2680
Antoine Pitrou480a1242010-04-28 21:37:09 +00002681 def test_starttls(self):
2682 """Switching from clear text to encrypted and back again."""
2683 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002684
Trent Nelson78520002008-04-10 20:54:35 +00002685 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002686 ssl_version=ssl.PROTOCOL_TLSv1,
2687 starttls_server=True,
2688 chatty=True,
2689 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002690 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002691 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002692 s = socket.socket()
2693 s.setblocking(1)
2694 s.connect((HOST, server.port))
2695 if support.verbose:
2696 sys.stdout.write("\n")
2697 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002698 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002699 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002700 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002701 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002702 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002703 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002704 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002705 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002706 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002707 msg = outdata.strip().lower()
2708 if indata == b"STARTTLS" and msg.startswith(b"ok"):
2709 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002710 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002711 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002712 " client: read %r from server, starting TLS...\n"
2713 % msg)
Christian Heimesd0486372016-09-10 23:23:33 +02002714 conn = test_wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002715 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00002716 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
2717 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002718 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002719 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002720 " client: read %r from server, ending TLS...\n"
2721 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002722 s = conn.unwrap()
2723 wrapped = False
2724 else:
2725 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002726 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002727 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002728 if support.verbose:
2729 sys.stdout.write(" client: closing connection.\n")
2730 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002731 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002732 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002733 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00002734 if wrapped:
2735 conn.close()
2736 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002737 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002738
Antoine Pitrou480a1242010-04-28 21:37:09 +00002739 def test_socketserver(self):
Martin Panter463ef2b2016-09-22 09:37:56 +00002740 """Using socketserver to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01002741 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002742 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002743 if support.verbose:
2744 sys.stdout.write('\n')
2745 with open(CERTFILE, 'rb') as f:
2746 d1 = f.read()
2747 d2 = ''
2748 # now fetch the same data from the HTTPS server
Benjamin Peterson4ffb0752014-11-03 14:29:33 -05002749 url = 'https://localhost:%d/%s' % (
2750 server.port, os.path.split(CERTFILE)[1])
2751 context = ssl.create_default_context(cafile=CERTFILE)
2752 f = urllib.request.urlopen(url, context=context)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002753 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00002754 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002755 if dlen and (int(dlen) > 0):
2756 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002757 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002758 sys.stdout.write(
2759 " client: read %d bytes from remote server '%s'\n"
2760 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002761 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002762 f.close()
2763 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002764
Antoine Pitrou480a1242010-04-28 21:37:09 +00002765 def test_asyncore_server(self):
2766 """Check the example asyncore integration."""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002767 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002768 sys.stdout.write("\n")
2769
Antoine Pitrou480a1242010-04-28 21:37:09 +00002770 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00002771 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002772 with server:
Christian Heimesd0486372016-09-10 23:23:33 +02002773 s = test_wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002774 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002775 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002776 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002777 " client: sending %r...\n" % indata)
2778 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002779 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002780 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002781 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002782 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002783 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002784 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2785 % (outdata[:20], len(outdata),
2786 indata[:20].lower(), len(indata)))
2787 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002788 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002789 sys.stdout.write(" client: closing connection.\n")
2790 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00002791 if support.verbose:
2792 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00002793
Antoine Pitrou480a1242010-04-28 21:37:09 +00002794 def test_recv_send(self):
2795 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00002796 if support.verbose:
2797 sys.stdout.write("\n")
2798
2799 server = ThreadedEchoServer(CERTFILE,
2800 certreqs=ssl.CERT_NONE,
2801 ssl_version=ssl.PROTOCOL_TLSv1,
2802 cacerts=CERTFILE,
2803 chatty=True,
2804 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002805 with server:
Christian Heimesd0486372016-09-10 23:23:33 +02002806 s = test_wrap_socket(socket.socket(),
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002807 server_side=False,
2808 certfile=CERTFILE,
2809 ca_certs=CERTFILE,
2810 cert_reqs=ssl.CERT_NONE,
2811 ssl_version=ssl.PROTOCOL_TLSv1)
2812 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002813 # helper methods for standardising recv* method signatures
2814 def _recv_into():
2815 b = bytearray(b"\0"*100)
2816 count = s.recv_into(b)
2817 return b[:count]
2818
2819 def _recvfrom_into():
2820 b = bytearray(b"\0"*100)
2821 count, addr = s.recvfrom_into(b)
2822 return b[:count]
2823
Martin Panter519f9122016-04-03 02:12:54 +00002824 # (name, method, expect success?, *args, return value func)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002825 send_methods = [
Martin Panter519f9122016-04-03 02:12:54 +00002826 ('send', s.send, True, [], len),
2827 ('sendto', s.sendto, False, ["some.address"], len),
2828 ('sendall', s.sendall, True, [], lambda x: None),
Bill Janssen58afe4c2008-09-08 16:45:19 +00002829 ]
Martin Panter519f9122016-04-03 02:12:54 +00002830 # (name, method, whether to expect success, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002831 recv_methods = [
2832 ('recv', s.recv, True, []),
2833 ('recvfrom', s.recvfrom, False, ["some.address"]),
2834 ('recv_into', _recv_into, True, []),
2835 ('recvfrom_into', _recvfrom_into, False, []),
2836 ]
2837 data_prefix = "PREFIX_"
2838
Martin Panter519f9122016-04-03 02:12:54 +00002839 for (meth_name, send_meth, expect_success, args,
2840 ret_val_meth) in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002841 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002842 try:
Martin Panter519f9122016-04-03 02:12:54 +00002843 ret = send_meth(indata, *args)
2844 msg = "sending with {}".format(meth_name)
2845 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002846 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002847 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002848 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002849 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002850 "<<{outdata:r}>> ({nout:d}) received; "
2851 "expected <<{indata:r}>> ({nin:d})\n".format(
2852 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002853 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002854 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002855 )
2856 )
2857 except ValueError as e:
2858 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002859 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002860 "Failed to send with method <<{name:s}>>; "
2861 "expected to succeed.\n".format(name=meth_name)
2862 )
2863 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002864 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002865 "Method <<{name:s}>> failed with unexpected "
2866 "exception message: {exp:s}\n".format(
2867 name=meth_name, exp=e
2868 )
2869 )
2870
2871 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002872 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002873 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002874 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002875 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002876 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002877 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002878 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002879 "<<{outdata:r}>> ({nout:d}) received; "
2880 "expected <<{indata:r}>> ({nin:d})\n".format(
2881 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002882 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002883 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002884 )
2885 )
2886 except ValueError as e:
2887 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002888 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002889 "Failed to receive with method <<{name:s}>>; "
2890 "expected to succeed.\n".format(name=meth_name)
2891 )
2892 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002893 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002894 "Method <<{name:s}>> failed with unexpected "
2895 "exception message: {exp:s}\n".format(
2896 name=meth_name, exp=e
2897 )
2898 )
2899 # consume data
2900 s.read()
2901
Martin Panterf6b1d662016-03-28 00:22:09 +00002902 # read(-1, buffer) is supported, even though read(-1) is not
Martin Panterbed7f1a2016-07-11 00:17:13 +00002903 data = b"data"
Martin Panter5503d472016-03-27 05:35:19 +00002904 s.send(data)
2905 buffer = bytearray(len(data))
2906 self.assertEqual(s.read(-1, buffer), len(data))
2907 self.assertEqual(buffer, data)
2908
Nick Coghlan513886a2011-08-28 00:00:27 +10002909 # Make sure sendmsg et al are disallowed to avoid
2910 # inadvertent disclosure of data and/or corruption
2911 # of the encrypted data stream
2912 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2913 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2914 self.assertRaises(NotImplementedError,
2915 s.recvmsg_into, bytearray(100))
2916
Antoine Pitrou480a1242010-04-28 21:37:09 +00002917 s.write(b"over\n")
Martin Panter5503d472016-03-27 05:35:19 +00002918
2919 self.assertRaises(ValueError, s.recv, -1)
2920 self.assertRaises(ValueError, s.read, -1)
2921
Bill Janssen58afe4c2008-09-08 16:45:19 +00002922 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002923
Martin Panterbed7f1a2016-07-11 00:17:13 +00002924 def test_recv_zero(self):
2925 server = ThreadedEchoServer(CERTFILE)
2926 server.__enter__()
2927 self.addCleanup(server.__exit__, None, None)
2928 s = socket.create_connection((HOST, server.port))
2929 self.addCleanup(s.close)
Christian Heimesd0486372016-09-10 23:23:33 +02002930 s = test_wrap_socket(s, suppress_ragged_eofs=False)
Martin Panterbed7f1a2016-07-11 00:17:13 +00002931 self.addCleanup(s.close)
2932
2933 # recv/read(0) should return no data
2934 s.send(b"data")
2935 self.assertEqual(s.recv(0), b"")
2936 self.assertEqual(s.read(0), b"")
2937 self.assertEqual(s.read(), b"data")
2938
2939 # Should not block if the other end sends no data
2940 s.setblocking(False)
2941 self.assertEqual(s.recv(0), b"")
2942 self.assertEqual(s.recv_into(bytearray()), 0)
2943
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002944 def test_nonblocking_send(self):
2945 server = ThreadedEchoServer(CERTFILE,
2946 certreqs=ssl.CERT_NONE,
2947 ssl_version=ssl.PROTOCOL_TLSv1,
2948 cacerts=CERTFILE,
2949 chatty=True,
2950 connectionchatty=False)
2951 with server:
Christian Heimesd0486372016-09-10 23:23:33 +02002952 s = test_wrap_socket(socket.socket(),
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002953 server_side=False,
2954 certfile=CERTFILE,
2955 ca_certs=CERTFILE,
2956 cert_reqs=ssl.CERT_NONE,
2957 ssl_version=ssl.PROTOCOL_TLSv1)
2958 s.connect((HOST, server.port))
2959 s.setblocking(False)
2960
2961 # If we keep sending data, at some point the buffers
2962 # will be full and the call will block
2963 buf = bytearray(8192)
2964 def fill_buffer():
2965 while True:
2966 s.send(buf)
2967 self.assertRaises((ssl.SSLWantWriteError,
2968 ssl.SSLWantReadError), fill_buffer)
2969
2970 # Now read all the output and discard it
2971 s.setblocking(True)
2972 s.close()
2973
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002974 def test_handshake_timeout(self):
2975 # Issue #5103: SSL handshake must respect the socket timeout
2976 server = socket.socket(socket.AF_INET)
2977 host = "127.0.0.1"
2978 port = support.bind_port(server)
2979 started = threading.Event()
2980 finish = False
2981
2982 def serve():
Charles-François Natali6e204602014-07-23 19:28:13 +01002983 server.listen()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002984 started.set()
2985 conns = []
2986 while not finish:
2987 r, w, e = select.select([server], [], [], 0.1)
2988 if server in r:
2989 # Let the socket hang around rather than having
2990 # it closed by garbage collection.
2991 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002992 for sock in conns:
2993 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002994
2995 t = threading.Thread(target=serve)
2996 t.start()
2997 started.wait()
2998
2999 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00003000 try:
3001 c = socket.socket(socket.AF_INET)
3002 c.settimeout(0.2)
3003 c.connect((host, port))
3004 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00003005 self.assertRaisesRegex(socket.timeout, "timed out",
Christian Heimesd0486372016-09-10 23:23:33 +02003006 test_wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00003007 finally:
3008 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003009 try:
3010 c = socket.socket(socket.AF_INET)
Christian Heimesd0486372016-09-10 23:23:33 +02003011 c = test_wrap_socket(c)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003012 c.settimeout(0.2)
3013 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00003014 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00003015 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00003016 finally:
3017 c.close()
3018 finally:
3019 finish = True
3020 t.join()
3021 server.close()
3022
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003023 def test_server_accept(self):
3024 # Issue #16357: accept() on a SSLSocket created through
3025 # SSLContext.wrap_socket().
3026 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3027 context.verify_mode = ssl.CERT_REQUIRED
3028 context.load_verify_locations(CERTFILE)
3029 context.load_cert_chain(CERTFILE)
3030 server = socket.socket(socket.AF_INET)
3031 host = "127.0.0.1"
3032 port = support.bind_port(server)
3033 server = context.wrap_socket(server, server_side=True)
Christian Heimesa5d07652016-09-24 10:48:05 +02003034 self.assertTrue(server.server_side)
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003035
3036 evt = threading.Event()
3037 remote = None
3038 peer = None
3039 def serve():
3040 nonlocal remote, peer
Charles-François Natali6e204602014-07-23 19:28:13 +01003041 server.listen()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003042 # Block on the accept and wait on the connection to close.
3043 evt.set()
3044 remote, peer = server.accept()
3045 remote.recv(1)
3046
3047 t = threading.Thread(target=serve)
3048 t.start()
3049 # Client wait until server setup and perform a connect.
3050 evt.wait()
3051 client = context.wrap_socket(socket.socket())
3052 client.connect((host, port))
3053 client_addr = client.getsockname()
3054 client.close()
3055 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01003056 remote.close()
3057 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01003058 # Sanity checks.
3059 self.assertIsInstance(remote, ssl.SSLSocket)
3060 self.assertEqual(peer, client_addr)
3061
Antoine Pitrou242db722013-05-01 20:52:07 +02003062 def test_getpeercert_enotconn(self):
3063 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3064 with context.wrap_socket(socket.socket()) as sock:
3065 with self.assertRaises(OSError) as cm:
3066 sock.getpeercert()
3067 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3068
3069 def test_do_handshake_enotconn(self):
3070 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3071 with context.wrap_socket(socket.socket()) as sock:
3072 with self.assertRaises(OSError) as cm:
3073 sock.do_handshake()
3074 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
3075
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003076 def test_default_ciphers(self):
3077 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3078 try:
3079 # Force a set of weak ciphers on our client context
3080 context.set_ciphers("DES")
3081 except ssl.SSLError:
3082 self.skipTest("no DES cipher available")
3083 with ThreadedEchoServer(CERTFILE,
3084 ssl_version=ssl.PROTOCOL_SSLv23,
3085 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01003086 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02003087 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01003088 s.connect((HOST, server.port))
3089 self.assertIn("no shared cipher", str(server.conn_errors[0]))
3090
Antoine Pitrou47e40422014-09-04 21:00:10 +02003091 def test_version_basic(self):
3092 """
3093 Basic tests for SSLSocket.version().
3094 More tests are done in the test_protocol_*() methods.
3095 """
3096 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3097 with ThreadedEchoServer(CERTFILE,
3098 ssl_version=ssl.PROTOCOL_TLSv1,
3099 chatty=False) as server:
3100 with context.wrap_socket(socket.socket()) as s:
3101 self.assertIs(s.version(), None)
3102 s.connect((HOST, server.port))
Christian Heimes598894f2016-09-05 23:19:05 +02003103 self.assertEqual(s.version(), 'TLSv1')
Antoine Pitrou47e40422014-09-04 21:00:10 +02003104 self.assertIs(s.version(), None)
3105
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01003106 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
3107 def test_default_ecdh_curve(self):
3108 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
3109 # should be enabled by default on SSL contexts.
3110 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3111 context.load_cert_chain(CERTFILE)
Antoine Pitrouc0430612014-04-16 18:33:39 +02003112 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
3113 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
3114 # our default cipher list should prefer ECDH-based ciphers
3115 # automatically.
3116 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
3117 context.set_ciphers("ECCdraft:ECDH")
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01003118 with ThreadedEchoServer(context=context) as server:
3119 with context.wrap_socket(socket.socket()) as s:
3120 s.connect((HOST, server.port))
3121 self.assertIn("ECDH", s.cipher()[0])
3122
Antoine Pitroud6494802011-07-21 01:11:30 +02003123 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
3124 "'tls-unique' channel binding not available")
3125 def test_tls_unique_channel_binding(self):
3126 """Test tls-unique channel binding."""
3127 if support.verbose:
3128 sys.stdout.write("\n")
3129
3130 server = ThreadedEchoServer(CERTFILE,
3131 certreqs=ssl.CERT_NONE,
3132 ssl_version=ssl.PROTOCOL_TLSv1,
3133 cacerts=CERTFILE,
3134 chatty=True,
3135 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01003136 with server:
Christian Heimesd0486372016-09-10 23:23:33 +02003137 s = test_wrap_socket(socket.socket(),
Antoine Pitrou6b15c902011-12-21 16:54:45 +01003138 server_side=False,
3139 certfile=CERTFILE,
3140 ca_certs=CERTFILE,
3141 cert_reqs=ssl.CERT_NONE,
3142 ssl_version=ssl.PROTOCOL_TLSv1)
3143 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003144 # get the data
3145 cb_data = s.get_channel_binding("tls-unique")
3146 if support.verbose:
3147 sys.stdout.write(" got channel binding data: {0!r}\n"
3148 .format(cb_data))
3149
3150 # check if it is sane
3151 self.assertIsNotNone(cb_data)
3152 self.assertEqual(len(cb_data), 12) # True for TLSv1
3153
3154 # and compare with the peers version
3155 s.write(b"CB tls-unique\n")
3156 peer_data_repr = s.read().strip()
3157 self.assertEqual(peer_data_repr,
3158 repr(cb_data).encode("us-ascii"))
3159 s.close()
3160
3161 # now, again
Christian Heimesd0486372016-09-10 23:23:33 +02003162 s = test_wrap_socket(socket.socket(),
Antoine Pitroud6494802011-07-21 01:11:30 +02003163 server_side=False,
3164 certfile=CERTFILE,
3165 ca_certs=CERTFILE,
3166 cert_reqs=ssl.CERT_NONE,
3167 ssl_version=ssl.PROTOCOL_TLSv1)
3168 s.connect((HOST, server.port))
3169 new_cb_data = s.get_channel_binding("tls-unique")
3170 if support.verbose:
3171 sys.stdout.write(" got another channel binding data: {0!r}\n"
3172 .format(new_cb_data))
3173 # is it really unique
3174 self.assertNotEqual(cb_data, new_cb_data)
3175 self.assertIsNotNone(cb_data)
3176 self.assertEqual(len(cb_data), 12) # True for TLSv1
3177 s.write(b"CB tls-unique\n")
3178 peer_data_repr = s.read().strip()
3179 self.assertEqual(peer_data_repr,
3180 repr(new_cb_data).encode("us-ascii"))
3181 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00003182
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003183 def test_compression(self):
3184 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3185 context.load_cert_chain(CERTFILE)
3186 stats = server_params_test(context, context,
3187 chatty=True, connectionchatty=True)
3188 if support.verbose:
3189 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
3190 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
3191
3192 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
3193 "ssl.OP_NO_COMPRESSION needed for this test")
3194 def test_compression_disabled(self):
3195 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3196 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01003197 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003198 stats = server_params_test(context, context,
3199 chatty=True, connectionchatty=True)
3200 self.assertIs(stats['compression'], None)
3201
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003202 def test_dh_params(self):
3203 # Check we can get a connection with ephemeral Diffie-Hellman
3204 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3205 context.load_cert_chain(CERTFILE)
3206 context.load_dh_params(DHFILE)
3207 context.set_ciphers("kEDH")
3208 stats = server_params_test(context, context,
3209 chatty=True, connectionchatty=True)
3210 cipher = stats["cipher"][0]
3211 parts = cipher.split("-")
3212 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
3213 self.fail("Non-DH cipher: " + cipher[0])
3214
Benjamin Petersoncca27322015-01-23 16:35:37 -05003215 def test_selected_alpn_protocol(self):
3216 # selected_alpn_protocol() is None unless ALPN is used.
3217 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3218 context.load_cert_chain(CERTFILE)
3219 stats = server_params_test(context, context,
3220 chatty=True, connectionchatty=True)
3221 self.assertIs(stats['client_alpn_protocol'], None)
3222
3223 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
3224 def test_selected_alpn_protocol_if_server_uses_alpn(self):
3225 # selected_alpn_protocol() is None unless ALPN is used by the client.
3226 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3227 client_context.load_verify_locations(CERTFILE)
3228 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3229 server_context.load_cert_chain(CERTFILE)
3230 server_context.set_alpn_protocols(['foo', 'bar'])
3231 stats = server_params_test(client_context, server_context,
3232 chatty=True, connectionchatty=True)
3233 self.assertIs(stats['client_alpn_protocol'], None)
3234
3235 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
3236 def test_alpn_protocols(self):
3237 server_protocols = ['foo', 'bar', 'milkshake']
3238 protocol_tests = [
3239 (['foo', 'bar'], 'foo'),
Benjamin Peterson88615022015-01-23 17:30:26 -05003240 (['bar', 'foo'], 'foo'),
Benjamin Petersoncca27322015-01-23 16:35:37 -05003241 (['milkshake'], 'milkshake'),
Benjamin Peterson88615022015-01-23 17:30:26 -05003242 (['http/3.0', 'http/4.0'], None)
Benjamin Petersoncca27322015-01-23 16:35:37 -05003243 ]
3244 for client_protocols, expected in protocol_tests:
Christian Heimes598894f2016-09-05 23:19:05 +02003245 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
Benjamin Petersoncca27322015-01-23 16:35:37 -05003246 server_context.load_cert_chain(CERTFILE)
3247 server_context.set_alpn_protocols(server_protocols)
Christian Heimes598894f2016-09-05 23:19:05 +02003248 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
Benjamin Petersoncca27322015-01-23 16:35:37 -05003249 client_context.load_cert_chain(CERTFILE)
3250 client_context.set_alpn_protocols(client_protocols)
Benjamin Petersoncca27322015-01-23 16:35:37 -05003251
Christian Heimes598894f2016-09-05 23:19:05 +02003252 try:
3253 stats = server_params_test(client_context,
3254 server_context,
3255 chatty=True,
3256 connectionchatty=True)
3257 except ssl.SSLError as e:
3258 stats = e
3259
3260 if expected is None and IS_OPENSSL_1_1:
3261 # OpenSSL 1.1.0 raises handshake error
3262 self.assertIsInstance(stats, ssl.SSLError)
3263 else:
3264 msg = "failed trying %s (s) and %s (c).\n" \
3265 "was expecting %s, but got %%s from the %%s" \
3266 % (str(server_protocols), str(client_protocols),
3267 str(expected))
3268 client_result = stats['client_alpn_protocol']
3269 self.assertEqual(client_result, expected,
3270 msg % (client_result, "client"))
3271 server_result = stats['server_alpn_protocols'][-1] \
3272 if len(stats['server_alpn_protocols']) else 'nothing'
3273 self.assertEqual(server_result, expected,
3274 msg % (server_result, "server"))
Benjamin Petersoncca27322015-01-23 16:35:37 -05003275
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01003276 def test_selected_npn_protocol(self):
3277 # selected_npn_protocol() is None unless NPN is used
3278 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3279 context.load_cert_chain(CERTFILE)
3280 stats = server_params_test(context, context,
3281 chatty=True, connectionchatty=True)
3282 self.assertIs(stats['client_npn_protocol'], None)
3283
3284 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
3285 def test_npn_protocols(self):
3286 server_protocols = ['http/1.1', 'spdy/2']
3287 protocol_tests = [
3288 (['http/1.1', 'spdy/2'], 'http/1.1'),
3289 (['spdy/2', 'http/1.1'], 'http/1.1'),
3290 (['spdy/2', 'test'], 'spdy/2'),
3291 (['abc', 'def'], 'abc')
3292 ]
3293 for client_protocols, expected in protocol_tests:
3294 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3295 server_context.load_cert_chain(CERTFILE)
3296 server_context.set_npn_protocols(server_protocols)
3297 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3298 client_context.load_cert_chain(CERTFILE)
3299 client_context.set_npn_protocols(client_protocols)
3300 stats = server_params_test(client_context, server_context,
3301 chatty=True, connectionchatty=True)
3302
3303 msg = "failed trying %s (s) and %s (c).\n" \
3304 "was expecting %s, but got %%s from the %%s" \
3305 % (str(server_protocols), str(client_protocols),
3306 str(expected))
3307 client_result = stats['client_npn_protocol']
3308 self.assertEqual(client_result, expected, msg % (client_result, "client"))
3309 server_result = stats['server_npn_protocols'][-1] \
3310 if len(stats['server_npn_protocols']) else 'nothing'
3311 self.assertEqual(server_result, expected, msg % (server_result, "server"))
3312
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003313 def sni_contexts(self):
3314 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3315 server_context.load_cert_chain(SIGNED_CERTFILE)
3316 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3317 other_context.load_cert_chain(SIGNED_CERTFILE2)
3318 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3319 client_context.verify_mode = ssl.CERT_REQUIRED
3320 client_context.load_verify_locations(SIGNING_CA)
3321 return server_context, other_context, client_context
3322
3323 def check_common_name(self, stats, name):
3324 cert = stats['peercert']
3325 self.assertIn((('commonName', name),), cert['subject'])
3326
3327 @needs_sni
3328 def test_sni_callback(self):
3329 calls = []
3330 server_context, other_context, client_context = self.sni_contexts()
3331
3332 def servername_cb(ssl_sock, server_name, initial_context):
3333 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02003334 if server_name is not None:
3335 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003336 server_context.set_servername_callback(servername_cb)
3337
3338 stats = server_params_test(client_context, server_context,
3339 chatty=True,
3340 sni_name='supermessage')
3341 # The hostname was fetched properly, and the certificate was
3342 # changed for the connection.
3343 self.assertEqual(calls, [("supermessage", server_context)])
3344 # CERTFILE4 was selected
3345 self.check_common_name(stats, 'fakehostname')
3346
Antoine Pitrou50b24d02013-04-11 20:48:42 +02003347 calls = []
3348 # The callback is called with server_name=None
3349 stats = server_params_test(client_context, server_context,
3350 chatty=True,
3351 sni_name=None)
3352 self.assertEqual(calls, [(None, server_context)])
3353 self.check_common_name(stats, 'localhost')
3354
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003355 # Check disabling the callback
3356 calls = []
3357 server_context.set_servername_callback(None)
3358
3359 stats = server_params_test(client_context, server_context,
3360 chatty=True,
3361 sni_name='notfunny')
3362 # Certificate didn't change
3363 self.check_common_name(stats, 'localhost')
3364 self.assertEqual(calls, [])
3365
3366 @needs_sni
3367 def test_sni_callback_alert(self):
3368 # Returning a TLS alert is reflected to the connecting client
3369 server_context, other_context, client_context = self.sni_contexts()
3370
3371 def cb_returning_alert(ssl_sock, server_name, initial_context):
3372 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
3373 server_context.set_servername_callback(cb_returning_alert)
3374
3375 with self.assertRaises(ssl.SSLError) as cm:
3376 stats = server_params_test(client_context, server_context,
3377 chatty=False,
3378 sni_name='supermessage')
3379 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
3380
3381 @needs_sni
3382 def test_sni_callback_raising(self):
3383 # Raising fails the connection with a TLS handshake failure alert.
3384 server_context, other_context, client_context = self.sni_contexts()
3385
3386 def cb_raising(ssl_sock, server_name, initial_context):
3387 1/0
3388 server_context.set_servername_callback(cb_raising)
3389
3390 with self.assertRaises(ssl.SSLError) as cm, \
3391 support.captured_stderr() as stderr:
3392 stats = server_params_test(client_context, server_context,
3393 chatty=False,
3394 sni_name='supermessage')
3395 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
3396 self.assertIn("ZeroDivisionError", stderr.getvalue())
3397
3398 @needs_sni
3399 def test_sni_callback_wrong_return_type(self):
3400 # Returning the wrong return type terminates the TLS connection
3401 # with an internal error alert.
3402 server_context, other_context, client_context = self.sni_contexts()
3403
3404 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
3405 return "foo"
3406 server_context.set_servername_callback(cb_wrong_return_type)
3407
3408 with self.assertRaises(ssl.SSLError) as cm, \
3409 support.captured_stderr() as stderr:
3410 stats = server_params_test(client_context, server_context,
3411 chatty=False,
3412 sni_name='supermessage')
3413 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
3414 self.assertIn("TypeError", stderr.getvalue())
3415
Benjamin Peterson4cb17812015-01-07 11:14:26 -06003416 def test_shared_ciphers(self):
Benjamin Petersonaacd5242015-01-07 11:42:38 -06003417 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson15042922015-01-07 22:12:43 -06003418 server_context.load_cert_chain(SIGNED_CERTFILE)
3419 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3420 client_context.verify_mode = ssl.CERT_REQUIRED
3421 client_context.load_verify_locations(SIGNING_CA)
Christian Heimes598894f2016-09-05 23:19:05 +02003422 if ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
3423 client_context.set_ciphers("AES128:AES256")
3424 server_context.set_ciphers("AES256")
3425 alg1 = "AES256"
3426 alg2 = "AES-256"
3427 else:
3428 client_context.set_ciphers("AES:3DES")
3429 server_context.set_ciphers("3DES")
3430 alg1 = "3DES"
3431 alg2 = "DES-CBC3"
3432
Benjamin Peterson4cb17812015-01-07 11:14:26 -06003433 stats = server_params_test(client_context, server_context)
3434 ciphers = stats['server_shared_ciphers'][0]
3435 self.assertGreater(len(ciphers), 0)
3436 for name, tls_version, bits in ciphers:
Christian Heimes598894f2016-09-05 23:19:05 +02003437 if not alg1 in name.split("-") and alg2 not in name:
3438 self.fail(name)
Benjamin Peterson4cb17812015-01-07 11:14:26 -06003439
Antoine Pitrou60a26e02013-07-20 19:35:16 +02003440 def test_read_write_after_close_raises_valuerror(self):
3441 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3442 context.verify_mode = ssl.CERT_REQUIRED
3443 context.load_verify_locations(CERTFILE)
3444 context.load_cert_chain(CERTFILE)
3445 server = ThreadedEchoServer(context=context, chatty=False)
3446
3447 with server:
3448 s = context.wrap_socket(socket.socket())
3449 s.connect((HOST, server.port))
3450 s.close()
3451
3452 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02003453 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02003454
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02003455 def test_sendfile(self):
3456 TEST_DATA = b"x" * 512
3457 with open(support.TESTFN, 'wb') as f:
3458 f.write(TEST_DATA)
3459 self.addCleanup(support.unlink, support.TESTFN)
3460 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3461 context.verify_mode = ssl.CERT_REQUIRED
3462 context.load_verify_locations(CERTFILE)
3463 context.load_cert_chain(CERTFILE)
3464 server = ThreadedEchoServer(context=context, chatty=False)
3465 with server:
3466 with context.wrap_socket(socket.socket()) as s:
3467 s.connect((HOST, server.port))
3468 with open(support.TESTFN, 'rb') as file:
3469 s.sendfile(file)
3470 self.assertEqual(s.recv(1024), TEST_DATA)
3471
Christian Heimes99a65702016-09-10 23:44:53 +02003472 def test_session(self):
3473 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3474 server_context.load_cert_chain(SIGNED_CERTFILE)
3475 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3476 client_context.verify_mode = ssl.CERT_REQUIRED
3477 client_context.load_verify_locations(SIGNING_CA)
3478
Martin Panterb1321fb2016-10-10 00:38:21 +00003479 # first connection without session
Christian Heimes99a65702016-09-10 23:44:53 +02003480 stats = server_params_test(client_context, server_context)
3481 session = stats['session']
3482 self.assertTrue(session.id)
3483 self.assertGreater(session.time, 0)
3484 self.assertGreater(session.timeout, 0)
3485 self.assertTrue(session.has_ticket)
3486 if ssl.OPENSSL_VERSION_INFO > (1, 0, 1):
3487 self.assertGreater(session.ticket_lifetime_hint, 0)
3488 self.assertFalse(stats['session_reused'])
3489 sess_stat = server_context.session_stats()
3490 self.assertEqual(sess_stat['accept'], 1)
3491 self.assertEqual(sess_stat['hits'], 0)
3492
3493 # reuse session
3494 stats = server_params_test(client_context, server_context, session=session)
3495 sess_stat = server_context.session_stats()
3496 self.assertEqual(sess_stat['accept'], 2)
3497 self.assertEqual(sess_stat['hits'], 1)
3498 self.assertTrue(stats['session_reused'])
3499 session2 = stats['session']
3500 self.assertEqual(session2.id, session.id)
3501 self.assertEqual(session2, session)
3502 self.assertIsNot(session2, session)
3503 self.assertGreaterEqual(session2.time, session.time)
3504 self.assertGreaterEqual(session2.timeout, session.timeout)
3505
3506 # another one without session
3507 stats = server_params_test(client_context, server_context)
3508 self.assertFalse(stats['session_reused'])
3509 session3 = stats['session']
3510 self.assertNotEqual(session3.id, session.id)
3511 self.assertNotEqual(session3, session)
3512 sess_stat = server_context.session_stats()
3513 self.assertEqual(sess_stat['accept'], 3)
3514 self.assertEqual(sess_stat['hits'], 1)
3515
3516 # reuse session again
3517 stats = server_params_test(client_context, server_context, session=session)
3518 self.assertTrue(stats['session_reused'])
3519 session4 = stats['session']
3520 self.assertEqual(session4.id, session.id)
3521 self.assertEqual(session4, session)
3522 self.assertGreaterEqual(session4.time, session.time)
3523 self.assertGreaterEqual(session4.timeout, session.timeout)
3524 sess_stat = server_context.session_stats()
3525 self.assertEqual(sess_stat['accept'], 4)
3526 self.assertEqual(sess_stat['hits'], 2)
3527
3528 def test_session_handling(self):
3529 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3530 context.verify_mode = ssl.CERT_REQUIRED
3531 context.load_verify_locations(CERTFILE)
3532 context.load_cert_chain(CERTFILE)
3533
3534 context2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3535 context2.verify_mode = ssl.CERT_REQUIRED
3536 context2.load_verify_locations(CERTFILE)
3537 context2.load_cert_chain(CERTFILE)
3538
3539 server = ThreadedEchoServer(context=context, chatty=False)
3540 with server:
3541 with context.wrap_socket(socket.socket()) as s:
3542 # session is None before handshake
3543 self.assertEqual(s.session, None)
3544 self.assertEqual(s.session_reused, None)
3545 s.connect((HOST, server.port))
3546 session = s.session
3547 self.assertTrue(session)
3548 with self.assertRaises(TypeError) as e:
3549 s.session = object
3550 self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
3551
3552 with context.wrap_socket(socket.socket()) as s:
3553 s.connect((HOST, server.port))
3554 # cannot set session after handshake
3555 with self.assertRaises(ValueError) as e:
3556 s.session = session
3557 self.assertEqual(str(e.exception),
3558 'Cannot set session after handshake.')
3559
3560 with context.wrap_socket(socket.socket()) as s:
3561 # can set session before handshake and before the
3562 # connection was established
3563 s.session = session
3564 s.connect((HOST, server.port))
3565 self.assertEqual(s.session.id, session.id)
3566 self.assertEqual(s.session, session)
3567 self.assertEqual(s.session_reused, True)
3568
3569 with context2.wrap_socket(socket.socket()) as s:
3570 # cannot re-use session with a different SSLContext
3571 with self.assertRaises(ValueError) as e:
3572 s.session = session
3573 s.connect((HOST, server.port))
3574 self.assertEqual(str(e.exception),
3575 'Session refers to a different SSLContext.')
3576
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003577
Thomas Woutersed03b412007-08-28 21:37:11 +00003578def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00003579 if support.verbose:
Berker Peksag9e7990a2015-05-16 23:21:26 +03003580 import warnings
Antoine Pitrou15cee622010-08-04 16:45:21 +00003581 plats = {
3582 'Linux': platform.linux_distribution,
3583 'Mac': platform.mac_ver,
3584 'Windows': platform.win32_ver,
3585 }
Berker Peksag9e7990a2015-05-16 23:21:26 +03003586 with warnings.catch_warnings():
3587 warnings.filterwarnings(
3588 'ignore',
R David Murray44b548d2016-09-08 13:59:53 -04003589 r'dist\(\) and linux_distribution\(\) '
Berker Peksag9e7990a2015-05-16 23:21:26 +03003590 'functions are deprecated .*',
3591 PendingDeprecationWarning,
3592 )
3593 for name, func in plats.items():
3594 plat = func()
3595 if plat and plat[0]:
3596 plat = '%s %r' % (name, plat)
3597 break
3598 else:
3599 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00003600 print("test_ssl: testing with %r %r" %
3601 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
3602 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00003603 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01003604 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
3605 try:
3606 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
3607 except AttributeError:
3608 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00003609
Antoine Pitrou152efa22010-05-16 18:19:27 +00003610 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00003611 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00003612 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003613 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00003614 BADCERT, BADKEY, EMPTYCERT]:
3615 if not os.path.exists(filename):
3616 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00003617
Martin Panter3840b2a2016-03-27 01:53:46 +00003618 tests = [
3619 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
3620 SimpleBackgroundTests,
3621 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00003622
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003623 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00003624 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00003625
Thomas Wouters1b7f8912007-09-19 03:06:30 +00003626 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003627 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01003628 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00003629 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00003630
Antoine Pitrou480a1242010-04-28 21:37:09 +00003631 try:
3632 support.run_unittest(*tests)
3633 finally:
3634 if _have_threads:
3635 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00003636
3637if __name__ == "__main__":
3638 test_main()