blob: d1cf5b27945bd3f191a36bf73a5257be730cc021 [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
Christian Heimes4c05b472013-11-23 15:58:30 +01001019 def test_create_default_context(self):
1020 ctx = ssl.create_default_context()
Donald Stufft6a2ba942014-03-23 19:05:28 -04001021 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001022 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001023 self.assertTrue(ctx.check_hostname)
Christian Heimes4c05b472013-11-23 15:58:30 +01001024 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001025 self.assertEqual(
1026 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1027 getattr(ssl, "OP_NO_COMPRESSION", 0),
1028 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001029
1030 with open(SIGNING_CA) as f:
1031 cadata = f.read()
1032 ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH,
1033 cadata=cadata)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001034 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001035 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
1036 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001037 self.assertEqual(
1038 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1039 getattr(ssl, "OP_NO_COMPRESSION", 0),
1040 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001041
1042 ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001043 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
Christian Heimes4c05b472013-11-23 15:58:30 +01001044 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1045 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Donald Stufft6a2ba942014-03-23 19:05:28 -04001046 self.assertEqual(
1047 ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0),
1048 getattr(ssl, "OP_NO_COMPRESSION", 0),
1049 )
1050 self.assertEqual(
1051 ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0),
1052 getattr(ssl, "OP_SINGLE_DH_USE", 0),
1053 )
1054 self.assertEqual(
1055 ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1056 getattr(ssl, "OP_SINGLE_ECDH_USE", 0),
1057 )
Christian Heimes4c05b472013-11-23 15:58:30 +01001058
Christian Heimes67986f92013-11-23 22:43:47 +01001059 def test__create_stdlib_context(self):
1060 ctx = ssl._create_stdlib_context()
1061 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1062 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
Christian Heimes1aa9a752013-12-02 02:41:19 +01001063 self.assertFalse(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001064 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1065
1066 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
1067 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1068 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1069 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1070
1071 ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1,
Christian Heimesa02c69a2013-12-02 20:59:28 +01001072 cert_reqs=ssl.CERT_REQUIRED,
1073 check_hostname=True)
Christian Heimes67986f92013-11-23 22:43:47 +01001074 self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
1075 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
Christian Heimesa02c69a2013-12-02 20:59:28 +01001076 self.assertTrue(ctx.check_hostname)
Christian Heimes67986f92013-11-23 22:43:47 +01001077 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
1078
1079 ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
1080 self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23)
1081 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
1082 self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
Christian Heimes4c05b472013-11-23 15:58:30 +01001083
Christian Heimes1aa9a752013-12-02 02:41:19 +01001084 def test_check_hostname(self):
1085 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1086 self.assertFalse(ctx.check_hostname)
1087
1088 # Requires CERT_REQUIRED or CERT_OPTIONAL
1089 with self.assertRaises(ValueError):
1090 ctx.check_hostname = True
1091 ctx.verify_mode = ssl.CERT_REQUIRED
1092 self.assertFalse(ctx.check_hostname)
1093 ctx.check_hostname = True
1094 self.assertTrue(ctx.check_hostname)
1095
1096 ctx.verify_mode = ssl.CERT_OPTIONAL
1097 ctx.check_hostname = True
1098 self.assertTrue(ctx.check_hostname)
1099
1100 # Cannot set CERT_NONE with check_hostname enabled
1101 with self.assertRaises(ValueError):
1102 ctx.verify_mode = ssl.CERT_NONE
1103 ctx.check_hostname = False
1104 self.assertFalse(ctx.check_hostname)
1105
Antoine Pitrou152efa22010-05-16 18:19:27 +00001106
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001107class SSLErrorTests(unittest.TestCase):
1108
1109 def test_str(self):
1110 # The str() of a SSLError doesn't include the errno
1111 e = ssl.SSLError(1, "foo")
1112 self.assertEqual(str(e), "foo")
1113 self.assertEqual(e.errno, 1)
1114 # Same for a subclass
1115 e = ssl.SSLZeroReturnError(1, "foo")
1116 self.assertEqual(str(e), "foo")
1117 self.assertEqual(e.errno, 1)
1118
1119 def test_lib_reason(self):
1120 # Test the library and reason attributes
1121 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1122 with self.assertRaises(ssl.SSLError) as cm:
1123 ctx.load_dh_params(CERTFILE)
1124 self.assertEqual(cm.exception.library, 'PEM')
1125 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
1126 s = str(cm.exception)
1127 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
1128
1129 def test_subclass(self):
1130 # Check that the appropriate SSLError subclass is raised
1131 # (this only tests one of them)
1132 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1133 with socket.socket() as s:
1134 s.bind(("127.0.0.1", 0))
1135 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001136 c = socket.socket()
1137 c.connect(s.getsockname())
1138 c.setblocking(False)
1139 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02001140 with self.assertRaises(ssl.SSLWantReadError) as cm:
1141 c.do_handshake()
1142 s = str(cm.exception)
1143 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
1144 # For compatibility
1145 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
1146
1147
Bill Janssen6e027db2007-11-15 22:23:56 +00001148class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001149
Antoine Pitrou480a1242010-04-28 21:37:09 +00001150 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001151 with support.transient_internet("svn.python.org"):
1152 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1153 cert_reqs=ssl.CERT_NONE)
1154 try:
1155 s.connect(("svn.python.org", 443))
1156 self.assertEqual({}, s.getpeercert())
1157 finally:
1158 s.close()
1159
1160 # this should fail because we have no verification certs
1161 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1162 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +00001163 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
1164 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001165 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166
Antoine Pitrou350c7222010-09-09 13:31:46 +00001167 # this should succeed because we specify the root cert
1168 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1169 cert_reqs=ssl.CERT_REQUIRED,
1170 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1171 try:
1172 s.connect(("svn.python.org", 443))
1173 self.assertTrue(s.getpeercert())
1174 finally:
1175 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001176
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001177 def test_connect_ex(self):
1178 # Issue #11326: check connect_ex() implementation
1179 with support.transient_internet("svn.python.org"):
1180 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1181 cert_reqs=ssl.CERT_REQUIRED,
1182 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1183 try:
1184 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
1185 self.assertTrue(s.getpeercert())
1186 finally:
1187 s.close()
1188
1189 def test_non_blocking_connect_ex(self):
1190 # Issue #11326: non-blocking connect_ex() should allow handshake
1191 # to proceed after the socket gets ready.
1192 with support.transient_internet("svn.python.org"):
1193 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1194 cert_reqs=ssl.CERT_REQUIRED,
1195 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1196 do_handshake_on_connect=False)
1197 try:
1198 s.setblocking(False)
1199 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +00001200 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
1201 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001202 # Wait for connect to finish
1203 select.select([], [s], [], 5.0)
1204 # Non-blocking handshake
1205 while True:
1206 try:
1207 s.do_handshake()
1208 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001209 except ssl.SSLWantReadError:
1210 select.select([s], [], [], 5.0)
1211 except ssl.SSLWantWriteError:
1212 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +00001213 # SSL established
1214 self.assertTrue(s.getpeercert())
1215 finally:
1216 s.close()
1217
Antoine Pitroub4410db2011-05-18 18:51:06 +02001218 def test_timeout_connect_ex(self):
1219 # Issue #12065: on a timeout, connect_ex() should return the original
1220 # errno (mimicking the behaviour of non-SSL sockets).
1221 with support.transient_internet("svn.python.org"):
1222 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1223 cert_reqs=ssl.CERT_REQUIRED,
1224 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
1225 do_handshake_on_connect=False)
1226 try:
1227 s.settimeout(0.0000001)
1228 rc = s.connect_ex(('svn.python.org', 443))
1229 if rc == 0:
1230 self.skipTest("svn.python.org responded too quickly")
1231 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
1232 finally:
1233 s.close()
1234
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001235 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +01001236 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001237 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
1238 cert_reqs=ssl.CERT_REQUIRED,
1239 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
1240 try:
Christian Heimesde570742013-12-16 21:15:44 +01001241 rc = s.connect_ex(("svn.python.org", 444))
1242 # Issue #19919: Windows machines or VMs hosted on Windows
1243 # machines sometimes return EWOULDBLOCK.
1244 self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK))
Antoine Pitrou40f12ab2012-12-28 19:03:43 +01001245 finally:
1246 s.close()
1247
Antoine Pitrou152efa22010-05-16 18:19:27 +00001248 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001249 with support.transient_internet("svn.python.org"):
1250 # Same as test_connect, but with a separately created context
1251 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1252 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1253 s.connect(("svn.python.org", 443))
1254 try:
1255 self.assertEqual({}, s.getpeercert())
1256 finally:
1257 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +00001258 # Same with a server hostname
1259 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1260 server_hostname="svn.python.org")
1261 if ssl.HAS_SNI:
1262 s.connect(("svn.python.org", 443))
1263 s.close()
1264 else:
1265 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001266 # This should fail because we have no verification certs
1267 ctx.verify_mode = ssl.CERT_REQUIRED
1268 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +00001269 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +00001270 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +00001271 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +00001272 # This should succeed because we specify the root cert
1273 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
1274 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1275 s.connect(("svn.python.org", 443))
1276 try:
1277 cert = s.getpeercert()
1278 self.assertTrue(cert)
1279 finally:
1280 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +00001281
1282 def test_connect_capath(self):
1283 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +00001284 # NOTE: the subject hashing algorithm has been changed between
1285 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
1286 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +00001287 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +00001288 with support.transient_internet("svn.python.org"):
1289 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1290 ctx.verify_mode = ssl.CERT_REQUIRED
1291 ctx.load_verify_locations(capath=CAPATH)
1292 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1293 s.connect(("svn.python.org", 443))
1294 try:
1295 cert = s.getpeercert()
1296 self.assertTrue(cert)
1297 finally:
1298 s.close()
1299 # Same with a bytes `capath` argument
1300 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1301 ctx.verify_mode = ssl.CERT_REQUIRED
1302 ctx.load_verify_locations(capath=BYTES_CAPATH)
1303 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1304 s.connect(("svn.python.org", 443))
1305 try:
1306 cert = s.getpeercert()
1307 self.assertTrue(cert)
1308 finally:
1309 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001310
Christian Heimesefff7062013-11-21 03:35:02 +01001311 def test_connect_cadata(self):
1312 with open(CAFILE_CACERT) as f:
1313 pem = f.read()
1314 der = ssl.PEM_cert_to_DER_cert(pem)
1315 with support.transient_internet("svn.python.org"):
1316 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1317 ctx.verify_mode = ssl.CERT_REQUIRED
1318 ctx.load_verify_locations(cadata=pem)
1319 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1320 s.connect(("svn.python.org", 443))
1321 cert = s.getpeercert()
1322 self.assertTrue(cert)
1323
1324 # same with DER
1325 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1326 ctx.verify_mode = ssl.CERT_REQUIRED
1327 ctx.load_verify_locations(cadata=der)
1328 with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
1329 s.connect(("svn.python.org", 443))
1330 cert = s.getpeercert()
1331 self.assertTrue(cert)
1332
Antoine Pitroue3220242010-04-24 11:13:53 +00001333 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1334 def test_makefile_close(self):
1335 # Issue #5238: creating a file-like object with makefile() shouldn't
1336 # delay closing the underlying "real socket" (here tested with its
1337 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +00001338 with support.transient_internet("svn.python.org"):
1339 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1340 ss.connect(("svn.python.org", 443))
1341 fd = ss.fileno()
1342 f = ss.makefile()
1343 f.close()
1344 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +00001345 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001346 # Closing the SSL socket should close the fd too
1347 ss.close()
1348 gc.collect()
1349 with self.assertRaises(OSError) as e:
1350 os.read(fd, 0)
1351 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001352
Antoine Pitrou480a1242010-04-28 21:37:09 +00001353 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001354 with support.transient_internet("svn.python.org"):
1355 s = socket.socket(socket.AF_INET)
1356 s.connect(("svn.python.org", 443))
1357 s.setblocking(False)
1358 s = ssl.wrap_socket(s,
1359 cert_reqs=ssl.CERT_NONE,
1360 do_handshake_on_connect=False)
1361 count = 0
1362 while True:
1363 try:
1364 count += 1
1365 s.do_handshake()
1366 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001367 except ssl.SSLWantReadError:
1368 select.select([s], [], [])
1369 except ssl.SSLWantWriteError:
1370 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +00001371 s.close()
1372 if support.verbose:
1373 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001374
Antoine Pitrou480a1242010-04-28 21:37:09 +00001375 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +02001376 def _test_get_server_certificate(host, port, cert=None):
1377 with support.transient_internet(host):
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001378 pem = ssl.get_server_certificate((host, port),
1379 ssl.PROTOCOL_SSLv23)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001380 if not pem:
1381 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001382
Antoine Pitrou15399c32011-04-28 19:23:55 +02001383 try:
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001384 pem = ssl.get_server_certificate((host, port),
1385 ssl.PROTOCOL_SSLv23,
1386 ca_certs=CERTFILE)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001387 except ssl.SSLError as x:
1388 #should fail
1389 if support.verbose:
1390 sys.stdout.write("%s\n" % x)
1391 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001392 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1393
Benjamin Peterson10b93cc2014-03-12 18:10:57 -05001394 pem = ssl.get_server_certificate((host, port),
1395 ssl.PROTOCOL_SSLv23,
1396 ca_certs=cert)
Antoine Pitrou15399c32011-04-28 19:23:55 +02001397 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001398 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001399 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001400 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001401
Antoine Pitrou15399c32011-04-28 19:23:55 +02001402 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
1403 if support.IPV6_ENABLED:
1404 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001405
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001406 def test_ciphers(self):
1407 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001408 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001409 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1410 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1411 s.connect(remote)
1412 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1413 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1414 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001415 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001416 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001417 with socket.socket(socket.AF_INET) as sock:
1418 s = ssl.wrap_socket(sock,
1419 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1420 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001421
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001422 def test_algorithms(self):
1423 # Issue #8484: all algorithms should be available when verifying a
1424 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001425 # SHA256 was added in OpenSSL 0.9.8
1426 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1427 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001428 # sha256.tbs-internet.com needs SNI to use the correct certificate
1429 if not ssl.HAS_SNI:
1430 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001431 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1432 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001433 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001434 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001435 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1436 ctx.verify_mode = ssl.CERT_REQUIRED
1437 ctx.load_verify_locations(sha256_cert)
1438 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1439 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001440 try:
1441 s.connect(remote)
1442 if support.verbose:
1443 sys.stdout.write("\nCipher with %r is %r\n" %
1444 (remote, s.cipher()))
1445 sys.stdout.write("Certificate is:\n%s\n" %
1446 pprint.pformat(s.getpeercert()))
1447 finally:
1448 s.close()
1449
Christian Heimes9a5395a2013-06-17 15:44:12 +02001450 def test_get_ca_certs_capath(self):
1451 # capath certs are loaded on request
1452 with support.transient_internet("svn.python.org"):
1453 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1454 ctx.verify_mode = ssl.CERT_REQUIRED
1455 ctx.load_verify_locations(capath=CAPATH)
1456 self.assertEqual(ctx.get_ca_certs(), [])
1457 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1458 s.connect(("svn.python.org", 443))
1459 try:
1460 cert = s.getpeercert()
1461 self.assertTrue(cert)
1462 finally:
1463 s.close()
1464 self.assertEqual(len(ctx.get_ca_certs()), 1)
1465
Christian Heimes575596e2013-12-15 21:49:17 +01001466 @needs_sni
Christian Heimes8e7f3942013-12-05 07:41:08 +01001467 def test_context_setget(self):
1468 # Check that the context of a connected socket can be replaced.
1469 with support.transient_internet("svn.python.org"):
1470 ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1471 ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1472 s = socket.socket(socket.AF_INET)
1473 with ctx1.wrap_socket(s) as ss:
1474 ss.connect(("svn.python.org", 443))
1475 self.assertIs(ss.context, ctx1)
1476 self.assertIs(ss._sslobj.context, ctx1)
1477 ss.context = ctx2
1478 self.assertIs(ss.context, ctx2)
1479 self.assertIs(ss._sslobj.context, ctx2)
1480
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001481try:
1482 import threading
1483except ImportError:
1484 _have_threads = False
1485else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001486 _have_threads = True
1487
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001488 from test.ssl_servers import make_https_server
1489
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001490 class ThreadedEchoServer(threading.Thread):
1491
1492 class ConnectionHandler(threading.Thread):
1493
1494 """A mildly complicated class, because we want it to work both
1495 with and without the SSL wrapper around the socket connection, so
1496 that we can test the STARTTLS functionality."""
1497
Bill Janssen6e027db2007-11-15 22:23:56 +00001498 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001499 self.server = server
1500 self.running = False
1501 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001502 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001503 self.sock.setblocking(1)
1504 self.sslconn = None
1505 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001506 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001507
Antoine Pitrou480a1242010-04-28 21:37:09 +00001508 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001509 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001510 self.sslconn = self.server.context.wrap_socket(
1511 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001512 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001513 except (ssl.SSLError, ConnectionResetError) as e:
1514 # We treat ConnectionResetError as though it were an
1515 # SSLError - OpenSSL on Ubuntu abruptly closes the
1516 # connection when asked to use an unsupported protocol.
1517 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001518 # XXX Various errors can have happened here, for example
1519 # a mismatching protocol version, an invalid certificate,
1520 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001521 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001522 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001523 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001524 self.running = False
1525 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001526 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001527 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001528 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001529 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001530 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001531 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001532 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1533 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001534 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001535 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1536 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001537 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001538 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001539 sys.stdout.write(" server: selected protocol is now "
1540 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001541 return True
1542
1543 def read(self):
1544 if self.sslconn:
1545 return self.sslconn.read()
1546 else:
1547 return self.sock.recv(1024)
1548
1549 def write(self, bytes):
1550 if self.sslconn:
1551 return self.sslconn.write(bytes)
1552 else:
1553 return self.sock.send(bytes)
1554
1555 def close(self):
1556 if self.sslconn:
1557 self.sslconn.close()
1558 else:
1559 self.sock.close()
1560
Antoine Pitrou480a1242010-04-28 21:37:09 +00001561 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001562 self.running = True
1563 if not self.server.starttls_server:
1564 if not self.wrap_conn():
1565 return
1566 while self.running:
1567 try:
1568 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001569 stripped = msg.strip()
1570 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001571 # eof, so quit this handler
1572 self.running = False
1573 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001574 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001575 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001576 sys.stdout.write(" server: client closed connection\n")
1577 self.close()
1578 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001579 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001580 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001581 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001582 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001583 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001584 if not self.wrap_conn():
1585 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001586 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001587 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001588 if support.verbose and self.server.connectionchatty:
1589 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001590 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001591 self.sock = self.sslconn.unwrap()
1592 self.sslconn = None
1593 if support.verbose and self.server.connectionchatty:
1594 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001595 elif stripped == b'CB tls-unique':
1596 if support.verbose and self.server.connectionchatty:
1597 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1598 data = self.sslconn.get_channel_binding("tls-unique")
1599 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001600 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001601 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001602 self.server.connectionchatty):
1603 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001604 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1605 % (msg, ctype, msg.lower(), ctype))
1606 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001607 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001608 if self.server.chatty:
1609 handle_error("Test server failure:\n")
1610 self.close()
1611 self.running = False
1612 # normally, we'd just stop here, but for the test
1613 # harness, we want to stop the server
1614 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001615
Antoine Pitroub5218772010-05-21 09:56:06 +00001616 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001617 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001618 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001619 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001620 if context:
1621 self.context = context
1622 else:
1623 self.context = ssl.SSLContext(ssl_version
1624 if ssl_version is not None
1625 else ssl.PROTOCOL_TLSv1)
1626 self.context.verify_mode = (certreqs if certreqs is not None
1627 else ssl.CERT_NONE)
1628 if cacerts:
1629 self.context.load_verify_locations(cacerts)
1630 if certificate:
1631 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001632 if npn_protocols:
1633 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001634 if ciphers:
1635 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001636 self.chatty = chatty
1637 self.connectionchatty = connectionchatty
1638 self.starttls_server = starttls_server
1639 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001640 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001641 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001642 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001643 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001644 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001645 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001646 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001647
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001648 def __enter__(self):
1649 self.start(threading.Event())
1650 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001651 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001652
1653 def __exit__(self, *args):
1654 self.stop()
1655 self.join()
1656
Antoine Pitrou480a1242010-04-28 21:37:09 +00001657 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001658 self.flag = flag
1659 threading.Thread.start(self)
1660
Antoine Pitrou480a1242010-04-28 21:37:09 +00001661 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001662 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001663 self.sock.listen(5)
1664 self.active = True
1665 if self.flag:
1666 # signal an event
1667 self.flag.set()
1668 while self.active:
1669 try:
1670 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001671 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001672 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001673 + repr(connaddr) + '\n')
1674 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001675 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001676 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001677 except socket.timeout:
1678 pass
1679 except KeyboardInterrupt:
1680 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001681 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001682
Antoine Pitrou480a1242010-04-28 21:37:09 +00001683 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001684 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001685
Bill Janssen54cc54c2007-12-14 22:08:56 +00001686 class AsyncoreEchoServer(threading.Thread):
1687
1688 # this one's based on asyncore.dispatcher
1689
1690 class EchoServer (asyncore.dispatcher):
1691
1692 class ConnectionHandler (asyncore.dispatcher_with_send):
1693
1694 def __init__(self, conn, certfile):
1695 self.socket = ssl.wrap_socket(conn, server_side=True,
1696 certfile=certfile,
1697 do_handshake_on_connect=False)
1698 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001699 self._ssl_accepting = True
1700 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001701
1702 def readable(self):
1703 if isinstance(self.socket, ssl.SSLSocket):
1704 while self.socket.pending() > 0:
1705 self.handle_read_event()
1706 return True
1707
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001708 def _do_ssl_handshake(self):
1709 try:
1710 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001711 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1712 return
1713 except ssl.SSLEOFError:
1714 return self.handle_close()
1715 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001716 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001717 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001718 if err.args[0] == errno.ECONNABORTED:
1719 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001720 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001721 self._ssl_accepting = False
1722
1723 def handle_read(self):
1724 if self._ssl_accepting:
1725 self._do_ssl_handshake()
1726 else:
1727 data = self.recv(1024)
1728 if support.verbose:
1729 sys.stdout.write(" server: read %s from client\n" % repr(data))
1730 if not data:
1731 self.close()
1732 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001733 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001734
1735 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001736 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001737 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001738 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1739
1740 def handle_error(self):
1741 raise
1742
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001743 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001744 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001745 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1746 self.port = support.bind_port(sock, '')
1747 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001748 self.listen(5)
1749
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001750 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001751 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001752 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1753 self.ConnectionHandler(sock_obj, self.certfile)
1754
1755 def handle_error(self):
1756 raise
1757
Trent Nelson78520002008-04-10 20:54:35 +00001758 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001759 self.flag = None
1760 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001761 self.server = self.EchoServer(certfile)
1762 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001763 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001764 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001765
1766 def __str__(self):
1767 return "<%s %s>" % (self.__class__.__name__, self.server)
1768
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001769 def __enter__(self):
1770 self.start(threading.Event())
1771 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001772 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001773
1774 def __exit__(self, *args):
1775 if support.verbose:
1776 sys.stdout.write(" cleanup: stopping server.\n")
1777 self.stop()
1778 if support.verbose:
1779 sys.stdout.write(" cleanup: joining server thread.\n")
1780 self.join()
1781 if support.verbose:
1782 sys.stdout.write(" cleanup: successfully joined.\n")
1783
Bill Janssen54cc54c2007-12-14 22:08:56 +00001784 def start (self, flag=None):
1785 self.flag = flag
1786 threading.Thread.start(self)
1787
Antoine Pitrou480a1242010-04-28 21:37:09 +00001788 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001789 self.active = True
1790 if self.flag:
1791 self.flag.set()
1792 while self.active:
1793 try:
1794 asyncore.loop(1)
1795 except:
1796 pass
1797
Antoine Pitrou480a1242010-04-28 21:37:09 +00001798 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001799 self.active = False
1800 self.server.close()
1801
Antoine Pitrou480a1242010-04-28 21:37:09 +00001802 def bad_cert_test(certfile):
1803 """
1804 Launch a server with CERT_REQUIRED, and check that trying to
1805 connect to it with the given client certificate fails.
1806 """
Trent Nelson78520002008-04-10 20:54:35 +00001807 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001808 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001809 cacerts=CERTFILE, chatty=False,
1810 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001811 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001812 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001813 with socket.socket() as sock:
1814 s = ssl.wrap_socket(sock,
1815 certfile=certfile,
1816 ssl_version=ssl.PROTOCOL_TLSv1)
1817 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001818 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001819 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001820 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001821 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001822 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001823 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001824 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001825 if x.errno != errno.ENOENT:
1826 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001827 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001828 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001829 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001830 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001831
Antoine Pitroub5218772010-05-21 09:56:06 +00001832 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001833 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001834 """
1835 Launch a server, connect a client to it and try various reads
1836 and writes.
1837 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001838 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001839 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001840 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001841 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001842 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001843 with client_context.wrap_socket(socket.socket(),
1844 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001845 s.connect((HOST, server.port))
1846 for arg in [indata, bytearray(indata), memoryview(indata)]:
1847 if connectionchatty:
1848 if support.verbose:
1849 sys.stdout.write(
1850 " client: sending %r...\n" % indata)
1851 s.write(arg)
1852 outdata = s.read()
1853 if connectionchatty:
1854 if support.verbose:
1855 sys.stdout.write(" client: read %r\n" % outdata)
1856 if outdata != indata.lower():
1857 raise AssertionError(
1858 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1859 % (outdata[:20], len(outdata),
1860 indata[:20].lower(), len(indata)))
1861 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001862 if connectionchatty:
1863 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001864 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001865 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001866 'compression': s.compression(),
1867 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001868 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001869 'client_npn_protocol': s.selected_npn_protocol()
1870 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001871 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001872 stats['server_npn_protocols'] = server.selected_protocols
1873 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001874
Antoine Pitroub5218772010-05-21 09:56:06 +00001875 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1876 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001877 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001878 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001879 certtype = {
1880 ssl.CERT_NONE: "CERT_NONE",
1881 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1882 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1883 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001884 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001885 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001886 sys.stdout.write(formatstr %
1887 (ssl.get_protocol_name(client_protocol),
1888 ssl.get_protocol_name(server_protocol),
1889 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001890 client_context = ssl.SSLContext(client_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001891 client_context.options |= client_options
Antoine Pitroub5218772010-05-21 09:56:06 +00001892 server_context = ssl.SSLContext(server_protocol)
Antoine Pitrou32c49152014-01-09 21:28:48 +01001893 server_context.options |= server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001894
1895 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1896 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1897 # starting from OpenSSL 1.0.0 (see issue #8322).
1898 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1899 client_context.set_ciphers("ALL")
1900
Antoine Pitroub5218772010-05-21 09:56:06 +00001901 for ctx in (client_context, server_context):
1902 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001903 ctx.load_cert_chain(CERTFILE)
1904 ctx.load_verify_locations(CERTFILE)
1905 try:
1906 server_params_test(client_context, server_context,
1907 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001908 # Protocol mismatch can result in either an SSLError, or a
1909 # "Connection reset by peer" error.
1910 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001911 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001912 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001913 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001914 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001915 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001916 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001917 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001918 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001919 "Client protocol %s succeeded with server protocol %s!"
1920 % (ssl.get_protocol_name(client_protocol),
1921 ssl.get_protocol_name(server_protocol)))
1922
1923
Bill Janssen6e027db2007-11-15 22:23:56 +00001924 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001925
Antoine Pitrou23df4832010-08-04 17:14:06 +00001926 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001927 def test_echo(self):
1928 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001929 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001930 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001931 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001932 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1933 context = ssl.SSLContext(protocol)
1934 context.load_cert_chain(CERTFILE)
1935 server_params_test(context, context,
1936 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001937
Antoine Pitrou480a1242010-04-28 21:37:09 +00001938 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001939 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001940 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001941 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1942 context.verify_mode = ssl.CERT_REQUIRED
1943 context.load_verify_locations(CERTFILE)
1944 context.load_cert_chain(CERTFILE)
1945 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001946 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02001947 s = context.wrap_socket(socket.socket(),
1948 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001949 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02001950 # getpeercert() raise ValueError while the handshake isn't
1951 # done.
1952 with self.assertRaises(ValueError):
1953 s.getpeercert()
1954 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001955 cert = s.getpeercert()
1956 self.assertTrue(cert, "Can't get peer certificate.")
1957 cipher = s.cipher()
1958 if support.verbose:
1959 sys.stdout.write(pprint.pformat(cert) + '\n')
1960 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1961 if 'subject' not in cert:
1962 self.fail("No subject field in certificate: %s." %
1963 pprint.pformat(cert))
1964 if ((('organizationName', 'Python Software Foundation'),)
1965 not in cert['subject']):
1966 self.fail(
1967 "Missing or invalid 'organizationName' field in certificate subject; "
1968 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001969 self.assertIn('notBefore', cert)
1970 self.assertIn('notAfter', cert)
1971 before = ssl.cert_time_to_seconds(cert['notBefore'])
1972 after = ssl.cert_time_to_seconds(cert['notAfter'])
1973 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001974 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001975
Christian Heimes2427b502013-11-23 11:24:32 +01001976 @unittest.skipUnless(have_verify_flags(),
1977 "verify_flags need OpenSSL > 0.9.8")
Christian Heimes22587792013-11-21 23:56:13 +01001978 def test_crl_check(self):
1979 if support.verbose:
1980 sys.stdout.write("\n")
1981
1982 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1983 server_context.load_cert_chain(SIGNED_CERTFILE)
1984
1985 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1986 context.verify_mode = ssl.CERT_REQUIRED
1987 context.load_verify_locations(SIGNING_CA)
Christian Heimes32f0c7a2013-11-22 03:43:48 +01001988 self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT)
Christian Heimes22587792013-11-21 23:56:13 +01001989
1990 # VERIFY_DEFAULT should pass
1991 server = ThreadedEchoServer(context=server_context, chatty=True)
1992 with server:
1993 with context.wrap_socket(socket.socket()) as s:
1994 s.connect((HOST, server.port))
1995 cert = s.getpeercert()
1996 self.assertTrue(cert, "Can't get peer certificate.")
1997
1998 # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails
Christian Heimes32f0c7a2013-11-22 03:43:48 +01001999 context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF
Christian Heimes22587792013-11-21 23:56:13 +01002000
2001 server = ThreadedEchoServer(context=server_context, chatty=True)
2002 with server:
2003 with context.wrap_socket(socket.socket()) as s:
2004 with self.assertRaisesRegex(ssl.SSLError,
2005 "certificate verify failed"):
2006 s.connect((HOST, server.port))
2007
2008 # now load a CRL file. The CRL file is signed by the CA.
2009 context.load_verify_locations(CRLFILE)
2010
2011 server = ThreadedEchoServer(context=server_context, chatty=True)
2012 with server:
2013 with context.wrap_socket(socket.socket()) as s:
2014 s.connect((HOST, server.port))
2015 cert = s.getpeercert()
2016 self.assertTrue(cert, "Can't get peer certificate.")
2017
Christian Heimes575596e2013-12-15 21:49:17 +01002018 @needs_sni
Christian Heimes1aa9a752013-12-02 02:41:19 +01002019 def test_check_hostname(self):
2020 if support.verbose:
2021 sys.stdout.write("\n")
2022
2023 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2024 server_context.load_cert_chain(SIGNED_CERTFILE)
2025
2026 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2027 context.verify_mode = ssl.CERT_REQUIRED
2028 context.check_hostname = True
2029 context.load_verify_locations(SIGNING_CA)
2030
2031 # correct hostname should verify
2032 server = ThreadedEchoServer(context=server_context, chatty=True)
2033 with server:
2034 with context.wrap_socket(socket.socket(),
2035 server_hostname="localhost") as s:
2036 s.connect((HOST, server.port))
2037 cert = s.getpeercert()
2038 self.assertTrue(cert, "Can't get peer certificate.")
2039
2040 # incorrect hostname should raise an exception
2041 server = ThreadedEchoServer(context=server_context, chatty=True)
2042 with server:
2043 with context.wrap_socket(socket.socket(),
2044 server_hostname="invalid") as s:
2045 with self.assertRaisesRegex(ssl.CertificateError,
2046 "hostname 'invalid' doesn't match 'localhost'"):
2047 s.connect((HOST, server.port))
2048
2049 # missing server_hostname arg should cause an exception, too
2050 server = ThreadedEchoServer(context=server_context, chatty=True)
2051 with server:
2052 with socket.socket() as s:
2053 with self.assertRaisesRegex(ValueError,
2054 "check_hostname requires server_hostname"):
2055 context.wrap_socket(s)
2056
Antoine Pitrou480a1242010-04-28 21:37:09 +00002057 def test_empty_cert(self):
2058 """Connecting with an empty cert file"""
2059 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2060 "nullcert.pem"))
2061 def test_malformed_cert(self):
2062 """Connecting with a badly formatted certificate (syntax error)"""
2063 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2064 "badcert.pem"))
2065 def test_nonexisting_cert(self):
2066 """Connecting with a non-existing cert file"""
2067 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2068 "wrongcert.pem"))
2069 def test_malformed_key(self):
2070 """Connecting with a badly formatted key (syntax error)"""
2071 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
2072 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002073
Antoine Pitrou480a1242010-04-28 21:37:09 +00002074 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002075 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00002076 in the client when attempting handshake.
2077 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00002078 listener_ready = threading.Event()
2079 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00002080
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002081 s = socket.socket()
2082 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002083
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002084 # `listener` runs in a thread. It sits in an accept() until
2085 # the main thread connects. Then it rudely closes the socket,
2086 # and sets Event `listener_gone` to let the main thread know
2087 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00002088 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00002089 s.listen(5)
2090 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002091 newsock, addr = s.accept()
2092 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002093 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002094 listener_gone.set()
2095
2096 def connector():
2097 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00002098 with socket.socket() as c:
2099 c.connect((HOST, port))
2100 listener_gone.wait()
2101 try:
2102 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02002103 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00002104 pass
2105 else:
2106 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00002107
2108 t = threading.Thread(target=listener)
2109 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00002110 try:
2111 connector()
2112 finally:
2113 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00002114
Antoine Pitrou23df4832010-08-04 17:14:06 +00002115 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02002116 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
2117 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002118 def test_protocol_sslv2(self):
2119 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002120 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002121 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002122 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
2123 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
2124 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002125 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002126 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
2127 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002128 # SSLv23 client with specific SSL options
2129 if no_sslv2_implies_sslv3_hello():
2130 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2131 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
2132 client_options=ssl.OP_NO_SSLv2)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002133 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002134 client_options=ssl.OP_NO_SSLv3)
Antoine Pitroucd3d7ca2014-01-09 20:02:20 +01002135 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
Antoine Pitroub5218772010-05-21 09:56:06 +00002136 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002137
Antoine Pitrou23df4832010-08-04 17:14:06 +00002138 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002139 def test_protocol_sslv23(self):
2140 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002141 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002142 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02002143 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2144 try:
2145 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02002146 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02002147 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
2148 if support.verbose:
2149 sys.stdout.write(
2150 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
2151 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00002152 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
2153 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
2154 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002155
Antoine Pitrou480a1242010-04-28 21:37:09 +00002156 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2157 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
2158 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002159
Antoine Pitrou480a1242010-04-28 21:37:09 +00002160 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
2161 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
2162 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002163
Antoine Pitroub5218772010-05-21 09:56:06 +00002164 # Server with specific SSL options
2165 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
2166 server_options=ssl.OP_NO_SSLv3)
2167 # Will choose TLSv1
2168 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
2169 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
2170 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
2171 server_options=ssl.OP_NO_TLSv1)
2172
2173
Antoine Pitrou23df4832010-08-04 17:14:06 +00002174 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002175 def test_protocol_sslv3(self):
2176 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002177 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002178 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002179 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
2180 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
2181 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002182 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2183 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002184 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
2185 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002186 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00002187 if no_sslv2_implies_sslv3_hello():
2188 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
2189 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
2190 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002191
Antoine Pitrou23df4832010-08-04 17:14:06 +00002192 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00002193 def test_protocol_tlsv1(self):
2194 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002195 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002196 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00002197 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
2198 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
2199 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02002200 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2201 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002202 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04002203 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
2204 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002205
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01002206 @skip_if_broken_ubuntu_ssl
2207 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
2208 "TLS version 1.1 not supported.")
2209 def test_protocol_tlsv1_1(self):
2210 """Connecting to a TLSv1.1 server with various client options.
2211 Testing against older TLS versions."""
2212 if support.verbose:
2213 sys.stdout.write("\n")
2214 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
2215 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2216 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
2217 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
2218 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
2219 client_options=ssl.OP_NO_TLSv1_1)
2220
2221 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
2222 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
2223 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
2224
2225
2226 @skip_if_broken_ubuntu_ssl
2227 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
2228 "TLS version 1.2 not supported.")
2229 def test_protocol_tlsv1_2(self):
2230 """Connecting to a TLSv1.2 server with various client options.
2231 Testing against older TLS versions."""
2232 if support.verbose:
2233 sys.stdout.write("\n")
2234 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
2235 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
2236 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
2237 if hasattr(ssl, 'PROTOCOL_SSLv2'):
2238 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
2239 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
2240 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
2241 client_options=ssl.OP_NO_TLSv1_2)
2242
2243 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
2244 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
2245 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
2246 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
2247 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
2248
Antoine Pitrou480a1242010-04-28 21:37:09 +00002249 def test_starttls(self):
2250 """Switching from clear text to encrypted and back again."""
2251 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 +00002252
Trent Nelson78520002008-04-10 20:54:35 +00002253 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002254 ssl_version=ssl.PROTOCOL_TLSv1,
2255 starttls_server=True,
2256 chatty=True,
2257 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002258 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002259 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002260 s = socket.socket()
2261 s.setblocking(1)
2262 s.connect((HOST, server.port))
2263 if support.verbose:
2264 sys.stdout.write("\n")
2265 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002266 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002267 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002268 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002269 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002270 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002271 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002272 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002273 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002274 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00002275 msg = outdata.strip().lower()
2276 if indata == b"STARTTLS" and msg.startswith(b"ok"):
2277 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002278 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002279 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002280 " client: read %r from server, starting TLS...\n"
2281 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002282 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
2283 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00002284 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
2285 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002286 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002287 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002288 " client: read %r from server, ending TLS...\n"
2289 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002290 s = conn.unwrap()
2291 wrapped = False
2292 else:
2293 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002294 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002295 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002296 if support.verbose:
2297 sys.stdout.write(" client: closing connection.\n")
2298 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002299 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002300 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002301 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00002302 if wrapped:
2303 conn.close()
2304 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002305 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002306
Antoine Pitrou480a1242010-04-28 21:37:09 +00002307 def test_socketserver(self):
2308 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01002309 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002310 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002311 if support.verbose:
2312 sys.stdout.write('\n')
2313 with open(CERTFILE, 'rb') as f:
2314 d1 = f.read()
2315 d2 = ''
2316 # now fetch the same data from the HTTPS server
2317 url = 'https://%s:%d/%s' % (
2318 HOST, server.port, os.path.split(CERTFILE)[1])
2319 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002320 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00002321 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002322 if dlen and (int(dlen) > 0):
2323 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002324 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002325 sys.stdout.write(
2326 " client: read %d bytes from remote server '%s'\n"
2327 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002328 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00002329 f.close()
2330 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002331
Antoine Pitrou480a1242010-04-28 21:37:09 +00002332 def test_asyncore_server(self):
2333 """Check the example asyncore integration."""
2334 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00002335
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002336 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002337 sys.stdout.write("\n")
2338
Antoine Pitrou480a1242010-04-28 21:37:09 +00002339 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00002340 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002341 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002342 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002343 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002344 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002345 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002346 " client: sending %r...\n" % indata)
2347 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002348 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002349 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002350 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00002351 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00002352 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00002353 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
2354 % (outdata[:20], len(outdata),
2355 indata[:20].lower(), len(indata)))
2356 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002357 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00002358 sys.stdout.write(" client: closing connection.\n")
2359 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00002360 if support.verbose:
2361 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00002362
Antoine Pitrou480a1242010-04-28 21:37:09 +00002363 def test_recv_send(self):
2364 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00002365 if support.verbose:
2366 sys.stdout.write("\n")
2367
2368 server = ThreadedEchoServer(CERTFILE,
2369 certreqs=ssl.CERT_NONE,
2370 ssl_version=ssl.PROTOCOL_TLSv1,
2371 cacerts=CERTFILE,
2372 chatty=True,
2373 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01002374 with server:
2375 s = ssl.wrap_socket(socket.socket(),
2376 server_side=False,
2377 certfile=CERTFILE,
2378 ca_certs=CERTFILE,
2379 cert_reqs=ssl.CERT_NONE,
2380 ssl_version=ssl.PROTOCOL_TLSv1)
2381 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00002382 # helper methods for standardising recv* method signatures
2383 def _recv_into():
2384 b = bytearray(b"\0"*100)
2385 count = s.recv_into(b)
2386 return b[:count]
2387
2388 def _recvfrom_into():
2389 b = bytearray(b"\0"*100)
2390 count, addr = s.recvfrom_into(b)
2391 return b[:count]
2392
2393 # (name, method, whether to expect success, *args)
2394 send_methods = [
2395 ('send', s.send, True, []),
2396 ('sendto', s.sendto, False, ["some.address"]),
2397 ('sendall', s.sendall, True, []),
2398 ]
2399 recv_methods = [
2400 ('recv', s.recv, True, []),
2401 ('recvfrom', s.recvfrom, False, ["some.address"]),
2402 ('recv_into', _recv_into, True, []),
2403 ('recvfrom_into', _recvfrom_into, False, []),
2404 ]
2405 data_prefix = "PREFIX_"
2406
2407 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002408 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002409 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002410 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002411 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002412 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002413 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002414 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002415 "<<{outdata:r}>> ({nout:d}) received; "
2416 "expected <<{indata:r}>> ({nin:d})\n".format(
2417 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002418 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002419 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002420 )
2421 )
2422 except ValueError as e:
2423 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002424 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002425 "Failed to send with method <<{name:s}>>; "
2426 "expected to succeed.\n".format(name=meth_name)
2427 )
2428 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002429 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002430 "Method <<{name:s}>> failed with unexpected "
2431 "exception message: {exp:s}\n".format(
2432 name=meth_name, exp=e
2433 )
2434 )
2435
2436 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002437 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002438 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002439 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002440 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002441 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002442 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002443 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002444 "<<{outdata:r}>> ({nout:d}) received; "
2445 "expected <<{indata:r}>> ({nin:d})\n".format(
2446 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002447 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002448 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002449 )
2450 )
2451 except ValueError as e:
2452 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002453 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002454 "Failed to receive with method <<{name:s}>>; "
2455 "expected to succeed.\n".format(name=meth_name)
2456 )
2457 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002458 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002459 "Method <<{name:s}>> failed with unexpected "
2460 "exception message: {exp:s}\n".format(
2461 name=meth_name, exp=e
2462 )
2463 )
2464 # consume data
2465 s.read()
2466
Nick Coghlan513886a2011-08-28 00:00:27 +10002467 # Make sure sendmsg et al are disallowed to avoid
2468 # inadvertent disclosure of data and/or corruption
2469 # of the encrypted data stream
2470 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2471 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2472 self.assertRaises(NotImplementedError,
2473 s.recvmsg_into, bytearray(100))
2474
Antoine Pitrou480a1242010-04-28 21:37:09 +00002475 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002476 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002477
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002478 def test_handshake_timeout(self):
2479 # Issue #5103: SSL handshake must respect the socket timeout
2480 server = socket.socket(socket.AF_INET)
2481 host = "127.0.0.1"
2482 port = support.bind_port(server)
2483 started = threading.Event()
2484 finish = False
2485
2486 def serve():
2487 server.listen(5)
2488 started.set()
2489 conns = []
2490 while not finish:
2491 r, w, e = select.select([server], [], [], 0.1)
2492 if server in r:
2493 # Let the socket hang around rather than having
2494 # it closed by garbage collection.
2495 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002496 for sock in conns:
2497 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002498
2499 t = threading.Thread(target=serve)
2500 t.start()
2501 started.wait()
2502
2503 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002504 try:
2505 c = socket.socket(socket.AF_INET)
2506 c.settimeout(0.2)
2507 c.connect((host, port))
2508 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002509 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002510 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002511 finally:
2512 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002513 try:
2514 c = socket.socket(socket.AF_INET)
2515 c = ssl.wrap_socket(c)
2516 c.settimeout(0.2)
2517 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002518 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002519 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002520 finally:
2521 c.close()
2522 finally:
2523 finish = True
2524 t.join()
2525 server.close()
2526
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002527 def test_server_accept(self):
2528 # Issue #16357: accept() on a SSLSocket created through
2529 # SSLContext.wrap_socket().
2530 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2531 context.verify_mode = ssl.CERT_REQUIRED
2532 context.load_verify_locations(CERTFILE)
2533 context.load_cert_chain(CERTFILE)
2534 server = socket.socket(socket.AF_INET)
2535 host = "127.0.0.1"
2536 port = support.bind_port(server)
2537 server = context.wrap_socket(server, server_side=True)
2538
2539 evt = threading.Event()
2540 remote = None
2541 peer = None
2542 def serve():
2543 nonlocal remote, peer
2544 server.listen(5)
2545 # Block on the accept and wait on the connection to close.
2546 evt.set()
2547 remote, peer = server.accept()
2548 remote.recv(1)
2549
2550 t = threading.Thread(target=serve)
2551 t.start()
2552 # Client wait until server setup and perform a connect.
2553 evt.wait()
2554 client = context.wrap_socket(socket.socket())
2555 client.connect((host, port))
2556 client_addr = client.getsockname()
2557 client.close()
2558 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002559 remote.close()
2560 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002561 # Sanity checks.
2562 self.assertIsInstance(remote, ssl.SSLSocket)
2563 self.assertEqual(peer, client_addr)
2564
Antoine Pitrou242db722013-05-01 20:52:07 +02002565 def test_getpeercert_enotconn(self):
2566 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2567 with context.wrap_socket(socket.socket()) as sock:
2568 with self.assertRaises(OSError) as cm:
2569 sock.getpeercert()
2570 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2571
2572 def test_do_handshake_enotconn(self):
2573 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2574 with context.wrap_socket(socket.socket()) as sock:
2575 with self.assertRaises(OSError) as cm:
2576 sock.do_handshake()
2577 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2578
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002579 def test_default_ciphers(self):
2580 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2581 try:
2582 # Force a set of weak ciphers on our client context
2583 context.set_ciphers("DES")
2584 except ssl.SSLError:
2585 self.skipTest("no DES cipher available")
2586 with ThreadedEchoServer(CERTFILE,
2587 ssl_version=ssl.PROTOCOL_SSLv23,
2588 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002589 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002590 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002591 s.connect((HOST, server.port))
2592 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2593
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002594 @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
2595 def test_default_ecdh_curve(self):
2596 # Issue #21015: elliptic curve-based Diffie Hellman key exchange
2597 # should be enabled by default on SSL contexts.
2598 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2599 context.load_cert_chain(CERTFILE)
Antoine Pitrouc0430612014-04-16 18:33:39 +02002600 # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
2601 # explicitly using the 'ECCdraft' cipher alias. Otherwise,
2602 # our default cipher list should prefer ECDH-based ciphers
2603 # automatically.
2604 if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
2605 context.set_ciphers("ECCdraft:ECDH")
Antoine Pitrou0bebbc32014-03-22 18:13:50 +01002606 with ThreadedEchoServer(context=context) as server:
2607 with context.wrap_socket(socket.socket()) as s:
2608 s.connect((HOST, server.port))
2609 self.assertIn("ECDH", s.cipher()[0])
2610
Antoine Pitroud6494802011-07-21 01:11:30 +02002611 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2612 "'tls-unique' channel binding not available")
2613 def test_tls_unique_channel_binding(self):
2614 """Test tls-unique channel binding."""
2615 if support.verbose:
2616 sys.stdout.write("\n")
2617
2618 server = ThreadedEchoServer(CERTFILE,
2619 certreqs=ssl.CERT_NONE,
2620 ssl_version=ssl.PROTOCOL_TLSv1,
2621 cacerts=CERTFILE,
2622 chatty=True,
2623 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002624 with server:
2625 s = ssl.wrap_socket(socket.socket(),
2626 server_side=False,
2627 certfile=CERTFILE,
2628 ca_certs=CERTFILE,
2629 cert_reqs=ssl.CERT_NONE,
2630 ssl_version=ssl.PROTOCOL_TLSv1)
2631 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002632 # get the data
2633 cb_data = s.get_channel_binding("tls-unique")
2634 if support.verbose:
2635 sys.stdout.write(" got channel binding data: {0!r}\n"
2636 .format(cb_data))
2637
2638 # check if it is sane
2639 self.assertIsNotNone(cb_data)
2640 self.assertEqual(len(cb_data), 12) # True for TLSv1
2641
2642 # and compare with the peers version
2643 s.write(b"CB tls-unique\n")
2644 peer_data_repr = s.read().strip()
2645 self.assertEqual(peer_data_repr,
2646 repr(cb_data).encode("us-ascii"))
2647 s.close()
2648
2649 # now, again
2650 s = ssl.wrap_socket(socket.socket(),
2651 server_side=False,
2652 certfile=CERTFILE,
2653 ca_certs=CERTFILE,
2654 cert_reqs=ssl.CERT_NONE,
2655 ssl_version=ssl.PROTOCOL_TLSv1)
2656 s.connect((HOST, server.port))
2657 new_cb_data = s.get_channel_binding("tls-unique")
2658 if support.verbose:
2659 sys.stdout.write(" got another channel binding data: {0!r}\n"
2660 .format(new_cb_data))
2661 # is it really unique
2662 self.assertNotEqual(cb_data, new_cb_data)
2663 self.assertIsNotNone(cb_data)
2664 self.assertEqual(len(cb_data), 12) # True for TLSv1
2665 s.write(b"CB tls-unique\n")
2666 peer_data_repr = s.read().strip()
2667 self.assertEqual(peer_data_repr,
2668 repr(new_cb_data).encode("us-ascii"))
2669 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002670
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002671 def test_compression(self):
2672 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2673 context.load_cert_chain(CERTFILE)
2674 stats = server_params_test(context, context,
2675 chatty=True, connectionchatty=True)
2676 if support.verbose:
2677 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2678 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2679
2680 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2681 "ssl.OP_NO_COMPRESSION needed for this test")
2682 def test_compression_disabled(self):
2683 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2684 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002685 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002686 stats = server_params_test(context, context,
2687 chatty=True, connectionchatty=True)
2688 self.assertIs(stats['compression'], None)
2689
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002690 def test_dh_params(self):
2691 # Check we can get a connection with ephemeral Diffie-Hellman
2692 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2693 context.load_cert_chain(CERTFILE)
2694 context.load_dh_params(DHFILE)
2695 context.set_ciphers("kEDH")
2696 stats = server_params_test(context, context,
2697 chatty=True, connectionchatty=True)
2698 cipher = stats["cipher"][0]
2699 parts = cipher.split("-")
2700 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2701 self.fail("Non-DH cipher: " + cipher[0])
2702
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002703 def test_selected_npn_protocol(self):
2704 # selected_npn_protocol() is None unless NPN is used
2705 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2706 context.load_cert_chain(CERTFILE)
2707 stats = server_params_test(context, context,
2708 chatty=True, connectionchatty=True)
2709 self.assertIs(stats['client_npn_protocol'], None)
2710
2711 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2712 def test_npn_protocols(self):
2713 server_protocols = ['http/1.1', 'spdy/2']
2714 protocol_tests = [
2715 (['http/1.1', 'spdy/2'], 'http/1.1'),
2716 (['spdy/2', 'http/1.1'], 'http/1.1'),
2717 (['spdy/2', 'test'], 'spdy/2'),
2718 (['abc', 'def'], 'abc')
2719 ]
2720 for client_protocols, expected in protocol_tests:
2721 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2722 server_context.load_cert_chain(CERTFILE)
2723 server_context.set_npn_protocols(server_protocols)
2724 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2725 client_context.load_cert_chain(CERTFILE)
2726 client_context.set_npn_protocols(client_protocols)
2727 stats = server_params_test(client_context, server_context,
2728 chatty=True, connectionchatty=True)
2729
2730 msg = "failed trying %s (s) and %s (c).\n" \
2731 "was expecting %s, but got %%s from the %%s" \
2732 % (str(server_protocols), str(client_protocols),
2733 str(expected))
2734 client_result = stats['client_npn_protocol']
2735 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2736 server_result = stats['server_npn_protocols'][-1] \
2737 if len(stats['server_npn_protocols']) else 'nothing'
2738 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2739
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002740 def sni_contexts(self):
2741 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2742 server_context.load_cert_chain(SIGNED_CERTFILE)
2743 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2744 other_context.load_cert_chain(SIGNED_CERTFILE2)
2745 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2746 client_context.verify_mode = ssl.CERT_REQUIRED
2747 client_context.load_verify_locations(SIGNING_CA)
2748 return server_context, other_context, client_context
2749
2750 def check_common_name(self, stats, name):
2751 cert = stats['peercert']
2752 self.assertIn((('commonName', name),), cert['subject'])
2753
2754 @needs_sni
2755 def test_sni_callback(self):
2756 calls = []
2757 server_context, other_context, client_context = self.sni_contexts()
2758
2759 def servername_cb(ssl_sock, server_name, initial_context):
2760 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002761 if server_name is not None:
2762 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002763 server_context.set_servername_callback(servername_cb)
2764
2765 stats = server_params_test(client_context, server_context,
2766 chatty=True,
2767 sni_name='supermessage')
2768 # The hostname was fetched properly, and the certificate was
2769 # changed for the connection.
2770 self.assertEqual(calls, [("supermessage", server_context)])
2771 # CERTFILE4 was selected
2772 self.check_common_name(stats, 'fakehostname')
2773
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002774 calls = []
2775 # The callback is called with server_name=None
2776 stats = server_params_test(client_context, server_context,
2777 chatty=True,
2778 sni_name=None)
2779 self.assertEqual(calls, [(None, server_context)])
2780 self.check_common_name(stats, 'localhost')
2781
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002782 # Check disabling the callback
2783 calls = []
2784 server_context.set_servername_callback(None)
2785
2786 stats = server_params_test(client_context, server_context,
2787 chatty=True,
2788 sni_name='notfunny')
2789 # Certificate didn't change
2790 self.check_common_name(stats, 'localhost')
2791 self.assertEqual(calls, [])
2792
2793 @needs_sni
2794 def test_sni_callback_alert(self):
2795 # Returning a TLS alert is reflected to the connecting client
2796 server_context, other_context, client_context = self.sni_contexts()
2797
2798 def cb_returning_alert(ssl_sock, server_name, initial_context):
2799 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2800 server_context.set_servername_callback(cb_returning_alert)
2801
2802 with self.assertRaises(ssl.SSLError) as cm:
2803 stats = server_params_test(client_context, server_context,
2804 chatty=False,
2805 sni_name='supermessage')
2806 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2807
2808 @needs_sni
2809 def test_sni_callback_raising(self):
2810 # Raising fails the connection with a TLS handshake failure alert.
2811 server_context, other_context, client_context = self.sni_contexts()
2812
2813 def cb_raising(ssl_sock, server_name, initial_context):
2814 1/0
2815 server_context.set_servername_callback(cb_raising)
2816
2817 with self.assertRaises(ssl.SSLError) as cm, \
2818 support.captured_stderr() as stderr:
2819 stats = server_params_test(client_context, server_context,
2820 chatty=False,
2821 sni_name='supermessage')
2822 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2823 self.assertIn("ZeroDivisionError", stderr.getvalue())
2824
2825 @needs_sni
2826 def test_sni_callback_wrong_return_type(self):
2827 # Returning the wrong return type terminates the TLS connection
2828 # with an internal error alert.
2829 server_context, other_context, client_context = self.sni_contexts()
2830
2831 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2832 return "foo"
2833 server_context.set_servername_callback(cb_wrong_return_type)
2834
2835 with self.assertRaises(ssl.SSLError) as cm, \
2836 support.captured_stderr() as stderr:
2837 stats = server_params_test(client_context, server_context,
2838 chatty=False,
2839 sni_name='supermessage')
2840 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2841 self.assertIn("TypeError", stderr.getvalue())
2842
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002843 def test_read_write_after_close_raises_valuerror(self):
2844 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2845 context.verify_mode = ssl.CERT_REQUIRED
2846 context.load_verify_locations(CERTFILE)
2847 context.load_cert_chain(CERTFILE)
2848 server = ThreadedEchoServer(context=context, chatty=False)
2849
2850 with server:
2851 s = context.wrap_socket(socket.socket())
2852 s.connect((HOST, server.port))
2853 s.close()
2854
2855 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02002856 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002857
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002858
Thomas Woutersed03b412007-08-28 21:37:11 +00002859def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002860 if support.verbose:
2861 plats = {
2862 'Linux': platform.linux_distribution,
2863 'Mac': platform.mac_ver,
2864 'Windows': platform.win32_ver,
2865 }
2866 for name, func in plats.items():
2867 plat = func()
2868 if plat and plat[0]:
2869 plat = '%s %r' % (name, plat)
2870 break
2871 else:
2872 plat = repr(platform.platform())
2873 print("test_ssl: testing with %r %r" %
2874 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2875 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002876 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002877 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2878 try:
2879 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2880 except AttributeError:
2881 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002882
Antoine Pitrou152efa22010-05-16 18:19:27 +00002883 for filename in [
2884 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2885 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002886 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002887 BADCERT, BADKEY, EMPTYCERT]:
2888 if not os.path.exists(filename):
2889 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002890
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002891 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002892
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002893 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002894 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002895
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002896 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002897 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002898 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002899 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002900
Antoine Pitrou480a1242010-04-28 21:37:09 +00002901 try:
2902 support.run_unittest(*tests)
2903 finally:
2904 if _have_threads:
2905 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002906
2907if __name__ == "__main__":
2908 test_main()