blob: 00d437a951c5e44bc4d44d52fd0808a65cfb4fea [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 Pitrou152efa22010-05-16 18:19:27 +000014import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000015import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000016import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000017import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000018import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000019import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000020import functools
Thomas Woutersed03b412007-08-28 21:37:11 +000021
Antoine Pitrou05d936d2010-10-13 11:38:36 +000022ssl = support.import_module("ssl")
23
Martin Panter3840b2a2016-03-27 01:53:46 +000024try:
25 import threading
26except ImportError:
27 _have_threads = False
28else:
29 _have_threads = True
30
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010031PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000032HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000033
Christian Heimesefff7062013-11-21 03:35:02 +010034def data_file(*name):
35 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000036
Antoine Pitrou81564092010-10-08 23:06:24 +000037# The custom key and certificate files used in test_ssl are generated
38# using Lib/test/make_ssl_certs.py.
39# Other certificates are simply fetched from the Internet servers they
40# are meant to authenticate.
41
Antoine Pitrou152efa22010-05-16 18:19:27 +000042CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000044ONLYCERT = data_file("ssl_cert.pem")
45ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_ONLYCERT = os.fsencode(ONLYCERT)
47BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020048CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
49ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
50KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000051CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000052BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010053CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
54CAFILE_CACERT = data_file("capath", "5ed36f99.0")
55
Antoine Pitrou152efa22010-05-16 18:19:27 +000056
Christian Heimes22587792013-11-21 23:56:13 +010057# empty CRL
58CRLFILE = data_file("revocation.crl")
59
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010060# Two keys and certs signed by the same CA (for SNI tests)
61SIGNED_CERTFILE = data_file("keycert3.pem")
62SIGNED_CERTFILE2 = data_file("keycert4.pem")
Martin Panter3840b2a2016-03-27 01:53:46 +000063# Same certificate as pycacert.pem, but without extra text in file
64SIGNING_CA = data_file("capath", "ceff1710.0")
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010065
Martin Panter3d81d932016-01-14 09:36:00 +000066REMOTE_HOST = "self-signed.pythontest.net"
Antoine Pitrou152efa22010-05-16 18:19:27 +000067
68EMPTYCERT = data_file("nullcert.pem")
69BADCERT = data_file("badcert.pem")
Martin Panter407b62f2016-01-30 03:41:43 +000070NONEXISTINGCERT = data_file("XXXnonexisting.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000071BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020072NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020073NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000074
Benjamin Petersona7eaf562015-04-02 00:04:06 -040075DHFILE = data_file("dh1024.pem")
Antoine Pitrou0e576f12011-12-22 10:03:38 +010076BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000077
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010078
Thomas Woutersed03b412007-08-28 21:37:11 +000079def handle_error(prefix):
80 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000081 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000082 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000083
Antoine Pitroub5218772010-05-21 09:56:06 +000084def can_clear_options():
85 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020086 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000087
88def no_sslv2_implies_sslv3_hello():
89 # 0.9.7h or higher
90 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
91
Christian Heimes2427b502013-11-23 11:24:32 +010092def have_verify_flags():
93 # 0.9.8 or higher
94 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
95
Antoine Pitrouc695c952014-04-28 20:57:36 +020096def utc_offset(): #NOTE: ignore issues like #1647654
97 # local time = utc time + utc offset
98 if time.daylight and time.localtime().tm_isdst > 0:
99 return -time.altzone # seconds
100 return -time.timezone
101
Christian Heimes9424bb42013-06-17 15:32:57 +0200102def asn1time(cert_time):
103 # Some versions of OpenSSL ignore seconds, see #18207
104 # 0.9.8.i
105 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
106 fmt = "%b %d %H:%M:%S %Y GMT"
107 dt = datetime.datetime.strptime(cert_time, fmt)
108 dt = dt.replace(second=0)
109 cert_time = dt.strftime(fmt)
110 # %d adds leading zero but ASN1_TIME_print() uses leading space
111 if cert_time[4] == "0":
112 cert_time = cert_time[:4] + " " + cert_time[5:]
113
114 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000115
Antoine Pitrou23df4832010-08-04 17:14:06 +0000116# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
117def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +0200118 if hasattr(ssl, 'PROTOCOL_SSLv2'):
119 @functools.wraps(func)
120 def f(*args, **kwargs):
121 try:
122 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
123 except ssl.SSLError:
124 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
125 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
126 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
127 return func(*args, **kwargs)
128 return f
129 else:
130 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +0000131
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100132needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
133
Antoine Pitrou23df4832010-08-04 17:14:06 +0000134
Antoine Pitrou152efa22010-05-16 18:19:27 +0000135class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000136
Antoine Pitrou480a1242010-04-28 21:37:09 +0000137 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 ssl.CERT_NONE
139 ssl.CERT_OPTIONAL
140 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100141 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100142 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100143 if ssl.HAS_ECDH:
144 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100145 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
146 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000147 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100148 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000149
Antoine Pitrou172f0252014-04-18 20:33:08 +0200150 def test_str_for_enums(self):
151 # Make sure that the PROTOCOL_* constants have enum-like string
152 # reprs.
Victor Stinner648b8622014-12-12 12:23:59 +0100153 proto = ssl.PROTOCOL_SSLv23
154 self.assertEqual(str(proto), '_SSLMethod.PROTOCOL_SSLv23')
Antoine Pitrou172f0252014-04-18 20:33:08 +0200155 ctx = ssl.SSLContext(proto)
156 self.assertIs(ctx.protocol, proto)
157
Antoine Pitrou480a1242010-04-28 21:37:09 +0000158 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000159 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000160 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000161 sys.stdout.write("\n RAND_status is %d (%s)\n"
162 % (v, (v and "sufficient randomness") or
163 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200164
165 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
166 self.assertEqual(len(data), 16)
167 self.assertEqual(is_cryptographic, v == 1)
168 if v:
169 data = ssl.RAND_bytes(16)
170 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200171 else:
172 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200173
Victor Stinner1e81a392013-12-19 16:47:04 +0100174 # negative num is invalid
175 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
176 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
177
Victor Stinnerbeeb5122014-11-28 13:28:25 +0100178 if hasattr(ssl, 'RAND_egd'):
179 self.assertRaises(TypeError, ssl.RAND_egd, 1)
180 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000181 ssl.RAND_add("this is a random string", 75.0)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200182 ssl.RAND_add(b"this is a random bytes object", 75.0)
183 ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000184
Christian Heimesf77b4b22013-08-21 13:26:05 +0200185 @unittest.skipUnless(os.name == 'posix', 'requires posix')
186 def test_random_fork(self):
187 status = ssl.RAND_status()
188 if not status:
189 self.fail("OpenSSL's PRNG has insufficient randomness")
190
191 rfd, wfd = os.pipe()
192 pid = os.fork()
193 if pid == 0:
194 try:
195 os.close(rfd)
196 child_random = ssl.RAND_pseudo_bytes(16)[0]
197 self.assertEqual(len(child_random), 16)
198 os.write(wfd, child_random)
199 os.close(wfd)
200 except BaseException:
201 os._exit(1)
202 else:
203 os._exit(0)
204 else:
205 os.close(wfd)
206 self.addCleanup(os.close, rfd)
207 _, status = os.waitpid(pid, 0)
208 self.assertEqual(status, 0)
209
210 child_random = os.read(rfd, 16)
211 self.assertEqual(len(child_random), 16)
212 parent_random = ssl.RAND_pseudo_bytes(16)[0]
213 self.assertEqual(len(parent_random), 16)
214
215 self.assertNotEqual(child_random, parent_random)
216
Antoine Pitrou480a1242010-04-28 21:37:09 +0000217 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000218 # note that this uses an 'unofficial' function in _ssl.c,
219 # provided solely for this test, to exercise the certificate
220 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000221 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000222 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000223 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200224 self.assertEqual(p['issuer'],
225 ((('countryName', 'XY'),),
226 (('localityName', 'Castle Anthrax'),),
227 (('organizationName', 'Python Software Foundation'),),
228 (('commonName', 'localhost'),))
229 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100230 # Note the next three asserts will fail if the keys are regenerated
Christian Heimes9424bb42013-06-17 15:32:57 +0200231 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
232 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200233 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
234 self.assertEqual(p['subject'],
235 ((('countryName', 'XY'),),
236 (('localityName', 'Castle Anthrax'),),
237 (('organizationName', 'Python Software Foundation'),),
238 (('commonName', 'localhost'),))
239 )
240 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
241 # Issue #13034: the subjectAltName in some certificates
242 # (notably projects.developer.nokia.com:443) wasn't parsed
243 p = ssl._ssl._test_decode_cert(NOKIACERT)
244 if support.verbose:
245 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
246 self.assertEqual(p['subjectAltName'],
247 (('DNS', 'projects.developer.nokia.com'),
248 ('DNS', 'projects.forum.nokia.com'))
249 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100250 # extra OCSP and AIA fields
251 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
252 self.assertEqual(p['caIssuers'],
253 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
254 self.assertEqual(p['crlDistributionPoints'],
255 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000256
Christian Heimes824f7f32013-08-17 00:54:47 +0200257 def test_parse_cert_CVE_2013_4238(self):
258 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
259 if support.verbose:
260 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
261 subject = ((('countryName', 'US'),),
262 (('stateOrProvinceName', 'Oregon'),),
263 (('localityName', 'Beaverton'),),
264 (('organizationName', 'Python Software Foundation'),),
265 (('organizationalUnitName', 'Python Core Development'),),
266 (('commonName', 'null.python.org\x00example.org'),),
267 (('emailAddress', 'python-dev@python.org'),))
268 self.assertEqual(p['subject'], subject)
269 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200270 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
271 san = (('DNS', 'altnull.python.org\x00example.com'),
272 ('email', 'null@python.org\x00user@example.org'),
273 ('URI', 'http://null.python.org\x00http://example.org'),
274 ('IP Address', '192.0.2.1'),
275 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
276 else:
277 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
278 san = (('DNS', 'altnull.python.org\x00example.com'),
279 ('email', 'null@python.org\x00user@example.org'),
280 ('URI', 'http://null.python.org\x00http://example.org'),
281 ('IP Address', '192.0.2.1'),
282 ('IP Address', '<invalid>'))
283
284 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200285
Antoine Pitrou480a1242010-04-28 21:37:09 +0000286 def test_DER_to_PEM(self):
Martin Panter3d81d932016-01-14 09:36:00 +0000287 with open(CAFILE_CACERT, 'r') as f:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000288 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000289 d1 = ssl.PEM_cert_to_DER_cert(pem)
290 p2 = ssl.DER_cert_to_PEM_cert(d1)
291 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000292 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000293 if not p2.startswith(ssl.PEM_HEADER + '\n'):
294 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
295 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
296 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000297
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000298 def test_openssl_version(self):
299 n = ssl.OPENSSL_VERSION_NUMBER
300 t = ssl.OPENSSL_VERSION_INFO
301 s = ssl.OPENSSL_VERSION
302 self.assertIsInstance(n, int)
303 self.assertIsInstance(t, tuple)
304 self.assertIsInstance(s, str)
305 # Some sanity checks follow
306 # >= 0.9
307 self.assertGreaterEqual(n, 0x900000)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400308 # < 3.0
309 self.assertLess(n, 0x30000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000310 major, minor, fix, patch, status = t
311 self.assertGreaterEqual(major, 0)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400312 self.assertLess(major, 3)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000313 self.assertGreaterEqual(minor, 0)
314 self.assertLess(minor, 256)
315 self.assertGreaterEqual(fix, 0)
316 self.assertLess(fix, 256)
317 self.assertGreaterEqual(patch, 0)
Ned Deily05784a72015-02-05 17:20:13 +1100318 self.assertLessEqual(patch, 63)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000319 self.assertGreaterEqual(status, 0)
320 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400321 # Version string as returned by {Open,Libre}SSL, the format might change
322 if "LibreSSL" in s:
323 self.assertTrue(s.startswith("LibreSSL {:d}.{:d}".format(major, minor)),
Victor Stinner789b8052015-01-06 11:51:06 +0100324 (s, t, hex(n)))
Antoine Pitroudfab9352014-07-21 18:35:01 -0400325 else:
326 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
Victor Stinner789b8052015-01-06 11:51:06 +0100327 (s, t, hex(n)))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000328
Antoine Pitrou9d543662010-04-23 23:10:32 +0000329 @support.cpython_only
330 def test_refcycle(self):
331 # Issue #7943: an SSL object doesn't create reference cycles with
332 # itself.
333 s = socket.socket(socket.AF_INET)
334 ss = ssl.wrap_socket(s)
335 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100336 with support.check_warnings(("", ResourceWarning)):
337 del ss
Victor Stinnere0b75b72016-03-21 17:26:04 +0100338 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000339
Antoine Pitroua468adc2010-09-14 14:43:44 +0000340 def test_wrapped_unconnected(self):
341 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200342 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000343 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100344 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100345 self.assertRaises(OSError, ss.recv, 1)
346 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
347 self.assertRaises(OSError, ss.recvfrom, 1)
348 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
349 self.assertRaises(OSError, ss.send, b'x')
350 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000351
Antoine Pitrou40f08742010-04-24 22:04:40 +0000352 def test_timeout(self):
353 # Issue #8524: when creating an SSL socket, the timeout of the
354 # original socket should be retained.
355 for timeout in (None, 0.0, 5.0):
356 s = socket.socket(socket.AF_INET)
357 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100358 with ssl.wrap_socket(s) as ss:
359 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000360
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000361 def test_errors(self):
362 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000363 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000364 "certfile must be specified",
365 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000366 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000367 "certfile must be specified for server-side operations",
368 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000369 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000370 "certfile must be specified for server-side operations",
371 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100372 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
373 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
374 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200375 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000376 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000377 ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000378 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200379 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000380 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000381 ssl.wrap_socket(sock,
382 certfile=CERTFILE, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000383 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200384 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000385 with socket.socket() as sock:
Martin Panter407b62f2016-01-30 03:41:43 +0000386 ssl.wrap_socket(sock,
387 certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000388 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000389
Martin Panter3464ea22016-02-01 21:58:11 +0000390 def bad_cert_test(self, certfile):
391 """Check that trying to use the given client certificate fails"""
392 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
393 certfile)
394 sock = socket.socket()
395 self.addCleanup(sock.close)
396 with self.assertRaises(ssl.SSLError):
397 ssl.wrap_socket(sock,
398 certfile=certfile,
399 ssl_version=ssl.PROTOCOL_TLSv1)
400
401 def test_empty_cert(self):
402 """Wrapping with an empty cert file"""
403 self.bad_cert_test("nullcert.pem")
404
405 def test_malformed_cert(self):
406 """Wrapping with a badly formatted certificate (syntax error)"""
407 self.bad_cert_test("badcert.pem")
408
409 def test_malformed_key(self):
410 """Wrapping with a badly formatted key (syntax error)"""
411 self.bad_cert_test("badkey.pem")
412
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000413 def test_match_hostname(self):
414 def ok(cert, hostname):
415 ssl.match_hostname(cert, hostname)
416 def fail(cert, hostname):
417 self.assertRaises(ssl.CertificateError,
418 ssl.match_hostname, cert, hostname)
419
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100420 # -- Hostname matching --
421
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000422 cert = {'subject': ((('commonName', 'example.com'),),)}
423 ok(cert, 'example.com')
424 ok(cert, 'ExAmple.cOm')
425 fail(cert, 'www.example.com')
426 fail(cert, '.example.com')
427 fail(cert, 'example.org')
428 fail(cert, 'exampleXcom')
429
430 cert = {'subject': ((('commonName', '*.a.com'),),)}
431 ok(cert, 'foo.a.com')
432 fail(cert, 'bar.foo.a.com')
433 fail(cert, 'a.com')
434 fail(cert, 'Xa.com')
435 fail(cert, '.a.com')
436
Georg Brandl72c98d32013-10-27 07:16:53 +0100437 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000438 cert = {'subject': ((('commonName', 'f*.com'),),)}
439 ok(cert, 'foo.com')
440 ok(cert, 'f.com')
441 fail(cert, 'bar.com')
442 fail(cert, 'foo.a.com')
443 fail(cert, 'bar.foo.com')
444
Christian Heimes824f7f32013-08-17 00:54:47 +0200445 # NULL bytes are bad, CVE-2013-4073
446 cert = {'subject': ((('commonName',
447 'null.python.org\x00example.org'),),)}
448 ok(cert, 'null.python.org\x00example.org') # or raise an error?
449 fail(cert, 'example.org')
450 fail(cert, 'null.python.org')
451
Georg Brandl72c98d32013-10-27 07:16:53 +0100452 # error cases with wildcards
453 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
454 fail(cert, 'bar.foo.a.com')
455 fail(cert, 'a.com')
456 fail(cert, 'Xa.com')
457 fail(cert, '.a.com')
458
459 cert = {'subject': ((('commonName', 'a.*.com'),),)}
460 fail(cert, 'a.foo.com')
461 fail(cert, 'a..com')
462 fail(cert, 'a.com')
463
464 # wildcard doesn't match IDNA prefix 'xn--'
465 idna = 'püthon.python.org'.encode("idna").decode("ascii")
466 cert = {'subject': ((('commonName', idna),),)}
467 ok(cert, idna)
468 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
469 fail(cert, idna)
470 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
471 fail(cert, idna)
472
473 # wildcard in first fragment and IDNA A-labels in sequent fragments
474 # are supported.
475 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
476 cert = {'subject': ((('commonName', idna),),)}
477 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
478 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
479 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
480 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
481
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000482 # Slightly fake real-world example
483 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
484 'subject': ((('commonName', 'linuxfrz.org'),),),
485 'subjectAltName': (('DNS', 'linuxfr.org'),
486 ('DNS', 'linuxfr.com'),
487 ('othername', '<unsupported>'))}
488 ok(cert, 'linuxfr.org')
489 ok(cert, 'linuxfr.com')
490 # Not a "DNS" entry
491 fail(cert, '<unsupported>')
492 # When there is a subjectAltName, commonName isn't used
493 fail(cert, 'linuxfrz.org')
494
495 # A pristine real-world example
496 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
497 'subject': ((('countryName', 'US'),),
498 (('stateOrProvinceName', 'California'),),
499 (('localityName', 'Mountain View'),),
500 (('organizationName', 'Google Inc'),),
501 (('commonName', 'mail.google.com'),))}
502 ok(cert, 'mail.google.com')
503 fail(cert, 'gmail.com')
504 # Only commonName is considered
505 fail(cert, 'California')
506
Antoine Pitrouc481bfb2015-02-15 18:12:20 +0100507 # -- IPv4 matching --
508 cert = {'subject': ((('commonName', 'example.com'),),),
509 'subjectAltName': (('DNS', 'example.com'),
510 ('IP Address', '10.11.12.13'),
511 ('IP Address', '14.15.16.17'))}
512 ok(cert, '10.11.12.13')
513 ok(cert, '14.15.16.17')
514 fail(cert, '14.15.16.18')
515 fail(cert, 'example.net')
516
517 # -- IPv6 matching --
518 cert = {'subject': ((('commonName', 'example.com'),),),
519 'subjectAltName': (('DNS', 'example.com'),
520 ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'),
521 ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))}
522 ok(cert, '2001::cafe')
523 ok(cert, '2003::baba')
524 fail(cert, '2003::bebe')
525 fail(cert, 'example.net')
526
527 # -- Miscellaneous --
528
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000529 # Neither commonName nor subjectAltName
530 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
531 'subject': ((('countryName', 'US'),),
532 (('stateOrProvinceName', 'California'),),
533 (('localityName', 'Mountain View'),),
534 (('organizationName', 'Google Inc'),))}
535 fail(cert, 'mail.google.com')
536
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200537 # No DNS entry in subjectAltName but a commonName
538 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
539 'subject': ((('countryName', 'US'),),
540 (('stateOrProvinceName', 'California'),),
541 (('localityName', 'Mountain View'),),
542 (('commonName', 'mail.google.com'),)),
543 'subjectAltName': (('othername', 'blabla'), )}
544 ok(cert, 'mail.google.com')
545
546 # No DNS entry subjectAltName and no commonName
547 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
548 'subject': ((('countryName', 'US'),),
549 (('stateOrProvinceName', 'California'),),
550 (('localityName', 'Mountain View'),),
551 (('organizationName', 'Google Inc'),)),
552 'subjectAltName': (('othername', 'blabla'),)}
553 fail(cert, 'google.com')
554
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000555 # Empty cert / no cert
556 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
557 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
558
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200559 # Issue #17980: avoid denials of service by refusing more than one
560 # wildcard per fragment.
561 cert = {'subject': ((('commonName', 'a*b.com'),),)}
562 ok(cert, 'axxb.com')
563 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100564 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200565 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
566 with self.assertRaises(ssl.CertificateError) as cm:
567 ssl.match_hostname(cert, 'axxbxxc.com')
568 self.assertIn("too many wildcards", str(cm.exception))
569
Antoine Pitroud5323212010-10-22 18:19:07 +0000570 def test_server_side(self):
571 # server_hostname doesn't work for server sockets
572 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000573 with socket.socket() as sock:
574 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
575 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000576
Antoine Pitroud6494802011-07-21 01:11:30 +0200577 def test_unknown_channel_binding(self):
578 # should raise ValueError for unknown type
579 s = socket.socket(socket.AF_INET)
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200580 s.bind(('127.0.0.1', 0))
581 s.listen()
582 c = socket.socket(socket.AF_INET)
583 c.connect(s.getsockname())
584 with ssl.wrap_socket(c, do_handshake_on_connect=False) as ss:
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100585 with self.assertRaises(ValueError):
586 ss.get_channel_binding("unknown-type")
Antoine Pitroub1fdf472014-10-05 20:41:53 +0200587 s.close()
Antoine Pitroud6494802011-07-21 01:11:30 +0200588
589 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
590 "'tls-unique' channel binding not available")
591 def test_tls_unique_channel_binding(self):
592 # unconnected should return None for known type
593 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100594 with ssl.wrap_socket(s) as ss:
595 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200596 # the same for server-side
597 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100598 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
599 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200600
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600601 def test_dealloc_warn(self):
602 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
603 r = repr(ss)
604 with self.assertWarns(ResourceWarning) as cm:
605 ss = None
606 support.gc_collect()
607 self.assertIn(r, str(cm.warning.args[0]))
608
Christian Heimes6d7ad132013-06-09 18:02:55 +0200609 def test_get_default_verify_paths(self):
610 paths = ssl.get_default_verify_paths()
611 self.assertEqual(len(paths), 6)
612 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
613
614 with support.EnvironmentVarGuard() as env:
615 env["SSL_CERT_DIR"] = CAPATH
616 env["SSL_CERT_FILE"] = CERTFILE
617 paths = ssl.get_default_verify_paths()
618 self.assertEqual(paths.cafile, CERTFILE)
619 self.assertEqual(paths.capath, CAPATH)
620
Christian Heimes44109d72013-11-22 01:51:30 +0100621 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
622 def test_enum_certificates(self):
623 self.assertTrue(ssl.enum_certificates("CA"))
624 self.assertTrue(ssl.enum_certificates("ROOT"))
625
626 self.assertRaises(TypeError, ssl.enum_certificates)
627 self.assertRaises(WindowsError, ssl.enum_certificates, "")
628
Christian Heimesc2d65e12013-11-22 16:13:55 +0100629 trust_oids = set()
630 for storename in ("CA", "ROOT"):
631 store = ssl.enum_certificates(storename)
632 self.assertIsInstance(store, list)
633 for element in store:
634 self.assertIsInstance(element, tuple)
635 self.assertEqual(len(element), 3)
636 cert, enc, trust = element
637 self.assertIsInstance(cert, bytes)
638 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
639 self.assertIsInstance(trust, (set, bool))
640 if isinstance(trust, set):
641 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100642
643 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100644 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200645
Christian Heimes46bebee2013-06-09 19:03:31 +0200646 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100647 def test_enum_crls(self):
648 self.assertTrue(ssl.enum_crls("CA"))
649 self.assertRaises(TypeError, ssl.enum_crls)
650 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200651
Christian Heimes44109d72013-11-22 01:51:30 +0100652 crls = ssl.enum_crls("CA")
653 self.assertIsInstance(crls, list)
654 for element in crls:
655 self.assertIsInstance(element, tuple)
656 self.assertEqual(len(element), 2)
657 self.assertIsInstance(element[0], bytes)
658 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200659
Christian Heimes46bebee2013-06-09 19:03:31 +0200660
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100661 def test_asn1object(self):
662 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
663 '1.3.6.1.5.5.7.3.1')
664
665 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
666 self.assertEqual(val, expected)
667 self.assertEqual(val.nid, 129)
668 self.assertEqual(val.shortname, 'serverAuth')
669 self.assertEqual(val.longname, 'TLS Web Server Authentication')
670 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
671 self.assertIsInstance(val, ssl._ASN1Object)
672 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
673
674 val = ssl._ASN1Object.fromnid(129)
675 self.assertEqual(val, expected)
676 self.assertIsInstance(val, ssl._ASN1Object)
677 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100678 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
679 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100680 for i in range(1000):
681 try:
682 obj = ssl._ASN1Object.fromnid(i)
683 except ValueError:
684 pass
685 else:
686 self.assertIsInstance(obj.nid, int)
687 self.assertIsInstance(obj.shortname, str)
688 self.assertIsInstance(obj.longname, str)
689 self.assertIsInstance(obj.oid, (str, type(None)))
690
691 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
692 self.assertEqual(val, expected)
693 self.assertIsInstance(val, ssl._ASN1Object)
694 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
695 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
696 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100697 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
698 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100699
Christian Heimes72d28502013-11-23 13:56:58 +0100700 def test_purpose_enum(self):
701 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
702 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
703 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
704 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
705 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
706 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
707 '1.3.6.1.5.5.7.3.1')
708
709 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
710 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
711 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
712 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
713 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
714 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
715 '1.3.6.1.5.5.7.3.2')
716
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100717 def test_unsupported_dtls(self):
718 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
719 self.addCleanup(s.close)
720 with self.assertRaises(NotImplementedError) as cx:
721 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
722 self.assertEqual(str(cx.exception), "only stream sockets are supported")
723 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
724 with self.assertRaises(NotImplementedError) as cx:
725 ctx.wrap_socket(s)
726 self.assertEqual(str(cx.exception), "only stream sockets are supported")
727
Antoine Pitrouc695c952014-04-28 20:57:36 +0200728 def cert_time_ok(self, timestring, timestamp):
729 self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp)
730
731 def cert_time_fail(self, timestring):
732 with self.assertRaises(ValueError):
733 ssl.cert_time_to_seconds(timestring)
734
735 @unittest.skipUnless(utc_offset(),
736 'local time needs to be different from UTC')
737 def test_cert_time_to_seconds_timezone(self):
738 # Issue #19940: ssl.cert_time_to_seconds() returns wrong
739 # results if local timezone is not UTC
740 self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0)
741 self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0)
742
743 def test_cert_time_to_seconds(self):
744 timestring = "Jan 5 09:34:43 2018 GMT"
745 ts = 1515144883.0
746 self.cert_time_ok(timestring, ts)
747 # accept keyword parameter, assert its name
748 self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts)
749 # accept both %e and %d (space or zero generated by strftime)
750 self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts)
751 # case-insensitive
752 self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts)
753 self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds
754 self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT
755 self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone
756 self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day
757 self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month
758 self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour
759 self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute
760
761 newyear_ts = 1230768000.0
762 # leap seconds
763 self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts)
764 # same timestamp
765 self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts)
766
767 self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899)
768 # allow 60th second (even if it is not a leap second)
769 self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900)
770 # allow 2nd leap second for compatibility with time.strptime()
771 self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901)
772 self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds
773
774 # no special treatement for the special value:
775 # 99991231235959Z (rfc 5280)
776 self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0)
777
778 @support.run_with_locale('LC_ALL', '')
779 def test_cert_time_to_seconds_locale(self):
780 # `cert_time_to_seconds()` should be locale independent
781
782 def local_february_name():
783 return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0))
784
785 if local_february_name().lower() == 'feb':
786 self.skipTest("locale-specific month name needs to be "
787 "different from C locale")
788
789 # locale-independent
790 self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0)
791 self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT")
792
Martin Panter3840b2a2016-03-27 01:53:46 +0000793 def test_connect_ex_error(self):
794 server = socket.socket(socket.AF_INET)
795 self.addCleanup(server.close)
796 port = support.bind_port(server) # Reserve port but don't listen
797 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
798 cert_reqs=ssl.CERT_REQUIRED)
799 self.addCleanup(s.close)
800 rc = s.connect_ex((HOST, port))
801 # Issue #19919: Windows machines or VMs hosted on Windows
802 # machines sometimes return EWOULDBLOCK.
803 errors = (
804 errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
805 errno.EWOULDBLOCK,
806 )
807 self.assertIn(rc, errors)
808
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100809
Antoine Pitrou152efa22010-05-16 18:19:27 +0000810class ContextTests(unittest.TestCase):
811
Antoine Pitrou23df4832010-08-04 17:14:06 +0000812 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000813 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100814 for protocol in PROTOCOLS:
815 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000816 self.assertRaises(TypeError, ssl.SSLContext)
817 self.assertRaises(ValueError, ssl.SSLContext, -1)
818 self.assertRaises(ValueError, ssl.SSLContext, 42)
819
Antoine Pitrou23df4832010-08-04 17:14:06 +0000820 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000821 def test_protocol(self):
822 for proto in PROTOCOLS:
823 ctx = ssl.SSLContext(proto)
824 self.assertEqual(ctx.protocol, proto)
825
826 def test_ciphers(self):
827 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
828 ctx.set_ciphers("ALL")
829 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000830 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000831 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000832
Antoine Pitrou23df4832010-08-04 17:14:06 +0000833 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000834 def test_options(self):
835 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -0800836 # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
Antoine Pitroub5218772010-05-21 09:56:06 +0000837 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
838 ctx.options)
Benjamin Petersona9dcdab2015-11-11 22:38:41 -0800839 ctx.options |= ssl.OP_NO_TLSv1
840 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1,
841 ctx.options)
Antoine Pitroub5218772010-05-21 09:56:06 +0000842 if can_clear_options():
843 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
844 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
845 ctx.options)
846 ctx.options = 0
847 self.assertEqual(0, ctx.options)
848 else:
849 with self.assertRaises(ValueError):
850 ctx.options = 0
851
Christian Heimes22587792013-11-21 23:56:13 +0100852 def test_verify_mode(self):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000853 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
854 # Default value
855 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
856 ctx.verify_mode = ssl.CERT_OPTIONAL
857 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
858 ctx.verify_mode = ssl.CERT_REQUIRED
859 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
860 ctx.verify_mode = ssl.CERT_NONE
861 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
862 with self.assertRaises(TypeError):
863 ctx.verify_mode = None
864 with self.assertRaises(ValueError):
865 ctx.verify_mode = 42
866
Christian Heimes2427b502013-11-23 11:24:32 +0100867 @unittest.skipUnless(have_verify_flags(),
868 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +0100869 def test_verify_flags(self):
870 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson990fcaa2015-03-04 22:49:41 -0500871 # default value
872 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
873 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +0100874 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
875 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
876 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
877 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
878 ctx.verify_flags = ssl.VERIFY_DEFAULT
879 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
880 # supports any value
881 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
882 self.assertEqual(ctx.verify_flags,
883 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
884 with self.assertRaises(TypeError):
885 ctx.verify_flags = None
886
Antoine Pitrou152efa22010-05-16 18:19:27 +0000887 def test_load_cert_chain(self):
888 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
889 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -0500890 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000891 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
892 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200893 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +0000894 ctx.load_cert_chain(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000895 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000896 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000897 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000898 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000899 ctx.load_cert_chain(EMPTYCERT)
900 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000901 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000902 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
903 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
904 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000905 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000906 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000907 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000908 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000909 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000910 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
911 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000912 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000913 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Martin Panter3d81d932016-01-14 09:36:00 +0000914 ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200915 # Password protected key and cert
916 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
917 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
918 ctx.load_cert_chain(CERTFILE_PROTECTED,
919 password=bytearray(KEY_PASSWORD.encode()))
920 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
921 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
922 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
923 bytearray(KEY_PASSWORD.encode()))
924 with self.assertRaisesRegex(TypeError, "should be a string"):
925 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
926 with self.assertRaises(ssl.SSLError):
927 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
928 with self.assertRaisesRegex(ValueError, "cannot be longer"):
929 # openssl has a fixed limit on the password buffer.
930 # PEM_BUFSIZE is generally set to 1kb.
931 # Return a string larger than this.
932 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
933 # Password callback
934 def getpass_unicode():
935 return KEY_PASSWORD
936 def getpass_bytes():
937 return KEY_PASSWORD.encode()
938 def getpass_bytearray():
939 return bytearray(KEY_PASSWORD.encode())
940 def getpass_badpass():
941 return "badpass"
942 def getpass_huge():
943 return b'a' * (1024 * 1024)
944 def getpass_bad_type():
945 return 9
946 def getpass_exception():
947 raise Exception('getpass error')
948 class GetPassCallable:
949 def __call__(self):
950 return KEY_PASSWORD
951 def getpass(self):
952 return KEY_PASSWORD
953 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
954 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
955 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
956 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
957 ctx.load_cert_chain(CERTFILE_PROTECTED,
958 password=GetPassCallable().getpass)
959 with self.assertRaises(ssl.SSLError):
960 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
961 with self.assertRaisesRegex(ValueError, "cannot be longer"):
962 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
963 with self.assertRaisesRegex(TypeError, "must return a string"):
964 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
965 with self.assertRaisesRegex(Exception, "getpass error"):
966 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
967 # Make sure the password function isn't called if it isn't needed
968 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000969
970 def test_load_verify_locations(self):
971 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
972 ctx.load_verify_locations(CERTFILE)
973 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
974 ctx.load_verify_locations(BYTES_CERTFILE)
975 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
976 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +0100977 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200978 with self.assertRaises(OSError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +0000979 ctx.load_verify_locations(NONEXISTINGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000980 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000981 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000982 ctx.load_verify_locations(BADCERT)
983 ctx.load_verify_locations(CERTFILE, CAPATH)
984 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
985
Victor Stinner80f75e62011-01-29 11:31:20 +0000986 # Issue #10989: crash if the second argument type is invalid
987 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
988
Christian Heimesefff7062013-11-21 03:35:02 +0100989 def test_load_verify_cadata(self):
990 # test cadata
991 with open(CAFILE_CACERT) as f:
992 cacert_pem = f.read()
993 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
994 with open(CAFILE_NEURONIO) as f:
995 neuronio_pem = f.read()
996 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
997
998 # test PEM
999 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1000 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
1001 ctx.load_verify_locations(cadata=cacert_pem)
1002 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
1003 ctx.load_verify_locations(cadata=neuronio_pem)
1004 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1005 # cert already in hash table
1006 ctx.load_verify_locations(cadata=neuronio_pem)
1007 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1008
1009 # combined
1010 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1011 combined = "\n".join((cacert_pem, neuronio_pem))
1012 ctx.load_verify_locations(cadata=combined)
1013 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1014
1015 # with junk around the certs
1016 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1017 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
1018 neuronio_pem, "tail"]
1019 ctx.load_verify_locations(cadata="\n".join(combined))
1020 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1021
1022 # test DER
1023 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1024 ctx.load_verify_locations(cadata=cacert_der)
1025 ctx.load_verify_locations(cadata=neuronio_der)
1026 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1027 # cert already in hash table
1028 ctx.load_verify_locations(cadata=cacert_der)
1029 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1030
1031 # combined
1032 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1033 combined = b"".join((cacert_der, neuronio_der))
1034 ctx.load_verify_locations(cadata=combined)
1035 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
1036
1037 # error cases
1038 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1039 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
1040
1041 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
1042 ctx.load_verify_locations(cadata="broken")
1043 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
1044 ctx.load_verify_locations(cadata=b"broken")
1045
1046
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001047 def test_load_dh_params(self):
1048 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1049 ctx.load_dh_params(DHFILE)
1050 if os.name != 'nt':
1051 ctx.load_dh_params(BYTES_DHFILE)
1052 self.assertRaises(TypeError, ctx.load_dh_params)
1053 self.assertRaises(TypeError, ctx.load_dh_params, None)
1054 with self.assertRaises(FileNotFoundError) as cm:
Martin Panter407b62f2016-01-30 03:41:43 +00001055 ctx.load_dh_params(NONEXISTINGCERT)
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001056 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001057 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001058 ctx.load_dh_params(CERTFILE)
1059
Antoine Pitroueb585ad2010-10-22 18:24:20 +00001060 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +00001061 def test_session_stats(self):
1062 for proto in PROTOCOLS:
1063 ctx = ssl.SSLContext(proto)
1064 self.assertEqual(ctx.session_stats(), {
1065 'number': 0,
1066 'connect': 0,
1067 'connect_good': 0,
1068 'connect_renegotiate': 0,
1069 'accept': 0,
1070 'accept_good': 0,
1071 'accept_renegotiate': 0,
1072 'hits': 0,
1073 'misses': 0,
1074 'timeouts': 0,
1075 'cache_full': 0,
1076 })
1077
Antoine Pitrou664c2d12010-11-17 20:29:42 +00001078 def test_set_default_verify_paths(self):
1079 # There's not much we can do to test that it acts as expected,
1080 # so just check it doesn't crash or raise an exception.
1081 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1082 ctx.set_default_verify_paths()
1083
Antoine Pitrou501da612011-12-21 09:27:41 +01001084 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +01001085 def test_set_ecdh_curve(self):
1086 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1087 ctx.set_ecdh_curve("prime256v1")
1088 ctx.set_ecdh_curve(b"prime256v1")
1089 self.assertRaises(TypeError, ctx.set_ecdh_curve)
1090 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
1091 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
1092 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
1093
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001094 @needs_sni
1095 def test_sni_callback(self):
1096 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1097
1098 # set_servername_callback expects a callable, or None
1099 self.assertRaises(TypeError, ctx.set_servername_callback)
1100 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
1101 self.assertRaises(TypeError, ctx.set_servername_callback, "")
1102 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
1103
1104 def dummycallback(sock, servername, ctx):
1105 pass
1106 ctx.set_servername_callback(None)
1107 ctx.set_servername_callback(dummycallback)
1108
1109 @needs_sni
1110 def test_sni_callback_refcycle(self):
1111 # Reference cycles through the servername callback are detected
1112 # and cleared.
1113 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1114 def dummycallback(sock, servername, ctx, cycle=ctx):
1115 pass
1116 ctx.set_servername_callback(dummycallback)
1117 wr = weakref.ref(ctx)
1118 del ctx, dummycallback
1119 gc.collect()
1120 self.assertIs(wr(), None)
1121
Christian Heimes9a5395a2013-06-17 15:44:12 +02001122 def test_cert_store_stats(self):
1123 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1124 self.assertEqual(ctx.cert_store_stats(),
1125 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1126 ctx.load_cert_chain(CERTFILE)
1127 self.assertEqual(ctx.cert_store_stats(),
1128 {'x509_ca': 0, 'crl': 0, 'x509': 0})
1129 ctx.load_verify_locations(CERTFILE)
1130 self.assertEqual(ctx.cert_store_stats(),
1131 {'x509_ca': 0, 'crl': 0, 'x509': 1})
Martin Panterb55f8b72016-01-14 12:53:56 +00001132 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001133 self.assertEqual(ctx.cert_store_stats(),
1134 {'x509_ca': 1, 'crl': 0, 'x509': 2})
1135
1136 def test_get_ca_certs(self):
1137 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1138 self.assertEqual(ctx.get_ca_certs(), [])
1139 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
1140 ctx.load_verify_locations(CERTFILE)
1141 self.assertEqual(ctx.get_ca_certs(), [])
Martin Panterb55f8b72016-01-14 12:53:56 +00001142 # but CAFILE_CACERT is a CA cert
1143 ctx.load_verify_locations(CAFILE_CACERT)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001144 self.assertEqual(ctx.get_ca_certs(),
1145 [{'issuer': ((('organizationName', 'Root CA'),),
1146 (('organizationalUnitName', 'http://www.cacert.org'),),
1147 (('commonName', 'CA Cert Signing Authority'),),
1148 (('emailAddress', 'support@cacert.org'),)),
1149 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
1150 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
1151 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +01001152 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +02001153 'subject': ((('organizationName', 'Root CA'),),
1154 (('organizationalUnitName', 'http://www.cacert.org'),),
1155 (('commonName', 'CA Cert Signing Authority'),),
1156 (('emailAddress', 'support@cacert.org'),)),
1157 'version': 3}])
1158
Martin Panterb55f8b72016-01-14 12:53:56 +00001159 with open(CAFILE_CACERT) as f:
Christian Heimes9a5395a2013-06-17 15:44:12 +02001160 pem = f.read()
1161 der = ssl.PEM_cert_to_DER_cert(pem)
1162 self.assertEqual(ctx.get_ca_certs(True), [der])
1163
Christian Heimes72d28502013-11-23 13:56:58 +01001164 def test_load_default_certs(self):
1165 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1166 ctx.load_default_certs()
1167
1168 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1169 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1170 ctx.load_default_certs()
1171
1172 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1173 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1174
1175 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1176 self.assertRaises(TypeError, ctx.load_default_certs, None)
1177 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1178
Benjamin Peterson91244e02014-10-03 18:17:15 -04001179 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001180 def test_load_default_certs_env(self):
1181 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1182 with support.EnvironmentVarGuard() as env:
1183 env["SSL_CERT_DIR"] = CAPATH
1184 env["SSL_CERT_FILE"] = CERTFILE
1185 ctx.load_default_certs()
1186 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1187
Benjamin Peterson91244e02014-10-03 18:17:15 -04001188 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1189 def test_load_default_certs_env_windows(self):
1190 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1191 ctx.load_default_certs()
1192 stats = ctx.cert_store_stats()
1193
1194 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1195 with support.EnvironmentVarGuard() as env:
1196 env["SSL_CERT_DIR"] = CAPATH
1197 env["SSL_CERT_FILE"] = CERTFILE
1198 ctx.load_default_certs()
1199 stats["x509"] += 1
1200 self.assertEqual(ctx.cert_store_stats(), stats)
1201
Christian Heimes4c05b472013-11-23 15:58:30 +01001202 def test_create_default_context(self):
1203 ctx = ssl.create_default_context()
Donald Stufft6a2ba942014-03-23 19:05:28 -04001204 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001205 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001206 self.assertTrue(ctx.check_hostname)
Christian Heimes4c05b472013-11-23 15:58:30 +01001207 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001208 self.assertEqual(
1209 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1210 getattr(ssl, "OP_NO_COMPRESSION", 0),
1211 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001212
1213 with open(SIGNING_CA) as f:
1214 cadata = f.read()
1215 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1216 cadata=cadata)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001217 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001218 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1219 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001220 self.assertEqual(
1221 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1222 getattr(ssl, "OP_NO_COMPRESSION", 0),
1223 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001224
1225 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001226 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001227 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1228 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001229 self.assertEqual(
1230 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1231 getattr(ssl, "OP_NO_COMPRESSION", 0),
1232 )
1233 self.assertEqual(
1234 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1235 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1236 )
1237 self.assertEqual(
1238 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1239 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1240 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001241
Christian Heimes67986f92013-11-23 22:43:47 +01001242 def test__create_stdlib_context(self):
1243 ctx = ssl._create_stdlib_context()
1244 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1245 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001246 self.assertFalse(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001247 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1248
1249 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1250 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1251 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1252 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1253
1254 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001255 cert_reqs=ssl.CERT_REQUIRED,
1256 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001257 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1258 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001259 self.assertTrue(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001260 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1261
1262 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1263 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1264 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1265 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Christian Heimes4c05b472013-11-23 15:58:30 +01001266
Christian Heimes1aa9a752013-12-02 02:41:19 +01001267 def test_check_hostname(self):
1268 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1269 self.assertFalse(ctx.check_hostname)
1270
1271 # Requires CERT_REQUIRED or CERT_OPTIONAL
1272 with self.assertRaises(ValueError):
1273 ctx.check_hostname = True
1274 ctx.verify_mode = ssl.CERT_REQUIRED
1275 self.assertFalse(ctx.check_hostname)
1276 ctx.check_hostname = True
1277 self.assertTrue(ctx.check_hostname)
1278
1279 ctx.verify_mode = ssl.CERT_OPTIONAL
1280 ctx.check_hostname = True
1281 self.assertTrue(ctx.check_hostname)
1282
1283 # Cannot set CERT_NONE with check_hostname enabled
1284 with self.assertRaises(ValueError):
1285 ctx.verify_mode = ssl.CERT_NONE
1286 ctx.check_hostname = False
1287 self.assertFalse(ctx.check_hostname)
1288
Antoine Pitrou152efa22010-05-16 18:19:27 +00001289
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001290class SSLErrorTests(unittest.TestCase):
1291
1292 def test_str(self):
1293 # The str() of a SSLError doesn't include the errno
1294 e = ssl.SSLError(1, "foo")
1295 self.assertEqual(str(e), "foo")
1296 self.assertEqual(e.errno, 1)
1297 # Same for a subclass
1298 e = ssl.SSLZeroReturnError(1, "foo")
1299 self.assertEqual(str(e), "foo")
1300 self.assertEqual(e.errno, 1)
1301
1302 def test_lib_reason(self):
1303 # Test the library and reason attributes
1304 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1305 with self.assertRaises(ssl.SSLError) as cm:
1306 ctx.load_dh_params(CERTFILE)
1307 self.assertEqual(cm.exception.library, 'PEM')
1308 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1309 s = str(cm.exception)
1310 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1311
1312 def test_subclass(self):
1313 # Check that the appropriate SSLError subclass is raised
1314 # (this only tests one of them)
1315 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1316 with socket.socket() as s:
1317 s.bind(("127.0.0.1", 0))
Charles-François Natali6e204602014-07-23 19:28:13 +01001318 s.listen()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001319 c = socket.socket()
1320 c.connect(s.getsockname())
1321 c.setblocking(False)
1322 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001323 with self.assertRaises(ssl.SSLWantReadError) as cm:
1324 c.do_handshake()
1325 s = str(cm.exception)
1326 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1327 # For compatibility
1328 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1329
1330
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001331class MemoryBIOTests(unittest.TestCase):
1332
1333 def test_read_write(self):
1334 bio = ssl.MemoryBIO()
1335 bio.write(b'foo')
1336 self.assertEqual(bio.read(), b'foo')
1337 self.assertEqual(bio.read(), b'')
1338 bio.write(b'foo')
1339 bio.write(b'bar')
1340 self.assertEqual(bio.read(), b'foobar')
1341 self.assertEqual(bio.read(), b'')
1342 bio.write(b'baz')
1343 self.assertEqual(bio.read(2), b'ba')
1344 self.assertEqual(bio.read(1), b'z')
1345 self.assertEqual(bio.read(1), b'')
1346
1347 def test_eof(self):
1348 bio = ssl.MemoryBIO()
1349 self.assertFalse(bio.eof)
1350 self.assertEqual(bio.read(), b'')
1351 self.assertFalse(bio.eof)
1352 bio.write(b'foo')
1353 self.assertFalse(bio.eof)
1354 bio.write_eof()
1355 self.assertFalse(bio.eof)
1356 self.assertEqual(bio.read(2), b'fo')
1357 self.assertFalse(bio.eof)
1358 self.assertEqual(bio.read(1), b'o')
1359 self.assertTrue(bio.eof)
1360 self.assertEqual(bio.read(), b'')
1361 self.assertTrue(bio.eof)
1362
1363 def test_pending(self):
1364 bio = ssl.MemoryBIO()
1365 self.assertEqual(bio.pending, 0)
1366 bio.write(b'foo')
1367 self.assertEqual(bio.pending, 3)
1368 for i in range(3):
1369 bio.read(1)
1370 self.assertEqual(bio.pending, 3-i-1)
1371 for i in range(3):
1372 bio.write(b'x')
1373 self.assertEqual(bio.pending, i+1)
1374 bio.read()
1375 self.assertEqual(bio.pending, 0)
1376
1377 def test_buffer_types(self):
1378 bio = ssl.MemoryBIO()
1379 bio.write(b'foo')
1380 self.assertEqual(bio.read(), b'foo')
1381 bio.write(bytearray(b'bar'))
1382 self.assertEqual(bio.read(), b'bar')
1383 bio.write(memoryview(b'baz'))
1384 self.assertEqual(bio.read(), b'baz')
1385
1386 def test_error_types(self):
1387 bio = ssl.MemoryBIO()
1388 self.assertRaises(TypeError, bio.write, 'foo')
1389 self.assertRaises(TypeError, bio.write, None)
1390 self.assertRaises(TypeError, bio.write, True)
1391 self.assertRaises(TypeError, bio.write, 1)
1392
1393
Martin Panter3840b2a2016-03-27 01:53:46 +00001394@unittest.skipUnless(_have_threads, "Needs threading module")
1395class SimpleBackgroundTests(unittest.TestCase):
1396
1397 """Tests that connect to a simple server running in the background"""
1398
1399 def setUp(self):
1400 server = ThreadedEchoServer(SIGNED_CERTFILE)
1401 self.server_addr = (HOST, server.port)
1402 server.__enter__()
1403 self.addCleanup(server.__exit__, None, None, None)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001404
Antoine Pitrou480a1242010-04-28 21:37:09 +00001405 def test_connect(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001406 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1407 cert_reqs=ssl.CERT_NONE) as s:
1408 s.connect(self.server_addr)
1409 self.assertEqual({}, s.getpeercert())
Antoine Pitrou350c7222010-09-09 13:31:46 +00001410
Martin Panter3840b2a2016-03-27 01:53:46 +00001411 # this should succeed because we specify the root cert
1412 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1413 cert_reqs=ssl.CERT_REQUIRED,
1414 ca_certs=SIGNING_CA) as s:
1415 s.connect(self.server_addr)
1416 self.assertTrue(s.getpeercert())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001417
Martin Panter3840b2a2016-03-27 01:53:46 +00001418 def test_connect_fail(self):
1419 # This should fail because we have no verification certs. Connection
1420 # failure crashes ThreadedEchoServer, so run this in an independent
1421 # test method.
1422 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1423 cert_reqs=ssl.CERT_REQUIRED)
1424 self.addCleanup(s.close)
1425 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1426 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001427
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001428 def test_connect_ex(self):
1429 # Issue #11326: check connect_ex() implementation
Martin Panter3840b2a2016-03-27 01:53:46 +00001430 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1431 cert_reqs=ssl.CERT_REQUIRED,
1432 ca_certs=SIGNING_CA)
1433 self.addCleanup(s.close)
1434 self.assertEqual(0, s.connect_ex(self.server_addr))
1435 self.assertTrue(s.getpeercert())
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001436
1437 def test_non_blocking_connect_ex(self):
1438 # Issue #11326: non-blocking connect_ex() should allow handshake
1439 # to proceed after the socket gets ready.
Martin Panter3840b2a2016-03-27 01:53:46 +00001440 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1441 cert_reqs=ssl.CERT_REQUIRED,
1442 ca_certs=SIGNING_CA,
1443 do_handshake_on_connect=False)
1444 self.addCleanup(s.close)
1445 s.setblocking(False)
1446 rc = s.connect_ex(self.server_addr)
1447 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1448 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
1449 # Wait for connect to finish
1450 select.select([], [s], [], 5.0)
1451 # Non-blocking handshake
1452 while True:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001453 try:
Martin Panter3840b2a2016-03-27 01:53:46 +00001454 s.do_handshake()
1455 break
1456 except ssl.SSLWantReadError:
1457 select.select([s], [], [], 5.0)
1458 except ssl.SSLWantWriteError:
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001459 select.select([], [s], [], 5.0)
Martin Panter3840b2a2016-03-27 01:53:46 +00001460 # SSL established
1461 self.assertTrue(s.getpeercert())
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001462
Antoine Pitrou152efa22010-05-16 18:19:27 +00001463 def test_connect_with_context(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001464 # Same as test_connect, but with a separately created context
1465 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1466 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1467 s.connect(self.server_addr)
1468 self.assertEqual({}, s.getpeercert())
1469 # Same with a server hostname
1470 with ctx.wrap_socket(socket.socket(socket.AF_INET),
1471 server_hostname="dummy") as s:
1472 s.connect(self.server_addr)
1473 ctx.verify_mode = ssl.CERT_REQUIRED
1474 # This should succeed because we specify the root cert
1475 ctx.load_verify_locations(SIGNING_CA)
1476 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1477 s.connect(self.server_addr)
1478 cert = s.getpeercert()
1479 self.assertTrue(cert)
1480
1481 def test_connect_with_context_fail(self):
1482 # This should fail because we have no verification certs. Connection
1483 # failure crashes ThreadedEchoServer, so run this in an independent
1484 # test method.
1485 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1486 ctx.verify_mode = ssl.CERT_REQUIRED
1487 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1488 self.addCleanup(s.close)
1489 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1490 s.connect, self.server_addr)
Antoine Pitrou152efa22010-05-16 18:19:27 +00001491
1492 def test_connect_capath(self):
1493 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00001494 # NOTE: the subject hashing algorithm has been changed between
1495 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1496 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00001497 # filename) for this test to be portable across OpenSSL releases.
Martin Panter3840b2a2016-03-27 01:53:46 +00001498 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1499 ctx.verify_mode = ssl.CERT_REQUIRED
1500 ctx.load_verify_locations(capath=CAPATH)
1501 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1502 s.connect(self.server_addr)
1503 cert = s.getpeercert()
1504 self.assertTrue(cert)
1505 # Same with a bytes `capath` argument
1506 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1507 ctx.verify_mode = ssl.CERT_REQUIRED
1508 ctx.load_verify_locations(capath=BYTES_CAPATH)
1509 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1510 s.connect(self.server_addr)
1511 cert = s.getpeercert()
1512 self.assertTrue(cert)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001513
Christian Heimesefff7062013-11-21 03:35:02 +01001514 def test_connect_cadata(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001515 with open(SIGNING_CA) as f:
Christian Heimesefff7062013-11-21 03:35:02 +01001516 pem = f.read()
1517 der = ssl.PEM_cert_to_DER_cert(pem)
Martin Panter3840b2a2016-03-27 01:53:46 +00001518 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1519 ctx.verify_mode = ssl.CERT_REQUIRED
1520 ctx.load_verify_locations(cadata=pem)
1521 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1522 s.connect(self.server_addr)
1523 cert = s.getpeercert()
1524 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01001525
Martin Panter3840b2a2016-03-27 01:53:46 +00001526 # same with DER
1527 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1528 ctx.verify_mode = ssl.CERT_REQUIRED
1529 ctx.load_verify_locations(cadata=der)
1530 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1531 s.connect(self.server_addr)
1532 cert = s.getpeercert()
1533 self.assertTrue(cert)
Christian Heimesefff7062013-11-21 03:35:02 +01001534
Antoine Pitroue3220242010-04-24 11:13:53 +00001535 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1536 def test_makefile_close(self):
1537 # Issue #5238: creating a file-like object with makefile() shouldn't
1538 # delay closing the underlying "real socket" (here tested with its
1539 # file descriptor, hence skipping the test under Windows).
Martin Panter3840b2a2016-03-27 01:53:46 +00001540 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1541 ss.connect(self.server_addr)
1542 fd = ss.fileno()
1543 f = ss.makefile()
1544 f.close()
1545 # The fd is still open
1546 os.read(fd, 0)
1547 # Closing the SSL socket should close the fd too
1548 ss.close()
1549 gc.collect()
1550 with self.assertRaises(OSError) as e:
Antoine Pitroue3220242010-04-24 11:13:53 +00001551 os.read(fd, 0)
Martin Panter3840b2a2016-03-27 01:53:46 +00001552 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001553
Antoine Pitrou480a1242010-04-28 21:37:09 +00001554 def test_non_blocking_handshake(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001555 s = socket.socket(socket.AF_INET)
1556 s.connect(self.server_addr)
1557 s.setblocking(False)
1558 s = ssl.wrap_socket(s,
1559 cert_reqs=ssl.CERT_NONE,
1560 do_handshake_on_connect=False)
1561 self.addCleanup(s.close)
1562 count = 0
1563 while True:
1564 try:
1565 count += 1
1566 s.do_handshake()
1567 break
1568 except ssl.SSLWantReadError:
1569 select.select([s], [], [])
1570 except ssl.SSLWantWriteError:
1571 select.select([], [s], [])
1572 if support.verbose:
1573 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001574
Antoine Pitrou480a1242010-04-28 21:37:09 +00001575 def test_get_server_certificate(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001576 _test_get_server_certificate(self, *self.server_addr, cert=SIGNING_CA)
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001577
Martin Panter3840b2a2016-03-27 01:53:46 +00001578 def test_get_server_certificate_fail(self):
1579 # Connection failure crashes ThreadedEchoServer, so run this in an
1580 # independent test method
1581 _test_get_server_certificate_fail(self, *self.server_addr)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001582
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001583 def test_ciphers(self):
Martin Panter3840b2a2016-03-27 01:53:46 +00001584 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1585 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1586 s.connect(self.server_addr)
1587 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1588 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1589 s.connect(self.server_addr)
1590 # Error checking can happen at instantiation or when connecting
1591 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
1592 with socket.socket(socket.AF_INET) as sock:
1593 s = ssl.wrap_socket(sock,
1594 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1595 s.connect(self.server_addr)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001596
Christian Heimes9a5395a2013-06-17 15:44:12 +02001597 def test_get_ca_certs_capath(self):
1598 # capath certs are loaded on request
Martin Panter3840b2a2016-03-27 01:53:46 +00001599 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1600 ctx.verify_mode = ssl.CERT_REQUIRED
1601 ctx.load_verify_locations(capath=CAPATH)
1602 self.assertEqual(ctx.get_ca_certs(), [])
1603 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1604 s.connect(self.server_addr)
1605 cert = s.getpeercert()
1606 self.assertTrue(cert)
1607 self.assertEqual(len(ctx.get_ca_certs()), 1)
Christian Heimes9a5395a2013-06-17 15:44:12 +02001608
Christian Heimes575596e2013-12-15 21:49:17 +01001609 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01001610 def test_context_setget(self):
1611 # Check that the context of a connected socket can be replaced.
Martin Panter3840b2a2016-03-27 01:53:46 +00001612 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1613 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1614 s = socket.socket(socket.AF_INET)
1615 with ctx1.wrap_socket(s) as ss:
1616 ss.connect(self.server_addr)
1617 self.assertIs(ss.context, ctx1)
1618 self.assertIs(ss._sslobj.context, ctx1)
1619 ss.context = ctx2
1620 self.assertIs(ss.context, ctx2)
1621 self.assertIs(ss._sslobj.context, ctx2)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001622
1623 def ssl_io_loop(self, sock, incoming, outgoing, func, *args, **kwargs):
1624 # A simple IO loop. Call func(*args) depending on the error we get
1625 # (WANT_READ or WANT_WRITE) move data between the socket and the BIOs.
1626 timeout = kwargs.get('timeout', 10)
1627 count = 0
1628 while True:
1629 errno = None
1630 count += 1
1631 try:
1632 ret = func(*args)
1633 except ssl.SSLError as e:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001634 if e.errno not in (ssl.SSL_ERROR_WANT_READ,
Martin Panter40b97ec2016-01-14 13:05:46 +00001635 ssl.SSL_ERROR_WANT_WRITE):
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001636 raise
1637 errno = e.errno
1638 # Get any data from the outgoing BIO irrespective of any error, and
1639 # send it to the socket.
1640 buf = outgoing.read()
1641 sock.sendall(buf)
1642 # If there's no error, we're done. For WANT_READ, we need to get
1643 # data from the socket and put it in the incoming BIO.
1644 if errno is None:
1645 break
1646 elif errno == ssl.SSL_ERROR_WANT_READ:
1647 buf = sock.recv(32768)
1648 if buf:
1649 incoming.write(buf)
1650 else:
1651 incoming.write_eof()
1652 if support.verbose:
1653 sys.stdout.write("Needed %d calls to complete %s().\n"
1654 % (count, func.__name__))
1655 return ret
1656
Martin Panter3840b2a2016-03-27 01:53:46 +00001657 def test_bio_handshake(self):
1658 sock = socket.socket(socket.AF_INET)
1659 self.addCleanup(sock.close)
1660 sock.connect(self.server_addr)
1661 incoming = ssl.MemoryBIO()
1662 outgoing = ssl.MemoryBIO()
1663 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1664 ctx.verify_mode = ssl.CERT_REQUIRED
1665 ctx.load_verify_locations(SIGNING_CA)
1666 ctx.check_hostname = True
1667 sslobj = ctx.wrap_bio(incoming, outgoing, False, 'localhost')
1668 self.assertIs(sslobj._sslobj.owner, sslobj)
1669 self.assertIsNone(sslobj.cipher())
1670 self.assertIsNone(sslobj.shared_ciphers())
1671 self.assertRaises(ValueError, sslobj.getpeercert)
1672 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
1673 self.assertIsNone(sslobj.get_channel_binding('tls-unique'))
1674 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
1675 self.assertTrue(sslobj.cipher())
1676 self.assertIsNone(sslobj.shared_ciphers())
1677 self.assertTrue(sslobj.getpeercert())
1678 if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
1679 self.assertTrue(sslobj.get_channel_binding('tls-unique'))
1680 try:
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001681 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Martin Panter3840b2a2016-03-27 01:53:46 +00001682 except ssl.SSLSyscallError:
1683 # If the server shuts down the TCP connection without sending a
1684 # secure shutdown message, this is reported as SSL_ERROR_SYSCALL
1685 pass
1686 self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
1687
1688 def test_bio_read_write_data(self):
1689 sock = socket.socket(socket.AF_INET)
1690 self.addCleanup(sock.close)
1691 sock.connect(self.server_addr)
1692 incoming = ssl.MemoryBIO()
1693 outgoing = ssl.MemoryBIO()
1694 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1695 ctx.verify_mode = ssl.CERT_NONE
1696 sslobj = ctx.wrap_bio(incoming, outgoing, False)
1697 self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)
1698 req = b'FOO\n'
1699 self.ssl_io_loop(sock, incoming, outgoing, sslobj.write, req)
1700 buf = self.ssl_io_loop(sock, incoming, outgoing, sslobj.read, 1024)
1701 self.assertEqual(buf, b'foo\n')
1702 self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
Antoine Pitroub1fdf472014-10-05 20:41:53 +02001703
1704
Martin Panter3840b2a2016-03-27 01:53:46 +00001705class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001706
Martin Panter3840b2a2016-03-27 01:53:46 +00001707 def test_timeout_connect_ex(self):
1708 # Issue #12065: on a timeout, connect_ex() should return the original
1709 # errno (mimicking the behaviour of non-SSL sockets).
1710 with support.transient_internet(REMOTE_HOST):
1711 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1712 cert_reqs=ssl.CERT_REQUIRED,
1713 do_handshake_on_connect=False)
1714 self.addCleanup(s.close)
1715 s.settimeout(0.0000001)
1716 rc = s.connect_ex((REMOTE_HOST, 443))
1717 if rc == 0:
1718 self.skipTest("REMOTE_HOST responded too quickly")
1719 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1720
1721 @unittest.skipUnless(support.IPV6_ENABLED, 'Needs IPv6')
1722 def test_get_server_certificate_ipv6(self):
1723 with support.transient_internet('ipv6.google.com'):
1724 _test_get_server_certificate(self, 'ipv6.google.com', 443)
1725 _test_get_server_certificate_fail(self, 'ipv6.google.com', 443)
1726
1727 def test_algorithms(self):
1728 # Issue #8484: all algorithms should be available when verifying a
1729 # certificate.
1730 # SHA256 was added in OpenSSL 0.9.8
1731 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1732 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
1733 # sha256.tbs-internet.com needs SNI to use the correct certificate
1734 if not ssl.HAS_SNI:
1735 self.skipTest("SNI needed for this test")
1736 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1737 remote = ("sha256.tbs-internet.com", 443)
1738 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
1739 with support.transient_internet("sha256.tbs-internet.com"):
1740 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1741 ctx.verify_mode = ssl.CERT_REQUIRED
1742 ctx.load_verify_locations(sha256_cert)
1743 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1744 server_hostname="sha256.tbs-internet.com")
1745 try:
1746 s.connect(remote)
1747 if support.verbose:
1748 sys.stdout.write("\nCipher with %r is %r\n" %
1749 (remote, s.cipher()))
1750 sys.stdout.write("Certificate is:\n%s\n" %
1751 pprint.pformat(s.getpeercert()))
1752 finally:
1753 s.close()
1754
1755
1756def _test_get_server_certificate(test, host, port, cert=None):
1757 pem = ssl.get_server_certificate((host, port))
1758 if not pem:
1759 test.fail("No server certificate on %s:%s!" % (host, port))
1760
1761 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
1762 if not pem:
1763 test.fail("No server certificate on %s:%s!" % (host, port))
1764 if support.verbose:
1765 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
1766
1767def _test_get_server_certificate_fail(test, host, port):
1768 try:
1769 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
1770 except ssl.SSLError as x:
1771 #should fail
1772 if support.verbose:
1773 sys.stdout.write("%s\n" % x)
1774 else:
1775 test.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1776
1777
1778if _have_threads:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001779 from test.ssl_servers import make_https_server
1780
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001781 class ThreadedEchoServer(threading.Thread):
1782
1783 class ConnectionHandler(threading.Thread):
1784
1785 """A mildly complicated class, because we want it to work both
1786 with and without the SSL wrapper around the socket connection, so
1787 that we can test the STARTTLS functionality."""
1788
Bill Janssen6e027db2007-11-15 22:23:56 +00001789 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001790 self.server = server
1791 self.running = False
1792 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001793 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001794 self.sock.setblocking(1)
1795 self.sslconn = None
1796 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001797 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001798
Antoine Pitrou480a1242010-04-28 21:37:09 +00001799 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001800 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001801 self.sslconn = self.server.context.wrap_socket(
1802 self.sock, server_side=True)
Benjamin Petersoncca27322015-01-23 16:35:37 -05001803 self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
1804 self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001805 except (ssl.SSLError, ConnectionResetError) as e:
1806 # We treat ConnectionResetError as though it were an
1807 # SSLError - OpenSSL on Ubuntu abruptly closes the
1808 # connection when asked to use an unsupported protocol.
1809 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001810 # XXX Various errors can have happened here, for example
1811 # a mismatching protocol version, an invalid certificate,
1812 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001813 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001814 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001815 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001816 self.running = False
1817 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001818 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001819 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001820 else:
Benjamin Peterson4cb17812015-01-07 11:14:26 -06001821 self.server.shared_ciphers.append(self.sslconn.shared_ciphers())
Antoine Pitroub5218772010-05-21 09:56:06 +00001822 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001823 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001824 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001825 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1826 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001827 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001828 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1829 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001830 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001831 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001832 sys.stdout.write(" server: selected protocol is now "
1833 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001834 return True
1835
1836 def read(self):
1837 if self.sslconn:
1838 return self.sslconn.read()
1839 else:
1840 return self.sock.recv(1024)
1841
1842 def write(self, bytes):
1843 if self.sslconn:
1844 return self.sslconn.write(bytes)
1845 else:
1846 return self.sock.send(bytes)
1847
1848 def close(self):
1849 if self.sslconn:
1850 self.sslconn.close()
1851 else:
1852 self.sock.close()
1853
Antoine Pitrou480a1242010-04-28 21:37:09 +00001854 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001855 self.running = True
1856 if not self.server.starttls_server:
1857 if not self.wrap_conn():
1858 return
1859 while self.running:
1860 try:
1861 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001862 stripped = msg.strip()
1863 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001864 # eof, so quit this handler
1865 self.running = False
Martin Panter3840b2a2016-03-27 01:53:46 +00001866 try:
1867 self.sock = self.sslconn.unwrap()
1868 except OSError:
1869 # Many tests shut the TCP connection down
1870 # without an SSL shutdown. This causes
1871 # unwrap() to raise OSError with errno=0!
1872 pass
1873 else:
1874 self.sslconn = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001875 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001876 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001877 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001878 sys.stdout.write(" server: client closed connection\n")
1879 self.close()
1880 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001881 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001882 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001883 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001884 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001885 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001886 if not self.wrap_conn():
1887 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001888 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001889 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001890 if support.verbose and self.server.connectionchatty:
1891 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001892 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001893 self.sock = self.sslconn.unwrap()
1894 self.sslconn = None
1895 if support.verbose and self.server.connectionchatty:
1896 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001897 elif stripped == b'CB tls-unique':
1898 if support.verbose and self.server.connectionchatty:
1899 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1900 data = self.sslconn.get_channel_binding("tls-unique")
1901 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001902 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001903 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001904 self.server.connectionchatty):
1905 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001906 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1907 % (msg, ctype, msg.lower(), ctype))
1908 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001909 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001910 if self.server.chatty:
1911 handle_error("Test server failure:\n")
1912 self.close()
1913 self.running = False
1914 # normally, we'd just stop here, but for the test
1915 # harness, we want to stop the server
1916 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001917
Antoine Pitroub5218772010-05-21 09:56:06 +00001918 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001919 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001920 chatty=True, connectionchatty=False, starttls_server=False,
Benjamin Petersoncca27322015-01-23 16:35:37 -05001921 npn_protocols=None, alpn_protocols=None,
1922 ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001923 if context:
1924 self.context = context
1925 else:
1926 self.context = ssl.SSLContext(ssl_version
1927 if ssl_version is not None
1928 else ssl.PROTOCOL_TLSv1)
1929 self.context.verify_mode = (certreqs if certreqs is not None
1930 else ssl.CERT_NONE)
1931 if cacerts:
1932 self.context.load_verify_locations(cacerts)
1933 if certificate:
1934 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001935 if npn_protocols:
1936 self.context.set_npn_protocols(npn_protocols)
Benjamin Petersoncca27322015-01-23 16:35:37 -05001937 if alpn_protocols:
1938 self.context.set_alpn_protocols(alpn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001939 if ciphers:
1940 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001941 self.chatty = chatty
1942 self.connectionchatty = connectionchatty
1943 self.starttls_server = starttls_server
1944 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001945 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001946 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001947 self.active = False
Benjamin Petersoncca27322015-01-23 16:35:37 -05001948 self.selected_npn_protocols = []
1949 self.selected_alpn_protocols = []
Benjamin Peterson4cb17812015-01-07 11:14:26 -06001950 self.shared_ciphers = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001951 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001952 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001953 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001954
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001955 def __enter__(self):
1956 self.start(threading.Event())
1957 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001958 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001959
1960 def __exit__(self, *args):
1961 self.stop()
1962 self.join()
1963
Antoine Pitrou480a1242010-04-28 21:37:09 +00001964 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001965 self.flag = flag
1966 threading.Thread.start(self)
1967
Antoine Pitrou480a1242010-04-28 21:37:09 +00001968 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001969 self.sock.settimeout(0.05)
Charles-François Natali6e204602014-07-23 19:28:13 +01001970 self.sock.listen()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001971 self.active = True
1972 if self.flag:
1973 # signal an event
1974 self.flag.set()
1975 while self.active:
1976 try:
1977 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001978 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001979 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001980 + repr(connaddr) + '\n')
1981 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001982 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001983 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001984 except socket.timeout:
1985 pass
1986 except KeyboardInterrupt:
1987 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001988 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001989
Antoine Pitrou480a1242010-04-28 21:37:09 +00001990 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001991 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001992
Bill Janssen54cc54c2007-12-14 22:08:56 +00001993 class AsyncoreEchoServer(threading.Thread):
1994
1995 # this one's based on asyncore.dispatcher
1996
1997 class EchoServer (asyncore.dispatcher):
1998
1999 class ConnectionHandler (asyncore.dispatcher_with_send):
2000
2001 def __init__(self, conn, certfile):
2002 self.socket = ssl.wrap_socket(conn, server_side=True,
2003 certfile=certfile,
2004 do_handshake_on_connect=False)
2005 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002006 self._ssl_accepting = True
2007 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002008
2009 def readable(self):
2010 if isinstance(self.socket, ssl.SSLSocket):
2011 while self.socket.pending() > 0:
2012 self.handle_read_event()
2013 return True
2014
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002015 def _do_ssl_handshake(self):
2016 try:
2017 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02002018 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
2019 return
2020 except ssl.SSLEOFError:
2021 return self.handle_close()
2022 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002023 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02002024 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002025 if err.args[0] == errno.ECONNABORTED:
2026 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00002027 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002028 self._ssl_accepting = False
2029
2030 def handle_read(self):
2031 if self._ssl_accepting:
2032 self._do_ssl_handshake()
2033 else:
2034 data = self.recv(1024)
2035 if support.verbose:
2036 sys.stdout.write(" server: read %s from client\n" % repr(data))
2037 if not data:
2038 self.close()
2039 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002040 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00002041
2042 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00002043 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002044 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002045 sys.stdout.write(" server: closed connection %s\n" % self.socket)
2046
2047 def handle_error(self):
2048 raise
2049
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002050 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002051 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002052 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2053 self.port = support.bind_port(sock, '')
2054 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00002055 self.listen(5)
2056
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00002057 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002058 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00002059 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
2060 self.ConnectionHandler(sock_obj, self.certfile)
2061
2062 def handle_error(self):
2063 raise
2064
Trent Nelson78520002008-04-10 20:54:35 +00002065 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002066 self.flag = None
2067 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002068 self.server = self.EchoServer(certfile)
2069 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00002070 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00002071 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00002072
2073 def __str__(self):
2074 return "<%s %s>" % (self.__class__.__name__, self.server)
2075
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002076 def __enter__(self):
2077 self.start(threading.Event())
2078 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002079 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002080
2081 def __exit__(self, *args):
2082 if support.verbose:
2083 sys.stdout.write(" cleanup: stopping server.\n")
2084 self.stop()
2085 if support.verbose:
2086 sys.stdout.write(" cleanup: joining server thread.\n")
2087 self.join()
2088 if support.verbose:
2089 sys.stdout.write(" cleanup: successfully joined.\n")
2090
Bill Janssen54cc54c2007-12-14 22:08:56 +00002091 def start (self, flag=None):
2092 self.flag = flag
2093 threading.Thread.start(self)
2094
Antoine Pitrou480a1242010-04-28 21:37:09 +00002095 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002096 self.active = True
2097 if self.flag:
2098 self.flag.set()
2099 while self.active:
2100 try:
2101 asyncore.loop(1)
2102 except:
2103 pass
2104
Antoine Pitrou480a1242010-04-28 21:37:09 +00002105 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00002106 self.active = False
2107 self.server.close()
2108
Antoine Pitroub5218772010-05-21 09:56:06 +00002109 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002110 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00002111 """
2112 Launch a server, connect a client to it and try various reads
2113 and writes.
2114 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002115 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00002116 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002117 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00002118 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002119 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002120 with client_context.wrap_socket(socket.socket(),
2121 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01002122 s.connect((HOST, server.port))
2123 for arg in [indata, bytearray(indata), memoryview(indata)]:
2124 if connectionchatty:
2125 if support.verbose:
2126 sys.stdout.write(
2127 " client: sending %r...\n" % indata)
2128 s.write(arg)
2129 outdata = s.read()
2130 if connectionchatty:
2131 if support.verbose:
2132 sys.stdout.write(" client: read %r\n" % outdata)
2133 if outdata != indata.lower():
2134 raise AssertionError(
2135 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2136 % (outdata[:20], len(outdata),
2137 indata[:20].lower(), len(indata)))
2138 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00002139 if connectionchatty:
2140 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01002141 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002142 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01002143 'compression': s.compression(),
2144 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002145 'peercert': s.getpeercert(),
Benjamin Petersoncca27322015-01-23 16:35:37 -05002146 'client_alpn_protocol': s.selected_alpn_protocol(),
Antoine Pitrou47e40422014-09-04 21:00:10 +02002147 'client_npn_protocol': s.selected_npn_protocol(),
2148 'version': s.version(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002149 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01002150 s.close()
Benjamin Petersoncca27322015-01-23 16:35:37 -05002151 stats['server_alpn_protocols'] = server.selected_alpn_protocols
2152 stats['server_npn_protocols'] = server.selected_npn_protocols
Benjamin Peterson4cb17812015-01-07 11:14:26 -06002153 stats['server_shared_ciphers'] = server.shared_ciphers
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002154 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00002155
Antoine Pitroub5218772010-05-21 09:56:06 +00002156 def try_protocol_combo(server_protocol, client_protocol, expect_success,
2157 certsreqs=None, server_options=0, client_options=0):
Antoine Pitrou47e40422014-09-04 21:00:10 +02002158 """
2159 Try to SSL-connect using *client_protocol* to *server_protocol*.
2160 If *expect_success* is true, assert that the connection succeeds,
2161 if it's false, assert that the connection fails.
2162 Also, if *expect_success* is a string, assert that it is the protocol
2163 version actually used by the connection.
2164 """
Benjamin Peterson2a691a82008-03-31 01:51:45 +00002165 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002166 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00002167 certtype = {
2168 ssl.CERT_NONE: "CERT_NONE",
2169 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
2170 ssl.CERT_REQUIRED: "CERT_REQUIRED",
2171 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002172 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002173 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002174 sys.stdout.write(formatstr %
2175 (ssl.get_protocol_name(client_protocol),
2176 ssl.get_protocol_name(server_protocol),
2177 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00002178 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01002179 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00002180 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01002181 server_context.options |= server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002182
2183 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
2184 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
2185 # starting from OpenSSL 1.0.0 (see issue #8322).
2186 if client_context.protocol == ssl.PROTOCOL_SSLv23:
2187 client_context.set_ciphers("ALL")
2188
Antoine Pitroub5218772010-05-21 09:56:06 +00002189 for ctx in (client_context, server_context):
2190 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00002191 ctx.load_cert_chain(CERTFILE)
2192 ctx.load_verify_locations(CERTFILE)
2193 try:
Antoine Pitrou47e40422014-09-04 21:00:10 +02002194 stats = server_params_test(client_context, server_context,
2195 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002196 # Protocol mismatch can result in either an SSLError, or a
2197 # "Connection reset by peer" error.
2198 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002199 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002200 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02002201 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002202 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002203 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002204 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002205 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00002206 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002207 "Client protocol %s succeeded with server protocol %s!"
2208 % (ssl.get_protocol_name(client_protocol),
2209 ssl.get_protocol_name(server_protocol)))
Antoine Pitrou47e40422014-09-04 21:00:10 +02002210 elif (expect_success is not True
2211 and expect_success != stats['version']):
2212 raise AssertionError("version mismatch: expected %r, got %r"
2213 % (expect_success, stats['version']))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002214
2215
Bill Janssen6e027db2007-11-15 22:23:56 +00002216 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002217
Antoine Pitrou23df4832010-08-04 17:14:06 +00002218 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002219 def test_echo(self):
2220 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002221 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002222 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00002223 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01002224 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
2225 context = ssl.SSLContext(protocol)
2226 context.load_cert_chain(CERTFILE)
2227 server_params_test(context, context,
2228 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002229
Antoine Pitrou480a1242010-04-28 21:37:09 +00002230 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002231 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002232 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00002233 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2234 context.verify_mode = ssl.CERT_REQUIRED
2235 context.load_verify_locations(CERTFILE)
2236 context.load_cert_chain(CERTFILE)
2237 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002238 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02002239 s = context.wrap_socket(socket.socket(),
2240 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002241 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02002242 # getpeercert() raise ValueError while the handshake isn't
2243 # done.
2244 with self.assertRaises(ValueError):
2245 s.getpeercert()
2246 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002247 cert = s.getpeercert()
2248 self.assertTrue(cert, "Can't get peer certificate.")
2249 cipher = s.cipher()
2250 if support.verbose:
2251 sys.stdout.write(pprint.pformat(cert) + '\n')
2252 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
2253 if 'subject' not in cert:
2254 self.fail("No subject field in certificate: %s." %
2255 pprint.pformat(cert))
2256 if ((('organizationName', 'Python Software Foundation'),)
2257 not in cert['subject']):
2258 self.fail(
2259 "Missing or invalid 'organizationName' field in certificate subject; "
2260 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00002261 self.assertIn('notBefore', cert)
2262 self.assertIn('notAfter', cert)
2263 before = ssl.cert_time_to_seconds(cert['notBefore'])
2264 after = ssl.cert_time_to_seconds(cert['notAfter'])
2265 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002266 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002267
Christian Heimes2427b502013-11-23 11:24:32 +01002268 @unittest.skipUnless(have_verify_flags(),
2269 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01002270 def test_crl_check(self):
2271 if support.verbose:
2272 sys.stdout.write("\n")
2273
2274 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2275 server_context.load_cert_chain(SIGNED_CERTFILE)
2276
2277 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2278 context.verify_mode = ssl.CERT_REQUIRED
2279 context.load_verify_locations(SIGNING_CA)
Benjamin Petersonc3d9c5c2015-03-04 23:18:48 -05002280 tf = getattr(ssl, "VERIFY_X509_TRUSTED_FIRST", 0)
2281 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT | tf)
Christian Heimes22587792013-11-21 23:56:13 +01002282
2283 # VERIFY_DEFAULT should pass
2284 server = ThreadedEchoServer(context=server_context, chatty=True)
2285 with server:
2286 with context.wrap_socket(socket.socket()) as s:
2287 s.connect((HOST, server.port))
2288 cert = s.getpeercert()
2289 self.assertTrue(cert, "Can't get peer certificate.")
2290
2291 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimes32f0c7a2013-11-22 03:43:48 +01002292 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Christian Heimes22587792013-11-21 23:56:13 +01002293
2294 server = ThreadedEchoServer(context=server_context, chatty=True)
2295 with server:
2296 with context.wrap_socket(socket.socket()) as s:
2297 with self.assertRaisesRegex(ssl.SSLError,
2298 "certificate verify failed"):
2299 s.connect((HOST, server.port))
2300
2301 # now load a CRL file. The CRL file is signed by the CA.
2302 context.load_verify_locations(CRLFILE)
2303
2304 server = ThreadedEchoServer(context=server_context, chatty=True)
2305 with server:
2306 with context.wrap_socket(socket.socket()) as s:
2307 s.connect((HOST, server.port))
2308 cert = s.getpeercert()
2309 self.assertTrue(cert, "Can't get peer certificate.")
2310
Christian Heimes1aa9a752013-12-02 02:41:19 +01002311 def test_check_hostname(self):
2312 if support.verbose:
2313 sys.stdout.write("\n")
2314
2315 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2316 server_context.load_cert_chain(SIGNED_CERTFILE)
2317
2318 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2319 context.verify_mode = ssl.CERT_REQUIRED
2320 context.check_hostname = True
2321 context.load_verify_locations(SIGNING_CA)
2322
2323 # correct hostname should verify
2324 server = ThreadedEchoServer(context=server_context, chatty=True)
2325 with server:
2326 with context.wrap_socket(socket.socket(),
2327 server_hostname="localhost") as s:
2328 s.connect((HOST, server.port))
2329 cert = s.getpeercert()
2330 self.assertTrue(cert, "Can't get peer certificate.")
2331
2332 # incorrect hostname should raise an exception
2333 server = ThreadedEchoServer(context=server_context, chatty=True)
2334 with server:
2335 with context.wrap_socket(socket.socket(),
2336 server_hostname="invalid") as s:
2337 with self.assertRaisesRegex(ssl.CertificateError,
2338 "hostname 'invalid' doesn't match 'localhost'"):
2339 s.connect((HOST, server.port))
2340
2341 # missing server_hostname arg should cause an exception, too
2342 server = ThreadedEchoServer(context=server_context, chatty=True)
2343 with server:
2344 with socket.socket() as s:
2345 with self.assertRaisesRegex(ValueError,
2346 "check_hostname requires server_hostname"):
2347 context.wrap_socket(s)
2348
Martin Panter407b62f2016-01-30 03:41:43 +00002349 def test_wrong_cert(self):
Martin Panter3464ea22016-02-01 21:58:11 +00002350 """Connecting when the server rejects the client's certificate
2351
2352 Launch a server with CERT_REQUIRED, and check that trying to
2353 connect to it with a wrong client certificate fails.
2354 """
2355 certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
2356 "wrongcert.pem")
2357 server = ThreadedEchoServer(CERTFILE,
2358 certreqs=ssl.CERT_REQUIRED,
2359 cacerts=CERTFILE, chatty=False,
2360 connectionchatty=False)
2361 with server, \
2362 socket.socket() as sock, \
2363 ssl.wrap_socket(sock,
2364 certfile=certfile,
2365 ssl_version=ssl.PROTOCOL_TLSv1) as s:
2366 try:
2367 # Expect either an SSL error about the server rejecting
2368 # the connection, or a low-level connection reset (which
2369 # sometimes happens on Windows)
2370 s.connect((HOST, server.port))
2371 except ssl.SSLError as e:
2372 if support.verbose:
2373 sys.stdout.write("\nSSLError is %r\n" % e)
2374 except OSError as e:
2375 if e.errno != errno.ECONNRESET:
2376 raise
2377 if support.verbose:
2378 sys.stdout.write("\nsocket.error is %r\n" % e)
2379 else:
2380 self.fail("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002381
Antoine Pitrou480a1242010-04-28 21:37:09 +00002382 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002383 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00002384 in the client when attempting handshake.
2385 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00002386 listener_ready = threading.Event()
2387 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00002388
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002389 s = socket.socket()
2390 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002391
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002392 # `listener` runs in a thread. It sits in an accept() until
2393 # the main thread connects. Then it rudely closes the socket,
2394 # and sets Event `listener_gone` to let the main thread know
2395 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00002396 def listener():
Charles-François Natali6e204602014-07-23 19:28:13 +01002397 s.listen()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002398 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002399 newsock, addr = s.accept()
2400 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002401 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002402 listener_gone.set()
2403
2404 def connector():
2405 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002406 with socket.socket() as c:
2407 c.connect((HOST, port))
2408 listener_gone.wait()
2409 try:
2410 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002411 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00002412 pass
2413 else:
2414 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00002415
2416 t = threading.Thread(target=listener)
2417 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002418 try:
2419 connector()
2420 finally:
2421 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002422
Antoine Pitrou23df4832010-08-04 17:14:06 +00002423 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02002424 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2425 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002426 def test_protocol_sslv2(self):
2427 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002428 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002429 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002430 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2431 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2432 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002433 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Victor Stinner648b8622014-12-12 12:23:59 +01002434 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2435 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002436 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002437 # SSLv23 client with specific SSL options
2438 if no_sslv2_implies_sslv3_hello():
2439 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2440 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2441 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002442 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002443 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002444 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002445 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002446
Antoine Pitrou23df4832010-08-04 17:14:06 +00002447 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002448 def test_protocol_sslv23(self):
2449 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002450 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002451 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02002452 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2453 try:
2454 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02002455 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02002456 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2457 if support.verbose:
2458 sys.stdout.write(
2459 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2460 % str(x))
Benjamin Petersone32467c2014-12-05 21:59:35 -05002461 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002462 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002463 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
Antoine Pitrou47e40422014-09-04 21:00:10 +02002464 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002465
Benjamin Petersone32467c2014-12-05 21:59:35 -05002466 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002467 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002468 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
Antoine Pitrou47e40422014-09-04 21:00:10 +02002469 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002470
Benjamin Petersone32467c2014-12-05 21:59:35 -05002471 if hasattr(ssl, 'PROTOCOL_SSLv3'):
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002472 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002473 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
Antoine Pitrou47e40422014-09-04 21:00:10 +02002474 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002475
Antoine Pitroub5218772010-05-21 09:56:06 +00002476 # Server with specific SSL options
Benjamin Petersone32467c2014-12-05 21:59:35 -05002477 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2478 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002479 server_options=ssl.OP_NO_SSLv3)
2480 # Will choose TLSv1
2481 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2482 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2483 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2484 server_options=ssl.OP_NO_TLSv1)
2485
2486
Antoine Pitrou23df4832010-08-04 17:14:06 +00002487 @skip_if_broken_ubuntu_ssl
Benjamin Petersone32467c2014-12-05 21:59:35 -05002488 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2489 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002490 def test_protocol_sslv3(self):
2491 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002492 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002493 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002494 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
2495 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
2496 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002497 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2498 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002499 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2500 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002501 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002502 if no_sslv2_implies_sslv3_hello():
2503 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
Benjamin Petersona9dcdab2015-11-11 22:38:41 -08002504 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23,
2505 False, client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002506
Antoine Pitrou23df4832010-08-04 17:14:06 +00002507 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002508 def test_protocol_tlsv1(self):
2509 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002510 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002511 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002512 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
2513 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
2514 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002515 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2516 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002517 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2518 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002519 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2520 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002521
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002522 @skip_if_broken_ubuntu_ssl
2523 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2524 "TLS version 1.1 not supported.")
2525 def test_protocol_tlsv1_1(self):
2526 """Connecting to a TLSv1.1 server with various client options.
2527 Testing against older TLS versions."""
2528 if support.verbose:
2529 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002530 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002531 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2532 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002533 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2534 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002535 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2536 client_options=ssl.OP_NO_TLSv1_1)
2537
Antoine Pitrou47e40422014-09-04 21:00:10 +02002538 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002539 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2540 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2541
2542
2543 @skip_if_broken_ubuntu_ssl
2544 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2545 "TLS version 1.2 not supported.")
2546 def test_protocol_tlsv1_2(self):
2547 """Connecting to a TLSv1.2 server with various client options.
2548 Testing against older TLS versions."""
2549 if support.verbose:
2550 sys.stdout.write("\n")
Antoine Pitrou47e40422014-09-04 21:00:10 +02002551 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002552 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2553 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2554 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2555 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002556 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2557 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002558 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2559 client_options=ssl.OP_NO_TLSv1_2)
2560
Antoine Pitrou47e40422014-09-04 21:00:10 +02002561 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002562 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2563 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2564 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2565 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
2566
Antoine Pitrou480a1242010-04-28 21:37:09 +00002567 def test_starttls(self):
2568 """Switching from clear text to encrypted and back again."""
2569 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 +00002570
Trent Nelson78520002008-04-10 20:54:35 +00002571 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002572 ssl_version=ssl.PROTOCOL_TLSv1,
2573 starttls_server=True,
2574 chatty=True,
2575 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002576 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002577 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002578 s = socket.socket()
2579 s.setblocking(1)
2580 s.connect((HOST, server.port))
2581 if support.verbose:
2582 sys.stdout.write("\n")
2583 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002584 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002585 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002586 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002587 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002588 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002589 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002590 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002591 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002592 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002593 msg = outdata.strip().lower()
2594 if indata == b"STARTTLS" and msg.startswith(b"ok"):
2595 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002596 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002597 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002598 " client: read %r from server, starting TLS...\n"
2599 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002600 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2601 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00002602 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
2603 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002604 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002605 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002606 " client: read %r from server, ending TLS...\n"
2607 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002608 s = conn.unwrap()
2609 wrapped = False
2610 else:
2611 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002612 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002613 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002614 if support.verbose:
2615 sys.stdout.write(" client: closing connection.\n")
2616 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002617 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002618 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002619 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00002620 if wrapped:
2621 conn.close()
2622 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002623 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002624
Antoine Pitrou480a1242010-04-28 21:37:09 +00002625 def test_socketserver(self):
2626 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01002627 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002628 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002629 if support.verbose:
2630 sys.stdout.write('\n')
2631 with open(CERTFILE, 'rb') as f:
2632 d1 = f.read()
2633 d2 = ''
2634 # now fetch the same data from the HTTPS server
Benjamin Peterson4ffb0752014-11-03 14:29:33 -05002635 url = 'https://localhost:%d/%s' % (
2636 server.port, os.path.split(CERTFILE)[1])
2637 context = ssl.create_default_context(cafile=CERTFILE)
2638 f = urllib.request.urlopen(url, context=context)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002639 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00002640 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002641 if dlen and (int(dlen) > 0):
2642 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002643 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002644 sys.stdout.write(
2645 " client: read %d bytes from remote server '%s'\n"
2646 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002647 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002648 f.close()
2649 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002650
Antoine Pitrou480a1242010-04-28 21:37:09 +00002651 def test_asyncore_server(self):
2652 """Check the example asyncore integration."""
2653 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00002654
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002655 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002656 sys.stdout.write("\n")
2657
Antoine Pitrou480a1242010-04-28 21:37:09 +00002658 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00002659 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002660 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002661 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002662 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002663 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002664 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002665 " client: sending %r...\n" % indata)
2666 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002667 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002668 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002669 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002670 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002671 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002672 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2673 % (outdata[:20], len(outdata),
2674 indata[:20].lower(), len(indata)))
2675 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002676 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002677 sys.stdout.write(" client: closing connection.\n")
2678 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00002679 if support.verbose:
2680 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00002681
Antoine Pitrou480a1242010-04-28 21:37:09 +00002682 def test_recv_send(self):
2683 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00002684 if support.verbose:
2685 sys.stdout.write("\n")
2686
2687 server = ThreadedEchoServer(CERTFILE,
2688 certreqs=ssl.CERT_NONE,
2689 ssl_version=ssl.PROTOCOL_TLSv1,
2690 cacerts=CERTFILE,
2691 chatty=True,
2692 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002693 with server:
2694 s = ssl.wrap_socket(socket.socket(),
2695 server_side=False,
2696 certfile=CERTFILE,
2697 ca_certs=CERTFILE,
2698 cert_reqs=ssl.CERT_NONE,
2699 ssl_version=ssl.PROTOCOL_TLSv1)
2700 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002701 # helper methods for standardising recv* method signatures
2702 def _recv_into():
2703 b = bytearray(b"\0"*100)
2704 count = s.recv_into(b)
2705 return b[:count]
2706
2707 def _recvfrom_into():
2708 b = bytearray(b"\0"*100)
2709 count, addr = s.recvfrom_into(b)
2710 return b[:count]
2711
Martin Panter519f9122016-04-03 02:12:54 +00002712 # (name, method, expect success?, *args, return value func)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002713 send_methods = [
Martin Panter519f9122016-04-03 02:12:54 +00002714 ('send', s.send, True, [], len),
2715 ('sendto', s.sendto, False, ["some.address"], len),
2716 ('sendall', s.sendall, True, [], lambda x: None),
Bill Janssen58afe4c2008-09-08 16:45:19 +00002717 ]
Martin Panter519f9122016-04-03 02:12:54 +00002718 # (name, method, whether to expect success, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002719 recv_methods = [
2720 ('recv', s.recv, True, []),
2721 ('recvfrom', s.recvfrom, False, ["some.address"]),
2722 ('recv_into', _recv_into, True, []),
2723 ('recvfrom_into', _recvfrom_into, False, []),
2724 ]
2725 data_prefix = "PREFIX_"
2726
Martin Panter519f9122016-04-03 02:12:54 +00002727 for (meth_name, send_meth, expect_success, args,
2728 ret_val_meth) in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002729 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002730 try:
Martin Panter519f9122016-04-03 02:12:54 +00002731 ret = send_meth(indata, *args)
2732 msg = "sending with {}".format(meth_name)
2733 self.assertEqual(ret, ret_val_meth(indata), msg=msg)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002734 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002735 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002736 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002737 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002738 "<<{outdata:r}>> ({nout:d}) received; "
2739 "expected <<{indata:r}>> ({nin:d})\n".format(
2740 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002741 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002742 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002743 )
2744 )
2745 except ValueError as e:
2746 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002747 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002748 "Failed to send with method <<{name:s}>>; "
2749 "expected to succeed.\n".format(name=meth_name)
2750 )
2751 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002752 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002753 "Method <<{name:s}>> failed with unexpected "
2754 "exception message: {exp:s}\n".format(
2755 name=meth_name, exp=e
2756 )
2757 )
2758
2759 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002760 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002761 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002762 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002763 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002764 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002765 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002766 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002767 "<<{outdata:r}>> ({nout:d}) received; "
2768 "expected <<{indata:r}>> ({nin:d})\n".format(
2769 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002770 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002771 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002772 )
2773 )
2774 except ValueError as e:
2775 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002776 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002777 "Failed to receive with method <<{name:s}>>; "
2778 "expected to succeed.\n".format(name=meth_name)
2779 )
2780 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002781 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002782 "Method <<{name:s}>> failed with unexpected "
2783 "exception message: {exp:s}\n".format(
2784 name=meth_name, exp=e
2785 )
2786 )
2787 # consume data
2788 s.read()
2789
Martin Panter5503d472016-03-27 05:35:19 +00002790 data = b"data"
Martin Panterf6b1d662016-03-28 00:22:09 +00002791
2792 # read(-1, buffer) is supported, even though read(-1) is not
Martin Panter5503d472016-03-27 05:35:19 +00002793 s.send(data)
2794 buffer = bytearray(len(data))
2795 self.assertEqual(s.read(-1, buffer), len(data))
2796 self.assertEqual(buffer, data)
2797
Martin Panterf6b1d662016-03-28 00:22:09 +00002798 # recv/read(0) should return no data
2799 s.send(data)
2800 self.assertEqual(s.recv(0), b"")
2801 self.assertEqual(s.read(0), b"")
2802 self.assertEqual(s.read(), data)
2803
Nick Coghlan513886a2011-08-28 00:00:27 +10002804 # Make sure sendmsg et al are disallowed to avoid
2805 # inadvertent disclosure of data and/or corruption
2806 # of the encrypted data stream
2807 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2808 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2809 self.assertRaises(NotImplementedError,
2810 s.recvmsg_into, bytearray(100))
2811
Antoine Pitrou480a1242010-04-28 21:37:09 +00002812 s.write(b"over\n")
Martin Panter5503d472016-03-27 05:35:19 +00002813
2814 self.assertRaises(ValueError, s.recv, -1)
2815 self.assertRaises(ValueError, s.read, -1)
2816
Bill Janssen58afe4c2008-09-08 16:45:19 +00002817 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002818
Antoine Pitroub4bebda2014-04-29 10:03:28 +02002819 def test_nonblocking_send(self):
2820 server = ThreadedEchoServer(CERTFILE,
2821 certreqs=ssl.CERT_NONE,
2822 ssl_version=ssl.PROTOCOL_TLSv1,
2823 cacerts=CERTFILE,
2824 chatty=True,
2825 connectionchatty=False)
2826 with server:
2827 s = ssl.wrap_socket(socket.socket(),
2828 server_side=False,
2829 certfile=CERTFILE,
2830 ca_certs=CERTFILE,
2831 cert_reqs=ssl.CERT_NONE,
2832 ssl_version=ssl.PROTOCOL_TLSv1)
2833 s.connect((HOST, server.port))
2834 s.setblocking(False)
2835
2836 # If we keep sending data, at some point the buffers
2837 # will be full and the call will block
2838 buf = bytearray(8192)
2839 def fill_buffer():
2840 while True:
2841 s.send(buf)
2842 self.assertRaises((ssl.SSLWantWriteError,
2843 ssl.SSLWantReadError), fill_buffer)
2844
2845 # Now read all the output and discard it
2846 s.setblocking(True)
2847 s.close()
2848
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002849 def test_handshake_timeout(self):
2850 # Issue #5103: SSL handshake must respect the socket timeout
2851 server = socket.socket(socket.AF_INET)
2852 host = "127.0.0.1"
2853 port = support.bind_port(server)
2854 started = threading.Event()
2855 finish = False
2856
2857 def serve():
Charles-François Natali6e204602014-07-23 19:28:13 +01002858 server.listen()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002859 started.set()
2860 conns = []
2861 while not finish:
2862 r, w, e = select.select([server], [], [], 0.1)
2863 if server in r:
2864 # Let the socket hang around rather than having
2865 # it closed by garbage collection.
2866 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002867 for sock in conns:
2868 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002869
2870 t = threading.Thread(target=serve)
2871 t.start()
2872 started.wait()
2873
2874 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002875 try:
2876 c = socket.socket(socket.AF_INET)
2877 c.settimeout(0.2)
2878 c.connect((host, port))
2879 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002880 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002881 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002882 finally:
2883 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002884 try:
2885 c = socket.socket(socket.AF_INET)
2886 c = ssl.wrap_socket(c)
2887 c.settimeout(0.2)
2888 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002889 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002890 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002891 finally:
2892 c.close()
2893 finally:
2894 finish = True
2895 t.join()
2896 server.close()
2897
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002898 def test_server_accept(self):
2899 # Issue #16357: accept() on a SSLSocket created through
2900 # SSLContext.wrap_socket().
2901 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2902 context.verify_mode = ssl.CERT_REQUIRED
2903 context.load_verify_locations(CERTFILE)
2904 context.load_cert_chain(CERTFILE)
2905 server = socket.socket(socket.AF_INET)
2906 host = "127.0.0.1"
2907 port = support.bind_port(server)
2908 server = context.wrap_socket(server, server_side=True)
2909
2910 evt = threading.Event()
2911 remote = None
2912 peer = None
2913 def serve():
2914 nonlocal remote, peer
Charles-François Natali6e204602014-07-23 19:28:13 +01002915 server.listen()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002916 # Block on the accept and wait on the connection to close.
2917 evt.set()
2918 remote, peer = server.accept()
2919 remote.recv(1)
2920
2921 t = threading.Thread(target=serve)
2922 t.start()
2923 # Client wait until server setup and perform a connect.
2924 evt.wait()
2925 client = context.wrap_socket(socket.socket())
2926 client.connect((host, port))
2927 client_addr = client.getsockname()
2928 client.close()
2929 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002930 remote.close()
2931 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002932 # Sanity checks.
2933 self.assertIsInstance(remote, ssl.SSLSocket)
2934 self.assertEqual(peer, client_addr)
2935
Antoine Pitrou242db722013-05-01 20:52:07 +02002936 def test_getpeercert_enotconn(self):
2937 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2938 with context.wrap_socket(socket.socket()) as sock:
2939 with self.assertRaises(OSError) as cm:
2940 sock.getpeercert()
2941 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2942
2943 def test_do_handshake_enotconn(self):
2944 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2945 with context.wrap_socket(socket.socket()) as sock:
2946 with self.assertRaises(OSError) as cm:
2947 sock.do_handshake()
2948 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2949
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002950 def test_default_ciphers(self):
2951 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2952 try:
2953 # Force a set of weak ciphers on our client context
2954 context.set_ciphers("DES")
2955 except ssl.SSLError:
2956 self.skipTest("no DES cipher available")
2957 with ThreadedEchoServer(CERTFILE,
2958 ssl_version=ssl.PROTOCOL_SSLv23,
2959 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002960 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002961 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002962 s.connect((HOST, server.port))
2963 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2964
Antoine Pitrou47e40422014-09-04 21:00:10 +02002965 def test_version_basic(self):
2966 """
2967 Basic tests for SSLSocket.version().
2968 More tests are done in the test_protocol_*() methods.
2969 """
2970 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2971 with ThreadedEchoServer(CERTFILE,
2972 ssl_version=ssl.PROTOCOL_TLSv1,
2973 chatty=False) as server:
2974 with context.wrap_socket(socket.socket()) as s:
2975 self.assertIs(s.version(), None)
2976 s.connect((HOST, server.port))
2977 self.assertEqual(s.version(), "TLSv1")
2978 self.assertIs(s.version(), None)
2979
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002980 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2981 def test_default_ecdh_curve(self):
2982 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2983 # should be enabled by default on SSL contexts.
2984 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2985 context.load_cert_chain(CERTFILE)
Antoine Pitrouc0430612014-04-16 18:33:39 +02002986 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2987 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2988 # our default cipher list should prefer ECDH-based ciphers
2989 # automatically.
2990 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2991 context.set_ciphers("ECCdraft:ECDH")
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002992 with ThreadedEchoServer(context=context) as server:
2993 with context.wrap_socket(socket.socket()) as s:
2994 s.connect((HOST, server.port))
2995 self.assertIn("ECDH", s.cipher()[0])
2996
Antoine Pitroud6494802011-07-21 01:11:30 +02002997 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2998 "'tls-unique' channel binding not available")
2999 def test_tls_unique_channel_binding(self):
3000 """Test tls-unique channel binding."""
3001 if support.verbose:
3002 sys.stdout.write("\n")
3003
3004 server = ThreadedEchoServer(CERTFILE,
3005 certreqs=ssl.CERT_NONE,
3006 ssl_version=ssl.PROTOCOL_TLSv1,
3007 cacerts=CERTFILE,
3008 chatty=True,
3009 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01003010 with server:
3011 s = ssl.wrap_socket(socket.socket(),
3012 server_side=False,
3013 certfile=CERTFILE,
3014 ca_certs=CERTFILE,
3015 cert_reqs=ssl.CERT_NONE,
3016 ssl_version=ssl.PROTOCOL_TLSv1)
3017 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02003018 # get the data
3019 cb_data = s.get_channel_binding("tls-unique")
3020 if support.verbose:
3021 sys.stdout.write(" got channel binding data: {0!r}\n"
3022 .format(cb_data))
3023
3024 # check if it is sane
3025 self.assertIsNotNone(cb_data)
3026 self.assertEqual(len(cb_data), 12) # True for TLSv1
3027
3028 # and compare with the peers version
3029 s.write(b"CB tls-unique\n")
3030 peer_data_repr = s.read().strip()
3031 self.assertEqual(peer_data_repr,
3032 repr(cb_data).encode("us-ascii"))
3033 s.close()
3034
3035 # now, again
3036 s = ssl.wrap_socket(socket.socket(),
3037 server_side=False,
3038 certfile=CERTFILE,
3039 ca_certs=CERTFILE,
3040 cert_reqs=ssl.CERT_NONE,
3041 ssl_version=ssl.PROTOCOL_TLSv1)
3042 s.connect((HOST, server.port))
3043 new_cb_data = s.get_channel_binding("tls-unique")
3044 if support.verbose:
3045 sys.stdout.write(" got another channel binding data: {0!r}\n"
3046 .format(new_cb_data))
3047 # is it really unique
3048 self.assertNotEqual(cb_data, new_cb_data)
3049 self.assertIsNotNone(cb_data)
3050 self.assertEqual(len(cb_data), 12) # True for TLSv1
3051 s.write(b"CB tls-unique\n")
3052 peer_data_repr = s.read().strip()
3053 self.assertEqual(peer_data_repr,
3054 repr(new_cb_data).encode("us-ascii"))
3055 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00003056
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003057 def test_compression(self):
3058 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3059 context.load_cert_chain(CERTFILE)
3060 stats = server_params_test(context, context,
3061 chatty=True, connectionchatty=True)
3062 if support.verbose:
3063 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
3064 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
3065
3066 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
3067 "ssl.OP_NO_COMPRESSION needed for this test")
3068 def test_compression_disabled(self):
3069 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3070 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01003071 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003072 stats = server_params_test(context, context,
3073 chatty=True, connectionchatty=True)
3074 self.assertIs(stats['compression'], None)
3075
Antoine Pitrou0e576f12011-12-22 10:03:38 +01003076 def test_dh_params(self):
3077 # Check we can get a connection with ephemeral Diffie-Hellman
3078 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3079 context.load_cert_chain(CERTFILE)
3080 context.load_dh_params(DHFILE)
3081 context.set_ciphers("kEDH")
3082 stats = server_params_test(context, context,
3083 chatty=True, connectionchatty=True)
3084 cipher = stats["cipher"][0]
3085 parts = cipher.split("-")
3086 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
3087 self.fail("Non-DH cipher: " + cipher[0])
3088
Benjamin Petersoncca27322015-01-23 16:35:37 -05003089 def test_selected_alpn_protocol(self):
3090 # selected_alpn_protocol() is None unless ALPN is used.
3091 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3092 context.load_cert_chain(CERTFILE)
3093 stats = server_params_test(context, context,
3094 chatty=True, connectionchatty=True)
3095 self.assertIs(stats['client_alpn_protocol'], None)
3096
3097 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
3098 def test_selected_alpn_protocol_if_server_uses_alpn(self):
3099 # selected_alpn_protocol() is None unless ALPN is used by the client.
3100 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3101 client_context.load_verify_locations(CERTFILE)
3102 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3103 server_context.load_cert_chain(CERTFILE)
3104 server_context.set_alpn_protocols(['foo', 'bar'])
3105 stats = server_params_test(client_context, server_context,
3106 chatty=True, connectionchatty=True)
3107 self.assertIs(stats['client_alpn_protocol'], None)
3108
3109 @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
3110 def test_alpn_protocols(self):
3111 server_protocols = ['foo', 'bar', 'milkshake']
3112 protocol_tests = [
3113 (['foo', 'bar'], 'foo'),
Benjamin Peterson88615022015-01-23 17:30:26 -05003114 (['bar', 'foo'], 'foo'),
Benjamin Petersoncca27322015-01-23 16:35:37 -05003115 (['milkshake'], 'milkshake'),
Benjamin Peterson88615022015-01-23 17:30:26 -05003116 (['http/3.0', 'http/4.0'], None)
Benjamin Petersoncca27322015-01-23 16:35:37 -05003117 ]
3118 for client_protocols, expected in protocol_tests:
3119 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3120 server_context.load_cert_chain(CERTFILE)
3121 server_context.set_alpn_protocols(server_protocols)
3122 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3123 client_context.load_cert_chain(CERTFILE)
3124 client_context.set_alpn_protocols(client_protocols)
3125 stats = server_params_test(client_context, server_context,
3126 chatty=True, connectionchatty=True)
3127
3128 msg = "failed trying %s (s) and %s (c).\n" \
3129 "was expecting %s, but got %%s from the %%s" \
3130 % (str(server_protocols), str(client_protocols),
3131 str(expected))
3132 client_result = stats['client_alpn_protocol']
3133 self.assertEqual(client_result, expected, msg % (client_result, "client"))
3134 server_result = stats['server_alpn_protocols'][-1] \
3135 if len(stats['server_alpn_protocols']) else 'nothing'
3136 self.assertEqual(server_result, expected, msg % (server_result, "server"))
3137
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01003138 def test_selected_npn_protocol(self):
3139 # selected_npn_protocol() is None unless NPN is used
3140 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3141 context.load_cert_chain(CERTFILE)
3142 stats = server_params_test(context, context,
3143 chatty=True, connectionchatty=True)
3144 self.assertIs(stats['client_npn_protocol'], None)
3145
3146 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
3147 def test_npn_protocols(self):
3148 server_protocols = ['http/1.1', 'spdy/2']
3149 protocol_tests = [
3150 (['http/1.1', 'spdy/2'], 'http/1.1'),
3151 (['spdy/2', 'http/1.1'], 'http/1.1'),
3152 (['spdy/2', 'test'], 'spdy/2'),
3153 (['abc', 'def'], 'abc')
3154 ]
3155 for client_protocols, expected in protocol_tests:
3156 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3157 server_context.load_cert_chain(CERTFILE)
3158 server_context.set_npn_protocols(server_protocols)
3159 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3160 client_context.load_cert_chain(CERTFILE)
3161 client_context.set_npn_protocols(client_protocols)
3162 stats = server_params_test(client_context, server_context,
3163 chatty=True, connectionchatty=True)
3164
3165 msg = "failed trying %s (s) and %s (c).\n" \
3166 "was expecting %s, but got %%s from the %%s" \
3167 % (str(server_protocols), str(client_protocols),
3168 str(expected))
3169 client_result = stats['client_npn_protocol']
3170 self.assertEqual(client_result, expected, msg % (client_result, "client"))
3171 server_result = stats['server_npn_protocols'][-1] \
3172 if len(stats['server_npn_protocols']) else 'nothing'
3173 self.assertEqual(server_result, expected, msg % (server_result, "server"))
3174
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003175 def sni_contexts(self):
3176 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3177 server_context.load_cert_chain(SIGNED_CERTFILE)
3178 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3179 other_context.load_cert_chain(SIGNED_CERTFILE2)
3180 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3181 client_context.verify_mode = ssl.CERT_REQUIRED
3182 client_context.load_verify_locations(SIGNING_CA)
3183 return server_context, other_context, client_context
3184
3185 def check_common_name(self, stats, name):
3186 cert = stats['peercert']
3187 self.assertIn((('commonName', name),), cert['subject'])
3188
3189 @needs_sni
3190 def test_sni_callback(self):
3191 calls = []
3192 server_context, other_context, client_context = self.sni_contexts()
3193
3194 def servername_cb(ssl_sock, server_name, initial_context):
3195 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02003196 if server_name is not None:
3197 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003198 server_context.set_servername_callback(servername_cb)
3199
3200 stats = server_params_test(client_context, server_context,
3201 chatty=True,
3202 sni_name='supermessage')
3203 # The hostname was fetched properly, and the certificate was
3204 # changed for the connection.
3205 self.assertEqual(calls, [("supermessage", server_context)])
3206 # CERTFILE4 was selected
3207 self.check_common_name(stats, 'fakehostname')
3208
Antoine Pitrou50b24d02013-04-11 20:48:42 +02003209 calls = []
3210 # The callback is called with server_name=None
3211 stats = server_params_test(client_context, server_context,
3212 chatty=True,
3213 sni_name=None)
3214 self.assertEqual(calls, [(None, server_context)])
3215 self.check_common_name(stats, 'localhost')
3216
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003217 # Check disabling the callback
3218 calls = []
3219 server_context.set_servername_callback(None)
3220
3221 stats = server_params_test(client_context, server_context,
3222 chatty=True,
3223 sni_name='notfunny')
3224 # Certificate didn't change
3225 self.check_common_name(stats, 'localhost')
3226 self.assertEqual(calls, [])
3227
3228 @needs_sni
3229 def test_sni_callback_alert(self):
3230 # Returning a TLS alert is reflected to the connecting client
3231 server_context, other_context, client_context = self.sni_contexts()
3232
3233 def cb_returning_alert(ssl_sock, server_name, initial_context):
3234 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
3235 server_context.set_servername_callback(cb_returning_alert)
3236
3237 with self.assertRaises(ssl.SSLError) as cm:
3238 stats = server_params_test(client_context, server_context,
3239 chatty=False,
3240 sni_name='supermessage')
3241 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
3242
3243 @needs_sni
3244 def test_sni_callback_raising(self):
3245 # Raising fails the connection with a TLS handshake failure alert.
3246 server_context, other_context, client_context = self.sni_contexts()
3247
3248 def cb_raising(ssl_sock, server_name, initial_context):
3249 1/0
3250 server_context.set_servername_callback(cb_raising)
3251
3252 with self.assertRaises(ssl.SSLError) as cm, \
3253 support.captured_stderr() as stderr:
3254 stats = server_params_test(client_context, server_context,
3255 chatty=False,
3256 sni_name='supermessage')
3257 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
3258 self.assertIn("ZeroDivisionError", stderr.getvalue())
3259
3260 @needs_sni
3261 def test_sni_callback_wrong_return_type(self):
3262 # Returning the wrong return type terminates the TLS connection
3263 # with an internal error alert.
3264 server_context, other_context, client_context = self.sni_contexts()
3265
3266 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
3267 return "foo"
3268 server_context.set_servername_callback(cb_wrong_return_type)
3269
3270 with self.assertRaises(ssl.SSLError) as cm, \
3271 support.captured_stderr() as stderr:
3272 stats = server_params_test(client_context, server_context,
3273 chatty=False,
3274 sni_name='supermessage')
3275 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
3276 self.assertIn("TypeError", stderr.getvalue())
3277
Benjamin Peterson4cb17812015-01-07 11:14:26 -06003278 def test_shared_ciphers(self):
Benjamin Petersonaacd5242015-01-07 11:42:38 -06003279 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Benjamin Peterson15042922015-01-07 22:12:43 -06003280 server_context.load_cert_chain(SIGNED_CERTFILE)
3281 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
3282 client_context.verify_mode = ssl.CERT_REQUIRED
3283 client_context.load_verify_locations(SIGNING_CA)
Benjamin Peterson23ef9fa2015-01-07 21:21:34 -06003284 client_context.set_ciphers("RC4")
Benjamin Petersone6838e02015-01-07 20:52:40 -06003285 server_context.set_ciphers("AES:RC4")
Benjamin Peterson4cb17812015-01-07 11:14:26 -06003286 stats = server_params_test(client_context, server_context)
3287 ciphers = stats['server_shared_ciphers'][0]
3288 self.assertGreater(len(ciphers), 0)
3289 for name, tls_version, bits in ciphers:
Benjamin Peterson23ef9fa2015-01-07 21:21:34 -06003290 self.assertIn("RC4", name.split("-"))
Benjamin Peterson4cb17812015-01-07 11:14:26 -06003291
Antoine Pitrou60a26e02013-07-20 19:35:16 +02003292 def test_read_write_after_close_raises_valuerror(self):
3293 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3294 context.verify_mode = ssl.CERT_REQUIRED
3295 context.load_verify_locations(CERTFILE)
3296 context.load_cert_chain(CERTFILE)
3297 server = ThreadedEchoServer(context=context, chatty=False)
3298
3299 with server:
3300 s = context.wrap_socket(socket.socket())
3301 s.connect((HOST, server.port))
3302 s.close()
3303
3304 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02003305 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02003306
Giampaolo Rodola'915d1412014-06-11 03:54:30 +02003307 def test_sendfile(self):
3308 TEST_DATA = b"x" * 512
3309 with open(support.TESTFN, 'wb') as f:
3310 f.write(TEST_DATA)
3311 self.addCleanup(support.unlink, support.TESTFN)
3312 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
3313 context.verify_mode = ssl.CERT_REQUIRED
3314 context.load_verify_locations(CERTFILE)
3315 context.load_cert_chain(CERTFILE)
3316 server = ThreadedEchoServer(context=context, chatty=False)
3317 with server:
3318 with context.wrap_socket(socket.socket()) as s:
3319 s.connect((HOST, server.port))
3320 with open(support.TESTFN, 'rb') as file:
3321 s.sendfile(file)
3322 self.assertEqual(s.recv(1024), TEST_DATA)
3323
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01003324
Thomas Woutersed03b412007-08-28 21:37:11 +00003325def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00003326 if support.verbose:
Berker Peksag9e7990a2015-05-16 23:21:26 +03003327 import warnings
Antoine Pitrou15cee622010-08-04 16:45:21 +00003328 plats = {
3329 'Linux': platform.linux_distribution,
3330 'Mac': platform.mac_ver,
3331 'Windows': platform.win32_ver,
3332 }
Berker Peksag9e7990a2015-05-16 23:21:26 +03003333 with warnings.catch_warnings():
3334 warnings.filterwarnings(
3335 'ignore',
3336 'dist\(\) and linux_distribution\(\) '
3337 'functions are deprecated .*',
3338 PendingDeprecationWarning,
3339 )
3340 for name, func in plats.items():
3341 plat = func()
3342 if plat and plat[0]:
3343 plat = '%s %r' % (name, plat)
3344 break
3345 else:
3346 plat = repr(platform.platform())
Antoine Pitrou15cee622010-08-04 16:45:21 +00003347 print("test_ssl: testing with %r %r" %
3348 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
3349 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00003350 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01003351 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
3352 try:
3353 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
3354 except AttributeError:
3355 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00003356
Antoine Pitrou152efa22010-05-16 18:19:27 +00003357 for filename in [
Martin Panter3840b2a2016-03-27 01:53:46 +00003358 CERTFILE, BYTES_CERTFILE,
Antoine Pitrou152efa22010-05-16 18:19:27 +00003359 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01003360 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00003361 BADCERT, BADKEY, EMPTYCERT]:
3362 if not os.path.exists(filename):
3363 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00003364
Martin Panter3840b2a2016-03-27 01:53:46 +00003365 tests = [
3366 ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests,
3367 SimpleBackgroundTests,
3368 ]
Thomas Woutersed03b412007-08-28 21:37:11 +00003369
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003370 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00003371 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00003372
Thomas Wouters1b7f8912007-09-19 03:06:30 +00003373 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003374 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01003375 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00003376 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00003377
Antoine Pitrou480a1242010-04-28 21:37:09 +00003378 try:
3379 support.run_unittest(*tests)
3380 finally:
3381 if _have_threads:
3382 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00003383
3384if __name__ == "__main__":
3385 test_main()