blob: d4c90cff8573cf83eef1b3ca50c37e31be51859d [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
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Antoine Pitrou152efa22010-05-16 18:19:27 +000013import tempfile
Antoine Pitrou803e6d62010-10-13 10:36:15 +000014import urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000015import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000016import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000017import weakref
Antoine Pitrou15cee622010-08-04 16:45:21 +000018import platform
Antoine Pitrou23df4832010-08-04 17:14:06 +000019import functools
Antoine Pitrou242db722013-05-01 20:52:07 +020020from unittest import mock
Thomas Woutersed03b412007-08-28 21:37:11 +000021
Antoine Pitrou05d936d2010-10-13 11:38:36 +000022ssl = support.import_module("ssl")
23
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010024PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000025HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000026
27data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000028
Antoine Pitrou81564092010-10-08 23:06:24 +000029# The custom key and certificate files used in test_ssl are generated
30# using Lib/test/make_ssl_certs.py.
31# Other certificates are simply fetched from the Internet servers they
32# are meant to authenticate.
33
Antoine Pitrou152efa22010-05-16 18:19:27 +000034CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000035BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000036ONLYCERT = data_file("ssl_cert.pem")
37ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000038BYTES_ONLYCERT = os.fsencode(ONLYCERT)
39BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020040CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
41ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
42KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000043CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000044BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010046# Two keys and certs signed by the same CA (for SNI tests)
47SIGNED_CERTFILE = data_file("keycert3.pem")
48SIGNED_CERTFILE2 = data_file("keycert4.pem")
49SIGNING_CA = data_file("pycacert.pem")
50
Antoine Pitrou152efa22010-05-16 18:19:27 +000051SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
52
53EMPTYCERT = data_file("nullcert.pem")
54BADCERT = data_file("badcert.pem")
55WRONGCERT = data_file("XXXnonexisting.pem")
56BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020057NOKIACERT = data_file("nokia.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000058
Antoine Pitrou0e576f12011-12-22 10:03:38 +010059DHFILE = data_file("dh512.pem")
60BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000061
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010062
Thomas Woutersed03b412007-08-28 21:37:11 +000063def handle_error(prefix):
64 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000065 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000066 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000067
Antoine Pitroub5218772010-05-21 09:56:06 +000068def can_clear_options():
69 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020070 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000071
72def no_sslv2_implies_sslv3_hello():
73 # 0.9.7h or higher
74 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
75
Thomas Woutersed03b412007-08-28 21:37:11 +000076
Antoine Pitrou23df4832010-08-04 17:14:06 +000077# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
78def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020079 if hasattr(ssl, 'PROTOCOL_SSLv2'):
80 @functools.wraps(func)
81 def f(*args, **kwargs):
82 try:
83 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
84 except ssl.SSLError:
85 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
86 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
87 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
88 return func(*args, **kwargs)
89 return f
90 else:
91 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000092
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010093needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
94
Antoine Pitrou23df4832010-08-04 17:14:06 +000095
Antoine Pitrou152efa22010-05-16 18:19:27 +000096class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000097
Antoine Pitrou480a1242010-04-28 21:37:09 +000098 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000099 ssl.CERT_NONE
100 ssl.CERT_OPTIONAL
101 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100102 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100103 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100104 if ssl.HAS_ECDH:
105 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100106 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
107 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000108 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100109 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000110
Antoine Pitrou480a1242010-04-28 21:37:09 +0000111 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000112 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000113 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 sys.stdout.write("\n RAND_status is %d (%s)\n"
115 % (v, (v and "sufficient randomness") or
116 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200117
118 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
119 self.assertEqual(len(data), 16)
120 self.assertEqual(is_cryptographic, v == 1)
121 if v:
122 data = ssl.RAND_bytes(16)
123 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200124 else:
125 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200126
Jesus Ceac8754a12012-09-11 02:00:58 +0200127 self.assertRaises(TypeError, ssl.RAND_egd, 1)
128 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000130
Antoine Pitrou480a1242010-04-28 21:37:09 +0000131 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000132 # note that this uses an 'unofficial' function in _ssl.c,
133 # provided solely for this test, to exercise the certificate
134 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000135 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000136 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000137 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200138 self.assertEqual(p['issuer'],
139 ((('countryName', 'XY'),),
140 (('localityName', 'Castle Anthrax'),),
141 (('organizationName', 'Python Software Foundation'),),
142 (('commonName', 'localhost'),))
143 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100144 # Note the next three asserts will fail if the keys are regenerated
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200145 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
146 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
147 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
148 self.assertEqual(p['subject'],
149 ((('countryName', 'XY'),),
150 (('localityName', 'Castle Anthrax'),),
151 (('organizationName', 'Python Software Foundation'),),
152 (('commonName', 'localhost'),))
153 )
154 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
155 # Issue #13034: the subjectAltName in some certificates
156 # (notably projects.developer.nokia.com:443) wasn't parsed
157 p = ssl._ssl._test_decode_cert(NOKIACERT)
158 if support.verbose:
159 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
160 self.assertEqual(p['subjectAltName'],
161 (('DNS', 'projects.developer.nokia.com'),
162 ('DNS', 'projects.forum.nokia.com'))
163 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000164
Antoine Pitrou480a1242010-04-28 21:37:09 +0000165 def test_DER_to_PEM(self):
166 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
167 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000168 d1 = ssl.PEM_cert_to_DER_cert(pem)
169 p2 = ssl.DER_cert_to_PEM_cert(d1)
170 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000171 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000172 if not p2.startswith(ssl.PEM_HEADER + '\n'):
173 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
174 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
175 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000176
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000177 def test_openssl_version(self):
178 n = ssl.OPENSSL_VERSION_NUMBER
179 t = ssl.OPENSSL_VERSION_INFO
180 s = ssl.OPENSSL_VERSION
181 self.assertIsInstance(n, int)
182 self.assertIsInstance(t, tuple)
183 self.assertIsInstance(s, str)
184 # Some sanity checks follow
185 # >= 0.9
186 self.assertGreaterEqual(n, 0x900000)
187 # < 2.0
188 self.assertLess(n, 0x20000000)
189 major, minor, fix, patch, status = t
190 self.assertGreaterEqual(major, 0)
191 self.assertLess(major, 2)
192 self.assertGreaterEqual(minor, 0)
193 self.assertLess(minor, 256)
194 self.assertGreaterEqual(fix, 0)
195 self.assertLess(fix, 256)
196 self.assertGreaterEqual(patch, 0)
197 self.assertLessEqual(patch, 26)
198 self.assertGreaterEqual(status, 0)
199 self.assertLessEqual(status, 15)
200 # Version string as returned by OpenSSL, the format might change
201 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
202 (s, t))
203
Antoine Pitrou9d543662010-04-23 23:10:32 +0000204 @support.cpython_only
205 def test_refcycle(self):
206 # Issue #7943: an SSL object doesn't create reference cycles with
207 # itself.
208 s = socket.socket(socket.AF_INET)
209 ss = ssl.wrap_socket(s)
210 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100211 with support.check_warnings(("", ResourceWarning)):
212 del ss
213 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000214
Antoine Pitroua468adc2010-09-14 14:43:44 +0000215 def test_wrapped_unconnected(self):
216 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200217 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000218 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100219 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100220 self.assertRaises(OSError, ss.recv, 1)
221 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
222 self.assertRaises(OSError, ss.recvfrom, 1)
223 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
224 self.assertRaises(OSError, ss.send, b'x')
225 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000226
Antoine Pitrou40f08742010-04-24 22:04:40 +0000227 def test_timeout(self):
228 # Issue #8524: when creating an SSL socket, the timeout of the
229 # original socket should be retained.
230 for timeout in (None, 0.0, 5.0):
231 s = socket.socket(socket.AF_INET)
232 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100233 with ssl.wrap_socket(s) as ss:
234 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000235
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000236 def test_errors(self):
237 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000238 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000239 "certfile must be specified",
240 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000241 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000242 "certfile must be specified for server-side operations",
243 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000244 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000245 "certfile must be specified for server-side operations",
246 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100247 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
248 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
249 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200250 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000251 with socket.socket() as sock:
252 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000253 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200254 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000255 with socket.socket() as sock:
256 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000257 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200258 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000259 with socket.socket() as sock:
260 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000261 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000262
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000263 def test_match_hostname(self):
264 def ok(cert, hostname):
265 ssl.match_hostname(cert, hostname)
266 def fail(cert, hostname):
267 self.assertRaises(ssl.CertificateError,
268 ssl.match_hostname, cert, hostname)
269
270 cert = {'subject': ((('commonName', 'example.com'),),)}
271 ok(cert, 'example.com')
272 ok(cert, 'ExAmple.cOm')
273 fail(cert, 'www.example.com')
274 fail(cert, '.example.com')
275 fail(cert, 'example.org')
276 fail(cert, 'exampleXcom')
277
278 cert = {'subject': ((('commonName', '*.a.com'),),)}
279 ok(cert, 'foo.a.com')
280 fail(cert, 'bar.foo.a.com')
281 fail(cert, 'a.com')
282 fail(cert, 'Xa.com')
283 fail(cert, '.a.com')
284
285 cert = {'subject': ((('commonName', 'a.*.com'),),)}
286 ok(cert, 'a.foo.com')
287 fail(cert, 'a..com')
288 fail(cert, 'a.com')
289
290 cert = {'subject': ((('commonName', 'f*.com'),),)}
291 ok(cert, 'foo.com')
292 ok(cert, 'f.com')
293 fail(cert, 'bar.com')
294 fail(cert, 'foo.a.com')
295 fail(cert, 'bar.foo.com')
296
297 # Slightly fake real-world example
298 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
299 'subject': ((('commonName', 'linuxfrz.org'),),),
300 'subjectAltName': (('DNS', 'linuxfr.org'),
301 ('DNS', 'linuxfr.com'),
302 ('othername', '<unsupported>'))}
303 ok(cert, 'linuxfr.org')
304 ok(cert, 'linuxfr.com')
305 # Not a "DNS" entry
306 fail(cert, '<unsupported>')
307 # When there is a subjectAltName, commonName isn't used
308 fail(cert, 'linuxfrz.org')
309
310 # A pristine real-world example
311 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
312 'subject': ((('countryName', 'US'),),
313 (('stateOrProvinceName', 'California'),),
314 (('localityName', 'Mountain View'),),
315 (('organizationName', 'Google Inc'),),
316 (('commonName', 'mail.google.com'),))}
317 ok(cert, 'mail.google.com')
318 fail(cert, 'gmail.com')
319 # Only commonName is considered
320 fail(cert, 'California')
321
322 # Neither commonName nor subjectAltName
323 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
324 'subject': ((('countryName', 'US'),),
325 (('stateOrProvinceName', 'California'),),
326 (('localityName', 'Mountain View'),),
327 (('organizationName', 'Google Inc'),))}
328 fail(cert, 'mail.google.com')
329
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200330 # No DNS entry in subjectAltName but a commonName
331 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
332 'subject': ((('countryName', 'US'),),
333 (('stateOrProvinceName', 'California'),),
334 (('localityName', 'Mountain View'),),
335 (('commonName', 'mail.google.com'),)),
336 'subjectAltName': (('othername', 'blabla'), )}
337 ok(cert, 'mail.google.com')
338
339 # No DNS entry subjectAltName and no commonName
340 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
341 'subject': ((('countryName', 'US'),),
342 (('stateOrProvinceName', 'California'),),
343 (('localityName', 'Mountain View'),),
344 (('organizationName', 'Google Inc'),)),
345 'subjectAltName': (('othername', 'blabla'),)}
346 fail(cert, 'google.com')
347
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000348 # Empty cert / no cert
349 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
350 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
351
Antoine Pitroud5323212010-10-22 18:19:07 +0000352 def test_server_side(self):
353 # server_hostname doesn't work for server sockets
354 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000355 with socket.socket() as sock:
356 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
357 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000358
Antoine Pitroud6494802011-07-21 01:11:30 +0200359 def test_unknown_channel_binding(self):
360 # should raise ValueError for unknown type
361 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100362 with ssl.wrap_socket(s) as ss:
363 with self.assertRaises(ValueError):
364 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200365
366 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
367 "'tls-unique' channel binding not available")
368 def test_tls_unique_channel_binding(self):
369 # unconnected should return None for known type
370 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100371 with ssl.wrap_socket(s) as ss:
372 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200373 # the same for server-side
374 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100375 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
376 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200377
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600378 def test_dealloc_warn(self):
379 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
380 r = repr(ss)
381 with self.assertWarns(ResourceWarning) as cm:
382 ss = None
383 support.gc_collect()
384 self.assertIn(r, str(cm.warning.args[0]))
385
Antoine Pitrou152efa22010-05-16 18:19:27 +0000386class ContextTests(unittest.TestCase):
387
Antoine Pitrou23df4832010-08-04 17:14:06 +0000388 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000389 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100390 for protocol in PROTOCOLS:
391 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000392 self.assertRaises(TypeError, ssl.SSLContext)
393 self.assertRaises(ValueError, ssl.SSLContext, -1)
394 self.assertRaises(ValueError, ssl.SSLContext, 42)
395
Antoine Pitrou23df4832010-08-04 17:14:06 +0000396 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000397 def test_protocol(self):
398 for proto in PROTOCOLS:
399 ctx = ssl.SSLContext(proto)
400 self.assertEqual(ctx.protocol, proto)
401
402 def test_ciphers(self):
403 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
404 ctx.set_ciphers("ALL")
405 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000406 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000407 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000408
Antoine Pitrou23df4832010-08-04 17:14:06 +0000409 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000410 def test_options(self):
411 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
412 # OP_ALL is the default value
413 self.assertEqual(ssl.OP_ALL, ctx.options)
414 ctx.options |= ssl.OP_NO_SSLv2
415 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
416 ctx.options)
417 ctx.options |= ssl.OP_NO_SSLv3
418 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
419 ctx.options)
420 if can_clear_options():
421 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
422 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
423 ctx.options)
424 ctx.options = 0
425 self.assertEqual(0, ctx.options)
426 else:
427 with self.assertRaises(ValueError):
428 ctx.options = 0
429
Antoine Pitrou152efa22010-05-16 18:19:27 +0000430 def test_verify(self):
431 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
432 # Default value
433 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
434 ctx.verify_mode = ssl.CERT_OPTIONAL
435 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
436 ctx.verify_mode = ssl.CERT_REQUIRED
437 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
438 ctx.verify_mode = ssl.CERT_NONE
439 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
440 with self.assertRaises(TypeError):
441 ctx.verify_mode = None
442 with self.assertRaises(ValueError):
443 ctx.verify_mode = 42
444
445 def test_load_cert_chain(self):
446 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
447 # Combined key and cert in a single file
448 ctx.load_cert_chain(CERTFILE)
449 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
450 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200451 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000452 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000453 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000454 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000455 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000456 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000457 ctx.load_cert_chain(EMPTYCERT)
458 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000459 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000460 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
461 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
462 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000463 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000464 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000465 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000466 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000467 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000468 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
469 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000470 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000471 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000472 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200473 # Password protected key and cert
474 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
475 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
476 ctx.load_cert_chain(CERTFILE_PROTECTED,
477 password=bytearray(KEY_PASSWORD.encode()))
478 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
479 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
480 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
481 bytearray(KEY_PASSWORD.encode()))
482 with self.assertRaisesRegex(TypeError, "should be a string"):
483 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
484 with self.assertRaises(ssl.SSLError):
485 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
486 with self.assertRaisesRegex(ValueError, "cannot be longer"):
487 # openssl has a fixed limit on the password buffer.
488 # PEM_BUFSIZE is generally set to 1kb.
489 # Return a string larger than this.
490 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
491 # Password callback
492 def getpass_unicode():
493 return KEY_PASSWORD
494 def getpass_bytes():
495 return KEY_PASSWORD.encode()
496 def getpass_bytearray():
497 return bytearray(KEY_PASSWORD.encode())
498 def getpass_badpass():
499 return "badpass"
500 def getpass_huge():
501 return b'a' * (1024 * 1024)
502 def getpass_bad_type():
503 return 9
504 def getpass_exception():
505 raise Exception('getpass error')
506 class GetPassCallable:
507 def __call__(self):
508 return KEY_PASSWORD
509 def getpass(self):
510 return KEY_PASSWORD
511 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
512 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
513 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
514 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
515 ctx.load_cert_chain(CERTFILE_PROTECTED,
516 password=GetPassCallable().getpass)
517 with self.assertRaises(ssl.SSLError):
518 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
519 with self.assertRaisesRegex(ValueError, "cannot be longer"):
520 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
521 with self.assertRaisesRegex(TypeError, "must return a string"):
522 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
523 with self.assertRaisesRegex(Exception, "getpass error"):
524 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
525 # Make sure the password function isn't called if it isn't needed
526 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000527
528 def test_load_verify_locations(self):
529 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
530 ctx.load_verify_locations(CERTFILE)
531 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
532 ctx.load_verify_locations(BYTES_CERTFILE)
533 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
534 self.assertRaises(TypeError, ctx.load_verify_locations)
535 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200536 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000537 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000538 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000539 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000540 ctx.load_verify_locations(BADCERT)
541 ctx.load_verify_locations(CERTFILE, CAPATH)
542 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
543
Victor Stinner80f75e62011-01-29 11:31:20 +0000544 # Issue #10989: crash if the second argument type is invalid
545 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
546
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100547 def test_load_dh_params(self):
548 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
549 ctx.load_dh_params(DHFILE)
550 if os.name != 'nt':
551 ctx.load_dh_params(BYTES_DHFILE)
552 self.assertRaises(TypeError, ctx.load_dh_params)
553 self.assertRaises(TypeError, ctx.load_dh_params, None)
554 with self.assertRaises(FileNotFoundError) as cm:
555 ctx.load_dh_params(WRONGCERT)
556 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200557 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100558 ctx.load_dh_params(CERTFILE)
559
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000560 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000561 def test_session_stats(self):
562 for proto in PROTOCOLS:
563 ctx = ssl.SSLContext(proto)
564 self.assertEqual(ctx.session_stats(), {
565 'number': 0,
566 'connect': 0,
567 'connect_good': 0,
568 'connect_renegotiate': 0,
569 'accept': 0,
570 'accept_good': 0,
571 'accept_renegotiate': 0,
572 'hits': 0,
573 'misses': 0,
574 'timeouts': 0,
575 'cache_full': 0,
576 })
577
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000578 def test_set_default_verify_paths(self):
579 # There's not much we can do to test that it acts as expected,
580 # so just check it doesn't crash or raise an exception.
581 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
582 ctx.set_default_verify_paths()
583
Antoine Pitrou501da612011-12-21 09:27:41 +0100584 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100585 def test_set_ecdh_curve(self):
586 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
587 ctx.set_ecdh_curve("prime256v1")
588 ctx.set_ecdh_curve(b"prime256v1")
589 self.assertRaises(TypeError, ctx.set_ecdh_curve)
590 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
591 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
592 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
593
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100594 @needs_sni
595 def test_sni_callback(self):
596 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
597
598 # set_servername_callback expects a callable, or None
599 self.assertRaises(TypeError, ctx.set_servername_callback)
600 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
601 self.assertRaises(TypeError, ctx.set_servername_callback, "")
602 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
603
604 def dummycallback(sock, servername, ctx):
605 pass
606 ctx.set_servername_callback(None)
607 ctx.set_servername_callback(dummycallback)
608
609 @needs_sni
610 def test_sni_callback_refcycle(self):
611 # Reference cycles through the servername callback are detected
612 # and cleared.
613 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
614 def dummycallback(sock, servername, ctx, cycle=ctx):
615 pass
616 ctx.set_servername_callback(dummycallback)
617 wr = weakref.ref(ctx)
618 del ctx, dummycallback
619 gc.collect()
620 self.assertIs(wr(), None)
621
Antoine Pitrou152efa22010-05-16 18:19:27 +0000622
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200623class SSLErrorTests(unittest.TestCase):
624
625 def test_str(self):
626 # The str() of a SSLError doesn't include the errno
627 e = ssl.SSLError(1, "foo")
628 self.assertEqual(str(e), "foo")
629 self.assertEqual(e.errno, 1)
630 # Same for a subclass
631 e = ssl.SSLZeroReturnError(1, "foo")
632 self.assertEqual(str(e), "foo")
633 self.assertEqual(e.errno, 1)
634
635 def test_lib_reason(self):
636 # Test the library and reason attributes
637 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
638 with self.assertRaises(ssl.SSLError) as cm:
639 ctx.load_dh_params(CERTFILE)
640 self.assertEqual(cm.exception.library, 'PEM')
641 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
642 s = str(cm.exception)
643 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
644
645 def test_subclass(self):
646 # Check that the appropriate SSLError subclass is raised
647 # (this only tests one of them)
648 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
649 with socket.socket() as s:
650 s.bind(("127.0.0.1", 0))
651 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100652 c = socket.socket()
653 c.connect(s.getsockname())
654 c.setblocking(False)
655 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200656 with self.assertRaises(ssl.SSLWantReadError) as cm:
657 c.do_handshake()
658 s = str(cm.exception)
659 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
660 # For compatibility
661 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
662
663
Bill Janssen6e027db2007-11-15 22:23:56 +0000664class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665
Antoine Pitrou480a1242010-04-28 21:37:09 +0000666 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000667 with support.transient_internet("svn.python.org"):
668 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
669 cert_reqs=ssl.CERT_NONE)
670 try:
671 s.connect(("svn.python.org", 443))
672 self.assertEqual({}, s.getpeercert())
673 finally:
674 s.close()
675
676 # this should fail because we have no verification certs
677 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
678 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000679 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
680 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000681 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000682
Antoine Pitrou350c7222010-09-09 13:31:46 +0000683 # this should succeed because we specify the root cert
684 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
685 cert_reqs=ssl.CERT_REQUIRED,
686 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
687 try:
688 s.connect(("svn.python.org", 443))
689 self.assertTrue(s.getpeercert())
690 finally:
691 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000692
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000693 def test_connect_ex(self):
694 # Issue #11326: check connect_ex() implementation
695 with support.transient_internet("svn.python.org"):
696 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
697 cert_reqs=ssl.CERT_REQUIRED,
698 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
699 try:
700 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
701 self.assertTrue(s.getpeercert())
702 finally:
703 s.close()
704
705 def test_non_blocking_connect_ex(self):
706 # Issue #11326: non-blocking connect_ex() should allow handshake
707 # to proceed after the socket gets ready.
708 with support.transient_internet("svn.python.org"):
709 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
710 cert_reqs=ssl.CERT_REQUIRED,
711 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
712 do_handshake_on_connect=False)
713 try:
714 s.setblocking(False)
715 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000716 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
717 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000718 # Wait for connect to finish
719 select.select([], [s], [], 5.0)
720 # Non-blocking handshake
721 while True:
722 try:
723 s.do_handshake()
724 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200725 except ssl.SSLWantReadError:
726 select.select([s], [], [], 5.0)
727 except ssl.SSLWantWriteError:
728 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000729 # SSL established
730 self.assertTrue(s.getpeercert())
731 finally:
732 s.close()
733
Antoine Pitroub4410db2011-05-18 18:51:06 +0200734 def test_timeout_connect_ex(self):
735 # Issue #12065: on a timeout, connect_ex() should return the original
736 # errno (mimicking the behaviour of non-SSL sockets).
737 with support.transient_internet("svn.python.org"):
738 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
739 cert_reqs=ssl.CERT_REQUIRED,
740 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
741 do_handshake_on_connect=False)
742 try:
743 s.settimeout(0.0000001)
744 rc = s.connect_ex(('svn.python.org', 443))
745 if rc == 0:
746 self.skipTest("svn.python.org responded too quickly")
747 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
748 finally:
749 s.close()
750
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100751 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100752 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100753 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
754 cert_reqs=ssl.CERT_REQUIRED,
755 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
756 try:
757 self.assertEqual(errno.ECONNREFUSED,
758 s.connect_ex(("svn.python.org", 444)))
759 finally:
760 s.close()
761
Antoine Pitrou152efa22010-05-16 18:19:27 +0000762 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000763 with support.transient_internet("svn.python.org"):
764 # Same as test_connect, but with a separately created context
765 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
766 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
767 s.connect(("svn.python.org", 443))
768 try:
769 self.assertEqual({}, s.getpeercert())
770 finally:
771 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000772 # Same with a server hostname
773 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
774 server_hostname="svn.python.org")
775 if ssl.HAS_SNI:
776 s.connect(("svn.python.org", 443))
777 s.close()
778 else:
779 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000780 # This should fail because we have no verification certs
781 ctx.verify_mode = ssl.CERT_REQUIRED
782 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000783 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000784 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000785 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000786 # This should succeed because we specify the root cert
787 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
788 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
789 s.connect(("svn.python.org", 443))
790 try:
791 cert = s.getpeercert()
792 self.assertTrue(cert)
793 finally:
794 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000795
796 def test_connect_capath(self):
797 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000798 # NOTE: the subject hashing algorithm has been changed between
799 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
800 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000801 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000802 with support.transient_internet("svn.python.org"):
803 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
804 ctx.verify_mode = ssl.CERT_REQUIRED
805 ctx.load_verify_locations(capath=CAPATH)
806 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
807 s.connect(("svn.python.org", 443))
808 try:
809 cert = s.getpeercert()
810 self.assertTrue(cert)
811 finally:
812 s.close()
813 # Same with a bytes `capath` argument
814 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
815 ctx.verify_mode = ssl.CERT_REQUIRED
816 ctx.load_verify_locations(capath=BYTES_CAPATH)
817 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
818 s.connect(("svn.python.org", 443))
819 try:
820 cert = s.getpeercert()
821 self.assertTrue(cert)
822 finally:
823 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000824
Antoine Pitroue3220242010-04-24 11:13:53 +0000825 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
826 def test_makefile_close(self):
827 # Issue #5238: creating a file-like object with makefile() shouldn't
828 # delay closing the underlying "real socket" (here tested with its
829 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000830 with support.transient_internet("svn.python.org"):
831 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
832 ss.connect(("svn.python.org", 443))
833 fd = ss.fileno()
834 f = ss.makefile()
835 f.close()
836 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000837 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000838 # Closing the SSL socket should close the fd too
839 ss.close()
840 gc.collect()
841 with self.assertRaises(OSError) as e:
842 os.read(fd, 0)
843 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000844
Antoine Pitrou480a1242010-04-28 21:37:09 +0000845 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000846 with support.transient_internet("svn.python.org"):
847 s = socket.socket(socket.AF_INET)
848 s.connect(("svn.python.org", 443))
849 s.setblocking(False)
850 s = ssl.wrap_socket(s,
851 cert_reqs=ssl.CERT_NONE,
852 do_handshake_on_connect=False)
853 count = 0
854 while True:
855 try:
856 count += 1
857 s.do_handshake()
858 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200859 except ssl.SSLWantReadError:
860 select.select([s], [], [])
861 except ssl.SSLWantWriteError:
862 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000863 s.close()
864 if support.verbose:
865 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000866
Antoine Pitrou480a1242010-04-28 21:37:09 +0000867 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200868 def _test_get_server_certificate(host, port, cert=None):
869 with support.transient_internet(host):
870 pem = ssl.get_server_certificate((host, port))
871 if not pem:
872 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200873
Antoine Pitrou15399c32011-04-28 19:23:55 +0200874 try:
875 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
876 except ssl.SSLError as x:
877 #should fail
878 if support.verbose:
879 sys.stdout.write("%s\n" % x)
880 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200881 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
882
Antoine Pitrou15399c32011-04-28 19:23:55 +0200883 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
884 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200885 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000886 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200887 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000888
Antoine Pitrou15399c32011-04-28 19:23:55 +0200889 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
890 if support.IPV6_ENABLED:
891 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000892
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000893 def test_ciphers(self):
894 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000895 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100896 with ssl.wrap_socket(socket.socket(socket.AF_INET),
897 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
898 s.connect(remote)
899 with ssl.wrap_socket(socket.socket(socket.AF_INET),
900 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
901 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000902 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000903 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000904 with socket.socket(socket.AF_INET) as sock:
905 s = ssl.wrap_socket(sock,
906 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
907 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000908
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000909 def test_algorithms(self):
910 # Issue #8484: all algorithms should be available when verifying a
911 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000912 # SHA256 was added in OpenSSL 0.9.8
913 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
914 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200915 # sha256.tbs-internet.com needs SNI to use the correct certificate
916 if not ssl.HAS_SNI:
917 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000918 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
919 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000920 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000921 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200922 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
923 ctx.verify_mode = ssl.CERT_REQUIRED
924 ctx.load_verify_locations(sha256_cert)
925 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
926 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000927 try:
928 s.connect(remote)
929 if support.verbose:
930 sys.stdout.write("\nCipher with %r is %r\n" %
931 (remote, s.cipher()))
932 sys.stdout.write("Certificate is:\n%s\n" %
933 pprint.pformat(s.getpeercert()))
934 finally:
935 s.close()
936
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000937
938try:
939 import threading
940except ImportError:
941 _have_threads = False
942else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000943 _have_threads = True
944
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000945 from test.ssl_servers import make_https_server
946
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000947 class ThreadedEchoServer(threading.Thread):
948
949 class ConnectionHandler(threading.Thread):
950
951 """A mildly complicated class, because we want it to work both
952 with and without the SSL wrapper around the socket connection, so
953 that we can test the STARTTLS functionality."""
954
Bill Janssen6e027db2007-11-15 22:23:56 +0000955 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000956 self.server = server
957 self.running = False
958 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000959 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000960 self.sock.setblocking(1)
961 self.sslconn = None
962 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000963 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000964
Antoine Pitrou480a1242010-04-28 21:37:09 +0000965 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000966 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000967 self.sslconn = self.server.context.wrap_socket(
968 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100969 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +0100970 except (ssl.SSLError, ConnectionResetError) as e:
971 # We treat ConnectionResetError as though it were an
972 # SSLError - OpenSSL on Ubuntu abruptly closes the
973 # connection when asked to use an unsupported protocol.
974 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000975 # XXX Various errors can have happened here, for example
976 # a mismatching protocol version, an invalid certificate,
977 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100978 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000979 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000980 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000981 self.running = False
982 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000983 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000985 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000986 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000987 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000988 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000989 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
990 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000991 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000992 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
993 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000994 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000995 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100996 sys.stdout.write(" server: selected protocol is now "
997 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 return True
999
1000 def read(self):
1001 if self.sslconn:
1002 return self.sslconn.read()
1003 else:
1004 return self.sock.recv(1024)
1005
1006 def write(self, bytes):
1007 if self.sslconn:
1008 return self.sslconn.write(bytes)
1009 else:
1010 return self.sock.send(bytes)
1011
1012 def close(self):
1013 if self.sslconn:
1014 self.sslconn.close()
1015 else:
1016 self.sock.close()
1017
Antoine Pitrou480a1242010-04-28 21:37:09 +00001018 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001019 self.running = True
1020 if not self.server.starttls_server:
1021 if not self.wrap_conn():
1022 return
1023 while self.running:
1024 try:
1025 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001026 stripped = msg.strip()
1027 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001028 # eof, so quit this handler
1029 self.running = False
1030 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001031 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001032 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001033 sys.stdout.write(" server: client closed connection\n")
1034 self.close()
1035 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001036 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001037 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001038 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001039 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001040 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001041 if not self.wrap_conn():
1042 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001043 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001044 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001045 if support.verbose and self.server.connectionchatty:
1046 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001047 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001048 self.sock = self.sslconn.unwrap()
1049 self.sslconn = None
1050 if support.verbose and self.server.connectionchatty:
1051 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001052 elif stripped == b'CB tls-unique':
1053 if support.verbose and self.server.connectionchatty:
1054 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1055 data = self.sslconn.get_channel_binding("tls-unique")
1056 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001057 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001058 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001059 self.server.connectionchatty):
1060 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001061 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1062 % (msg, ctype, msg.lower(), ctype))
1063 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001064 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001065 if self.server.chatty:
1066 handle_error("Test server failure:\n")
1067 self.close()
1068 self.running = False
1069 # normally, we'd just stop here, but for the test
1070 # harness, we want to stop the server
1071 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001072
Antoine Pitroub5218772010-05-21 09:56:06 +00001073 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001074 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001075 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001076 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001077 if context:
1078 self.context = context
1079 else:
1080 self.context = ssl.SSLContext(ssl_version
1081 if ssl_version is not None
1082 else ssl.PROTOCOL_TLSv1)
1083 self.context.verify_mode = (certreqs if certreqs is not None
1084 else ssl.CERT_NONE)
1085 if cacerts:
1086 self.context.load_verify_locations(cacerts)
1087 if certificate:
1088 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001089 if npn_protocols:
1090 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001091 if ciphers:
1092 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001093 self.chatty = chatty
1094 self.connectionchatty = connectionchatty
1095 self.starttls_server = starttls_server
1096 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001097 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001098 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001099 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001100 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001101 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001102 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001103 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001104
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001105 def __enter__(self):
1106 self.start(threading.Event())
1107 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001108 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001109
1110 def __exit__(self, *args):
1111 self.stop()
1112 self.join()
1113
Antoine Pitrou480a1242010-04-28 21:37:09 +00001114 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001115 self.flag = flag
1116 threading.Thread.start(self)
1117
Antoine Pitrou480a1242010-04-28 21:37:09 +00001118 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001119 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001120 self.sock.listen(5)
1121 self.active = True
1122 if self.flag:
1123 # signal an event
1124 self.flag.set()
1125 while self.active:
1126 try:
1127 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001128 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001129 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001130 + repr(connaddr) + '\n')
1131 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001132 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001133 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001134 except socket.timeout:
1135 pass
1136 except KeyboardInterrupt:
1137 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001138 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001139
Antoine Pitrou480a1242010-04-28 21:37:09 +00001140 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001141 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001142
Bill Janssen54cc54c2007-12-14 22:08:56 +00001143 class AsyncoreEchoServer(threading.Thread):
1144
1145 # this one's based on asyncore.dispatcher
1146
1147 class EchoServer (asyncore.dispatcher):
1148
1149 class ConnectionHandler (asyncore.dispatcher_with_send):
1150
1151 def __init__(self, conn, certfile):
1152 self.socket = ssl.wrap_socket(conn, server_side=True,
1153 certfile=certfile,
1154 do_handshake_on_connect=False)
1155 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001156 self._ssl_accepting = True
1157 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001158
1159 def readable(self):
1160 if isinstance(self.socket, ssl.SSLSocket):
1161 while self.socket.pending() > 0:
1162 self.handle_read_event()
1163 return True
1164
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001165 def _do_ssl_handshake(self):
1166 try:
1167 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001168 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1169 return
1170 except ssl.SSLEOFError:
1171 return self.handle_close()
1172 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001173 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001174 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001175 if err.args[0] == errno.ECONNABORTED:
1176 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001177 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001178 self._ssl_accepting = False
1179
1180 def handle_read(self):
1181 if self._ssl_accepting:
1182 self._do_ssl_handshake()
1183 else:
1184 data = self.recv(1024)
1185 if support.verbose:
1186 sys.stdout.write(" server: read %s from client\n" % repr(data))
1187 if not data:
1188 self.close()
1189 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001190 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001191
1192 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001193 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001194 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001195 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1196
1197 def handle_error(self):
1198 raise
1199
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001200 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001201 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001202 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1203 self.port = support.bind_port(sock, '')
1204 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001205 self.listen(5)
1206
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001207 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001208 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001209 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1210 self.ConnectionHandler(sock_obj, self.certfile)
1211
1212 def handle_error(self):
1213 raise
1214
Trent Nelson78520002008-04-10 20:54:35 +00001215 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001216 self.flag = None
1217 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001218 self.server = self.EchoServer(certfile)
1219 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001220 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001221 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001222
1223 def __str__(self):
1224 return "<%s %s>" % (self.__class__.__name__, self.server)
1225
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001226 def __enter__(self):
1227 self.start(threading.Event())
1228 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001229 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001230
1231 def __exit__(self, *args):
1232 if support.verbose:
1233 sys.stdout.write(" cleanup: stopping server.\n")
1234 self.stop()
1235 if support.verbose:
1236 sys.stdout.write(" cleanup: joining server thread.\n")
1237 self.join()
1238 if support.verbose:
1239 sys.stdout.write(" cleanup: successfully joined.\n")
1240
Bill Janssen54cc54c2007-12-14 22:08:56 +00001241 def start (self, flag=None):
1242 self.flag = flag
1243 threading.Thread.start(self)
1244
Antoine Pitrou480a1242010-04-28 21:37:09 +00001245 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001246 self.active = True
1247 if self.flag:
1248 self.flag.set()
1249 while self.active:
1250 try:
1251 asyncore.loop(1)
1252 except:
1253 pass
1254
Antoine Pitrou480a1242010-04-28 21:37:09 +00001255 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001256 self.active = False
1257 self.server.close()
1258
Antoine Pitrou480a1242010-04-28 21:37:09 +00001259 def bad_cert_test(certfile):
1260 """
1261 Launch a server with CERT_REQUIRED, and check that trying to
1262 connect to it with the given client certificate fails.
1263 """
Trent Nelson78520002008-04-10 20:54:35 +00001264 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001265 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001266 cacerts=CERTFILE, chatty=False,
1267 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001268 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001269 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001270 with socket.socket() as sock:
1271 s = ssl.wrap_socket(sock,
1272 certfile=certfile,
1273 ssl_version=ssl.PROTOCOL_TLSv1)
1274 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001275 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001276 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001277 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001278 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001279 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001280 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001281 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001282 if x.errno != errno.ENOENT:
1283 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001284 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001285 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001286 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001287 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001288
Antoine Pitroub5218772010-05-21 09:56:06 +00001289 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001290 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001291 """
1292 Launch a server, connect a client to it and try various reads
1293 and writes.
1294 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001295 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001296 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001297 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001298 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001299 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001300 with client_context.wrap_socket(socket.socket(),
1301 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001302 s.connect((HOST, server.port))
1303 for arg in [indata, bytearray(indata), memoryview(indata)]:
1304 if connectionchatty:
1305 if support.verbose:
1306 sys.stdout.write(
1307 " client: sending %r...\n" % indata)
1308 s.write(arg)
1309 outdata = s.read()
1310 if connectionchatty:
1311 if support.verbose:
1312 sys.stdout.write(" client: read %r\n" % outdata)
1313 if outdata != indata.lower():
1314 raise AssertionError(
1315 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1316 % (outdata[:20], len(outdata),
1317 indata[:20].lower(), len(indata)))
1318 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001319 if connectionchatty:
1320 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001321 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001322 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001323 'compression': s.compression(),
1324 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001325 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001326 'client_npn_protocol': s.selected_npn_protocol()
1327 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001328 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001329 stats['server_npn_protocols'] = server.selected_protocols
1330 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001331
Antoine Pitroub5218772010-05-21 09:56:06 +00001332 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1333 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001334 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001335 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001336 certtype = {
1337 ssl.CERT_NONE: "CERT_NONE",
1338 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1339 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1340 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001341 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001342 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001343 sys.stdout.write(formatstr %
1344 (ssl.get_protocol_name(client_protocol),
1345 ssl.get_protocol_name(server_protocol),
1346 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001347 client_context = ssl.SSLContext(client_protocol)
1348 client_context.options = ssl.OP_ALL | client_options
1349 server_context = ssl.SSLContext(server_protocol)
1350 server_context.options = ssl.OP_ALL | server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001351
1352 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1353 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1354 # starting from OpenSSL 1.0.0 (see issue #8322).
1355 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1356 client_context.set_ciphers("ALL")
1357
Antoine Pitroub5218772010-05-21 09:56:06 +00001358 for ctx in (client_context, server_context):
1359 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001360 ctx.load_cert_chain(CERTFILE)
1361 ctx.load_verify_locations(CERTFILE)
1362 try:
1363 server_params_test(client_context, server_context,
1364 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001365 # Protocol mismatch can result in either an SSLError, or a
1366 # "Connection reset by peer" error.
1367 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001368 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001369 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001370 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001371 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001372 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001373 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001374 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001375 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001376 "Client protocol %s succeeded with server protocol %s!"
1377 % (ssl.get_protocol_name(client_protocol),
1378 ssl.get_protocol_name(server_protocol)))
1379
1380
Bill Janssen6e027db2007-11-15 22:23:56 +00001381 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001382
Antoine Pitrou23df4832010-08-04 17:14:06 +00001383 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001384 def test_echo(self):
1385 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001386 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001387 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001388 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001389 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1390 context = ssl.SSLContext(protocol)
1391 context.load_cert_chain(CERTFILE)
1392 server_params_test(context, context,
1393 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001394
Antoine Pitrou480a1242010-04-28 21:37:09 +00001395 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001396 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001397 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001398 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1399 context.verify_mode = ssl.CERT_REQUIRED
1400 context.load_verify_locations(CERTFILE)
1401 context.load_cert_chain(CERTFILE)
1402 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001403 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001404 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001405 s.connect((HOST, server.port))
1406 cert = s.getpeercert()
1407 self.assertTrue(cert, "Can't get peer certificate.")
1408 cipher = s.cipher()
1409 if support.verbose:
1410 sys.stdout.write(pprint.pformat(cert) + '\n')
1411 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1412 if 'subject' not in cert:
1413 self.fail("No subject field in certificate: %s." %
1414 pprint.pformat(cert))
1415 if ((('organizationName', 'Python Software Foundation'),)
1416 not in cert['subject']):
1417 self.fail(
1418 "Missing or invalid 'organizationName' field in certificate subject; "
1419 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001420 self.assertIn('notBefore', cert)
1421 self.assertIn('notAfter', cert)
1422 before = ssl.cert_time_to_seconds(cert['notBefore'])
1423 after = ssl.cert_time_to_seconds(cert['notAfter'])
1424 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001425 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001426
Antoine Pitrou480a1242010-04-28 21:37:09 +00001427 def test_empty_cert(self):
1428 """Connecting with an empty cert file"""
1429 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1430 "nullcert.pem"))
1431 def test_malformed_cert(self):
1432 """Connecting with a badly formatted certificate (syntax error)"""
1433 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1434 "badcert.pem"))
1435 def test_nonexisting_cert(self):
1436 """Connecting with a non-existing cert file"""
1437 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1438 "wrongcert.pem"))
1439 def test_malformed_key(self):
1440 """Connecting with a badly formatted key (syntax error)"""
1441 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1442 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001443
Antoine Pitrou480a1242010-04-28 21:37:09 +00001444 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001445 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00001446 in the client when attempting handshake.
1447 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001448 listener_ready = threading.Event()
1449 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001450
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001451 s = socket.socket()
1452 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001453
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001454 # `listener` runs in a thread. It sits in an accept() until
1455 # the main thread connects. Then it rudely closes the socket,
1456 # and sets Event `listener_gone` to let the main thread know
1457 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001458 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001459 s.listen(5)
1460 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001461 newsock, addr = s.accept()
1462 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001463 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001464 listener_gone.set()
1465
1466 def connector():
1467 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001468 with socket.socket() as c:
1469 c.connect((HOST, port))
1470 listener_gone.wait()
1471 try:
1472 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001473 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001474 pass
1475 else:
1476 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001477
1478 t = threading.Thread(target=listener)
1479 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001480 try:
1481 connector()
1482 finally:
1483 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001484
Antoine Pitrou23df4832010-08-04 17:14:06 +00001485 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001486 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1487 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001488 def test_protocol_sslv2(self):
1489 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001490 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001491 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1493 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1494 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1495 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1496 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1497 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001498 # SSLv23 client with specific SSL options
1499 if no_sslv2_implies_sslv3_hello():
1500 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1501 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1502 client_options=ssl.OP_NO_SSLv2)
1503 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1504 client_options=ssl.OP_NO_SSLv3)
1505 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1506 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001507
Antoine Pitrou23df4832010-08-04 17:14:06 +00001508 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001509 def test_protocol_sslv23(self):
1510 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001511 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001512 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001513 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1514 try:
1515 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02001516 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02001517 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1518 if support.verbose:
1519 sys.stdout.write(
1520 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1521 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001522 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1523 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1524 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001525
Antoine Pitrou480a1242010-04-28 21:37:09 +00001526 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1527 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1528 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001529
Antoine Pitrou480a1242010-04-28 21:37:09 +00001530 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1531 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1532 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001533
Antoine Pitroub5218772010-05-21 09:56:06 +00001534 # Server with specific SSL options
1535 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1536 server_options=ssl.OP_NO_SSLv3)
1537 # Will choose TLSv1
1538 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1539 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1540 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1541 server_options=ssl.OP_NO_TLSv1)
1542
1543
Antoine Pitrou23df4832010-08-04 17:14:06 +00001544 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001545 def test_protocol_sslv3(self):
1546 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001547 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001548 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001549 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1550 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1551 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001552 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1553 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001554 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1555 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001556 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001557 if no_sslv2_implies_sslv3_hello():
1558 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1559 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1560 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001561
Antoine Pitrou23df4832010-08-04 17:14:06 +00001562 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001563 def test_protocol_tlsv1(self):
1564 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001565 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001566 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001567 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1568 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1569 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001570 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1571 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001572 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001573 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1574 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001575
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001576 @skip_if_broken_ubuntu_ssl
1577 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
1578 "TLS version 1.1 not supported.")
1579 def test_protocol_tlsv1_1(self):
1580 """Connecting to a TLSv1.1 server with various client options.
1581 Testing against older TLS versions."""
1582 if support.verbose:
1583 sys.stdout.write("\n")
1584 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
1585 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1586 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
1587 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
1588 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
1589 client_options=ssl.OP_NO_TLSv1_1)
1590
1591 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
1592 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
1593 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
1594
1595
1596 @skip_if_broken_ubuntu_ssl
1597 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
1598 "TLS version 1.2 not supported.")
1599 def test_protocol_tlsv1_2(self):
1600 """Connecting to a TLSv1.2 server with various client options.
1601 Testing against older TLS versions."""
1602 if support.verbose:
1603 sys.stdout.write("\n")
1604 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
1605 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
1606 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
1607 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1608 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
1609 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
1610 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
1611 client_options=ssl.OP_NO_TLSv1_2)
1612
1613 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
1614 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
1615 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
1616 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
1617 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
1618
Antoine Pitrou480a1242010-04-28 21:37:09 +00001619 def test_starttls(self):
1620 """Switching from clear text to encrypted and back again."""
1621 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 +00001622
Trent Nelson78520002008-04-10 20:54:35 +00001623 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001624 ssl_version=ssl.PROTOCOL_TLSv1,
1625 starttls_server=True,
1626 chatty=True,
1627 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001628 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001629 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001630 s = socket.socket()
1631 s.setblocking(1)
1632 s.connect((HOST, server.port))
1633 if support.verbose:
1634 sys.stdout.write("\n")
1635 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001636 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001637 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001638 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001639 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001640 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001641 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001642 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001643 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001644 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001645 msg = outdata.strip().lower()
1646 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1647 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001648 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001649 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001650 " client: read %r from server, starting TLS...\n"
1651 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001652 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1653 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001654 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1655 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001656 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001657 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001658 " client: read %r from server, ending TLS...\n"
1659 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001660 s = conn.unwrap()
1661 wrapped = False
1662 else:
1663 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001664 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001665 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001666 if support.verbose:
1667 sys.stdout.write(" client: closing connection.\n")
1668 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001669 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001670 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001671 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001672 if wrapped:
1673 conn.close()
1674 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001675 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001676
Antoine Pitrou480a1242010-04-28 21:37:09 +00001677 def test_socketserver(self):
1678 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01001679 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001680 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001681 if support.verbose:
1682 sys.stdout.write('\n')
1683 with open(CERTFILE, 'rb') as f:
1684 d1 = f.read()
1685 d2 = ''
1686 # now fetch the same data from the HTTPS server
1687 url = 'https://%s:%d/%s' % (
1688 HOST, server.port, os.path.split(CERTFILE)[1])
1689 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001690 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001691 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001692 if dlen and (int(dlen) > 0):
1693 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001694 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001695 sys.stdout.write(
1696 " client: read %d bytes from remote server '%s'\n"
1697 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001698 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001699 f.close()
1700 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001701
Antoine Pitrou480a1242010-04-28 21:37:09 +00001702 def test_asyncore_server(self):
1703 """Check the example asyncore integration."""
1704 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001705
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001706 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001707 sys.stdout.write("\n")
1708
Antoine Pitrou480a1242010-04-28 21:37:09 +00001709 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001710 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001711 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001712 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001713 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001714 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001715 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001716 " client: sending %r...\n" % indata)
1717 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001718 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001719 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001720 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001721 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001722 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001723 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1724 % (outdata[:20], len(outdata),
1725 indata[:20].lower(), len(indata)))
1726 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001727 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001728 sys.stdout.write(" client: closing connection.\n")
1729 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001730 if support.verbose:
1731 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001732
Antoine Pitrou480a1242010-04-28 21:37:09 +00001733 def test_recv_send(self):
1734 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001735 if support.verbose:
1736 sys.stdout.write("\n")
1737
1738 server = ThreadedEchoServer(CERTFILE,
1739 certreqs=ssl.CERT_NONE,
1740 ssl_version=ssl.PROTOCOL_TLSv1,
1741 cacerts=CERTFILE,
1742 chatty=True,
1743 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001744 with server:
1745 s = ssl.wrap_socket(socket.socket(),
1746 server_side=False,
1747 certfile=CERTFILE,
1748 ca_certs=CERTFILE,
1749 cert_reqs=ssl.CERT_NONE,
1750 ssl_version=ssl.PROTOCOL_TLSv1)
1751 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001752 # helper methods for standardising recv* method signatures
1753 def _recv_into():
1754 b = bytearray(b"\0"*100)
1755 count = s.recv_into(b)
1756 return b[:count]
1757
1758 def _recvfrom_into():
1759 b = bytearray(b"\0"*100)
1760 count, addr = s.recvfrom_into(b)
1761 return b[:count]
1762
1763 # (name, method, whether to expect success, *args)
1764 send_methods = [
1765 ('send', s.send, True, []),
1766 ('sendto', s.sendto, False, ["some.address"]),
1767 ('sendall', s.sendall, True, []),
1768 ]
1769 recv_methods = [
1770 ('recv', s.recv, True, []),
1771 ('recvfrom', s.recvfrom, False, ["some.address"]),
1772 ('recv_into', _recv_into, True, []),
1773 ('recvfrom_into', _recvfrom_into, False, []),
1774 ]
1775 data_prefix = "PREFIX_"
1776
1777 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001778 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001779 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001780 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001781 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001782 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001783 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001784 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001785 "<<{outdata:r}>> ({nout:d}) received; "
1786 "expected <<{indata:r}>> ({nin:d})\n".format(
1787 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001788 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001789 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001790 )
1791 )
1792 except ValueError as e:
1793 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001794 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001795 "Failed to send with method <<{name:s}>>; "
1796 "expected to succeed.\n".format(name=meth_name)
1797 )
1798 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001799 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001800 "Method <<{name:s}>> failed with unexpected "
1801 "exception message: {exp:s}\n".format(
1802 name=meth_name, exp=e
1803 )
1804 )
1805
1806 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001807 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001808 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001809 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001810 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001811 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001812 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001813 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001814 "<<{outdata:r}>> ({nout:d}) received; "
1815 "expected <<{indata:r}>> ({nin:d})\n".format(
1816 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001817 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001818 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001819 )
1820 )
1821 except ValueError as e:
1822 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001823 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001824 "Failed to receive with method <<{name:s}>>; "
1825 "expected to succeed.\n".format(name=meth_name)
1826 )
1827 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001828 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001829 "Method <<{name:s}>> failed with unexpected "
1830 "exception message: {exp:s}\n".format(
1831 name=meth_name, exp=e
1832 )
1833 )
1834 # consume data
1835 s.read()
1836
Nick Coghlan513886a2011-08-28 00:00:27 +10001837 # Make sure sendmsg et al are disallowed to avoid
1838 # inadvertent disclosure of data and/or corruption
1839 # of the encrypted data stream
1840 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1841 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1842 self.assertRaises(NotImplementedError,
1843 s.recvmsg_into, bytearray(100))
1844
Antoine Pitrou480a1242010-04-28 21:37:09 +00001845 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001846 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001847
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001848 def test_handshake_timeout(self):
1849 # Issue #5103: SSL handshake must respect the socket timeout
1850 server = socket.socket(socket.AF_INET)
1851 host = "127.0.0.1"
1852 port = support.bind_port(server)
1853 started = threading.Event()
1854 finish = False
1855
1856 def serve():
1857 server.listen(5)
1858 started.set()
1859 conns = []
1860 while not finish:
1861 r, w, e = select.select([server], [], [], 0.1)
1862 if server in r:
1863 # Let the socket hang around rather than having
1864 # it closed by garbage collection.
1865 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001866 for sock in conns:
1867 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001868
1869 t = threading.Thread(target=serve)
1870 t.start()
1871 started.wait()
1872
1873 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001874 try:
1875 c = socket.socket(socket.AF_INET)
1876 c.settimeout(0.2)
1877 c.connect((host, port))
1878 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001879 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001880 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001881 finally:
1882 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001883 try:
1884 c = socket.socket(socket.AF_INET)
1885 c = ssl.wrap_socket(c)
1886 c.settimeout(0.2)
1887 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001888 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001889 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001890 finally:
1891 c.close()
1892 finally:
1893 finish = True
1894 t.join()
1895 server.close()
1896
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001897 def test_server_accept(self):
1898 # Issue #16357: accept() on a SSLSocket created through
1899 # SSLContext.wrap_socket().
1900 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1901 context.verify_mode = ssl.CERT_REQUIRED
1902 context.load_verify_locations(CERTFILE)
1903 context.load_cert_chain(CERTFILE)
1904 server = socket.socket(socket.AF_INET)
1905 host = "127.0.0.1"
1906 port = support.bind_port(server)
1907 server = context.wrap_socket(server, server_side=True)
1908
1909 evt = threading.Event()
1910 remote = None
1911 peer = None
1912 def serve():
1913 nonlocal remote, peer
1914 server.listen(5)
1915 # Block on the accept and wait on the connection to close.
1916 evt.set()
1917 remote, peer = server.accept()
1918 remote.recv(1)
1919
1920 t = threading.Thread(target=serve)
1921 t.start()
1922 # Client wait until server setup and perform a connect.
1923 evt.wait()
1924 client = context.wrap_socket(socket.socket())
1925 client.connect((host, port))
1926 client_addr = client.getsockname()
1927 client.close()
1928 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001929 remote.close()
1930 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001931 # Sanity checks.
1932 self.assertIsInstance(remote, ssl.SSLSocket)
1933 self.assertEqual(peer, client_addr)
1934
Antoine Pitrou242db722013-05-01 20:52:07 +02001935 def test_getpeercert_enotconn(self):
1936 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1937 with context.wrap_socket(socket.socket()) as sock:
1938 with self.assertRaises(OSError) as cm:
1939 sock.getpeercert()
1940 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
1941
1942 def test_do_handshake_enotconn(self):
1943 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1944 with context.wrap_socket(socket.socket()) as sock:
1945 with self.assertRaises(OSError) as cm:
1946 sock.do_handshake()
1947 self.assertEqual(cm.exception.errno, errno.ENOTCONN)
1948
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001949 def test_default_ciphers(self):
1950 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1951 try:
1952 # Force a set of weak ciphers on our client context
1953 context.set_ciphers("DES")
1954 except ssl.SSLError:
1955 self.skipTest("no DES cipher available")
1956 with ThreadedEchoServer(CERTFILE,
1957 ssl_version=ssl.PROTOCOL_SSLv23,
1958 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001959 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001960 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001961 s.connect((HOST, server.port))
1962 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1963
Antoine Pitroud6494802011-07-21 01:11:30 +02001964 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1965 "'tls-unique' channel binding not available")
1966 def test_tls_unique_channel_binding(self):
1967 """Test tls-unique channel binding."""
1968 if support.verbose:
1969 sys.stdout.write("\n")
1970
1971 server = ThreadedEchoServer(CERTFILE,
1972 certreqs=ssl.CERT_NONE,
1973 ssl_version=ssl.PROTOCOL_TLSv1,
1974 cacerts=CERTFILE,
1975 chatty=True,
1976 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001977 with server:
1978 s = ssl.wrap_socket(socket.socket(),
1979 server_side=False,
1980 certfile=CERTFILE,
1981 ca_certs=CERTFILE,
1982 cert_reqs=ssl.CERT_NONE,
1983 ssl_version=ssl.PROTOCOL_TLSv1)
1984 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001985 # get the data
1986 cb_data = s.get_channel_binding("tls-unique")
1987 if support.verbose:
1988 sys.stdout.write(" got channel binding data: {0!r}\n"
1989 .format(cb_data))
1990
1991 # check if it is sane
1992 self.assertIsNotNone(cb_data)
1993 self.assertEqual(len(cb_data), 12) # True for TLSv1
1994
1995 # and compare with the peers version
1996 s.write(b"CB tls-unique\n")
1997 peer_data_repr = s.read().strip()
1998 self.assertEqual(peer_data_repr,
1999 repr(cb_data).encode("us-ascii"))
2000 s.close()
2001
2002 # now, again
2003 s = ssl.wrap_socket(socket.socket(),
2004 server_side=False,
2005 certfile=CERTFILE,
2006 ca_certs=CERTFILE,
2007 cert_reqs=ssl.CERT_NONE,
2008 ssl_version=ssl.PROTOCOL_TLSv1)
2009 s.connect((HOST, server.port))
2010 new_cb_data = s.get_channel_binding("tls-unique")
2011 if support.verbose:
2012 sys.stdout.write(" got another channel binding data: {0!r}\n"
2013 .format(new_cb_data))
2014 # is it really unique
2015 self.assertNotEqual(cb_data, new_cb_data)
2016 self.assertIsNotNone(cb_data)
2017 self.assertEqual(len(cb_data), 12) # True for TLSv1
2018 s.write(b"CB tls-unique\n")
2019 peer_data_repr = s.read().strip()
2020 self.assertEqual(peer_data_repr,
2021 repr(new_cb_data).encode("us-ascii"))
2022 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002023
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002024 def test_compression(self):
2025 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2026 context.load_cert_chain(CERTFILE)
2027 stats = server_params_test(context, context,
2028 chatty=True, connectionchatty=True)
2029 if support.verbose:
2030 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2031 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2032
2033 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2034 "ssl.OP_NO_COMPRESSION needed for this test")
2035 def test_compression_disabled(self):
2036 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2037 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002038 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002039 stats = server_params_test(context, context,
2040 chatty=True, connectionchatty=True)
2041 self.assertIs(stats['compression'], None)
2042
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002043 def test_dh_params(self):
2044 # Check we can get a connection with ephemeral Diffie-Hellman
2045 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2046 context.load_cert_chain(CERTFILE)
2047 context.load_dh_params(DHFILE)
2048 context.set_ciphers("kEDH")
2049 stats = server_params_test(context, context,
2050 chatty=True, connectionchatty=True)
2051 cipher = stats["cipher"][0]
2052 parts = cipher.split("-")
2053 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2054 self.fail("Non-DH cipher: " + cipher[0])
2055
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002056 def test_selected_npn_protocol(self):
2057 # selected_npn_protocol() is None unless NPN is used
2058 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2059 context.load_cert_chain(CERTFILE)
2060 stats = server_params_test(context, context,
2061 chatty=True, connectionchatty=True)
2062 self.assertIs(stats['client_npn_protocol'], None)
2063
2064 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2065 def test_npn_protocols(self):
2066 server_protocols = ['http/1.1', 'spdy/2']
2067 protocol_tests = [
2068 (['http/1.1', 'spdy/2'], 'http/1.1'),
2069 (['spdy/2', 'http/1.1'], 'http/1.1'),
2070 (['spdy/2', 'test'], 'spdy/2'),
2071 (['abc', 'def'], 'abc')
2072 ]
2073 for client_protocols, expected in protocol_tests:
2074 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2075 server_context.load_cert_chain(CERTFILE)
2076 server_context.set_npn_protocols(server_protocols)
2077 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2078 client_context.load_cert_chain(CERTFILE)
2079 client_context.set_npn_protocols(client_protocols)
2080 stats = server_params_test(client_context, server_context,
2081 chatty=True, connectionchatty=True)
2082
2083 msg = "failed trying %s (s) and %s (c).\n" \
2084 "was expecting %s, but got %%s from the %%s" \
2085 % (str(server_protocols), str(client_protocols),
2086 str(expected))
2087 client_result = stats['client_npn_protocol']
2088 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2089 server_result = stats['server_npn_protocols'][-1] \
2090 if len(stats['server_npn_protocols']) else 'nothing'
2091 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2092
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002093 def sni_contexts(self):
2094 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2095 server_context.load_cert_chain(SIGNED_CERTFILE)
2096 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2097 other_context.load_cert_chain(SIGNED_CERTFILE2)
2098 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2099 client_context.verify_mode = ssl.CERT_REQUIRED
2100 client_context.load_verify_locations(SIGNING_CA)
2101 return server_context, other_context, client_context
2102
2103 def check_common_name(self, stats, name):
2104 cert = stats['peercert']
2105 self.assertIn((('commonName', name),), cert['subject'])
2106
2107 @needs_sni
2108 def test_sni_callback(self):
2109 calls = []
2110 server_context, other_context, client_context = self.sni_contexts()
2111
2112 def servername_cb(ssl_sock, server_name, initial_context):
2113 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002114 if server_name is not None:
2115 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002116 server_context.set_servername_callback(servername_cb)
2117
2118 stats = server_params_test(client_context, server_context,
2119 chatty=True,
2120 sni_name='supermessage')
2121 # The hostname was fetched properly, and the certificate was
2122 # changed for the connection.
2123 self.assertEqual(calls, [("supermessage", server_context)])
2124 # CERTFILE4 was selected
2125 self.check_common_name(stats, 'fakehostname')
2126
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002127 calls = []
2128 # The callback is called with server_name=None
2129 stats = server_params_test(client_context, server_context,
2130 chatty=True,
2131 sni_name=None)
2132 self.assertEqual(calls, [(None, server_context)])
2133 self.check_common_name(stats, 'localhost')
2134
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002135 # Check disabling the callback
2136 calls = []
2137 server_context.set_servername_callback(None)
2138
2139 stats = server_params_test(client_context, server_context,
2140 chatty=True,
2141 sni_name='notfunny')
2142 # Certificate didn't change
2143 self.check_common_name(stats, 'localhost')
2144 self.assertEqual(calls, [])
2145
2146 @needs_sni
2147 def test_sni_callback_alert(self):
2148 # Returning a TLS alert is reflected to the connecting client
2149 server_context, other_context, client_context = self.sni_contexts()
2150
2151 def cb_returning_alert(ssl_sock, server_name, initial_context):
2152 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2153 server_context.set_servername_callback(cb_returning_alert)
2154
2155 with self.assertRaises(ssl.SSLError) as cm:
2156 stats = server_params_test(client_context, server_context,
2157 chatty=False,
2158 sni_name='supermessage')
2159 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2160
2161 @needs_sni
2162 def test_sni_callback_raising(self):
2163 # Raising fails the connection with a TLS handshake failure alert.
2164 server_context, other_context, client_context = self.sni_contexts()
2165
2166 def cb_raising(ssl_sock, server_name, initial_context):
2167 1/0
2168 server_context.set_servername_callback(cb_raising)
2169
2170 with self.assertRaises(ssl.SSLError) as cm, \
2171 support.captured_stderr() as stderr:
2172 stats = server_params_test(client_context, server_context,
2173 chatty=False,
2174 sni_name='supermessage')
2175 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2176 self.assertIn("ZeroDivisionError", stderr.getvalue())
2177
2178 @needs_sni
2179 def test_sni_callback_wrong_return_type(self):
2180 # Returning the wrong return type terminates the TLS connection
2181 # with an internal error alert.
2182 server_context, other_context, client_context = self.sni_contexts()
2183
2184 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2185 return "foo"
2186 server_context.set_servername_callback(cb_wrong_return_type)
2187
2188 with self.assertRaises(ssl.SSLError) as cm, \
2189 support.captured_stderr() as stderr:
2190 stats = server_params_test(client_context, server_context,
2191 chatty=False,
2192 sni_name='supermessage')
2193 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2194 self.assertIn("TypeError", stderr.getvalue())
2195
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002196
Thomas Woutersed03b412007-08-28 21:37:11 +00002197def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002198 if support.verbose:
2199 plats = {
2200 'Linux': platform.linux_distribution,
2201 'Mac': platform.mac_ver,
2202 'Windows': platform.win32_ver,
2203 }
2204 for name, func in plats.items():
2205 plat = func()
2206 if plat and plat[0]:
2207 plat = '%s %r' % (name, plat)
2208 break
2209 else:
2210 plat = repr(platform.platform())
2211 print("test_ssl: testing with %r %r" %
2212 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2213 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002214 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002215 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2216 try:
2217 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2218 except AttributeError:
2219 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002220
Antoine Pitrou152efa22010-05-16 18:19:27 +00002221 for filename in [
2222 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2223 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002224 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002225 BADCERT, BADKEY, EMPTYCERT]:
2226 if not os.path.exists(filename):
2227 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002228
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002229 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002230
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002231 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002232 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002233
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002234 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002235 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002236 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002237 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002238
Antoine Pitrou480a1242010-04-28 21:37:09 +00002239 try:
2240 support.run_unittest(*tests)
2241 finally:
2242 if _have_threads:
2243 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002244
2245if __name__ == "__main__":
2246 test_main()