blob: 89153052131bf760280e07cf4000454f1d95964b [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 Pitroub5218772010-05-21 09:56:06 +00001591 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001592 s.connect((HOST, server.port))
1593 cert = s.getpeercert()
1594 self.assertTrue(cert, "Can't get peer certificate.")
1595 cipher = s.cipher()
1596 if support.verbose:
1597 sys.stdout.write(pprint.pformat(cert) + '\n')
1598 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1599 if 'subject' not in cert:
1600 self.fail("No subject field in certificate: %s." %
1601 pprint.pformat(cert))
1602 if ((('organizationName', 'Python Software Foundation'),)
1603 not in cert['subject']):
1604 self.fail(
1605 "Missing or invalid 'organizationName' field in certificate subject; "
1606 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001607 self.assertIn('notBefore', cert)
1608 self.assertIn('notAfter', cert)
1609 before = ssl.cert_time_to_seconds(cert['notBefore'])
1610 after = ssl.cert_time_to_seconds(cert['notAfter'])
1611 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001612 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001613
Antoine Pitrou480a1242010-04-28 21:37:09 +00001614 def test_empty_cert(self):
1615 """Connecting with an empty cert file"""
1616 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1617 "nullcert.pem"))
1618 def test_malformed_cert(self):
1619 """Connecting with a badly formatted certificate (syntax error)"""
1620 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1621 "badcert.pem"))
1622 def test_nonexisting_cert(self):
1623 """Connecting with a non-existing cert file"""
1624 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1625 "wrongcert.pem"))
1626 def test_malformed_key(self):
1627 """Connecting with a badly formatted key (syntax error)"""
1628 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1629 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001630
Antoine Pitrou480a1242010-04-28 21:37:09 +00001631 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001632 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00001633 in the client when attempting handshake.
1634 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001635 listener_ready = threading.Event()
1636 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001637
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001638 s = socket.socket()
1639 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001640
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001641 # `listener` runs in a thread. It sits in an accept() until
1642 # the main thread connects. Then it rudely closes the socket,
1643 # and sets Event `listener_gone` to let the main thread know
1644 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001645 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001646 s.listen(5)
1647 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001648 newsock, addr = s.accept()
1649 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001650 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001651 listener_gone.set()
1652
1653 def connector():
1654 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001655 with socket.socket() as c:
1656 c.connect((HOST, port))
1657 listener_gone.wait()
1658 try:
1659 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001660 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001661 pass
1662 else:
1663 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001664
1665 t = threading.Thread(target=listener)
1666 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001667 try:
1668 connector()
1669 finally:
1670 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001671
Antoine Pitrou23df4832010-08-04 17:14:06 +00001672 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001673 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1674 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001675 def test_protocol_sslv2(self):
1676 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001677 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001678 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001679 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1680 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1681 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1682 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1683 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1684 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001685 # SSLv23 client with specific SSL options
1686 if no_sslv2_implies_sslv3_hello():
1687 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1688 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1689 client_options=ssl.OP_NO_SSLv2)
1690 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1691 client_options=ssl.OP_NO_SSLv3)
1692 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1693 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001694
Antoine Pitrou23df4832010-08-04 17:14:06 +00001695 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001696 def test_protocol_sslv23(self):
1697 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001698 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001699 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001700 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1701 try:
1702 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02001703 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02001704 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1705 if support.verbose:
1706 sys.stdout.write(
1707 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1708 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001709 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1710 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1711 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001712
Antoine Pitrou480a1242010-04-28 21:37:09 +00001713 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1714 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1715 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001716
Antoine Pitrou480a1242010-04-28 21:37:09 +00001717 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1718 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1719 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001720
Antoine Pitroub5218772010-05-21 09:56:06 +00001721 # Server with specific SSL options
1722 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1723 server_options=ssl.OP_NO_SSLv3)
1724 # Will choose TLSv1
1725 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1726 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1727 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1728 server_options=ssl.OP_NO_TLSv1)
1729
1730
Antoine Pitrou23df4832010-08-04 17:14:06 +00001731 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001732 def test_protocol_sslv3(self):
1733 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001734 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001735 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001736 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1737 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1738 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001739 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1740 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001741 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1742 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001743 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001744 if no_sslv2_implies_sslv3_hello():
1745 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1746 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1747 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001748
Antoine Pitrou23df4832010-08-04 17:14:06 +00001749 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001750 def test_protocol_tlsv1(self):
1751 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001752 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001753 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001754 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1755 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1756 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001757 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1758 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001759 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001760 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1761 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001762
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001763 @skip_if_broken_ubuntu_ssl
1764 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
1765 "TLS version 1.1 not supported.")
1766 def test_protocol_tlsv1_1(self):
1767 """Connecting to a TLSv1.1 server with various client options.
1768 Testing against older TLS versions."""
1769 if support.verbose:
1770 sys.stdout.write("\n")
1771 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
1772 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1773 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
1774 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
1775 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
1776 client_options=ssl.OP_NO_TLSv1_1)
1777
1778 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
1779 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
1780 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
1781
1782
1783 @skip_if_broken_ubuntu_ssl
1784 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
1785 "TLS version 1.2 not supported.")
1786 def test_protocol_tlsv1_2(self):
1787 """Connecting to a TLSv1.2 server with various client options.
1788 Testing against older TLS versions."""
1789 if support.verbose:
1790 sys.stdout.write("\n")
1791 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
1792 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
1793 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
1794 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1795 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
1796 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
1797 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
1798 client_options=ssl.OP_NO_TLSv1_2)
1799
1800 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
1801 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
1802 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
1803 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
1804 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
1805
Antoine Pitrou480a1242010-04-28 21:37:09 +00001806 def test_starttls(self):
1807 """Switching from clear text to encrypted and back again."""
1808 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 +00001809
Trent Nelson78520002008-04-10 20:54:35 +00001810 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001811 ssl_version=ssl.PROTOCOL_TLSv1,
1812 starttls_server=True,
1813 chatty=True,
1814 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001815 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001816 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001817 s = socket.socket()
1818 s.setblocking(1)
1819 s.connect((HOST, server.port))
1820 if support.verbose:
1821 sys.stdout.write("\n")
1822 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001823 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001824 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001825 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001826 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001827 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001828 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001829 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001830 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001831 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001832 msg = outdata.strip().lower()
1833 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1834 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001835 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001836 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001837 " client: read %r from server, starting TLS...\n"
1838 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001839 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1840 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001841 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1842 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001843 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001844 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001845 " client: read %r from server, ending TLS...\n"
1846 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001847 s = conn.unwrap()
1848 wrapped = False
1849 else:
1850 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001851 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001852 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001853 if support.verbose:
1854 sys.stdout.write(" client: closing connection.\n")
1855 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001856 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001857 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001858 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001859 if wrapped:
1860 conn.close()
1861 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001862 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001863
Antoine Pitrou480a1242010-04-28 21:37:09 +00001864 def test_socketserver(self):
1865 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01001866 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001867 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001868 if support.verbose:
1869 sys.stdout.write('\n')
1870 with open(CERTFILE, 'rb') as f:
1871 d1 = f.read()
1872 d2 = ''
1873 # now fetch the same data from the HTTPS server
1874 url = 'https://%s:%d/%s' % (
1875 HOST, server.port, os.path.split(CERTFILE)[1])
1876 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001877 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001878 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001879 if dlen and (int(dlen) > 0):
1880 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001881 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001882 sys.stdout.write(
1883 " client: read %d bytes from remote server '%s'\n"
1884 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001885 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001886 f.close()
1887 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001888
Antoine Pitrou480a1242010-04-28 21:37:09 +00001889 def test_asyncore_server(self):
1890 """Check the example asyncore integration."""
1891 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001892
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001893 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001894 sys.stdout.write("\n")
1895
Antoine Pitrou480a1242010-04-28 21:37:09 +00001896 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001897 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001898 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001899 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001900 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001901 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001902 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001903 " client: sending %r...\n" % indata)
1904 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001905 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001906 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001907 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001908 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001909 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001910 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1911 % (outdata[:20], len(outdata),
1912 indata[:20].lower(), len(indata)))
1913 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001914 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001915 sys.stdout.write(" client: closing connection.\n")
1916 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001917 if support.verbose:
1918 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001919
Antoine Pitrou480a1242010-04-28 21:37:09 +00001920 def test_recv_send(self):
1921 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001922 if support.verbose:
1923 sys.stdout.write("\n")
1924
1925 server = ThreadedEchoServer(CERTFILE,
1926 certreqs=ssl.CERT_NONE,
1927 ssl_version=ssl.PROTOCOL_TLSv1,
1928 cacerts=CERTFILE,
1929 chatty=True,
1930 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001931 with server:
1932 s = ssl.wrap_socket(socket.socket(),
1933 server_side=False,
1934 certfile=CERTFILE,
1935 ca_certs=CERTFILE,
1936 cert_reqs=ssl.CERT_NONE,
1937 ssl_version=ssl.PROTOCOL_TLSv1)
1938 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001939 # helper methods for standardising recv* method signatures
1940 def _recv_into():
1941 b = bytearray(b"\0"*100)
1942 count = s.recv_into(b)
1943 return b[:count]
1944
1945 def _recvfrom_into():
1946 b = bytearray(b"\0"*100)
1947 count, addr = s.recvfrom_into(b)
1948 return b[:count]
1949
1950 # (name, method, whether to expect success, *args)
1951 send_methods = [
1952 ('send', s.send, True, []),
1953 ('sendto', s.sendto, False, ["some.address"]),
1954 ('sendall', s.sendall, True, []),
1955 ]
1956 recv_methods = [
1957 ('recv', s.recv, True, []),
1958 ('recvfrom', s.recvfrom, False, ["some.address"]),
1959 ('recv_into', _recv_into, True, []),
1960 ('recvfrom_into', _recvfrom_into, False, []),
1961 ]
1962 data_prefix = "PREFIX_"
1963
1964 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001965 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001966 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001967 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001968 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001969 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001970 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001971 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001972 "<<{outdata:r}>> ({nout:d}) received; "
1973 "expected <<{indata:r}>> ({nin:d})\n".format(
1974 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001975 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001976 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001977 )
1978 )
1979 except ValueError as e:
1980 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001981 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001982 "Failed to send with method <<{name:s}>>; "
1983 "expected to succeed.\n".format(name=meth_name)
1984 )
1985 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001986 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001987 "Method <<{name:s}>> failed with unexpected "
1988 "exception message: {exp:s}\n".format(
1989 name=meth_name, exp=e
1990 )
1991 )
1992
1993 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001994 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001995 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001996 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001997 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001998 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001999 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002000 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002001 "<<{outdata:r}>> ({nout:d}) received; "
2002 "expected <<{indata:r}>> ({nin:d})\n".format(
2003 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002004 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002005 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002006 )
2007 )
2008 except ValueError as e:
2009 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002010 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002011 "Failed to receive with method <<{name:s}>>; "
2012 "expected to succeed.\n".format(name=meth_name)
2013 )
2014 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002015 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002016 "Method <<{name:s}>> failed with unexpected "
2017 "exception message: {exp:s}\n".format(
2018 name=meth_name, exp=e
2019 )
2020 )
2021 # consume data
2022 s.read()
2023
Nick Coghlan513886a2011-08-28 00:00:27 +10002024 # Make sure sendmsg et al are disallowed to avoid
2025 # inadvertent disclosure of data and/or corruption
2026 # of the encrypted data stream
2027 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2028 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2029 self.assertRaises(NotImplementedError,
2030 s.recvmsg_into, bytearray(100))
2031
Antoine Pitrou480a1242010-04-28 21:37:09 +00002032 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002033 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002034
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002035 def test_handshake_timeout(self):
2036 # Issue #5103: SSL handshake must respect the socket timeout
2037 server = socket.socket(socket.AF_INET)
2038 host = "127.0.0.1"
2039 port = support.bind_port(server)
2040 started = threading.Event()
2041 finish = False
2042
2043 def serve():
2044 server.listen(5)
2045 started.set()
2046 conns = []
2047 while not finish:
2048 r, w, e = select.select([server], [], [], 0.1)
2049 if server in r:
2050 # Let the socket hang around rather than having
2051 # it closed by garbage collection.
2052 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002053 for sock in conns:
2054 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002055
2056 t = threading.Thread(target=serve)
2057 t.start()
2058 started.wait()
2059
2060 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002061 try:
2062 c = socket.socket(socket.AF_INET)
2063 c.settimeout(0.2)
2064 c.connect((host, port))
2065 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002066 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002067 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002068 finally:
2069 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002070 try:
2071 c = socket.socket(socket.AF_INET)
2072 c = ssl.wrap_socket(c)
2073 c.settimeout(0.2)
2074 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002075 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002076 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002077 finally:
2078 c.close()
2079 finally:
2080 finish = True
2081 t.join()
2082 server.close()
2083
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002084 def test_server_accept(self):
2085 # Issue #16357: accept() on a SSLSocket created through
2086 # SSLContext.wrap_socket().
2087 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2088 context.verify_mode = ssl.CERT_REQUIRED
2089 context.load_verify_locations(CERTFILE)
2090 context.load_cert_chain(CERTFILE)
2091 server = socket.socket(socket.AF_INET)
2092 host = "127.0.0.1"
2093 port = support.bind_port(server)
2094 server = context.wrap_socket(server, server_side=True)
2095
2096 evt = threading.Event()
2097 remote = None
2098 peer = None
2099 def serve():
2100 nonlocal remote, peer
2101 server.listen(5)
2102 # Block on the accept and wait on the connection to close.
2103 evt.set()
2104 remote, peer = server.accept()
2105 remote.recv(1)
2106
2107 t = threading.Thread(target=serve)
2108 t.start()
2109 # Client wait until server setup and perform a connect.
2110 evt.wait()
2111 client = context.wrap_socket(socket.socket())
2112 client.connect((host, port))
2113 client_addr = client.getsockname()
2114 client.close()
2115 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002116 remote.close()
2117 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002118 # Sanity checks.
2119 self.assertIsInstance(remote, ssl.SSLSocket)
2120 self.assertEqual(peer, client_addr)
2121
Antoine Pitrou242db722013-05-01 20:52:07 +02002122 def test_getpeercert_enotconn(self):
2123 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2124 with context.wrap_socket(socket.socket()) as sock:
2125 with self.assertRaises(OSError) as cm:
2126 sock.getpeercert()
2127 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2128
2129 def test_do_handshake_enotconn(self):
2130 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2131 with context.wrap_socket(socket.socket()) as sock:
2132 with self.assertRaises(OSError) as cm:
2133 sock.do_handshake()
2134 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2135
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002136 def test_default_ciphers(self):
2137 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2138 try:
2139 # Force a set of weak ciphers on our client context
2140 context.set_ciphers("DES")
2141 except ssl.SSLError:
2142 self.skipTest("no DES cipher available")
2143 with ThreadedEchoServer(CERTFILE,
2144 ssl_version=ssl.PROTOCOL_SSLv23,
2145 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002146 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002147 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002148 s.connect((HOST, server.port))
2149 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2150
Antoine Pitroud6494802011-07-21 01:11:30 +02002151 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2152 "'tls-unique' channel binding not available")
2153 def test_tls_unique_channel_binding(self):
2154 """Test tls-unique channel binding."""
2155 if support.verbose:
2156 sys.stdout.write("\n")
2157
2158 server = ThreadedEchoServer(CERTFILE,
2159 certreqs=ssl.CERT_NONE,
2160 ssl_version=ssl.PROTOCOL_TLSv1,
2161 cacerts=CERTFILE,
2162 chatty=True,
2163 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002164 with server:
2165 s = ssl.wrap_socket(socket.socket(),
2166 server_side=False,
2167 certfile=CERTFILE,
2168 ca_certs=CERTFILE,
2169 cert_reqs=ssl.CERT_NONE,
2170 ssl_version=ssl.PROTOCOL_TLSv1)
2171 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002172 # get the data
2173 cb_data = s.get_channel_binding("tls-unique")
2174 if support.verbose:
2175 sys.stdout.write(" got channel binding data: {0!r}\n"
2176 .format(cb_data))
2177
2178 # check if it is sane
2179 self.assertIsNotNone(cb_data)
2180 self.assertEqual(len(cb_data), 12) # True for TLSv1
2181
2182 # and compare with the peers version
2183 s.write(b"CB tls-unique\n")
2184 peer_data_repr = s.read().strip()
2185 self.assertEqual(peer_data_repr,
2186 repr(cb_data).encode("us-ascii"))
2187 s.close()
2188
2189 # now, again
2190 s = ssl.wrap_socket(socket.socket(),
2191 server_side=False,
2192 certfile=CERTFILE,
2193 ca_certs=CERTFILE,
2194 cert_reqs=ssl.CERT_NONE,
2195 ssl_version=ssl.PROTOCOL_TLSv1)
2196 s.connect((HOST, server.port))
2197 new_cb_data = s.get_channel_binding("tls-unique")
2198 if support.verbose:
2199 sys.stdout.write(" got another channel binding data: {0!r}\n"
2200 .format(new_cb_data))
2201 # is it really unique
2202 self.assertNotEqual(cb_data, new_cb_data)
2203 self.assertIsNotNone(cb_data)
2204 self.assertEqual(len(cb_data), 12) # True for TLSv1
2205 s.write(b"CB tls-unique\n")
2206 peer_data_repr = s.read().strip()
2207 self.assertEqual(peer_data_repr,
2208 repr(new_cb_data).encode("us-ascii"))
2209 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002210
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002211 def test_compression(self):
2212 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2213 context.load_cert_chain(CERTFILE)
2214 stats = server_params_test(context, context,
2215 chatty=True, connectionchatty=True)
2216 if support.verbose:
2217 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2218 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2219
2220 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2221 "ssl.OP_NO_COMPRESSION needed for this test")
2222 def test_compression_disabled(self):
2223 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2224 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002225 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002226 stats = server_params_test(context, context,
2227 chatty=True, connectionchatty=True)
2228 self.assertIs(stats['compression'], None)
2229
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002230 def test_dh_params(self):
2231 # Check we can get a connection with ephemeral Diffie-Hellman
2232 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2233 context.load_cert_chain(CERTFILE)
2234 context.load_dh_params(DHFILE)
2235 context.set_ciphers("kEDH")
2236 stats = server_params_test(context, context,
2237 chatty=True, connectionchatty=True)
2238 cipher = stats["cipher"][0]
2239 parts = cipher.split("-")
2240 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2241 self.fail("Non-DH cipher: " + cipher[0])
2242
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002243 def test_selected_npn_protocol(self):
2244 # selected_npn_protocol() is None unless NPN is used
2245 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2246 context.load_cert_chain(CERTFILE)
2247 stats = server_params_test(context, context,
2248 chatty=True, connectionchatty=True)
2249 self.assertIs(stats['client_npn_protocol'], None)
2250
2251 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2252 def test_npn_protocols(self):
2253 server_protocols = ['http/1.1', 'spdy/2']
2254 protocol_tests = [
2255 (['http/1.1', 'spdy/2'], 'http/1.1'),
2256 (['spdy/2', 'http/1.1'], 'http/1.1'),
2257 (['spdy/2', 'test'], 'spdy/2'),
2258 (['abc', 'def'], 'abc')
2259 ]
2260 for client_protocols, expected in protocol_tests:
2261 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2262 server_context.load_cert_chain(CERTFILE)
2263 server_context.set_npn_protocols(server_protocols)
2264 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2265 client_context.load_cert_chain(CERTFILE)
2266 client_context.set_npn_protocols(client_protocols)
2267 stats = server_params_test(client_context, server_context,
2268 chatty=True, connectionchatty=True)
2269
2270 msg = "failed trying %s (s) and %s (c).\n" \
2271 "was expecting %s, but got %%s from the %%s" \
2272 % (str(server_protocols), str(client_protocols),
2273 str(expected))
2274 client_result = stats['client_npn_protocol']
2275 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2276 server_result = stats['server_npn_protocols'][-1] \
2277 if len(stats['server_npn_protocols']) else 'nothing'
2278 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2279
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002280 def sni_contexts(self):
2281 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2282 server_context.load_cert_chain(SIGNED_CERTFILE)
2283 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2284 other_context.load_cert_chain(SIGNED_CERTFILE2)
2285 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2286 client_context.verify_mode = ssl.CERT_REQUIRED
2287 client_context.load_verify_locations(SIGNING_CA)
2288 return server_context, other_context, client_context
2289
2290 def check_common_name(self, stats, name):
2291 cert = stats['peercert']
2292 self.assertIn((('commonName', name),), cert['subject'])
2293
2294 @needs_sni
2295 def test_sni_callback(self):
2296 calls = []
2297 server_context, other_context, client_context = self.sni_contexts()
2298
2299 def servername_cb(ssl_sock, server_name, initial_context):
2300 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002301 if server_name is not None:
2302 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002303 server_context.set_servername_callback(servername_cb)
2304
2305 stats = server_params_test(client_context, server_context,
2306 chatty=True,
2307 sni_name='supermessage')
2308 # The hostname was fetched properly, and the certificate was
2309 # changed for the connection.
2310 self.assertEqual(calls, [("supermessage", server_context)])
2311 # CERTFILE4 was selected
2312 self.check_common_name(stats, 'fakehostname')
2313
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002314 calls = []
2315 # The callback is called with server_name=None
2316 stats = server_params_test(client_context, server_context,
2317 chatty=True,
2318 sni_name=None)
2319 self.assertEqual(calls, [(None, server_context)])
2320 self.check_common_name(stats, 'localhost')
2321
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002322 # Check disabling the callback
2323 calls = []
2324 server_context.set_servername_callback(None)
2325
2326 stats = server_params_test(client_context, server_context,
2327 chatty=True,
2328 sni_name='notfunny')
2329 # Certificate didn't change
2330 self.check_common_name(stats, 'localhost')
2331 self.assertEqual(calls, [])
2332
2333 @needs_sni
2334 def test_sni_callback_alert(self):
2335 # Returning a TLS alert is reflected to the connecting client
2336 server_context, other_context, client_context = self.sni_contexts()
2337
2338 def cb_returning_alert(ssl_sock, server_name, initial_context):
2339 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2340 server_context.set_servername_callback(cb_returning_alert)
2341
2342 with self.assertRaises(ssl.SSLError) as cm:
2343 stats = server_params_test(client_context, server_context,
2344 chatty=False,
2345 sni_name='supermessage')
2346 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2347
2348 @needs_sni
2349 def test_sni_callback_raising(self):
2350 # Raising fails the connection with a TLS handshake failure alert.
2351 server_context, other_context, client_context = self.sni_contexts()
2352
2353 def cb_raising(ssl_sock, server_name, initial_context):
2354 1/0
2355 server_context.set_servername_callback(cb_raising)
2356
2357 with self.assertRaises(ssl.SSLError) as cm, \
2358 support.captured_stderr() as stderr:
2359 stats = server_params_test(client_context, server_context,
2360 chatty=False,
2361 sni_name='supermessage')
2362 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2363 self.assertIn("ZeroDivisionError", stderr.getvalue())
2364
2365 @needs_sni
2366 def test_sni_callback_wrong_return_type(self):
2367 # Returning the wrong return type terminates the TLS connection
2368 # with an internal error alert.
2369 server_context, other_context, client_context = self.sni_contexts()
2370
2371 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2372 return "foo"
2373 server_context.set_servername_callback(cb_wrong_return_type)
2374
2375 with self.assertRaises(ssl.SSLError) as cm, \
2376 support.captured_stderr() as stderr:
2377 stats = server_params_test(client_context, server_context,
2378 chatty=False,
2379 sni_name='supermessage')
2380 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2381 self.assertIn("TypeError", stderr.getvalue())
2382
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002383 def test_read_write_after_close_raises_valuerror(self):
2384 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2385 context.verify_mode = ssl.CERT_REQUIRED
2386 context.load_verify_locations(CERTFILE)
2387 context.load_cert_chain(CERTFILE)
2388 server = ThreadedEchoServer(context=context, chatty=False)
2389
2390 with server:
2391 s = context.wrap_socket(socket.socket())
2392 s.connect((HOST, server.port))
2393 s.close()
2394
2395 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02002396 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002397
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002398
Thomas Woutersed03b412007-08-28 21:37:11 +00002399def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002400 if support.verbose:
2401 plats = {
2402 'Linux': platform.linux_distribution,
2403 'Mac': platform.mac_ver,
2404 'Windows': platform.win32_ver,
2405 }
2406 for name, func in plats.items():
2407 plat = func()
2408 if plat and plat[0]:
2409 plat = '%s %r' % (name, plat)
2410 break
2411 else:
2412 plat = repr(platform.platform())
2413 print("test_ssl: testing with %r %r" %
2414 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2415 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002416 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002417 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2418 try:
2419 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2420 except AttributeError:
2421 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002422
Antoine Pitrou152efa22010-05-16 18:19:27 +00002423 for filename in [
2424 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2425 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002426 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002427 BADCERT, BADKEY, EMPTYCERT]:
2428 if not os.path.exists(filename):
2429 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002430
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002431 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002432
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002433 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002434 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002435
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002436 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002437 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002438 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002439 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002440
Antoine Pitrou480a1242010-04-28 21:37:09 +00002441 try:
2442 support.run_unittest(*tests)
2443 finally:
2444 if _have_threads:
2445 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002446
2447if __name__ == "__main__":
2448 test_main()