blob: b1cb8c5424846ae5b5902e13cea86a188bfd13e6 [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
Georg Brandl72c98d32013-10-27 07:16:53 +0100361 # only match one left-most wildcard
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000362 cert = {'subject': ((('commonName', 'f*.com'),),)}
363 ok(cert, 'foo.com')
364 ok(cert, 'f.com')
365 fail(cert, 'bar.com')
366 fail(cert, 'foo.a.com')
367 fail(cert, 'bar.foo.com')
368
Christian Heimes824f7f32013-08-17 00:54:47 +0200369 # NULL bytes are bad, CVE-2013-4073
370 cert = {'subject': ((('commonName',
371 'null.python.org\x00example.org'),),)}
372 ok(cert, 'null.python.org\x00example.org') # or raise an error?
373 fail(cert, 'example.org')
374 fail(cert, 'null.python.org')
375
Georg Brandl72c98d32013-10-27 07:16:53 +0100376 # error cases with wildcards
377 cert = {'subject': ((('commonName', '*.*.a.com'),),)}
378 fail(cert, 'bar.foo.a.com')
379 fail(cert, 'a.com')
380 fail(cert, 'Xa.com')
381 fail(cert, '.a.com')
382
383 cert = {'subject': ((('commonName', 'a.*.com'),),)}
384 fail(cert, 'a.foo.com')
385 fail(cert, 'a..com')
386 fail(cert, 'a.com')
387
388 # wildcard doesn't match IDNA prefix 'xn--'
389 idna = 'püthon.python.org'.encode("idna").decode("ascii")
390 cert = {'subject': ((('commonName', idna),),)}
391 ok(cert, idna)
392 cert = {'subject': ((('commonName', 'x*.python.org'),),)}
393 fail(cert, idna)
394 cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)}
395 fail(cert, idna)
396
397 # wildcard in first fragment and IDNA A-labels in sequent fragments
398 # are supported.
399 idna = 'www*.pythön.org'.encode("idna").decode("ascii")
400 cert = {'subject': ((('commonName', idna),),)}
401 ok(cert, 'www.pythön.org'.encode("idna").decode("ascii"))
402 ok(cert, 'www1.pythön.org'.encode("idna").decode("ascii"))
403 fail(cert, 'ftp.pythön.org'.encode("idna").decode("ascii"))
404 fail(cert, 'pythön.org'.encode("idna").decode("ascii"))
405
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000406 # Slightly fake real-world example
407 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
408 'subject': ((('commonName', 'linuxfrz.org'),),),
409 'subjectAltName': (('DNS', 'linuxfr.org'),
410 ('DNS', 'linuxfr.com'),
411 ('othername', '<unsupported>'))}
412 ok(cert, 'linuxfr.org')
413 ok(cert, 'linuxfr.com')
414 # Not a "DNS" entry
415 fail(cert, '<unsupported>')
416 # When there is a subjectAltName, commonName isn't used
417 fail(cert, 'linuxfrz.org')
418
419 # A pristine real-world example
420 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
421 'subject': ((('countryName', 'US'),),
422 (('stateOrProvinceName', 'California'),),
423 (('localityName', 'Mountain View'),),
424 (('organizationName', 'Google Inc'),),
425 (('commonName', 'mail.google.com'),))}
426 ok(cert, 'mail.google.com')
427 fail(cert, 'gmail.com')
428 # Only commonName is considered
429 fail(cert, 'California')
430
431 # Neither commonName nor subjectAltName
432 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
433 'subject': ((('countryName', 'US'),),
434 (('stateOrProvinceName', 'California'),),
435 (('localityName', 'Mountain View'),),
436 (('organizationName', 'Google Inc'),))}
437 fail(cert, 'mail.google.com')
438
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200439 # No DNS entry in subjectAltName but a commonName
440 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
441 'subject': ((('countryName', 'US'),),
442 (('stateOrProvinceName', 'California'),),
443 (('localityName', 'Mountain View'),),
444 (('commonName', 'mail.google.com'),)),
445 'subjectAltName': (('othername', 'blabla'), )}
446 ok(cert, 'mail.google.com')
447
448 # No DNS entry subjectAltName and no commonName
449 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
450 'subject': ((('countryName', 'US'),),
451 (('stateOrProvinceName', 'California'),),
452 (('localityName', 'Mountain View'),),
453 (('organizationName', 'Google Inc'),)),
454 'subjectAltName': (('othername', 'blabla'),)}
455 fail(cert, 'google.com')
456
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000457 # Empty cert / no cert
458 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
459 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
460
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200461 # Issue #17980: avoid denials of service by refusing more than one
462 # wildcard per fragment.
463 cert = {'subject': ((('commonName', 'a*b.com'),),)}
464 ok(cert, 'axxb.com')
465 cert = {'subject': ((('commonName', 'a*b.co*'),),)}
Georg Brandl72c98d32013-10-27 07:16:53 +0100466 fail(cert, 'axxb.com')
Antoine Pitrou636f93c2013-05-18 17:56:42 +0200467 cert = {'subject': ((('commonName', 'a*b*.com'),),)}
468 with self.assertRaises(ssl.CertificateError) as cm:
469 ssl.match_hostname(cert, 'axxbxxc.com')
470 self.assertIn("too many wildcards", str(cm.exception))
471
Antoine Pitroud5323212010-10-22 18:19:07 +0000472 def test_server_side(self):
473 # server_hostname doesn't work for server sockets
474 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000475 with socket.socket() as sock:
476 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
477 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000478
Antoine Pitroud6494802011-07-21 01:11:30 +0200479 def test_unknown_channel_binding(self):
480 # should raise ValueError for unknown type
481 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100482 with ssl.wrap_socket(s) as ss:
483 with self.assertRaises(ValueError):
484 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200485
486 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
487 "'tls-unique' channel binding not available")
488 def test_tls_unique_channel_binding(self):
489 # unconnected should return None for known type
490 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100491 with ssl.wrap_socket(s) as ss:
492 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200493 # the same for server-side
494 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100495 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
496 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200497
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600498 def test_dealloc_warn(self):
499 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
500 r = repr(ss)
501 with self.assertWarns(ResourceWarning) as cm:
502 ss = None
503 support.gc_collect()
504 self.assertIn(r, str(cm.warning.args[0]))
505
Christian Heimes6d7ad132013-06-09 18:02:55 +0200506 def test_get_default_verify_paths(self):
507 paths = ssl.get_default_verify_paths()
508 self.assertEqual(len(paths), 6)
509 self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
510
511 with support.EnvironmentVarGuard() as env:
512 env["SSL_CERT_DIR"] = CAPATH
513 env["SSL_CERT_FILE"] = CERTFILE
514 paths = ssl.get_default_verify_paths()
515 self.assertEqual(paths.cafile, CERTFILE)
516 self.assertEqual(paths.capath, CAPATH)
517
518
Christian Heimes46bebee2013-06-09 19:03:31 +0200519 @unittest.skipUnless(sys.platform == "win32", "Windows specific")
520 def test_enum_cert_store(self):
521 self.assertEqual(ssl.X509_ASN_ENCODING, 1)
522 self.assertEqual(ssl.PKCS_7_ASN_ENCODING, 0x00010000)
523
524 self.assertEqual(ssl.enum_cert_store("CA"),
525 ssl.enum_cert_store("CA", "certificate"))
526 ssl.enum_cert_store("CA", "crl")
527 self.assertEqual(ssl.enum_cert_store("ROOT"),
528 ssl.enum_cert_store("ROOT", "certificate"))
529 ssl.enum_cert_store("ROOT", "crl")
530
531 self.assertRaises(TypeError, ssl.enum_cert_store)
532 self.assertRaises(WindowsError, ssl.enum_cert_store, "")
533 self.assertRaises(ValueError, ssl.enum_cert_store, "CA", "wrong")
534
535 ca = ssl.enum_cert_store("CA")
536 self.assertIsInstance(ca, list)
537 self.assertIsInstance(ca[0], tuple)
538 self.assertEqual(len(ca[0]), 2)
539 self.assertIsInstance(ca[0][0], bytes)
540 self.assertIsInstance(ca[0][1], int)
541
Antoine Pitrou152efa22010-05-16 18:19:27 +0000542class ContextTests(unittest.TestCase):
543
Antoine Pitrou23df4832010-08-04 17:14:06 +0000544 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000545 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100546 for protocol in PROTOCOLS:
547 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000548 self.assertRaises(TypeError, ssl.SSLContext)
549 self.assertRaises(ValueError, ssl.SSLContext, -1)
550 self.assertRaises(ValueError, ssl.SSLContext, 42)
551
Antoine Pitrou23df4832010-08-04 17:14:06 +0000552 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000553 def test_protocol(self):
554 for proto in PROTOCOLS:
555 ctx = ssl.SSLContext(proto)
556 self.assertEqual(ctx.protocol, proto)
557
558 def test_ciphers(self):
559 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
560 ctx.set_ciphers("ALL")
561 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000562 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000563 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000564
Antoine Pitrou23df4832010-08-04 17:14:06 +0000565 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000566 def test_options(self):
567 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
568 # OP_ALL is the default value
569 self.assertEqual(ssl.OP_ALL, ctx.options)
570 ctx.options |= ssl.OP_NO_SSLv2
571 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
572 ctx.options)
573 ctx.options |= ssl.OP_NO_SSLv3
574 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
575 ctx.options)
576 if can_clear_options():
577 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
578 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
579 ctx.options)
580 ctx.options = 0
581 self.assertEqual(0, ctx.options)
582 else:
583 with self.assertRaises(ValueError):
584 ctx.options = 0
585
Antoine Pitrou152efa22010-05-16 18:19:27 +0000586 def test_verify(self):
587 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
588 # Default value
589 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
590 ctx.verify_mode = ssl.CERT_OPTIONAL
591 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
592 ctx.verify_mode = ssl.CERT_REQUIRED
593 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
594 ctx.verify_mode = ssl.CERT_NONE
595 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
596 with self.assertRaises(TypeError):
597 ctx.verify_mode = None
598 with self.assertRaises(ValueError):
599 ctx.verify_mode = 42
600
601 def test_load_cert_chain(self):
602 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
603 # Combined key and cert in a single file
604 ctx.load_cert_chain(CERTFILE)
605 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
606 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200607 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000608 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000609 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000610 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000611 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000612 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000613 ctx.load_cert_chain(EMPTYCERT)
614 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000615 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000616 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
617 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
618 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000619 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000620 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000621 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000622 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000623 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000624 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
625 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000626 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000627 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000628 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200629 # Password protected key and cert
630 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
631 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
632 ctx.load_cert_chain(CERTFILE_PROTECTED,
633 password=bytearray(KEY_PASSWORD.encode()))
634 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
635 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
636 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
637 bytearray(KEY_PASSWORD.encode()))
638 with self.assertRaisesRegex(TypeError, "should be a string"):
639 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
640 with self.assertRaises(ssl.SSLError):
641 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
642 with self.assertRaisesRegex(ValueError, "cannot be longer"):
643 # openssl has a fixed limit on the password buffer.
644 # PEM_BUFSIZE is generally set to 1kb.
645 # Return a string larger than this.
646 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
647 # Password callback
648 def getpass_unicode():
649 return KEY_PASSWORD
650 def getpass_bytes():
651 return KEY_PASSWORD.encode()
652 def getpass_bytearray():
653 return bytearray(KEY_PASSWORD.encode())
654 def getpass_badpass():
655 return "badpass"
656 def getpass_huge():
657 return b'a' * (1024 * 1024)
658 def getpass_bad_type():
659 return 9
660 def getpass_exception():
661 raise Exception('getpass error')
662 class GetPassCallable:
663 def __call__(self):
664 return KEY_PASSWORD
665 def getpass(self):
666 return KEY_PASSWORD
667 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
668 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
669 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
670 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
671 ctx.load_cert_chain(CERTFILE_PROTECTED,
672 password=GetPassCallable().getpass)
673 with self.assertRaises(ssl.SSLError):
674 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
675 with self.assertRaisesRegex(ValueError, "cannot be longer"):
676 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
677 with self.assertRaisesRegex(TypeError, "must return a string"):
678 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
679 with self.assertRaisesRegex(Exception, "getpass error"):
680 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
681 # Make sure the password function isn't called if it isn't needed
682 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000683
684 def test_load_verify_locations(self):
685 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
686 ctx.load_verify_locations(CERTFILE)
687 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
688 ctx.load_verify_locations(BYTES_CERTFILE)
689 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
690 self.assertRaises(TypeError, ctx.load_verify_locations)
691 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200692 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000693 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000694 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000695 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000696 ctx.load_verify_locations(BADCERT)
697 ctx.load_verify_locations(CERTFILE, CAPATH)
698 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
699
Victor Stinner80f75e62011-01-29 11:31:20 +0000700 # Issue #10989: crash if the second argument type is invalid
701 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
702
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100703 def test_load_dh_params(self):
704 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
705 ctx.load_dh_params(DHFILE)
706 if os.name != 'nt':
707 ctx.load_dh_params(BYTES_DHFILE)
708 self.assertRaises(TypeError, ctx.load_dh_params)
709 self.assertRaises(TypeError, ctx.load_dh_params, None)
710 with self.assertRaises(FileNotFoundError) as cm:
711 ctx.load_dh_params(WRONGCERT)
712 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200713 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100714 ctx.load_dh_params(CERTFILE)
715
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000716 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000717 def test_session_stats(self):
718 for proto in PROTOCOLS:
719 ctx = ssl.SSLContext(proto)
720 self.assertEqual(ctx.session_stats(), {
721 'number': 0,
722 'connect': 0,
723 'connect_good': 0,
724 'connect_renegotiate': 0,
725 'accept': 0,
726 'accept_good': 0,
727 'accept_renegotiate': 0,
728 'hits': 0,
729 'misses': 0,
730 'timeouts': 0,
731 'cache_full': 0,
732 })
733
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000734 def test_set_default_verify_paths(self):
735 # There's not much we can do to test that it acts as expected,
736 # so just check it doesn't crash or raise an exception.
737 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
738 ctx.set_default_verify_paths()
739
Antoine Pitrou501da612011-12-21 09:27:41 +0100740 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100741 def test_set_ecdh_curve(self):
742 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
743 ctx.set_ecdh_curve("prime256v1")
744 ctx.set_ecdh_curve(b"prime256v1")
745 self.assertRaises(TypeError, ctx.set_ecdh_curve)
746 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
747 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
748 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
749
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100750 @needs_sni
751 def test_sni_callback(self):
752 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
753
754 # set_servername_callback expects a callable, or None
755 self.assertRaises(TypeError, ctx.set_servername_callback)
756 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
757 self.assertRaises(TypeError, ctx.set_servername_callback, "")
758 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
759
760 def dummycallback(sock, servername, ctx):
761 pass
762 ctx.set_servername_callback(None)
763 ctx.set_servername_callback(dummycallback)
764
765 @needs_sni
766 def test_sni_callback_refcycle(self):
767 # Reference cycles through the servername callback are detected
768 # and cleared.
769 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
770 def dummycallback(sock, servername, ctx, cycle=ctx):
771 pass
772 ctx.set_servername_callback(dummycallback)
773 wr = weakref.ref(ctx)
774 del ctx, dummycallback
775 gc.collect()
776 self.assertIs(wr(), None)
777
Christian Heimes9a5395a2013-06-17 15:44:12 +0200778 def test_cert_store_stats(self):
779 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
780 self.assertEqual(ctx.cert_store_stats(),
781 {'x509_ca': 0, 'crl': 0, 'x509': 0})
782 ctx.load_cert_chain(CERTFILE)
783 self.assertEqual(ctx.cert_store_stats(),
784 {'x509_ca': 0, 'crl': 0, 'x509': 0})
785 ctx.load_verify_locations(CERTFILE)
786 self.assertEqual(ctx.cert_store_stats(),
787 {'x509_ca': 0, 'crl': 0, 'x509': 1})
788 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
789 self.assertEqual(ctx.cert_store_stats(),
790 {'x509_ca': 1, 'crl': 0, 'x509': 2})
791
792 def test_get_ca_certs(self):
793 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
794 self.assertEqual(ctx.get_ca_certs(), [])
795 # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
796 ctx.load_verify_locations(CERTFILE)
797 self.assertEqual(ctx.get_ca_certs(), [])
798 # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
799 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
800 self.assertEqual(ctx.get_ca_certs(),
801 [{'issuer': ((('organizationName', 'Root CA'),),
802 (('organizationalUnitName', 'http://www.cacert.org'),),
803 (('commonName', 'CA Cert Signing Authority'),),
804 (('emailAddress', 'support@cacert.org'),)),
805 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'),
806 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'),
807 'serialNumber': '00',
808 'subject': ((('organizationName', 'Root CA'),),
809 (('organizationalUnitName', 'http://www.cacert.org'),),
810 (('commonName', 'CA Cert Signing Authority'),),
811 (('emailAddress', 'support@cacert.org'),)),
812 'version': 3}])
813
814 with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
815 pem = f.read()
816 der = ssl.PEM_cert_to_DER_cert(pem)
817 self.assertEqual(ctx.get_ca_certs(True), [der])
818
Antoine Pitrou152efa22010-05-16 18:19:27 +0000819
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200820class SSLErrorTests(unittest.TestCase):
821
822 def test_str(self):
823 # The str() of a SSLError doesn't include the errno
824 e = ssl.SSLError(1, "foo")
825 self.assertEqual(str(e), "foo")
826 self.assertEqual(e.errno, 1)
827 # Same for a subclass
828 e = ssl.SSLZeroReturnError(1, "foo")
829 self.assertEqual(str(e), "foo")
830 self.assertEqual(e.errno, 1)
831
832 def test_lib_reason(self):
833 # Test the library and reason attributes
834 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
835 with self.assertRaises(ssl.SSLError) as cm:
836 ctx.load_dh_params(CERTFILE)
837 self.assertEqual(cm.exception.library, 'PEM')
838 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
839 s = str(cm.exception)
840 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
841
842 def test_subclass(self):
843 # Check that the appropriate SSLError subclass is raised
844 # (this only tests one of them)
845 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
846 with socket.socket() as s:
847 s.bind(("127.0.0.1", 0))
848 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100849 c = socket.socket()
850 c.connect(s.getsockname())
851 c.setblocking(False)
852 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200853 with self.assertRaises(ssl.SSLWantReadError) as cm:
854 c.do_handshake()
855 s = str(cm.exception)
856 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
857 # For compatibility
858 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
859
860
Bill Janssen6e027db2007-11-15 22:23:56 +0000861class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000862
Antoine Pitrou480a1242010-04-28 21:37:09 +0000863 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000864 with support.transient_internet("svn.python.org"):
865 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
866 cert_reqs=ssl.CERT_NONE)
867 try:
868 s.connect(("svn.python.org", 443))
869 self.assertEqual({}, s.getpeercert())
870 finally:
871 s.close()
872
873 # this should fail because we have no verification certs
874 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
875 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000876 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
877 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000878 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000879
Antoine Pitrou350c7222010-09-09 13:31:46 +0000880 # this should succeed because we specify the root cert
881 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
882 cert_reqs=ssl.CERT_REQUIRED,
883 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
884 try:
885 s.connect(("svn.python.org", 443))
886 self.assertTrue(s.getpeercert())
887 finally:
888 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000889
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000890 def test_connect_ex(self):
891 # Issue #11326: check connect_ex() implementation
892 with support.transient_internet("svn.python.org"):
893 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
894 cert_reqs=ssl.CERT_REQUIRED,
895 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
896 try:
897 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
898 self.assertTrue(s.getpeercert())
899 finally:
900 s.close()
901
902 def test_non_blocking_connect_ex(self):
903 # Issue #11326: non-blocking connect_ex() should allow handshake
904 # to proceed after the socket gets ready.
905 with support.transient_internet("svn.python.org"):
906 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
907 cert_reqs=ssl.CERT_REQUIRED,
908 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
909 do_handshake_on_connect=False)
910 try:
911 s.setblocking(False)
912 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000913 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
914 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000915 # Wait for connect to finish
916 select.select([], [s], [], 5.0)
917 # Non-blocking handshake
918 while True:
919 try:
920 s.do_handshake()
921 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200922 except ssl.SSLWantReadError:
923 select.select([s], [], [], 5.0)
924 except ssl.SSLWantWriteError:
925 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000926 # SSL established
927 self.assertTrue(s.getpeercert())
928 finally:
929 s.close()
930
Antoine Pitroub4410db2011-05-18 18:51:06 +0200931 def test_timeout_connect_ex(self):
932 # Issue #12065: on a timeout, connect_ex() should return the original
933 # errno (mimicking the behaviour of non-SSL sockets).
934 with support.transient_internet("svn.python.org"):
935 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
936 cert_reqs=ssl.CERT_REQUIRED,
937 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
938 do_handshake_on_connect=False)
939 try:
940 s.settimeout(0.0000001)
941 rc = s.connect_ex(('svn.python.org', 443))
942 if rc == 0:
943 self.skipTest("svn.python.org responded too quickly")
944 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
945 finally:
946 s.close()
947
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100948 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100949 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100950 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
951 cert_reqs=ssl.CERT_REQUIRED,
952 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
953 try:
954 self.assertEqual(errno.ECONNREFUSED,
955 s.connect_ex(("svn.python.org", 444)))
956 finally:
957 s.close()
958
Antoine Pitrou152efa22010-05-16 18:19:27 +0000959 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000960 with support.transient_internet("svn.python.org"):
961 # Same as test_connect, but with a separately created context
962 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
963 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
964 s.connect(("svn.python.org", 443))
965 try:
966 self.assertEqual({}, s.getpeercert())
967 finally:
968 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000969 # Same with a server hostname
970 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
971 server_hostname="svn.python.org")
972 if ssl.HAS_SNI:
973 s.connect(("svn.python.org", 443))
974 s.close()
975 else:
976 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000977 # This should fail because we have no verification certs
978 ctx.verify_mode = ssl.CERT_REQUIRED
979 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000980 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000981 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000982 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000983 # This should succeed because we specify the root cert
984 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
985 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
986 s.connect(("svn.python.org", 443))
987 try:
988 cert = s.getpeercert()
989 self.assertTrue(cert)
990 finally:
991 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000992
993 def test_connect_capath(self):
994 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000995 # NOTE: the subject hashing algorithm has been changed between
996 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
997 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000998 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000999 with support.transient_internet("svn.python.org"):
1000 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1001 ctx.verify_mode = ssl.CERT_REQUIRED
1002 ctx.load_verify_locations(capath=CAPATH)
1003 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1004 s.connect(("svn.python.org", 443))
1005 try:
1006 cert = s.getpeercert()
1007 self.assertTrue(cert)
1008 finally:
1009 s.close()
1010 # Same with a bytes `capath` argument
1011 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1012 ctx.verify_mode = ssl.CERT_REQUIRED
1013 ctx.load_verify_locations(capath=BYTES_CAPATH)
1014 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1015 s.connect(("svn.python.org", 443))
1016 try:
1017 cert = s.getpeercert()
1018 self.assertTrue(cert)
1019 finally:
1020 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001021
Antoine Pitroue3220242010-04-24 11:13:53 +00001022 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
1023 def test_makefile_close(self):
1024 # Issue #5238: creating a file-like object with makefile() shouldn't
1025 # delay closing the underlying "real socket" (here tested with its
1026 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +00001027 with support.transient_internet("svn.python.org"):
1028 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
1029 ss.connect(("svn.python.org", 443))
1030 fd = ss.fileno()
1031 f = ss.makefile()
1032 f.close()
1033 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +00001034 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001035 # Closing the SSL socket should close the fd too
1036 ss.close()
1037 gc.collect()
1038 with self.assertRaises(OSError) as e:
1039 os.read(fd, 0)
1040 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +00001041
Antoine Pitrou480a1242010-04-28 21:37:09 +00001042 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +00001043 with support.transient_internet("svn.python.org"):
1044 s = socket.socket(socket.AF_INET)
1045 s.connect(("svn.python.org", 443))
1046 s.setblocking(False)
1047 s = ssl.wrap_socket(s,
1048 cert_reqs=ssl.CERT_NONE,
1049 do_handshake_on_connect=False)
1050 count = 0
1051 while True:
1052 try:
1053 count += 1
1054 s.do_handshake()
1055 break
Antoine Pitrou41032a62011-10-27 23:56:55 +02001056 except ssl.SSLWantReadError:
1057 select.select([s], [], [])
1058 except ssl.SSLWantWriteError:
1059 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +00001060 s.close()
1061 if support.verbose:
1062 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001063
Antoine Pitrou480a1242010-04-28 21:37:09 +00001064 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +02001065 def _test_get_server_certificate(host, port, cert=None):
1066 with support.transient_internet(host):
1067 pem = ssl.get_server_certificate((host, port))
1068 if not pem:
1069 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001070
Antoine Pitrou15399c32011-04-28 19:23:55 +02001071 try:
1072 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
1073 except ssl.SSLError as x:
1074 #should fail
1075 if support.verbose:
1076 sys.stdout.write("%s\n" % x)
1077 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001078 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
1079
Antoine Pitrou15399c32011-04-28 19:23:55 +02001080 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
1081 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001082 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001083 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +02001084 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +00001085
Antoine Pitrou15399c32011-04-28 19:23:55 +02001086 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
1087 if support.IPV6_ENABLED:
1088 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001089
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001090 def test_ciphers(self):
1091 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001092 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001093 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1094 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
1095 s.connect(remote)
1096 with ssl.wrap_socket(socket.socket(socket.AF_INET),
1097 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
1098 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +00001099 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +00001100 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +00001101 with socket.socket(socket.AF_INET) as sock:
1102 s = ssl.wrap_socket(sock,
1103 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
1104 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +00001105
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001106 def test_algorithms(self):
1107 # Issue #8484: all algorithms should be available when verifying a
1108 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +00001109 # SHA256 was added in OpenSSL 0.9.8
1110 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
1111 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001112 # sha256.tbs-internet.com needs SNI to use the correct certificate
1113 if not ssl.HAS_SNI:
1114 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +00001115 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
1116 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001117 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +00001118 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +02001119 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1120 ctx.verify_mode = ssl.CERT_REQUIRED
1121 ctx.load_verify_locations(sha256_cert)
1122 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
1123 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +00001124 try:
1125 s.connect(remote)
1126 if support.verbose:
1127 sys.stdout.write("\nCipher with %r is %r\n" %
1128 (remote, s.cipher()))
1129 sys.stdout.write("Certificate is:\n%s\n" %
1130 pprint.pformat(s.getpeercert()))
1131 finally:
1132 s.close()
1133
Christian Heimes9a5395a2013-06-17 15:44:12 +02001134 def test_get_ca_certs_capath(self):
1135 # capath certs are loaded on request
1136 with support.transient_internet("svn.python.org"):
1137 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1138 ctx.verify_mode = ssl.CERT_REQUIRED
1139 ctx.load_verify_locations(capath=CAPATH)
1140 self.assertEqual(ctx.get_ca_certs(), [])
1141 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
1142 s.connect(("svn.python.org", 443))
1143 try:
1144 cert = s.getpeercert()
1145 self.assertTrue(cert)
1146 finally:
1147 s.close()
1148 self.assertEqual(len(ctx.get_ca_certs()), 1)
1149
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150
1151try:
1152 import threading
1153except ImportError:
1154 _have_threads = False
1155else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001156 _have_threads = True
1157
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001158 from test.ssl_servers import make_https_server
1159
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001160 class ThreadedEchoServer(threading.Thread):
1161
1162 class ConnectionHandler(threading.Thread):
1163
1164 """A mildly complicated class, because we want it to work both
1165 with and without the SSL wrapper around the socket connection, so
1166 that we can test the STARTTLS functionality."""
1167
Bill Janssen6e027db2007-11-15 22:23:56 +00001168 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001169 self.server = server
1170 self.running = False
1171 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +00001172 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001173 self.sock.setblocking(1)
1174 self.sslconn = None
1175 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001176 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001177
Antoine Pitrou480a1242010-04-28 21:37:09 +00001178 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001179 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001180 self.sslconn = self.server.context.wrap_socket(
1181 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001182 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +01001183 except (ssl.SSLError, ConnectionResetError) as e:
1184 # We treat ConnectionResetError as though it were an
1185 # SSLError - OpenSSL on Ubuntu abruptly closes the
1186 # connection when asked to use an unsupported protocol.
1187 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001188 # XXX Various errors can have happened here, for example
1189 # a mismatching protocol version, an invalid certificate,
1190 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001191 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001192 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +00001193 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001194 self.running = False
1195 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001196 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001197 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001198 else:
Antoine Pitroub5218772010-05-21 09:56:06 +00001199 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001200 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001201 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001202 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
1203 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001204 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001205 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
1206 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001207 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001208 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001209 sys.stdout.write(" server: selected protocol is now "
1210 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001211 return True
1212
1213 def read(self):
1214 if self.sslconn:
1215 return self.sslconn.read()
1216 else:
1217 return self.sock.recv(1024)
1218
1219 def write(self, bytes):
1220 if self.sslconn:
1221 return self.sslconn.write(bytes)
1222 else:
1223 return self.sock.send(bytes)
1224
1225 def close(self):
1226 if self.sslconn:
1227 self.sslconn.close()
1228 else:
1229 self.sock.close()
1230
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001232 self.running = True
1233 if not self.server.starttls_server:
1234 if not self.wrap_conn():
1235 return
1236 while self.running:
1237 try:
1238 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001239 stripped = msg.strip()
1240 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241 # eof, so quit this handler
1242 self.running = False
1243 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001244 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001245 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001246 sys.stdout.write(" server: client closed connection\n")
1247 self.close()
1248 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001249 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001250 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001251 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001252 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001253 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001254 if not self.wrap_conn():
1255 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001256 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001257 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001258 if support.verbose and self.server.connectionchatty:
1259 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001260 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001261 self.sock = self.sslconn.unwrap()
1262 self.sslconn = None
1263 if support.verbose and self.server.connectionchatty:
1264 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001265 elif stripped == b'CB tls-unique':
1266 if support.verbose and self.server.connectionchatty:
1267 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1268 data = self.sslconn.get_channel_binding("tls-unique")
1269 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001270 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001271 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001272 self.server.connectionchatty):
1273 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001274 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1275 % (msg, ctype, msg.lower(), ctype))
1276 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001277 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001278 if self.server.chatty:
1279 handle_error("Test server failure:\n")
1280 self.close()
1281 self.running = False
1282 # normally, we'd just stop here, but for the test
1283 # harness, we want to stop the server
1284 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001285
Antoine Pitroub5218772010-05-21 09:56:06 +00001286 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001287 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001288 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001289 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001290 if context:
1291 self.context = context
1292 else:
1293 self.context = ssl.SSLContext(ssl_version
1294 if ssl_version is not None
1295 else ssl.PROTOCOL_TLSv1)
1296 self.context.verify_mode = (certreqs if certreqs is not None
1297 else ssl.CERT_NONE)
1298 if cacerts:
1299 self.context.load_verify_locations(cacerts)
1300 if certificate:
1301 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001302 if npn_protocols:
1303 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001304 if ciphers:
1305 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001306 self.chatty = chatty
1307 self.connectionchatty = connectionchatty
1308 self.starttls_server = starttls_server
1309 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001310 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001311 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001312 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001313 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001314 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001315 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001316 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001317
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001318 def __enter__(self):
1319 self.start(threading.Event())
1320 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001321 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001322
1323 def __exit__(self, *args):
1324 self.stop()
1325 self.join()
1326
Antoine Pitrou480a1242010-04-28 21:37:09 +00001327 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001328 self.flag = flag
1329 threading.Thread.start(self)
1330
Antoine Pitrou480a1242010-04-28 21:37:09 +00001331 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001332 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001333 self.sock.listen(5)
1334 self.active = True
1335 if self.flag:
1336 # signal an event
1337 self.flag.set()
1338 while self.active:
1339 try:
1340 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001341 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001342 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001343 + repr(connaddr) + '\n')
1344 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001345 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001346 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001347 except socket.timeout:
1348 pass
1349 except KeyboardInterrupt:
1350 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001351 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001352
Antoine Pitrou480a1242010-04-28 21:37:09 +00001353 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001354 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001355
Bill Janssen54cc54c2007-12-14 22:08:56 +00001356 class AsyncoreEchoServer(threading.Thread):
1357
1358 # this one's based on asyncore.dispatcher
1359
1360 class EchoServer (asyncore.dispatcher):
1361
1362 class ConnectionHandler (asyncore.dispatcher_with_send):
1363
1364 def __init__(self, conn, certfile):
1365 self.socket = ssl.wrap_socket(conn, server_side=True,
1366 certfile=certfile,
1367 do_handshake_on_connect=False)
1368 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001369 self._ssl_accepting = True
1370 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001371
1372 def readable(self):
1373 if isinstance(self.socket, ssl.SSLSocket):
1374 while self.socket.pending() > 0:
1375 self.handle_read_event()
1376 return True
1377
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001378 def _do_ssl_handshake(self):
1379 try:
1380 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001381 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1382 return
1383 except ssl.SSLEOFError:
1384 return self.handle_close()
1385 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001386 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001387 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001388 if err.args[0] == errno.ECONNABORTED:
1389 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001390 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001391 self._ssl_accepting = False
1392
1393 def handle_read(self):
1394 if self._ssl_accepting:
1395 self._do_ssl_handshake()
1396 else:
1397 data = self.recv(1024)
1398 if support.verbose:
1399 sys.stdout.write(" server: read %s from client\n" % repr(data))
1400 if not data:
1401 self.close()
1402 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001403 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001404
1405 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001406 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001407 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001408 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1409
1410 def handle_error(self):
1411 raise
1412
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001413 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001414 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001415 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1416 self.port = support.bind_port(sock, '')
1417 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001418 self.listen(5)
1419
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001420 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001421 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001422 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1423 self.ConnectionHandler(sock_obj, self.certfile)
1424
1425 def handle_error(self):
1426 raise
1427
Trent Nelson78520002008-04-10 20:54:35 +00001428 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001429 self.flag = None
1430 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001431 self.server = self.EchoServer(certfile)
1432 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001433 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001434 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001435
1436 def __str__(self):
1437 return "<%s %s>" % (self.__class__.__name__, self.server)
1438
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001439 def __enter__(self):
1440 self.start(threading.Event())
1441 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001442 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001443
1444 def __exit__(self, *args):
1445 if support.verbose:
1446 sys.stdout.write(" cleanup: stopping server.\n")
1447 self.stop()
1448 if support.verbose:
1449 sys.stdout.write(" cleanup: joining server thread.\n")
1450 self.join()
1451 if support.verbose:
1452 sys.stdout.write(" cleanup: successfully joined.\n")
1453
Bill Janssen54cc54c2007-12-14 22:08:56 +00001454 def start (self, flag=None):
1455 self.flag = flag
1456 threading.Thread.start(self)
1457
Antoine Pitrou480a1242010-04-28 21:37:09 +00001458 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001459 self.active = True
1460 if self.flag:
1461 self.flag.set()
1462 while self.active:
1463 try:
1464 asyncore.loop(1)
1465 except:
1466 pass
1467
Antoine Pitrou480a1242010-04-28 21:37:09 +00001468 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001469 self.active = False
1470 self.server.close()
1471
Antoine Pitrou480a1242010-04-28 21:37:09 +00001472 def bad_cert_test(certfile):
1473 """
1474 Launch a server with CERT_REQUIRED, and check that trying to
1475 connect to it with the given client certificate fails.
1476 """
Trent Nelson78520002008-04-10 20:54:35 +00001477 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001478 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001479 cacerts=CERTFILE, chatty=False,
1480 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001481 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001482 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001483 with socket.socket() as sock:
1484 s = ssl.wrap_socket(sock,
1485 certfile=certfile,
1486 ssl_version=ssl.PROTOCOL_TLSv1)
1487 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001488 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001489 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001490 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001491 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001493 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001494 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001495 if x.errno != errno.ENOENT:
1496 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001497 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001498 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001499 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001500 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001501
Antoine Pitroub5218772010-05-21 09:56:06 +00001502 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001503 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001504 """
1505 Launch a server, connect a client to it and try various reads
1506 and writes.
1507 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001508 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001509 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001510 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001511 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001512 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001513 with client_context.wrap_socket(socket.socket(),
1514 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001515 s.connect((HOST, server.port))
1516 for arg in [indata, bytearray(indata), memoryview(indata)]:
1517 if connectionchatty:
1518 if support.verbose:
1519 sys.stdout.write(
1520 " client: sending %r...\n" % indata)
1521 s.write(arg)
1522 outdata = s.read()
1523 if connectionchatty:
1524 if support.verbose:
1525 sys.stdout.write(" client: read %r\n" % outdata)
1526 if outdata != indata.lower():
1527 raise AssertionError(
1528 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1529 % (outdata[:20], len(outdata),
1530 indata[:20].lower(), len(indata)))
1531 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001532 if connectionchatty:
1533 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001534 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001535 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001536 'compression': s.compression(),
1537 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001538 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001539 'client_npn_protocol': s.selected_npn_protocol()
1540 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001541 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001542 stats['server_npn_protocols'] = server.selected_protocols
1543 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001544
Antoine Pitroub5218772010-05-21 09:56:06 +00001545 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1546 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001547 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001548 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001549 certtype = {
1550 ssl.CERT_NONE: "CERT_NONE",
1551 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1552 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1553 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001554 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001555 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001556 sys.stdout.write(formatstr %
1557 (ssl.get_protocol_name(client_protocol),
1558 ssl.get_protocol_name(server_protocol),
1559 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001560 client_context = ssl.SSLContext(client_protocol)
1561 client_context.options = ssl.OP_ALL | client_options
1562 server_context = ssl.SSLContext(server_protocol)
1563 server_context.options = ssl.OP_ALL | server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001564
1565 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1566 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1567 # starting from OpenSSL 1.0.0 (see issue #8322).
1568 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1569 client_context.set_ciphers("ALL")
1570
Antoine Pitroub5218772010-05-21 09:56:06 +00001571 for ctx in (client_context, server_context):
1572 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001573 ctx.load_cert_chain(CERTFILE)
1574 ctx.load_verify_locations(CERTFILE)
1575 try:
1576 server_params_test(client_context, server_context,
1577 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001578 # Protocol mismatch can result in either an SSLError, or a
1579 # "Connection reset by peer" error.
1580 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001581 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001582 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001583 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001584 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001585 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001586 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001587 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001588 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001589 "Client protocol %s succeeded with server protocol %s!"
1590 % (ssl.get_protocol_name(client_protocol),
1591 ssl.get_protocol_name(server_protocol)))
1592
1593
Bill Janssen6e027db2007-11-15 22:23:56 +00001594 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001595
Antoine Pitrou23df4832010-08-04 17:14:06 +00001596 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001597 def test_echo(self):
1598 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001599 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001600 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001601 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001602 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1603 context = ssl.SSLContext(protocol)
1604 context.load_cert_chain(CERTFILE)
1605 server_params_test(context, context,
1606 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001607
Antoine Pitrou480a1242010-04-28 21:37:09 +00001608 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001609 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001610 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001611 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1612 context.verify_mode = ssl.CERT_REQUIRED
1613 context.load_verify_locations(CERTFILE)
1614 context.load_cert_chain(CERTFILE)
1615 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001616 with server:
Antoine Pitrou20b85552013-09-29 19:50:53 +02001617 s = context.wrap_socket(socket.socket(),
1618 do_handshake_on_connect=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001619 s.connect((HOST, server.port))
Antoine Pitrou20b85552013-09-29 19:50:53 +02001620 # getpeercert() raise ValueError while the handshake isn't
1621 # done.
1622 with self.assertRaises(ValueError):
1623 s.getpeercert()
1624 s.do_handshake()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001625 cert = s.getpeercert()
1626 self.assertTrue(cert, "Can't get peer certificate.")
1627 cipher = s.cipher()
1628 if support.verbose:
1629 sys.stdout.write(pprint.pformat(cert) + '\n')
1630 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1631 if 'subject' not in cert:
1632 self.fail("No subject field in certificate: %s." %
1633 pprint.pformat(cert))
1634 if ((('organizationName', 'Python Software Foundation'),)
1635 not in cert['subject']):
1636 self.fail(
1637 "Missing or invalid 'organizationName' field in certificate subject; "
1638 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001639 self.assertIn('notBefore', cert)
1640 self.assertIn('notAfter', cert)
1641 before = ssl.cert_time_to_seconds(cert['notBefore'])
1642 after = ssl.cert_time_to_seconds(cert['notAfter'])
1643 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001644 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001645
Antoine Pitrou480a1242010-04-28 21:37:09 +00001646 def test_empty_cert(self):
1647 """Connecting with an empty cert file"""
1648 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1649 "nullcert.pem"))
1650 def test_malformed_cert(self):
1651 """Connecting with a badly formatted certificate (syntax error)"""
1652 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1653 "badcert.pem"))
1654 def test_nonexisting_cert(self):
1655 """Connecting with a non-existing cert file"""
1656 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1657 "wrongcert.pem"))
1658 def test_malformed_key(self):
1659 """Connecting with a badly formatted key (syntax error)"""
1660 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1661 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001662
Antoine Pitrou480a1242010-04-28 21:37:09 +00001663 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001664 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00001665 in the client when attempting handshake.
1666 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001667 listener_ready = threading.Event()
1668 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001669
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001670 s = socket.socket()
1671 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001672
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001673 # `listener` runs in a thread. It sits in an accept() until
1674 # the main thread connects. Then it rudely closes the socket,
1675 # and sets Event `listener_gone` to let the main thread know
1676 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001677 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001678 s.listen(5)
1679 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001680 newsock, addr = s.accept()
1681 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001682 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001683 listener_gone.set()
1684
1685 def connector():
1686 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001687 with socket.socket() as c:
1688 c.connect((HOST, port))
1689 listener_gone.wait()
1690 try:
1691 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001692 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001693 pass
1694 else:
1695 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001696
1697 t = threading.Thread(target=listener)
1698 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001699 try:
1700 connector()
1701 finally:
1702 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001703
Antoine Pitrou23df4832010-08-04 17:14:06 +00001704 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001705 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1706 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001707 def test_protocol_sslv2(self):
1708 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001709 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001710 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001711 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1712 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1713 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1714 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1715 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1716 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001717 # SSLv23 client with specific SSL options
1718 if no_sslv2_implies_sslv3_hello():
1719 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1720 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1721 client_options=ssl.OP_NO_SSLv2)
1722 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1723 client_options=ssl.OP_NO_SSLv3)
1724 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1725 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001726
Antoine Pitrou23df4832010-08-04 17:14:06 +00001727 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001728 def test_protocol_sslv23(self):
1729 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001730 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001731 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001732 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1733 try:
1734 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02001735 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02001736 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1737 if support.verbose:
1738 sys.stdout.write(
1739 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1740 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001741 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1742 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1743 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001744
Antoine Pitrou480a1242010-04-28 21:37:09 +00001745 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1746 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1747 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001748
Antoine Pitrou480a1242010-04-28 21:37:09 +00001749 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1750 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1751 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001752
Antoine Pitroub5218772010-05-21 09:56:06 +00001753 # Server with specific SSL options
1754 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1755 server_options=ssl.OP_NO_SSLv3)
1756 # Will choose TLSv1
1757 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1758 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1759 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1760 server_options=ssl.OP_NO_TLSv1)
1761
1762
Antoine Pitrou23df4832010-08-04 17:14:06 +00001763 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001764 def test_protocol_sslv3(self):
1765 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001766 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001767 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001768 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1769 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1770 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001771 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1772 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001773 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1774 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001775 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001776 if no_sslv2_implies_sslv3_hello():
1777 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1778 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1779 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001780
Antoine Pitrou23df4832010-08-04 17:14:06 +00001781 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001782 def test_protocol_tlsv1(self):
1783 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001784 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001785 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001786 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1787 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1788 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001789 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1790 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001791 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001792 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1793 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001794
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001795 @skip_if_broken_ubuntu_ssl
1796 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
1797 "TLS version 1.1 not supported.")
1798 def test_protocol_tlsv1_1(self):
1799 """Connecting to a TLSv1.1 server with various client options.
1800 Testing against older TLS versions."""
1801 if support.verbose:
1802 sys.stdout.write("\n")
1803 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
1804 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1805 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
1806 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
1807 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
1808 client_options=ssl.OP_NO_TLSv1_1)
1809
1810 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
1811 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
1812 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
1813
1814
1815 @skip_if_broken_ubuntu_ssl
1816 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
1817 "TLS version 1.2 not supported.")
1818 def test_protocol_tlsv1_2(self):
1819 """Connecting to a TLSv1.2 server with various client options.
1820 Testing against older TLS versions."""
1821 if support.verbose:
1822 sys.stdout.write("\n")
1823 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
1824 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
1825 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
1826 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1827 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
1828 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
1829 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
1830 client_options=ssl.OP_NO_TLSv1_2)
1831
1832 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
1833 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
1834 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
1835 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
1836 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
1837
Antoine Pitrou480a1242010-04-28 21:37:09 +00001838 def test_starttls(self):
1839 """Switching from clear text to encrypted and back again."""
1840 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 +00001841
Trent Nelson78520002008-04-10 20:54:35 +00001842 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001843 ssl_version=ssl.PROTOCOL_TLSv1,
1844 starttls_server=True,
1845 chatty=True,
1846 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001847 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001848 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001849 s = socket.socket()
1850 s.setblocking(1)
1851 s.connect((HOST, server.port))
1852 if support.verbose:
1853 sys.stdout.write("\n")
1854 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001855 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001856 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001857 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001858 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001859 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001860 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001861 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001862 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001863 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001864 msg = outdata.strip().lower()
1865 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1866 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001867 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001868 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001869 " client: read %r from server, starting TLS...\n"
1870 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001871 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1872 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001873 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1874 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001875 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001876 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001877 " client: read %r from server, ending TLS...\n"
1878 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001879 s = conn.unwrap()
1880 wrapped = False
1881 else:
1882 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001883 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001884 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001885 if support.verbose:
1886 sys.stdout.write(" client: closing connection.\n")
1887 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001888 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001889 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001890 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001891 if wrapped:
1892 conn.close()
1893 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001894 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001895
Antoine Pitrou480a1242010-04-28 21:37:09 +00001896 def test_socketserver(self):
1897 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01001898 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001899 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001900 if support.verbose:
1901 sys.stdout.write('\n')
1902 with open(CERTFILE, 'rb') as f:
1903 d1 = f.read()
1904 d2 = ''
1905 # now fetch the same data from the HTTPS server
1906 url = 'https://%s:%d/%s' % (
1907 HOST, server.port, os.path.split(CERTFILE)[1])
1908 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001909 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001910 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001911 if dlen and (int(dlen) > 0):
1912 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001913 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001914 sys.stdout.write(
1915 " client: read %d bytes from remote server '%s'\n"
1916 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001917 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001918 f.close()
1919 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001920
Antoine Pitrou480a1242010-04-28 21:37:09 +00001921 def test_asyncore_server(self):
1922 """Check the example asyncore integration."""
1923 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001924
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001925 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001926 sys.stdout.write("\n")
1927
Antoine Pitrou480a1242010-04-28 21:37:09 +00001928 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001929 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001930 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001931 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001932 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001933 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001934 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001935 " client: sending %r...\n" % indata)
1936 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001937 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001938 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001939 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001940 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001941 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001942 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1943 % (outdata[:20], len(outdata),
1944 indata[:20].lower(), len(indata)))
1945 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001946 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001947 sys.stdout.write(" client: closing connection.\n")
1948 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001949 if support.verbose:
1950 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001951
Antoine Pitrou480a1242010-04-28 21:37:09 +00001952 def test_recv_send(self):
1953 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001954 if support.verbose:
1955 sys.stdout.write("\n")
1956
1957 server = ThreadedEchoServer(CERTFILE,
1958 certreqs=ssl.CERT_NONE,
1959 ssl_version=ssl.PROTOCOL_TLSv1,
1960 cacerts=CERTFILE,
1961 chatty=True,
1962 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001963 with server:
1964 s = ssl.wrap_socket(socket.socket(),
1965 server_side=False,
1966 certfile=CERTFILE,
1967 ca_certs=CERTFILE,
1968 cert_reqs=ssl.CERT_NONE,
1969 ssl_version=ssl.PROTOCOL_TLSv1)
1970 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001971 # helper methods for standardising recv* method signatures
1972 def _recv_into():
1973 b = bytearray(b"\0"*100)
1974 count = s.recv_into(b)
1975 return b[:count]
1976
1977 def _recvfrom_into():
1978 b = bytearray(b"\0"*100)
1979 count, addr = s.recvfrom_into(b)
1980 return b[:count]
1981
1982 # (name, method, whether to expect success, *args)
1983 send_methods = [
1984 ('send', s.send, True, []),
1985 ('sendto', s.sendto, False, ["some.address"]),
1986 ('sendall', s.sendall, True, []),
1987 ]
1988 recv_methods = [
1989 ('recv', s.recv, True, []),
1990 ('recvfrom', s.recvfrom, False, ["some.address"]),
1991 ('recv_into', _recv_into, True, []),
1992 ('recvfrom_into', _recvfrom_into, False, []),
1993 ]
1994 data_prefix = "PREFIX_"
1995
1996 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001997 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001998 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001999 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002000 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002001 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002002 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002003 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002004 "<<{outdata:r}>> ({nout:d}) received; "
2005 "expected <<{indata:r}>> ({nin:d})\n".format(
2006 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002007 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002008 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002009 )
2010 )
2011 except ValueError as e:
2012 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002013 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002014 "Failed to send with method <<{name:s}>>; "
2015 "expected to succeed.\n".format(name=meth_name)
2016 )
2017 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002018 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002019 "Method <<{name:s}>> failed with unexpected "
2020 "exception message: {exp:s}\n".format(
2021 name=meth_name, exp=e
2022 )
2023 )
2024
2025 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002026 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00002027 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00002028 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002029 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002030 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00002031 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002032 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00002033 "<<{outdata:r}>> ({nout:d}) received; "
2034 "expected <<{indata:r}>> ({nin:d})\n".format(
2035 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00002036 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00002037 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00002038 )
2039 )
2040 except ValueError as e:
2041 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00002042 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002043 "Failed to receive with method <<{name:s}>>; "
2044 "expected to succeed.\n".format(name=meth_name)
2045 )
2046 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00002047 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00002048 "Method <<{name:s}>> failed with unexpected "
2049 "exception message: {exp:s}\n".format(
2050 name=meth_name, exp=e
2051 )
2052 )
2053 # consume data
2054 s.read()
2055
Nick Coghlan513886a2011-08-28 00:00:27 +10002056 # Make sure sendmsg et al are disallowed to avoid
2057 # inadvertent disclosure of data and/or corruption
2058 # of the encrypted data stream
2059 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
2060 self.assertRaises(NotImplementedError, s.recvmsg, 100)
2061 self.assertRaises(NotImplementedError,
2062 s.recvmsg_into, bytearray(100))
2063
Antoine Pitrou480a1242010-04-28 21:37:09 +00002064 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00002065 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002066
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002067 def test_handshake_timeout(self):
2068 # Issue #5103: SSL handshake must respect the socket timeout
2069 server = socket.socket(socket.AF_INET)
2070 host = "127.0.0.1"
2071 port = support.bind_port(server)
2072 started = threading.Event()
2073 finish = False
2074
2075 def serve():
2076 server.listen(5)
2077 started.set()
2078 conns = []
2079 while not finish:
2080 r, w, e = select.select([server], [], [], 0.1)
2081 if server in r:
2082 # Let the socket hang around rather than having
2083 # it closed by garbage collection.
2084 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00002085 for sock in conns:
2086 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002087
2088 t = threading.Thread(target=serve)
2089 t.start()
2090 started.wait()
2091
2092 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00002093 try:
2094 c = socket.socket(socket.AF_INET)
2095 c.settimeout(0.2)
2096 c.connect((host, port))
2097 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002098 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002099 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00002100 finally:
2101 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002102 try:
2103 c = socket.socket(socket.AF_INET)
2104 c = ssl.wrap_socket(c)
2105 c.settimeout(0.2)
2106 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00002107 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00002108 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00002109 finally:
2110 c.close()
2111 finally:
2112 finish = True
2113 t.join()
2114 server.close()
2115
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002116 def test_server_accept(self):
2117 # Issue #16357: accept() on a SSLSocket created through
2118 # SSLContext.wrap_socket().
2119 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2120 context.verify_mode = ssl.CERT_REQUIRED
2121 context.load_verify_locations(CERTFILE)
2122 context.load_cert_chain(CERTFILE)
2123 server = socket.socket(socket.AF_INET)
2124 host = "127.0.0.1"
2125 port = support.bind_port(server)
2126 server = context.wrap_socket(server, server_side=True)
2127
2128 evt = threading.Event()
2129 remote = None
2130 peer = None
2131 def serve():
2132 nonlocal remote, peer
2133 server.listen(5)
2134 # Block on the accept and wait on the connection to close.
2135 evt.set()
2136 remote, peer = server.accept()
2137 remote.recv(1)
2138
2139 t = threading.Thread(target=serve)
2140 t.start()
2141 # Client wait until server setup and perform a connect.
2142 evt.wait()
2143 client = context.wrap_socket(socket.socket())
2144 client.connect((host, port))
2145 client_addr = client.getsockname()
2146 client.close()
2147 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002148 remote.close()
2149 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01002150 # Sanity checks.
2151 self.assertIsInstance(remote, ssl.SSLSocket)
2152 self.assertEqual(peer, client_addr)
2153
Antoine Pitrou242db722013-05-01 20:52:07 +02002154 def test_getpeercert_enotconn(self):
2155 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2156 with context.wrap_socket(socket.socket()) as sock:
2157 with self.assertRaises(OSError) as cm:
2158 sock.getpeercert()
2159 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2160
2161 def test_do_handshake_enotconn(self):
2162 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2163 with context.wrap_socket(socket.socket()) as sock:
2164 with self.assertRaises(OSError) as cm:
2165 sock.do_handshake()
2166 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
2167
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002168 def test_default_ciphers(self):
2169 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2170 try:
2171 # Force a set of weak ciphers on our client context
2172 context.set_ciphers("DES")
2173 except ssl.SSLError:
2174 self.skipTest("no DES cipher available")
2175 with ThreadedEchoServer(CERTFILE,
2176 ssl_version=ssl.PROTOCOL_SSLv23,
2177 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01002178 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02002179 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01002180 s.connect((HOST, server.port))
2181 self.assertIn("no shared cipher", str(server.conn_errors[0]))
2182
Antoine Pitroud6494802011-07-21 01:11:30 +02002183 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
2184 "'tls-unique' channel binding not available")
2185 def test_tls_unique_channel_binding(self):
2186 """Test tls-unique channel binding."""
2187 if support.verbose:
2188 sys.stdout.write("\n")
2189
2190 server = ThreadedEchoServer(CERTFILE,
2191 certreqs=ssl.CERT_NONE,
2192 ssl_version=ssl.PROTOCOL_TLSv1,
2193 cacerts=CERTFILE,
2194 chatty=True,
2195 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01002196 with server:
2197 s = ssl.wrap_socket(socket.socket(),
2198 server_side=False,
2199 certfile=CERTFILE,
2200 ca_certs=CERTFILE,
2201 cert_reqs=ssl.CERT_NONE,
2202 ssl_version=ssl.PROTOCOL_TLSv1)
2203 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02002204 # get the data
2205 cb_data = s.get_channel_binding("tls-unique")
2206 if support.verbose:
2207 sys.stdout.write(" got channel binding data: {0!r}\n"
2208 .format(cb_data))
2209
2210 # check if it is sane
2211 self.assertIsNotNone(cb_data)
2212 self.assertEqual(len(cb_data), 12) # True for TLSv1
2213
2214 # and compare with the peers version
2215 s.write(b"CB tls-unique\n")
2216 peer_data_repr = s.read().strip()
2217 self.assertEqual(peer_data_repr,
2218 repr(cb_data).encode("us-ascii"))
2219 s.close()
2220
2221 # now, again
2222 s = ssl.wrap_socket(socket.socket(),
2223 server_side=False,
2224 certfile=CERTFILE,
2225 ca_certs=CERTFILE,
2226 cert_reqs=ssl.CERT_NONE,
2227 ssl_version=ssl.PROTOCOL_TLSv1)
2228 s.connect((HOST, server.port))
2229 new_cb_data = s.get_channel_binding("tls-unique")
2230 if support.verbose:
2231 sys.stdout.write(" got another channel binding data: {0!r}\n"
2232 .format(new_cb_data))
2233 # is it really unique
2234 self.assertNotEqual(cb_data, new_cb_data)
2235 self.assertIsNotNone(cb_data)
2236 self.assertEqual(len(cb_data), 12) # True for TLSv1
2237 s.write(b"CB tls-unique\n")
2238 peer_data_repr = s.read().strip()
2239 self.assertEqual(peer_data_repr,
2240 repr(new_cb_data).encode("us-ascii"))
2241 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002242
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002243 def test_compression(self):
2244 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2245 context.load_cert_chain(CERTFILE)
2246 stats = server_params_test(context, context,
2247 chatty=True, connectionchatty=True)
2248 if support.verbose:
2249 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2250 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2251
2252 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2253 "ssl.OP_NO_COMPRESSION needed for this test")
2254 def test_compression_disabled(self):
2255 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2256 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002257 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002258 stats = server_params_test(context, context,
2259 chatty=True, connectionchatty=True)
2260 self.assertIs(stats['compression'], None)
2261
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002262 def test_dh_params(self):
2263 # Check we can get a connection with ephemeral Diffie-Hellman
2264 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2265 context.load_cert_chain(CERTFILE)
2266 context.load_dh_params(DHFILE)
2267 context.set_ciphers("kEDH")
2268 stats = server_params_test(context, context,
2269 chatty=True, connectionchatty=True)
2270 cipher = stats["cipher"][0]
2271 parts = cipher.split("-")
2272 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2273 self.fail("Non-DH cipher: " + cipher[0])
2274
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002275 def test_selected_npn_protocol(self):
2276 # selected_npn_protocol() is None unless NPN is used
2277 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2278 context.load_cert_chain(CERTFILE)
2279 stats = server_params_test(context, context,
2280 chatty=True, connectionchatty=True)
2281 self.assertIs(stats['client_npn_protocol'], None)
2282
2283 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2284 def test_npn_protocols(self):
2285 server_protocols = ['http/1.1', 'spdy/2']
2286 protocol_tests = [
2287 (['http/1.1', 'spdy/2'], 'http/1.1'),
2288 (['spdy/2', 'http/1.1'], 'http/1.1'),
2289 (['spdy/2', 'test'], 'spdy/2'),
2290 (['abc', 'def'], 'abc')
2291 ]
2292 for client_protocols, expected in protocol_tests:
2293 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2294 server_context.load_cert_chain(CERTFILE)
2295 server_context.set_npn_protocols(server_protocols)
2296 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2297 client_context.load_cert_chain(CERTFILE)
2298 client_context.set_npn_protocols(client_protocols)
2299 stats = server_params_test(client_context, server_context,
2300 chatty=True, connectionchatty=True)
2301
2302 msg = "failed trying %s (s) and %s (c).\n" \
2303 "was expecting %s, but got %%s from the %%s" \
2304 % (str(server_protocols), str(client_protocols),
2305 str(expected))
2306 client_result = stats['client_npn_protocol']
2307 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2308 server_result = stats['server_npn_protocols'][-1] \
2309 if len(stats['server_npn_protocols']) else 'nothing'
2310 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2311
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002312 def sni_contexts(self):
2313 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2314 server_context.load_cert_chain(SIGNED_CERTFILE)
2315 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2316 other_context.load_cert_chain(SIGNED_CERTFILE2)
2317 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2318 client_context.verify_mode = ssl.CERT_REQUIRED
2319 client_context.load_verify_locations(SIGNING_CA)
2320 return server_context, other_context, client_context
2321
2322 def check_common_name(self, stats, name):
2323 cert = stats['peercert']
2324 self.assertIn((('commonName', name),), cert['subject'])
2325
2326 @needs_sni
2327 def test_sni_callback(self):
2328 calls = []
2329 server_context, other_context, client_context = self.sni_contexts()
2330
2331 def servername_cb(ssl_sock, server_name, initial_context):
2332 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002333 if server_name is not None:
2334 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002335 server_context.set_servername_callback(servername_cb)
2336
2337 stats = server_params_test(client_context, server_context,
2338 chatty=True,
2339 sni_name='supermessage')
2340 # The hostname was fetched properly, and the certificate was
2341 # changed for the connection.
2342 self.assertEqual(calls, [("supermessage", server_context)])
2343 # CERTFILE4 was selected
2344 self.check_common_name(stats, 'fakehostname')
2345
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002346 calls = []
2347 # The callback is called with server_name=None
2348 stats = server_params_test(client_context, server_context,
2349 chatty=True,
2350 sni_name=None)
2351 self.assertEqual(calls, [(None, server_context)])
2352 self.check_common_name(stats, 'localhost')
2353
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002354 # Check disabling the callback
2355 calls = []
2356 server_context.set_servername_callback(None)
2357
2358 stats = server_params_test(client_context, server_context,
2359 chatty=True,
2360 sni_name='notfunny')
2361 # Certificate didn't change
2362 self.check_common_name(stats, 'localhost')
2363 self.assertEqual(calls, [])
2364
2365 @needs_sni
2366 def test_sni_callback_alert(self):
2367 # Returning a TLS alert is reflected to the connecting client
2368 server_context, other_context, client_context = self.sni_contexts()
2369
2370 def cb_returning_alert(ssl_sock, server_name, initial_context):
2371 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2372 server_context.set_servername_callback(cb_returning_alert)
2373
2374 with self.assertRaises(ssl.SSLError) as cm:
2375 stats = server_params_test(client_context, server_context,
2376 chatty=False,
2377 sni_name='supermessage')
2378 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2379
2380 @needs_sni
2381 def test_sni_callback_raising(self):
2382 # Raising fails the connection with a TLS handshake failure alert.
2383 server_context, other_context, client_context = self.sni_contexts()
2384
2385 def cb_raising(ssl_sock, server_name, initial_context):
2386 1/0
2387 server_context.set_servername_callback(cb_raising)
2388
2389 with self.assertRaises(ssl.SSLError) as cm, \
2390 support.captured_stderr() as stderr:
2391 stats = server_params_test(client_context, server_context,
2392 chatty=False,
2393 sni_name='supermessage')
2394 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2395 self.assertIn("ZeroDivisionError", stderr.getvalue())
2396
2397 @needs_sni
2398 def test_sni_callback_wrong_return_type(self):
2399 # Returning the wrong return type terminates the TLS connection
2400 # with an internal error alert.
2401 server_context, other_context, client_context = self.sni_contexts()
2402
2403 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2404 return "foo"
2405 server_context.set_servername_callback(cb_wrong_return_type)
2406
2407 with self.assertRaises(ssl.SSLError) as cm, \
2408 support.captured_stderr() as stderr:
2409 stats = server_params_test(client_context, server_context,
2410 chatty=False,
2411 sni_name='supermessage')
2412 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2413 self.assertIn("TypeError", stderr.getvalue())
2414
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002415 def test_read_write_after_close_raises_valuerror(self):
2416 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
2417 context.verify_mode = ssl.CERT_REQUIRED
2418 context.load_verify_locations(CERTFILE)
2419 context.load_cert_chain(CERTFILE)
2420 server = ThreadedEchoServer(context=context, chatty=False)
2421
2422 with server:
2423 s = context.wrap_socket(socket.socket())
2424 s.connect((HOST, server.port))
2425 s.close()
2426
2427 self.assertRaises(ValueError, s.read, 1024)
Antoine Pitrou28940732013-07-20 19:36:15 +02002428 self.assertRaises(ValueError, s.write, b'hello')
Antoine Pitrou60a26e02013-07-20 19:35:16 +02002429
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002430
Thomas Woutersed03b412007-08-28 21:37:11 +00002431def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002432 if support.verbose:
2433 plats = {
2434 'Linux': platform.linux_distribution,
2435 'Mac': platform.mac_ver,
2436 'Windows': platform.win32_ver,
2437 }
2438 for name, func in plats.items():
2439 plat = func()
2440 if plat and plat[0]:
2441 plat = '%s %r' % (name, plat)
2442 break
2443 else:
2444 plat = repr(platform.platform())
2445 print("test_ssl: testing with %r %r" %
2446 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2447 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002448 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002449 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2450 try:
2451 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2452 except AttributeError:
2453 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002454
Antoine Pitrou152efa22010-05-16 18:19:27 +00002455 for filename in [
2456 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2457 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002458 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002459 BADCERT, BADKEY, EMPTYCERT]:
2460 if not os.path.exists(filename):
2461 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002462
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002463 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002464
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002465 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002466 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002467
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002468 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002469 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002470 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002471 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002472
Antoine Pitrou480a1242010-04-28 21:37:09 +00002473 try:
2474 support.run_unittest(*tests)
2475 finally:
2476 if _have_threads:
2477 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002478
2479if __name__ == "__main__":
2480 test_main()