blob: 0a7b905073c3d0f570e3485e419d550ab607298e [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
Antoine Pitrou242db722013-05-01 20:52:07 +020021from unittest import mock
Thomas Woutersed03b412007-08-28 21:37:11 +000022
Antoine Pitrou05d936d2010-10-13 11:38:36 +000023ssl = support.import_module("ssl")
24
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010025PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000026HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000027
Christian Heimesefff7062013-11-21 03:35:02 +010028def data_file(*name):
29 return os.path.join(os.path.dirname(__file__), *name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000030
Antoine Pitrou81564092010-10-08 23:06:24 +000031# The custom key and certificate files used in test_ssl are generated
32# using Lib/test/make_ssl_certs.py.
33# Other certificates are simply fetched from the Internet servers they
34# are meant to authenticate.
35
Antoine Pitrou152efa22010-05-16 18:19:27 +000036CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000037BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038ONLYCERT = data_file("ssl_cert.pem")
39ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_ONLYCERT = os.fsencode(ONLYCERT)
41BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020042CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
43ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
44KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Christian Heimesefff7062013-11-21 03:35:02 +010047CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
48CAFILE_CACERT = data_file("capath", "5ed36f99.0")
49
Antoine Pitrou152efa22010-05-16 18:19:27 +000050
Christian Heimes22587792013-11-21 23:56:13 +010051# empty CRL
52CRLFILE = data_file("revocation.crl")
53
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010054# Two keys and certs signed by the same CA (for SNI tests)
55SIGNED_CERTFILE = data_file("keycert3.pem")
56SIGNED_CERTFILE2 = data_file("keycert4.pem")
57SIGNING_CA = data_file("pycacert.pem")
58
Antoine Pitrou152efa22010-05-16 18:19:27 +000059SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
60
61EMPTYCERT = data_file("nullcert.pem")
62BADCERT = data_file("badcert.pem")
63WRONGCERT = data_file("XXXnonexisting.pem")
64BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020065NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020066NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000067
Antoine Pitrou0e576f12011-12-22 10:03:38 +010068DHFILE = data_file("dh512.pem")
69BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000070
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010071
Thomas Woutersed03b412007-08-28 21:37:11 +000072def handle_error(prefix):
73 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000074 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000075 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000076
Antoine Pitroub5218772010-05-21 09:56:06 +000077def can_clear_options():
78 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020079 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000080
81def no_sslv2_implies_sslv3_hello():
82 # 0.9.7h or higher
83 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
84
Christian Heimes2427b502013-11-23 11:24:32 +010085def have_verify_flags():
86 # 0.9.8 or higher
87 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
88
Christian Heimes9424bb42013-06-17 15:32:57 +020089def asn1time(cert_time):
90 # Some versions of OpenSSL ignore seconds, see #18207
91 # 0.9.8.i
92 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
93 fmt = "%b %d %H:%M:%S %Y GMT"
94 dt = datetime.datetime.strptime(cert_time, fmt)
95 dt = dt.replace(second=0)
96 cert_time = dt.strftime(fmt)
97 # %d adds leading zero but ASN1_TIME_print() uses leading space
98 if cert_time[4] == "0":
99 cert_time = cert_time[:4] + " " + cert_time[5:]
100
101 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +0000102
Antoine Pitrou23df4832010-08-04 17:14:06 +0000103# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
104def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +0200105 if hasattr(ssl, 'PROTOCOL_SSLv2'):
106 @functools.wraps(func)
107 def f(*args, **kwargs):
108 try:
109 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
110 except ssl.SSLError:
111 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
112 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
113 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
114 return func(*args, **kwargs)
115 return f
116 else:
117 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +0000118
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100119needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
120
Antoine Pitrou23df4832010-08-04 17:14:06 +0000121
Antoine Pitrou152efa22010-05-16 18:19:27 +0000122class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000123
Antoine Pitrou480a1242010-04-28 21:37:09 +0000124 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000125 ssl.CERT_NONE
126 ssl.CERT_OPTIONAL
127 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100128 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100129 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100130 if ssl.HAS_ECDH:
131 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100132 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
133 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000134 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100135 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000136
Antoine Pitrou480a1242010-04-28 21:37:09 +0000137 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000139 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000140 sys.stdout.write("\n RAND_status is %d (%s)\n"
141 % (v, (v and "sufficient randomness") or
142 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200143
144 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
145 self.assertEqual(len(data), 16)
146 self.assertEqual(is_cryptographic, v == 1)
147 if v:
148 data = ssl.RAND_bytes(16)
149 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200150 else:
151 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200152
Victor Stinner1e81a392013-12-19 16:47:04 +0100153 # negative num is invalid
154 self.assertRaises(ValueError, ssl.RAND_bytes, -5)
155 self.assertRaises(ValueError, ssl.RAND_pseudo_bytes, -5)
156
Victor Stinnerfcfed192015-01-06 13:54:58 +0100157 if hasattr(ssl, 'RAND_egd'):
158 self.assertRaises(TypeError, ssl.RAND_egd, 1)
159 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000160 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000161
Christian Heimesf77b4b22013-08-21 13:26:05 +0200162 @unittest.skipUnless(os.name == 'posix', 'requires posix')
163 def test_random_fork(self):
164 status = ssl.RAND_status()
165 if not status:
166 self.fail("OpenSSL's PRNG has insufficient randomness")
167
168 rfd, wfd = os.pipe()
169 pid = os.fork()
170 if pid == 0:
171 try:
172 os.close(rfd)
173 child_random = ssl.RAND_pseudo_bytes(16)[0]
174 self.assertEqual(len(child_random), 16)
175 os.write(wfd, child_random)
176 os.close(wfd)
177 except BaseException:
178 os._exit(1)
179 else:
180 os._exit(0)
181 else:
182 os.close(wfd)
183 self.addCleanup(os.close, rfd)
184 _, status = os.waitpid(pid, 0)
185 self.assertEqual(status, 0)
186
187 child_random = os.read(rfd, 16)
188 self.assertEqual(len(child_random), 16)
189 parent_random = ssl.RAND_pseudo_bytes(16)[0]
190 self.assertEqual(len(parent_random), 16)
191
192 self.assertNotEqual(child_random, parent_random)
193
Antoine Pitrou480a1242010-04-28 21:37:09 +0000194 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000195 # note that this uses an 'unofficial' function in _ssl.c,
196 # provided solely for this test, to exercise the certificate
197 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000198 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000199 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000200 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200201 self.assertEqual(p['issuer'],
202 ((('countryName', 'XY'),),
203 (('localityName', 'Castle Anthrax'),),
204 (('organizationName', 'Python Software Foundation'),),
205 (('commonName', 'localhost'),))
206 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100207 # Note the next three asserts will fail if the keys are regenerated
Christian Heimes9424bb42013-06-17 15:32:57 +0200208 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
209 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200210 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
211 self.assertEqual(p['subject'],
212 ((('countryName', 'XY'),),
213 (('localityName', 'Castle Anthrax'),),
214 (('organizationName', 'Python Software Foundation'),),
215 (('commonName', 'localhost'),))
216 )
217 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
218 # Issue #13034: the subjectAltName in some certificates
219 # (notably projects.developer.nokia.com:443) wasn't parsed
220 p = ssl._ssl._test_decode_cert(NOKIACERT)
221 if support.verbose:
222 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
223 self.assertEqual(p['subjectAltName'],
224 (('DNS', 'projects.developer.nokia.com'),
225 ('DNS', 'projects.forum.nokia.com'))
226 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100227 # extra OCSP and AIA fields
228 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
229 self.assertEqual(p['caIssuers'],
230 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
231 self.assertEqual(p['crlDistributionPoints'],
232 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000233
Christian Heimes824f7f32013-08-17 00:54:47 +0200234 def test_parse_cert_CVE_2013_4238(self):
235 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
236 if support.verbose:
237 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
238 subject = ((('countryName', 'US'),),
239 (('stateOrProvinceName', 'Oregon'),),
240 (('localityName', 'Beaverton'),),
241 (('organizationName', 'Python Software Foundation'),),
242 (('organizationalUnitName', 'Python Core Development'),),
243 (('commonName', 'null.python.org\x00example.org'),),
244 (('emailAddress', 'python-dev@python.org'),))
245 self.assertEqual(p['subject'], subject)
246 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200247 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
248 san = (('DNS', 'altnull.python.org\x00example.com'),
249 ('email', 'null@python.org\x00user@example.org'),
250 ('URI', 'http://null.python.org\x00http://example.org'),
251 ('IP Address', '192.0.2.1'),
252 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
253 else:
254 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
255 san = (('DNS', 'altnull.python.org\x00example.com'),
256 ('email', 'null@python.org\x00user@example.org'),
257 ('URI', 'http://null.python.org\x00http://example.org'),
258 ('IP Address', '192.0.2.1'),
259 ('IP Address', '<invalid>'))
260
261 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200262
Antoine Pitrou480a1242010-04-28 21:37:09 +0000263 def test_DER_to_PEM(self):
264 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
265 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000266 d1 = ssl.PEM_cert_to_DER_cert(pem)
267 p2 = ssl.DER_cert_to_PEM_cert(d1)
268 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000269 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000270 if not p2.startswith(ssl.PEM_HEADER + '\n'):
271 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
272 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
273 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000274
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000275 def test_openssl_version(self):
276 n = ssl.OPENSSL_VERSION_NUMBER
277 t = ssl.OPENSSL_VERSION_INFO
278 s = ssl.OPENSSL_VERSION
279 self.assertIsInstance(n, int)
280 self.assertIsInstance(t, tuple)
281 self.assertIsInstance(s, str)
282 # Some sanity checks follow
283 # >= 0.9
284 self.assertGreaterEqual(n, 0x900000)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400285 # < 3.0
286 self.assertLess(n, 0x30000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000287 major, minor, fix, patch, status = t
288 self.assertGreaterEqual(major, 0)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400289 self.assertLess(major, 3)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000290 self.assertGreaterEqual(minor, 0)
291 self.assertLess(minor, 256)
292 self.assertGreaterEqual(fix, 0)
293 self.assertLess(fix, 256)
294 self.assertGreaterEqual(patch, 0)
295 self.assertLessEqual(patch, 26)
296 self.assertGreaterEqual(status, 0)
297 self.assertLessEqual(status, 15)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400298 # Version string as returned by {Open,Libre}SSL, the format might change
299 if "LibreSSL" in s:
300 self.assertTrue(s.startswith("LibreSSL {:d}.{:d}".format(major, minor)),
301 (s, t))
302 else:
303 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
304 (s, t))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000305
Antoine Pitrou9d543662010-04-23 23:10:32 +0000306 @support.cpython_only
307 def test_refcycle(self):
308 # Issue #7943: an SSL object doesn't create reference cycles with
309 # itself.
310 s = socket.socket(socket.AF_INET)
311 ss = ssl.wrap_socket(s)
312 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100313 with support.check_warnings(("", ResourceWarning)):
314 del ss
315 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000316
Antoine Pitroua468adc2010-09-14 14:43:44 +0000317 def test_wrapped_unconnected(self):
318 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200319 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000320 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100321 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100322 self.assertRaises(OSError, ss.recv, 1)
323 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
324 self.assertRaises(OSError, ss.recvfrom, 1)
325 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
326 self.assertRaises(OSError, ss.send, b'x')
327 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000328
Antoine Pitrou40f08742010-04-24 22:04:40 +0000329 def test_timeout(self):
330 # Issue #8524: when creating an SSL socket, the timeout of the
331 # original socket should be retained.
332 for timeout in (None, 0.0, 5.0):
333 s = socket.socket(socket.AF_INET)
334 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100335 with ssl.wrap_socket(s) as ss:
336 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000337
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000338 def test_errors(self):
339 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000340 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000341 "certfile must be specified",
342 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000343 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000344 "certfile must be specified for server-side operations",
345 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000346 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000347 "certfile must be specified for server-side operations",
348 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100349 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
350 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
351 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200352 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000353 with socket.socket() as sock:
354 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000355 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200356 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000357 with socket.socket() as sock:
358 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000359 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200360 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000361 with socket.socket() as sock:
362 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000363 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000364
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000365 def test_match_hostname(self):
366 def ok(cert, hostname):
367 ssl.match_hostname(cert, hostname)
368 def fail(cert, hostname):
369 self.assertRaises(ssl.CertificateError,
370 ssl.match_hostname, cert, hostname)
371
372 cert = {'subject': ((('commonName', 'example.com'),),)}
373 ok(cert, 'example.com')
374 ok(cert, 'ExAmple.cOm')
375 fail(cert, 'www.example.com')
376 fail(cert, '.example.com')
377 fail(cert, 'example.org')
378 fail(cert, 'exampleXcom')
379
380 cert = {'subject': ((('commonName', '*.a.com'),),)}
381 ok(cert, 'foo.a.com')
382 fail(cert, 'bar.foo.a.com')
383 fail(cert, 'a.com')
384 fail(cert, 'Xa.com')
385 fail(cert, '.a.com')
386
Georg Brandl72c98d32013-10-27 07:16:53 +0100387 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000388 cert = {'subject': ((('commonName', 'f*.com'),),)}
389 ok(cert, 'foo.com')
390 ok(cert, 'f.com')
391 fail(cert, 'bar.com')
392 fail(cert, 'foo.a.com')
393 fail(cert, 'bar.foo.com')
394
Christian Heimes824f7f32013-08-17 00:54:47 +0200395 # NULL bytes are bad, CVE-2013-4073
396 cert = {'subject': ((('commonName',
397 'null.python.org\x00example.org'),),)}
398 ok(cert, 'null.python.org\x00example.org') # or raise an error?
399 fail(cert, 'example.org')
400 fail(cert, 'null.python.org')
401
Georg Brandl72c98d32013-10-27 07:16:53 +0100402 # error cases with wildcards
403 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
404 fail(cert, 'bar.foo.a.com')
405 fail(cert, 'a.com')
406 fail(cert, 'Xa.com')
407 fail(cert, '.a.com')
408
409 cert = {'subject': ((('commonName', 'a.*.com'),),)}
410 fail(cert, 'a.foo.com')
411 fail(cert, 'a..com')
412 fail(cert, 'a.com')
413
414 # wildcard doesn't match IDNA prefix 'xn--'
415 idna = 'püthon.python.org'.encode("idna").decode("ascii")
416 cert = {'subject': ((('commonName', idna),),)}
417 ok(cert, idna)
418 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
419 fail(cert, idna)
420 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
421 fail(cert, idna)
422
423 # wildcard in first fragment and IDNA A-labels in sequent fragments
424 # are supported.
425 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
426 cert = {'subject': ((('commonName', idna),),)}
427 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
428 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
429 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
430 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
431
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000432 # Slightly fake real-world example
433 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
434 'subject': ((('commonName', 'linuxfrz.org'),),),
435 'subjectAltName': (('DNS', 'linuxfr.org'),
436 ('DNS', 'linuxfr.com'),
437 ('othername', '<unsupported>'))}
438 ok(cert, 'linuxfr.org')
439 ok(cert, 'linuxfr.com')
440 # Not a "DNS" entry
441 fail(cert, '<unsupported>')
442 # When there is a subjectAltName, commonName isn't used
443 fail(cert, 'linuxfrz.org')
444
445 # A pristine real-world example
446 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
447 'subject': ((('countryName', 'US'),),
448 (('stateOrProvinceName', 'California'),),
449 (('localityName', 'Mountain View'),),
450 (('organizationName', 'Google Inc'),),
451 (('commonName', 'mail.google.com'),))}
452 ok(cert, 'mail.google.com')
453 fail(cert, 'gmail.com')
454 # Only commonName is considered
455 fail(cert, 'California')
456
457 # Neither commonName nor subjectAltName
458 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
459 'subject': ((('countryName', 'US'),),
460 (('stateOrProvinceName', 'California'),),
461 (('localityName', 'Mountain View'),),
462 (('organizationName', 'Google Inc'),))}
463 fail(cert, 'mail.google.com')
464
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200465 # No DNS entry in subjectAltName but a commonName
466 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
467 'subject': ((('countryName', 'US'),),
468 (('stateOrProvinceName', 'California'),),
469 (('localityName', 'Mountain View'),),
470 (('commonName', 'mail.google.com'),)),
471 'subjectAltName': (('othername', 'blabla'), )}
472 ok(cert, 'mail.google.com')
473
474 # No DNS entry subjectAltName and no commonName
475 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
476 'subject': ((('countryName', 'US'),),
477 (('stateOrProvinceName', 'California'),),
478 (('localityName', 'Mountain View'),),
479 (('organizationName', 'Google Inc'),)),
480 'subjectAltName': (('othername', 'blabla'),)}
481 fail(cert, 'google.com')
482
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000483 # Empty cert / no cert
484 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
485 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
486
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200487 # Issue #17980: avoid denials of service by refusing more than one
488 # wildcard per fragment.
489 cert = {'subject': ((('commonName', 'a*b.com'),),)}
490 ok(cert, 'axxb.com')
491 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100492 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200493 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
494 with self.assertRaises(ssl.CertificateError) as cm:
495 ssl.match_hostname(cert, 'axxbxxc.com')
496 self.assertIn("too many wildcards", str(cm.exception))
497
Antoine Pitroud5323212010-10-22 18:19:07 +0000498 def test_server_side(self):
499 # server_hostname doesn't work for server sockets
500 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000501 with socket.socket() as sock:
502 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
503 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000504
Antoine Pitroud6494802011-07-21 01:11:30 +0200505 def test_unknown_channel_binding(self):
506 # should raise ValueError for unknown type
507 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100508 with ssl.wrap_socket(s) as ss:
509 with self.assertRaises(ValueError):
510 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200511
512 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
513 "'tls-unique' channel binding not available")
514 def test_tls_unique_channel_binding(self):
515 # unconnected should return None for known type
516 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100517 with ssl.wrap_socket(s) as ss:
518 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200519 # the same for server-side
520 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100521 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
522 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200523
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600524 def test_dealloc_warn(self):
525 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
526 r = repr(ss)
527 with self.assertWarns(ResourceWarning) as cm:
528 ss = None
529 support.gc_collect()
530 self.assertIn(r, str(cm.warning.args[0]))
531
Christian Heimes6d7ad132013-06-09 18:02:55 +0200532 def test_get_default_verify_paths(self):
533 paths = ssl.get_default_verify_paths()
534 self.assertEqual(len(paths), 6)
535 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
536
537 with support.EnvironmentVarGuard() as env:
538 env["SSL_CERT_DIR"] = CAPATH
539 env["SSL_CERT_FILE"] = CERTFILE
540 paths = ssl.get_default_verify_paths()
541 self.assertEqual(paths.cafile, CERTFILE)
542 self.assertEqual(paths.capath, CAPATH)
543
Christian Heimes44109d72013-11-22 01:51:30 +0100544 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
545 def test_enum_certificates(self):
546 self.assertTrue(ssl.enum_certificates("CA"))
547 self.assertTrue(ssl.enum_certificates("ROOT"))
548
549 self.assertRaises(TypeError, ssl.enum_certificates)
550 self.assertRaises(WindowsError, ssl.enum_certificates, "")
551
Christian Heimesc2d65e12013-11-22 16:13:55 +0100552 trust_oids = set()
553 for storename in ("CA", "ROOT"):
554 store = ssl.enum_certificates(storename)
555 self.assertIsInstance(store, list)
556 for element in store:
557 self.assertIsInstance(element, tuple)
558 self.assertEqual(len(element), 3)
559 cert, enc, trust = element
560 self.assertIsInstance(cert, bytes)
561 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
562 self.assertIsInstance(trust, (set, bool))
563 if isinstance(trust, set):
564 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100565
566 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100567 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200568
Christian Heimes46bebee2013-06-09 19:03:31 +0200569 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100570 def test_enum_crls(self):
571 self.assertTrue(ssl.enum_crls("CA"))
572 self.assertRaises(TypeError, ssl.enum_crls)
573 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200574
Christian Heimes44109d72013-11-22 01:51:30 +0100575 crls = ssl.enum_crls("CA")
576 self.assertIsInstance(crls, list)
577 for element in crls:
578 self.assertIsInstance(element, tuple)
579 self.assertEqual(len(element), 2)
580 self.assertIsInstance(element[0], bytes)
581 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200582
Christian Heimes46bebee2013-06-09 19:03:31 +0200583
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100584 def test_asn1object(self):
585 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
586 '1.3.6.1.5.5.7.3.1')
587
588 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
589 self.assertEqual(val, expected)
590 self.assertEqual(val.nid, 129)
591 self.assertEqual(val.shortname, 'serverAuth')
592 self.assertEqual(val.longname, 'TLS Web Server Authentication')
593 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
594 self.assertIsInstance(val, ssl._ASN1Object)
595 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
596
597 val = ssl._ASN1Object.fromnid(129)
598 self.assertEqual(val, expected)
599 self.assertIsInstance(val, ssl._ASN1Object)
600 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100601 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
602 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100603 for i in range(1000):
604 try:
605 obj = ssl._ASN1Object.fromnid(i)
606 except ValueError:
607 pass
608 else:
609 self.assertIsInstance(obj.nid, int)
610 self.assertIsInstance(obj.shortname, str)
611 self.assertIsInstance(obj.longname, str)
612 self.assertIsInstance(obj.oid, (str, type(None)))
613
614 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
615 self.assertEqual(val, expected)
616 self.assertIsInstance(val, ssl._ASN1Object)
617 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
618 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
619 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100620 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
621 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100622
Christian Heimes72d28502013-11-23 13:56:58 +0100623 def test_purpose_enum(self):
624 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
625 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
626 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
627 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
628 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
629 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
630 '1.3.6.1.5.5.7.3.1')
631
632 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
633 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
634 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
635 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
636 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
637 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
638 '1.3.6.1.5.5.7.3.2')
639
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100640 def test_unsupported_dtls(self):
641 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
642 self.addCleanup(s.close)
643 with self.assertRaises(NotImplementedError) as cx:
644 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
645 self.assertEqual(str(cx.exception), "only stream sockets are supported")
646 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
647 with self.assertRaises(NotImplementedError) as cx:
648 ctx.wrap_socket(s)
649 self.assertEqual(str(cx.exception), "only stream sockets are supported")
650
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100651
Antoine Pitrou152efa22010-05-16 18:19:27 +0000652class ContextTests(unittest.TestCase):
653
Antoine Pitrou23df4832010-08-04 17:14:06 +0000654 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000655 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100656 for protocol in PROTOCOLS:
657 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000658 self.assertRaises(TypeError, ssl.SSLContext)
659 self.assertRaises(ValueError, ssl.SSLContext, -1)
660 self.assertRaises(ValueError, ssl.SSLContext, 42)
661
Antoine Pitrou23df4832010-08-04 17:14:06 +0000662 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000663 def test_protocol(self):
664 for proto in PROTOCOLS:
665 ctx = ssl.SSLContext(proto)
666 self.assertEqual(ctx.protocol, proto)
667
668 def test_ciphers(self):
669 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
670 ctx.set_ciphers("ALL")
671 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000672 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000673 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000674
Antoine Pitrou23df4832010-08-04 17:14:06 +0000675 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000676 def test_options(self):
677 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +0100678 # OP_ALL | OP_NO_SSLv2 is the default value
Antoine Pitroub5218772010-05-21 09:56:06 +0000679 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
680 ctx.options)
681 ctx.options |= ssl.OP_NO_SSLv3
682 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
683 ctx.options)
684 if can_clear_options():
685 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
686 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
687 ctx.options)
688 ctx.options = 0
689 self.assertEqual(0, ctx.options)
690 else:
691 with self.assertRaises(ValueError):
692 ctx.options = 0
693
Christian Heimes22587792013-11-21 23:56:13 +0100694 def test_verify_mode(self):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000695 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
696 # Default value
697 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
698 ctx.verify_mode = ssl.CERT_OPTIONAL
699 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
700 ctx.verify_mode = ssl.CERT_REQUIRED
701 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
702 ctx.verify_mode = ssl.CERT_NONE
703 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
704 with self.assertRaises(TypeError):
705 ctx.verify_mode = None
706 with self.assertRaises(ValueError):
707 ctx.verify_mode = 42
708
Christian Heimes2427b502013-11-23 11:24:32 +0100709 @unittest.skipUnless(have_verify_flags(),
710 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +0100711 def test_verify_flags(self):
712 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
713 # default value by OpenSSL
714 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
715 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
716 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
717 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
718 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
719 ctx.verify_flags = ssl.VERIFY_DEFAULT
720 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
721 # supports any value
722 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
723 self.assertEqual(ctx.verify_flags,
724 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
725 with self.assertRaises(TypeError):
726 ctx.verify_flags = None
727
Antoine Pitrou152efa22010-05-16 18:19:27 +0000728 def test_load_cert_chain(self):
729 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
730 # Combined key and cert in a single file
Benjamin Peterson1ea070e2014-11-03 21:05:01 -0500731 ctx.load_cert_chain(CERTFILE, keyfile=None)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000732 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
733 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200734 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000735 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000736 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000737 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000738 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000739 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000740 ctx.load_cert_chain(EMPTYCERT)
741 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000742 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000743 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
744 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
745 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000746 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000747 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000748 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000749 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000750 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000751 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
752 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000753 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000754 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000755 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200756 # Password protected key and cert
757 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
758 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
759 ctx.load_cert_chain(CERTFILE_PROTECTED,
760 password=bytearray(KEY_PASSWORD.encode()))
761 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
762 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
763 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
764 bytearray(KEY_PASSWORD.encode()))
765 with self.assertRaisesRegex(TypeError, "should be a string"):
766 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
767 with self.assertRaises(ssl.SSLError):
768 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
769 with self.assertRaisesRegex(ValueError, "cannot be longer"):
770 # openssl has a fixed limit on the password buffer.
771 # PEM_BUFSIZE is generally set to 1kb.
772 # Return a string larger than this.
773 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
774 # Password callback
775 def getpass_unicode():
776 return KEY_PASSWORD
777 def getpass_bytes():
778 return KEY_PASSWORD.encode()
779 def getpass_bytearray():
780 return bytearray(KEY_PASSWORD.encode())
781 def getpass_badpass():
782 return "badpass"
783 def getpass_huge():
784 return b'a' * (1024 * 1024)
785 def getpass_bad_type():
786 return 9
787 def getpass_exception():
788 raise Exception('getpass error')
789 class GetPassCallable:
790 def __call__(self):
791 return KEY_PASSWORD
792 def getpass(self):
793 return KEY_PASSWORD
794 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
795 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
796 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
797 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
798 ctx.load_cert_chain(CERTFILE_PROTECTED,
799 password=GetPassCallable().getpass)
800 with self.assertRaises(ssl.SSLError):
801 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
802 with self.assertRaisesRegex(ValueError, "cannot be longer"):
803 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
804 with self.assertRaisesRegex(TypeError, "must return a string"):
805 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
806 with self.assertRaisesRegex(Exception, "getpass error"):
807 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
808 # Make sure the password function isn't called if it isn't needed
809 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000810
811 def test_load_verify_locations(self):
812 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
813 ctx.load_verify_locations(CERTFILE)
814 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
815 ctx.load_verify_locations(BYTES_CERTFILE)
816 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
817 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +0100818 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200819 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000820 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000821 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000822 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000823 ctx.load_verify_locations(BADCERT)
824 ctx.load_verify_locations(CERTFILE, CAPATH)
825 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
826
Victor Stinner80f75e62011-01-29 11:31:20 +0000827 # Issue #10989: crash if the second argument type is invalid
828 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
829
Christian Heimesefff7062013-11-21 03:35:02 +0100830 def test_load_verify_cadata(self):
831 # test cadata
832 with open(CAFILE_CACERT) as f:
833 cacert_pem = f.read()
834 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
835 with open(CAFILE_NEURONIO) as f:
836 neuronio_pem = f.read()
837 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
838
839 # test PEM
840 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
841 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
842 ctx.load_verify_locations(cadata=cacert_pem)
843 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
844 ctx.load_verify_locations(cadata=neuronio_pem)
845 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
846 # cert already in hash table
847 ctx.load_verify_locations(cadata=neuronio_pem)
848 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
849
850 # combined
851 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
852 combined = "\n".join((cacert_pem, neuronio_pem))
853 ctx.load_verify_locations(cadata=combined)
854 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
855
856 # with junk around the certs
857 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
858 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
859 neuronio_pem, "tail"]
860 ctx.load_verify_locations(cadata="\n".join(combined))
861 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
862
863 # test DER
864 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
865 ctx.load_verify_locations(cadata=cacert_der)
866 ctx.load_verify_locations(cadata=neuronio_der)
867 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
868 # cert already in hash table
869 ctx.load_verify_locations(cadata=cacert_der)
870 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
871
872 # combined
873 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
874 combined = b"".join((cacert_der, neuronio_der))
875 ctx.load_verify_locations(cadata=combined)
876 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
877
878 # error cases
879 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
880 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
881
882 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
883 ctx.load_verify_locations(cadata="broken")
884 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
885 ctx.load_verify_locations(cadata=b"broken")
886
887
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100888 def test_load_dh_params(self):
889 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
890 ctx.load_dh_params(DHFILE)
891 if os.name != 'nt':
892 ctx.load_dh_params(BYTES_DHFILE)
893 self.assertRaises(TypeError, ctx.load_dh_params)
894 self.assertRaises(TypeError, ctx.load_dh_params, None)
895 with self.assertRaises(FileNotFoundError) as cm:
896 ctx.load_dh_params(WRONGCERT)
897 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200898 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100899 ctx.load_dh_params(CERTFILE)
900
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000901 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000902 def test_session_stats(self):
903 for proto in PROTOCOLS:
904 ctx = ssl.SSLContext(proto)
905 self.assertEqual(ctx.session_stats(), {
906 'number': 0,
907 'connect': 0,
908 'connect_good': 0,
909 'connect_renegotiate': 0,
910 'accept': 0,
911 'accept_good': 0,
912 'accept_renegotiate': 0,
913 'hits': 0,
914 'misses': 0,
915 'timeouts': 0,
916 'cache_full': 0,
917 })
918
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000919 def test_set_default_verify_paths(self):
920 # There's not much we can do to test that it acts as expected,
921 # so just check it doesn't crash or raise an exception.
922 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
923 ctx.set_default_verify_paths()
924
Antoine Pitrou501da612011-12-21 09:27:41 +0100925 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100926 def test_set_ecdh_curve(self):
927 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
928 ctx.set_ecdh_curve("prime256v1")
929 ctx.set_ecdh_curve(b"prime256v1")
930 self.assertRaises(TypeError, ctx.set_ecdh_curve)
931 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
932 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
933 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
934
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100935 @needs_sni
936 def test_sni_callback(self):
937 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
938
939 # set_servername_callback expects a callable, or None
940 self.assertRaises(TypeError, ctx.set_servername_callback)
941 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
942 self.assertRaises(TypeError, ctx.set_servername_callback, "")
943 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
944
945 def dummycallback(sock, servername, ctx):
946 pass
947 ctx.set_servername_callback(None)
948 ctx.set_servername_callback(dummycallback)
949
950 @needs_sni
951 def test_sni_callback_refcycle(self):
952 # Reference cycles through the servername callback are detected
953 # and cleared.
954 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
955 def dummycallback(sock, servername, ctx, cycle=ctx):
956 pass
957 ctx.set_servername_callback(dummycallback)
958 wr = weakref.ref(ctx)
959 del ctx, dummycallback
960 gc.collect()
961 self.assertIs(wr(), None)
962
Christian Heimes9a5395a2013-06-17 15:44:12 +0200963 def test_cert_store_stats(self):
964 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
965 self.assertEqual(ctx.cert_store_stats(),
966 {'x509_ca': 0, 'crl': 0, 'x509': 0})
967 ctx.load_cert_chain(CERTFILE)
968 self.assertEqual(ctx.cert_store_stats(),
969 {'x509_ca': 0, 'crl': 0, 'x509': 0})
970 ctx.load_verify_locations(CERTFILE)
971 self.assertEqual(ctx.cert_store_stats(),
972 {'x509_ca': 0, 'crl': 0, 'x509': 1})
973 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
974 self.assertEqual(ctx.cert_store_stats(),
975 {'x509_ca': 1, 'crl': 0, 'x509': 2})
976
977 def test_get_ca_certs(self):
978 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
979 self.assertEqual(ctx.get_ca_certs(), [])
980 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
981 ctx.load_verify_locations(CERTFILE)
982 self.assertEqual(ctx.get_ca_certs(), [])
983 # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
984 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
985 self.assertEqual(ctx.get_ca_certs(),
986 [{'issuer': ((('organizationName', 'Root CA'),),
987 (('organizationalUnitName', 'http://www.cacert.org'),),
988 (('commonName', 'CA Cert Signing Authority'),),
989 (('emailAddress', 'support@cacert.org'),)),
990 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
991 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
992 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100993 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +0200994 'subject': ((('organizationName', 'Root CA'),),
995 (('organizationalUnitName', 'http://www.cacert.org'),),
996 (('commonName', 'CA Cert Signing Authority'),),
997 (('emailAddress', 'support@cacert.org'),)),
998 'version': 3}])
999
1000 with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
1001 pem = f.read()
1002 der = ssl.PEM_cert_to_DER_cert(pem)
1003 self.assertEqual(ctx.get_ca_certs(True), [der])
1004
Christian Heimes72d28502013-11-23 13:56:58 +01001005 def test_load_default_certs(self):
1006 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1007 ctx.load_default_certs()
1008
1009 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1010 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1011 ctx.load_default_certs()
1012
1013 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1014 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1015
1016 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1017 self.assertRaises(TypeError, ctx.load_default_certs, None)
1018 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1019
Benjamin Peterson91244e02014-10-03 18:17:15 -04001020 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001021 def test_load_default_certs_env(self):
1022 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1023 with support.EnvironmentVarGuard() as env:
1024 env["SSL_CERT_DIR"] = CAPATH
1025 env["SSL_CERT_FILE"] = CERTFILE
1026 ctx.load_default_certs()
1027 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1028
Benjamin Peterson91244e02014-10-03 18:17:15 -04001029 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1030 def test_load_default_certs_env_windows(self):
1031 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1032 ctx.load_default_certs()
1033 stats = ctx.cert_store_stats()
1034
1035 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1036 with support.EnvironmentVarGuard() as env:
1037 env["SSL_CERT_DIR"] = CAPATH
1038 env["SSL_CERT_FILE"] = CERTFILE
1039 ctx.load_default_certs()
1040 stats["x509"] += 1
1041 self.assertEqual(ctx.cert_store_stats(), stats)
1042
Christian Heimes4c05b472013-11-23 15:58:30 +01001043 def test_create_default_context(self):
1044 ctx = ssl.create_default_context()
Donald Stufft6a2ba942014-03-23 19:05:28 -04001045 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001046 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001047 self.assertTrue(ctx.check_hostname)
Christian Heimes4c05b472013-11-23 15:58:30 +01001048 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001049 self.assertEqual(
1050 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1051 getattr(ssl, "OP_NO_COMPRESSION", 0),
1052 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001053
1054 with open(SIGNING_CA) as f:
1055 cadata = f.read()
1056 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1057 cadata=cadata)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001058 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001059 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1060 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001061 self.assertEqual(
1062 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1063 getattr(ssl, "OP_NO_COMPRESSION", 0),
1064 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001065
1066 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001067 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001068 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1069 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001070 self.assertEqual(
1071 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1072 getattr(ssl, "OP_NO_COMPRESSION", 0),
1073 )
1074 self.assertEqual(
1075 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1076 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1077 )
1078 self.assertEqual(
1079 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1080 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1081 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001082
Christian Heimes67986f92013-11-23 22:43:47 +01001083 def test__create_stdlib_context(self):
1084 ctx = ssl._create_stdlib_context()
1085 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1086 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001087 self.assertFalse(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001088 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1089
1090 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1091 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1092 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1093 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1094
1095 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001096 cert_reqs=ssl.CERT_REQUIRED,
1097 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001098 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1099 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001100 self.assertTrue(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001101 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1102
1103 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1104 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1105 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1106 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Christian Heimes4c05b472013-11-23 15:58:30 +01001107
Christian Heimes1aa9a752013-12-02 02:41:19 +01001108 def test_check_hostname(self):
1109 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1110 self.assertFalse(ctx.check_hostname)
1111
1112 # Requires CERT_REQUIRED or CERT_OPTIONAL
1113 with self.assertRaises(ValueError):
1114 ctx.check_hostname = True
1115 ctx.verify_mode = ssl.CERT_REQUIRED
1116 self.assertFalse(ctx.check_hostname)
1117 ctx.check_hostname = True
1118 self.assertTrue(ctx.check_hostname)
1119
1120 ctx.verify_mode = ssl.CERT_OPTIONAL
1121 ctx.check_hostname = True
1122 self.assertTrue(ctx.check_hostname)
1123
1124 # Cannot set CERT_NONE with check_hostname enabled
1125 with self.assertRaises(ValueError):
1126 ctx.verify_mode = ssl.CERT_NONE
1127 ctx.check_hostname = False
1128 self.assertFalse(ctx.check_hostname)
1129
Antoine Pitrou152efa22010-05-16 18:19:27 +00001130
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001131class SSLErrorTests(unittest.TestCase):
1132
1133 def test_str(self):
1134 # The str() of a SSLError doesn't include the errno
1135 e = ssl.SSLError(1, "foo")
1136 self.assertEqual(str(e), "foo")
1137 self.assertEqual(e.errno, 1)
1138 # Same for a subclass
1139 e = ssl.SSLZeroReturnError(1, "foo")
1140 self.assertEqual(str(e), "foo")
1141 self.assertEqual(e.errno, 1)
1142
1143 def test_lib_reason(self):
1144 # Test the library and reason attributes
1145 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1146 with self.assertRaises(ssl.SSLError) as cm:
1147 ctx.load_dh_params(CERTFILE)
1148 self.assertEqual(cm.exception.library, 'PEM')
1149 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1150 s = str(cm.exception)
1151 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1152
1153 def test_subclass(self):
1154 # Check that the appropriate SSLError subclass is raised
1155 # (this only tests one of them)
1156 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1157 with socket.socket() as s:
1158 s.bind(("127.0.0.1", 0))
1159 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001160 c = socket.socket()
1161 c.connect(s.getsockname())
1162 c.setblocking(False)
1163 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001164 with self.assertRaises(ssl.SSLWantReadError) as cm:
1165 c.do_handshake()
1166 s = str(cm.exception)
1167 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1168 # For compatibility
1169 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1170
1171
Bill Janssen6e027db2007-11-15 22:23:56 +00001172class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001173
Antoine Pitrou480a1242010-04-28 21:37:09 +00001174 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001175 with support.transient_internet("svn.python.org"):
1176 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1177 cert_reqs=ssl.CERT_NONE)
1178 try:
1179 s.connect(("svn.python.org", 443))
1180 self.assertEqual({}, s.getpeercert())
1181 finally:
1182 s.close()
1183
1184 # this should fail because we have no verification certs
1185 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1186 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001187 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1188 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001189 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001190
Antoine Pitrou350c7222010-09-09 13:31:46 +00001191 # this should succeed because we specify the root cert
1192 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1193 cert_reqs=ssl.CERT_REQUIRED,
1194 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1195 try:
1196 s.connect(("svn.python.org", 443))
1197 self.assertTrue(s.getpeercert())
1198 finally:
1199 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001200
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001201 def test_connect_ex(self):
1202 # Issue #11326: check connect_ex() implementation
1203 with support.transient_internet("svn.python.org"):
1204 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1205 cert_reqs=ssl.CERT_REQUIRED,
1206 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1207 try:
1208 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
1209 self.assertTrue(s.getpeercert())
1210 finally:
1211 s.close()
1212
1213 def test_non_blocking_connect_ex(self):
1214 # Issue #11326: non-blocking connect_ex() should allow handshake
1215 # to proceed after the socket gets ready.
1216 with support.transient_internet("svn.python.org"):
1217 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1218 cert_reqs=ssl.CERT_REQUIRED,
1219 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1220 do_handshake_on_connect=False)
1221 try:
1222 s.setblocking(False)
1223 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +00001224 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1225 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001226 # Wait for connect to finish
1227 select.select([], [s], [], 5.0)
1228 # Non-blocking handshake
1229 while True:
1230 try:
1231 s.do_handshake()
1232 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001233 except ssl.SSLWantReadError:
1234 select.select([s], [], [], 5.0)
1235 except ssl.SSLWantWriteError:
1236 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001237 # SSL established
1238 self.assertTrue(s.getpeercert())
1239 finally:
1240 s.close()
1241
Antoine Pitroub4410db2011-05-18 18:51:06 +02001242 def test_timeout_connect_ex(self):
1243 # Issue #12065: on a timeout, connect_ex() should return the original
1244 # errno (mimicking the behaviour of non-SSL sockets).
1245 with support.transient_internet("svn.python.org"):
1246 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1247 cert_reqs=ssl.CERT_REQUIRED,
1248 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1249 do_handshake_on_connect=False)
1250 try:
1251 s.settimeout(0.0000001)
1252 rc = s.connect_ex(('svn.python.org', 443))
1253 if rc == 0:
1254 self.skipTest("svn.python.org responded too quickly")
1255 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1256 finally:
1257 s.close()
1258
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001259 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +01001260 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001261 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1262 cert_reqs=ssl.CERT_REQUIRED,
1263 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1264 try:
Christian Heimesde570742013-12-16 21:15:44 +01001265 rc = s.connect_ex(("svn.python.org", 444))
1266 # Issue #19919: Windows machines or VMs hosted on Windows
1267 # machines sometimes return EWOULDBLOCK.
1268 self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001269 finally:
1270 s.close()
1271
Antoine Pitrou152efa22010-05-16 18:19:27 +00001272 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001273 with support.transient_internet("svn.python.org"):
1274 # Same as test_connect, but with a separately created context
1275 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1276 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1277 s.connect(("svn.python.org", 443))
1278 try:
1279 self.assertEqual({}, s.getpeercert())
1280 finally:
1281 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +00001282 # Same with a server hostname
1283 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1284 server_hostname="svn.python.org")
Benjamin Peterson7243b572014-11-23 17:04:34 -06001285 s.connect(("svn.python.org", 443))
1286 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001287 # This should fail because we have no verification certs
1288 ctx.verify_mode = ssl.CERT_REQUIRED
1289 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +00001290 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +00001291 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001292 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001293 # This should succeed because we specify the root cert
1294 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
1295 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1296 s.connect(("svn.python.org", 443))
1297 try:
1298 cert = s.getpeercert()
1299 self.assertTrue(cert)
1300 finally:
1301 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001302
1303 def test_connect_capath(self):
1304 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00001305 # NOTE: the subject hashing algorithm has been changed between
1306 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1307 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00001308 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +00001309 with support.transient_internet("svn.python.org"):
1310 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1311 ctx.verify_mode = ssl.CERT_REQUIRED
1312 ctx.load_verify_locations(capath=CAPATH)
1313 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1314 s.connect(("svn.python.org", 443))
1315 try:
1316 cert = s.getpeercert()
1317 self.assertTrue(cert)
1318 finally:
1319 s.close()
1320 # Same with a bytes `capath` argument
1321 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1322 ctx.verify_mode = ssl.CERT_REQUIRED
1323 ctx.load_verify_locations(capath=BYTES_CAPATH)
1324 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1325 s.connect(("svn.python.org", 443))
1326 try:
1327 cert = s.getpeercert()
1328 self.assertTrue(cert)
1329 finally:
1330 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001331
Christian Heimesefff7062013-11-21 03:35:02 +01001332 def test_connect_cadata(self):
1333 with open(CAFILE_CACERT) as f:
1334 pem = f.read()
1335 der = ssl.PEM_cert_to_DER_cert(pem)
1336 with support.transient_internet("svn.python.org"):
1337 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1338 ctx.verify_mode = ssl.CERT_REQUIRED
1339 ctx.load_verify_locations(cadata=pem)
1340 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1341 s.connect(("svn.python.org", 443))
1342 cert = s.getpeercert()
1343 self.assertTrue(cert)
1344
1345 # same with DER
1346 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1347 ctx.verify_mode = ssl.CERT_REQUIRED
1348 ctx.load_verify_locations(cadata=der)
1349 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1350 s.connect(("svn.python.org", 443))
1351 cert = s.getpeercert()
1352 self.assertTrue(cert)
1353
Antoine Pitroue3220242010-04-24 11:13:53 +00001354 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1355 def test_makefile_close(self):
1356 # Issue #5238: creating a file-like object with makefile() shouldn't
1357 # delay closing the underlying "real socket" (here tested with its
1358 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +00001359 with support.transient_internet("svn.python.org"):
1360 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1361 ss.connect(("svn.python.org", 443))
1362 fd = ss.fileno()
1363 f = ss.makefile()
1364 f.close()
1365 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +00001366 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001367 # Closing the SSL socket should close the fd too
1368 ss.close()
1369 gc.collect()
1370 with self.assertRaises(OSError) as e:
1371 os.read(fd, 0)
1372 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001373
Antoine Pitrou480a1242010-04-28 21:37:09 +00001374 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001375 with support.transient_internet("svn.python.org"):
1376 s = socket.socket(socket.AF_INET)
1377 s.connect(("svn.python.org", 443))
1378 s.setblocking(False)
1379 s = ssl.wrap_socket(s,
1380 cert_reqs=ssl.CERT_NONE,
1381 do_handshake_on_connect=False)
1382 count = 0
1383 while True:
1384 try:
1385 count += 1
1386 s.do_handshake()
1387 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001388 except ssl.SSLWantReadError:
1389 select.select([s], [], [])
1390 except ssl.SSLWantWriteError:
1391 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +00001392 s.close()
1393 if support.verbose:
1394 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001395
Antoine Pitrou480a1242010-04-28 21:37:09 +00001396 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +02001397 def _test_get_server_certificate(host, port, cert=None):
1398 with support.transient_internet(host):
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001399 pem = ssl.get_server_certificate((host, port),
1400 ssl.PROTOCOL_SSLv23)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001401 if not pem:
1402 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001403
Antoine Pitrou15399c32011-04-28 19:23:55 +02001404 try:
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001405 pem = ssl.get_server_certificate((host, port),
1406 ssl.PROTOCOL_SSLv23,
1407 ca_certs=CERTFILE)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001408 except ssl.SSLError as x:
1409 #should fail
1410 if support.verbose:
1411 sys.stdout.write("%s\n" % x)
1412 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001413 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1414
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001415 pem = ssl.get_server_certificate((host, port),
1416 ssl.PROTOCOL_SSLv23,
1417 ca_certs=cert)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001418 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001419 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001420 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001421 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001422
Antoine Pitrou15399c32011-04-28 19:23:55 +02001423 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
1424 if support.IPV6_ENABLED:
1425 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001426
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001427 def test_ciphers(self):
1428 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001429 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001430 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1431 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1432 s.connect(remote)
1433 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1434 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1435 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001436 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001437 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001438 with socket.socket(socket.AF_INET) as sock:
1439 s = ssl.wrap_socket(sock,
1440 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1441 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001442
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001443 def test_algorithms(self):
1444 # Issue #8484: all algorithms should be available when verifying a
1445 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001446 # SHA256 was added in OpenSSL 0.9.8
1447 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1448 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001449 # sha256.tbs-internet.com needs SNI to use the correct certificate
1450 if not ssl.HAS_SNI:
1451 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001452 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1453 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001454 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001455 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001456 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1457 ctx.verify_mode = ssl.CERT_REQUIRED
1458 ctx.load_verify_locations(sha256_cert)
1459 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1460 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001461 try:
1462 s.connect(remote)
1463 if support.verbose:
1464 sys.stdout.write("\nCipher with %r is %r\n" %
1465 (remote, s.cipher()))
1466 sys.stdout.write("Certificate is:\n%s\n" %
1467 pprint.pformat(s.getpeercert()))
1468 finally:
1469 s.close()
1470
Christian Heimes9a5395a2013-06-17 15:44:12 +02001471 def test_get_ca_certs_capath(self):
1472 # capath certs are loaded on request
1473 with support.transient_internet("svn.python.org"):
1474 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1475 ctx.verify_mode = ssl.CERT_REQUIRED
1476 ctx.load_verify_locations(capath=CAPATH)
1477 self.assertEqual(ctx.get_ca_certs(), [])
1478 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1479 s.connect(("svn.python.org", 443))
1480 try:
1481 cert = s.getpeercert()
1482 self.assertTrue(cert)
1483 finally:
1484 s.close()
1485 self.assertEqual(len(ctx.get_ca_certs()), 1)
1486
Christian Heimes575596e2013-12-15 21:49:17 +01001487 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01001488 def test_context_setget(self):
1489 # Check that the context of a connected socket can be replaced.
1490 with support.transient_internet("svn.python.org"):
1491 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1492 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1493 s = socket.socket(socket.AF_INET)
1494 with ctx1.wrap_socket(s) as ss:
1495 ss.connect(("svn.python.org", 443))
1496 self.assertIs(ss.context, ctx1)
1497 self.assertIs(ss._sslobj.context, ctx1)
1498 ss.context = ctx2
1499 self.assertIs(ss.context, ctx2)
1500 self.assertIs(ss._sslobj.context, ctx2)
1501
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001502try:
1503 import threading
1504except ImportError:
1505 _have_threads = False
1506else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001507 _have_threads = True
1508
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001509 from test.ssl_servers import make_https_server
1510
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001511 class ThreadedEchoServer(threading.Thread):
1512
1513 class ConnectionHandler(threading.Thread):
1514
1515 """A mildly complicated class, because we want it to work both
1516 with and without the SSL wrapper around the socket connection, so
1517 that we can test the STARTTLS functionality."""
1518
Bill Janssen6e027db2007-11-15 22:23:56 +00001519 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001520 self.server = server
1521 self.running = False
1522 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001523 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001524 self.sock.setblocking(1)
1525 self.sslconn = None
1526 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001527 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001528
Antoine Pitrou480a1242010-04-28 21:37:09 +00001529 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001530 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001531 self.sslconn = self.server.context.wrap_socket(
1532 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001533 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001534 except (ssl.SSLError, ConnectionResetError) as e:
1535 # We treat ConnectionResetError as though it were an
1536 # SSLError - OpenSSL on Ubuntu abruptly closes the
1537 # connection when asked to use an unsupported protocol.
1538 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001539 # XXX Various errors can have happened here, for example
1540 # a mismatching protocol version, an invalid certificate,
1541 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001542 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001543 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001544 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001545 self.running = False
1546 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001547 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001548 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001549 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001550 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001551 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001552 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001553 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1554 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001555 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001556 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1557 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001558 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001559 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001560 sys.stdout.write(" server: selected protocol is now "
1561 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001562 return True
1563
1564 def read(self):
1565 if self.sslconn:
1566 return self.sslconn.read()
1567 else:
1568 return self.sock.recv(1024)
1569
1570 def write(self, bytes):
1571 if self.sslconn:
1572 return self.sslconn.write(bytes)
1573 else:
1574 return self.sock.send(bytes)
1575
1576 def close(self):
1577 if self.sslconn:
1578 self.sslconn.close()
1579 else:
1580 self.sock.close()
1581
Antoine Pitrou480a1242010-04-28 21:37:09 +00001582 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001583 self.running = True
1584 if not self.server.starttls_server:
1585 if not self.wrap_conn():
1586 return
1587 while self.running:
1588 try:
1589 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001590 stripped = msg.strip()
1591 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001592 # eof, so quit this handler
1593 self.running = False
1594 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001595 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001596 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001597 sys.stdout.write(" server: client closed connection\n")
1598 self.close()
1599 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001600 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001601 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001602 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001603 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001604 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001605 if not self.wrap_conn():
1606 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001607 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001608 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001609 if support.verbose and self.server.connectionchatty:
1610 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001611 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001612 self.sock = self.sslconn.unwrap()
1613 self.sslconn = None
1614 if support.verbose and self.server.connectionchatty:
1615 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001616 elif stripped == b'CB tls-unique':
1617 if support.verbose and self.server.connectionchatty:
1618 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1619 data = self.sslconn.get_channel_binding("tls-unique")
1620 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001621 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001622 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001623 self.server.connectionchatty):
1624 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001625 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1626 % (msg, ctype, msg.lower(), ctype))
1627 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001628 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001629 if self.server.chatty:
1630 handle_error("Test server failure:\n")
1631 self.close()
1632 self.running = False
1633 # normally, we'd just stop here, but for the test
1634 # harness, we want to stop the server
1635 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001636
Antoine Pitroub5218772010-05-21 09:56:06 +00001637 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001638 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001639 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001640 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001641 if context:
1642 self.context = context
1643 else:
1644 self.context = ssl.SSLContext(ssl_version
1645 if ssl_version is not None
1646 else ssl.PROTOCOL_TLSv1)
1647 self.context.verify_mode = (certreqs if certreqs is not None
1648 else ssl.CERT_NONE)
1649 if cacerts:
1650 self.context.load_verify_locations(cacerts)
1651 if certificate:
1652 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001653 if npn_protocols:
1654 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001655 if ciphers:
1656 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001657 self.chatty = chatty
1658 self.connectionchatty = connectionchatty
1659 self.starttls_server = starttls_server
1660 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001661 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001662 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001663 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001664 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001665 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001666 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001667 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001668
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001669 def __enter__(self):
1670 self.start(threading.Event())
1671 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001672 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001673
1674 def __exit__(self, *args):
1675 self.stop()
1676 self.join()
1677
Antoine Pitrou480a1242010-04-28 21:37:09 +00001678 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001679 self.flag = flag
1680 threading.Thread.start(self)
1681
Antoine Pitrou480a1242010-04-28 21:37:09 +00001682 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001683 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001684 self.sock.listen(5)
1685 self.active = True
1686 if self.flag:
1687 # signal an event
1688 self.flag.set()
1689 while self.active:
1690 try:
1691 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001692 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001693 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001694 + repr(connaddr) + '\n')
1695 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001696 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001697 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001698 except socket.timeout:
1699 pass
1700 except KeyboardInterrupt:
1701 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001702 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001703
Antoine Pitrou480a1242010-04-28 21:37:09 +00001704 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001705 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001706
Bill Janssen54cc54c2007-12-14 22:08:56 +00001707 class AsyncoreEchoServer(threading.Thread):
1708
1709 # this one's based on asyncore.dispatcher
1710
1711 class EchoServer (asyncore.dispatcher):
1712
1713 class ConnectionHandler (asyncore.dispatcher_with_send):
1714
1715 def __init__(self, conn, certfile):
1716 self.socket = ssl.wrap_socket(conn, server_side=True,
1717 certfile=certfile,
1718 do_handshake_on_connect=False)
1719 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001720 self._ssl_accepting = True
1721 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001722
1723 def readable(self):
1724 if isinstance(self.socket, ssl.SSLSocket):
1725 while self.socket.pending() > 0:
1726 self.handle_read_event()
1727 return True
1728
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001729 def _do_ssl_handshake(self):
1730 try:
1731 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001732 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1733 return
1734 except ssl.SSLEOFError:
1735 return self.handle_close()
1736 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001737 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001738 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001739 if err.args[0] == errno.ECONNABORTED:
1740 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001741 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001742 self._ssl_accepting = False
1743
1744 def handle_read(self):
1745 if self._ssl_accepting:
1746 self._do_ssl_handshake()
1747 else:
1748 data = self.recv(1024)
1749 if support.verbose:
1750 sys.stdout.write(" server: read %s from client\n" % repr(data))
1751 if not data:
1752 self.close()
1753 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001754 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001755
1756 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001757 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001758 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001759 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1760
1761 def handle_error(self):
1762 raise
1763
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001764 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001765 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001766 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1767 self.port = support.bind_port(sock, '')
1768 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001769 self.listen(5)
1770
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001771 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001772 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001773 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1774 self.ConnectionHandler(sock_obj, self.certfile)
1775
1776 def handle_error(self):
1777 raise
1778
Trent Nelson78520002008-04-10 20:54:35 +00001779 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001780 self.flag = None
1781 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001782 self.server = self.EchoServer(certfile)
1783 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001784 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001785 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001786
1787 def __str__(self):
1788 return "<%s %s>" % (self.__class__.__name__, self.server)
1789
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001790 def __enter__(self):
1791 self.start(threading.Event())
1792 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001793 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001794
1795 def __exit__(self, *args):
1796 if support.verbose:
1797 sys.stdout.write(" cleanup: stopping server.\n")
1798 self.stop()
1799 if support.verbose:
1800 sys.stdout.write(" cleanup: joining server thread.\n")
1801 self.join()
1802 if support.verbose:
1803 sys.stdout.write(" cleanup: successfully joined.\n")
1804
Bill Janssen54cc54c2007-12-14 22:08:56 +00001805 def start (self, flag=None):
1806 self.flag = flag
1807 threading.Thread.start(self)
1808
Antoine Pitrou480a1242010-04-28 21:37:09 +00001809 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001810 self.active = True
1811 if self.flag:
1812 self.flag.set()
1813 while self.active:
1814 try:
1815 asyncore.loop(1)
1816 except:
1817 pass
1818
Antoine Pitrou480a1242010-04-28 21:37:09 +00001819 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001820 self.active = False
1821 self.server.close()
1822
Antoine Pitrou480a1242010-04-28 21:37:09 +00001823 def bad_cert_test(certfile):
1824 """
1825 Launch a server with CERT_REQUIRED, and check that trying to
1826 connect to it with the given client certificate fails.
1827 """
Trent Nelson78520002008-04-10 20:54:35 +00001828 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001829 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001830 cacerts=CERTFILE, chatty=False,
1831 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001832 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001833 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001834 with socket.socket() as sock:
1835 s = ssl.wrap_socket(sock,
1836 certfile=certfile,
1837 ssl_version=ssl.PROTOCOL_TLSv1)
1838 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001839 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001840 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001841 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001842 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001843 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001844 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001845 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001846 if x.errno != errno.ENOENT:
1847 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001848 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001849 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001850 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001851 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001852
Antoine Pitroub5218772010-05-21 09:56:06 +00001853 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001854 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001855 """
1856 Launch a server, connect a client to it and try various reads
1857 and writes.
1858 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001859 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001860 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001861 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001862 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001863 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001864 with client_context.wrap_socket(socket.socket(),
1865 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001866 s.connect((HOST, server.port))
1867 for arg in [indata, bytearray(indata), memoryview(indata)]:
1868 if connectionchatty:
1869 if support.verbose:
1870 sys.stdout.write(
1871 " client: sending %r...\n" % indata)
1872 s.write(arg)
1873 outdata = s.read()
1874 if connectionchatty:
1875 if support.verbose:
1876 sys.stdout.write(" client: read %r\n" % outdata)
1877 if outdata != indata.lower():
1878 raise AssertionError(
1879 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1880 % (outdata[:20], len(outdata),
1881 indata[:20].lower(), len(indata)))
1882 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001883 if connectionchatty:
1884 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001885 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001886 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001887 'compression': s.compression(),
1888 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001889 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001890 'client_npn_protocol': s.selected_npn_protocol()
1891 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001892 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001893 stats['server_npn_protocols'] = server.selected_protocols
1894 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001895
Antoine Pitroub5218772010-05-21 09:56:06 +00001896 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1897 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001898 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001899 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001900 certtype = {
1901 ssl.CERT_NONE: "CERT_NONE",
1902 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1903 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1904 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001905 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001906 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001907 sys.stdout.write(formatstr %
1908 (ssl.get_protocol_name(client_protocol),
1909 ssl.get_protocol_name(server_protocol),
1910 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001911 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001912 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001913 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001914 server_context.options |= server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001915
1916 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1917 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1918 # starting from OpenSSL 1.0.0 (see issue #8322).
1919 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1920 client_context.set_ciphers("ALL")
1921
Antoine Pitroub5218772010-05-21 09:56:06 +00001922 for ctx in (client_context, server_context):
1923 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001924 ctx.load_cert_chain(CERTFILE)
1925 ctx.load_verify_locations(CERTFILE)
1926 try:
1927 server_params_test(client_context, server_context,
1928 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001929 # Protocol mismatch can result in either an SSLError, or a
1930 # "Connection reset by peer" error.
1931 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001932 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001933 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001934 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001935 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001936 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001937 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001938 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001939 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001940 "Client protocol %s succeeded with server protocol %s!"
1941 % (ssl.get_protocol_name(client_protocol),
1942 ssl.get_protocol_name(server_protocol)))
1943
1944
Bill Janssen6e027db2007-11-15 22:23:56 +00001945 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001946
Antoine Pitrou23df4832010-08-04 17:14:06 +00001947 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001948 def test_echo(self):
1949 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001950 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001951 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001952 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001953 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1954 context = ssl.SSLContext(protocol)
1955 context.load_cert_chain(CERTFILE)
1956 server_params_test(context, context,
1957 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001958
Antoine Pitrou480a1242010-04-28 21:37:09 +00001959 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001960 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001961 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001962 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1963 context.verify_mode = ssl.CERT_REQUIRED
1964 context.load_verify_locations(CERTFILE)
1965 context.load_cert_chain(CERTFILE)
1966 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001967 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02001968 s = context.wrap_socket(socket.socket(),
1969 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001970 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02001971 # getpeercert() raise ValueError while the handshake isn't
1972 # done.
1973 with self.assertRaises(ValueError):
1974 s.getpeercert()
1975 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001976 cert = s.getpeercert()
1977 self.assertTrue(cert, "Can't get peer certificate.")
1978 cipher = s.cipher()
1979 if support.verbose:
1980 sys.stdout.write(pprint.pformat(cert) + '\n')
1981 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1982 if 'subject' not in cert:
1983 self.fail("No subject field in certificate: %s." %
1984 pprint.pformat(cert))
1985 if ((('organizationName', 'Python Software Foundation'),)
1986 not in cert['subject']):
1987 self.fail(
1988 "Missing or invalid 'organizationName' field in certificate subject; "
1989 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001990 self.assertIn('notBefore', cert)
1991 self.assertIn('notAfter', cert)
1992 before = ssl.cert_time_to_seconds(cert['notBefore'])
1993 after = ssl.cert_time_to_seconds(cert['notAfter'])
1994 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001995 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001996
Christian Heimes2427b502013-11-23 11:24:32 +01001997 @unittest.skipUnless(have_verify_flags(),
1998 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01001999 def test_crl_check(self):
2000 if support.verbose:
2001 sys.stdout.write("\n")
2002
2003 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2004 server_context.load_cert_chain(SIGNED_CERTFILE)
2005
2006 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2007 context.verify_mode = ssl.CERT_REQUIRED
2008 context.load_verify_locations(SIGNING_CA)
Christian Heimes32f0c7a2013-11-22 03:43:48 +01002009 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT)
Christian Heimes22587792013-11-21 23:56:13 +01002010
2011 # VERIFY_DEFAULT should pass
2012 server = ThreadedEchoServer(context=server_context, chatty=True)
2013 with server:
2014 with context.wrap_socket(socket.socket()) as s:
2015 s.connect((HOST, server.port))
2016 cert = s.getpeercert()
2017 self.assertTrue(cert, "Can't get peer certificate.")
2018
2019 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimes32f0c7a2013-11-22 03:43:48 +01002020 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Christian Heimes22587792013-11-21 23:56:13 +01002021
2022 server = ThreadedEchoServer(context=server_context, chatty=True)
2023 with server:
2024 with context.wrap_socket(socket.socket()) as s:
2025 with self.assertRaisesRegex(ssl.SSLError,
2026 "certificate verify failed"):
2027 s.connect((HOST, server.port))
2028
2029 # now load a CRL file. The CRL file is signed by the CA.
2030 context.load_verify_locations(CRLFILE)
2031
2032 server = ThreadedEchoServer(context=server_context, chatty=True)
2033 with server:
2034 with context.wrap_socket(socket.socket()) as s:
2035 s.connect((HOST, server.port))
2036 cert = s.getpeercert()
2037 self.assertTrue(cert, "Can't get peer certificate.")
2038
Christian Heimes1aa9a752013-12-02 02:41:19 +01002039 def test_check_hostname(self):
2040 if support.verbose:
2041 sys.stdout.write("\n")
2042
2043 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2044 server_context.load_cert_chain(SIGNED_CERTFILE)
2045
2046 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2047 context.verify_mode = ssl.CERT_REQUIRED
2048 context.check_hostname = True
2049 context.load_verify_locations(SIGNING_CA)
2050
2051 # correct hostname should verify
2052 server = ThreadedEchoServer(context=server_context, chatty=True)
2053 with server:
2054 with context.wrap_socket(socket.socket(),
2055 server_hostname="localhost") as s:
2056 s.connect((HOST, server.port))
2057 cert = s.getpeercert()
2058 self.assertTrue(cert, "Can't get peer certificate.")
2059
2060 # incorrect hostname should raise an exception
2061 server = ThreadedEchoServer(context=server_context, chatty=True)
2062 with server:
2063 with context.wrap_socket(socket.socket(),
2064 server_hostname="invalid") as s:
2065 with self.assertRaisesRegex(ssl.CertificateError,
2066 "hostname 'invalid' doesn't match 'localhost'"):
2067 s.connect((HOST, server.port))
2068
2069 # missing server_hostname arg should cause an exception, too
2070 server = ThreadedEchoServer(context=server_context, chatty=True)
2071 with server:
2072 with socket.socket() as s:
2073 with self.assertRaisesRegex(ValueError,
2074 "check_hostname requires server_hostname"):
2075 context.wrap_socket(s)
2076
Antoine Pitrou480a1242010-04-28 21:37:09 +00002077 def test_empty_cert(self):
2078 """Connecting with an empty cert file"""
2079 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2080 "nullcert.pem"))
2081 def test_malformed_cert(self):
2082 """Connecting with a badly formatted certificate (syntax error)"""
2083 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2084 "badcert.pem"))
2085 def test_nonexisting_cert(self):
2086 """Connecting with a non-existing cert file"""
2087 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2088 "wrongcert.pem"))
2089 def test_malformed_key(self):
2090 """Connecting with a badly formatted key (syntax error)"""
2091 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2092 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002093
Antoine Pitrou480a1242010-04-28 21:37:09 +00002094 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002095 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00002096 in the client when attempting handshake.
2097 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00002098 listener_ready = threading.Event()
2099 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00002100
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002101 s = socket.socket()
2102 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002103
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002104 # `listener` runs in a thread. It sits in an accept() until
2105 # the main thread connects. Then it rudely closes the socket,
2106 # and sets Event `listener_gone` to let the main thread know
2107 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00002108 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00002109 s.listen(5)
2110 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002111 newsock, addr = s.accept()
2112 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002113 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002114 listener_gone.set()
2115
2116 def connector():
2117 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002118 with socket.socket() as c:
2119 c.connect((HOST, port))
2120 listener_gone.wait()
2121 try:
2122 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002123 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00002124 pass
2125 else:
2126 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00002127
2128 t = threading.Thread(target=listener)
2129 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002130 try:
2131 connector()
2132 finally:
2133 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002134
Antoine Pitrou23df4832010-08-04 17:14:06 +00002135 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02002136 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2137 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002138 def test_protocol_sslv2(self):
2139 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002140 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002141 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002142 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2143 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2144 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002145 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Victor Stinner3f7e0642014-12-12 12:27:08 +01002146 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2147 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002148 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002149 # SSLv23 client with specific SSL options
2150 if no_sslv2_implies_sslv3_hello():
2151 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2152 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2153 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002154 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002155 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002156 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002157 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002158
Antoine Pitrou23df4832010-08-04 17:14:06 +00002159 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002160 def test_protocol_sslv23(self):
2161 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002162 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002163 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02002164 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2165 try:
2166 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02002167 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02002168 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2169 if support.verbose:
2170 sys.stdout.write(
2171 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2172 % str(x))
Benjamin Petersone32467c2014-12-05 21:59:35 -05002173 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2174 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002175 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
2176 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002177
Benjamin Petersone32467c2014-12-05 21:59:35 -05002178 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2179 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002180 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
2181 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002182
Benjamin Petersone32467c2014-12-05 21:59:35 -05002183 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2184 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002185 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
2186 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002187
Antoine Pitroub5218772010-05-21 09:56:06 +00002188 # Server with specific SSL options
Benjamin Petersone32467c2014-12-05 21:59:35 -05002189 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2190 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002191 server_options=ssl.OP_NO_SSLv3)
2192 # Will choose TLSv1
2193 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2194 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2195 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2196 server_options=ssl.OP_NO_TLSv1)
2197
2198
Antoine Pitrou23df4832010-08-04 17:14:06 +00002199 @skip_if_broken_ubuntu_ssl
Benjamin Petersone32467c2014-12-05 21:59:35 -05002200 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
2201 "OpenSSL is compiled without SSLv3 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002202 def test_protocol_sslv3(self):
2203 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002204 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002205 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002206 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
2207 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2208 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002209 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2210 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002211 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2212 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002213 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002214 if no_sslv2_implies_sslv3_hello():
2215 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2216 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
2217 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002218
Antoine Pitrou23df4832010-08-04 17:14:06 +00002219 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002220 def test_protocol_tlsv1(self):
2221 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002222 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002223 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002224 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
2225 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
2226 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002227 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2228 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002229 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2230 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002231 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2232 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002233
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002234 @skip_if_broken_ubuntu_ssl
2235 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2236 "TLS version 1.1 not supported.")
2237 def test_protocol_tlsv1_1(self):
2238 """Connecting to a TLSv1.1 server with various client options.
2239 Testing against older TLS versions."""
2240 if support.verbose:
2241 sys.stdout.write("\n")
2242 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
2243 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2244 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002245 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2246 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002247 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2248 client_options=ssl.OP_NO_TLSv1_1)
2249
2250 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
2251 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2252 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2253
2254
2255 @skip_if_broken_ubuntu_ssl
2256 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2257 "TLS version 1.2 not supported.")
2258 def test_protocol_tlsv1_2(self):
2259 """Connecting to a TLSv1.2 server with various client options.
2260 Testing against older TLS versions."""
2261 if support.verbose:
2262 sys.stdout.write("\n")
2263 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
2264 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2265 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2266 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2267 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
Benjamin Petersone32467c2014-12-05 21:59:35 -05002268 if hasattr(ssl, 'PROTOCOL_SSLv3'):
2269 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002270 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2271 client_options=ssl.OP_NO_TLSv1_2)
2272
2273 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
2274 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2275 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2276 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2277 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
2278
Antoine Pitrou480a1242010-04-28 21:37:09 +00002279 def test_starttls(self):
2280 """Switching from clear text to encrypted and back again."""
2281 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 +00002282
Trent Nelson78520002008-04-10 20:54:35 +00002283 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002284 ssl_version=ssl.PROTOCOL_TLSv1,
2285 starttls_server=True,
2286 chatty=True,
2287 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002288 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002289 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002290 s = socket.socket()
2291 s.setblocking(1)
2292 s.connect((HOST, server.port))
2293 if support.verbose:
2294 sys.stdout.write("\n")
2295 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002296 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002297 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002298 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002299 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002300 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002301 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002302 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002303 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002304 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002305 msg = outdata.strip().lower()
2306 if indata == b"STARTTLS" and msg.startswith(b"ok"):
2307 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002308 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002309 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002310 " client: read %r from server, starting TLS...\n"
2311 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002312 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2313 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00002314 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
2315 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002316 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002317 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002318 " client: read %r from server, ending TLS...\n"
2319 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002320 s = conn.unwrap()
2321 wrapped = False
2322 else:
2323 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002324 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002325 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002326 if support.verbose:
2327 sys.stdout.write(" client: closing connection.\n")
2328 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002329 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002330 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002331 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00002332 if wrapped:
2333 conn.close()
2334 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002335 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002336
Antoine Pitrou480a1242010-04-28 21:37:09 +00002337 def test_socketserver(self):
2338 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01002339 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002340 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002341 if support.verbose:
2342 sys.stdout.write('\n')
2343 with open(CERTFILE, 'rb') as f:
2344 d1 = f.read()
2345 d2 = ''
2346 # now fetch the same data from the HTTPS server
Benjamin Peterson4ffb0752014-11-03 14:29:33 -05002347 url = 'https://localhost:%d/%s' % (
2348 server.port, os.path.split(CERTFILE)[1])
2349 context = ssl.create_default_context(cafile=CERTFILE)
2350 f = urllib.request.urlopen(url, context=context)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002351 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00002352 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002353 if dlen and (int(dlen) > 0):
2354 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002355 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002356 sys.stdout.write(
2357 " client: read %d bytes from remote server '%s'\n"
2358 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002359 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002360 f.close()
2361 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002362
Antoine Pitrou480a1242010-04-28 21:37:09 +00002363 def test_asyncore_server(self):
2364 """Check the example asyncore integration."""
2365 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00002366
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002367 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002368 sys.stdout.write("\n")
2369
Antoine Pitrou480a1242010-04-28 21:37:09 +00002370 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00002371 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002372 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002373 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002374 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002375 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002376 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002377 " client: sending %r...\n" % indata)
2378 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002379 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002380 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002381 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002382 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002383 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002384 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2385 % (outdata[:20], len(outdata),
2386 indata[:20].lower(), len(indata)))
2387 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002388 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002389 sys.stdout.write(" client: closing connection.\n")
2390 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00002391 if support.verbose:
2392 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00002393
Antoine Pitrou480a1242010-04-28 21:37:09 +00002394 def test_recv_send(self):
2395 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00002396 if support.verbose:
2397 sys.stdout.write("\n")
2398
2399 server = ThreadedEchoServer(CERTFILE,
2400 certreqs=ssl.CERT_NONE,
2401 ssl_version=ssl.PROTOCOL_TLSv1,
2402 cacerts=CERTFILE,
2403 chatty=True,
2404 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002405 with server:
2406 s = ssl.wrap_socket(socket.socket(),
2407 server_side=False,
2408 certfile=CERTFILE,
2409 ca_certs=CERTFILE,
2410 cert_reqs=ssl.CERT_NONE,
2411 ssl_version=ssl.PROTOCOL_TLSv1)
2412 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002413 # helper methods for standardising recv* method signatures
2414 def _recv_into():
2415 b = bytearray(b"\0"*100)
2416 count = s.recv_into(b)
2417 return b[:count]
2418
2419 def _recvfrom_into():
2420 b = bytearray(b"\0"*100)
2421 count, addr = s.recvfrom_into(b)
2422 return b[:count]
2423
2424 # (name, method, whether to expect success, *args)
2425 send_methods = [
2426 ('send', s.send, True, []),
2427 ('sendto', s.sendto, False, ["some.address"]),
2428 ('sendall', s.sendall, True, []),
2429 ]
2430 recv_methods = [
2431 ('recv', s.recv, True, []),
2432 ('recvfrom', s.recvfrom, False, ["some.address"]),
2433 ('recv_into', _recv_into, True, []),
2434 ('recvfrom_into', _recvfrom_into, False, []),
2435 ]
2436 data_prefix = "PREFIX_"
2437
2438 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002439 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002440 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002441 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002442 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002443 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002444 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002445 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002446 "<<{outdata:r}>> ({nout:d}) received; "
2447 "expected <<{indata:r}>> ({nin:d})\n".format(
2448 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002449 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002450 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002451 )
2452 )
2453 except ValueError as e:
2454 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002455 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002456 "Failed to send with method <<{name:s}>>; "
2457 "expected to succeed.\n".format(name=meth_name)
2458 )
2459 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002460 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002461 "Method <<{name:s}>> failed with unexpected "
2462 "exception message: {exp:s}\n".format(
2463 name=meth_name, exp=e
2464 )
2465 )
2466
2467 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002468 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002469 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002470 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002471 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002472 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002473 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002474 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002475 "<<{outdata:r}>> ({nout:d}) received; "
2476 "expected <<{indata:r}>> ({nin:d})\n".format(
2477 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002478 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002479 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002480 )
2481 )
2482 except ValueError as e:
2483 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002484 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002485 "Failed to receive with method <<{name:s}>>; "
2486 "expected to succeed.\n".format(name=meth_name)
2487 )
2488 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002489 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002490 "Method <<{name:s}>> failed with unexpected "
2491 "exception message: {exp:s}\n".format(
2492 name=meth_name, exp=e
2493 )
2494 )
2495 # consume data
2496 s.read()
2497
Nick Coghlan513886a2011-08-28 00:00:27 +10002498 # Make sure sendmsg et al are disallowed to avoid
2499 # inadvertent disclosure of data and/or corruption
2500 # of the encrypted data stream
2501 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2502 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2503 self.assertRaises(NotImplementedError,
2504 s.recvmsg_into, bytearray(100))
2505
Antoine Pitrou480a1242010-04-28 21:37:09 +00002506 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002507 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002508
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002509 def test_handshake_timeout(self):
2510 # Issue #5103: SSL handshake must respect the socket timeout
2511 server = socket.socket(socket.AF_INET)
2512 host = "127.0.0.1"
2513 port = support.bind_port(server)
2514 started = threading.Event()
2515 finish = False
2516
2517 def serve():
2518 server.listen(5)
2519 started.set()
2520 conns = []
2521 while not finish:
2522 r, w, e = select.select([server], [], [], 0.1)
2523 if server in r:
2524 # Let the socket hang around rather than having
2525 # it closed by garbage collection.
2526 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002527 for sock in conns:
2528 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002529
2530 t = threading.Thread(target=serve)
2531 t.start()
2532 started.wait()
2533
2534 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002535 try:
2536 c = socket.socket(socket.AF_INET)
2537 c.settimeout(0.2)
2538 c.connect((host, port))
2539 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002540 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002541 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002542 finally:
2543 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002544 try:
2545 c = socket.socket(socket.AF_INET)
2546 c = ssl.wrap_socket(c)
2547 c.settimeout(0.2)
2548 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002549 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002550 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002551 finally:
2552 c.close()
2553 finally:
2554 finish = True
2555 t.join()
2556 server.close()
2557
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002558 def test_server_accept(self):
2559 # Issue #16357: accept() on a SSLSocket created through
2560 # SSLContext.wrap_socket().
2561 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2562 context.verify_mode = ssl.CERT_REQUIRED
2563 context.load_verify_locations(CERTFILE)
2564 context.load_cert_chain(CERTFILE)
2565 server = socket.socket(socket.AF_INET)
2566 host = "127.0.0.1"
2567 port = support.bind_port(server)
2568 server = context.wrap_socket(server, server_side=True)
2569
2570 evt = threading.Event()
2571 remote = None
2572 peer = None
2573 def serve():
2574 nonlocal remote, peer
2575 server.listen(5)
2576 # Block on the accept and wait on the connection to close.
2577 evt.set()
2578 remote, peer = server.accept()
2579 remote.recv(1)
2580
2581 t = threading.Thread(target=serve)
2582 t.start()
2583 # Client wait until server setup and perform a connect.
2584 evt.wait()
2585 client = context.wrap_socket(socket.socket())
2586 client.connect((host, port))
2587 client_addr = client.getsockname()
2588 client.close()
2589 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002590 remote.close()
2591 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002592 # Sanity checks.
2593 self.assertIsInstance(remote, ssl.SSLSocket)
2594 self.assertEqual(peer, client_addr)
2595
Antoine Pitrou242db722013-05-01 20:52:07 +02002596 def test_getpeercert_enotconn(self):
2597 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2598 with context.wrap_socket(socket.socket()) as sock:
2599 with self.assertRaises(OSError) as cm:
2600 sock.getpeercert()
2601 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2602
2603 def test_do_handshake_enotconn(self):
2604 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2605 with context.wrap_socket(socket.socket()) as sock:
2606 with self.assertRaises(OSError) as cm:
2607 sock.do_handshake()
2608 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2609
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002610 def test_default_ciphers(self):
2611 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2612 try:
2613 # Force a set of weak ciphers on our client context
2614 context.set_ciphers("DES")
2615 except ssl.SSLError:
2616 self.skipTest("no DES cipher available")
2617 with ThreadedEchoServer(CERTFILE,
2618 ssl_version=ssl.PROTOCOL_SSLv23,
2619 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002620 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002621 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002622 s.connect((HOST, server.port))
2623 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2624
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002625 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2626 def test_default_ecdh_curve(self):
2627 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2628 # should be enabled by default on SSL contexts.
2629 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2630 context.load_cert_chain(CERTFILE)
Antoine Pitrouc0430612014-04-16 18:33:39 +02002631 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2632 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2633 # our default cipher list should prefer ECDH-based ciphers
2634 # automatically.
2635 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2636 context.set_ciphers("ECCdraft:ECDH")
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002637 with ThreadedEchoServer(context=context) as server:
2638 with context.wrap_socket(socket.socket()) as s:
2639 s.connect((HOST, server.port))
2640 self.assertIn("ECDH", s.cipher()[0])
2641
Antoine Pitroud6494802011-07-21 01:11:30 +02002642 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2643 "'tls-unique' channel binding not available")
2644 def test_tls_unique_channel_binding(self):
2645 """Test tls-unique channel binding."""
2646 if support.verbose:
2647 sys.stdout.write("\n")
2648
2649 server = ThreadedEchoServer(CERTFILE,
2650 certreqs=ssl.CERT_NONE,
2651 ssl_version=ssl.PROTOCOL_TLSv1,
2652 cacerts=CERTFILE,
2653 chatty=True,
2654 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002655 with server:
2656 s = ssl.wrap_socket(socket.socket(),
2657 server_side=False,
2658 certfile=CERTFILE,
2659 ca_certs=CERTFILE,
2660 cert_reqs=ssl.CERT_NONE,
2661 ssl_version=ssl.PROTOCOL_TLSv1)
2662 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002663 # get the data
2664 cb_data = s.get_channel_binding("tls-unique")
2665 if support.verbose:
2666 sys.stdout.write(" got channel binding data: {0!r}\n"
2667 .format(cb_data))
2668
2669 # check if it is sane
2670 self.assertIsNotNone(cb_data)
2671 self.assertEqual(len(cb_data), 12) # True for TLSv1
2672
2673 # and compare with the peers version
2674 s.write(b"CB tls-unique\n")
2675 peer_data_repr = s.read().strip()
2676 self.assertEqual(peer_data_repr,
2677 repr(cb_data).encode("us-ascii"))
2678 s.close()
2679
2680 # now, again
2681 s = ssl.wrap_socket(socket.socket(),
2682 server_side=False,
2683 certfile=CERTFILE,
2684 ca_certs=CERTFILE,
2685 cert_reqs=ssl.CERT_NONE,
2686 ssl_version=ssl.PROTOCOL_TLSv1)
2687 s.connect((HOST, server.port))
2688 new_cb_data = s.get_channel_binding("tls-unique")
2689 if support.verbose:
2690 sys.stdout.write(" got another channel binding data: {0!r}\n"
2691 .format(new_cb_data))
2692 # is it really unique
2693 self.assertNotEqual(cb_data, new_cb_data)
2694 self.assertIsNotNone(cb_data)
2695 self.assertEqual(len(cb_data), 12) # True for TLSv1
2696 s.write(b"CB tls-unique\n")
2697 peer_data_repr = s.read().strip()
2698 self.assertEqual(peer_data_repr,
2699 repr(new_cb_data).encode("us-ascii"))
2700 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002701
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002702 def test_compression(self):
2703 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2704 context.load_cert_chain(CERTFILE)
2705 stats = server_params_test(context, context,
2706 chatty=True, connectionchatty=True)
2707 if support.verbose:
2708 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2709 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2710
2711 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2712 "ssl.OP_NO_COMPRESSION needed for this test")
2713 def test_compression_disabled(self):
2714 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2715 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002716 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002717 stats = server_params_test(context, context,
2718 chatty=True, connectionchatty=True)
2719 self.assertIs(stats['compression'], None)
2720
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002721 def test_dh_params(self):
2722 # Check we can get a connection with ephemeral Diffie-Hellman
2723 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2724 context.load_cert_chain(CERTFILE)
2725 context.load_dh_params(DHFILE)
2726 context.set_ciphers("kEDH")
2727 stats = server_params_test(context, context,
2728 chatty=True, connectionchatty=True)
2729 cipher = stats["cipher"][0]
2730 parts = cipher.split("-")
2731 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2732 self.fail("Non-DH cipher: " + cipher[0])
2733
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002734 def test_selected_npn_protocol(self):
2735 # selected_npn_protocol() is None unless NPN is used
2736 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2737 context.load_cert_chain(CERTFILE)
2738 stats = server_params_test(context, context,
2739 chatty=True, connectionchatty=True)
2740 self.assertIs(stats['client_npn_protocol'], None)
2741
2742 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2743 def test_npn_protocols(self):
2744 server_protocols = ['http/1.1', 'spdy/2']
2745 protocol_tests = [
2746 (['http/1.1', 'spdy/2'], 'http/1.1'),
2747 (['spdy/2', 'http/1.1'], 'http/1.1'),
2748 (['spdy/2', 'test'], 'spdy/2'),
2749 (['abc', 'def'], 'abc')
2750 ]
2751 for client_protocols, expected in protocol_tests:
2752 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2753 server_context.load_cert_chain(CERTFILE)
2754 server_context.set_npn_protocols(server_protocols)
2755 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2756 client_context.load_cert_chain(CERTFILE)
2757 client_context.set_npn_protocols(client_protocols)
2758 stats = server_params_test(client_context, server_context,
2759 chatty=True, connectionchatty=True)
2760
2761 msg = "failed trying %s (s) and %s (c).\n" \
2762 "was expecting %s, but got %%s from the %%s" \
2763 % (str(server_protocols), str(client_protocols),
2764 str(expected))
2765 client_result = stats['client_npn_protocol']
2766 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2767 server_result = stats['server_npn_protocols'][-1] \
2768 if len(stats['server_npn_protocols']) else 'nothing'
2769 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2770
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002771 def sni_contexts(self):
2772 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2773 server_context.load_cert_chain(SIGNED_CERTFILE)
2774 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2775 other_context.load_cert_chain(SIGNED_CERTFILE2)
2776 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2777 client_context.verify_mode = ssl.CERT_REQUIRED
2778 client_context.load_verify_locations(SIGNING_CA)
2779 return server_context, other_context, client_context
2780
2781 def check_common_name(self, stats, name):
2782 cert = stats['peercert']
2783 self.assertIn((('commonName', name),), cert['subject'])
2784
2785 @needs_sni
2786 def test_sni_callback(self):
2787 calls = []
2788 server_context, other_context, client_context = self.sni_contexts()
2789
2790 def servername_cb(ssl_sock, server_name, initial_context):
2791 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002792 if server_name is not None:
2793 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002794 server_context.set_servername_callback(servername_cb)
2795
2796 stats = server_params_test(client_context, server_context,
2797 chatty=True,
2798 sni_name='supermessage')
2799 # The hostname was fetched properly, and the certificate was
2800 # changed for the connection.
2801 self.assertEqual(calls, [("supermessage", server_context)])
2802 # CERTFILE4 was selected
2803 self.check_common_name(stats, 'fakehostname')
2804
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002805 calls = []
2806 # The callback is called with server_name=None
2807 stats = server_params_test(client_context, server_context,
2808 chatty=True,
2809 sni_name=None)
2810 self.assertEqual(calls, [(None, server_context)])
2811 self.check_common_name(stats, 'localhost')
2812
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002813 # Check disabling the callback
2814 calls = []
2815 server_context.set_servername_callback(None)
2816
2817 stats = server_params_test(client_context, server_context,
2818 chatty=True,
2819 sni_name='notfunny')
2820 # Certificate didn't change
2821 self.check_common_name(stats, 'localhost')
2822 self.assertEqual(calls, [])
2823
2824 @needs_sni
2825 def test_sni_callback_alert(self):
2826 # Returning a TLS alert is reflected to the connecting client
2827 server_context, other_context, client_context = self.sni_contexts()
2828
2829 def cb_returning_alert(ssl_sock, server_name, initial_context):
2830 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2831 server_context.set_servername_callback(cb_returning_alert)
2832
2833 with self.assertRaises(ssl.SSLError) as cm:
2834 stats = server_params_test(client_context, server_context,
2835 chatty=False,
2836 sni_name='supermessage')
2837 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2838
2839 @needs_sni
2840 def test_sni_callback_raising(self):
2841 # Raising fails the connection with a TLS handshake failure alert.
2842 server_context, other_context, client_context = self.sni_contexts()
2843
2844 def cb_raising(ssl_sock, server_name, initial_context):
2845 1/0
2846 server_context.set_servername_callback(cb_raising)
2847
2848 with self.assertRaises(ssl.SSLError) as cm, \
2849 support.captured_stderr() as stderr:
2850 stats = server_params_test(client_context, server_context,
2851 chatty=False,
2852 sni_name='supermessage')
2853 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2854 self.assertIn("ZeroDivisionError", stderr.getvalue())
2855
2856 @needs_sni
2857 def test_sni_callback_wrong_return_type(self):
2858 # Returning the wrong return type terminates the TLS connection
2859 # with an internal error alert.
2860 server_context, other_context, client_context = self.sni_contexts()
2861
2862 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2863 return "foo"
2864 server_context.set_servername_callback(cb_wrong_return_type)
2865
2866 with self.assertRaises(ssl.SSLError) as cm, \
2867 support.captured_stderr() as stderr:
2868 stats = server_params_test(client_context, server_context,
2869 chatty=False,
2870 sni_name='supermessage')
2871 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2872 self.assertIn("TypeError", stderr.getvalue())
2873
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002874 def test_read_write_after_close_raises_valuerror(self):
2875 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2876 context.verify_mode = ssl.CERT_REQUIRED
2877 context.load_verify_locations(CERTFILE)
2878 context.load_cert_chain(CERTFILE)
2879 server = ThreadedEchoServer(context=context, chatty=False)
2880
2881 with server:
2882 s = context.wrap_socket(socket.socket())
2883 s.connect((HOST, server.port))
2884 s.close()
2885
2886 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02002887 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002888
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002889
Thomas Woutersed03b412007-08-28 21:37:11 +00002890def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002891 if support.verbose:
2892 plats = {
2893 'Linux': platform.linux_distribution,
2894 'Mac': platform.mac_ver,
2895 'Windows': platform.win32_ver,
2896 }
2897 for name, func in plats.items():
2898 plat = func()
2899 if plat and plat[0]:
2900 plat = '%s %r' % (name, plat)
2901 break
2902 else:
2903 plat = repr(platform.platform())
2904 print("test_ssl: testing with %r %r" %
2905 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2906 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002907 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002908 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2909 try:
2910 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2911 except AttributeError:
2912 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002913
Antoine Pitrou152efa22010-05-16 18:19:27 +00002914 for filename in [
2915 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2916 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002917 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002918 BADCERT, BADKEY, EMPTYCERT]:
2919 if not os.path.exists(filename):
2920 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002921
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002922 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002923
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002924 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002925 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002926
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002927 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002928 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002929 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002930 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002931
Antoine Pitrou480a1242010-04-28 21:37:09 +00002932 try:
2933 support.run_unittest(*tests)
2934 finally:
2935 if _have_threads:
2936 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002937
2938if __name__ == "__main__":
2939 test_main()