blob: e71a40016019acbc3d09c7eed0607effbdac1db8 [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)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400284 # < 3.0
285 self.assertLess(n, 0x30000000)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000286 major, minor, fix, patch, status = t
287 self.assertGreaterEqual(major, 0)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400288 self.assertLess(major, 3)
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000289 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)
Antoine Pitroudfab9352014-07-21 18:35:01 -0400297 # Version string as returned by {Open,Libre}SSL, the format might change
298 if "LibreSSL" in s:
299 self.assertTrue(s.startswith("LibreSSL {:d}.{:d}".format(major, minor)),
300 (s, t))
301 else:
302 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
303 (s, t))
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000304
Antoine Pitrou9d543662010-04-23 23:10:32 +0000305 @support.cpython_only
306 def test_refcycle(self):
307 # Issue #7943: an SSL object doesn't create reference cycles with
308 # itself.
309 s = socket.socket(socket.AF_INET)
310 ss = ssl.wrap_socket(s)
311 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100312 with support.check_warnings(("", ResourceWarning)):
313 del ss
314 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000315
Antoine Pitroua468adc2010-09-14 14:43:44 +0000316 def test_wrapped_unconnected(self):
317 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200318 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000319 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100320 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100321 self.assertRaises(OSError, ss.recv, 1)
322 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
323 self.assertRaises(OSError, ss.recvfrom, 1)
324 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
325 self.assertRaises(OSError, ss.send, b'x')
326 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000327
Antoine Pitrou40f08742010-04-24 22:04:40 +0000328 def test_timeout(self):
329 # Issue #8524: when creating an SSL socket, the timeout of the
330 # original socket should be retained.
331 for timeout in (None, 0.0, 5.0):
332 s = socket.socket(socket.AF_INET)
333 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100334 with ssl.wrap_socket(s) as ss:
335 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000336
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000337 def test_errors(self):
338 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000339 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000340 "certfile must be specified",
341 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000342 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000343 "certfile must be specified for server-side operations",
344 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000345 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000346 "certfile must be specified for server-side operations",
347 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100348 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
349 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
350 s.connect, (HOST, 8080))
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=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +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=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000358 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200359 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000360 with socket.socket() as sock:
361 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000362 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000363
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000364 def test_match_hostname(self):
365 def ok(cert, hostname):
366 ssl.match_hostname(cert, hostname)
367 def fail(cert, hostname):
368 self.assertRaises(ssl.CertificateError,
369 ssl.match_hostname, cert, hostname)
370
371 cert = {'subject': ((('commonName', 'example.com'),),)}
372 ok(cert, 'example.com')
373 ok(cert, 'ExAmple.cOm')
374 fail(cert, 'www.example.com')
375 fail(cert, '.example.com')
376 fail(cert, 'example.org')
377 fail(cert, 'exampleXcom')
378
379 cert = {'subject': ((('commonName', '*.a.com'),),)}
380 ok(cert, 'foo.a.com')
381 fail(cert, 'bar.foo.a.com')
382 fail(cert, 'a.com')
383 fail(cert, 'Xa.com')
384 fail(cert, '.a.com')
385
Georg Brandl72c98d32013-10-27 07:16:53 +0100386 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000387 cert = {'subject': ((('commonName', 'f*.com'),),)}
388 ok(cert, 'foo.com')
389 ok(cert, 'f.com')
390 fail(cert, 'bar.com')
391 fail(cert, 'foo.a.com')
392 fail(cert, 'bar.foo.com')
393
Christian Heimes824f7f32013-08-17 00:54:47 +0200394 # NULL bytes are bad, CVE-2013-4073
395 cert = {'subject': ((('commonName',
396 'null.python.org\x00example.org'),),)}
397 ok(cert, 'null.python.org\x00example.org') # or raise an error?
398 fail(cert, 'example.org')
399 fail(cert, 'null.python.org')
400
Georg Brandl72c98d32013-10-27 07:16:53 +0100401 # error cases with wildcards
402 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
403 fail(cert, 'bar.foo.a.com')
404 fail(cert, 'a.com')
405 fail(cert, 'Xa.com')
406 fail(cert, '.a.com')
407
408 cert = {'subject': ((('commonName', 'a.*.com'),),)}
409 fail(cert, 'a.foo.com')
410 fail(cert, 'a..com')
411 fail(cert, 'a.com')
412
413 # wildcard doesn't match IDNA prefix 'xn--'
414 idna = 'püthon.python.org'.encode("idna").decode("ascii")
415 cert = {'subject': ((('commonName', idna),),)}
416 ok(cert, idna)
417 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
418 fail(cert, idna)
419 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
420 fail(cert, idna)
421
422 # wildcard in first fragment and IDNA A-labels in sequent fragments
423 # are supported.
424 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
425 cert = {'subject': ((('commonName', idna),),)}
426 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
427 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
428 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
429 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
430
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000431 # Slightly fake real-world example
432 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
433 'subject': ((('commonName', 'linuxfrz.org'),),),
434 'subjectAltName': (('DNS', 'linuxfr.org'),
435 ('DNS', 'linuxfr.com'),
436 ('othername', '<unsupported>'))}
437 ok(cert, 'linuxfr.org')
438 ok(cert, 'linuxfr.com')
439 # Not a "DNS" entry
440 fail(cert, '<unsupported>')
441 # When there is a subjectAltName, commonName isn't used
442 fail(cert, 'linuxfrz.org')
443
444 # A pristine real-world example
445 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
446 'subject': ((('countryName', 'US'),),
447 (('stateOrProvinceName', 'California'),),
448 (('localityName', 'Mountain View'),),
449 (('organizationName', 'Google Inc'),),
450 (('commonName', 'mail.google.com'),))}
451 ok(cert, 'mail.google.com')
452 fail(cert, 'gmail.com')
453 # Only commonName is considered
454 fail(cert, 'California')
455
456 # Neither commonName nor subjectAltName
457 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
458 'subject': ((('countryName', 'US'),),
459 (('stateOrProvinceName', 'California'),),
460 (('localityName', 'Mountain View'),),
461 (('organizationName', 'Google Inc'),))}
462 fail(cert, 'mail.google.com')
463
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200464 # No DNS entry in subjectAltName but a commonName
465 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
466 'subject': ((('countryName', 'US'),),
467 (('stateOrProvinceName', 'California'),),
468 (('localityName', 'Mountain View'),),
469 (('commonName', 'mail.google.com'),)),
470 'subjectAltName': (('othername', 'blabla'), )}
471 ok(cert, 'mail.google.com')
472
473 # No DNS entry subjectAltName and no commonName
474 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
475 'subject': ((('countryName', 'US'),),
476 (('stateOrProvinceName', 'California'),),
477 (('localityName', 'Mountain View'),),
478 (('organizationName', 'Google Inc'),)),
479 'subjectAltName': (('othername', 'blabla'),)}
480 fail(cert, 'google.com')
481
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000482 # Empty cert / no cert
483 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
484 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
485
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200486 # Issue #17980: avoid denials of service by refusing more than one
487 # wildcard per fragment.
488 cert = {'subject': ((('commonName', 'a*b.com'),),)}
489 ok(cert, 'axxb.com')
490 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100491 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200492 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
493 with self.assertRaises(ssl.CertificateError) as cm:
494 ssl.match_hostname(cert, 'axxbxxc.com')
495 self.assertIn("too many wildcards", str(cm.exception))
496
Antoine Pitroud5323212010-10-22 18:19:07 +0000497 def test_server_side(self):
498 # server_hostname doesn't work for server sockets
499 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000500 with socket.socket() as sock:
501 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
502 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000503
Antoine Pitroud6494802011-07-21 01:11:30 +0200504 def test_unknown_channel_binding(self):
505 # should raise ValueError for unknown type
506 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100507 with ssl.wrap_socket(s) as ss:
508 with self.assertRaises(ValueError):
509 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200510
511 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
512 "'tls-unique' channel binding not available")
513 def test_tls_unique_channel_binding(self):
514 # unconnected should return None for known type
515 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100516 with ssl.wrap_socket(s) as ss:
517 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200518 # the same for server-side
519 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100520 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
521 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200522
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600523 def test_dealloc_warn(self):
524 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
525 r = repr(ss)
526 with self.assertWarns(ResourceWarning) as cm:
527 ss = None
528 support.gc_collect()
529 self.assertIn(r, str(cm.warning.args[0]))
530
Christian Heimes6d7ad132013-06-09 18:02:55 +0200531 def test_get_default_verify_paths(self):
532 paths = ssl.get_default_verify_paths()
533 self.assertEqual(len(paths), 6)
534 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
535
536 with support.EnvironmentVarGuard() as env:
537 env["SSL_CERT_DIR"] = CAPATH
538 env["SSL_CERT_FILE"] = CERTFILE
539 paths = ssl.get_default_verify_paths()
540 self.assertEqual(paths.cafile, CERTFILE)
541 self.assertEqual(paths.capath, CAPATH)
542
Christian Heimes44109d72013-11-22 01:51:30 +0100543 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
544 def test_enum_certificates(self):
545 self.assertTrue(ssl.enum_certificates("CA"))
546 self.assertTrue(ssl.enum_certificates("ROOT"))
547
548 self.assertRaises(TypeError, ssl.enum_certificates)
549 self.assertRaises(WindowsError, ssl.enum_certificates, "")
550
Christian Heimesc2d65e12013-11-22 16:13:55 +0100551 trust_oids = set()
552 for storename in ("CA", "ROOT"):
553 store = ssl.enum_certificates(storename)
554 self.assertIsInstance(store, list)
555 for element in store:
556 self.assertIsInstance(element, tuple)
557 self.assertEqual(len(element), 3)
558 cert, enc, trust = element
559 self.assertIsInstance(cert, bytes)
560 self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
561 self.assertIsInstance(trust, (set, bool))
562 if isinstance(trust, set):
563 trust_oids.update(trust)
Christian Heimes44109d72013-11-22 01:51:30 +0100564
565 serverAuth = "1.3.6.1.5.5.7.3.1"
Christian Heimesc2d65e12013-11-22 16:13:55 +0100566 self.assertIn(serverAuth, trust_oids)
Christian Heimes6d7ad132013-06-09 18:02:55 +0200567
Christian Heimes46bebee2013-06-09 19:03:31 +0200568 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
Christian Heimes44109d72013-11-22 01:51:30 +0100569 def test_enum_crls(self):
570 self.assertTrue(ssl.enum_crls("CA"))
571 self.assertRaises(TypeError, ssl.enum_crls)
572 self.assertRaises(WindowsError, ssl.enum_crls, "")
Christian Heimes46bebee2013-06-09 19:03:31 +0200573
Christian Heimes44109d72013-11-22 01:51:30 +0100574 crls = ssl.enum_crls("CA")
575 self.assertIsInstance(crls, list)
576 for element in crls:
577 self.assertIsInstance(element, tuple)
578 self.assertEqual(len(element), 2)
579 self.assertIsInstance(element[0], bytes)
580 self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"})
Christian Heimes46bebee2013-06-09 19:03:31 +0200581
Christian Heimes46bebee2013-06-09 19:03:31 +0200582
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100583 def test_asn1object(self):
584 expected = (129, 'serverAuth', 'TLS Web Server Authentication',
585 '1.3.6.1.5.5.7.3.1')
586
587 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
588 self.assertEqual(val, expected)
589 self.assertEqual(val.nid, 129)
590 self.assertEqual(val.shortname, 'serverAuth')
591 self.assertEqual(val.longname, 'TLS Web Server Authentication')
592 self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1')
593 self.assertIsInstance(val, ssl._ASN1Object)
594 self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth')
595
596 val = ssl._ASN1Object.fromnid(129)
597 self.assertEqual(val, expected)
598 self.assertIsInstance(val, ssl._ASN1Object)
599 self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100600 with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
601 ssl._ASN1Object.fromnid(100000)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100602 for i in range(1000):
603 try:
604 obj = ssl._ASN1Object.fromnid(i)
605 except ValueError:
606 pass
607 else:
608 self.assertIsInstance(obj.nid, int)
609 self.assertIsInstance(obj.shortname, str)
610 self.assertIsInstance(obj.longname, str)
611 self.assertIsInstance(obj.oid, (str, type(None)))
612
613 val = ssl._ASN1Object.fromname('TLS Web Server Authentication')
614 self.assertEqual(val, expected)
615 self.assertIsInstance(val, ssl._ASN1Object)
616 self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
617 self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
618 expected)
Christian Heimes5398e1a2013-11-22 16:20:53 +0100619 with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
620 ssl._ASN1Object.fromname('serverauth')
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100621
Christian Heimes72d28502013-11-23 13:56:58 +0100622 def test_purpose_enum(self):
623 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1')
624 self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object)
625 self.assertEqual(ssl.Purpose.SERVER_AUTH, val)
626 self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129)
627 self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth')
628 self.assertEqual(ssl.Purpose.SERVER_AUTH.oid,
629 '1.3.6.1.5.5.7.3.1')
630
631 val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2')
632 self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object)
633 self.assertEqual(ssl.Purpose.CLIENT_AUTH, val)
634 self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130)
635 self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth')
636 self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid,
637 '1.3.6.1.5.5.7.3.2')
638
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100639 def test_unsupported_dtls(self):
640 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
641 self.addCleanup(s.close)
642 with self.assertRaises(NotImplementedError) as cx:
643 ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE)
644 self.assertEqual(str(cx.exception), "only stream sockets are supported")
645 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
646 with self.assertRaises(NotImplementedError) as cx:
647 ctx.wrap_socket(s)
648 self.assertEqual(str(cx.exception), "only stream sockets are supported")
649
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100650
Antoine Pitrou152efa22010-05-16 18:19:27 +0000651class ContextTests(unittest.TestCase):
652
Antoine Pitrou23df4832010-08-04 17:14:06 +0000653 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000654 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100655 for protocol in PROTOCOLS:
656 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000657 self.assertRaises(TypeError, ssl.SSLContext)
658 self.assertRaises(ValueError, ssl.SSLContext, -1)
659 self.assertRaises(ValueError, ssl.SSLContext, 42)
660
Antoine Pitrou23df4832010-08-04 17:14:06 +0000661 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000662 def test_protocol(self):
663 for proto in PROTOCOLS:
664 ctx = ssl.SSLContext(proto)
665 self.assertEqual(ctx.protocol, proto)
666
667 def test_ciphers(self):
668 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
669 ctx.set_ciphers("ALL")
670 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000671 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000672 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000673
Antoine Pitrou23df4832010-08-04 17:14:06 +0000674 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000675 def test_options(self):
676 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +0100677 # OP_ALL | OP_NO_SSLv2 is the default value
Antoine Pitroub5218772010-05-21 09:56:06 +0000678 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
679 ctx.options)
680 ctx.options |= ssl.OP_NO_SSLv3
681 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
682 ctx.options)
683 if can_clear_options():
684 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
685 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
686 ctx.options)
687 ctx.options = 0
688 self.assertEqual(0, ctx.options)
689 else:
690 with self.assertRaises(ValueError):
691 ctx.options = 0
692
Christian Heimes22587792013-11-21 23:56:13 +0100693 def test_verify_mode(self):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000694 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
695 # Default value
696 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
697 ctx.verify_mode = ssl.CERT_OPTIONAL
698 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
699 ctx.verify_mode = ssl.CERT_REQUIRED
700 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
701 ctx.verify_mode = ssl.CERT_NONE
702 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
703 with self.assertRaises(TypeError):
704 ctx.verify_mode = None
705 with self.assertRaises(ValueError):
706 ctx.verify_mode = 42
707
Christian Heimes2427b502013-11-23 11:24:32 +0100708 @unittest.skipUnless(have_verify_flags(),
709 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +0100710 def test_verify_flags(self):
711 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
712 # default value by OpenSSL
713 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
714 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
715 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF)
716 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN
717 self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN)
718 ctx.verify_flags = ssl.VERIFY_DEFAULT
719 self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT)
720 # supports any value
721 ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT
722 self.assertEqual(ctx.verify_flags,
723 ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT)
724 with self.assertRaises(TypeError):
725 ctx.verify_flags = None
726
Antoine Pitrou152efa22010-05-16 18:19:27 +0000727 def test_load_cert_chain(self):
728 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
729 # Combined key and cert in a single file
730 ctx.load_cert_chain(CERTFILE)
731 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
732 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200733 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000734 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000735 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000736 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000737 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000738 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000739 ctx.load_cert_chain(EMPTYCERT)
740 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000741 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000742 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
743 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
744 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_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(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000747 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000748 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000749 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000750 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
751 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000752 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000753 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000754 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200755 # Password protected key and cert
756 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
757 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
758 ctx.load_cert_chain(CERTFILE_PROTECTED,
759 password=bytearray(KEY_PASSWORD.encode()))
760 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
761 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
762 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
763 bytearray(KEY_PASSWORD.encode()))
764 with self.assertRaisesRegex(TypeError, "should be a string"):
765 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
766 with self.assertRaises(ssl.SSLError):
767 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
768 with self.assertRaisesRegex(ValueError, "cannot be longer"):
769 # openssl has a fixed limit on the password buffer.
770 # PEM_BUFSIZE is generally set to 1kb.
771 # Return a string larger than this.
772 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
773 # Password callback
774 def getpass_unicode():
775 return KEY_PASSWORD
776 def getpass_bytes():
777 return KEY_PASSWORD.encode()
778 def getpass_bytearray():
779 return bytearray(KEY_PASSWORD.encode())
780 def getpass_badpass():
781 return "badpass"
782 def getpass_huge():
783 return b'a' * (1024 * 1024)
784 def getpass_bad_type():
785 return 9
786 def getpass_exception():
787 raise Exception('getpass error')
788 class GetPassCallable:
789 def __call__(self):
790 return KEY_PASSWORD
791 def getpass(self):
792 return KEY_PASSWORD
793 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
794 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
795 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
796 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
797 ctx.load_cert_chain(CERTFILE_PROTECTED,
798 password=GetPassCallable().getpass)
799 with self.assertRaises(ssl.SSLError):
800 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
801 with self.assertRaisesRegex(ValueError, "cannot be longer"):
802 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
803 with self.assertRaisesRegex(TypeError, "must return a string"):
804 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
805 with self.assertRaisesRegex(Exception, "getpass error"):
806 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
807 # Make sure the password function isn't called if it isn't needed
808 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000809
810 def test_load_verify_locations(self):
811 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
812 ctx.load_verify_locations(CERTFILE)
813 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
814 ctx.load_verify_locations(BYTES_CERTFILE)
815 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
816 self.assertRaises(TypeError, ctx.load_verify_locations)
Christian Heimesefff7062013-11-21 03:35:02 +0100817 self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200818 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000819 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000820 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000821 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000822 ctx.load_verify_locations(BADCERT)
823 ctx.load_verify_locations(CERTFILE, CAPATH)
824 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
825
Victor Stinner80f75e62011-01-29 11:31:20 +0000826 # Issue #10989: crash if the second argument type is invalid
827 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
828
Christian Heimesefff7062013-11-21 03:35:02 +0100829 def test_load_verify_cadata(self):
830 # test cadata
831 with open(CAFILE_CACERT) as f:
832 cacert_pem = f.read()
833 cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem)
834 with open(CAFILE_NEURONIO) as f:
835 neuronio_pem = f.read()
836 neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem)
837
838 # test PEM
839 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
840 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0)
841 ctx.load_verify_locations(cadata=cacert_pem)
842 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1)
843 ctx.load_verify_locations(cadata=neuronio_pem)
844 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
845 # cert already in hash table
846 ctx.load_verify_locations(cadata=neuronio_pem)
847 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
848
849 # combined
850 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
851 combined = "\n".join((cacert_pem, neuronio_pem))
852 ctx.load_verify_locations(cadata=combined)
853 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
854
855 # with junk around the certs
856 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
857 combined = ["head", cacert_pem, "other", neuronio_pem, "again",
858 neuronio_pem, "tail"]
859 ctx.load_verify_locations(cadata="\n".join(combined))
860 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
861
862 # test DER
863 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
864 ctx.load_verify_locations(cadata=cacert_der)
865 ctx.load_verify_locations(cadata=neuronio_der)
866 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
867 # cert already in hash table
868 ctx.load_verify_locations(cadata=cacert_der)
869 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
870
871 # combined
872 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
873 combined = b"".join((cacert_der, neuronio_der))
874 ctx.load_verify_locations(cadata=combined)
875 self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2)
876
877 # error cases
878 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
879 self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object)
880
881 with self.assertRaisesRegex(ssl.SSLError, "no start line"):
882 ctx.load_verify_locations(cadata="broken")
883 with self.assertRaisesRegex(ssl.SSLError, "not enough data"):
884 ctx.load_verify_locations(cadata=b"broken")
885
886
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100887 def test_load_dh_params(self):
888 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
889 ctx.load_dh_params(DHFILE)
890 if os.name != 'nt':
891 ctx.load_dh_params(BYTES_DHFILE)
892 self.assertRaises(TypeError, ctx.load_dh_params)
893 self.assertRaises(TypeError, ctx.load_dh_params, None)
894 with self.assertRaises(FileNotFoundError) as cm:
895 ctx.load_dh_params(WRONGCERT)
896 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200897 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100898 ctx.load_dh_params(CERTFILE)
899
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000900 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000901 def test_session_stats(self):
902 for proto in PROTOCOLS:
903 ctx = ssl.SSLContext(proto)
904 self.assertEqual(ctx.session_stats(), {
905 'number': 0,
906 'connect': 0,
907 'connect_good': 0,
908 'connect_renegotiate': 0,
909 'accept': 0,
910 'accept_good': 0,
911 'accept_renegotiate': 0,
912 'hits': 0,
913 'misses': 0,
914 'timeouts': 0,
915 'cache_full': 0,
916 })
917
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000918 def test_set_default_verify_paths(self):
919 # There's not much we can do to test that it acts as expected,
920 # so just check it doesn't crash or raise an exception.
921 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
922 ctx.set_default_verify_paths()
923
Antoine Pitrou501da612011-12-21 09:27:41 +0100924 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100925 def test_set_ecdh_curve(self):
926 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
927 ctx.set_ecdh_curve("prime256v1")
928 ctx.set_ecdh_curve(b"prime256v1")
929 self.assertRaises(TypeError, ctx.set_ecdh_curve)
930 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
931 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
932 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
933
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100934 @needs_sni
935 def test_sni_callback(self):
936 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
937
938 # set_servername_callback expects a callable, or None
939 self.assertRaises(TypeError, ctx.set_servername_callback)
940 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
941 self.assertRaises(TypeError, ctx.set_servername_callback, "")
942 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
943
944 def dummycallback(sock, servername, ctx):
945 pass
946 ctx.set_servername_callback(None)
947 ctx.set_servername_callback(dummycallback)
948
949 @needs_sni
950 def test_sni_callback_refcycle(self):
951 # Reference cycles through the servername callback are detected
952 # and cleared.
953 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
954 def dummycallback(sock, servername, ctx, cycle=ctx):
955 pass
956 ctx.set_servername_callback(dummycallback)
957 wr = weakref.ref(ctx)
958 del ctx, dummycallback
959 gc.collect()
960 self.assertIs(wr(), None)
961
Christian Heimes9a5395a2013-06-17 15:44:12 +0200962 def test_cert_store_stats(self):
963 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
964 self.assertEqual(ctx.cert_store_stats(),
965 {'x509_ca': 0, 'crl': 0, 'x509': 0})
966 ctx.load_cert_chain(CERTFILE)
967 self.assertEqual(ctx.cert_store_stats(),
968 {'x509_ca': 0, 'crl': 0, 'x509': 0})
969 ctx.load_verify_locations(CERTFILE)
970 self.assertEqual(ctx.cert_store_stats(),
971 {'x509_ca': 0, 'crl': 0, 'x509': 1})
972 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
973 self.assertEqual(ctx.cert_store_stats(),
974 {'x509_ca': 1, 'crl': 0, 'x509': 2})
975
976 def test_get_ca_certs(self):
977 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
978 self.assertEqual(ctx.get_ca_certs(), [])
979 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
980 ctx.load_verify_locations(CERTFILE)
981 self.assertEqual(ctx.get_ca_certs(), [])
982 # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
983 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
984 self.assertEqual(ctx.get_ca_certs(),
985 [{'issuer': ((('organizationName', 'Root CA'),),
986 (('organizationalUnitName', 'http://www.cacert.org'),),
987 (('commonName', 'CA Cert Signing Authority'),),
988 (('emailAddress', 'support@cacert.org'),)),
989 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
990 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
991 'serialNumber': '00',
Christian Heimesbd3a7f92013-11-21 03:40:15 +0100992 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',),
Christian Heimes9a5395a2013-06-17 15:44:12 +0200993 'subject': ((('organizationName', 'Root CA'),),
994 (('organizationalUnitName', 'http://www.cacert.org'),),
995 (('commonName', 'CA Cert Signing Authority'),),
996 (('emailAddress', 'support@cacert.org'),)),
997 'version': 3}])
998
999 with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
1000 pem = f.read()
1001 der = ssl.PEM_cert_to_DER_cert(pem)
1002 self.assertEqual(ctx.get_ca_certs(True), [der])
1003
Christian Heimes72d28502013-11-23 13:56:58 +01001004 def test_load_default_certs(self):
1005 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1006 ctx.load_default_certs()
1007
1008 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1009 ctx.load_default_certs(ssl.Purpose.SERVER_AUTH)
1010 ctx.load_default_certs()
1011
1012 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1013 ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH)
1014
1015 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1016 self.assertRaises(TypeError, ctx.load_default_certs, None)
1017 self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH')
1018
Benjamin Peterson91244e02014-10-03 18:17:15 -04001019 @unittest.skipIf(sys.platform == "win32", "not-Windows specific")
Benjamin Peterson5915b0f2014-10-03 17:27:05 -04001020 def test_load_default_certs_env(self):
1021 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1022 with support.EnvironmentVarGuard() as env:
1023 env["SSL_CERT_DIR"] = CAPATH
1024 env["SSL_CERT_FILE"] = CERTFILE
1025 ctx.load_default_certs()
1026 self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
1027
Benjamin Peterson91244e02014-10-03 18:17:15 -04001028 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
1029 def test_load_default_certs_env_windows(self):
1030 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1031 ctx.load_default_certs()
1032 stats = ctx.cert_store_stats()
1033
1034 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1035 with support.EnvironmentVarGuard() as env:
1036 env["SSL_CERT_DIR"] = CAPATH
1037 env["SSL_CERT_FILE"] = CERTFILE
1038 ctx.load_default_certs()
1039 stats["x509"] += 1
1040 self.assertEqual(ctx.cert_store_stats(), stats)
1041
Christian Heimes4c05b472013-11-23 15:58:30 +01001042 def test_create_default_context(self):
1043 ctx = ssl.create_default_context()
Donald Stufft6a2ba942014-03-23 19:05:28 -04001044 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001045 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001046 self.assertTrue(ctx.check_hostname)
Christian Heimes4c05b472013-11-23 15:58:30 +01001047 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001048 self.assertEqual(
1049 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1050 getattr(ssl, "OP_NO_COMPRESSION", 0),
1051 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001052
1053 with open(SIGNING_CA) as f:
1054 cadata = f.read()
1055 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1056 cadata=cadata)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001057 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001058 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1059 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001060 self.assertEqual(
1061 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1062 getattr(ssl, "OP_NO_COMPRESSION", 0),
1063 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001064
1065 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001066 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001067 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1068 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001069 self.assertEqual(
1070 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1071 getattr(ssl, "OP_NO_COMPRESSION", 0),
1072 )
1073 self.assertEqual(
1074 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1075 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1076 )
1077 self.assertEqual(
1078 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1079 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1080 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001081
Christian Heimes67986f92013-11-23 22:43:47 +01001082 def test__create_stdlib_context(self):
1083 ctx = ssl._create_stdlib_context()
1084 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1085 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001086 self.assertFalse(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001087 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1088
1089 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1090 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1091 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1092 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1093
1094 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001095 cert_reqs=ssl.CERT_REQUIRED,
1096 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001097 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1098 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001099 self.assertTrue(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001100 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1101
1102 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1103 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1104 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1105 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Christian Heimes4c05b472013-11-23 15:58:30 +01001106
Christian Heimes1aa9a752013-12-02 02:41:19 +01001107 def test_check_hostname(self):
1108 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1109 self.assertFalse(ctx.check_hostname)
1110
1111 # Requires CERT_REQUIRED or CERT_OPTIONAL
1112 with self.assertRaises(ValueError):
1113 ctx.check_hostname = True
1114 ctx.verify_mode = ssl.CERT_REQUIRED
1115 self.assertFalse(ctx.check_hostname)
1116 ctx.check_hostname = True
1117 self.assertTrue(ctx.check_hostname)
1118
1119 ctx.verify_mode = ssl.CERT_OPTIONAL
1120 ctx.check_hostname = True
1121 self.assertTrue(ctx.check_hostname)
1122
1123 # Cannot set CERT_NONE with check_hostname enabled
1124 with self.assertRaises(ValueError):
1125 ctx.verify_mode = ssl.CERT_NONE
1126 ctx.check_hostname = False
1127 self.assertFalse(ctx.check_hostname)
1128
Antoine Pitrou152efa22010-05-16 18:19:27 +00001129
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001130class SSLErrorTests(unittest.TestCase):
1131
1132 def test_str(self):
1133 # The str() of a SSLError doesn't include the errno
1134 e = ssl.SSLError(1, "foo")
1135 self.assertEqual(str(e), "foo")
1136 self.assertEqual(e.errno, 1)
1137 # Same for a subclass
1138 e = ssl.SSLZeroReturnError(1, "foo")
1139 self.assertEqual(str(e), "foo")
1140 self.assertEqual(e.errno, 1)
1141
1142 def test_lib_reason(self):
1143 # Test the library and reason attributes
1144 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1145 with self.assertRaises(ssl.SSLError) as cm:
1146 ctx.load_dh_params(CERTFILE)
1147 self.assertEqual(cm.exception.library, 'PEM')
1148 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1149 s = str(cm.exception)
1150 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1151
1152 def test_subclass(self):
1153 # Check that the appropriate SSLError subclass is raised
1154 # (this only tests one of them)
1155 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1156 with socket.socket() as s:
1157 s.bind(("127.0.0.1", 0))
1158 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001159 c = socket.socket()
1160 c.connect(s.getsockname())
1161 c.setblocking(False)
1162 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001163 with self.assertRaises(ssl.SSLWantReadError) as cm:
1164 c.do_handshake()
1165 s = str(cm.exception)
1166 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1167 # For compatibility
1168 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1169
1170
Bill Janssen6e027db2007-11-15 22:23:56 +00001171class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001172
Antoine Pitrou480a1242010-04-28 21:37:09 +00001173 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001174 with support.transient_internet("svn.python.org"):
1175 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1176 cert_reqs=ssl.CERT_NONE)
1177 try:
1178 s.connect(("svn.python.org", 443))
1179 self.assertEqual({}, s.getpeercert())
1180 finally:
1181 s.close()
1182
1183 # this should fail because we have no verification certs
1184 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1185 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001186 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1187 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001188 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001189
Antoine Pitrou350c7222010-09-09 13:31:46 +00001190 # this should succeed because we specify the root cert
1191 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1192 cert_reqs=ssl.CERT_REQUIRED,
1193 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1194 try:
1195 s.connect(("svn.python.org", 443))
1196 self.assertTrue(s.getpeercert())
1197 finally:
1198 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001199
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001200 def test_connect_ex(self):
1201 # Issue #11326: check connect_ex() implementation
1202 with support.transient_internet("svn.python.org"):
1203 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1204 cert_reqs=ssl.CERT_REQUIRED,
1205 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1206 try:
1207 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
1208 self.assertTrue(s.getpeercert())
1209 finally:
1210 s.close()
1211
1212 def test_non_blocking_connect_ex(self):
1213 # Issue #11326: non-blocking connect_ex() should allow handshake
1214 # to proceed after the socket gets ready.
1215 with support.transient_internet("svn.python.org"):
1216 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1217 cert_reqs=ssl.CERT_REQUIRED,
1218 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1219 do_handshake_on_connect=False)
1220 try:
1221 s.setblocking(False)
1222 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +00001223 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1224 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001225 # Wait for connect to finish
1226 select.select([], [s], [], 5.0)
1227 # Non-blocking handshake
1228 while True:
1229 try:
1230 s.do_handshake()
1231 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001232 except ssl.SSLWantReadError:
1233 select.select([s], [], [], 5.0)
1234 except ssl.SSLWantWriteError:
1235 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001236 # SSL established
1237 self.assertTrue(s.getpeercert())
1238 finally:
1239 s.close()
1240
Antoine Pitroub4410db2011-05-18 18:51:06 +02001241 def test_timeout_connect_ex(self):
1242 # Issue #12065: on a timeout, connect_ex() should return the original
1243 # errno (mimicking the behaviour of non-SSL sockets).
1244 with support.transient_internet("svn.python.org"):
1245 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1246 cert_reqs=ssl.CERT_REQUIRED,
1247 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1248 do_handshake_on_connect=False)
1249 try:
1250 s.settimeout(0.0000001)
1251 rc = s.connect_ex(('svn.python.org', 443))
1252 if rc == 0:
1253 self.skipTest("svn.python.org responded too quickly")
1254 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1255 finally:
1256 s.close()
1257
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001258 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +01001259 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001260 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1261 cert_reqs=ssl.CERT_REQUIRED,
1262 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1263 try:
Christian Heimesde570742013-12-16 21:15:44 +01001264 rc = s.connect_ex(("svn.python.org", 444))
1265 # Issue #19919: Windows machines or VMs hosted on Windows
1266 # machines sometimes return EWOULDBLOCK.
1267 self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001268 finally:
1269 s.close()
1270
Antoine Pitrou152efa22010-05-16 18:19:27 +00001271 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001272 with support.transient_internet("svn.python.org"):
1273 # Same as test_connect, but with a separately created context
1274 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1275 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1276 s.connect(("svn.python.org", 443))
1277 try:
1278 self.assertEqual({}, s.getpeercert())
1279 finally:
1280 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +00001281 # Same with a server hostname
1282 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1283 server_hostname="svn.python.org")
1284 if ssl.HAS_SNI:
1285 s.connect(("svn.python.org", 443))
1286 s.close()
1287 else:
1288 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001289 # This should fail because we have no verification certs
1290 ctx.verify_mode = ssl.CERT_REQUIRED
1291 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +00001292 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +00001293 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001294 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001295 # This should succeed because we specify the root cert
1296 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
1297 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1298 s.connect(("svn.python.org", 443))
1299 try:
1300 cert = s.getpeercert()
1301 self.assertTrue(cert)
1302 finally:
1303 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001304
1305 def test_connect_capath(self):
1306 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00001307 # NOTE: the subject hashing algorithm has been changed between
1308 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1309 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00001310 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +00001311 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(capath=CAPATH)
1315 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1316 s.connect(("svn.python.org", 443))
1317 try:
1318 cert = s.getpeercert()
1319 self.assertTrue(cert)
1320 finally:
1321 s.close()
1322 # Same with a bytes `capath` argument
1323 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1324 ctx.verify_mode = ssl.CERT_REQUIRED
1325 ctx.load_verify_locations(capath=BYTES_CAPATH)
1326 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1327 s.connect(("svn.python.org", 443))
1328 try:
1329 cert = s.getpeercert()
1330 self.assertTrue(cert)
1331 finally:
1332 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001333
Christian Heimesefff7062013-11-21 03:35:02 +01001334 def test_connect_cadata(self):
1335 with open(CAFILE_CACERT) as f:
1336 pem = f.read()
1337 der = ssl.PEM_cert_to_DER_cert(pem)
1338 with support.transient_internet("svn.python.org"):
1339 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1340 ctx.verify_mode = ssl.CERT_REQUIRED
1341 ctx.load_verify_locations(cadata=pem)
1342 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1343 s.connect(("svn.python.org", 443))
1344 cert = s.getpeercert()
1345 self.assertTrue(cert)
1346
1347 # same with DER
1348 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1349 ctx.verify_mode = ssl.CERT_REQUIRED
1350 ctx.load_verify_locations(cadata=der)
1351 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1352 s.connect(("svn.python.org", 443))
1353 cert = s.getpeercert()
1354 self.assertTrue(cert)
1355
Antoine Pitroue3220242010-04-24 11:13:53 +00001356 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1357 def test_makefile_close(self):
1358 # Issue #5238: creating a file-like object with makefile() shouldn't
1359 # delay closing the underlying "real socket" (here tested with its
1360 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +00001361 with support.transient_internet("svn.python.org"):
1362 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1363 ss.connect(("svn.python.org", 443))
1364 fd = ss.fileno()
1365 f = ss.makefile()
1366 f.close()
1367 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +00001368 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001369 # Closing the SSL socket should close the fd too
1370 ss.close()
1371 gc.collect()
1372 with self.assertRaises(OSError) as e:
1373 os.read(fd, 0)
1374 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001375
Antoine Pitrou480a1242010-04-28 21:37:09 +00001376 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001377 with support.transient_internet("svn.python.org"):
1378 s = socket.socket(socket.AF_INET)
1379 s.connect(("svn.python.org", 443))
1380 s.setblocking(False)
1381 s = ssl.wrap_socket(s,
1382 cert_reqs=ssl.CERT_NONE,
1383 do_handshake_on_connect=False)
1384 count = 0
1385 while True:
1386 try:
1387 count += 1
1388 s.do_handshake()
1389 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001390 except ssl.SSLWantReadError:
1391 select.select([s], [], [])
1392 except ssl.SSLWantWriteError:
1393 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +00001394 s.close()
1395 if support.verbose:
1396 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001397
Antoine Pitrou480a1242010-04-28 21:37:09 +00001398 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +02001399 def _test_get_server_certificate(host, port, cert=None):
1400 with support.transient_internet(host):
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001401 pem = ssl.get_server_certificate((host, port),
1402 ssl.PROTOCOL_SSLv23)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001403 if not pem:
1404 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001405
Antoine Pitrou15399c32011-04-28 19:23:55 +02001406 try:
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001407 pem = ssl.get_server_certificate((host, port),
1408 ssl.PROTOCOL_SSLv23,
1409 ca_certs=CERTFILE)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001410 except ssl.SSLError as x:
1411 #should fail
1412 if support.verbose:
1413 sys.stdout.write("%s\n" % x)
1414 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001415 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1416
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001417 pem = ssl.get_server_certificate((host, port),
1418 ssl.PROTOCOL_SSLv23,
1419 ca_certs=cert)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001420 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001421 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001422 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001423 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001424
Antoine Pitrou15399c32011-04-28 19:23:55 +02001425 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
1426 if support.IPV6_ENABLED:
1427 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001428
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001429 def test_ciphers(self):
1430 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001431 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001432 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1433 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1434 s.connect(remote)
1435 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1436 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1437 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001438 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001439 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001440 with socket.socket(socket.AF_INET) as sock:
1441 s = ssl.wrap_socket(sock,
1442 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1443 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001444
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001445 def test_algorithms(self):
1446 # Issue #8484: all algorithms should be available when verifying a
1447 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001448 # SHA256 was added in OpenSSL 0.9.8
1449 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1450 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001451 # sha256.tbs-internet.com needs SNI to use the correct certificate
1452 if not ssl.HAS_SNI:
1453 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001454 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1455 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001456 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001457 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001458 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1459 ctx.verify_mode = ssl.CERT_REQUIRED
1460 ctx.load_verify_locations(sha256_cert)
1461 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1462 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001463 try:
1464 s.connect(remote)
1465 if support.verbose:
1466 sys.stdout.write("\nCipher with %r is %r\n" %
1467 (remote, s.cipher()))
1468 sys.stdout.write("Certificate is:\n%s\n" %
1469 pprint.pformat(s.getpeercert()))
1470 finally:
1471 s.close()
1472
Christian Heimes9a5395a2013-06-17 15:44:12 +02001473 def test_get_ca_certs_capath(self):
1474 # capath certs are loaded on request
1475 with support.transient_internet("svn.python.org"):
1476 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1477 ctx.verify_mode = ssl.CERT_REQUIRED
1478 ctx.load_verify_locations(capath=CAPATH)
1479 self.assertEqual(ctx.get_ca_certs(), [])
1480 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1481 s.connect(("svn.python.org", 443))
1482 try:
1483 cert = s.getpeercert()
1484 self.assertTrue(cert)
1485 finally:
1486 s.close()
1487 self.assertEqual(len(ctx.get_ca_certs()), 1)
1488
Christian Heimes575596e2013-12-15 21:49:17 +01001489 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01001490 def test_context_setget(self):
1491 # Check that the context of a connected socket can be replaced.
1492 with support.transient_internet("svn.python.org"):
1493 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1494 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1495 s = socket.socket(socket.AF_INET)
1496 with ctx1.wrap_socket(s) as ss:
1497 ss.connect(("svn.python.org", 443))
1498 self.assertIs(ss.context, ctx1)
1499 self.assertIs(ss._sslobj.context, ctx1)
1500 ss.context = ctx2
1501 self.assertIs(ss.context, ctx2)
1502 self.assertIs(ss._sslobj.context, ctx2)
1503
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001504try:
1505 import threading
1506except ImportError:
1507 _have_threads = False
1508else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001509 _have_threads = True
1510
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001511 from test.ssl_servers import make_https_server
1512
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001513 class ThreadedEchoServer(threading.Thread):
1514
1515 class ConnectionHandler(threading.Thread):
1516
1517 """A mildly complicated class, because we want it to work both
1518 with and without the SSL wrapper around the socket connection, so
1519 that we can test the STARTTLS functionality."""
1520
Bill Janssen6e027db2007-11-15 22:23:56 +00001521 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001522 self.server = server
1523 self.running = False
1524 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001525 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001526 self.sock.setblocking(1)
1527 self.sslconn = None
1528 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001529 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001530
Antoine Pitrou480a1242010-04-28 21:37:09 +00001531 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001532 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001533 self.sslconn = self.server.context.wrap_socket(
1534 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001535 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001536 except (ssl.SSLError, ConnectionResetError) as e:
1537 # We treat ConnectionResetError as though it were an
1538 # SSLError - OpenSSL on Ubuntu abruptly closes the
1539 # connection when asked to use an unsupported protocol.
1540 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001541 # XXX Various errors can have happened here, for example
1542 # a mismatching protocol version, an invalid certificate,
1543 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001544 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001545 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001546 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001547 self.running = False
1548 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001549 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001550 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001551 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001552 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001553 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001554 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001555 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1556 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001557 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001558 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1559 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001560 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001561 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001562 sys.stdout.write(" server: selected protocol is now "
1563 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001564 return True
1565
1566 def read(self):
1567 if self.sslconn:
1568 return self.sslconn.read()
1569 else:
1570 return self.sock.recv(1024)
1571
1572 def write(self, bytes):
1573 if self.sslconn:
1574 return self.sslconn.write(bytes)
1575 else:
1576 return self.sock.send(bytes)
1577
1578 def close(self):
1579 if self.sslconn:
1580 self.sslconn.close()
1581 else:
1582 self.sock.close()
1583
Antoine Pitrou480a1242010-04-28 21:37:09 +00001584 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001585 self.running = True
1586 if not self.server.starttls_server:
1587 if not self.wrap_conn():
1588 return
1589 while self.running:
1590 try:
1591 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001592 stripped = msg.strip()
1593 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001594 # eof, so quit this handler
1595 self.running = False
1596 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001597 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001598 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001599 sys.stdout.write(" server: client closed connection\n")
1600 self.close()
1601 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001602 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001603 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001604 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001605 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001606 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001607 if not self.wrap_conn():
1608 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001609 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001610 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001611 if support.verbose and self.server.connectionchatty:
1612 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001613 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001614 self.sock = self.sslconn.unwrap()
1615 self.sslconn = None
1616 if support.verbose and self.server.connectionchatty:
1617 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001618 elif stripped == b'CB tls-unique':
1619 if support.verbose and self.server.connectionchatty:
1620 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1621 data = self.sslconn.get_channel_binding("tls-unique")
1622 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001623 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001624 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001625 self.server.connectionchatty):
1626 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001627 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1628 % (msg, ctype, msg.lower(), ctype))
1629 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001630 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001631 if self.server.chatty:
1632 handle_error("Test server failure:\n")
1633 self.close()
1634 self.running = False
1635 # normally, we'd just stop here, but for the test
1636 # harness, we want to stop the server
1637 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001638
Antoine Pitroub5218772010-05-21 09:56:06 +00001639 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001640 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001641 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001642 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001643 if context:
1644 self.context = context
1645 else:
1646 self.context = ssl.SSLContext(ssl_version
1647 if ssl_version is not None
1648 else ssl.PROTOCOL_TLSv1)
1649 self.context.verify_mode = (certreqs if certreqs is not None
1650 else ssl.CERT_NONE)
1651 if cacerts:
1652 self.context.load_verify_locations(cacerts)
1653 if certificate:
1654 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001655 if npn_protocols:
1656 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001657 if ciphers:
1658 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001659 self.chatty = chatty
1660 self.connectionchatty = connectionchatty
1661 self.starttls_server = starttls_server
1662 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001663 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001664 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001665 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001666 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001667 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001668 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001669 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001670
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001671 def __enter__(self):
1672 self.start(threading.Event())
1673 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001674 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001675
1676 def __exit__(self, *args):
1677 self.stop()
1678 self.join()
1679
Antoine Pitrou480a1242010-04-28 21:37:09 +00001680 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001681 self.flag = flag
1682 threading.Thread.start(self)
1683
Antoine Pitrou480a1242010-04-28 21:37:09 +00001684 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001685 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001686 self.sock.listen(5)
1687 self.active = True
1688 if self.flag:
1689 # signal an event
1690 self.flag.set()
1691 while self.active:
1692 try:
1693 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001694 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001695 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001696 + repr(connaddr) + '\n')
1697 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001698 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001699 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001700 except socket.timeout:
1701 pass
1702 except KeyboardInterrupt:
1703 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001704 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001705
Antoine Pitrou480a1242010-04-28 21:37:09 +00001706 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001707 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001708
Bill Janssen54cc54c2007-12-14 22:08:56 +00001709 class AsyncoreEchoServer(threading.Thread):
1710
1711 # this one's based on asyncore.dispatcher
1712
1713 class EchoServer (asyncore.dispatcher):
1714
1715 class ConnectionHandler (asyncore.dispatcher_with_send):
1716
1717 def __init__(self, conn, certfile):
1718 self.socket = ssl.wrap_socket(conn, server_side=True,
1719 certfile=certfile,
1720 do_handshake_on_connect=False)
1721 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001722 self._ssl_accepting = True
1723 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001724
1725 def readable(self):
1726 if isinstance(self.socket, ssl.SSLSocket):
1727 while self.socket.pending() > 0:
1728 self.handle_read_event()
1729 return True
1730
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001731 def _do_ssl_handshake(self):
1732 try:
1733 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001734 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1735 return
1736 except ssl.SSLEOFError:
1737 return self.handle_close()
1738 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001739 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001740 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001741 if err.args[0] == errno.ECONNABORTED:
1742 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001743 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001744 self._ssl_accepting = False
1745
1746 def handle_read(self):
1747 if self._ssl_accepting:
1748 self._do_ssl_handshake()
1749 else:
1750 data = self.recv(1024)
1751 if support.verbose:
1752 sys.stdout.write(" server: read %s from client\n" % repr(data))
1753 if not data:
1754 self.close()
1755 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001756 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001757
1758 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001759 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001760 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001761 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1762
1763 def handle_error(self):
1764 raise
1765
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001766 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001767 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001768 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1769 self.port = support.bind_port(sock, '')
1770 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001771 self.listen(5)
1772
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001773 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001774 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001775 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1776 self.ConnectionHandler(sock_obj, self.certfile)
1777
1778 def handle_error(self):
1779 raise
1780
Trent Nelson78520002008-04-10 20:54:35 +00001781 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001782 self.flag = None
1783 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001784 self.server = self.EchoServer(certfile)
1785 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001786 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001787 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001788
1789 def __str__(self):
1790 return "<%s %s>" % (self.__class__.__name__, self.server)
1791
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001792 def __enter__(self):
1793 self.start(threading.Event())
1794 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001795 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001796
1797 def __exit__(self, *args):
1798 if support.verbose:
1799 sys.stdout.write(" cleanup: stopping server.\n")
1800 self.stop()
1801 if support.verbose:
1802 sys.stdout.write(" cleanup: joining server thread.\n")
1803 self.join()
1804 if support.verbose:
1805 sys.stdout.write(" cleanup: successfully joined.\n")
1806
Bill Janssen54cc54c2007-12-14 22:08:56 +00001807 def start (self, flag=None):
1808 self.flag = flag
1809 threading.Thread.start(self)
1810
Antoine Pitrou480a1242010-04-28 21:37:09 +00001811 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001812 self.active = True
1813 if self.flag:
1814 self.flag.set()
1815 while self.active:
1816 try:
1817 asyncore.loop(1)
1818 except:
1819 pass
1820
Antoine Pitrou480a1242010-04-28 21:37:09 +00001821 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001822 self.active = False
1823 self.server.close()
1824
Antoine Pitrou480a1242010-04-28 21:37:09 +00001825 def bad_cert_test(certfile):
1826 """
1827 Launch a server with CERT_REQUIRED, and check that trying to
1828 connect to it with the given client certificate fails.
1829 """
Trent Nelson78520002008-04-10 20:54:35 +00001830 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001831 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001832 cacerts=CERTFILE, chatty=False,
1833 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001834 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001835 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001836 with socket.socket() as sock:
1837 s = ssl.wrap_socket(sock,
1838 certfile=certfile,
1839 ssl_version=ssl.PROTOCOL_TLSv1)
1840 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001841 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001842 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001843 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001844 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001845 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001846 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001847 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001848 if x.errno != errno.ENOENT:
1849 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001850 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001851 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001852 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001853 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001854
Antoine Pitroub5218772010-05-21 09:56:06 +00001855 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001856 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001857 """
1858 Launch a server, connect a client to it and try various reads
1859 and writes.
1860 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001861 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001862 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001863 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001864 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001865 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001866 with client_context.wrap_socket(socket.socket(),
1867 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001868 s.connect((HOST, server.port))
1869 for arg in [indata, bytearray(indata), memoryview(indata)]:
1870 if connectionchatty:
1871 if support.verbose:
1872 sys.stdout.write(
1873 " client: sending %r...\n" % indata)
1874 s.write(arg)
1875 outdata = s.read()
1876 if connectionchatty:
1877 if support.verbose:
1878 sys.stdout.write(" client: read %r\n" % outdata)
1879 if outdata != indata.lower():
1880 raise AssertionError(
1881 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1882 % (outdata[:20], len(outdata),
1883 indata[:20].lower(), len(indata)))
1884 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001885 if connectionchatty:
1886 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001887 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001888 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001889 'compression': s.compression(),
1890 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001891 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001892 'client_npn_protocol': s.selected_npn_protocol()
1893 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001894 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001895 stats['server_npn_protocols'] = server.selected_protocols
1896 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001897
Antoine Pitroub5218772010-05-21 09:56:06 +00001898 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1899 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001900 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001901 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001902 certtype = {
1903 ssl.CERT_NONE: "CERT_NONE",
1904 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1905 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1906 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001907 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001908 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001909 sys.stdout.write(formatstr %
1910 (ssl.get_protocol_name(client_protocol),
1911 ssl.get_protocol_name(server_protocol),
1912 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001913 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001914 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001915 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001916 server_context.options |= server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001917
1918 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1919 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1920 # starting from OpenSSL 1.0.0 (see issue #8322).
1921 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1922 client_context.set_ciphers("ALL")
1923
Antoine Pitroub5218772010-05-21 09:56:06 +00001924 for ctx in (client_context, server_context):
1925 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001926 ctx.load_cert_chain(CERTFILE)
1927 ctx.load_verify_locations(CERTFILE)
1928 try:
1929 server_params_test(client_context, server_context,
1930 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001931 # Protocol mismatch can result in either an SSLError, or a
1932 # "Connection reset by peer" error.
1933 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001934 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001935 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001936 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001937 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001938 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001939 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001940 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001941 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001942 "Client protocol %s succeeded with server protocol %s!"
1943 % (ssl.get_protocol_name(client_protocol),
1944 ssl.get_protocol_name(server_protocol)))
1945
1946
Bill Janssen6e027db2007-11-15 22:23:56 +00001947 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001948
Antoine Pitrou23df4832010-08-04 17:14:06 +00001949 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001950 def test_echo(self):
1951 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001952 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001953 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001954 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001955 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1956 context = ssl.SSLContext(protocol)
1957 context.load_cert_chain(CERTFILE)
1958 server_params_test(context, context,
1959 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001960
Antoine Pitrou480a1242010-04-28 21:37:09 +00001961 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001962 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001963 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001964 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1965 context.verify_mode = ssl.CERT_REQUIRED
1966 context.load_verify_locations(CERTFILE)
1967 context.load_cert_chain(CERTFILE)
1968 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001969 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02001970 s = context.wrap_socket(socket.socket(),
1971 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001972 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02001973 # getpeercert() raise ValueError while the handshake isn't
1974 # done.
1975 with self.assertRaises(ValueError):
1976 s.getpeercert()
1977 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001978 cert = s.getpeercert()
1979 self.assertTrue(cert, "Can't get peer certificate.")
1980 cipher = s.cipher()
1981 if support.verbose:
1982 sys.stdout.write(pprint.pformat(cert) + '\n')
1983 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1984 if 'subject' not in cert:
1985 self.fail("No subject field in certificate: %s." %
1986 pprint.pformat(cert))
1987 if ((('organizationName', 'Python Software Foundation'),)
1988 not in cert['subject']):
1989 self.fail(
1990 "Missing or invalid 'organizationName' field in certificate subject; "
1991 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001992 self.assertIn('notBefore', cert)
1993 self.assertIn('notAfter', cert)
1994 before = ssl.cert_time_to_seconds(cert['notBefore'])
1995 after = ssl.cert_time_to_seconds(cert['notAfter'])
1996 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001997 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001998
Christian Heimes2427b502013-11-23 11:24:32 +01001999 @unittest.skipUnless(have_verify_flags(),
2000 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01002001 def test_crl_check(self):
2002 if support.verbose:
2003 sys.stdout.write("\n")
2004
2005 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2006 server_context.load_cert_chain(SIGNED_CERTFILE)
2007
2008 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2009 context.verify_mode = ssl.CERT_REQUIRED
2010 context.load_verify_locations(SIGNING_CA)
Christian Heimes32f0c7a2013-11-22 03:43:48 +01002011 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT)
Christian Heimes22587792013-11-21 23:56:13 +01002012
2013 # VERIFY_DEFAULT should pass
2014 server = ThreadedEchoServer(context=server_context, chatty=True)
2015 with server:
2016 with context.wrap_socket(socket.socket()) as s:
2017 s.connect((HOST, server.port))
2018 cert = s.getpeercert()
2019 self.assertTrue(cert, "Can't get peer certificate.")
2020
2021 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimes32f0c7a2013-11-22 03:43:48 +01002022 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Christian Heimes22587792013-11-21 23:56:13 +01002023
2024 server = ThreadedEchoServer(context=server_context, chatty=True)
2025 with server:
2026 with context.wrap_socket(socket.socket()) as s:
2027 with self.assertRaisesRegex(ssl.SSLError,
2028 "certificate verify failed"):
2029 s.connect((HOST, server.port))
2030
2031 # now load a CRL file. The CRL file is signed by the CA.
2032 context.load_verify_locations(CRLFILE)
2033
2034 server = ThreadedEchoServer(context=server_context, chatty=True)
2035 with server:
2036 with context.wrap_socket(socket.socket()) as s:
2037 s.connect((HOST, server.port))
2038 cert = s.getpeercert()
2039 self.assertTrue(cert, "Can't get peer certificate.")
2040
Christian Heimes575596e2013-12-15 21:49:17 +01002041 @needs_sni
Christian Heimes1aa9a752013-12-02 02:41:19 +01002042 def test_check_hostname(self):
2043 if support.verbose:
2044 sys.stdout.write("\n")
2045
2046 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2047 server_context.load_cert_chain(SIGNED_CERTFILE)
2048
2049 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2050 context.verify_mode = ssl.CERT_REQUIRED
2051 context.check_hostname = True
2052 context.load_verify_locations(SIGNING_CA)
2053
2054 # correct hostname should verify
2055 server = ThreadedEchoServer(context=server_context, chatty=True)
2056 with server:
2057 with context.wrap_socket(socket.socket(),
2058 server_hostname="localhost") as s:
2059 s.connect((HOST, server.port))
2060 cert = s.getpeercert()
2061 self.assertTrue(cert, "Can't get peer certificate.")
2062
2063 # incorrect hostname should raise an exception
2064 server = ThreadedEchoServer(context=server_context, chatty=True)
2065 with server:
2066 with context.wrap_socket(socket.socket(),
2067 server_hostname="invalid") as s:
2068 with self.assertRaisesRegex(ssl.CertificateError,
2069 "hostname 'invalid' doesn't match 'localhost'"):
2070 s.connect((HOST, server.port))
2071
2072 # missing server_hostname arg should cause an exception, too
2073 server = ThreadedEchoServer(context=server_context, chatty=True)
2074 with server:
2075 with socket.socket() as s:
2076 with self.assertRaisesRegex(ValueError,
2077 "check_hostname requires server_hostname"):
2078 context.wrap_socket(s)
2079
Antoine Pitrou480a1242010-04-28 21:37:09 +00002080 def test_empty_cert(self):
2081 """Connecting with an empty cert file"""
2082 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2083 "nullcert.pem"))
2084 def test_malformed_cert(self):
2085 """Connecting with a badly formatted certificate (syntax error)"""
2086 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2087 "badcert.pem"))
2088 def test_nonexisting_cert(self):
2089 """Connecting with a non-existing cert file"""
2090 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2091 "wrongcert.pem"))
2092 def test_malformed_key(self):
2093 """Connecting with a badly formatted key (syntax error)"""
2094 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2095 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002096
Antoine Pitrou480a1242010-04-28 21:37:09 +00002097 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002098 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00002099 in the client when attempting handshake.
2100 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00002101 listener_ready = threading.Event()
2102 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00002103
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002104 s = socket.socket()
2105 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002106
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002107 # `listener` runs in a thread. It sits in an accept() until
2108 # the main thread connects. Then it rudely closes the socket,
2109 # and sets Event `listener_gone` to let the main thread know
2110 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00002111 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00002112 s.listen(5)
2113 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002114 newsock, addr = s.accept()
2115 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002116 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002117 listener_gone.set()
2118
2119 def connector():
2120 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002121 with socket.socket() as c:
2122 c.connect((HOST, port))
2123 listener_gone.wait()
2124 try:
2125 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002126 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00002127 pass
2128 else:
2129 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00002130
2131 t = threading.Thread(target=listener)
2132 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002133 try:
2134 connector()
2135 finally:
2136 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002137
Antoine Pitrou23df4832010-08-04 17:14:06 +00002138 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02002139 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2140 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002141 def test_protocol_sslv2(self):
2142 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002143 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002144 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002145 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2146 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2147 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002148 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002149 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2150 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002151 # SSLv23 client with specific SSL options
2152 if no_sslv2_implies_sslv3_hello():
2153 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2154 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2155 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002156 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002157 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002158 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002159 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002160
Antoine Pitrou23df4832010-08-04 17:14:06 +00002161 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002162 def test_protocol_sslv23(self):
2163 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002164 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002165 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02002166 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2167 try:
2168 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02002169 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02002170 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2171 if support.verbose:
2172 sys.stdout.write(
2173 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2174 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00002175 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
2176 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
2177 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002178
Antoine Pitrou480a1242010-04-28 21:37:09 +00002179 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2180 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
2181 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002182
Antoine Pitrou480a1242010-04-28 21:37:09 +00002183 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
2184 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
2185 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002186
Antoine Pitroub5218772010-05-21 09:56:06 +00002187 # Server with specific SSL options
2188 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
2189 server_options=ssl.OP_NO_SSLv3)
2190 # Will choose TLSv1
2191 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2192 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2193 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2194 server_options=ssl.OP_NO_TLSv1)
2195
2196
Antoine Pitrou23df4832010-08-04 17:14:06 +00002197 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002198 def test_protocol_sslv3(self):
2199 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002200 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002201 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002202 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
2203 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2204 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002205 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2206 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002207 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2208 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002209 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002210 if no_sslv2_implies_sslv3_hello():
2211 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2212 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
2213 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002214
Antoine Pitrou23df4832010-08-04 17:14:06 +00002215 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002216 def test_protocol_tlsv1(self):
2217 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002218 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002219 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002220 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
2221 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
2222 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002223 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2224 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002225 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002226 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2227 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002228
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002229 @skip_if_broken_ubuntu_ssl
2230 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2231 "TLS version 1.1 not supported.")
2232 def test_protocol_tlsv1_1(self):
2233 """Connecting to a TLSv1.1 server with various client options.
2234 Testing against older TLS versions."""
2235 if support.verbose:
2236 sys.stdout.write("\n")
2237 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
2238 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2239 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
2240 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
2241 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2242 client_options=ssl.OP_NO_TLSv1_1)
2243
2244 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
2245 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2246 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2247
2248
2249 @skip_if_broken_ubuntu_ssl
2250 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2251 "TLS version 1.2 not supported.")
2252 def test_protocol_tlsv1_2(self):
2253 """Connecting to a TLSv1.2 server with various client options.
2254 Testing against older TLS versions."""
2255 if support.verbose:
2256 sys.stdout.write("\n")
2257 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
2258 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2259 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2260 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2261 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
2262 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
2263 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2264 client_options=ssl.OP_NO_TLSv1_2)
2265
2266 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
2267 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2268 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2269 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2270 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
2271
Antoine Pitrou480a1242010-04-28 21:37:09 +00002272 def test_starttls(self):
2273 """Switching from clear text to encrypted and back again."""
2274 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 +00002275
Trent Nelson78520002008-04-10 20:54:35 +00002276 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002277 ssl_version=ssl.PROTOCOL_TLSv1,
2278 starttls_server=True,
2279 chatty=True,
2280 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002281 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002282 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002283 s = socket.socket()
2284 s.setblocking(1)
2285 s.connect((HOST, server.port))
2286 if support.verbose:
2287 sys.stdout.write("\n")
2288 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002289 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002290 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002291 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002292 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002293 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002294 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002295 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002296 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002297 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002298 msg = outdata.strip().lower()
2299 if indata == b"STARTTLS" and msg.startswith(b"ok"):
2300 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002301 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002302 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002303 " client: read %r from server, starting TLS...\n"
2304 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002305 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2306 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00002307 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
2308 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002309 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002310 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002311 " client: read %r from server, ending TLS...\n"
2312 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002313 s = conn.unwrap()
2314 wrapped = False
2315 else:
2316 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002317 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002318 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002319 if support.verbose:
2320 sys.stdout.write(" client: closing connection.\n")
2321 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002322 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002323 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002324 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00002325 if wrapped:
2326 conn.close()
2327 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002328 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002329
Antoine Pitrou480a1242010-04-28 21:37:09 +00002330 def test_socketserver(self):
2331 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01002332 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002333 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002334 if support.verbose:
2335 sys.stdout.write('\n')
2336 with open(CERTFILE, 'rb') as f:
2337 d1 = f.read()
2338 d2 = ''
2339 # now fetch the same data from the HTTPS server
2340 url = 'https://%s:%d/%s' % (
2341 HOST, server.port, os.path.split(CERTFILE)[1])
2342 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002343 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00002344 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002345 if dlen and (int(dlen) > 0):
2346 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002347 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002348 sys.stdout.write(
2349 " client: read %d bytes from remote server '%s'\n"
2350 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002351 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002352 f.close()
2353 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002354
Antoine Pitrou480a1242010-04-28 21:37:09 +00002355 def test_asyncore_server(self):
2356 """Check the example asyncore integration."""
2357 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00002358
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002359 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002360 sys.stdout.write("\n")
2361
Antoine Pitrou480a1242010-04-28 21:37:09 +00002362 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00002363 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002364 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002365 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002366 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002367 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002368 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002369 " client: sending %r...\n" % indata)
2370 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002371 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002372 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002373 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002374 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002375 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002376 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2377 % (outdata[:20], len(outdata),
2378 indata[:20].lower(), len(indata)))
2379 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002380 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002381 sys.stdout.write(" client: closing connection.\n")
2382 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00002383 if support.verbose:
2384 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00002385
Antoine Pitrou480a1242010-04-28 21:37:09 +00002386 def test_recv_send(self):
2387 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00002388 if support.verbose:
2389 sys.stdout.write("\n")
2390
2391 server = ThreadedEchoServer(CERTFILE,
2392 certreqs=ssl.CERT_NONE,
2393 ssl_version=ssl.PROTOCOL_TLSv1,
2394 cacerts=CERTFILE,
2395 chatty=True,
2396 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002397 with server:
2398 s = ssl.wrap_socket(socket.socket(),
2399 server_side=False,
2400 certfile=CERTFILE,
2401 ca_certs=CERTFILE,
2402 cert_reqs=ssl.CERT_NONE,
2403 ssl_version=ssl.PROTOCOL_TLSv1)
2404 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002405 # helper methods for standardising recv* method signatures
2406 def _recv_into():
2407 b = bytearray(b"\0"*100)
2408 count = s.recv_into(b)
2409 return b[:count]
2410
2411 def _recvfrom_into():
2412 b = bytearray(b"\0"*100)
2413 count, addr = s.recvfrom_into(b)
2414 return b[:count]
2415
2416 # (name, method, whether to expect success, *args)
2417 send_methods = [
2418 ('send', s.send, True, []),
2419 ('sendto', s.sendto, False, ["some.address"]),
2420 ('sendall', s.sendall, True, []),
2421 ]
2422 recv_methods = [
2423 ('recv', s.recv, True, []),
2424 ('recvfrom', s.recvfrom, False, ["some.address"]),
2425 ('recv_into', _recv_into, True, []),
2426 ('recvfrom_into', _recvfrom_into, False, []),
2427 ]
2428 data_prefix = "PREFIX_"
2429
2430 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002431 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002432 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002433 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002434 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002435 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002436 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002437 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002438 "<<{outdata:r}>> ({nout:d}) received; "
2439 "expected <<{indata:r}>> ({nin:d})\n".format(
2440 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002441 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002442 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002443 )
2444 )
2445 except ValueError as e:
2446 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002447 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002448 "Failed to send with method <<{name:s}>>; "
2449 "expected to succeed.\n".format(name=meth_name)
2450 )
2451 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002452 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002453 "Method <<{name:s}>> failed with unexpected "
2454 "exception message: {exp:s}\n".format(
2455 name=meth_name, exp=e
2456 )
2457 )
2458
2459 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002460 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002461 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002462 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002463 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002464 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002465 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002466 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002467 "<<{outdata:r}>> ({nout:d}) received; "
2468 "expected <<{indata:r}>> ({nin:d})\n".format(
2469 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002470 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002471 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002472 )
2473 )
2474 except ValueError as e:
2475 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002476 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002477 "Failed to receive with method <<{name:s}>>; "
2478 "expected to succeed.\n".format(name=meth_name)
2479 )
2480 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002481 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002482 "Method <<{name:s}>> failed with unexpected "
2483 "exception message: {exp:s}\n".format(
2484 name=meth_name, exp=e
2485 )
2486 )
2487 # consume data
2488 s.read()
2489
Nick Coghlan513886a2011-08-28 00:00:27 +10002490 # Make sure sendmsg et al are disallowed to avoid
2491 # inadvertent disclosure of data and/or corruption
2492 # of the encrypted data stream
2493 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2494 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2495 self.assertRaises(NotImplementedError,
2496 s.recvmsg_into, bytearray(100))
2497
Antoine Pitrou480a1242010-04-28 21:37:09 +00002498 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002499 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002500
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002501 def test_handshake_timeout(self):
2502 # Issue #5103: SSL handshake must respect the socket timeout
2503 server = socket.socket(socket.AF_INET)
2504 host = "127.0.0.1"
2505 port = support.bind_port(server)
2506 started = threading.Event()
2507 finish = False
2508
2509 def serve():
2510 server.listen(5)
2511 started.set()
2512 conns = []
2513 while not finish:
2514 r, w, e = select.select([server], [], [], 0.1)
2515 if server in r:
2516 # Let the socket hang around rather than having
2517 # it closed by garbage collection.
2518 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002519 for sock in conns:
2520 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002521
2522 t = threading.Thread(target=serve)
2523 t.start()
2524 started.wait()
2525
2526 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002527 try:
2528 c = socket.socket(socket.AF_INET)
2529 c.settimeout(0.2)
2530 c.connect((host, port))
2531 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002532 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002533 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002534 finally:
2535 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002536 try:
2537 c = socket.socket(socket.AF_INET)
2538 c = ssl.wrap_socket(c)
2539 c.settimeout(0.2)
2540 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002541 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002542 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002543 finally:
2544 c.close()
2545 finally:
2546 finish = True
2547 t.join()
2548 server.close()
2549
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002550 def test_server_accept(self):
2551 # Issue #16357: accept() on a SSLSocket created through
2552 # SSLContext.wrap_socket().
2553 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2554 context.verify_mode = ssl.CERT_REQUIRED
2555 context.load_verify_locations(CERTFILE)
2556 context.load_cert_chain(CERTFILE)
2557 server = socket.socket(socket.AF_INET)
2558 host = "127.0.0.1"
2559 port = support.bind_port(server)
2560 server = context.wrap_socket(server, server_side=True)
2561
2562 evt = threading.Event()
2563 remote = None
2564 peer = None
2565 def serve():
2566 nonlocal remote, peer
2567 server.listen(5)
2568 # Block on the accept and wait on the connection to close.
2569 evt.set()
2570 remote, peer = server.accept()
2571 remote.recv(1)
2572
2573 t = threading.Thread(target=serve)
2574 t.start()
2575 # Client wait until server setup and perform a connect.
2576 evt.wait()
2577 client = context.wrap_socket(socket.socket())
2578 client.connect((host, port))
2579 client_addr = client.getsockname()
2580 client.close()
2581 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002582 remote.close()
2583 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002584 # Sanity checks.
2585 self.assertIsInstance(remote, ssl.SSLSocket)
2586 self.assertEqual(peer, client_addr)
2587
Antoine Pitrou242db722013-05-01 20:52:07 +02002588 def test_getpeercert_enotconn(self):
2589 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2590 with context.wrap_socket(socket.socket()) as sock:
2591 with self.assertRaises(OSError) as cm:
2592 sock.getpeercert()
2593 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2594
2595 def test_do_handshake_enotconn(self):
2596 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2597 with context.wrap_socket(socket.socket()) as sock:
2598 with self.assertRaises(OSError) as cm:
2599 sock.do_handshake()
2600 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2601
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002602 def test_default_ciphers(self):
2603 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2604 try:
2605 # Force a set of weak ciphers on our client context
2606 context.set_ciphers("DES")
2607 except ssl.SSLError:
2608 self.skipTest("no DES cipher available")
2609 with ThreadedEchoServer(CERTFILE,
2610 ssl_version=ssl.PROTOCOL_SSLv23,
2611 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002612 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002613 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002614 s.connect((HOST, server.port))
2615 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2616
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002617 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2618 def test_default_ecdh_curve(self):
2619 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2620 # should be enabled by default on SSL contexts.
2621 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2622 context.load_cert_chain(CERTFILE)
Antoine Pitrouc0430612014-04-16 18:33:39 +02002623 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2624 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2625 # our default cipher list should prefer ECDH-based ciphers
2626 # automatically.
2627 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2628 context.set_ciphers("ECCdraft:ECDH")
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002629 with ThreadedEchoServer(context=context) as server:
2630 with context.wrap_socket(socket.socket()) as s:
2631 s.connect((HOST, server.port))
2632 self.assertIn("ECDH", s.cipher()[0])
2633
Antoine Pitroud6494802011-07-21 01:11:30 +02002634 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2635 "'tls-unique' channel binding not available")
2636 def test_tls_unique_channel_binding(self):
2637 """Test tls-unique channel binding."""
2638 if support.verbose:
2639 sys.stdout.write("\n")
2640
2641 server = ThreadedEchoServer(CERTFILE,
2642 certreqs=ssl.CERT_NONE,
2643 ssl_version=ssl.PROTOCOL_TLSv1,
2644 cacerts=CERTFILE,
2645 chatty=True,
2646 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002647 with server:
2648 s = ssl.wrap_socket(socket.socket(),
2649 server_side=False,
2650 certfile=CERTFILE,
2651 ca_certs=CERTFILE,
2652 cert_reqs=ssl.CERT_NONE,
2653 ssl_version=ssl.PROTOCOL_TLSv1)
2654 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002655 # get the data
2656 cb_data = s.get_channel_binding("tls-unique")
2657 if support.verbose:
2658 sys.stdout.write(" got channel binding data: {0!r}\n"
2659 .format(cb_data))
2660
2661 # check if it is sane
2662 self.assertIsNotNone(cb_data)
2663 self.assertEqual(len(cb_data), 12) # True for TLSv1
2664
2665 # and compare with the peers version
2666 s.write(b"CB tls-unique\n")
2667 peer_data_repr = s.read().strip()
2668 self.assertEqual(peer_data_repr,
2669 repr(cb_data).encode("us-ascii"))
2670 s.close()
2671
2672 # now, again
2673 s = ssl.wrap_socket(socket.socket(),
2674 server_side=False,
2675 certfile=CERTFILE,
2676 ca_certs=CERTFILE,
2677 cert_reqs=ssl.CERT_NONE,
2678 ssl_version=ssl.PROTOCOL_TLSv1)
2679 s.connect((HOST, server.port))
2680 new_cb_data = s.get_channel_binding("tls-unique")
2681 if support.verbose:
2682 sys.stdout.write(" got another channel binding data: {0!r}\n"
2683 .format(new_cb_data))
2684 # is it really unique
2685 self.assertNotEqual(cb_data, new_cb_data)
2686 self.assertIsNotNone(cb_data)
2687 self.assertEqual(len(cb_data), 12) # True for TLSv1
2688 s.write(b"CB tls-unique\n")
2689 peer_data_repr = s.read().strip()
2690 self.assertEqual(peer_data_repr,
2691 repr(new_cb_data).encode("us-ascii"))
2692 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002693
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002694 def test_compression(self):
2695 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2696 context.load_cert_chain(CERTFILE)
2697 stats = server_params_test(context, context,
2698 chatty=True, connectionchatty=True)
2699 if support.verbose:
2700 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2701 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2702
2703 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2704 "ssl.OP_NO_COMPRESSION needed for this test")
2705 def test_compression_disabled(self):
2706 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2707 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002708 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002709 stats = server_params_test(context, context,
2710 chatty=True, connectionchatty=True)
2711 self.assertIs(stats['compression'], None)
2712
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002713 def test_dh_params(self):
2714 # Check we can get a connection with ephemeral Diffie-Hellman
2715 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2716 context.load_cert_chain(CERTFILE)
2717 context.load_dh_params(DHFILE)
2718 context.set_ciphers("kEDH")
2719 stats = server_params_test(context, context,
2720 chatty=True, connectionchatty=True)
2721 cipher = stats["cipher"][0]
2722 parts = cipher.split("-")
2723 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2724 self.fail("Non-DH cipher: " + cipher[0])
2725
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002726 def test_selected_npn_protocol(self):
2727 # selected_npn_protocol() is None unless NPN is used
2728 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2729 context.load_cert_chain(CERTFILE)
2730 stats = server_params_test(context, context,
2731 chatty=True, connectionchatty=True)
2732 self.assertIs(stats['client_npn_protocol'], None)
2733
2734 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2735 def test_npn_protocols(self):
2736 server_protocols = ['http/1.1', 'spdy/2']
2737 protocol_tests = [
2738 (['http/1.1', 'spdy/2'], 'http/1.1'),
2739 (['spdy/2', 'http/1.1'], 'http/1.1'),
2740 (['spdy/2', 'test'], 'spdy/2'),
2741 (['abc', 'def'], 'abc')
2742 ]
2743 for client_protocols, expected in protocol_tests:
2744 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2745 server_context.load_cert_chain(CERTFILE)
2746 server_context.set_npn_protocols(server_protocols)
2747 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2748 client_context.load_cert_chain(CERTFILE)
2749 client_context.set_npn_protocols(client_protocols)
2750 stats = server_params_test(client_context, server_context,
2751 chatty=True, connectionchatty=True)
2752
2753 msg = "failed trying %s (s) and %s (c).\n" \
2754 "was expecting %s, but got %%s from the %%s" \
2755 % (str(server_protocols), str(client_protocols),
2756 str(expected))
2757 client_result = stats['client_npn_protocol']
2758 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2759 server_result = stats['server_npn_protocols'][-1] \
2760 if len(stats['server_npn_protocols']) else 'nothing'
2761 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2762
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002763 def sni_contexts(self):
2764 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2765 server_context.load_cert_chain(SIGNED_CERTFILE)
2766 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2767 other_context.load_cert_chain(SIGNED_CERTFILE2)
2768 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2769 client_context.verify_mode = ssl.CERT_REQUIRED
2770 client_context.load_verify_locations(SIGNING_CA)
2771 return server_context, other_context, client_context
2772
2773 def check_common_name(self, stats, name):
2774 cert = stats['peercert']
2775 self.assertIn((('commonName', name),), cert['subject'])
2776
2777 @needs_sni
2778 def test_sni_callback(self):
2779 calls = []
2780 server_context, other_context, client_context = self.sni_contexts()
2781
2782 def servername_cb(ssl_sock, server_name, initial_context):
2783 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002784 if server_name is not None:
2785 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002786 server_context.set_servername_callback(servername_cb)
2787
2788 stats = server_params_test(client_context, server_context,
2789 chatty=True,
2790 sni_name='supermessage')
2791 # The hostname was fetched properly, and the certificate was
2792 # changed for the connection.
2793 self.assertEqual(calls, [("supermessage", server_context)])
2794 # CERTFILE4 was selected
2795 self.check_common_name(stats, 'fakehostname')
2796
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002797 calls = []
2798 # The callback is called with server_name=None
2799 stats = server_params_test(client_context, server_context,
2800 chatty=True,
2801 sni_name=None)
2802 self.assertEqual(calls, [(None, server_context)])
2803 self.check_common_name(stats, 'localhost')
2804
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002805 # Check disabling the callback
2806 calls = []
2807 server_context.set_servername_callback(None)
2808
2809 stats = server_params_test(client_context, server_context,
2810 chatty=True,
2811 sni_name='notfunny')
2812 # Certificate didn't change
2813 self.check_common_name(stats, 'localhost')
2814 self.assertEqual(calls, [])
2815
2816 @needs_sni
2817 def test_sni_callback_alert(self):
2818 # Returning a TLS alert is reflected to the connecting client
2819 server_context, other_context, client_context = self.sni_contexts()
2820
2821 def cb_returning_alert(ssl_sock, server_name, initial_context):
2822 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2823 server_context.set_servername_callback(cb_returning_alert)
2824
2825 with self.assertRaises(ssl.SSLError) as cm:
2826 stats = server_params_test(client_context, server_context,
2827 chatty=False,
2828 sni_name='supermessage')
2829 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2830
2831 @needs_sni
2832 def test_sni_callback_raising(self):
2833 # Raising fails the connection with a TLS handshake failure alert.
2834 server_context, other_context, client_context = self.sni_contexts()
2835
2836 def cb_raising(ssl_sock, server_name, initial_context):
2837 1/0
2838 server_context.set_servername_callback(cb_raising)
2839
2840 with self.assertRaises(ssl.SSLError) as cm, \
2841 support.captured_stderr() as stderr:
2842 stats = server_params_test(client_context, server_context,
2843 chatty=False,
2844 sni_name='supermessage')
2845 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2846 self.assertIn("ZeroDivisionError", stderr.getvalue())
2847
2848 @needs_sni
2849 def test_sni_callback_wrong_return_type(self):
2850 # Returning the wrong return type terminates the TLS connection
2851 # with an internal error alert.
2852 server_context, other_context, client_context = self.sni_contexts()
2853
2854 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2855 return "foo"
2856 server_context.set_servername_callback(cb_wrong_return_type)
2857
2858 with self.assertRaises(ssl.SSLError) as cm, \
2859 support.captured_stderr() as stderr:
2860 stats = server_params_test(client_context, server_context,
2861 chatty=False,
2862 sni_name='supermessage')
2863 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2864 self.assertIn("TypeError", stderr.getvalue())
2865
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002866 def test_read_write_after_close_raises_valuerror(self):
2867 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2868 context.verify_mode = ssl.CERT_REQUIRED
2869 context.load_verify_locations(CERTFILE)
2870 context.load_cert_chain(CERTFILE)
2871 server = ThreadedEchoServer(context=context, chatty=False)
2872
2873 with server:
2874 s = context.wrap_socket(socket.socket())
2875 s.connect((HOST, server.port))
2876 s.close()
2877
2878 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02002879 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002880
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002881
Thomas Woutersed03b412007-08-28 21:37:11 +00002882def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002883 if support.verbose:
2884 plats = {
2885 'Linux': platform.linux_distribution,
2886 'Mac': platform.mac_ver,
2887 'Windows': platform.win32_ver,
2888 }
2889 for name, func in plats.items():
2890 plat = func()
2891 if plat and plat[0]:
2892 plat = '%s %r' % (name, plat)
2893 break
2894 else:
2895 plat = repr(platform.platform())
2896 print("test_ssl: testing with %r %r" %
2897 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2898 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002899 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002900 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2901 try:
2902 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2903 except AttributeError:
2904 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002905
Antoine Pitrou152efa22010-05-16 18:19:27 +00002906 for filename in [
2907 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2908 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002909 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002910 BADCERT, BADKEY, EMPTYCERT]:
2911 if not os.path.exists(filename):
2912 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002913
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002914 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002915
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002916 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002917 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002918
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002919 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002920 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002921 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002922 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002923
Antoine Pitrou480a1242010-04-28 21:37:09 +00002924 try:
2925 support.run_unittest(*tests)
2926 finally:
2927 if _have_threads:
2928 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002929
2930if __name__ == "__main__":
2931 test_main()