blob: 2605e68cceda24af37b402c2cf49add0891d4e7f [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
28data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000029
Antoine Pitrou81564092010-10-08 23:06:24 +000030# The custom key and certificate files used in test_ssl are generated
31# using Lib/test/make_ssl_certs.py.
32# Other certificates are simply fetched from the Internet servers they
33# are meant to authenticate.
34
Antoine Pitrou152efa22010-05-16 18:19:27 +000035CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000036BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000037ONLYCERT = data_file("ssl_cert.pem")
38ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000039BYTES_ONLYCERT = os.fsencode(ONLYCERT)
40BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020041CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
42ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
43KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000044CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000045BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000046
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010047# Two keys and certs signed by the same CA (for SNI tests)
48SIGNED_CERTFILE = data_file("keycert3.pem")
49SIGNED_CERTFILE2 = data_file("keycert4.pem")
50SIGNING_CA = data_file("pycacert.pem")
51
Antoine Pitrou152efa22010-05-16 18:19:27 +000052SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
53
54EMPTYCERT = data_file("nullcert.pem")
55BADCERT = data_file("badcert.pem")
56WRONGCERT = data_file("XXXnonexisting.pem")
57BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020058NOKIACERT = data_file("nokia.pem")
Christian Heimes824f7f32013-08-17 00:54:47 +020059NULLBYTECERT = data_file("nullbytecert.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000060
Antoine Pitrou0e576f12011-12-22 10:03:38 +010061DHFILE = data_file("dh512.pem")
62BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000063
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010064
Thomas Woutersed03b412007-08-28 21:37:11 +000065def handle_error(prefix):
66 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000067 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000068 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitroub5218772010-05-21 09:56:06 +000070def can_clear_options():
71 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020072 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000073
74def no_sslv2_implies_sslv3_hello():
75 # 0.9.7h or higher
76 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
77
Christian Heimes9424bb42013-06-17 15:32:57 +020078def asn1time(cert_time):
79 # Some versions of OpenSSL ignore seconds, see #18207
80 # 0.9.8.i
81 if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15):
82 fmt = "%b %d %H:%M:%S %Y GMT"
83 dt = datetime.datetime.strptime(cert_time, fmt)
84 dt = dt.replace(second=0)
85 cert_time = dt.strftime(fmt)
86 # %d adds leading zero but ASN1_TIME_print() uses leading space
87 if cert_time[4] == "0":
88 cert_time = cert_time[:4] + " " + cert_time[5:]
89
90 return cert_time
Thomas Woutersed03b412007-08-28 21:37:11 +000091
Antoine Pitrou23df4832010-08-04 17:14:06 +000092# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
93def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020094 if hasattr(ssl, 'PROTOCOL_SSLv2'):
95 @functools.wraps(func)
96 def f(*args, **kwargs):
97 try:
98 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
99 except ssl.SSLError:
100 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
101 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
102 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
103 return func(*args, **kwargs)
104 return f
105 else:
106 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +0000107
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100108needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
109
Antoine Pitrou23df4832010-08-04 17:14:06 +0000110
Antoine Pitrou152efa22010-05-16 18:19:27 +0000111class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +0000112
Antoine Pitrou480a1242010-04-28 21:37:09 +0000113 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 ssl.CERT_NONE
115 ssl.CERT_OPTIONAL
116 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100117 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100118 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100119 if ssl.HAS_ECDH:
120 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100121 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
122 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000123 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100124 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000125
Antoine Pitrou480a1242010-04-28 21:37:09 +0000126 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000127 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000128 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 sys.stdout.write("\n RAND_status is %d (%s)\n"
130 % (v, (v and "sufficient randomness") or
131 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200132
133 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
134 self.assertEqual(len(data), 16)
135 self.assertEqual(is_cryptographic, v == 1)
136 if v:
137 data = ssl.RAND_bytes(16)
138 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200139 else:
140 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200141
Jesus Ceac8754a12012-09-11 02:00:58 +0200142 self.assertRaises(TypeError, ssl.RAND_egd, 1)
143 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000144 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000145
Christian Heimesf77b4b22013-08-21 13:26:05 +0200146 @unittest.skipUnless(os.name == 'posix', 'requires posix')
147 def test_random_fork(self):
148 status = ssl.RAND_status()
149 if not status:
150 self.fail("OpenSSL's PRNG has insufficient randomness")
151
152 rfd, wfd = os.pipe()
153 pid = os.fork()
154 if pid == 0:
155 try:
156 os.close(rfd)
157 child_random = ssl.RAND_pseudo_bytes(16)[0]
158 self.assertEqual(len(child_random), 16)
159 os.write(wfd, child_random)
160 os.close(wfd)
161 except BaseException:
162 os._exit(1)
163 else:
164 os._exit(0)
165 else:
166 os.close(wfd)
167 self.addCleanup(os.close, rfd)
168 _, status = os.waitpid(pid, 0)
169 self.assertEqual(status, 0)
170
171 child_random = os.read(rfd, 16)
172 self.assertEqual(len(child_random), 16)
173 parent_random = ssl.RAND_pseudo_bytes(16)[0]
174 self.assertEqual(len(parent_random), 16)
175
176 self.assertNotEqual(child_random, parent_random)
177
Antoine Pitrou480a1242010-04-28 21:37:09 +0000178 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000179 # note that this uses an 'unofficial' function in _ssl.c,
180 # provided solely for this test, to exercise the certificate
181 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000182 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000183 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000184 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200185 self.assertEqual(p['issuer'],
186 ((('countryName', 'XY'),),
187 (('localityName', 'Castle Anthrax'),),
188 (('organizationName', 'Python Software Foundation'),),
189 (('commonName', 'localhost'),))
190 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100191 # Note the next three asserts will fail if the keys are regenerated
Christian Heimes9424bb42013-06-17 15:32:57 +0200192 self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT'))
193 self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT'))
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200194 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
195 self.assertEqual(p['subject'],
196 ((('countryName', 'XY'),),
197 (('localityName', 'Castle Anthrax'),),
198 (('organizationName', 'Python Software Foundation'),),
199 (('commonName', 'localhost'),))
200 )
201 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
202 # Issue #13034: the subjectAltName in some certificates
203 # (notably projects.developer.nokia.com:443) wasn't parsed
204 p = ssl._ssl._test_decode_cert(NOKIACERT)
205 if support.verbose:
206 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
207 self.assertEqual(p['subjectAltName'],
208 (('DNS', 'projects.developer.nokia.com'),
209 ('DNS', 'projects.forum.nokia.com'))
210 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000211
Christian Heimes824f7f32013-08-17 00:54:47 +0200212 def test_parse_cert_CVE_2013_4238(self):
213 p = ssl._ssl._test_decode_cert(NULLBYTECERT)
214 if support.verbose:
215 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
216 subject = ((('countryName', 'US'),),
217 (('stateOrProvinceName', 'Oregon'),),
218 (('localityName', 'Beaverton'),),
219 (('organizationName', 'Python Software Foundation'),),
220 (('organizationalUnitName', 'Python Core Development'),),
221 (('commonName', 'null.python.org\x00example.org'),),
222 (('emailAddress', 'python-dev@python.org'),))
223 self.assertEqual(p['subject'], subject)
224 self.assertEqual(p['issuer'], subject)
Christian Heimes157c9832013-08-25 14:12:41 +0200225 if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
226 san = (('DNS', 'altnull.python.org\x00example.com'),
227 ('email', 'null@python.org\x00user@example.org'),
228 ('URI', 'http://null.python.org\x00http://example.org'),
229 ('IP Address', '192.0.2.1'),
230 ('IP Address', '2001:DB8:0:0:0:0:0:1\n'))
231 else:
232 # OpenSSL 0.9.7 doesn't support IPv6 addresses in subjectAltName
233 san = (('DNS', 'altnull.python.org\x00example.com'),
234 ('email', 'null@python.org\x00user@example.org'),
235 ('URI', 'http://null.python.org\x00http://example.org'),
236 ('IP Address', '192.0.2.1'),
237 ('IP Address', '<invalid>'))
238
239 self.assertEqual(p['subjectAltName'], san)
Christian Heimes824f7f32013-08-17 00:54:47 +0200240
Antoine Pitrou480a1242010-04-28 21:37:09 +0000241 def test_DER_to_PEM(self):
242 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
243 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000244 d1 = ssl.PEM_cert_to_DER_cert(pem)
245 p2 = ssl.DER_cert_to_PEM_cert(d1)
246 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000247 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000248 if not p2.startswith(ssl.PEM_HEADER + '\n'):
249 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
250 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
251 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000252
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000253 def test_openssl_version(self):
254 n = ssl.OPENSSL_VERSION_NUMBER
255 t = ssl.OPENSSL_VERSION_INFO
256 s = ssl.OPENSSL_VERSION
257 self.assertIsInstance(n, int)
258 self.assertIsInstance(t, tuple)
259 self.assertIsInstance(s, str)
260 # Some sanity checks follow
261 # >= 0.9
262 self.assertGreaterEqual(n, 0x900000)
263 # < 2.0
264 self.assertLess(n, 0x20000000)
265 major, minor, fix, patch, status = t
266 self.assertGreaterEqual(major, 0)
267 self.assertLess(major, 2)
268 self.assertGreaterEqual(minor, 0)
269 self.assertLess(minor, 256)
270 self.assertGreaterEqual(fix, 0)
271 self.assertLess(fix, 256)
272 self.assertGreaterEqual(patch, 0)
273 self.assertLessEqual(patch, 26)
274 self.assertGreaterEqual(status, 0)
275 self.assertLessEqual(status, 15)
276 # Version string as returned by OpenSSL, the format might change
277 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
278 (s, t))
279
Antoine Pitrou9d543662010-04-23 23:10:32 +0000280 @support.cpython_only
281 def test_refcycle(self):
282 # Issue #7943: an SSL object doesn't create reference cycles with
283 # itself.
284 s = socket.socket(socket.AF_INET)
285 ss = ssl.wrap_socket(s)
286 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100287 with support.check_warnings(("", ResourceWarning)):
288 del ss
289 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000290
Antoine Pitroua468adc2010-09-14 14:43:44 +0000291 def test_wrapped_unconnected(self):
292 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200293 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000294 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100295 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100296 self.assertRaises(OSError, ss.recv, 1)
297 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
298 self.assertRaises(OSError, ss.recvfrom, 1)
299 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
300 self.assertRaises(OSError, ss.send, b'x')
301 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000302
Antoine Pitrou40f08742010-04-24 22:04:40 +0000303 def test_timeout(self):
304 # Issue #8524: when creating an SSL socket, the timeout of the
305 # original socket should be retained.
306 for timeout in (None, 0.0, 5.0):
307 s = socket.socket(socket.AF_INET)
308 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100309 with ssl.wrap_socket(s) as ss:
310 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000311
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000312 def test_errors(self):
313 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000314 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000315 "certfile must be specified",
316 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000317 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000318 "certfile must be specified for server-side operations",
319 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000320 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000321 "certfile must be specified for server-side operations",
322 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100323 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
324 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
325 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200326 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000327 with socket.socket() as sock:
328 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000329 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200330 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000331 with socket.socket() as sock:
332 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000333 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200334 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000335 with socket.socket() as sock:
336 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000337 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000338
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000339 def test_match_hostname(self):
340 def ok(cert, hostname):
341 ssl.match_hostname(cert, hostname)
342 def fail(cert, hostname):
343 self.assertRaises(ssl.CertificateError,
344 ssl.match_hostname, cert, hostname)
345
346 cert = {'subject': ((('commonName', 'example.com'),),)}
347 ok(cert, 'example.com')
348 ok(cert, 'ExAmple.cOm')
349 fail(cert, 'www.example.com')
350 fail(cert, '.example.com')
351 fail(cert, 'example.org')
352 fail(cert, 'exampleXcom')
353
354 cert = {'subject': ((('commonName', '*.a.com'),),)}
355 ok(cert, 'foo.a.com')
356 fail(cert, 'bar.foo.a.com')
357 fail(cert, 'a.com')
358 fail(cert, 'Xa.com')
359 fail(cert, '.a.com')
360
361 cert = {'subject': ((('commonName', 'a.*.com'),),)}
362 ok(cert, 'a.foo.com')
363 fail(cert, 'a..com')
364 fail(cert, 'a.com')
365
366 cert = {'subject': ((('commonName', 'f*.com'),),)}
367 ok(cert, 'foo.com')
368 ok(cert, 'f.com')
369 fail(cert, 'bar.com')
370 fail(cert, 'foo.a.com')
371 fail(cert, 'bar.foo.com')
372
Christian Heimes824f7f32013-08-17 00:54:47 +0200373 # NULL bytes are bad, CVE-2013-4073
374 cert = {'subject': ((('commonName',
375 'null.python.org\x00example.org'),),)}
376 ok(cert, 'null.python.org\x00example.org') # or raise an error?
377 fail(cert, 'example.org')
378 fail(cert, 'null.python.org')
379
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000380 # Slightly fake real-world example
381 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
382 'subject': ((('commonName', 'linuxfrz.org'),),),
383 'subjectAltName': (('DNS', 'linuxfr.org'),
384 ('DNS', 'linuxfr.com'),
385 ('othername', '<unsupported>'))}
386 ok(cert, 'linuxfr.org')
387 ok(cert, 'linuxfr.com')
388 # Not a "DNS" entry
389 fail(cert, '<unsupported>')
390 # When there is a subjectAltName, commonName isn't used
391 fail(cert, 'linuxfrz.org')
392
393 # A pristine real-world example
394 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
395 'subject': ((('countryName', 'US'),),
396 (('stateOrProvinceName', 'California'),),
397 (('localityName', 'Mountain View'),),
398 (('organizationName', 'Google Inc'),),
399 (('commonName', 'mail.google.com'),))}
400 ok(cert, 'mail.google.com')
401 fail(cert, 'gmail.com')
402 # Only commonName is considered
403 fail(cert, 'California')
404
405 # Neither commonName nor subjectAltName
406 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
407 'subject': ((('countryName', 'US'),),
408 (('stateOrProvinceName', 'California'),),
409 (('localityName', 'Mountain View'),),
410 (('organizationName', 'Google Inc'),))}
411 fail(cert, 'mail.google.com')
412
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200413 # No DNS entry in subjectAltName but a commonName
414 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
415 'subject': ((('countryName', 'US'),),
416 (('stateOrProvinceName', 'California'),),
417 (('localityName', 'Mountain View'),),
418 (('commonName', 'mail.google.com'),)),
419 'subjectAltName': (('othername', 'blabla'), )}
420 ok(cert, 'mail.google.com')
421
422 # No DNS entry subjectAltName and no commonName
423 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
424 'subject': ((('countryName', 'US'),),
425 (('stateOrProvinceName', 'California'),),
426 (('localityName', 'Mountain View'),),
427 (('organizationName', 'Google Inc'),)),
428 'subjectAltName': (('othername', 'blabla'),)}
429 fail(cert, 'google.com')
430
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000431 # Empty cert / no cert
432 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
433 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
434
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200435 # Issue #17980: avoid denials of service by refusing more than one
436 # wildcard per fragment.
437 cert = {'subject': ((('commonName', 'a*b.com'),),)}
438 ok(cert, 'axxb.com')
439 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
440 ok(cert, 'axxb.com')
441 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
442 with self.assertRaises(ssl.CertificateError) as cm:
443 ssl.match_hostname(cert, 'axxbxxc.com')
444 self.assertIn("too many wildcards", str(cm.exception))
445
Antoine Pitroud5323212010-10-22 18:19:07 +0000446 def test_server_side(self):
447 # server_hostname doesn't work for server sockets
448 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000449 with socket.socket() as sock:
450 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
451 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000452
Antoine Pitroud6494802011-07-21 01:11:30 +0200453 def test_unknown_channel_binding(self):
454 # should raise ValueError for unknown type
455 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100456 with ssl.wrap_socket(s) as ss:
457 with self.assertRaises(ValueError):
458 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200459
460 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
461 "'tls-unique' channel binding not available")
462 def test_tls_unique_channel_binding(self):
463 # unconnected should return None for known type
464 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100465 with ssl.wrap_socket(s) as ss:
466 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200467 # the same for server-side
468 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100469 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
470 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200471
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600472 def test_dealloc_warn(self):
473 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
474 r = repr(ss)
475 with self.assertWarns(ResourceWarning) as cm:
476 ss = None
477 support.gc_collect()
478 self.assertIn(r, str(cm.warning.args[0]))
479
Christian Heimes6d7ad132013-06-09 18:02:55 +0200480 def test_get_default_verify_paths(self):
481 paths = ssl.get_default_verify_paths()
482 self.assertEqual(len(paths), 6)
483 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
484
485 with support.EnvironmentVarGuard() as env:
486 env["SSL_CERT_DIR"] = CAPATH
487 env["SSL_CERT_FILE"] = CERTFILE
488 paths = ssl.get_default_verify_paths()
489 self.assertEqual(paths.cafile, CERTFILE)
490 self.assertEqual(paths.capath, CAPATH)
491
492
Christian Heimes46bebee2013-06-09 19:03:31 +0200493 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
494 def test_enum_cert_store(self):
495 self.assertEqual(ssl.X509_ASN_ENCODING, 1)
496 self.assertEqual(ssl.PKCS_7_ASN_ENCODING, 0x00010000)
497
498 self.assertEqual(ssl.enum_cert_store("CA"),
499 ssl.enum_cert_store("CA", "certificate"))
500 ssl.enum_cert_store("CA", "crl")
501 self.assertEqual(ssl.enum_cert_store("ROOT"),
502 ssl.enum_cert_store("ROOT", "certificate"))
503 ssl.enum_cert_store("ROOT", "crl")
504
505 self.assertRaises(TypeError, ssl.enum_cert_store)
506 self.assertRaises(WindowsError, ssl.enum_cert_store, "")
507 self.assertRaises(ValueError, ssl.enum_cert_store, "CA", "wrong")
508
509 ca = ssl.enum_cert_store("CA")
510 self.assertIsInstance(ca, list)
511 self.assertIsInstance(ca[0], tuple)
512 self.assertEqual(len(ca[0]), 2)
513 self.assertIsInstance(ca[0][0], bytes)
514 self.assertIsInstance(ca[0][1], int)
515
Antoine Pitrou152efa22010-05-16 18:19:27 +0000516class ContextTests(unittest.TestCase):
517
Antoine Pitrou23df4832010-08-04 17:14:06 +0000518 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000519 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100520 for protocol in PROTOCOLS:
521 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000522 self.assertRaises(TypeError, ssl.SSLContext)
523 self.assertRaises(ValueError, ssl.SSLContext, -1)
524 self.assertRaises(ValueError, ssl.SSLContext, 42)
525
Antoine Pitrou23df4832010-08-04 17:14:06 +0000526 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000527 def test_protocol(self):
528 for proto in PROTOCOLS:
529 ctx = ssl.SSLContext(proto)
530 self.assertEqual(ctx.protocol, proto)
531
532 def test_ciphers(self):
533 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
534 ctx.set_ciphers("ALL")
535 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000536 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000537 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000538
Antoine Pitrou23df4832010-08-04 17:14:06 +0000539 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000540 def test_options(self):
541 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
542 # OP_ALL is the default value
543 self.assertEqual(ssl.OP_ALL, ctx.options)
544 ctx.options |= ssl.OP_NO_SSLv2
545 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
546 ctx.options)
547 ctx.options |= ssl.OP_NO_SSLv3
548 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
549 ctx.options)
550 if can_clear_options():
551 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
552 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
553 ctx.options)
554 ctx.options = 0
555 self.assertEqual(0, ctx.options)
556 else:
557 with self.assertRaises(ValueError):
558 ctx.options = 0
559
Antoine Pitrou152efa22010-05-16 18:19:27 +0000560 def test_verify(self):
561 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
562 # Default value
563 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
564 ctx.verify_mode = ssl.CERT_OPTIONAL
565 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
566 ctx.verify_mode = ssl.CERT_REQUIRED
567 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
568 ctx.verify_mode = ssl.CERT_NONE
569 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
570 with self.assertRaises(TypeError):
571 ctx.verify_mode = None
572 with self.assertRaises(ValueError):
573 ctx.verify_mode = 42
574
575 def test_load_cert_chain(self):
576 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
577 # Combined key and cert in a single file
578 ctx.load_cert_chain(CERTFILE)
579 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
580 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200581 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000582 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000583 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000584 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000585 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000586 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000587 ctx.load_cert_chain(EMPTYCERT)
588 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000589 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000590 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
591 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
592 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000593 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000594 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000595 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000596 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000597 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000598 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
599 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000600 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000601 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000602 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200603 # Password protected key and cert
604 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
605 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
606 ctx.load_cert_chain(CERTFILE_PROTECTED,
607 password=bytearray(KEY_PASSWORD.encode()))
608 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
609 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
610 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
611 bytearray(KEY_PASSWORD.encode()))
612 with self.assertRaisesRegex(TypeError, "should be a string"):
613 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
614 with self.assertRaises(ssl.SSLError):
615 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
616 with self.assertRaisesRegex(ValueError, "cannot be longer"):
617 # openssl has a fixed limit on the password buffer.
618 # PEM_BUFSIZE is generally set to 1kb.
619 # Return a string larger than this.
620 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
621 # Password callback
622 def getpass_unicode():
623 return KEY_PASSWORD
624 def getpass_bytes():
625 return KEY_PASSWORD.encode()
626 def getpass_bytearray():
627 return bytearray(KEY_PASSWORD.encode())
628 def getpass_badpass():
629 return "badpass"
630 def getpass_huge():
631 return b'a' * (1024 * 1024)
632 def getpass_bad_type():
633 return 9
634 def getpass_exception():
635 raise Exception('getpass error')
636 class GetPassCallable:
637 def __call__(self):
638 return KEY_PASSWORD
639 def getpass(self):
640 return KEY_PASSWORD
641 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
642 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
643 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
644 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
645 ctx.load_cert_chain(CERTFILE_PROTECTED,
646 password=GetPassCallable().getpass)
647 with self.assertRaises(ssl.SSLError):
648 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
649 with self.assertRaisesRegex(ValueError, "cannot be longer"):
650 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
651 with self.assertRaisesRegex(TypeError, "must return a string"):
652 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
653 with self.assertRaisesRegex(Exception, "getpass error"):
654 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
655 # Make sure the password function isn't called if it isn't needed
656 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000657
658 def test_load_verify_locations(self):
659 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
660 ctx.load_verify_locations(CERTFILE)
661 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
662 ctx.load_verify_locations(BYTES_CERTFILE)
663 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
664 self.assertRaises(TypeError, ctx.load_verify_locations)
665 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200666 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000667 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000668 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000669 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000670 ctx.load_verify_locations(BADCERT)
671 ctx.load_verify_locations(CERTFILE, CAPATH)
672 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
673
Victor Stinner80f75e62011-01-29 11:31:20 +0000674 # Issue #10989: crash if the second argument type is invalid
675 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
676
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100677 def test_load_dh_params(self):
678 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
679 ctx.load_dh_params(DHFILE)
680 if os.name != 'nt':
681 ctx.load_dh_params(BYTES_DHFILE)
682 self.assertRaises(TypeError, ctx.load_dh_params)
683 self.assertRaises(TypeError, ctx.load_dh_params, None)
684 with self.assertRaises(FileNotFoundError) as cm:
685 ctx.load_dh_params(WRONGCERT)
686 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200687 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100688 ctx.load_dh_params(CERTFILE)
689
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000690 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000691 def test_session_stats(self):
692 for proto in PROTOCOLS:
693 ctx = ssl.SSLContext(proto)
694 self.assertEqual(ctx.session_stats(), {
695 'number': 0,
696 'connect': 0,
697 'connect_good': 0,
698 'connect_renegotiate': 0,
699 'accept': 0,
700 'accept_good': 0,
701 'accept_renegotiate': 0,
702 'hits': 0,
703 'misses': 0,
704 'timeouts': 0,
705 'cache_full': 0,
706 })
707
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000708 def test_set_default_verify_paths(self):
709 # There's not much we can do to test that it acts as expected,
710 # so just check it doesn't crash or raise an exception.
711 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
712 ctx.set_default_verify_paths()
713
Antoine Pitrou501da612011-12-21 09:27:41 +0100714 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100715 def test_set_ecdh_curve(self):
716 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
717 ctx.set_ecdh_curve("prime256v1")
718 ctx.set_ecdh_curve(b"prime256v1")
719 self.assertRaises(TypeError, ctx.set_ecdh_curve)
720 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
721 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
722 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
723
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100724 @needs_sni
725 def test_sni_callback(self):
726 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
727
728 # set_servername_callback expects a callable, or None
729 self.assertRaises(TypeError, ctx.set_servername_callback)
730 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
731 self.assertRaises(TypeError, ctx.set_servername_callback, "")
732 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
733
734 def dummycallback(sock, servername, ctx):
735 pass
736 ctx.set_servername_callback(None)
737 ctx.set_servername_callback(dummycallback)
738
739 @needs_sni
740 def test_sni_callback_refcycle(self):
741 # Reference cycles through the servername callback are detected
742 # and cleared.
743 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
744 def dummycallback(sock, servername, ctx, cycle=ctx):
745 pass
746 ctx.set_servername_callback(dummycallback)
747 wr = weakref.ref(ctx)
748 del ctx, dummycallback
749 gc.collect()
750 self.assertIs(wr(), None)
751
Christian Heimes9a5395a2013-06-17 15:44:12 +0200752 def test_cert_store_stats(self):
753 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
754 self.assertEqual(ctx.cert_store_stats(),
755 {'x509_ca': 0, 'crl': 0, 'x509': 0})
756 ctx.load_cert_chain(CERTFILE)
757 self.assertEqual(ctx.cert_store_stats(),
758 {'x509_ca': 0, 'crl': 0, 'x509': 0})
759 ctx.load_verify_locations(CERTFILE)
760 self.assertEqual(ctx.cert_store_stats(),
761 {'x509_ca': 0, 'crl': 0, 'x509': 1})
762 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
763 self.assertEqual(ctx.cert_store_stats(),
764 {'x509_ca': 1, 'crl': 0, 'x509': 2})
765
766 def test_get_ca_certs(self):
767 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
768 self.assertEqual(ctx.get_ca_certs(), [])
769 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
770 ctx.load_verify_locations(CERTFILE)
771 self.assertEqual(ctx.get_ca_certs(), [])
772 # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
773 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
774 self.assertEqual(ctx.get_ca_certs(),
775 [{'issuer': ((('organizationName', 'Root CA'),),
776 (('organizationalUnitName', 'http://www.cacert.org'),),
777 (('commonName', 'CA Cert Signing Authority'),),
778 (('emailAddress', 'support@cacert.org'),)),
779 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
780 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
781 'serialNumber': '00',
782 'subject': ((('organizationName', 'Root CA'),),
783 (('organizationalUnitName', 'http://www.cacert.org'),),
784 (('commonName', 'CA Cert Signing Authority'),),
785 (('emailAddress', 'support@cacert.org'),)),
786 'version': 3}])
787
788 with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
789 pem = f.read()
790 der = ssl.PEM_cert_to_DER_cert(pem)
791 self.assertEqual(ctx.get_ca_certs(True), [der])
792
Antoine Pitrou152efa22010-05-16 18:19:27 +0000793
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200794class SSLErrorTests(unittest.TestCase):
795
796 def test_str(self):
797 # The str() of a SSLError doesn't include the errno
798 e = ssl.SSLError(1, "foo")
799 self.assertEqual(str(e), "foo")
800 self.assertEqual(e.errno, 1)
801 # Same for a subclass
802 e = ssl.SSLZeroReturnError(1, "foo")
803 self.assertEqual(str(e), "foo")
804 self.assertEqual(e.errno, 1)
805
806 def test_lib_reason(self):
807 # Test the library and reason attributes
808 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
809 with self.assertRaises(ssl.SSLError) as cm:
810 ctx.load_dh_params(CERTFILE)
811 self.assertEqual(cm.exception.library, 'PEM')
812 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
813 s = str(cm.exception)
814 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
815
816 def test_subclass(self):
817 # Check that the appropriate SSLError subclass is raised
818 # (this only tests one of them)
819 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
820 with socket.socket() as s:
821 s.bind(("127.0.0.1", 0))
822 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100823 c = socket.socket()
824 c.connect(s.getsockname())
825 c.setblocking(False)
826 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200827 with self.assertRaises(ssl.SSLWantReadError) as cm:
828 c.do_handshake()
829 s = str(cm.exception)
830 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
831 # For compatibility
832 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
833
834
Bill Janssen6e027db2007-11-15 22:23:56 +0000835class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000836
Antoine Pitrou480a1242010-04-28 21:37:09 +0000837 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000838 with support.transient_internet("svn.python.org"):
839 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
840 cert_reqs=ssl.CERT_NONE)
841 try:
842 s.connect(("svn.python.org", 443))
843 self.assertEqual({}, s.getpeercert())
844 finally:
845 s.close()
846
847 # this should fail because we have no verification certs
848 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
849 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000850 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
851 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000852 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000853
Antoine Pitrou350c7222010-09-09 13:31:46 +0000854 # this should succeed because we specify the root cert
855 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
856 cert_reqs=ssl.CERT_REQUIRED,
857 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
858 try:
859 s.connect(("svn.python.org", 443))
860 self.assertTrue(s.getpeercert())
861 finally:
862 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000863
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000864 def test_connect_ex(self):
865 # Issue #11326: check connect_ex() implementation
866 with support.transient_internet("svn.python.org"):
867 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
868 cert_reqs=ssl.CERT_REQUIRED,
869 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
870 try:
871 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
872 self.assertTrue(s.getpeercert())
873 finally:
874 s.close()
875
876 def test_non_blocking_connect_ex(self):
877 # Issue #11326: non-blocking connect_ex() should allow handshake
878 # to proceed after the socket gets ready.
879 with support.transient_internet("svn.python.org"):
880 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
881 cert_reqs=ssl.CERT_REQUIRED,
882 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
883 do_handshake_on_connect=False)
884 try:
885 s.setblocking(False)
886 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000887 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
888 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000889 # Wait for connect to finish
890 select.select([], [s], [], 5.0)
891 # Non-blocking handshake
892 while True:
893 try:
894 s.do_handshake()
895 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200896 except ssl.SSLWantReadError:
897 select.select([s], [], [], 5.0)
898 except ssl.SSLWantWriteError:
899 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000900 # SSL established
901 self.assertTrue(s.getpeercert())
902 finally:
903 s.close()
904
Antoine Pitroub4410db2011-05-18 18:51:06 +0200905 def test_timeout_connect_ex(self):
906 # Issue #12065: on a timeout, connect_ex() should return the original
907 # errno (mimicking the behaviour of non-SSL sockets).
908 with support.transient_internet("svn.python.org"):
909 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
910 cert_reqs=ssl.CERT_REQUIRED,
911 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
912 do_handshake_on_connect=False)
913 try:
914 s.settimeout(0.0000001)
915 rc = s.connect_ex(('svn.python.org', 443))
916 if rc == 0:
917 self.skipTest("svn.python.org responded too quickly")
918 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
919 finally:
920 s.close()
921
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100922 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100923 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100924 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
925 cert_reqs=ssl.CERT_REQUIRED,
926 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
927 try:
928 self.assertEqual(errno.ECONNREFUSED,
929 s.connect_ex(("svn.python.org", 444)))
930 finally:
931 s.close()
932
Antoine Pitrou152efa22010-05-16 18:19:27 +0000933 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000934 with support.transient_internet("svn.python.org"):
935 # Same as test_connect, but with a separately created context
936 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
937 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
938 s.connect(("svn.python.org", 443))
939 try:
940 self.assertEqual({}, s.getpeercert())
941 finally:
942 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000943 # Same with a server hostname
944 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
945 server_hostname="svn.python.org")
946 if ssl.HAS_SNI:
947 s.connect(("svn.python.org", 443))
948 s.close()
949 else:
950 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000951 # This should fail because we have no verification certs
952 ctx.verify_mode = ssl.CERT_REQUIRED
953 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000954 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000955 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000956 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000957 # This should succeed because we specify the root cert
958 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
959 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
960 s.connect(("svn.python.org", 443))
961 try:
962 cert = s.getpeercert()
963 self.assertTrue(cert)
964 finally:
965 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000966
967 def test_connect_capath(self):
968 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000969 # NOTE: the subject hashing algorithm has been changed between
970 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
971 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000972 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000973 with support.transient_internet("svn.python.org"):
974 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
975 ctx.verify_mode = ssl.CERT_REQUIRED
976 ctx.load_verify_locations(capath=CAPATH)
977 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
978 s.connect(("svn.python.org", 443))
979 try:
980 cert = s.getpeercert()
981 self.assertTrue(cert)
982 finally:
983 s.close()
984 # Same with a bytes `capath` argument
985 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
986 ctx.verify_mode = ssl.CERT_REQUIRED
987 ctx.load_verify_locations(capath=BYTES_CAPATH)
988 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
989 s.connect(("svn.python.org", 443))
990 try:
991 cert = s.getpeercert()
992 self.assertTrue(cert)
993 finally:
994 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000995
Antoine Pitroue3220242010-04-24 11:13:53 +0000996 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
997 def test_makefile_close(self):
998 # Issue #5238: creating a file-like object with makefile() shouldn't
999 # delay closing the underlying "real socket" (here tested with its
1000 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +00001001 with support.transient_internet("svn.python.org"):
1002 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1003 ss.connect(("svn.python.org", 443))
1004 fd = ss.fileno()
1005 f = ss.makefile()
1006 f.close()
1007 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +00001008 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001009 # Closing the SSL socket should close the fd too
1010 ss.close()
1011 gc.collect()
1012 with self.assertRaises(OSError) as e:
1013 os.read(fd, 0)
1014 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001015
Antoine Pitrou480a1242010-04-28 21:37:09 +00001016 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001017 with support.transient_internet("svn.python.org"):
1018 s = socket.socket(socket.AF_INET)
1019 s.connect(("svn.python.org", 443))
1020 s.setblocking(False)
1021 s = ssl.wrap_socket(s,
1022 cert_reqs=ssl.CERT_NONE,
1023 do_handshake_on_connect=False)
1024 count = 0
1025 while True:
1026 try:
1027 count += 1
1028 s.do_handshake()
1029 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001030 except ssl.SSLWantReadError:
1031 select.select([s], [], [])
1032 except ssl.SSLWantWriteError:
1033 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +00001034 s.close()
1035 if support.verbose:
1036 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001037
Antoine Pitrou480a1242010-04-28 21:37:09 +00001038 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +02001039 def _test_get_server_certificate(host, port, cert=None):
1040 with support.transient_internet(host):
1041 pem = ssl.get_server_certificate((host, port))
1042 if not pem:
1043 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001044
Antoine Pitrou15399c32011-04-28 19:23:55 +02001045 try:
1046 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
1047 except ssl.SSLError as x:
1048 #should fail
1049 if support.verbose:
1050 sys.stdout.write("%s\n" % x)
1051 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001052 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1053
Antoine Pitrou15399c32011-04-28 19:23:55 +02001054 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
1055 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001056 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001057 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001058 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001059
Antoine Pitrou15399c32011-04-28 19:23:55 +02001060 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
1061 if support.IPV6_ENABLED:
1062 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001063
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001064 def test_ciphers(self):
1065 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001066 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001067 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1068 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1069 s.connect(remote)
1070 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1071 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1072 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001073 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001074 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001075 with socket.socket(socket.AF_INET) as sock:
1076 s = ssl.wrap_socket(sock,
1077 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1078 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001079
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001080 def test_algorithms(self):
1081 # Issue #8484: all algorithms should be available when verifying a
1082 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001083 # SHA256 was added in OpenSSL 0.9.8
1084 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1085 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001086 # sha256.tbs-internet.com needs SNI to use the correct certificate
1087 if not ssl.HAS_SNI:
1088 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001089 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1090 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001091 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001092 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001093 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1094 ctx.verify_mode = ssl.CERT_REQUIRED
1095 ctx.load_verify_locations(sha256_cert)
1096 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1097 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001098 try:
1099 s.connect(remote)
1100 if support.verbose:
1101 sys.stdout.write("\nCipher with %r is %r\n" %
1102 (remote, s.cipher()))
1103 sys.stdout.write("Certificate is:\n%s\n" %
1104 pprint.pformat(s.getpeercert()))
1105 finally:
1106 s.close()
1107
Christian Heimes9a5395a2013-06-17 15:44:12 +02001108 def test_get_ca_certs_capath(self):
1109 # capath certs are loaded on request
1110 with support.transient_internet("svn.python.org"):
1111 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1112 ctx.verify_mode = ssl.CERT_REQUIRED
1113 ctx.load_verify_locations(capath=CAPATH)
1114 self.assertEqual(ctx.get_ca_certs(), [])
1115 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1116 s.connect(("svn.python.org", 443))
1117 try:
1118 cert = s.getpeercert()
1119 self.assertTrue(cert)
1120 finally:
1121 s.close()
1122 self.assertEqual(len(ctx.get_ca_certs()), 1)
1123
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001124
1125try:
1126 import threading
1127except ImportError:
1128 _have_threads = False
1129else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001130 _have_threads = True
1131
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001132 from test.ssl_servers import make_https_server
1133
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001134 class ThreadedEchoServer(threading.Thread):
1135
1136 class ConnectionHandler(threading.Thread):
1137
1138 """A mildly complicated class, because we want it to work both
1139 with and without the SSL wrapper around the socket connection, so
1140 that we can test the STARTTLS functionality."""
1141
Bill Janssen6e027db2007-11-15 22:23:56 +00001142 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001143 self.server = server
1144 self.running = False
1145 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001146 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001147 self.sock.setblocking(1)
1148 self.sslconn = None
1149 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001150 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001151
Antoine Pitrou480a1242010-04-28 21:37:09 +00001152 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001153 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001154 self.sslconn = self.server.context.wrap_socket(
1155 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001156 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001157 except (ssl.SSLError, ConnectionResetError) as e:
1158 # We treat ConnectionResetError as though it were an
1159 # SSLError - OpenSSL on Ubuntu abruptly closes the
1160 # connection when asked to use an unsupported protocol.
1161 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001162 # XXX Various errors can have happened here, for example
1163 # a mismatching protocol version, an invalid certificate,
1164 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001165 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001167 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001168 self.running = False
1169 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001170 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001171 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001172 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001173 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001175 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001176 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1177 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001178 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1180 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001181 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001182 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001183 sys.stdout.write(" server: selected protocol is now "
1184 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001185 return True
1186
1187 def read(self):
1188 if self.sslconn:
1189 return self.sslconn.read()
1190 else:
1191 return self.sock.recv(1024)
1192
1193 def write(self, bytes):
1194 if self.sslconn:
1195 return self.sslconn.write(bytes)
1196 else:
1197 return self.sock.send(bytes)
1198
1199 def close(self):
1200 if self.sslconn:
1201 self.sslconn.close()
1202 else:
1203 self.sock.close()
1204
Antoine Pitrou480a1242010-04-28 21:37:09 +00001205 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001206 self.running = True
1207 if not self.server.starttls_server:
1208 if not self.wrap_conn():
1209 return
1210 while self.running:
1211 try:
1212 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001213 stripped = msg.strip()
1214 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001215 # eof, so quit this handler
1216 self.running = False
1217 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001218 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001219 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001220 sys.stdout.write(" server: client closed connection\n")
1221 self.close()
1222 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001223 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001224 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001225 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001226 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001227 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001228 if not self.wrap_conn():
1229 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001230 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001231 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001232 if support.verbose and self.server.connectionchatty:
1233 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001234 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001235 self.sock = self.sslconn.unwrap()
1236 self.sslconn = None
1237 if support.verbose and self.server.connectionchatty:
1238 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001239 elif stripped == b'CB tls-unique':
1240 if support.verbose and self.server.connectionchatty:
1241 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1242 data = self.sslconn.get_channel_binding("tls-unique")
1243 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001244 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001245 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001246 self.server.connectionchatty):
1247 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001248 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1249 % (msg, ctype, msg.lower(), ctype))
1250 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001251 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001252 if self.server.chatty:
1253 handle_error("Test server failure:\n")
1254 self.close()
1255 self.running = False
1256 # normally, we'd just stop here, but for the test
1257 # harness, we want to stop the server
1258 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001259
Antoine Pitroub5218772010-05-21 09:56:06 +00001260 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001261 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001262 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001263 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001264 if context:
1265 self.context = context
1266 else:
1267 self.context = ssl.SSLContext(ssl_version
1268 if ssl_version is not None
1269 else ssl.PROTOCOL_TLSv1)
1270 self.context.verify_mode = (certreqs if certreqs is not None
1271 else ssl.CERT_NONE)
1272 if cacerts:
1273 self.context.load_verify_locations(cacerts)
1274 if certificate:
1275 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001276 if npn_protocols:
1277 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001278 if ciphers:
1279 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001280 self.chatty = chatty
1281 self.connectionchatty = connectionchatty
1282 self.starttls_server = starttls_server
1283 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001284 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001285 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001286 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001287 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001288 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001289 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001290 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001291
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001292 def __enter__(self):
1293 self.start(threading.Event())
1294 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001295 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001296
1297 def __exit__(self, *args):
1298 self.stop()
1299 self.join()
1300
Antoine Pitrou480a1242010-04-28 21:37:09 +00001301 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001302 self.flag = flag
1303 threading.Thread.start(self)
1304
Antoine Pitrou480a1242010-04-28 21:37:09 +00001305 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001306 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001307 self.sock.listen(5)
1308 self.active = True
1309 if self.flag:
1310 # signal an event
1311 self.flag.set()
1312 while self.active:
1313 try:
1314 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001315 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001316 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001317 + repr(connaddr) + '\n')
1318 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001319 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001320 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001321 except socket.timeout:
1322 pass
1323 except KeyboardInterrupt:
1324 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001325 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001326
Antoine Pitrou480a1242010-04-28 21:37:09 +00001327 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001328 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001329
Bill Janssen54cc54c2007-12-14 22:08:56 +00001330 class AsyncoreEchoServer(threading.Thread):
1331
1332 # this one's based on asyncore.dispatcher
1333
1334 class EchoServer (asyncore.dispatcher):
1335
1336 class ConnectionHandler (asyncore.dispatcher_with_send):
1337
1338 def __init__(self, conn, certfile):
1339 self.socket = ssl.wrap_socket(conn, server_side=True,
1340 certfile=certfile,
1341 do_handshake_on_connect=False)
1342 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001343 self._ssl_accepting = True
1344 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001345
1346 def readable(self):
1347 if isinstance(self.socket, ssl.SSLSocket):
1348 while self.socket.pending() > 0:
1349 self.handle_read_event()
1350 return True
1351
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001352 def _do_ssl_handshake(self):
1353 try:
1354 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001355 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1356 return
1357 except ssl.SSLEOFError:
1358 return self.handle_close()
1359 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001360 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001361 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001362 if err.args[0] == errno.ECONNABORTED:
1363 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001364 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001365 self._ssl_accepting = False
1366
1367 def handle_read(self):
1368 if self._ssl_accepting:
1369 self._do_ssl_handshake()
1370 else:
1371 data = self.recv(1024)
1372 if support.verbose:
1373 sys.stdout.write(" server: read %s from client\n" % repr(data))
1374 if not data:
1375 self.close()
1376 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001377 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001378
1379 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001380 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001381 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001382 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1383
1384 def handle_error(self):
1385 raise
1386
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001387 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001388 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001389 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1390 self.port = support.bind_port(sock, '')
1391 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001392 self.listen(5)
1393
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001394 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001395 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001396 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1397 self.ConnectionHandler(sock_obj, self.certfile)
1398
1399 def handle_error(self):
1400 raise
1401
Trent Nelson78520002008-04-10 20:54:35 +00001402 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001403 self.flag = None
1404 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001405 self.server = self.EchoServer(certfile)
1406 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001407 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001408 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001409
1410 def __str__(self):
1411 return "<%s %s>" % (self.__class__.__name__, self.server)
1412
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001413 def __enter__(self):
1414 self.start(threading.Event())
1415 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001416 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001417
1418 def __exit__(self, *args):
1419 if support.verbose:
1420 sys.stdout.write(" cleanup: stopping server.\n")
1421 self.stop()
1422 if support.verbose:
1423 sys.stdout.write(" cleanup: joining server thread.\n")
1424 self.join()
1425 if support.verbose:
1426 sys.stdout.write(" cleanup: successfully joined.\n")
1427
Bill Janssen54cc54c2007-12-14 22:08:56 +00001428 def start (self, flag=None):
1429 self.flag = flag
1430 threading.Thread.start(self)
1431
Antoine Pitrou480a1242010-04-28 21:37:09 +00001432 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001433 self.active = True
1434 if self.flag:
1435 self.flag.set()
1436 while self.active:
1437 try:
1438 asyncore.loop(1)
1439 except:
1440 pass
1441
Antoine Pitrou480a1242010-04-28 21:37:09 +00001442 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001443 self.active = False
1444 self.server.close()
1445
Antoine Pitrou480a1242010-04-28 21:37:09 +00001446 def bad_cert_test(certfile):
1447 """
1448 Launch a server with CERT_REQUIRED, and check that trying to
1449 connect to it with the given client certificate fails.
1450 """
Trent Nelson78520002008-04-10 20:54:35 +00001451 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001452 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001453 cacerts=CERTFILE, chatty=False,
1454 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001455 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001456 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001457 with socket.socket() as sock:
1458 s = ssl.wrap_socket(sock,
1459 certfile=certfile,
1460 ssl_version=ssl.PROTOCOL_TLSv1)
1461 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001462 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001463 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001464 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001465 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001466 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001467 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001468 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001469 if x.errno != errno.ENOENT:
1470 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001471 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001472 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001473 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001474 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001475
Antoine Pitroub5218772010-05-21 09:56:06 +00001476 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001477 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001478 """
1479 Launch a server, connect a client to it and try various reads
1480 and writes.
1481 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001482 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001483 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001484 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001485 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001486 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001487 with client_context.wrap_socket(socket.socket(),
1488 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001489 s.connect((HOST, server.port))
1490 for arg in [indata, bytearray(indata), memoryview(indata)]:
1491 if connectionchatty:
1492 if support.verbose:
1493 sys.stdout.write(
1494 " client: sending %r...\n" % indata)
1495 s.write(arg)
1496 outdata = s.read()
1497 if connectionchatty:
1498 if support.verbose:
1499 sys.stdout.write(" client: read %r\n" % outdata)
1500 if outdata != indata.lower():
1501 raise AssertionError(
1502 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1503 % (outdata[:20], len(outdata),
1504 indata[:20].lower(), len(indata)))
1505 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001506 if connectionchatty:
1507 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001508 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001509 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001510 'compression': s.compression(),
1511 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001512 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001513 'client_npn_protocol': s.selected_npn_protocol()
1514 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001515 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001516 stats['server_npn_protocols'] = server.selected_protocols
1517 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001518
Antoine Pitroub5218772010-05-21 09:56:06 +00001519 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1520 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001521 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001522 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001523 certtype = {
1524 ssl.CERT_NONE: "CERT_NONE",
1525 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1526 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1527 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001528 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001529 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001530 sys.stdout.write(formatstr %
1531 (ssl.get_protocol_name(client_protocol),
1532 ssl.get_protocol_name(server_protocol),
1533 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001534 client_context = ssl.SSLContext(client_protocol)
1535 client_context.options = ssl.OP_ALL | client_options
1536 server_context = ssl.SSLContext(server_protocol)
1537 server_context.options = ssl.OP_ALL | server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001538
1539 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1540 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1541 # starting from OpenSSL 1.0.0 (see issue #8322).
1542 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1543 client_context.set_ciphers("ALL")
1544
Antoine Pitroub5218772010-05-21 09:56:06 +00001545 for ctx in (client_context, server_context):
1546 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001547 ctx.load_cert_chain(CERTFILE)
1548 ctx.load_verify_locations(CERTFILE)
1549 try:
1550 server_params_test(client_context, server_context,
1551 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001552 # Protocol mismatch can result in either an SSLError, or a
1553 # "Connection reset by peer" error.
1554 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001555 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001556 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001557 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001558 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001559 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001560 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001561 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001562 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001563 "Client protocol %s succeeded with server protocol %s!"
1564 % (ssl.get_protocol_name(client_protocol),
1565 ssl.get_protocol_name(server_protocol)))
1566
1567
Bill Janssen6e027db2007-11-15 22:23:56 +00001568 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001569
Antoine Pitrou23df4832010-08-04 17:14:06 +00001570 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 def test_echo(self):
1572 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001573 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001574 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001575 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001576 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1577 context = ssl.SSLContext(protocol)
1578 context.load_cert_chain(CERTFILE)
1579 server_params_test(context, context,
1580 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001581
Antoine Pitrou480a1242010-04-28 21:37:09 +00001582 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001583 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001584 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001585 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1586 context.verify_mode = ssl.CERT_REQUIRED
1587 context.load_verify_locations(CERTFILE)
1588 context.load_cert_chain(CERTFILE)
1589 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001590 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02001591 s = context.wrap_socket(socket.socket(),
1592 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001593 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02001594 # getpeercert() raise ValueError while the handshake isn't
1595 # done.
1596 with self.assertRaises(ValueError):
1597 s.getpeercert()
1598 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001599 cert = s.getpeercert()
1600 self.assertTrue(cert, "Can't get peer certificate.")
1601 cipher = s.cipher()
1602 if support.verbose:
1603 sys.stdout.write(pprint.pformat(cert) + '\n')
1604 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1605 if 'subject' not in cert:
1606 self.fail("No subject field in certificate: %s." %
1607 pprint.pformat(cert))
1608 if ((('organizationName', 'Python Software Foundation'),)
1609 not in cert['subject']):
1610 self.fail(
1611 "Missing or invalid 'organizationName' field in certificate subject; "
1612 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001613 self.assertIn('notBefore', cert)
1614 self.assertIn('notAfter', cert)
1615 before = ssl.cert_time_to_seconds(cert['notBefore'])
1616 after = ssl.cert_time_to_seconds(cert['notAfter'])
1617 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001618 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001619
Antoine Pitrou480a1242010-04-28 21:37:09 +00001620 def test_empty_cert(self):
1621 """Connecting with an empty cert file"""
1622 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1623 "nullcert.pem"))
1624 def test_malformed_cert(self):
1625 """Connecting with a badly formatted certificate (syntax error)"""
1626 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1627 "badcert.pem"))
1628 def test_nonexisting_cert(self):
1629 """Connecting with a non-existing cert file"""
1630 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1631 "wrongcert.pem"))
1632 def test_malformed_key(self):
1633 """Connecting with a badly formatted key (syntax error)"""
1634 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1635 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001636
Antoine Pitrou480a1242010-04-28 21:37:09 +00001637 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001638 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00001639 in the client when attempting handshake.
1640 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001641 listener_ready = threading.Event()
1642 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001643
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001644 s = socket.socket()
1645 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001646
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001647 # `listener` runs in a thread. It sits in an accept() until
1648 # the main thread connects. Then it rudely closes the socket,
1649 # and sets Event `listener_gone` to let the main thread know
1650 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001651 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001652 s.listen(5)
1653 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001654 newsock, addr = s.accept()
1655 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001656 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001657 listener_gone.set()
1658
1659 def connector():
1660 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001661 with socket.socket() as c:
1662 c.connect((HOST, port))
1663 listener_gone.wait()
1664 try:
1665 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001666 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001667 pass
1668 else:
1669 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001670
1671 t = threading.Thread(target=listener)
1672 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001673 try:
1674 connector()
1675 finally:
1676 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001677
Antoine Pitrou23df4832010-08-04 17:14:06 +00001678 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001679 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1680 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001681 def test_protocol_sslv2(self):
1682 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001683 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001684 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001685 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1686 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1687 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1688 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1689 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1690 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001691 # SSLv23 client with specific SSL options
1692 if no_sslv2_implies_sslv3_hello():
1693 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1694 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1695 client_options=ssl.OP_NO_SSLv2)
1696 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1697 client_options=ssl.OP_NO_SSLv3)
1698 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1699 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001700
Antoine Pitrou23df4832010-08-04 17:14:06 +00001701 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001702 def test_protocol_sslv23(self):
1703 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001704 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001705 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001706 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1707 try:
1708 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02001709 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02001710 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1711 if support.verbose:
1712 sys.stdout.write(
1713 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1714 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001715 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1716 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1717 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001718
Antoine Pitrou480a1242010-04-28 21:37:09 +00001719 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1720 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1721 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001722
Antoine Pitrou480a1242010-04-28 21:37:09 +00001723 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1724 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1725 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001726
Antoine Pitroub5218772010-05-21 09:56:06 +00001727 # Server with specific SSL options
1728 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1729 server_options=ssl.OP_NO_SSLv3)
1730 # Will choose TLSv1
1731 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1732 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1733 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1734 server_options=ssl.OP_NO_TLSv1)
1735
1736
Antoine Pitrou23df4832010-08-04 17:14:06 +00001737 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001738 def test_protocol_sslv3(self):
1739 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001740 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001741 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001742 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1743 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1744 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001745 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1746 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001747 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1748 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001749 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001750 if no_sslv2_implies_sslv3_hello():
1751 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1752 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1753 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001754
Antoine Pitrou23df4832010-08-04 17:14:06 +00001755 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001756 def test_protocol_tlsv1(self):
1757 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001758 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001759 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001760 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1761 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1762 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001763 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1764 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001765 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001766 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1767 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001768
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001769 @skip_if_broken_ubuntu_ssl
1770 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
1771 "TLS version 1.1 not supported.")
1772 def test_protocol_tlsv1_1(self):
1773 """Connecting to a TLSv1.1 server with various client options.
1774 Testing against older TLS versions."""
1775 if support.verbose:
1776 sys.stdout.write("\n")
1777 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
1778 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1779 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
1780 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
1781 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
1782 client_options=ssl.OP_NO_TLSv1_1)
1783
1784 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
1785 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
1786 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
1787
1788
1789 @skip_if_broken_ubuntu_ssl
1790 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
1791 "TLS version 1.2 not supported.")
1792 def test_protocol_tlsv1_2(self):
1793 """Connecting to a TLSv1.2 server with various client options.
1794 Testing against older TLS versions."""
1795 if support.verbose:
1796 sys.stdout.write("\n")
1797 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
1798 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
1799 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
1800 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1801 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
1802 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
1803 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
1804 client_options=ssl.OP_NO_TLSv1_2)
1805
1806 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
1807 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
1808 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
1809 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
1810 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
1811
Antoine Pitrou480a1242010-04-28 21:37:09 +00001812 def test_starttls(self):
1813 """Switching from clear text to encrypted and back again."""
1814 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 +00001815
Trent Nelson78520002008-04-10 20:54:35 +00001816 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001817 ssl_version=ssl.PROTOCOL_TLSv1,
1818 starttls_server=True,
1819 chatty=True,
1820 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001821 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001822 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001823 s = socket.socket()
1824 s.setblocking(1)
1825 s.connect((HOST, server.port))
1826 if support.verbose:
1827 sys.stdout.write("\n")
1828 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001829 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001830 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001831 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001832 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001833 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001834 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001835 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001836 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001837 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001838 msg = outdata.strip().lower()
1839 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1840 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001841 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001842 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001843 " client: read %r from server, starting TLS...\n"
1844 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001845 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1846 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001847 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1848 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001849 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001850 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001851 " client: read %r from server, ending TLS...\n"
1852 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001853 s = conn.unwrap()
1854 wrapped = False
1855 else:
1856 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001857 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001858 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001859 if support.verbose:
1860 sys.stdout.write(" client: closing connection.\n")
1861 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001862 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001863 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001864 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001865 if wrapped:
1866 conn.close()
1867 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001868 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001869
Antoine Pitrou480a1242010-04-28 21:37:09 +00001870 def test_socketserver(self):
1871 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01001872 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001873 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001874 if support.verbose:
1875 sys.stdout.write('\n')
1876 with open(CERTFILE, 'rb') as f:
1877 d1 = f.read()
1878 d2 = ''
1879 # now fetch the same data from the HTTPS server
1880 url = 'https://%s:%d/%s' % (
1881 HOST, server.port, os.path.split(CERTFILE)[1])
1882 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001883 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001884 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001885 if dlen and (int(dlen) > 0):
1886 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001887 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001888 sys.stdout.write(
1889 " client: read %d bytes from remote server '%s'\n"
1890 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001891 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001892 f.close()
1893 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001894
Antoine Pitrou480a1242010-04-28 21:37:09 +00001895 def test_asyncore_server(self):
1896 """Check the example asyncore integration."""
1897 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001898
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001899 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001900 sys.stdout.write("\n")
1901
Antoine Pitrou480a1242010-04-28 21:37:09 +00001902 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001903 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001904 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001905 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001906 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001907 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001908 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001909 " client: sending %r...\n" % indata)
1910 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001911 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001912 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001913 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001914 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001915 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001916 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1917 % (outdata[:20], len(outdata),
1918 indata[:20].lower(), len(indata)))
1919 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001920 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001921 sys.stdout.write(" client: closing connection.\n")
1922 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001923 if support.verbose:
1924 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001925
Antoine Pitrou480a1242010-04-28 21:37:09 +00001926 def test_recv_send(self):
1927 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001928 if support.verbose:
1929 sys.stdout.write("\n")
1930
1931 server = ThreadedEchoServer(CERTFILE,
1932 certreqs=ssl.CERT_NONE,
1933 ssl_version=ssl.PROTOCOL_TLSv1,
1934 cacerts=CERTFILE,
1935 chatty=True,
1936 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001937 with server:
1938 s = ssl.wrap_socket(socket.socket(),
1939 server_side=False,
1940 certfile=CERTFILE,
1941 ca_certs=CERTFILE,
1942 cert_reqs=ssl.CERT_NONE,
1943 ssl_version=ssl.PROTOCOL_TLSv1)
1944 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001945 # helper methods for standardising recv* method signatures
1946 def _recv_into():
1947 b = bytearray(b"\0"*100)
1948 count = s.recv_into(b)
1949 return b[:count]
1950
1951 def _recvfrom_into():
1952 b = bytearray(b"\0"*100)
1953 count, addr = s.recvfrom_into(b)
1954 return b[:count]
1955
1956 # (name, method, whether to expect success, *args)
1957 send_methods = [
1958 ('send', s.send, True, []),
1959 ('sendto', s.sendto, False, ["some.address"]),
1960 ('sendall', s.sendall, True, []),
1961 ]
1962 recv_methods = [
1963 ('recv', s.recv, True, []),
1964 ('recvfrom', s.recvfrom, False, ["some.address"]),
1965 ('recv_into', _recv_into, True, []),
1966 ('recvfrom_into', _recvfrom_into, False, []),
1967 ]
1968 data_prefix = "PREFIX_"
1969
1970 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001971 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001972 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001973 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001974 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001975 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001976 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001977 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001978 "<<{outdata:r}>> ({nout:d}) received; "
1979 "expected <<{indata:r}>> ({nin:d})\n".format(
1980 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001981 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001982 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001983 )
1984 )
1985 except ValueError as e:
1986 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001987 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001988 "Failed to send with method <<{name:s}>>; "
1989 "expected to succeed.\n".format(name=meth_name)
1990 )
1991 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001992 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001993 "Method <<{name:s}>> failed with unexpected "
1994 "exception message: {exp:s}\n".format(
1995 name=meth_name, exp=e
1996 )
1997 )
1998
1999 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002000 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002001 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002002 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002003 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002004 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002005 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002006 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002007 "<<{outdata:r}>> ({nout:d}) received; "
2008 "expected <<{indata:r}>> ({nin:d})\n".format(
2009 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002010 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002011 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002012 )
2013 )
2014 except ValueError as e:
2015 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002016 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002017 "Failed to receive with method <<{name:s}>>; "
2018 "expected to succeed.\n".format(name=meth_name)
2019 )
2020 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002021 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002022 "Method <<{name:s}>> failed with unexpected "
2023 "exception message: {exp:s}\n".format(
2024 name=meth_name, exp=e
2025 )
2026 )
2027 # consume data
2028 s.read()
2029
Nick Coghlan513886a2011-08-28 00:00:27 +10002030 # Make sure sendmsg et al are disallowed to avoid
2031 # inadvertent disclosure of data and/or corruption
2032 # of the encrypted data stream
2033 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2034 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2035 self.assertRaises(NotImplementedError,
2036 s.recvmsg_into, bytearray(100))
2037
Antoine Pitrou480a1242010-04-28 21:37:09 +00002038 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002039 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002040
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002041 def test_handshake_timeout(self):
2042 # Issue #5103: SSL handshake must respect the socket timeout
2043 server = socket.socket(socket.AF_INET)
2044 host = "127.0.0.1"
2045 port = support.bind_port(server)
2046 started = threading.Event()
2047 finish = False
2048
2049 def serve():
2050 server.listen(5)
2051 started.set()
2052 conns = []
2053 while not finish:
2054 r, w, e = select.select([server], [], [], 0.1)
2055 if server in r:
2056 # Let the socket hang around rather than having
2057 # it closed by garbage collection.
2058 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002059 for sock in conns:
2060 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002061
2062 t = threading.Thread(target=serve)
2063 t.start()
2064 started.wait()
2065
2066 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002067 try:
2068 c = socket.socket(socket.AF_INET)
2069 c.settimeout(0.2)
2070 c.connect((host, port))
2071 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002072 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002073 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002074 finally:
2075 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002076 try:
2077 c = socket.socket(socket.AF_INET)
2078 c = ssl.wrap_socket(c)
2079 c.settimeout(0.2)
2080 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002081 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002082 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002083 finally:
2084 c.close()
2085 finally:
2086 finish = True
2087 t.join()
2088 server.close()
2089
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002090 def test_server_accept(self):
2091 # Issue #16357: accept() on a SSLSocket created through
2092 # SSLContext.wrap_socket().
2093 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2094 context.verify_mode = ssl.CERT_REQUIRED
2095 context.load_verify_locations(CERTFILE)
2096 context.load_cert_chain(CERTFILE)
2097 server = socket.socket(socket.AF_INET)
2098 host = "127.0.0.1"
2099 port = support.bind_port(server)
2100 server = context.wrap_socket(server, server_side=True)
2101
2102 evt = threading.Event()
2103 remote = None
2104 peer = None
2105 def serve():
2106 nonlocal remote, peer
2107 server.listen(5)
2108 # Block on the accept and wait on the connection to close.
2109 evt.set()
2110 remote, peer = server.accept()
2111 remote.recv(1)
2112
2113 t = threading.Thread(target=serve)
2114 t.start()
2115 # Client wait until server setup and perform a connect.
2116 evt.wait()
2117 client = context.wrap_socket(socket.socket())
2118 client.connect((host, port))
2119 client_addr = client.getsockname()
2120 client.close()
2121 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002122 remote.close()
2123 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002124 # Sanity checks.
2125 self.assertIsInstance(remote, ssl.SSLSocket)
2126 self.assertEqual(peer, client_addr)
2127
Antoine Pitrou242db722013-05-01 20:52:07 +02002128 def test_getpeercert_enotconn(self):
2129 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2130 with context.wrap_socket(socket.socket()) as sock:
2131 with self.assertRaises(OSError) as cm:
2132 sock.getpeercert()
2133 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2134
2135 def test_do_handshake_enotconn(self):
2136 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2137 with context.wrap_socket(socket.socket()) as sock:
2138 with self.assertRaises(OSError) as cm:
2139 sock.do_handshake()
2140 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2141
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002142 def test_default_ciphers(self):
2143 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2144 try:
2145 # Force a set of weak ciphers on our client context
2146 context.set_ciphers("DES")
2147 except ssl.SSLError:
2148 self.skipTest("no DES cipher available")
2149 with ThreadedEchoServer(CERTFILE,
2150 ssl_version=ssl.PROTOCOL_SSLv23,
2151 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002152 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002153 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002154 s.connect((HOST, server.port))
2155 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2156
Antoine Pitroud6494802011-07-21 01:11:30 +02002157 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2158 "'tls-unique' channel binding not available")
2159 def test_tls_unique_channel_binding(self):
2160 """Test tls-unique channel binding."""
2161 if support.verbose:
2162 sys.stdout.write("\n")
2163
2164 server = ThreadedEchoServer(CERTFILE,
2165 certreqs=ssl.CERT_NONE,
2166 ssl_version=ssl.PROTOCOL_TLSv1,
2167 cacerts=CERTFILE,
2168 chatty=True,
2169 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002170 with server:
2171 s = ssl.wrap_socket(socket.socket(),
2172 server_side=False,
2173 certfile=CERTFILE,
2174 ca_certs=CERTFILE,
2175 cert_reqs=ssl.CERT_NONE,
2176 ssl_version=ssl.PROTOCOL_TLSv1)
2177 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002178 # get the data
2179 cb_data = s.get_channel_binding("tls-unique")
2180 if support.verbose:
2181 sys.stdout.write(" got channel binding data: {0!r}\n"
2182 .format(cb_data))
2183
2184 # check if it is sane
2185 self.assertIsNotNone(cb_data)
2186 self.assertEqual(len(cb_data), 12) # True for TLSv1
2187
2188 # and compare with the peers version
2189 s.write(b"CB tls-unique\n")
2190 peer_data_repr = s.read().strip()
2191 self.assertEqual(peer_data_repr,
2192 repr(cb_data).encode("us-ascii"))
2193 s.close()
2194
2195 # now, again
2196 s = ssl.wrap_socket(socket.socket(),
2197 server_side=False,
2198 certfile=CERTFILE,
2199 ca_certs=CERTFILE,
2200 cert_reqs=ssl.CERT_NONE,
2201 ssl_version=ssl.PROTOCOL_TLSv1)
2202 s.connect((HOST, server.port))
2203 new_cb_data = s.get_channel_binding("tls-unique")
2204 if support.verbose:
2205 sys.stdout.write(" got another channel binding data: {0!r}\n"
2206 .format(new_cb_data))
2207 # is it really unique
2208 self.assertNotEqual(cb_data, new_cb_data)
2209 self.assertIsNotNone(cb_data)
2210 self.assertEqual(len(cb_data), 12) # True for TLSv1
2211 s.write(b"CB tls-unique\n")
2212 peer_data_repr = s.read().strip()
2213 self.assertEqual(peer_data_repr,
2214 repr(new_cb_data).encode("us-ascii"))
2215 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002216
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002217 def test_compression(self):
2218 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2219 context.load_cert_chain(CERTFILE)
2220 stats = server_params_test(context, context,
2221 chatty=True, connectionchatty=True)
2222 if support.verbose:
2223 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2224 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2225
2226 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2227 "ssl.OP_NO_COMPRESSION needed for this test")
2228 def test_compression_disabled(self):
2229 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2230 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002231 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002232 stats = server_params_test(context, context,
2233 chatty=True, connectionchatty=True)
2234 self.assertIs(stats['compression'], None)
2235
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002236 def test_dh_params(self):
2237 # Check we can get a connection with ephemeral Diffie-Hellman
2238 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2239 context.load_cert_chain(CERTFILE)
2240 context.load_dh_params(DHFILE)
2241 context.set_ciphers("kEDH")
2242 stats = server_params_test(context, context,
2243 chatty=True, connectionchatty=True)
2244 cipher = stats["cipher"][0]
2245 parts = cipher.split("-")
2246 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2247 self.fail("Non-DH cipher: " + cipher[0])
2248
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002249 def test_selected_npn_protocol(self):
2250 # selected_npn_protocol() is None unless NPN is used
2251 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2252 context.load_cert_chain(CERTFILE)
2253 stats = server_params_test(context, context,
2254 chatty=True, connectionchatty=True)
2255 self.assertIs(stats['client_npn_protocol'], None)
2256
2257 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2258 def test_npn_protocols(self):
2259 server_protocols = ['http/1.1', 'spdy/2']
2260 protocol_tests = [
2261 (['http/1.1', 'spdy/2'], 'http/1.1'),
2262 (['spdy/2', 'http/1.1'], 'http/1.1'),
2263 (['spdy/2', 'test'], 'spdy/2'),
2264 (['abc', 'def'], 'abc')
2265 ]
2266 for client_protocols, expected in protocol_tests:
2267 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2268 server_context.load_cert_chain(CERTFILE)
2269 server_context.set_npn_protocols(server_protocols)
2270 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2271 client_context.load_cert_chain(CERTFILE)
2272 client_context.set_npn_protocols(client_protocols)
2273 stats = server_params_test(client_context, server_context,
2274 chatty=True, connectionchatty=True)
2275
2276 msg = "failed trying %s (s) and %s (c).\n" \
2277 "was expecting %s, but got %%s from the %%s" \
2278 % (str(server_protocols), str(client_protocols),
2279 str(expected))
2280 client_result = stats['client_npn_protocol']
2281 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2282 server_result = stats['server_npn_protocols'][-1] \
2283 if len(stats['server_npn_protocols']) else 'nothing'
2284 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2285
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002286 def sni_contexts(self):
2287 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2288 server_context.load_cert_chain(SIGNED_CERTFILE)
2289 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2290 other_context.load_cert_chain(SIGNED_CERTFILE2)
2291 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2292 client_context.verify_mode = ssl.CERT_REQUIRED
2293 client_context.load_verify_locations(SIGNING_CA)
2294 return server_context, other_context, client_context
2295
2296 def check_common_name(self, stats, name):
2297 cert = stats['peercert']
2298 self.assertIn((('commonName', name),), cert['subject'])
2299
2300 @needs_sni
2301 def test_sni_callback(self):
2302 calls = []
2303 server_context, other_context, client_context = self.sni_contexts()
2304
2305 def servername_cb(ssl_sock, server_name, initial_context):
2306 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002307 if server_name is not None:
2308 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002309 server_context.set_servername_callback(servername_cb)
2310
2311 stats = server_params_test(client_context, server_context,
2312 chatty=True,
2313 sni_name='supermessage')
2314 # The hostname was fetched properly, and the certificate was
2315 # changed for the connection.
2316 self.assertEqual(calls, [("supermessage", server_context)])
2317 # CERTFILE4 was selected
2318 self.check_common_name(stats, 'fakehostname')
2319
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002320 calls = []
2321 # The callback is called with server_name=None
2322 stats = server_params_test(client_context, server_context,
2323 chatty=True,
2324 sni_name=None)
2325 self.assertEqual(calls, [(None, server_context)])
2326 self.check_common_name(stats, 'localhost')
2327
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002328 # Check disabling the callback
2329 calls = []
2330 server_context.set_servername_callback(None)
2331
2332 stats = server_params_test(client_context, server_context,
2333 chatty=True,
2334 sni_name='notfunny')
2335 # Certificate didn't change
2336 self.check_common_name(stats, 'localhost')
2337 self.assertEqual(calls, [])
2338
2339 @needs_sni
2340 def test_sni_callback_alert(self):
2341 # Returning a TLS alert is reflected to the connecting client
2342 server_context, other_context, client_context = self.sni_contexts()
2343
2344 def cb_returning_alert(ssl_sock, server_name, initial_context):
2345 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2346 server_context.set_servername_callback(cb_returning_alert)
2347
2348 with self.assertRaises(ssl.SSLError) as cm:
2349 stats = server_params_test(client_context, server_context,
2350 chatty=False,
2351 sni_name='supermessage')
2352 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2353
2354 @needs_sni
2355 def test_sni_callback_raising(self):
2356 # Raising fails the connection with a TLS handshake failure alert.
2357 server_context, other_context, client_context = self.sni_contexts()
2358
2359 def cb_raising(ssl_sock, server_name, initial_context):
2360 1/0
2361 server_context.set_servername_callback(cb_raising)
2362
2363 with self.assertRaises(ssl.SSLError) as cm, \
2364 support.captured_stderr() as stderr:
2365 stats = server_params_test(client_context, server_context,
2366 chatty=False,
2367 sni_name='supermessage')
2368 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2369 self.assertIn("ZeroDivisionError", stderr.getvalue())
2370
2371 @needs_sni
2372 def test_sni_callback_wrong_return_type(self):
2373 # Returning the wrong return type terminates the TLS connection
2374 # with an internal error alert.
2375 server_context, other_context, client_context = self.sni_contexts()
2376
2377 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2378 return "foo"
2379 server_context.set_servername_callback(cb_wrong_return_type)
2380
2381 with self.assertRaises(ssl.SSLError) as cm, \
2382 support.captured_stderr() as stderr:
2383 stats = server_params_test(client_context, server_context,
2384 chatty=False,
2385 sni_name='supermessage')
2386 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2387 self.assertIn("TypeError", stderr.getvalue())
2388
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002389 def test_read_write_after_close_raises_valuerror(self):
2390 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2391 context.verify_mode = ssl.CERT_REQUIRED
2392 context.load_verify_locations(CERTFILE)
2393 context.load_cert_chain(CERTFILE)
2394 server = ThreadedEchoServer(context=context, chatty=False)
2395
2396 with server:
2397 s = context.wrap_socket(socket.socket())
2398 s.connect((HOST, server.port))
2399 s.close()
2400
2401 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02002402 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002403
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002404
Thomas Woutersed03b412007-08-28 21:37:11 +00002405def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002406 if support.verbose:
2407 plats = {
2408 'Linux': platform.linux_distribution,
2409 'Mac': platform.mac_ver,
2410 'Windows': platform.win32_ver,
2411 }
2412 for name, func in plats.items():
2413 plat = func()
2414 if plat and plat[0]:
2415 plat = '%s %r' % (name, plat)
2416 break
2417 else:
2418 plat = repr(platform.platform())
2419 print("test_ssl: testing with %r %r" %
2420 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2421 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002422 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002423 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2424 try:
2425 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2426 except AttributeError:
2427 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002428
Antoine Pitrou152efa22010-05-16 18:19:27 +00002429 for filename in [
2430 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2431 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002432 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002433 BADCERT, BADKEY, EMPTYCERT]:
2434 if not os.path.exists(filename):
2435 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002436
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002437 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002438
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002439 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002440 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002441
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002442 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002443 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002444 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002445 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002446
Antoine Pitrou480a1242010-04-28 21:37:09 +00002447 try:
2448 support.run_unittest(*tests)
2449 finally:
2450 if _have_threads:
2451 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002452
2453if __name__ == "__main__":
2454 test_main()