blob: 2b3de1f477e613968f93b44dfb561a4414f35507 [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
Jesus Ceac8754a12012-09-11 02:00:58 +0200157 self.assertRaises(TypeError, ssl.RAND_egd, 1)
158 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000159 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000160
Christian Heimesf77b4b22013-08-21 13:26:05 +0200161 @unittest.skipUnless(os.name == 'posix', 'requires posix')
162 def test_random_fork(self):
163 status = ssl.RAND_status()
164 if not status:
165 self.fail("OpenSSL's PRNG has insufficient randomness")
166
167 rfd, wfd = os.pipe()
168 pid = os.fork()
169 if pid == 0:
170 try:
171 os.close(rfd)
172 child_random = ssl.RAND_pseudo_bytes(16)[0]
173 self.assertEqual(len(child_random), 16)
174 os.write(wfd, child_random)
175 os.close(wfd)
176 except BaseException:
177 os._exit(1)
178 else:
179 os._exit(0)
180 else:
181 os.close(wfd)
182 self.addCleanup(os.close, rfd)
183 _, status = os.waitpid(pid, 0)
184 self.assertEqual(status, 0)
185
186 child_random = os.read(rfd, 16)
187 self.assertEqual(len(child_random), 16)
188 parent_random = ssl.RAND_pseudo_bytes(16)[0]
189 self.assertEqual(len(parent_random), 16)
190
191 self.assertNotEqual(child_random, parent_random)
192
Antoine Pitrou480a1242010-04-28 21:37:09 +0000193 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000194 # note that this uses an 'unofficial' function in _ssl.c,
195 # provided solely for this test, to exercise the certificate
196 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000197 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000198 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000199 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200200 self.assertEqual(p['issuer'],
201 ((('countryName', 'XY'),),
202 (('localityName', 'Castle Anthrax'),),
203 (('organizationName', 'Python Software Foundation'),),
204 (('commonName', 'localhost'),))
205 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100206 # Note the next three asserts will fail if the keys are regenerated
Christian Heimes9424bb42013-06-17 15:32:57 +0200207 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
208 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200209 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
210 self.assertEqual(p['subject'],
211 ((('countryName', 'XY'),),
212 (('localityName', 'Castle Anthrax'),),
213 (('organizationName', 'Python Software Foundation'),),
214 (('commonName', 'localhost'),))
215 )
216 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
217 # Issue #13034: the subjectAltName in some certificates
218 # (notably projects.developer.nokia.com:443) wasn't parsed
219 p = ssl._ssl._test_decode_cert(NOKIACERT)
220 if support.verbose:
221 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
222 self.assertEqual(p['subjectAltName'],
223 (('DNS', 'projects.developer.nokia.com'),
224 ('DNS', 'projects.forum.nokia.com'))
225 )
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100226 # extra OCSP and AIA fields
227 self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',))
228 self.assertEqual(p['caIssuers'],
229 ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',))
230 self.assertEqual(p['crlDistributionPoints'],
231 ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',))
Thomas Woutersed03b412007-08-28 21:37:11 +0000232
Christian Heimes824f7f32013-08-17 00:54:47 +0200233 def test_parse_cert_CVE_2013_4238(self):
234 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
235 if support.verbose:
236 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
237 subject = ((('countryName', 'US'),),
238 (('stateOrProvinceName', 'Oregon'),),
239 (('localityName', 'Beaverton'),),
240 (('organizationName', 'Python Software Foundation'),),
241 (('organizationalUnitName', 'Python Core Development'),),
242 (('commonName', 'null.python.org\x00example.org'),),
243 (('emailAddress', 'python-dev@python.org'),))
244 self.assertEqual(p['subject'], subject)
245 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200246 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
247 san = (('DNS', 'altnull.python.org\x00example.com'),
248 ('email', 'null@python.org\x00user@example.org'),
249 ('URI', 'http://null.python.org\x00http://example.org'),
250 ('IP Address', '192.0.2.1'),
251 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
252 else:
253 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
254 san = (('DNS', 'altnull.python.org\x00example.com'),
255 ('email', 'null@python.org\x00user@example.org'),
256 ('URI', 'http://null.python.org\x00http://example.org'),
257 ('IP Address', '192.0.2.1'),
258 ('IP Address', '<invalid>'))
259
260 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200261
Antoine Pitrou480a1242010-04-28 21:37:09 +0000262 def test_DER_to_PEM(self):
263 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
264 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000265 d1 = ssl.PEM_cert_to_DER_cert(pem)
266 p2 = ssl.DER_cert_to_PEM_cert(d1)
267 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000268 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000269 if not p2.startswith(ssl.PEM_HEADER + '\n'):
270 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
271 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
272 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000273
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000274 def test_openssl_version(self):
275 n = ssl.OPENSSL_VERSION_NUMBER
276 t = ssl.OPENSSL_VERSION_INFO
277 s = ssl.OPENSSL_VERSION
278 self.assertIsInstance(n, int)
279 self.assertIsInstance(t, tuple)
280 self.assertIsInstance(s, str)
281 # Some sanity checks follow
282 # >= 0.9
283 self.assertGreaterEqual(n, 0x900000)
284 # < 2.0
285 self.assertLess(n, 0x20000000)
286 major, minor, fix, patch, status = t
287 self.assertGreaterEqual(major, 0)
288 self.assertLess(major, 2)
289 self.assertGreaterEqual(minor, 0)
290 self.assertLess(minor, 256)
291 self.assertGreaterEqual(fix, 0)
292 self.assertLess(fix, 256)
293 self.assertGreaterEqual(patch, 0)
294 self.assertLessEqual(patch, 26)
295 self.assertGreaterEqual(status, 0)
296 self.assertLessEqual(status, 15)
297 # Version string as returned by OpenSSL, the format might change
298 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
299 (s, t))
300
Antoine Pitrou9d543662010-04-23 23:10:32 +0000301 @support.cpython_only
302 def test_refcycle(self):
303 # Issue #7943: an SSL object doesn't create reference cycles with
304 # itself.
305 s = socket.socket(socket.AF_INET)
306 ss = ssl.wrap_socket(s)
307 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100308 with support.check_warnings(("", ResourceWarning)):
309 del ss
310 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000311
Antoine Pitroua468adc2010-09-14 14:43:44 +0000312 def test_wrapped_unconnected(self):
313 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200314 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000315 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100316 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100317 self.assertRaises(OSError, ss.recv, 1)
318 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
319 self.assertRaises(OSError, ss.recvfrom, 1)
320 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
321 self.assertRaises(OSError, ss.send, b'x')
322 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000323
Antoine Pitrou40f08742010-04-24 22:04:40 +0000324 def test_timeout(self):
325 # Issue #8524: when creating an SSL socket, the timeout of the
326 # original socket should be retained.
327 for timeout in (None, 0.0, 5.0):
328 s = socket.socket(socket.AF_INET)
329 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100330 with ssl.wrap_socket(s) as ss:
331 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000332
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000333 def test_errors(self):
334 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000335 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000336 "certfile must be specified",
337 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000338 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000339 "certfile must be specified for server-side operations",
340 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000341 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000342 "certfile must be specified for server-side operations",
343 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100344 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
345 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
346 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200347 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000348 with socket.socket() as sock:
349 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000350 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200351 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000352 with socket.socket() as sock:
353 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000354 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200355 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000356 with socket.socket() as sock:
357 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000358 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000359
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000360 def test_match_hostname(self):
361 def ok(cert, hostname):
362 ssl.match_hostname(cert, hostname)
363 def fail(cert, hostname):
364 self.assertRaises(ssl.CertificateError,
365 ssl.match_hostname, cert, hostname)
366
367 cert = {'subject': ((('commonName', 'example.com'),),)}
368 ok(cert, 'example.com')
369 ok(cert, 'ExAmple.cOm')
370 fail(cert, 'www.example.com')
371 fail(cert, '.example.com')
372 fail(cert, 'example.org')
373 fail(cert, 'exampleXcom')
374
375 cert = {'subject': ((('commonName', '*.a.com'),),)}
376 ok(cert, 'foo.a.com')
377 fail(cert, 'bar.foo.a.com')
378 fail(cert, 'a.com')
379 fail(cert, 'Xa.com')
380 fail(cert, '.a.com')
381
Georg Brandl72c98d32013-10-27 07:16:53 +0100382 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000383 cert = {'subject': ((('commonName', 'f*.com'),),)}
384 ok(cert, 'foo.com')
385 ok(cert, 'f.com')
386 fail(cert, 'bar.com')
387 fail(cert, 'foo.a.com')
388 fail(cert, 'bar.foo.com')
389
Christian Heimes824f7f32013-08-17 00:54:47 +0200390 # NULL bytes are bad, CVE-2013-4073
391 cert = {'subject': ((('commonName',
392 'null.python.org\x00example.org'),),)}
393 ok(cert, 'null.python.org\x00example.org') # or raise an error?
394 fail(cert, 'example.org')
395 fail(cert, 'null.python.org')
396
Georg Brandl72c98d32013-10-27 07:16:53 +0100397 # error cases with wildcards
398 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
399 fail(cert, 'bar.foo.a.com')
400 fail(cert, 'a.com')
401 fail(cert, 'Xa.com')
402 fail(cert, '.a.com')
403
404 cert = {'subject': ((('commonName', 'a.*.com'),),)}
405 fail(cert, 'a.foo.com')
406 fail(cert, 'a..com')
407 fail(cert, 'a.com')
408
409 # wildcard doesn't match IDNA prefix 'xn--'
410 idna = 'püthon.python.org'.encode("idna").decode("ascii")
411 cert = {'subject': ((('commonName', idna),),)}
412 ok(cert, idna)
413 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
414 fail(cert, idna)
415 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
416 fail(cert, idna)
417
418 # wildcard in first fragment and IDNA A-labels in sequent fragments
419 # are supported.
420 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
421 cert = {'subject': ((('commonName', idna),),)}
422 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
423 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
424 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
425 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
426
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000427 # Slightly fake real-world example
428 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
429 'subject': ((('commonName', 'linuxfrz.org'),),),
430 'subjectAltName': (('DNS', 'linuxfr.org'),
431 ('DNS', 'linuxfr.com'),
432 ('othername', '<unsupported>'))}
433 ok(cert, 'linuxfr.org')
434 ok(cert, 'linuxfr.com')
435 # Not a "DNS" entry
436 fail(cert, '<unsupported>')
437 # When there is a subjectAltName, commonName isn't used
438 fail(cert, 'linuxfrz.org')
439
440 # A pristine real-world example
441 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
442 'subject': ((('countryName', 'US'),),
443 (('stateOrProvinceName', 'California'),),
444 (('localityName', 'Mountain View'),),
445 (('organizationName', 'Google Inc'),),
446 (('commonName', 'mail.google.com'),))}
447 ok(cert, 'mail.google.com')
448 fail(cert, 'gmail.com')
449 # Only commonName is considered
450 fail(cert, 'California')
451
452 # Neither commonName nor subjectAltName
453 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
454 'subject': ((('countryName', 'US'),),
455 (('stateOrProvinceName', 'California'),),
456 (('localityName', 'Mountain View'),),
457 (('organizationName', 'Google Inc'),))}
458 fail(cert, 'mail.google.com')
459
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200460 # No DNS entry in subjectAltName but a commonName
461 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
462 'subject': ((('countryName', 'US'),),
463 (('stateOrProvinceName', 'California'),),
464 (('localityName', 'Mountain View'),),
465 (('commonName', 'mail.google.com'),)),
466 'subjectAltName': (('othername', 'blabla'), )}
467 ok(cert, 'mail.google.com')
468
469 # No DNS entry subjectAltName and no commonName
470 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
471 'subject': ((('countryName', 'US'),),
472 (('stateOrProvinceName', 'California'),),
473 (('localityName', 'Mountain View'),),
474 (('organizationName', 'Google Inc'),)),
475 'subjectAltName': (('othername', 'blabla'),)}
476 fail(cert, 'google.com')
477
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000478 # Empty cert / no cert
479 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
480 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
481
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200482 # Issue #17980: avoid denials of service by refusing more than one
483 # wildcard per fragment.
484 cert = {'subject': ((('commonName', 'a*b.com'),),)}
485 ok(cert, 'axxb.com')
486 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100487 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200488 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
489 with self.assertRaises(ssl.CertificateError) as cm:
490 ssl.match_hostname(cert, 'axxbxxc.com')
491 self.assertIn("too many wildcards", str(cm.exception))
492
Antoine Pitroud5323212010-10-22 18:19:07 +0000493 def test_server_side(self):
494 # server_hostname doesn't work for server sockets
495 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000496 with socket.socket() as sock:
497 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
498 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000499
Antoine Pitroud6494802011-07-21 01:11:30 +0200500 def test_unknown_channel_binding(self):
501 # should raise ValueError for unknown type
502 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100503 with ssl.wrap_socket(s) as ss:
504 with self.assertRaises(ValueError):
505 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200506
507 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
508 "'tls-unique' channel binding not available")
509 def test_tls_unique_channel_binding(self):
510 # unconnected should return None for known type
511 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100512 with ssl.wrap_socket(s) as ss:
513 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200514 # the same for server-side
515 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100516 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
517 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200518
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600519 def test_dealloc_warn(self):
520 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
521 r = repr(ss)
522 with self.assertWarns(ResourceWarning) as cm:
523 ss = None
524 support.gc_collect()
525 self.assertIn(r, str(cm.warning.args[0]))
526
Christian Heimes6d7ad132013-06-09 18:02:55 +0200527 def test_get_default_verify_paths(self):
528 paths = ssl.get_default_verify_paths()
529 self.assertEqual(len(paths), 6)
530 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
531
532 with support.EnvironmentVarGuard() as env:
533 env["SSL_CERT_DIR"] = CAPATH
534 env["SSL_CERT_FILE"] = CERTFILE
535 paths = ssl.get_default_verify_paths()
536 self.assertEqual(paths.cafile, CERTFILE)
537 self.assertEqual(paths.capath, CAPATH)
538
Christian Heimes44109d72013-11-22 01:51:30 +0100539 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
540 def test_enum_certificates(self):
541 self.assertTrue(ssl.enum_certificates("CA"))
542 self.assertTrue(ssl.enum_certificates("ROOT"))
543
544 self.assertRaises(TypeError, ssl.enum_certificates)
545 self.assertRaises(WindowsError, ssl.enum_certificates, "")
546
Christian Heimesc2d65e12013-11-22 16:13:55 +0100547 trust_oids = set()
548 for storename in ("CA", "ROOT"):
549 store = ssl.enum_certificates(storename)
550 self.assertIsInstance(store, list)
551 for element in store:
552 self.assertIsInstance(element, tuple)
553 self.assertEqual(len(element), 3)
554 cert, enc, trust = element
555 self.assertIsInstance(cert, bytes)
556 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
557 self.assertIsInstance(trust, (set, bool))
558 if isinstance(trust, set):
559 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100560
561 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100562 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200563
Christian Heimes46bebee2013-06-09 19:03:31 +0200564 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100565 def test_enum_crls(self):
566 self.assertTrue(ssl.enum_crls("CA"))
567 self.assertRaises(TypeError, ssl.enum_crls)
568 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200569
Christian Heimes44109d72013-11-22 01:51:30 +0100570 crls = ssl.enum_crls("CA")
571 self.assertIsInstance(crls, list)
572 for element in crls:
573 self.assertIsInstance(element, tuple)
574 self.assertEqual(len(element), 2)
575 self.assertIsInstance(element[0], bytes)
576 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200577
Christian Heimes46bebee2013-06-09 19:03:31 +0200578
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100579 def test_asn1object(self):
580 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
581 '1.3.6.1.5.5.7.3.1')
582
583 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
584 self.assertEqual(val, expected)
585 self.assertEqual(val.nid, 129)
586 self.assertEqual(val.shortname, 'serverAuth')
587 self.assertEqual(val.longname, 'TLS Web Server Authentication')
588 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
589 self.assertIsInstance(val, ssl._ASN1Object)
590 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
591
592 val = ssl._ASN1Object.fromnid(129)
593 self.assertEqual(val, expected)
594 self.assertIsInstance(val, ssl._ASN1Object)
595 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100596 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
597 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100598 for i in range(1000):
599 try:
600 obj = ssl._ASN1Object.fromnid(i)
601 except ValueError:
602 pass
603 else:
604 self.assertIsInstance(obj.nid, int)
605 self.assertIsInstance(obj.shortname, str)
606 self.assertIsInstance(obj.longname, str)
607 self.assertIsInstance(obj.oid, (str, type(None)))
608
609 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
610 self.assertEqual(val, expected)
611 self.assertIsInstance(val, ssl._ASN1Object)
612 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
613 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
614 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100615 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
616 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100617
Christian Heimes72d28502013-11-23 13:56:58 +0100618 def test_purpose_enum(self):
619 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
620 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
621 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
622 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
623 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
624 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
625 '1.3.6.1.5.5.7.3.1')
626
627 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
628 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
629 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
630 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
631 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
632 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
633 '1.3.6.1.5.5.7.3.2')
634
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100635 def test_unsupported_dtls(self):
636 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
637 self.addCleanup(s.close)
638 with self.assertRaises(NotImplementedError) as cx:
639 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
640 self.assertEqual(str(cx.exception), "only stream sockets are supported")
641 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
642 with self.assertRaises(NotImplementedError) as cx:
643 ctx.wrap_socket(s)
644 self.assertEqual(str(cx.exception), "only stream sockets are supported")
645
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100646
Antoine Pitrou152efa22010-05-16 18:19:27 +0000647class ContextTests(unittest.TestCase):
648
Antoine Pitrou23df4832010-08-04 17:14:06 +0000649 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000650 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100651 for protocol in PROTOCOLS:
652 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000653 self.assertRaises(TypeError, ssl.SSLContext)
654 self.assertRaises(ValueError, ssl.SSLContext, -1)
655 self.assertRaises(ValueError, ssl.SSLContext, 42)
656
Antoine Pitrou23df4832010-08-04 17:14:06 +0000657 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000658 def test_protocol(self):
659 for proto in PROTOCOLS:
660 ctx = ssl.SSLContext(proto)
661 self.assertEqual(ctx.protocol, proto)
662
663 def test_ciphers(self):
664 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
665 ctx.set_ciphers("ALL")
666 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000667 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000668 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000669
Antoine Pitrou23df4832010-08-04 17:14:06 +0000670 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000671 def test_options(self):
672 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +0100673 # OP_ALL | OP_NO_SSLv2 is the default value
Antoine Pitroub5218772010-05-21 09:56:06 +0000674 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
675 ctx.options)
676 ctx.options |= ssl.OP_NO_SSLv3
677 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
678 ctx.options)
679 if can_clear_options():
680 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
681 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
682 ctx.options)
683 ctx.options = 0
684 self.assertEqual(0, ctx.options)
685 else:
686 with self.assertRaises(ValueError):
687 ctx.options = 0
688
Christian Heimes22587792013-11-21 23:56:13 +0100689 def test_verify_mode(self):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000690 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
691 # Default value
692 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
693 ctx.verify_mode = ssl.CERT_OPTIONAL
694 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
695 ctx.verify_mode = ssl.CERT_REQUIRED
696 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
697 ctx.verify_mode = ssl.CERT_NONE
698 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
699 with self.assertRaises(TypeError):
700 ctx.verify_mode = None
701 with self.assertRaises(ValueError):
702 ctx.verify_mode = 42
703
Christian Heimes2427b502013-11-23 11:24:32 +0100704 @unittest.skipUnless(have_verify_flags(),
705 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +0100706 def test_verify_flags(self):
707 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
708 # default value by OpenSSL
709 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
710 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
711 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
712 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
713 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
714 ctx.verify_flags = ssl.VERIFY_DEFAULT
715 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
716 # supports any value
717 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
718 self.assertEqual(ctx.verify_flags,
719 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
720 with self.assertRaises(TypeError):
721 ctx.verify_flags = None
722
Antoine Pitrou152efa22010-05-16 18:19:27 +0000723 def test_load_cert_chain(self):
724 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
725 # Combined key and cert in a single file
726 ctx.load_cert_chain(CERTFILE)
727 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
728 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200729 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000730 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000731 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000732 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000733 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000734 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000735 ctx.load_cert_chain(EMPTYCERT)
736 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000737 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000738 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
739 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
740 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000741 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000742 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000743 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000744 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000745 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000746 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
747 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000748 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000749 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000750 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200751 # Password protected key and cert
752 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
753 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
754 ctx.load_cert_chain(CERTFILE_PROTECTED,
755 password=bytearray(KEY_PASSWORD.encode()))
756 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
757 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
758 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
759 bytearray(KEY_PASSWORD.encode()))
760 with self.assertRaisesRegex(TypeError, "should be a string"):
761 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
762 with self.assertRaises(ssl.SSLError):
763 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
764 with self.assertRaisesRegex(ValueError, "cannot be longer"):
765 # openssl has a fixed limit on the password buffer.
766 # PEM_BUFSIZE is generally set to 1kb.
767 # Return a string larger than this.
768 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
769 # Password callback
770 def getpass_unicode():
771 return KEY_PASSWORD
772 def getpass_bytes():
773 return KEY_PASSWORD.encode()
774 def getpass_bytearray():
775 return bytearray(KEY_PASSWORD.encode())
776 def getpass_badpass():
777 return "badpass"
778 def getpass_huge():
779 return b'a' * (1024 * 1024)
780 def getpass_bad_type():
781 return 9
782 def getpass_exception():
783 raise Exception('getpass error')
784 class GetPassCallable:
785 def __call__(self):
786 return KEY_PASSWORD
787 def getpass(self):
788 return KEY_PASSWORD
789 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
790 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
791 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
792 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
793 ctx.load_cert_chain(CERTFILE_PROTECTED,
794 password=GetPassCallable().getpass)
795 with self.assertRaises(ssl.SSLError):
796 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
797 with self.assertRaisesRegex(ValueError, "cannot be longer"):
798 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
799 with self.assertRaisesRegex(TypeError, "must return a string"):
800 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
801 with self.assertRaisesRegex(Exception, "getpass error"):
802 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
803 # Make sure the password function isn't called if it isn't needed
804 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000805
806 def test_load_verify_locations(self):
807 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
808 ctx.load_verify_locations(CERTFILE)
809 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
810 ctx.load_verify_locations(BYTES_CERTFILE)
811 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
812 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +0100813 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200814 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000815 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000816 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000817 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000818 ctx.load_verify_locations(BADCERT)
819 ctx.load_verify_locations(CERTFILE, CAPATH)
820 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
821
Victor Stinner80f75e62011-01-29 11:31:20 +0000822 # Issue #10989: crash if the second argument type is invalid
823 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
824
Christian Heimesefff7062013-11-21 03:35:02 +0100825 def test_load_verify_cadata(self):
826 # test cadata
827 with open(CAFILE_CACERT) as f:
828 cacert_pem = f.read()
829 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
830 with open(CAFILE_NEURONIO) as f:
831 neuronio_pem = f.read()
832 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
833
834 # test PEM
835 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
836 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
837 ctx.load_verify_locations(cadata=cacert_pem)
838 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
839 ctx.load_verify_locations(cadata=neuronio_pem)
840 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
841 # cert already in hash table
842 ctx.load_verify_locations(cadata=neuronio_pem)
843 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
844
845 # combined
846 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
847 combined = "\n".join((cacert_pem, neuronio_pem))
848 ctx.load_verify_locations(cadata=combined)
849 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
850
851 # with junk around the certs
852 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
853 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
854 neuronio_pem, "tail"]
855 ctx.load_verify_locations(cadata="\n".join(combined))
856 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
857
858 # test DER
859 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
860 ctx.load_verify_locations(cadata=cacert_der)
861 ctx.load_verify_locations(cadata=neuronio_der)
862 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
863 # cert already in hash table
864 ctx.load_verify_locations(cadata=cacert_der)
865 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
866
867 # combined
868 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
869 combined = b"".join((cacert_der, neuronio_der))
870 ctx.load_verify_locations(cadata=combined)
871 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
872
873 # error cases
874 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
875 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
876
877 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
878 ctx.load_verify_locations(cadata="broken")
879 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
880 ctx.load_verify_locations(cadata=b"broken")
881
882
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100883 def test_load_dh_params(self):
884 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
885 ctx.load_dh_params(DHFILE)
886 if os.name != 'nt':
887 ctx.load_dh_params(BYTES_DHFILE)
888 self.assertRaises(TypeError, ctx.load_dh_params)
889 self.assertRaises(TypeError, ctx.load_dh_params, None)
890 with self.assertRaises(FileNotFoundError) as cm:
891 ctx.load_dh_params(WRONGCERT)
892 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200893 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100894 ctx.load_dh_params(CERTFILE)
895
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000896 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000897 def test_session_stats(self):
898 for proto in PROTOCOLS:
899 ctx = ssl.SSLContext(proto)
900 self.assertEqual(ctx.session_stats(), {
901 'number': 0,
902 'connect': 0,
903 'connect_good': 0,
904 'connect_renegotiate': 0,
905 'accept': 0,
906 'accept_good': 0,
907 'accept_renegotiate': 0,
908 'hits': 0,
909 'misses': 0,
910 'timeouts': 0,
911 'cache_full': 0,
912 })
913
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000914 def test_set_default_verify_paths(self):
915 # There's not much we can do to test that it acts as expected,
916 # so just check it doesn't crash or raise an exception.
917 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
918 ctx.set_default_verify_paths()
919
Antoine Pitrou501da612011-12-21 09:27:41 +0100920 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100921 def test_set_ecdh_curve(self):
922 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
923 ctx.set_ecdh_curve("prime256v1")
924 ctx.set_ecdh_curve(b"prime256v1")
925 self.assertRaises(TypeError, ctx.set_ecdh_curve)
926 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
927 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
928 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
929
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100930 @needs_sni
931 def test_sni_callback(self):
932 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
933
934 # set_servername_callback expects a callable, or None
935 self.assertRaises(TypeError, ctx.set_servername_callback)
936 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
937 self.assertRaises(TypeError, ctx.set_servername_callback, "")
938 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
939
940 def dummycallback(sock, servername, ctx):
941 pass
942 ctx.set_servername_callback(None)
943 ctx.set_servername_callback(dummycallback)
944
945 @needs_sni
946 def test_sni_callback_refcycle(self):
947 # Reference cycles through the servername callback are detected
948 # and cleared.
949 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
950 def dummycallback(sock, servername, ctx, cycle=ctx):
951 pass
952 ctx.set_servername_callback(dummycallback)
953 wr = weakref.ref(ctx)
954 del ctx, dummycallback
955 gc.collect()
956 self.assertIs(wr(), None)
957
Christian Heimes9a5395a2013-06-17 15:44:12 +0200958 def test_cert_store_stats(self):
959 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
960 self.assertEqual(ctx.cert_store_stats(),
961 {'x509_ca': 0, 'crl': 0, 'x509': 0})
962 ctx.load_cert_chain(CERTFILE)
963 self.assertEqual(ctx.cert_store_stats(),
964 {'x509_ca': 0, 'crl': 0, 'x509': 0})
965 ctx.load_verify_locations(CERTFILE)
966 self.assertEqual(ctx.cert_store_stats(),
967 {'x509_ca': 0, 'crl': 0, 'x509': 1})
968 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
969 self.assertEqual(ctx.cert_store_stats(),
970 {'x509_ca': 1, 'crl': 0, 'x509': 2})
971
972 def test_get_ca_certs(self):
973 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
974 self.assertEqual(ctx.get_ca_certs(), [])
975 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
976 ctx.load_verify_locations(CERTFILE)
977 self.assertEqual(ctx.get_ca_certs(), [])
978 # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
979 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
980 self.assertEqual(ctx.get_ca_certs(),
981 [{'issuer': ((('organizationName', 'Root CA'),),
982 (('organizationalUnitName', 'http://www.cacert.org'),),
983 (('commonName', 'CA Cert Signing Authority'),),
984 (('emailAddress', 'support@cacert.org'),)),
985 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
986 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
987 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100988 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +0200989 'subject': ((('organizationName', 'Root CA'),),
990 (('organizationalUnitName', 'http://www.cacert.org'),),
991 (('commonName', 'CA Cert Signing Authority'),),
992 (('emailAddress', 'support@cacert.org'),)),
993 'version': 3}])
994
995 with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
996 pem = f.read()
997 der = ssl.PEM_cert_to_DER_cert(pem)
998 self.assertEqual(ctx.get_ca_certs(True), [der])
999
Christian Heimes72d28502013-11-23 13:56:58 +01001000 def test_load_default_certs(self):
1001 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1002 ctx.load_default_certs()
1003
1004 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1005 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1006 ctx.load_default_certs()
1007
1008 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1009 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1010
1011 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1012 self.assertRaises(TypeError, ctx.load_default_certs, None)
1013 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1014
Christian Heimes4c05b472013-11-23 15:58:30 +01001015 def test_create_default_context(self):
1016 ctx = ssl.create_default_context()
Donald Stufft6a2ba942014-03-23 19:05:28 -04001017 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001018 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001019 self.assertTrue(ctx.check_hostname)
Christian Heimes4c05b472013-11-23 15:58:30 +01001020 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001021 self.assertEqual(
1022 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1023 getattr(ssl, "OP_NO_COMPRESSION", 0),
1024 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001025
1026 with open(SIGNING_CA) as f:
1027 cadata = f.read()
1028 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1029 cadata=cadata)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001030 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001031 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1032 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001033 self.assertEqual(
1034 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1035 getattr(ssl, "OP_NO_COMPRESSION", 0),
1036 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001037
1038 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001039 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001040 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1041 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001042 self.assertEqual(
1043 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1044 getattr(ssl, "OP_NO_COMPRESSION", 0),
1045 )
1046 self.assertEqual(
1047 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1048 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1049 )
1050 self.assertEqual(
1051 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1052 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1053 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001054
Christian Heimes67986f92013-11-23 22:43:47 +01001055 def test__create_stdlib_context(self):
1056 ctx = ssl._create_stdlib_context()
1057 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1058 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001059 self.assertFalse(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001060 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1061
1062 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1063 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1064 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1065 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1066
1067 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001068 cert_reqs=ssl.CERT_REQUIRED,
1069 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001070 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1071 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001072 self.assertTrue(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001073 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1074
1075 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1076 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1077 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1078 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Christian Heimes4c05b472013-11-23 15:58:30 +01001079
Christian Heimes1aa9a752013-12-02 02:41:19 +01001080 def test_check_hostname(self):
1081 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1082 self.assertFalse(ctx.check_hostname)
1083
1084 # Requires CERT_REQUIRED or CERT_OPTIONAL
1085 with self.assertRaises(ValueError):
1086 ctx.check_hostname = True
1087 ctx.verify_mode = ssl.CERT_REQUIRED
1088 self.assertFalse(ctx.check_hostname)
1089 ctx.check_hostname = True
1090 self.assertTrue(ctx.check_hostname)
1091
1092 ctx.verify_mode = ssl.CERT_OPTIONAL
1093 ctx.check_hostname = True
1094 self.assertTrue(ctx.check_hostname)
1095
1096 # Cannot set CERT_NONE with check_hostname enabled
1097 with self.assertRaises(ValueError):
1098 ctx.verify_mode = ssl.CERT_NONE
1099 ctx.check_hostname = False
1100 self.assertFalse(ctx.check_hostname)
1101
Antoine Pitrou152efa22010-05-16 18:19:27 +00001102
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001103class SSLErrorTests(unittest.TestCase):
1104
1105 def test_str(self):
1106 # The str() of a SSLError doesn't include the errno
1107 e = ssl.SSLError(1, "foo")
1108 self.assertEqual(str(e), "foo")
1109 self.assertEqual(e.errno, 1)
1110 # Same for a subclass
1111 e = ssl.SSLZeroReturnError(1, "foo")
1112 self.assertEqual(str(e), "foo")
1113 self.assertEqual(e.errno, 1)
1114
1115 def test_lib_reason(self):
1116 # Test the library and reason attributes
1117 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1118 with self.assertRaises(ssl.SSLError) as cm:
1119 ctx.load_dh_params(CERTFILE)
1120 self.assertEqual(cm.exception.library, 'PEM')
1121 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1122 s = str(cm.exception)
1123 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1124
1125 def test_subclass(self):
1126 # Check that the appropriate SSLError subclass is raised
1127 # (this only tests one of them)
1128 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1129 with socket.socket() as s:
1130 s.bind(("127.0.0.1", 0))
1131 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001132 c = socket.socket()
1133 c.connect(s.getsockname())
1134 c.setblocking(False)
1135 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001136 with self.assertRaises(ssl.SSLWantReadError) as cm:
1137 c.do_handshake()
1138 s = str(cm.exception)
1139 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1140 # For compatibility
1141 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1142
1143
Bill Janssen6e027db2007-11-15 22:23:56 +00001144class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001145
Antoine Pitrou480a1242010-04-28 21:37:09 +00001146 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001147 with support.transient_internet("svn.python.org"):
1148 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1149 cert_reqs=ssl.CERT_NONE)
1150 try:
1151 s.connect(("svn.python.org", 443))
1152 self.assertEqual({}, s.getpeercert())
1153 finally:
1154 s.close()
1155
1156 # this should fail because we have no verification certs
1157 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1158 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001159 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1160 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001161 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001162
Antoine Pitrou350c7222010-09-09 13:31:46 +00001163 # this should succeed because we specify the root cert
1164 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1165 cert_reqs=ssl.CERT_REQUIRED,
1166 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1167 try:
1168 s.connect(("svn.python.org", 443))
1169 self.assertTrue(s.getpeercert())
1170 finally:
1171 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001172
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001173 def test_connect_ex(self):
1174 # Issue #11326: check connect_ex() implementation
1175 with support.transient_internet("svn.python.org"):
1176 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1177 cert_reqs=ssl.CERT_REQUIRED,
1178 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1179 try:
1180 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
1181 self.assertTrue(s.getpeercert())
1182 finally:
1183 s.close()
1184
1185 def test_non_blocking_connect_ex(self):
1186 # Issue #11326: non-blocking connect_ex() should allow handshake
1187 # to proceed after the socket gets ready.
1188 with support.transient_internet("svn.python.org"):
1189 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1190 cert_reqs=ssl.CERT_REQUIRED,
1191 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1192 do_handshake_on_connect=False)
1193 try:
1194 s.setblocking(False)
1195 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +00001196 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1197 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001198 # Wait for connect to finish
1199 select.select([], [s], [], 5.0)
1200 # Non-blocking handshake
1201 while True:
1202 try:
1203 s.do_handshake()
1204 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001205 except ssl.SSLWantReadError:
1206 select.select([s], [], [], 5.0)
1207 except ssl.SSLWantWriteError:
1208 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001209 # SSL established
1210 self.assertTrue(s.getpeercert())
1211 finally:
1212 s.close()
1213
Antoine Pitroub4410db2011-05-18 18:51:06 +02001214 def test_timeout_connect_ex(self):
1215 # Issue #12065: on a timeout, connect_ex() should return the original
1216 # errno (mimicking the behaviour of non-SSL sockets).
1217 with support.transient_internet("svn.python.org"):
1218 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1219 cert_reqs=ssl.CERT_REQUIRED,
1220 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1221 do_handshake_on_connect=False)
1222 try:
1223 s.settimeout(0.0000001)
1224 rc = s.connect_ex(('svn.python.org', 443))
1225 if rc == 0:
1226 self.skipTest("svn.python.org responded too quickly")
1227 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1228 finally:
1229 s.close()
1230
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001231 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +01001232 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001233 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1234 cert_reqs=ssl.CERT_REQUIRED,
1235 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1236 try:
Christian Heimesde570742013-12-16 21:15:44 +01001237 rc = s.connect_ex(("svn.python.org", 444))
1238 # Issue #19919: Windows machines or VMs hosted on Windows
1239 # machines sometimes return EWOULDBLOCK.
1240 self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001241 finally:
1242 s.close()
1243
Antoine Pitrou152efa22010-05-16 18:19:27 +00001244 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001245 with support.transient_internet("svn.python.org"):
1246 # Same as test_connect, but with a separately created context
1247 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1248 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1249 s.connect(("svn.python.org", 443))
1250 try:
1251 self.assertEqual({}, s.getpeercert())
1252 finally:
1253 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +00001254 # Same with a server hostname
1255 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1256 server_hostname="svn.python.org")
1257 if ssl.HAS_SNI:
1258 s.connect(("svn.python.org", 443))
1259 s.close()
1260 else:
1261 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001262 # This should fail because we have no verification certs
1263 ctx.verify_mode = ssl.CERT_REQUIRED
1264 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +00001265 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +00001266 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001267 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001268 # This should succeed because we specify the root cert
1269 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
1270 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1271 s.connect(("svn.python.org", 443))
1272 try:
1273 cert = s.getpeercert()
1274 self.assertTrue(cert)
1275 finally:
1276 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001277
1278 def test_connect_capath(self):
1279 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00001280 # NOTE: the subject hashing algorithm has been changed between
1281 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1282 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00001283 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +00001284 with support.transient_internet("svn.python.org"):
1285 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1286 ctx.verify_mode = ssl.CERT_REQUIRED
1287 ctx.load_verify_locations(capath=CAPATH)
1288 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1289 s.connect(("svn.python.org", 443))
1290 try:
1291 cert = s.getpeercert()
1292 self.assertTrue(cert)
1293 finally:
1294 s.close()
1295 # Same with a bytes `capath` argument
1296 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1297 ctx.verify_mode = ssl.CERT_REQUIRED
1298 ctx.load_verify_locations(capath=BYTES_CAPATH)
1299 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1300 s.connect(("svn.python.org", 443))
1301 try:
1302 cert = s.getpeercert()
1303 self.assertTrue(cert)
1304 finally:
1305 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001306
Christian Heimesefff7062013-11-21 03:35:02 +01001307 def test_connect_cadata(self):
1308 with open(CAFILE_CACERT) as f:
1309 pem = f.read()
1310 der = ssl.PEM_cert_to_DER_cert(pem)
1311 with support.transient_internet("svn.python.org"):
1312 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1313 ctx.verify_mode = ssl.CERT_REQUIRED
1314 ctx.load_verify_locations(cadata=pem)
1315 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1316 s.connect(("svn.python.org", 443))
1317 cert = s.getpeercert()
1318 self.assertTrue(cert)
1319
1320 # same with DER
1321 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1322 ctx.verify_mode = ssl.CERT_REQUIRED
1323 ctx.load_verify_locations(cadata=der)
1324 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1325 s.connect(("svn.python.org", 443))
1326 cert = s.getpeercert()
1327 self.assertTrue(cert)
1328
Antoine Pitroue3220242010-04-24 11:13:53 +00001329 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1330 def test_makefile_close(self):
1331 # Issue #5238: creating a file-like object with makefile() shouldn't
1332 # delay closing the underlying "real socket" (here tested with its
1333 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +00001334 with support.transient_internet("svn.python.org"):
1335 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1336 ss.connect(("svn.python.org", 443))
1337 fd = ss.fileno()
1338 f = ss.makefile()
1339 f.close()
1340 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +00001341 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001342 # Closing the SSL socket should close the fd too
1343 ss.close()
1344 gc.collect()
1345 with self.assertRaises(OSError) as e:
1346 os.read(fd, 0)
1347 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001348
Antoine Pitrou480a1242010-04-28 21:37:09 +00001349 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001350 with support.transient_internet("svn.python.org"):
1351 s = socket.socket(socket.AF_INET)
1352 s.connect(("svn.python.org", 443))
1353 s.setblocking(False)
1354 s = ssl.wrap_socket(s,
1355 cert_reqs=ssl.CERT_NONE,
1356 do_handshake_on_connect=False)
1357 count = 0
1358 while True:
1359 try:
1360 count += 1
1361 s.do_handshake()
1362 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001363 except ssl.SSLWantReadError:
1364 select.select([s], [], [])
1365 except ssl.SSLWantWriteError:
1366 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +00001367 s.close()
1368 if support.verbose:
1369 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001370
Antoine Pitrou480a1242010-04-28 21:37:09 +00001371 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +02001372 def _test_get_server_certificate(host, port, cert=None):
1373 with support.transient_internet(host):
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001374 pem = ssl.get_server_certificate((host, port),
1375 ssl.PROTOCOL_SSLv23)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001376 if not pem:
1377 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001378
Antoine Pitrou15399c32011-04-28 19:23:55 +02001379 try:
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001380 pem = ssl.get_server_certificate((host, port),
1381 ssl.PROTOCOL_SSLv23,
1382 ca_certs=CERTFILE)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001383 except ssl.SSLError as x:
1384 #should fail
1385 if support.verbose:
1386 sys.stdout.write("%s\n" % x)
1387 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001388 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1389
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001390 pem = ssl.get_server_certificate((host, port),
1391 ssl.PROTOCOL_SSLv23,
1392 ca_certs=cert)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001393 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001394 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001395 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001396 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001397
Antoine Pitrou15399c32011-04-28 19:23:55 +02001398 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
1399 if support.IPV6_ENABLED:
1400 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001401
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001402 def test_ciphers(self):
1403 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001404 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001405 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1406 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1407 s.connect(remote)
1408 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1409 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1410 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001411 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001412 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001413 with socket.socket(socket.AF_INET) as sock:
1414 s = ssl.wrap_socket(sock,
1415 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1416 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001417
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001418 def test_algorithms(self):
1419 # Issue #8484: all algorithms should be available when verifying a
1420 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001421 # SHA256 was added in OpenSSL 0.9.8
1422 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1423 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001424 # sha256.tbs-internet.com needs SNI to use the correct certificate
1425 if not ssl.HAS_SNI:
1426 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001427 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1428 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001429 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001430 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001431 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1432 ctx.verify_mode = ssl.CERT_REQUIRED
1433 ctx.load_verify_locations(sha256_cert)
1434 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1435 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001436 try:
1437 s.connect(remote)
1438 if support.verbose:
1439 sys.stdout.write("\nCipher with %r is %r\n" %
1440 (remote, s.cipher()))
1441 sys.stdout.write("Certificate is:\n%s\n" %
1442 pprint.pformat(s.getpeercert()))
1443 finally:
1444 s.close()
1445
Christian Heimes9a5395a2013-06-17 15:44:12 +02001446 def test_get_ca_certs_capath(self):
1447 # capath certs are loaded on request
1448 with support.transient_internet("svn.python.org"):
1449 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1450 ctx.verify_mode = ssl.CERT_REQUIRED
1451 ctx.load_verify_locations(capath=CAPATH)
1452 self.assertEqual(ctx.get_ca_certs(), [])
1453 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1454 s.connect(("svn.python.org", 443))
1455 try:
1456 cert = s.getpeercert()
1457 self.assertTrue(cert)
1458 finally:
1459 s.close()
1460 self.assertEqual(len(ctx.get_ca_certs()), 1)
1461
Christian Heimes575596e2013-12-15 21:49:17 +01001462 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01001463 def test_context_setget(self):
1464 # Check that the context of a connected socket can be replaced.
1465 with support.transient_internet("svn.python.org"):
1466 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1467 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1468 s = socket.socket(socket.AF_INET)
1469 with ctx1.wrap_socket(s) as ss:
1470 ss.connect(("svn.python.org", 443))
1471 self.assertIs(ss.context, ctx1)
1472 self.assertIs(ss._sslobj.context, ctx1)
1473 ss.context = ctx2
1474 self.assertIs(ss.context, ctx2)
1475 self.assertIs(ss._sslobj.context, ctx2)
1476
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001477try:
1478 import threading
1479except ImportError:
1480 _have_threads = False
1481else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001482 _have_threads = True
1483
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001484 from test.ssl_servers import make_https_server
1485
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001486 class ThreadedEchoServer(threading.Thread):
1487
1488 class ConnectionHandler(threading.Thread):
1489
1490 """A mildly complicated class, because we want it to work both
1491 with and without the SSL wrapper around the socket connection, so
1492 that we can test the STARTTLS functionality."""
1493
Bill Janssen6e027db2007-11-15 22:23:56 +00001494 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001495 self.server = server
1496 self.running = False
1497 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001498 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001499 self.sock.setblocking(1)
1500 self.sslconn = None
1501 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001502 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001503
Antoine Pitrou480a1242010-04-28 21:37:09 +00001504 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001505 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001506 self.sslconn = self.server.context.wrap_socket(
1507 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001508 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001509 except (ssl.SSLError, ConnectionResetError) as e:
1510 # We treat ConnectionResetError as though it were an
1511 # SSLError - OpenSSL on Ubuntu abruptly closes the
1512 # connection when asked to use an unsupported protocol.
1513 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001514 # XXX Various errors can have happened here, for example
1515 # a mismatching protocol version, an invalid certificate,
1516 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001517 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001518 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001519 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001520 self.running = False
1521 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001522 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001523 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001524 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001525 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001526 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001527 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001528 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1529 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001530 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001531 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1532 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001533 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001534 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001535 sys.stdout.write(" server: selected protocol is now "
1536 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001537 return True
1538
1539 def read(self):
1540 if self.sslconn:
1541 return self.sslconn.read()
1542 else:
1543 return self.sock.recv(1024)
1544
1545 def write(self, bytes):
1546 if self.sslconn:
1547 return self.sslconn.write(bytes)
1548 else:
1549 return self.sock.send(bytes)
1550
1551 def close(self):
1552 if self.sslconn:
1553 self.sslconn.close()
1554 else:
1555 self.sock.close()
1556
Antoine Pitrou480a1242010-04-28 21:37:09 +00001557 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001558 self.running = True
1559 if not self.server.starttls_server:
1560 if not self.wrap_conn():
1561 return
1562 while self.running:
1563 try:
1564 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001565 stripped = msg.strip()
1566 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001567 # eof, so quit this handler
1568 self.running = False
1569 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001570 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001571 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001572 sys.stdout.write(" server: client closed connection\n")
1573 self.close()
1574 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001575 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001576 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001577 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001578 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001579 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001580 if not self.wrap_conn():
1581 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001582 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001583 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001584 if support.verbose and self.server.connectionchatty:
1585 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001586 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001587 self.sock = self.sslconn.unwrap()
1588 self.sslconn = None
1589 if support.verbose and self.server.connectionchatty:
1590 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001591 elif stripped == b'CB tls-unique':
1592 if support.verbose and self.server.connectionchatty:
1593 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1594 data = self.sslconn.get_channel_binding("tls-unique")
1595 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001596 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001597 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001598 self.server.connectionchatty):
1599 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001600 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1601 % (msg, ctype, msg.lower(), ctype))
1602 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001603 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001604 if self.server.chatty:
1605 handle_error("Test server failure:\n")
1606 self.close()
1607 self.running = False
1608 # normally, we'd just stop here, but for the test
1609 # harness, we want to stop the server
1610 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001611
Antoine Pitroub5218772010-05-21 09:56:06 +00001612 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001613 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001614 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001615 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001616 if context:
1617 self.context = context
1618 else:
1619 self.context = ssl.SSLContext(ssl_version
1620 if ssl_version is not None
1621 else ssl.PROTOCOL_TLSv1)
1622 self.context.verify_mode = (certreqs if certreqs is not None
1623 else ssl.CERT_NONE)
1624 if cacerts:
1625 self.context.load_verify_locations(cacerts)
1626 if certificate:
1627 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001628 if npn_protocols:
1629 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001630 if ciphers:
1631 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001632 self.chatty = chatty
1633 self.connectionchatty = connectionchatty
1634 self.starttls_server = starttls_server
1635 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001636 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001637 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001638 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001639 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001640 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001641 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001642 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001643
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001644 def __enter__(self):
1645 self.start(threading.Event())
1646 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001647 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001648
1649 def __exit__(self, *args):
1650 self.stop()
1651 self.join()
1652
Antoine Pitrou480a1242010-04-28 21:37:09 +00001653 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001654 self.flag = flag
1655 threading.Thread.start(self)
1656
Antoine Pitrou480a1242010-04-28 21:37:09 +00001657 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001658 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001659 self.sock.listen(5)
1660 self.active = True
1661 if self.flag:
1662 # signal an event
1663 self.flag.set()
1664 while self.active:
1665 try:
1666 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001667 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001668 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001669 + repr(connaddr) + '\n')
1670 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001671 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001672 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001673 except socket.timeout:
1674 pass
1675 except KeyboardInterrupt:
1676 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001677 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001678
Antoine Pitrou480a1242010-04-28 21:37:09 +00001679 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001680 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001681
Bill Janssen54cc54c2007-12-14 22:08:56 +00001682 class AsyncoreEchoServer(threading.Thread):
1683
1684 # this one's based on asyncore.dispatcher
1685
1686 class EchoServer (asyncore.dispatcher):
1687
1688 class ConnectionHandler (asyncore.dispatcher_with_send):
1689
1690 def __init__(self, conn, certfile):
1691 self.socket = ssl.wrap_socket(conn, server_side=True,
1692 certfile=certfile,
1693 do_handshake_on_connect=False)
1694 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001695 self._ssl_accepting = True
1696 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001697
1698 def readable(self):
1699 if isinstance(self.socket, ssl.SSLSocket):
1700 while self.socket.pending() > 0:
1701 self.handle_read_event()
1702 return True
1703
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001704 def _do_ssl_handshake(self):
1705 try:
1706 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001707 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1708 return
1709 except ssl.SSLEOFError:
1710 return self.handle_close()
1711 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001712 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001713 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001714 if err.args[0] == errno.ECONNABORTED:
1715 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001716 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001717 self._ssl_accepting = False
1718
1719 def handle_read(self):
1720 if self._ssl_accepting:
1721 self._do_ssl_handshake()
1722 else:
1723 data = self.recv(1024)
1724 if support.verbose:
1725 sys.stdout.write(" server: read %s from client\n" % repr(data))
1726 if not data:
1727 self.close()
1728 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001729 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001730
1731 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001732 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001733 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001734 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1735
1736 def handle_error(self):
1737 raise
1738
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001739 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001740 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001741 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1742 self.port = support.bind_port(sock, '')
1743 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001744 self.listen(5)
1745
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001746 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001747 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001748 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1749 self.ConnectionHandler(sock_obj, self.certfile)
1750
1751 def handle_error(self):
1752 raise
1753
Trent Nelson78520002008-04-10 20:54:35 +00001754 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001755 self.flag = None
1756 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001757 self.server = self.EchoServer(certfile)
1758 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001759 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001760 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001761
1762 def __str__(self):
1763 return "<%s %s>" % (self.__class__.__name__, self.server)
1764
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001765 def __enter__(self):
1766 self.start(threading.Event())
1767 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001768 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001769
1770 def __exit__(self, *args):
1771 if support.verbose:
1772 sys.stdout.write(" cleanup: stopping server.\n")
1773 self.stop()
1774 if support.verbose:
1775 sys.stdout.write(" cleanup: joining server thread.\n")
1776 self.join()
1777 if support.verbose:
1778 sys.stdout.write(" cleanup: successfully joined.\n")
1779
Bill Janssen54cc54c2007-12-14 22:08:56 +00001780 def start (self, flag=None):
1781 self.flag = flag
1782 threading.Thread.start(self)
1783
Antoine Pitrou480a1242010-04-28 21:37:09 +00001784 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001785 self.active = True
1786 if self.flag:
1787 self.flag.set()
1788 while self.active:
1789 try:
1790 asyncore.loop(1)
1791 except:
1792 pass
1793
Antoine Pitrou480a1242010-04-28 21:37:09 +00001794 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001795 self.active = False
1796 self.server.close()
1797
Antoine Pitrou480a1242010-04-28 21:37:09 +00001798 def bad_cert_test(certfile):
1799 """
1800 Launch a server with CERT_REQUIRED, and check that trying to
1801 connect to it with the given client certificate fails.
1802 """
Trent Nelson78520002008-04-10 20:54:35 +00001803 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001804 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001805 cacerts=CERTFILE, chatty=False,
1806 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001807 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001808 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001809 with socket.socket() as sock:
1810 s = ssl.wrap_socket(sock,
1811 certfile=certfile,
1812 ssl_version=ssl.PROTOCOL_TLSv1)
1813 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001814 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001815 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001816 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001817 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001818 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001819 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001820 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001821 if x.errno != errno.ENOENT:
1822 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001823 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001824 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001825 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001826 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001827
Antoine Pitroub5218772010-05-21 09:56:06 +00001828 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001829 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001830 """
1831 Launch a server, connect a client to it and try various reads
1832 and writes.
1833 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001834 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001835 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001836 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001837 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001838 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001839 with client_context.wrap_socket(socket.socket(),
1840 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001841 s.connect((HOST, server.port))
1842 for arg in [indata, bytearray(indata), memoryview(indata)]:
1843 if connectionchatty:
1844 if support.verbose:
1845 sys.stdout.write(
1846 " client: sending %r...\n" % indata)
1847 s.write(arg)
1848 outdata = s.read()
1849 if connectionchatty:
1850 if support.verbose:
1851 sys.stdout.write(" client: read %r\n" % outdata)
1852 if outdata != indata.lower():
1853 raise AssertionError(
1854 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1855 % (outdata[:20], len(outdata),
1856 indata[:20].lower(), len(indata)))
1857 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001858 if connectionchatty:
1859 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001860 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001861 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001862 'compression': s.compression(),
1863 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001864 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001865 'client_npn_protocol': s.selected_npn_protocol()
1866 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001867 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001868 stats['server_npn_protocols'] = server.selected_protocols
1869 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001870
Antoine Pitroub5218772010-05-21 09:56:06 +00001871 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1872 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001873 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001874 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001875 certtype = {
1876 ssl.CERT_NONE: "CERT_NONE",
1877 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1878 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1879 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001880 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001881 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001882 sys.stdout.write(formatstr %
1883 (ssl.get_protocol_name(client_protocol),
1884 ssl.get_protocol_name(server_protocol),
1885 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001886 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001887 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001888 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001889 server_context.options |= server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001890
1891 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1892 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1893 # starting from OpenSSL 1.0.0 (see issue #8322).
1894 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1895 client_context.set_ciphers("ALL")
1896
Antoine Pitroub5218772010-05-21 09:56:06 +00001897 for ctx in (client_context, server_context):
1898 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001899 ctx.load_cert_chain(CERTFILE)
1900 ctx.load_verify_locations(CERTFILE)
1901 try:
1902 server_params_test(client_context, server_context,
1903 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001904 # Protocol mismatch can result in either an SSLError, or a
1905 # "Connection reset by peer" error.
1906 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001907 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001908 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001909 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001910 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001911 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001912 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001913 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001914 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001915 "Client protocol %s succeeded with server protocol %s!"
1916 % (ssl.get_protocol_name(client_protocol),
1917 ssl.get_protocol_name(server_protocol)))
1918
1919
Bill Janssen6e027db2007-11-15 22:23:56 +00001920 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001921
Antoine Pitrou23df4832010-08-04 17:14:06 +00001922 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001923 def test_echo(self):
1924 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001925 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001926 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001927 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001928 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1929 context = ssl.SSLContext(protocol)
1930 context.load_cert_chain(CERTFILE)
1931 server_params_test(context, context,
1932 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001933
Antoine Pitrou480a1242010-04-28 21:37:09 +00001934 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001935 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001936 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001937 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1938 context.verify_mode = ssl.CERT_REQUIRED
1939 context.load_verify_locations(CERTFILE)
1940 context.load_cert_chain(CERTFILE)
1941 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001942 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02001943 s = context.wrap_socket(socket.socket(),
1944 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001945 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02001946 # getpeercert() raise ValueError while the handshake isn't
1947 # done.
1948 with self.assertRaises(ValueError):
1949 s.getpeercert()
1950 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001951 cert = s.getpeercert()
1952 self.assertTrue(cert, "Can't get peer certificate.")
1953 cipher = s.cipher()
1954 if support.verbose:
1955 sys.stdout.write(pprint.pformat(cert) + '\n')
1956 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1957 if 'subject' not in cert:
1958 self.fail("No subject field in certificate: %s." %
1959 pprint.pformat(cert))
1960 if ((('organizationName', 'Python Software Foundation'),)
1961 not in cert['subject']):
1962 self.fail(
1963 "Missing or invalid 'organizationName' field in certificate subject; "
1964 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001965 self.assertIn('notBefore', cert)
1966 self.assertIn('notAfter', cert)
1967 before = ssl.cert_time_to_seconds(cert['notBefore'])
1968 after = ssl.cert_time_to_seconds(cert['notAfter'])
1969 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001970 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001971
Christian Heimes2427b502013-11-23 11:24:32 +01001972 @unittest.skipUnless(have_verify_flags(),
1973 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01001974 def test_crl_check(self):
1975 if support.verbose:
1976 sys.stdout.write("\n")
1977
1978 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1979 server_context.load_cert_chain(SIGNED_CERTFILE)
1980
1981 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1982 context.verify_mode = ssl.CERT_REQUIRED
1983 context.load_verify_locations(SIGNING_CA)
Christian Heimes32f0c7a2013-11-22 03:43:48 +01001984 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT)
Christian Heimes22587792013-11-21 23:56:13 +01001985
1986 # VERIFY_DEFAULT should pass
1987 server = ThreadedEchoServer(context=server_context, chatty=True)
1988 with server:
1989 with context.wrap_socket(socket.socket()) as s:
1990 s.connect((HOST, server.port))
1991 cert = s.getpeercert()
1992 self.assertTrue(cert, "Can't get peer certificate.")
1993
1994 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimes32f0c7a2013-11-22 03:43:48 +01001995 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Christian Heimes22587792013-11-21 23:56:13 +01001996
1997 server = ThreadedEchoServer(context=server_context, chatty=True)
1998 with server:
1999 with context.wrap_socket(socket.socket()) as s:
2000 with self.assertRaisesRegex(ssl.SSLError,
2001 "certificate verify failed"):
2002 s.connect((HOST, server.port))
2003
2004 # now load a CRL file. The CRL file is signed by the CA.
2005 context.load_verify_locations(CRLFILE)
2006
2007 server = ThreadedEchoServer(context=server_context, chatty=True)
2008 with server:
2009 with context.wrap_socket(socket.socket()) as s:
2010 s.connect((HOST, server.port))
2011 cert = s.getpeercert()
2012 self.assertTrue(cert, "Can't get peer certificate.")
2013
Christian Heimes575596e2013-12-15 21:49:17 +01002014 @needs_sni
Christian Heimes1aa9a752013-12-02 02:41:19 +01002015 def test_check_hostname(self):
2016 if support.verbose:
2017 sys.stdout.write("\n")
2018
2019 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2020 server_context.load_cert_chain(SIGNED_CERTFILE)
2021
2022 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2023 context.verify_mode = ssl.CERT_REQUIRED
2024 context.check_hostname = True
2025 context.load_verify_locations(SIGNING_CA)
2026
2027 # correct hostname should verify
2028 server = ThreadedEchoServer(context=server_context, chatty=True)
2029 with server:
2030 with context.wrap_socket(socket.socket(),
2031 server_hostname="localhost") as s:
2032 s.connect((HOST, server.port))
2033 cert = s.getpeercert()
2034 self.assertTrue(cert, "Can't get peer certificate.")
2035
2036 # incorrect hostname should raise an exception
2037 server = ThreadedEchoServer(context=server_context, chatty=True)
2038 with server:
2039 with context.wrap_socket(socket.socket(),
2040 server_hostname="invalid") as s:
2041 with self.assertRaisesRegex(ssl.CertificateError,
2042 "hostname 'invalid' doesn't match 'localhost'"):
2043 s.connect((HOST, server.port))
2044
2045 # missing server_hostname arg should cause an exception, too
2046 server = ThreadedEchoServer(context=server_context, chatty=True)
2047 with server:
2048 with socket.socket() as s:
2049 with self.assertRaisesRegex(ValueError,
2050 "check_hostname requires server_hostname"):
2051 context.wrap_socket(s)
2052
Antoine Pitrou480a1242010-04-28 21:37:09 +00002053 def test_empty_cert(self):
2054 """Connecting with an empty cert file"""
2055 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2056 "nullcert.pem"))
2057 def test_malformed_cert(self):
2058 """Connecting with a badly formatted certificate (syntax error)"""
2059 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2060 "badcert.pem"))
2061 def test_nonexisting_cert(self):
2062 """Connecting with a non-existing cert file"""
2063 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2064 "wrongcert.pem"))
2065 def test_malformed_key(self):
2066 """Connecting with a badly formatted key (syntax error)"""
2067 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2068 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002069
Antoine Pitrou480a1242010-04-28 21:37:09 +00002070 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002071 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00002072 in the client when attempting handshake.
2073 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00002074 listener_ready = threading.Event()
2075 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00002076
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002077 s = socket.socket()
2078 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002079
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002080 # `listener` runs in a thread. It sits in an accept() until
2081 # the main thread connects. Then it rudely closes the socket,
2082 # and sets Event `listener_gone` to let the main thread know
2083 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00002084 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00002085 s.listen(5)
2086 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002087 newsock, addr = s.accept()
2088 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002089 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002090 listener_gone.set()
2091
2092 def connector():
2093 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002094 with socket.socket() as c:
2095 c.connect((HOST, port))
2096 listener_gone.wait()
2097 try:
2098 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002099 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00002100 pass
2101 else:
2102 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00002103
2104 t = threading.Thread(target=listener)
2105 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002106 try:
2107 connector()
2108 finally:
2109 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002110
Antoine Pitrou23df4832010-08-04 17:14:06 +00002111 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02002112 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2113 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002114 def test_protocol_sslv2(self):
2115 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002116 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002117 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002118 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2119 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2120 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002121 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002122 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2123 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002124 # SSLv23 client with specific SSL options
2125 if no_sslv2_implies_sslv3_hello():
2126 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2127 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2128 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002129 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002130 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002131 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002132 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002133
Antoine Pitrou23df4832010-08-04 17:14:06 +00002134 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002135 def test_protocol_sslv23(self):
2136 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002137 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002138 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02002139 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2140 try:
2141 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02002142 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02002143 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2144 if support.verbose:
2145 sys.stdout.write(
2146 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2147 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00002148 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
2149 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
2150 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002151
Antoine Pitrou480a1242010-04-28 21:37:09 +00002152 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2153 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
2154 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002155
Antoine Pitrou480a1242010-04-28 21:37:09 +00002156 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
2157 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
2158 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002159
Antoine Pitroub5218772010-05-21 09:56:06 +00002160 # Server with specific SSL options
2161 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
2162 server_options=ssl.OP_NO_SSLv3)
2163 # Will choose TLSv1
2164 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2165 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2166 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2167 server_options=ssl.OP_NO_TLSv1)
2168
2169
Antoine Pitrou23df4832010-08-04 17:14:06 +00002170 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002171 def test_protocol_sslv3(self):
2172 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002173 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002174 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002175 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
2176 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2177 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002178 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2179 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002180 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2181 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002182 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002183 if no_sslv2_implies_sslv3_hello():
2184 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2185 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
2186 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002187
Antoine Pitrou23df4832010-08-04 17:14:06 +00002188 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002189 def test_protocol_tlsv1(self):
2190 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002191 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002192 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002193 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
2194 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
2195 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002196 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2197 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002198 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002199 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2200 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002201
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002202 @skip_if_broken_ubuntu_ssl
2203 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2204 "TLS version 1.1 not supported.")
2205 def test_protocol_tlsv1_1(self):
2206 """Connecting to a TLSv1.1 server with various client options.
2207 Testing against older TLS versions."""
2208 if support.verbose:
2209 sys.stdout.write("\n")
2210 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
2211 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2212 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
2213 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
2214 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2215 client_options=ssl.OP_NO_TLSv1_1)
2216
2217 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
2218 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2219 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2220
2221
2222 @skip_if_broken_ubuntu_ssl
2223 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2224 "TLS version 1.2 not supported.")
2225 def test_protocol_tlsv1_2(self):
2226 """Connecting to a TLSv1.2 server with various client options.
2227 Testing against older TLS versions."""
2228 if support.verbose:
2229 sys.stdout.write("\n")
2230 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
2231 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2232 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2233 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2234 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
2235 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
2236 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2237 client_options=ssl.OP_NO_TLSv1_2)
2238
2239 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
2240 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2241 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2242 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2243 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
2244
Antoine Pitrou480a1242010-04-28 21:37:09 +00002245 def test_starttls(self):
2246 """Switching from clear text to encrypted and back again."""
2247 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 +00002248
Trent Nelson78520002008-04-10 20:54:35 +00002249 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002250 ssl_version=ssl.PROTOCOL_TLSv1,
2251 starttls_server=True,
2252 chatty=True,
2253 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002254 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002255 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002256 s = socket.socket()
2257 s.setblocking(1)
2258 s.connect((HOST, server.port))
2259 if support.verbose:
2260 sys.stdout.write("\n")
2261 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002262 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002263 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002264 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002265 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002266 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002267 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002268 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002269 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002270 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002271 msg = outdata.strip().lower()
2272 if indata == b"STARTTLS" and msg.startswith(b"ok"):
2273 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002274 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002275 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002276 " client: read %r from server, starting TLS...\n"
2277 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002278 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2279 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00002280 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
2281 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002282 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002283 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002284 " client: read %r from server, ending TLS...\n"
2285 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002286 s = conn.unwrap()
2287 wrapped = False
2288 else:
2289 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002290 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002291 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002292 if support.verbose:
2293 sys.stdout.write(" client: closing connection.\n")
2294 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002295 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002296 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002297 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00002298 if wrapped:
2299 conn.close()
2300 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002301 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002302
Antoine Pitrou480a1242010-04-28 21:37:09 +00002303 def test_socketserver(self):
2304 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01002305 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002306 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002307 if support.verbose:
2308 sys.stdout.write('\n')
2309 with open(CERTFILE, 'rb') as f:
2310 d1 = f.read()
2311 d2 = ''
2312 # now fetch the same data from the HTTPS server
2313 url = 'https://%s:%d/%s' % (
2314 HOST, server.port, os.path.split(CERTFILE)[1])
2315 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002316 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00002317 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002318 if dlen and (int(dlen) > 0):
2319 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002320 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002321 sys.stdout.write(
2322 " client: read %d bytes from remote server '%s'\n"
2323 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002324 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002325 f.close()
2326 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002327
Antoine Pitrou480a1242010-04-28 21:37:09 +00002328 def test_asyncore_server(self):
2329 """Check the example asyncore integration."""
2330 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00002331
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002332 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002333 sys.stdout.write("\n")
2334
Antoine Pitrou480a1242010-04-28 21:37:09 +00002335 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00002336 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002337 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002338 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002339 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002340 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002341 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002342 " client: sending %r...\n" % indata)
2343 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002344 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002345 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002346 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002347 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002348 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002349 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2350 % (outdata[:20], len(outdata),
2351 indata[:20].lower(), len(indata)))
2352 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002353 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002354 sys.stdout.write(" client: closing connection.\n")
2355 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00002356 if support.verbose:
2357 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00002358
Antoine Pitrou480a1242010-04-28 21:37:09 +00002359 def test_recv_send(self):
2360 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00002361 if support.verbose:
2362 sys.stdout.write("\n")
2363
2364 server = ThreadedEchoServer(CERTFILE,
2365 certreqs=ssl.CERT_NONE,
2366 ssl_version=ssl.PROTOCOL_TLSv1,
2367 cacerts=CERTFILE,
2368 chatty=True,
2369 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002370 with server:
2371 s = ssl.wrap_socket(socket.socket(),
2372 server_side=False,
2373 certfile=CERTFILE,
2374 ca_certs=CERTFILE,
2375 cert_reqs=ssl.CERT_NONE,
2376 ssl_version=ssl.PROTOCOL_TLSv1)
2377 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002378 # helper methods for standardising recv* method signatures
2379 def _recv_into():
2380 b = bytearray(b"\0"*100)
2381 count = s.recv_into(b)
2382 return b[:count]
2383
2384 def _recvfrom_into():
2385 b = bytearray(b"\0"*100)
2386 count, addr = s.recvfrom_into(b)
2387 return b[:count]
2388
2389 # (name, method, whether to expect success, *args)
2390 send_methods = [
2391 ('send', s.send, True, []),
2392 ('sendto', s.sendto, False, ["some.address"]),
2393 ('sendall', s.sendall, True, []),
2394 ]
2395 recv_methods = [
2396 ('recv', s.recv, True, []),
2397 ('recvfrom', s.recvfrom, False, ["some.address"]),
2398 ('recv_into', _recv_into, True, []),
2399 ('recvfrom_into', _recvfrom_into, False, []),
2400 ]
2401 data_prefix = "PREFIX_"
2402
2403 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002404 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002405 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002406 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002407 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002408 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002409 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002410 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002411 "<<{outdata:r}>> ({nout:d}) received; "
2412 "expected <<{indata:r}>> ({nin:d})\n".format(
2413 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002414 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002415 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002416 )
2417 )
2418 except ValueError as e:
2419 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002420 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002421 "Failed to send with method <<{name:s}>>; "
2422 "expected to succeed.\n".format(name=meth_name)
2423 )
2424 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002425 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002426 "Method <<{name:s}>> failed with unexpected "
2427 "exception message: {exp:s}\n".format(
2428 name=meth_name, exp=e
2429 )
2430 )
2431
2432 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002433 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002434 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002435 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002436 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002437 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002438 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002439 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002440 "<<{outdata:r}>> ({nout:d}) received; "
2441 "expected <<{indata:r}>> ({nin:d})\n".format(
2442 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002443 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002444 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002445 )
2446 )
2447 except ValueError as e:
2448 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002449 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002450 "Failed to receive with method <<{name:s}>>; "
2451 "expected to succeed.\n".format(name=meth_name)
2452 )
2453 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002454 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002455 "Method <<{name:s}>> failed with unexpected "
2456 "exception message: {exp:s}\n".format(
2457 name=meth_name, exp=e
2458 )
2459 )
2460 # consume data
2461 s.read()
2462
Nick Coghlan513886a2011-08-28 00:00:27 +10002463 # Make sure sendmsg et al are disallowed to avoid
2464 # inadvertent disclosure of data and/or corruption
2465 # of the encrypted data stream
2466 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2467 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2468 self.assertRaises(NotImplementedError,
2469 s.recvmsg_into, bytearray(100))
2470
Antoine Pitrou480a1242010-04-28 21:37:09 +00002471 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002472 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002473
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002474 def test_handshake_timeout(self):
2475 # Issue #5103: SSL handshake must respect the socket timeout
2476 server = socket.socket(socket.AF_INET)
2477 host = "127.0.0.1"
2478 port = support.bind_port(server)
2479 started = threading.Event()
2480 finish = False
2481
2482 def serve():
2483 server.listen(5)
2484 started.set()
2485 conns = []
2486 while not finish:
2487 r, w, e = select.select([server], [], [], 0.1)
2488 if server in r:
2489 # Let the socket hang around rather than having
2490 # it closed by garbage collection.
2491 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002492 for sock in conns:
2493 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002494
2495 t = threading.Thread(target=serve)
2496 t.start()
2497 started.wait()
2498
2499 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002500 try:
2501 c = socket.socket(socket.AF_INET)
2502 c.settimeout(0.2)
2503 c.connect((host, port))
2504 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002505 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002506 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002507 finally:
2508 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002509 try:
2510 c = socket.socket(socket.AF_INET)
2511 c = ssl.wrap_socket(c)
2512 c.settimeout(0.2)
2513 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002514 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002515 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002516 finally:
2517 c.close()
2518 finally:
2519 finish = True
2520 t.join()
2521 server.close()
2522
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002523 def test_server_accept(self):
2524 # Issue #16357: accept() on a SSLSocket created through
2525 # SSLContext.wrap_socket().
2526 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2527 context.verify_mode = ssl.CERT_REQUIRED
2528 context.load_verify_locations(CERTFILE)
2529 context.load_cert_chain(CERTFILE)
2530 server = socket.socket(socket.AF_INET)
2531 host = "127.0.0.1"
2532 port = support.bind_port(server)
2533 server = context.wrap_socket(server, server_side=True)
2534
2535 evt = threading.Event()
2536 remote = None
2537 peer = None
2538 def serve():
2539 nonlocal remote, peer
2540 server.listen(5)
2541 # Block on the accept and wait on the connection to close.
2542 evt.set()
2543 remote, peer = server.accept()
2544 remote.recv(1)
2545
2546 t = threading.Thread(target=serve)
2547 t.start()
2548 # Client wait until server setup and perform a connect.
2549 evt.wait()
2550 client = context.wrap_socket(socket.socket())
2551 client.connect((host, port))
2552 client_addr = client.getsockname()
2553 client.close()
2554 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002555 remote.close()
2556 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002557 # Sanity checks.
2558 self.assertIsInstance(remote, ssl.SSLSocket)
2559 self.assertEqual(peer, client_addr)
2560
Antoine Pitrou242db722013-05-01 20:52:07 +02002561 def test_getpeercert_enotconn(self):
2562 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2563 with context.wrap_socket(socket.socket()) as sock:
2564 with self.assertRaises(OSError) as cm:
2565 sock.getpeercert()
2566 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2567
2568 def test_do_handshake_enotconn(self):
2569 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2570 with context.wrap_socket(socket.socket()) as sock:
2571 with self.assertRaises(OSError) as cm:
2572 sock.do_handshake()
2573 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2574
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002575 def test_default_ciphers(self):
2576 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2577 try:
2578 # Force a set of weak ciphers on our client context
2579 context.set_ciphers("DES")
2580 except ssl.SSLError:
2581 self.skipTest("no DES cipher available")
2582 with ThreadedEchoServer(CERTFILE,
2583 ssl_version=ssl.PROTOCOL_SSLv23,
2584 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002585 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002586 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002587 s.connect((HOST, server.port))
2588 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2589
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002590 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2591 def test_default_ecdh_curve(self):
2592 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2593 # should be enabled by default on SSL contexts.
2594 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2595 context.load_cert_chain(CERTFILE)
Antoine Pitrouc0430612014-04-16 18:33:39 +02002596 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2597 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2598 # our default cipher list should prefer ECDH-based ciphers
2599 # automatically.
2600 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2601 context.set_ciphers("ECCdraft:ECDH")
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002602 with ThreadedEchoServer(context=context) as server:
2603 with context.wrap_socket(socket.socket()) as s:
2604 s.connect((HOST, server.port))
2605 self.assertIn("ECDH", s.cipher()[0])
2606
Antoine Pitroud6494802011-07-21 01:11:30 +02002607 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2608 "'tls-unique' channel binding not available")
2609 def test_tls_unique_channel_binding(self):
2610 """Test tls-unique channel binding."""
2611 if support.verbose:
2612 sys.stdout.write("\n")
2613
2614 server = ThreadedEchoServer(CERTFILE,
2615 certreqs=ssl.CERT_NONE,
2616 ssl_version=ssl.PROTOCOL_TLSv1,
2617 cacerts=CERTFILE,
2618 chatty=True,
2619 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002620 with server:
2621 s = ssl.wrap_socket(socket.socket(),
2622 server_side=False,
2623 certfile=CERTFILE,
2624 ca_certs=CERTFILE,
2625 cert_reqs=ssl.CERT_NONE,
2626 ssl_version=ssl.PROTOCOL_TLSv1)
2627 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002628 # get the data
2629 cb_data = s.get_channel_binding("tls-unique")
2630 if support.verbose:
2631 sys.stdout.write(" got channel binding data: {0!r}\n"
2632 .format(cb_data))
2633
2634 # check if it is sane
2635 self.assertIsNotNone(cb_data)
2636 self.assertEqual(len(cb_data), 12) # True for TLSv1
2637
2638 # and compare with the peers version
2639 s.write(b"CB tls-unique\n")
2640 peer_data_repr = s.read().strip()
2641 self.assertEqual(peer_data_repr,
2642 repr(cb_data).encode("us-ascii"))
2643 s.close()
2644
2645 # now, again
2646 s = ssl.wrap_socket(socket.socket(),
2647 server_side=False,
2648 certfile=CERTFILE,
2649 ca_certs=CERTFILE,
2650 cert_reqs=ssl.CERT_NONE,
2651 ssl_version=ssl.PROTOCOL_TLSv1)
2652 s.connect((HOST, server.port))
2653 new_cb_data = s.get_channel_binding("tls-unique")
2654 if support.verbose:
2655 sys.stdout.write(" got another channel binding data: {0!r}\n"
2656 .format(new_cb_data))
2657 # is it really unique
2658 self.assertNotEqual(cb_data, new_cb_data)
2659 self.assertIsNotNone(cb_data)
2660 self.assertEqual(len(cb_data), 12) # True for TLSv1
2661 s.write(b"CB tls-unique\n")
2662 peer_data_repr = s.read().strip()
2663 self.assertEqual(peer_data_repr,
2664 repr(new_cb_data).encode("us-ascii"))
2665 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002666
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002667 def test_compression(self):
2668 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2669 context.load_cert_chain(CERTFILE)
2670 stats = server_params_test(context, context,
2671 chatty=True, connectionchatty=True)
2672 if support.verbose:
2673 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2674 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2675
2676 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2677 "ssl.OP_NO_COMPRESSION needed for this test")
2678 def test_compression_disabled(self):
2679 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2680 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002681 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002682 stats = server_params_test(context, context,
2683 chatty=True, connectionchatty=True)
2684 self.assertIs(stats['compression'], None)
2685
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002686 def test_dh_params(self):
2687 # Check we can get a connection with ephemeral Diffie-Hellman
2688 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2689 context.load_cert_chain(CERTFILE)
2690 context.load_dh_params(DHFILE)
2691 context.set_ciphers("kEDH")
2692 stats = server_params_test(context, context,
2693 chatty=True, connectionchatty=True)
2694 cipher = stats["cipher"][0]
2695 parts = cipher.split("-")
2696 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2697 self.fail("Non-DH cipher: " + cipher[0])
2698
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002699 def test_selected_npn_protocol(self):
2700 # selected_npn_protocol() is None unless NPN is used
2701 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2702 context.load_cert_chain(CERTFILE)
2703 stats = server_params_test(context, context,
2704 chatty=True, connectionchatty=True)
2705 self.assertIs(stats['client_npn_protocol'], None)
2706
2707 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2708 def test_npn_protocols(self):
2709 server_protocols = ['http/1.1', 'spdy/2']
2710 protocol_tests = [
2711 (['http/1.1', 'spdy/2'], 'http/1.1'),
2712 (['spdy/2', 'http/1.1'], 'http/1.1'),
2713 (['spdy/2', 'test'], 'spdy/2'),
2714 (['abc', 'def'], 'abc')
2715 ]
2716 for client_protocols, expected in protocol_tests:
2717 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2718 server_context.load_cert_chain(CERTFILE)
2719 server_context.set_npn_protocols(server_protocols)
2720 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2721 client_context.load_cert_chain(CERTFILE)
2722 client_context.set_npn_protocols(client_protocols)
2723 stats = server_params_test(client_context, server_context,
2724 chatty=True, connectionchatty=True)
2725
2726 msg = "failed trying %s (s) and %s (c).\n" \
2727 "was expecting %s, but got %%s from the %%s" \
2728 % (str(server_protocols), str(client_protocols),
2729 str(expected))
2730 client_result = stats['client_npn_protocol']
2731 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2732 server_result = stats['server_npn_protocols'][-1] \
2733 if len(stats['server_npn_protocols']) else 'nothing'
2734 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2735
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002736 def sni_contexts(self):
2737 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2738 server_context.load_cert_chain(SIGNED_CERTFILE)
2739 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2740 other_context.load_cert_chain(SIGNED_CERTFILE2)
2741 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2742 client_context.verify_mode = ssl.CERT_REQUIRED
2743 client_context.load_verify_locations(SIGNING_CA)
2744 return server_context, other_context, client_context
2745
2746 def check_common_name(self, stats, name):
2747 cert = stats['peercert']
2748 self.assertIn((('commonName', name),), cert['subject'])
2749
2750 @needs_sni
2751 def test_sni_callback(self):
2752 calls = []
2753 server_context, other_context, client_context = self.sni_contexts()
2754
2755 def servername_cb(ssl_sock, server_name, initial_context):
2756 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002757 if server_name is not None:
2758 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002759 server_context.set_servername_callback(servername_cb)
2760
2761 stats = server_params_test(client_context, server_context,
2762 chatty=True,
2763 sni_name='supermessage')
2764 # The hostname was fetched properly, and the certificate was
2765 # changed for the connection.
2766 self.assertEqual(calls, [("supermessage", server_context)])
2767 # CERTFILE4 was selected
2768 self.check_common_name(stats, 'fakehostname')
2769
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002770 calls = []
2771 # The callback is called with server_name=None
2772 stats = server_params_test(client_context, server_context,
2773 chatty=True,
2774 sni_name=None)
2775 self.assertEqual(calls, [(None, server_context)])
2776 self.check_common_name(stats, 'localhost')
2777
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002778 # Check disabling the callback
2779 calls = []
2780 server_context.set_servername_callback(None)
2781
2782 stats = server_params_test(client_context, server_context,
2783 chatty=True,
2784 sni_name='notfunny')
2785 # Certificate didn't change
2786 self.check_common_name(stats, 'localhost')
2787 self.assertEqual(calls, [])
2788
2789 @needs_sni
2790 def test_sni_callback_alert(self):
2791 # Returning a TLS alert is reflected to the connecting client
2792 server_context, other_context, client_context = self.sni_contexts()
2793
2794 def cb_returning_alert(ssl_sock, server_name, initial_context):
2795 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2796 server_context.set_servername_callback(cb_returning_alert)
2797
2798 with self.assertRaises(ssl.SSLError) as cm:
2799 stats = server_params_test(client_context, server_context,
2800 chatty=False,
2801 sni_name='supermessage')
2802 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2803
2804 @needs_sni
2805 def test_sni_callback_raising(self):
2806 # Raising fails the connection with a TLS handshake failure alert.
2807 server_context, other_context, client_context = self.sni_contexts()
2808
2809 def cb_raising(ssl_sock, server_name, initial_context):
2810 1/0
2811 server_context.set_servername_callback(cb_raising)
2812
2813 with self.assertRaises(ssl.SSLError) as cm, \
2814 support.captured_stderr() as stderr:
2815 stats = server_params_test(client_context, server_context,
2816 chatty=False,
2817 sni_name='supermessage')
2818 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2819 self.assertIn("ZeroDivisionError", stderr.getvalue())
2820
2821 @needs_sni
2822 def test_sni_callback_wrong_return_type(self):
2823 # Returning the wrong return type terminates the TLS connection
2824 # with an internal error alert.
2825 server_context, other_context, client_context = self.sni_contexts()
2826
2827 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2828 return "foo"
2829 server_context.set_servername_callback(cb_wrong_return_type)
2830
2831 with self.assertRaises(ssl.SSLError) as cm, \
2832 support.captured_stderr() as stderr:
2833 stats = server_params_test(client_context, server_context,
2834 chatty=False,
2835 sni_name='supermessage')
2836 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2837 self.assertIn("TypeError", stderr.getvalue())
2838
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002839 def test_read_write_after_close_raises_valuerror(self):
2840 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2841 context.verify_mode = ssl.CERT_REQUIRED
2842 context.load_verify_locations(CERTFILE)
2843 context.load_cert_chain(CERTFILE)
2844 server = ThreadedEchoServer(context=context, chatty=False)
2845
2846 with server:
2847 s = context.wrap_socket(socket.socket())
2848 s.connect((HOST, server.port))
2849 s.close()
2850
2851 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02002852 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002853
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002854
Thomas Woutersed03b412007-08-28 21:37:11 +00002855def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002856 if support.verbose:
2857 plats = {
2858 'Linux': platform.linux_distribution,
2859 'Mac': platform.mac_ver,
2860 'Windows': platform.win32_ver,
2861 }
2862 for name, func in plats.items():
2863 plat = func()
2864 if plat and plat[0]:
2865 plat = '%s %r' % (name, plat)
2866 break
2867 else:
2868 plat = repr(platform.platform())
2869 print("test_ssl: testing with %r %r" %
2870 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2871 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002872 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002873 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2874 try:
2875 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2876 except AttributeError:
2877 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002878
Antoine Pitrou152efa22010-05-16 18:19:27 +00002879 for filename in [
2880 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2881 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002882 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002883 BADCERT, BADKEY, EMPTYCERT]:
2884 if not os.path.exists(filename):
2885 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002886
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002887 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002888
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002889 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002890 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002891
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002892 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002893 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002894 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002895 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002896
Antoine Pitrou480a1242010-04-28 21:37:09 +00002897 try:
2898 support.run_unittest(*tests)
2899 finally:
2900 if _have_threads:
2901 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002902
2903if __name__ == "__main__":
2904 test_main()