blob: 1f0f62ab80f4f8b94d52fb1e957224eee2627f0d [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
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Antoine Pitrou05d936d2010-10-13 11:38:36 +000021ssl = support.import_module("ssl")
22
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010023PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000024HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000025
26data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000027
Antoine Pitrou81564092010-10-08 23:06:24 +000028# The custom key and certificate files used in test_ssl are generated
29# using Lib/test/make_ssl_certs.py.
30# Other certificates are simply fetched from the Internet servers they
31# are meant to authenticate.
32
Antoine Pitrou152efa22010-05-16 18:19:27 +000033CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000034BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000035ONLYCERT = data_file("ssl_cert.pem")
36ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000037BYTES_ONLYCERT = os.fsencode(ONLYCERT)
38BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020039CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
40ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
41KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000042CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000044
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010045# Two keys and certs signed by the same CA (for SNI tests)
46SIGNED_CERTFILE = data_file("keycert3.pem")
47SIGNED_CERTFILE2 = data_file("keycert4.pem")
48SIGNING_CA = data_file("pycacert.pem")
49
Antoine Pitrou152efa22010-05-16 18:19:27 +000050SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
51
52EMPTYCERT = data_file("nullcert.pem")
53BADCERT = data_file("badcert.pem")
54WRONGCERT = data_file("XXXnonexisting.pem")
55BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020056NOKIACERT = data_file("nokia.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000057
Antoine Pitrou0e576f12011-12-22 10:03:38 +010058DHFILE = data_file("dh512.pem")
59BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010061
Thomas Woutersed03b412007-08-28 21:37:11 +000062def handle_error(prefix):
63 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000064 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000065 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000066
Antoine Pitroub5218772010-05-21 09:56:06 +000067def can_clear_options():
68 # 0.9.8m or higher
Antoine Pitroub9ac25d2011-07-08 18:47:06 +020069 return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
Antoine Pitroub5218772010-05-21 09:56:06 +000070
71def no_sslv2_implies_sslv3_hello():
72 # 0.9.7h or higher
73 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
74
Thomas Woutersed03b412007-08-28 21:37:11 +000075
Antoine Pitrou23df4832010-08-04 17:14:06 +000076# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
77def skip_if_broken_ubuntu_ssl(func):
Victor Stinner3de49192011-05-09 00:42:58 +020078 if hasattr(ssl, 'PROTOCOL_SSLv2'):
79 @functools.wraps(func)
80 def f(*args, **kwargs):
81 try:
82 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
83 except ssl.SSLError:
84 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
85 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
86 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
87 return func(*args, **kwargs)
88 return f
89 else:
90 return func
Antoine Pitrou23df4832010-08-04 17:14:06 +000091
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010092needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
93
Antoine Pitrou23df4832010-08-04 17:14:06 +000094
Antoine Pitrou152efa22010-05-16 18:19:27 +000095class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000096
Antoine Pitrou480a1242010-04-28 21:37:09 +000097 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098 ssl.CERT_NONE
99 ssl.CERT_OPTIONAL
100 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100101 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100102 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100103 if ssl.HAS_ECDH:
104 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100105 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
106 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000107 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100108 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000109
Antoine Pitrou480a1242010-04-28 21:37:09 +0000110 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000111 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000112 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000113 sys.stdout.write("\n RAND_status is %d (%s)\n"
114 % (v, (v and "sufficient randomness") or
115 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200116
117 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
118 self.assertEqual(len(data), 16)
119 self.assertEqual(is_cryptographic, v == 1)
120 if v:
121 data = ssl.RAND_bytes(16)
122 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200123 else:
124 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200125
Jesus Ceac8754a12012-09-11 02:00:58 +0200126 self.assertRaises(TypeError, ssl.RAND_egd, 1)
127 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000129
Antoine Pitrou480a1242010-04-28 21:37:09 +0000130 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000131 # note that this uses an 'unofficial' function in _ssl.c,
132 # provided solely for this test, to exercise the certificate
133 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000134 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000135 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000136 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200137 self.assertEqual(p['issuer'],
138 ((('countryName', 'XY'),),
139 (('localityName', 'Castle Anthrax'),),
140 (('organizationName', 'Python Software Foundation'),),
141 (('commonName', 'localhost'),))
142 )
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100143 # Note the next three asserts will fail if the keys are regenerated
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200144 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
145 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
146 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
147 self.assertEqual(p['subject'],
148 ((('countryName', 'XY'),),
149 (('localityName', 'Castle Anthrax'),),
150 (('organizationName', 'Python Software Foundation'),),
151 (('commonName', 'localhost'),))
152 )
153 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
154 # Issue #13034: the subjectAltName in some certificates
155 # (notably projects.developer.nokia.com:443) wasn't parsed
156 p = ssl._ssl._test_decode_cert(NOKIACERT)
157 if support.verbose:
158 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
159 self.assertEqual(p['subjectAltName'],
160 (('DNS', 'projects.developer.nokia.com'),
161 ('DNS', 'projects.forum.nokia.com'))
162 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000163
Antoine Pitrou480a1242010-04-28 21:37:09 +0000164 def test_DER_to_PEM(self):
165 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
166 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000167 d1 = ssl.PEM_cert_to_DER_cert(pem)
168 p2 = ssl.DER_cert_to_PEM_cert(d1)
169 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000170 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000171 if not p2.startswith(ssl.PEM_HEADER + '\n'):
172 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
173 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
174 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000175
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000176 def test_openssl_version(self):
177 n = ssl.OPENSSL_VERSION_NUMBER
178 t = ssl.OPENSSL_VERSION_INFO
179 s = ssl.OPENSSL_VERSION
180 self.assertIsInstance(n, int)
181 self.assertIsInstance(t, tuple)
182 self.assertIsInstance(s, str)
183 # Some sanity checks follow
184 # >= 0.9
185 self.assertGreaterEqual(n, 0x900000)
186 # < 2.0
187 self.assertLess(n, 0x20000000)
188 major, minor, fix, patch, status = t
189 self.assertGreaterEqual(major, 0)
190 self.assertLess(major, 2)
191 self.assertGreaterEqual(minor, 0)
192 self.assertLess(minor, 256)
193 self.assertGreaterEqual(fix, 0)
194 self.assertLess(fix, 256)
195 self.assertGreaterEqual(patch, 0)
196 self.assertLessEqual(patch, 26)
197 self.assertGreaterEqual(status, 0)
198 self.assertLessEqual(status, 15)
199 # Version string as returned by OpenSSL, the format might change
200 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
201 (s, t))
202
Antoine Pitrou9d543662010-04-23 23:10:32 +0000203 @support.cpython_only
204 def test_refcycle(self):
205 # Issue #7943: an SSL object doesn't create reference cycles with
206 # itself.
207 s = socket.socket(socket.AF_INET)
208 ss = ssl.wrap_socket(s)
209 wr = weakref.ref(ss)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100210 with support.check_warnings(("", ResourceWarning)):
211 del ss
212 self.assertEqual(wr(), None)
Antoine Pitrou9d543662010-04-23 23:10:32 +0000213
Antoine Pitroua468adc2010-09-14 14:43:44 +0000214 def test_wrapped_unconnected(self):
215 # Methods on an unconnected SSLSocket propagate the original
Andrew Svetlov0832af62012-12-18 23:10:48 +0200216 # OSError raise by the underlying socket object.
Antoine Pitroua468adc2010-09-14 14:43:44 +0000217 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100218 with ssl.wrap_socket(s) as ss:
Antoine Pitroue9bb4732013-01-12 21:56:56 +0100219 self.assertRaises(OSError, ss.recv, 1)
220 self.assertRaises(OSError, ss.recv_into, bytearray(b'x'))
221 self.assertRaises(OSError, ss.recvfrom, 1)
222 self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1)
223 self.assertRaises(OSError, ss.send, b'x')
224 self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0))
Antoine Pitroua468adc2010-09-14 14:43:44 +0000225
Antoine Pitrou40f08742010-04-24 22:04:40 +0000226 def test_timeout(self):
227 # Issue #8524: when creating an SSL socket, the timeout of the
228 # original socket should be retained.
229 for timeout in (None, 0.0, 5.0):
230 s = socket.socket(socket.AF_INET)
231 s.settimeout(timeout)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100232 with ssl.wrap_socket(s) as ss:
233 self.assertEqual(timeout, ss.gettimeout())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000234
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000235 def test_errors(self):
236 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000237 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000238 "certfile must be specified",
239 ssl.wrap_socket, sock, keyfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000240 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000241 "certfile must be specified for server-side operations",
242 ssl.wrap_socket, sock, server_side=True)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000243 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000244 "certfile must be specified for server-side operations",
245 ssl.wrap_socket, sock, server_side=True, certfile="")
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100246 with ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE) as s:
247 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
248 s.connect, (HOST, 8080))
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200249 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000250 with socket.socket() as sock:
251 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000252 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200253 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000254 with socket.socket() as sock:
255 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000256 self.assertEqual(cm.exception.errno, errno.ENOENT)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200257 with self.assertRaises(OSError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000258 with socket.socket() as sock:
259 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000260 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000261
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000262 def test_match_hostname(self):
263 def ok(cert, hostname):
264 ssl.match_hostname(cert, hostname)
265 def fail(cert, hostname):
266 self.assertRaises(ssl.CertificateError,
267 ssl.match_hostname, cert, hostname)
268
269 cert = {'subject': ((('commonName', 'example.com'),),)}
270 ok(cert, 'example.com')
271 ok(cert, 'ExAmple.cOm')
272 fail(cert, 'www.example.com')
273 fail(cert, '.example.com')
274 fail(cert, 'example.org')
275 fail(cert, 'exampleXcom')
276
277 cert = {'subject': ((('commonName', '*.a.com'),),)}
278 ok(cert, 'foo.a.com')
279 fail(cert, 'bar.foo.a.com')
280 fail(cert, 'a.com')
281 fail(cert, 'Xa.com')
282 fail(cert, '.a.com')
283
284 cert = {'subject': ((('commonName', 'a.*.com'),),)}
285 ok(cert, 'a.foo.com')
286 fail(cert, 'a..com')
287 fail(cert, 'a.com')
288
289 cert = {'subject': ((('commonName', 'f*.com'),),)}
290 ok(cert, 'foo.com')
291 ok(cert, 'f.com')
292 fail(cert, 'bar.com')
293 fail(cert, 'foo.a.com')
294 fail(cert, 'bar.foo.com')
295
296 # Slightly fake real-world example
297 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
298 'subject': ((('commonName', 'linuxfrz.org'),),),
299 'subjectAltName': (('DNS', 'linuxfr.org'),
300 ('DNS', 'linuxfr.com'),
301 ('othername', '<unsupported>'))}
302 ok(cert, 'linuxfr.org')
303 ok(cert, 'linuxfr.com')
304 # Not a "DNS" entry
305 fail(cert, '<unsupported>')
306 # When there is a subjectAltName, commonName isn't used
307 fail(cert, 'linuxfrz.org')
308
309 # A pristine real-world example
310 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
311 'subject': ((('countryName', 'US'),),
312 (('stateOrProvinceName', 'California'),),
313 (('localityName', 'Mountain View'),),
314 (('organizationName', 'Google Inc'),),
315 (('commonName', 'mail.google.com'),))}
316 ok(cert, 'mail.google.com')
317 fail(cert, 'gmail.com')
318 # Only commonName is considered
319 fail(cert, 'California')
320
321 # Neither commonName nor subjectAltName
322 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
323 'subject': ((('countryName', 'US'),),
324 (('stateOrProvinceName', 'California'),),
325 (('localityName', 'Mountain View'),),
326 (('organizationName', 'Google Inc'),))}
327 fail(cert, 'mail.google.com')
328
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200329 # No DNS entry in subjectAltName but a commonName
330 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
331 'subject': ((('countryName', 'US'),),
332 (('stateOrProvinceName', 'California'),),
333 (('localityName', 'Mountain View'),),
334 (('commonName', 'mail.google.com'),)),
335 'subjectAltName': (('othername', 'blabla'), )}
336 ok(cert, 'mail.google.com')
337
338 # No DNS entry subjectAltName and no commonName
339 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
340 'subject': ((('countryName', 'US'),),
341 (('stateOrProvinceName', 'California'),),
342 (('localityName', 'Mountain View'),),
343 (('organizationName', 'Google Inc'),)),
344 'subjectAltName': (('othername', 'blabla'),)}
345 fail(cert, 'google.com')
346
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000347 # Empty cert / no cert
348 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
349 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
350
Antoine Pitroud5323212010-10-22 18:19:07 +0000351 def test_server_side(self):
352 # server_hostname doesn't work for server sockets
353 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000354 with socket.socket() as sock:
355 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
356 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000357
Antoine Pitroud6494802011-07-21 01:11:30 +0200358 def test_unknown_channel_binding(self):
359 # should raise ValueError for unknown type
360 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100361 with ssl.wrap_socket(s) as ss:
362 with self.assertRaises(ValueError):
363 ss.get_channel_binding("unknown-type")
Antoine Pitroud6494802011-07-21 01:11:30 +0200364
365 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
366 "'tls-unique' channel binding not available")
367 def test_tls_unique_channel_binding(self):
368 # unconnected should return None for known type
369 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100370 with ssl.wrap_socket(s) as ss:
371 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200372 # the same for server-side
373 s = socket.socket(socket.AF_INET)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100374 with ssl.wrap_socket(s, server_side=True, certfile=CERTFILE) as ss:
375 self.assertIsNone(ss.get_channel_binding("tls-unique"))
Antoine Pitroud6494802011-07-21 01:11:30 +0200376
Benjamin Peterson36f7b972013-01-10 14:16:20 -0600377 def test_dealloc_warn(self):
378 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
379 r = repr(ss)
380 with self.assertWarns(ResourceWarning) as cm:
381 ss = None
382 support.gc_collect()
383 self.assertIn(r, str(cm.warning.args[0]))
384
Antoine Pitrou152efa22010-05-16 18:19:27 +0000385class ContextTests(unittest.TestCase):
386
Antoine Pitrou23df4832010-08-04 17:14:06 +0000387 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000388 def test_constructor(self):
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100389 for protocol in PROTOCOLS:
390 ssl.SSLContext(protocol)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000391 self.assertRaises(TypeError, ssl.SSLContext)
392 self.assertRaises(ValueError, ssl.SSLContext, -1)
393 self.assertRaises(ValueError, ssl.SSLContext, 42)
394
Antoine Pitrou23df4832010-08-04 17:14:06 +0000395 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000396 def test_protocol(self):
397 for proto in PROTOCOLS:
398 ctx = ssl.SSLContext(proto)
399 self.assertEqual(ctx.protocol, proto)
400
401 def test_ciphers(self):
402 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
403 ctx.set_ciphers("ALL")
404 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000405 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000406 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000407
Antoine Pitrou23df4832010-08-04 17:14:06 +0000408 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000409 def test_options(self):
410 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
411 # OP_ALL is the default value
412 self.assertEqual(ssl.OP_ALL, ctx.options)
413 ctx.options |= ssl.OP_NO_SSLv2
414 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
415 ctx.options)
416 ctx.options |= ssl.OP_NO_SSLv3
417 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
418 ctx.options)
419 if can_clear_options():
420 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
421 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
422 ctx.options)
423 ctx.options = 0
424 self.assertEqual(0, ctx.options)
425 else:
426 with self.assertRaises(ValueError):
427 ctx.options = 0
428
Antoine Pitrou152efa22010-05-16 18:19:27 +0000429 def test_verify(self):
430 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
431 # Default value
432 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
433 ctx.verify_mode = ssl.CERT_OPTIONAL
434 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
435 ctx.verify_mode = ssl.CERT_REQUIRED
436 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
437 ctx.verify_mode = ssl.CERT_NONE
438 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
439 with self.assertRaises(TypeError):
440 ctx.verify_mode = None
441 with self.assertRaises(ValueError):
442 ctx.verify_mode = 42
443
444 def test_load_cert_chain(self):
445 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
446 # Combined key and cert in a single file
447 ctx.load_cert_chain(CERTFILE)
448 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
449 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200450 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000451 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000452 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000453 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000454 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000455 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000456 ctx.load_cert_chain(EMPTYCERT)
457 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000458 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000459 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
460 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
461 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000462 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000463 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000464 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000465 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000466 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000467 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
468 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000469 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000470 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000471 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200472 # Password protected key and cert
473 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
474 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
475 ctx.load_cert_chain(CERTFILE_PROTECTED,
476 password=bytearray(KEY_PASSWORD.encode()))
477 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
478 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
479 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
480 bytearray(KEY_PASSWORD.encode()))
481 with self.assertRaisesRegex(TypeError, "should be a string"):
482 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
483 with self.assertRaises(ssl.SSLError):
484 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
485 with self.assertRaisesRegex(ValueError, "cannot be longer"):
486 # openssl has a fixed limit on the password buffer.
487 # PEM_BUFSIZE is generally set to 1kb.
488 # Return a string larger than this.
489 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
490 # Password callback
491 def getpass_unicode():
492 return KEY_PASSWORD
493 def getpass_bytes():
494 return KEY_PASSWORD.encode()
495 def getpass_bytearray():
496 return bytearray(KEY_PASSWORD.encode())
497 def getpass_badpass():
498 return "badpass"
499 def getpass_huge():
500 return b'a' * (1024 * 1024)
501 def getpass_bad_type():
502 return 9
503 def getpass_exception():
504 raise Exception('getpass error')
505 class GetPassCallable:
506 def __call__(self):
507 return KEY_PASSWORD
508 def getpass(self):
509 return KEY_PASSWORD
510 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
511 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
512 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
513 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
514 ctx.load_cert_chain(CERTFILE_PROTECTED,
515 password=GetPassCallable().getpass)
516 with self.assertRaises(ssl.SSLError):
517 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
518 with self.assertRaisesRegex(ValueError, "cannot be longer"):
519 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
520 with self.assertRaisesRegex(TypeError, "must return a string"):
521 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
522 with self.assertRaisesRegex(Exception, "getpass error"):
523 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
524 # Make sure the password function isn't called if it isn't needed
525 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000526
527 def test_load_verify_locations(self):
528 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
529 ctx.load_verify_locations(CERTFILE)
530 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
531 ctx.load_verify_locations(BYTES_CERTFILE)
532 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
533 self.assertRaises(TypeError, ctx.load_verify_locations)
534 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200535 with self.assertRaises(OSError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000536 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000537 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000538 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000539 ctx.load_verify_locations(BADCERT)
540 ctx.load_verify_locations(CERTFILE, CAPATH)
541 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
542
Victor Stinner80f75e62011-01-29 11:31:20 +0000543 # Issue #10989: crash if the second argument type is invalid
544 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
545
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100546 def test_load_dh_params(self):
547 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
548 ctx.load_dh_params(DHFILE)
549 if os.name != 'nt':
550 ctx.load_dh_params(BYTES_DHFILE)
551 self.assertRaises(TypeError, ctx.load_dh_params)
552 self.assertRaises(TypeError, ctx.load_dh_params, None)
553 with self.assertRaises(FileNotFoundError) as cm:
554 ctx.load_dh_params(WRONGCERT)
555 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200556 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100557 ctx.load_dh_params(CERTFILE)
558
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000559 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000560 def test_session_stats(self):
561 for proto in PROTOCOLS:
562 ctx = ssl.SSLContext(proto)
563 self.assertEqual(ctx.session_stats(), {
564 'number': 0,
565 'connect': 0,
566 'connect_good': 0,
567 'connect_renegotiate': 0,
568 'accept': 0,
569 'accept_good': 0,
570 'accept_renegotiate': 0,
571 'hits': 0,
572 'misses': 0,
573 'timeouts': 0,
574 'cache_full': 0,
575 })
576
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000577 def test_set_default_verify_paths(self):
578 # There's not much we can do to test that it acts as expected,
579 # so just check it doesn't crash or raise an exception.
580 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
581 ctx.set_default_verify_paths()
582
Antoine Pitrou501da612011-12-21 09:27:41 +0100583 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100584 def test_set_ecdh_curve(self):
585 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
586 ctx.set_ecdh_curve("prime256v1")
587 ctx.set_ecdh_curve(b"prime256v1")
588 self.assertRaises(TypeError, ctx.set_ecdh_curve)
589 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
590 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
591 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
592
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100593 @needs_sni
594 def test_sni_callback(self):
595 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
596
597 # set_servername_callback expects a callable, or None
598 self.assertRaises(TypeError, ctx.set_servername_callback)
599 self.assertRaises(TypeError, ctx.set_servername_callback, 4)
600 self.assertRaises(TypeError, ctx.set_servername_callback, "")
601 self.assertRaises(TypeError, ctx.set_servername_callback, ctx)
602
603 def dummycallback(sock, servername, ctx):
604 pass
605 ctx.set_servername_callback(None)
606 ctx.set_servername_callback(dummycallback)
607
608 @needs_sni
609 def test_sni_callback_refcycle(self):
610 # Reference cycles through the servername callback are detected
611 # and cleared.
612 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
613 def dummycallback(sock, servername, ctx, cycle=ctx):
614 pass
615 ctx.set_servername_callback(dummycallback)
616 wr = weakref.ref(ctx)
617 del ctx, dummycallback
618 gc.collect()
619 self.assertIs(wr(), None)
620
Antoine Pitrou152efa22010-05-16 18:19:27 +0000621
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200622class SSLErrorTests(unittest.TestCase):
623
624 def test_str(self):
625 # The str() of a SSLError doesn't include the errno
626 e = ssl.SSLError(1, "foo")
627 self.assertEqual(str(e), "foo")
628 self.assertEqual(e.errno, 1)
629 # Same for a subclass
630 e = ssl.SSLZeroReturnError(1, "foo")
631 self.assertEqual(str(e), "foo")
632 self.assertEqual(e.errno, 1)
633
634 def test_lib_reason(self):
635 # Test the library and reason attributes
636 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
637 with self.assertRaises(ssl.SSLError) as cm:
638 ctx.load_dh_params(CERTFILE)
639 self.assertEqual(cm.exception.library, 'PEM')
640 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
641 s = str(cm.exception)
642 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
643
644 def test_subclass(self):
645 # Check that the appropriate SSLError subclass is raised
646 # (this only tests one of them)
647 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
648 with socket.socket() as s:
649 s.bind(("127.0.0.1", 0))
650 s.listen(5)
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100651 c = socket.socket()
652 c.connect(s.getsockname())
653 c.setblocking(False)
654 with ctx.wrap_socket(c, False, do_handshake_on_connect=False) as c:
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200655 with self.assertRaises(ssl.SSLWantReadError) as cm:
656 c.do_handshake()
657 s = str(cm.exception)
658 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
659 # For compatibility
660 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
661
662
Bill Janssen6e027db2007-11-15 22:23:56 +0000663class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000664
Antoine Pitrou480a1242010-04-28 21:37:09 +0000665 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000666 with support.transient_internet("svn.python.org"):
667 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
668 cert_reqs=ssl.CERT_NONE)
669 try:
670 s.connect(("svn.python.org", 443))
671 self.assertEqual({}, s.getpeercert())
672 finally:
673 s.close()
674
675 # this should fail because we have no verification certs
676 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
677 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000678 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
679 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000680 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000681
Antoine Pitrou350c7222010-09-09 13:31:46 +0000682 # this should succeed because we specify the root cert
683 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
684 cert_reqs=ssl.CERT_REQUIRED,
685 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
686 try:
687 s.connect(("svn.python.org", 443))
688 self.assertTrue(s.getpeercert())
689 finally:
690 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000691
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000692 def test_connect_ex(self):
693 # Issue #11326: check connect_ex() implementation
694 with support.transient_internet("svn.python.org"):
695 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
696 cert_reqs=ssl.CERT_REQUIRED,
697 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
698 try:
699 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
700 self.assertTrue(s.getpeercert())
701 finally:
702 s.close()
703
704 def test_non_blocking_connect_ex(self):
705 # Issue #11326: non-blocking connect_ex() should allow handshake
706 # to proceed after the socket gets ready.
707 with support.transient_internet("svn.python.org"):
708 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
709 cert_reqs=ssl.CERT_REQUIRED,
710 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
711 do_handshake_on_connect=False)
712 try:
713 s.setblocking(False)
714 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000715 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
716 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000717 # Wait for connect to finish
718 select.select([], [s], [], 5.0)
719 # Non-blocking handshake
720 while True:
721 try:
722 s.do_handshake()
723 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200724 except ssl.SSLWantReadError:
725 select.select([s], [], [], 5.0)
726 except ssl.SSLWantWriteError:
727 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000728 # SSL established
729 self.assertTrue(s.getpeercert())
730 finally:
731 s.close()
732
Antoine Pitroub4410db2011-05-18 18:51:06 +0200733 def test_timeout_connect_ex(self):
734 # Issue #12065: on a timeout, connect_ex() should return the original
735 # errno (mimicking the behaviour of non-SSL sockets).
736 with support.transient_internet("svn.python.org"):
737 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
738 cert_reqs=ssl.CERT_REQUIRED,
739 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
740 do_handshake_on_connect=False)
741 try:
742 s.settimeout(0.0000001)
743 rc = s.connect_ex(('svn.python.org', 443))
744 if rc == 0:
745 self.skipTest("svn.python.org responded too quickly")
746 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
747 finally:
748 s.close()
749
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100750 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100751 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100752 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
753 cert_reqs=ssl.CERT_REQUIRED,
754 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
755 try:
756 self.assertEqual(errno.ECONNREFUSED,
757 s.connect_ex(("svn.python.org", 444)))
758 finally:
759 s.close()
760
Antoine Pitrou152efa22010-05-16 18:19:27 +0000761 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000762 with support.transient_internet("svn.python.org"):
763 # Same as test_connect, but with a separately created context
764 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
765 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
766 s.connect(("svn.python.org", 443))
767 try:
768 self.assertEqual({}, s.getpeercert())
769 finally:
770 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000771 # Same with a server hostname
772 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
773 server_hostname="svn.python.org")
774 if ssl.HAS_SNI:
775 s.connect(("svn.python.org", 443))
776 s.close()
777 else:
778 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000779 # This should fail because we have no verification certs
780 ctx.verify_mode = ssl.CERT_REQUIRED
781 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000782 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000783 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000784 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000785 # This should succeed because we specify the root cert
786 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
787 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
788 s.connect(("svn.python.org", 443))
789 try:
790 cert = s.getpeercert()
791 self.assertTrue(cert)
792 finally:
793 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000794
795 def test_connect_capath(self):
796 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000797 # NOTE: the subject hashing algorithm has been changed between
798 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
799 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000800 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000801 with support.transient_internet("svn.python.org"):
802 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
803 ctx.verify_mode = ssl.CERT_REQUIRED
804 ctx.load_verify_locations(capath=CAPATH)
805 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
806 s.connect(("svn.python.org", 443))
807 try:
808 cert = s.getpeercert()
809 self.assertTrue(cert)
810 finally:
811 s.close()
812 # Same with a bytes `capath` argument
813 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
814 ctx.verify_mode = ssl.CERT_REQUIRED
815 ctx.load_verify_locations(capath=BYTES_CAPATH)
816 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
817 s.connect(("svn.python.org", 443))
818 try:
819 cert = s.getpeercert()
820 self.assertTrue(cert)
821 finally:
822 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000823
Antoine Pitroue3220242010-04-24 11:13:53 +0000824 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
825 def test_makefile_close(self):
826 # Issue #5238: creating a file-like object with makefile() shouldn't
827 # delay closing the underlying "real socket" (here tested with its
828 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000829 with support.transient_internet("svn.python.org"):
830 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
831 ss.connect(("svn.python.org", 443))
832 fd = ss.fileno()
833 f = ss.makefile()
834 f.close()
835 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000836 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000837 # Closing the SSL socket should close the fd too
838 ss.close()
839 gc.collect()
840 with self.assertRaises(OSError) as e:
841 os.read(fd, 0)
842 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000843
Antoine Pitrou480a1242010-04-28 21:37:09 +0000844 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000845 with support.transient_internet("svn.python.org"):
846 s = socket.socket(socket.AF_INET)
847 s.connect(("svn.python.org", 443))
848 s.setblocking(False)
849 s = ssl.wrap_socket(s,
850 cert_reqs=ssl.CERT_NONE,
851 do_handshake_on_connect=False)
852 count = 0
853 while True:
854 try:
855 count += 1
856 s.do_handshake()
857 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200858 except ssl.SSLWantReadError:
859 select.select([s], [], [])
860 except ssl.SSLWantWriteError:
861 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000862 s.close()
863 if support.verbose:
864 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865
Antoine Pitrou480a1242010-04-28 21:37:09 +0000866 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200867 def _test_get_server_certificate(host, port, cert=None):
868 with support.transient_internet(host):
869 pem = ssl.get_server_certificate((host, port))
870 if not pem:
871 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200872
Antoine Pitrou15399c32011-04-28 19:23:55 +0200873 try:
874 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
875 except ssl.SSLError as x:
876 #should fail
877 if support.verbose:
878 sys.stdout.write("%s\n" % x)
879 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200880 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
881
Antoine Pitrou15399c32011-04-28 19:23:55 +0200882 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
883 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200884 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000885 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200886 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000887
Antoine Pitrou15399c32011-04-28 19:23:55 +0200888 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
889 if support.IPV6_ENABLED:
890 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000891
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000892 def test_ciphers(self):
893 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000894 with support.transient_internet(remote[0]):
Antoine Pitroue1ceb502013-01-12 21:54:44 +0100895 with ssl.wrap_socket(socket.socket(socket.AF_INET),
896 cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
897 s.connect(remote)
898 with ssl.wrap_socket(socket.socket(socket.AF_INET),
899 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") as s:
900 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000901 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000902 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000903 with socket.socket(socket.AF_INET) as sock:
904 s = ssl.wrap_socket(sock,
905 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
906 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000907
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000908 def test_algorithms(self):
909 # Issue #8484: all algorithms should be available when verifying a
910 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000911 # SHA256 was added in OpenSSL 0.9.8
912 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
913 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200914 # sha256.tbs-internet.com needs SNI to use the correct certificate
915 if not ssl.HAS_SNI:
916 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000917 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
918 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000919 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000920 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200921 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
922 ctx.verify_mode = ssl.CERT_REQUIRED
923 ctx.load_verify_locations(sha256_cert)
924 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
925 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000926 try:
927 s.connect(remote)
928 if support.verbose:
929 sys.stdout.write("\nCipher with %r is %r\n" %
930 (remote, s.cipher()))
931 sys.stdout.write("Certificate is:\n%s\n" %
932 pprint.pformat(s.getpeercert()))
933 finally:
934 s.close()
935
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000936
937try:
938 import threading
939except ImportError:
940 _have_threads = False
941else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000942 _have_threads = True
943
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000944 from test.ssl_servers import make_https_server
945
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000946 class ThreadedEchoServer(threading.Thread):
947
948 class ConnectionHandler(threading.Thread):
949
950 """A mildly complicated class, because we want it to work both
951 with and without the SSL wrapper around the socket connection, so
952 that we can test the STARTTLS functionality."""
953
Bill Janssen6e027db2007-11-15 22:23:56 +0000954 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000955 self.server = server
956 self.running = False
957 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000958 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000959 self.sock.setblocking(1)
960 self.sslconn = None
961 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000962 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000963
Antoine Pitrou480a1242010-04-28 21:37:09 +0000964 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000965 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000966 self.sslconn = self.server.context.wrap_socket(
967 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100968 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Nadeem Vawdaad246bf2013-03-03 22:44:22 +0100969 except (ssl.SSLError, ConnectionResetError) as e:
970 # We treat ConnectionResetError as though it were an
971 # SSLError - OpenSSL on Ubuntu abruptly closes the
972 # connection when asked to use an unsupported protocol.
973 #
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000974 # XXX Various errors can have happened here, for example
975 # a mismatching protocol version, an invalid certificate,
976 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100977 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000979 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000980 self.running = False
981 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000982 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000983 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000985 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000986 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000987 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000988 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
989 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000990 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
992 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000993 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000994 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100995 sys.stdout.write(" server: selected protocol is now "
996 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000997 return True
998
999 def read(self):
1000 if self.sslconn:
1001 return self.sslconn.read()
1002 else:
1003 return self.sock.recv(1024)
1004
1005 def write(self, bytes):
1006 if self.sslconn:
1007 return self.sslconn.write(bytes)
1008 else:
1009 return self.sock.send(bytes)
1010
1011 def close(self):
1012 if self.sslconn:
1013 self.sslconn.close()
1014 else:
1015 self.sock.close()
1016
Antoine Pitrou480a1242010-04-28 21:37:09 +00001017 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001018 self.running = True
1019 if not self.server.starttls_server:
1020 if not self.wrap_conn():
1021 return
1022 while self.running:
1023 try:
1024 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001025 stripped = msg.strip()
1026 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001027 # eof, so quit this handler
1028 self.running = False
1029 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001030 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001031 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001032 sys.stdout.write(" server: client closed connection\n")
1033 self.close()
1034 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001035 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001036 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001037 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001038 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001039 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001040 if not self.wrap_conn():
1041 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001042 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001043 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001044 if support.verbose and self.server.connectionchatty:
1045 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001046 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001047 self.sock = self.sslconn.unwrap()
1048 self.sslconn = None
1049 if support.verbose and self.server.connectionchatty:
1050 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001051 elif stripped == b'CB tls-unique':
1052 if support.verbose and self.server.connectionchatty:
1053 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1054 data = self.sslconn.get_channel_binding("tls-unique")
1055 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001056 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001057 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001058 self.server.connectionchatty):
1059 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001060 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1061 % (msg, ctype, msg.lower(), ctype))
1062 self.write(msg.lower())
Andrew Svetlov0832af62012-12-18 23:10:48 +02001063 except OSError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001064 if self.server.chatty:
1065 handle_error("Test server failure:\n")
1066 self.close()
1067 self.running = False
1068 # normally, we'd just stop here, but for the test
1069 # harness, we want to stop the server
1070 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001071
Antoine Pitroub5218772010-05-21 09:56:06 +00001072 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001073 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001074 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001075 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001076 if context:
1077 self.context = context
1078 else:
1079 self.context = ssl.SSLContext(ssl_version
1080 if ssl_version is not None
1081 else ssl.PROTOCOL_TLSv1)
1082 self.context.verify_mode = (certreqs if certreqs is not None
1083 else ssl.CERT_NONE)
1084 if cacerts:
1085 self.context.load_verify_locations(cacerts)
1086 if certificate:
1087 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001088 if npn_protocols:
1089 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001090 if ciphers:
1091 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001092 self.chatty = chatty
1093 self.connectionchatty = connectionchatty
1094 self.starttls_server = starttls_server
1095 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001096 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001097 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001098 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001099 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001100 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001101 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001102 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001103
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001104 def __enter__(self):
1105 self.start(threading.Event())
1106 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001107 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001108
1109 def __exit__(self, *args):
1110 self.stop()
1111 self.join()
1112
Antoine Pitrou480a1242010-04-28 21:37:09 +00001113 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001114 self.flag = flag
1115 threading.Thread.start(self)
1116
Antoine Pitrou480a1242010-04-28 21:37:09 +00001117 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001118 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001119 self.sock.listen(5)
1120 self.active = True
1121 if self.flag:
1122 # signal an event
1123 self.flag.set()
1124 while self.active:
1125 try:
1126 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001127 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001128 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001129 + repr(connaddr) + '\n')
1130 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001131 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001132 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001133 except socket.timeout:
1134 pass
1135 except KeyboardInterrupt:
1136 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001137 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001138
Antoine Pitrou480a1242010-04-28 21:37:09 +00001139 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001141
Bill Janssen54cc54c2007-12-14 22:08:56 +00001142 class AsyncoreEchoServer(threading.Thread):
1143
1144 # this one's based on asyncore.dispatcher
1145
1146 class EchoServer (asyncore.dispatcher):
1147
1148 class ConnectionHandler (asyncore.dispatcher_with_send):
1149
1150 def __init__(self, conn, certfile):
1151 self.socket = ssl.wrap_socket(conn, server_side=True,
1152 certfile=certfile,
1153 do_handshake_on_connect=False)
1154 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001155 self._ssl_accepting = True
1156 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001157
1158 def readable(self):
1159 if isinstance(self.socket, ssl.SSLSocket):
1160 while self.socket.pending() > 0:
1161 self.handle_read_event()
1162 return True
1163
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001164 def _do_ssl_handshake(self):
1165 try:
1166 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001167 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1168 return
1169 except ssl.SSLEOFError:
1170 return self.handle_close()
1171 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001172 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001173 except OSError as err:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001174 if err.args[0] == errno.ECONNABORTED:
1175 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001176 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001177 self._ssl_accepting = False
1178
1179 def handle_read(self):
1180 if self._ssl_accepting:
1181 self._do_ssl_handshake()
1182 else:
1183 data = self.recv(1024)
1184 if support.verbose:
1185 sys.stdout.write(" server: read %s from client\n" % repr(data))
1186 if not data:
1187 self.close()
1188 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001189 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001190
1191 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001192 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001193 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001194 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1195
1196 def handle_error(self):
1197 raise
1198
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001199 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001200 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001201 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1202 self.port = support.bind_port(sock, '')
1203 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001204 self.listen(5)
1205
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001206 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001207 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001208 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1209 self.ConnectionHandler(sock_obj, self.certfile)
1210
1211 def handle_error(self):
1212 raise
1213
Trent Nelson78520002008-04-10 20:54:35 +00001214 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001215 self.flag = None
1216 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001217 self.server = self.EchoServer(certfile)
1218 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001219 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001220 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001221
1222 def __str__(self):
1223 return "<%s %s>" % (self.__class__.__name__, self.server)
1224
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001225 def __enter__(self):
1226 self.start(threading.Event())
1227 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001228 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001229
1230 def __exit__(self, *args):
1231 if support.verbose:
1232 sys.stdout.write(" cleanup: stopping server.\n")
1233 self.stop()
1234 if support.verbose:
1235 sys.stdout.write(" cleanup: joining server thread.\n")
1236 self.join()
1237 if support.verbose:
1238 sys.stdout.write(" cleanup: successfully joined.\n")
1239
Bill Janssen54cc54c2007-12-14 22:08:56 +00001240 def start (self, flag=None):
1241 self.flag = flag
1242 threading.Thread.start(self)
1243
Antoine Pitrou480a1242010-04-28 21:37:09 +00001244 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001245 self.active = True
1246 if self.flag:
1247 self.flag.set()
1248 while self.active:
1249 try:
1250 asyncore.loop(1)
1251 except:
1252 pass
1253
Antoine Pitrou480a1242010-04-28 21:37:09 +00001254 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001255 self.active = False
1256 self.server.close()
1257
Antoine Pitrou480a1242010-04-28 21:37:09 +00001258 def bad_cert_test(certfile):
1259 """
1260 Launch a server with CERT_REQUIRED, and check that trying to
1261 connect to it with the given client certificate fails.
1262 """
Trent Nelson78520002008-04-10 20:54:35 +00001263 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001264 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001265 cacerts=CERTFILE, chatty=False,
1266 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001267 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001268 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001269 with socket.socket() as sock:
1270 s = ssl.wrap_socket(sock,
1271 certfile=certfile,
1272 ssl_version=ssl.PROTOCOL_TLSv1)
1273 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001274 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001275 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001276 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Andrew Svetlov0832af62012-12-18 23:10:48 +02001277 except OSError as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001278 if support.verbose:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001279 sys.stdout.write("\nOSError is %s\n" % x.args[1])
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001280 except OSError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001281 if x.errno != errno.ENOENT:
1282 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001283 if support.verbose:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001284 sys.stdout.write("\OSError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001285 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001286 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001287
Antoine Pitroub5218772010-05-21 09:56:06 +00001288 def server_params_test(client_context, server_context, indata=b"FOO\n",
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001289 chatty=True, connectionchatty=False, sni_name=None):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001290 """
1291 Launch a server, connect a client to it and try various reads
1292 and writes.
1293 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001294 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001295 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001296 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001297 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001298 with server:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001299 with client_context.wrap_socket(socket.socket(),
1300 server_hostname=sni_name) as s:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001301 s.connect((HOST, server.port))
1302 for arg in [indata, bytearray(indata), memoryview(indata)]:
1303 if connectionchatty:
1304 if support.verbose:
1305 sys.stdout.write(
1306 " client: sending %r...\n" % indata)
1307 s.write(arg)
1308 outdata = s.read()
1309 if connectionchatty:
1310 if support.verbose:
1311 sys.stdout.write(" client: read %r\n" % outdata)
1312 if outdata != indata.lower():
1313 raise AssertionError(
1314 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1315 % (outdata[:20], len(outdata),
1316 indata[:20].lower(), len(indata)))
1317 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001318 if connectionchatty:
1319 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001320 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001321 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001322 'compression': s.compression(),
1323 'cipher': s.cipher(),
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01001324 'peercert': s.getpeercert(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001325 'client_npn_protocol': s.selected_npn_protocol()
1326 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001327 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001328 stats['server_npn_protocols'] = server.selected_protocols
1329 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001330
Antoine Pitroub5218772010-05-21 09:56:06 +00001331 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1332 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001333 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001334 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001335 certtype = {
1336 ssl.CERT_NONE: "CERT_NONE",
1337 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1338 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1339 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001340 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001341 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001342 sys.stdout.write(formatstr %
1343 (ssl.get_protocol_name(client_protocol),
1344 ssl.get_protocol_name(server_protocol),
1345 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001346 client_context = ssl.SSLContext(client_protocol)
1347 client_context.options = ssl.OP_ALL | client_options
1348 server_context = ssl.SSLContext(server_protocol)
1349 server_context.options = ssl.OP_ALL | server_options
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001350
1351 # NOTE: we must enable "ALL" ciphers on the client, otherwise an
1352 # SSLv23 client will send an SSLv3 hello (rather than SSLv2)
1353 # starting from OpenSSL 1.0.0 (see issue #8322).
1354 if client_context.protocol == ssl.PROTOCOL_SSLv23:
1355 client_context.set_ciphers("ALL")
1356
Antoine Pitroub5218772010-05-21 09:56:06 +00001357 for ctx in (client_context, server_context):
1358 ctx.verify_mode = certsreqs
Antoine Pitroub5218772010-05-21 09:56:06 +00001359 ctx.load_cert_chain(CERTFILE)
1360 ctx.load_verify_locations(CERTFILE)
1361 try:
1362 server_params_test(client_context, server_context,
1363 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001364 # Protocol mismatch can result in either an SSLError, or a
1365 # "Connection reset by peer" error.
1366 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001367 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001368 raise
Andrew Svetlov0832af62012-12-18 23:10:48 +02001369 except OSError as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001370 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001371 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001372 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001373 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001374 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001375 "Client protocol %s succeeded with server protocol %s!"
1376 % (ssl.get_protocol_name(client_protocol),
1377 ssl.get_protocol_name(server_protocol)))
1378
1379
Bill Janssen6e027db2007-11-15 22:23:56 +00001380 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001381
Antoine Pitrou23df4832010-08-04 17:14:06 +00001382 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001383 def test_echo(self):
1384 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001385 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001386 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001387 for protocol in PROTOCOLS:
Antoine Pitrou972d5bb2013-03-29 17:56:03 +01001388 with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
1389 context = ssl.SSLContext(protocol)
1390 context.load_cert_chain(CERTFILE)
1391 server_params_test(context, context,
1392 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001393
Antoine Pitrou480a1242010-04-28 21:37:09 +00001394 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001395 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001396 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001397 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1398 context.verify_mode = ssl.CERT_REQUIRED
1399 context.load_verify_locations(CERTFILE)
1400 context.load_cert_chain(CERTFILE)
1401 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001402 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001403 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001404 s.connect((HOST, server.port))
1405 cert = s.getpeercert()
1406 self.assertTrue(cert, "Can't get peer certificate.")
1407 cipher = s.cipher()
1408 if support.verbose:
1409 sys.stdout.write(pprint.pformat(cert) + '\n')
1410 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1411 if 'subject' not in cert:
1412 self.fail("No subject field in certificate: %s." %
1413 pprint.pformat(cert))
1414 if ((('organizationName', 'Python Software Foundation'),)
1415 not in cert['subject']):
1416 self.fail(
1417 "Missing or invalid 'organizationName' field in certificate subject; "
1418 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001419 self.assertIn('notBefore', cert)
1420 self.assertIn('notAfter', cert)
1421 before = ssl.cert_time_to_seconds(cert['notBefore'])
1422 after = ssl.cert_time_to_seconds(cert['notAfter'])
1423 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001424 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001425
Antoine Pitrou480a1242010-04-28 21:37:09 +00001426 def test_empty_cert(self):
1427 """Connecting with an empty cert file"""
1428 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1429 "nullcert.pem"))
1430 def test_malformed_cert(self):
1431 """Connecting with a badly formatted certificate (syntax error)"""
1432 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1433 "badcert.pem"))
1434 def test_nonexisting_cert(self):
1435 """Connecting with a non-existing cert file"""
1436 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1437 "wrongcert.pem"))
1438 def test_malformed_key(self):
1439 """Connecting with a badly formatted key (syntax error)"""
1440 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1441 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001442
Antoine Pitrou480a1242010-04-28 21:37:09 +00001443 def test_rude_shutdown(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001444 """A brutal shutdown of an SSL server should raise an OSError
Antoine Pitrou480a1242010-04-28 21:37:09 +00001445 in the client when attempting handshake.
1446 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001447 listener_ready = threading.Event()
1448 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001449
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001450 s = socket.socket()
1451 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001452
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001453 # `listener` runs in a thread. It sits in an accept() until
1454 # the main thread connects. Then it rudely closes the socket,
1455 # and sets Event `listener_gone` to let the main thread know
1456 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001457 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001458 s.listen(5)
1459 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001460 newsock, addr = s.accept()
1461 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001462 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001463 listener_gone.set()
1464
1465 def connector():
1466 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001467 with socket.socket() as c:
1468 c.connect((HOST, port))
1469 listener_gone.wait()
1470 try:
1471 ssl_sock = ssl.wrap_socket(c)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001472 except OSError:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001473 pass
1474 else:
1475 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001476
1477 t = threading.Thread(target=listener)
1478 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001479 try:
1480 connector()
1481 finally:
1482 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001483
Antoine Pitrou23df4832010-08-04 17:14:06 +00001484 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001485 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1486 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001487 def test_protocol_sslv2(self):
1488 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001489 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001490 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001491 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1492 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1493 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1494 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1495 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1496 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001497 # SSLv23 client with specific SSL options
1498 if no_sslv2_implies_sslv3_hello():
1499 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1500 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1501 client_options=ssl.OP_NO_SSLv2)
1502 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1503 client_options=ssl.OP_NO_SSLv3)
1504 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1505 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001506
Antoine Pitrou23df4832010-08-04 17:14:06 +00001507 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001508 def test_protocol_sslv23(self):
1509 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001510 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001511 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001512 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1513 try:
1514 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Andrew Svetlov0832af62012-12-18 23:10:48 +02001515 except OSError as x:
Victor Stinner3de49192011-05-09 00:42:58 +02001516 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1517 if support.verbose:
1518 sys.stdout.write(
1519 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1520 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001521 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1522 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1523 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001524
Antoine Pitrou480a1242010-04-28 21:37:09 +00001525 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1526 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1527 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001528
Antoine Pitrou480a1242010-04-28 21:37:09 +00001529 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1530 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1531 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001532
Antoine Pitroub5218772010-05-21 09:56:06 +00001533 # Server with specific SSL options
1534 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1535 server_options=ssl.OP_NO_SSLv3)
1536 # Will choose TLSv1
1537 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1538 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1539 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1540 server_options=ssl.OP_NO_TLSv1)
1541
1542
Antoine Pitrou23df4832010-08-04 17:14:06 +00001543 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001544 def test_protocol_sslv3(self):
1545 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001546 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001547 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001548 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1549 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1550 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001551 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1552 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001553 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1554 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001555 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001556 if no_sslv2_implies_sslv3_hello():
1557 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1558 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1559 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001560
Antoine Pitrou23df4832010-08-04 17:14:06 +00001561 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001562 def test_protocol_tlsv1(self):
1563 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001564 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001565 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001566 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1567 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1568 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001569 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1570 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001572 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1573 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001574
Antoine Pitrou2463e5f2013-03-28 22:24:43 +01001575 @skip_if_broken_ubuntu_ssl
1576 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
1577 "TLS version 1.1 not supported.")
1578 def test_protocol_tlsv1_1(self):
1579 """Connecting to a TLSv1.1 server with various client options.
1580 Testing against older TLS versions."""
1581 if support.verbose:
1582 sys.stdout.write("\n")
1583 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
1584 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1585 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
1586 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
1587 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
1588 client_options=ssl.OP_NO_TLSv1_1)
1589
1590 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
1591 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
1592 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
1593
1594
1595 @skip_if_broken_ubuntu_ssl
1596 @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
1597 "TLS version 1.2 not supported.")
1598 def test_protocol_tlsv1_2(self):
1599 """Connecting to a TLSv1.2 server with various client options.
1600 Testing against older TLS versions."""
1601 if support.verbose:
1602 sys.stdout.write("\n")
1603 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
1604 server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
1605 client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
1606 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1607 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
1608 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
1609 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
1610 client_options=ssl.OP_NO_TLSv1_2)
1611
1612 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
1613 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
1614 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
1615 try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
1616 try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
1617
Antoine Pitrou480a1242010-04-28 21:37:09 +00001618 def test_starttls(self):
1619 """Switching from clear text to encrypted and back again."""
1620 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 +00001621
Trent Nelson78520002008-04-10 20:54:35 +00001622 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001623 ssl_version=ssl.PROTOCOL_TLSv1,
1624 starttls_server=True,
1625 chatty=True,
1626 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001627 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001628 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001629 s = socket.socket()
1630 s.setblocking(1)
1631 s.connect((HOST, server.port))
1632 if support.verbose:
1633 sys.stdout.write("\n")
1634 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001635 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001636 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001637 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001638 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001639 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001640 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001641 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001642 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001643 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001644 msg = outdata.strip().lower()
1645 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1646 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001647 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001648 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001649 " client: read %r from server, starting TLS...\n"
1650 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001651 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1652 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001653 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1654 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001655 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001656 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001657 " client: read %r from server, ending TLS...\n"
1658 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001659 s = conn.unwrap()
1660 wrapped = False
1661 else:
1662 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001663 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001664 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001665 if support.verbose:
1666 sys.stdout.write(" client: closing connection.\n")
1667 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001668 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001669 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001670 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001671 if wrapped:
1672 conn.close()
1673 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001674 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001675
Antoine Pitrou480a1242010-04-28 21:37:09 +00001676 def test_socketserver(self):
1677 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrouda232592013-02-05 21:20:51 +01001678 server = make_https_server(self, certfile=CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001679 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001680 if support.verbose:
1681 sys.stdout.write('\n')
1682 with open(CERTFILE, 'rb') as f:
1683 d1 = f.read()
1684 d2 = ''
1685 # now fetch the same data from the HTTPS server
1686 url = 'https://%s:%d/%s' % (
1687 HOST, server.port, os.path.split(CERTFILE)[1])
1688 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001689 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001690 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001691 if dlen and (int(dlen) > 0):
1692 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001693 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001694 sys.stdout.write(
1695 " client: read %d bytes from remote server '%s'\n"
1696 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001697 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001698 f.close()
1699 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001700
Antoine Pitrou480a1242010-04-28 21:37:09 +00001701 def test_asyncore_server(self):
1702 """Check the example asyncore integration."""
1703 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001704
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001705 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001706 sys.stdout.write("\n")
1707
Antoine Pitrou480a1242010-04-28 21:37:09 +00001708 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001709 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001710 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001711 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001712 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001713 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001714 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001715 " client: sending %r...\n" % indata)
1716 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001717 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001718 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001719 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001720 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001721 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001722 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1723 % (outdata[:20], len(outdata),
1724 indata[:20].lower(), len(indata)))
1725 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001726 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001727 sys.stdout.write(" client: closing connection.\n")
1728 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001729 if support.verbose:
1730 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001731
Antoine Pitrou480a1242010-04-28 21:37:09 +00001732 def test_recv_send(self):
1733 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001734 if support.verbose:
1735 sys.stdout.write("\n")
1736
1737 server = ThreadedEchoServer(CERTFILE,
1738 certreqs=ssl.CERT_NONE,
1739 ssl_version=ssl.PROTOCOL_TLSv1,
1740 cacerts=CERTFILE,
1741 chatty=True,
1742 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001743 with server:
1744 s = ssl.wrap_socket(socket.socket(),
1745 server_side=False,
1746 certfile=CERTFILE,
1747 ca_certs=CERTFILE,
1748 cert_reqs=ssl.CERT_NONE,
1749 ssl_version=ssl.PROTOCOL_TLSv1)
1750 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001751 # helper methods for standardising recv* method signatures
1752 def _recv_into():
1753 b = bytearray(b"\0"*100)
1754 count = s.recv_into(b)
1755 return b[:count]
1756
1757 def _recvfrom_into():
1758 b = bytearray(b"\0"*100)
1759 count, addr = s.recvfrom_into(b)
1760 return b[:count]
1761
1762 # (name, method, whether to expect success, *args)
1763 send_methods = [
1764 ('send', s.send, True, []),
1765 ('sendto', s.sendto, False, ["some.address"]),
1766 ('sendall', s.sendall, True, []),
1767 ]
1768 recv_methods = [
1769 ('recv', s.recv, True, []),
1770 ('recvfrom', s.recvfrom, False, ["some.address"]),
1771 ('recv_into', _recv_into, True, []),
1772 ('recvfrom_into', _recvfrom_into, False, []),
1773 ]
1774 data_prefix = "PREFIX_"
1775
1776 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001777 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001778 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001779 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001780 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001781 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001782 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001783 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001784 "<<{outdata:r}>> ({nout:d}) received; "
1785 "expected <<{indata:r}>> ({nin:d})\n".format(
1786 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001787 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001788 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001789 )
1790 )
1791 except ValueError as e:
1792 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001793 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001794 "Failed to send with method <<{name:s}>>; "
1795 "expected to succeed.\n".format(name=meth_name)
1796 )
1797 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001798 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001799 "Method <<{name:s}>> failed with unexpected "
1800 "exception message: {exp:s}\n".format(
1801 name=meth_name, exp=e
1802 )
1803 )
1804
1805 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001806 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001807 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001808 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001809 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001810 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001811 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001812 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001813 "<<{outdata:r}>> ({nout:d}) received; "
1814 "expected <<{indata:r}>> ({nin:d})\n".format(
1815 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001816 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001817 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001818 )
1819 )
1820 except ValueError as e:
1821 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001822 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001823 "Failed to receive with method <<{name:s}>>; "
1824 "expected to succeed.\n".format(name=meth_name)
1825 )
1826 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001827 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001828 "Method <<{name:s}>> failed with unexpected "
1829 "exception message: {exp:s}\n".format(
1830 name=meth_name, exp=e
1831 )
1832 )
1833 # consume data
1834 s.read()
1835
Nick Coghlan513886a2011-08-28 00:00:27 +10001836 # Make sure sendmsg et al are disallowed to avoid
1837 # inadvertent disclosure of data and/or corruption
1838 # of the encrypted data stream
1839 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1840 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1841 self.assertRaises(NotImplementedError,
1842 s.recvmsg_into, bytearray(100))
1843
Antoine Pitrou480a1242010-04-28 21:37:09 +00001844 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001845 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001846
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001847 def test_handshake_timeout(self):
1848 # Issue #5103: SSL handshake must respect the socket timeout
1849 server = socket.socket(socket.AF_INET)
1850 host = "127.0.0.1"
1851 port = support.bind_port(server)
1852 started = threading.Event()
1853 finish = False
1854
1855 def serve():
1856 server.listen(5)
1857 started.set()
1858 conns = []
1859 while not finish:
1860 r, w, e = select.select([server], [], [], 0.1)
1861 if server in r:
1862 # Let the socket hang around rather than having
1863 # it closed by garbage collection.
1864 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001865 for sock in conns:
1866 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001867
1868 t = threading.Thread(target=serve)
1869 t.start()
1870 started.wait()
1871
1872 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001873 try:
1874 c = socket.socket(socket.AF_INET)
1875 c.settimeout(0.2)
1876 c.connect((host, port))
1877 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001878 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001879 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001880 finally:
1881 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001882 try:
1883 c = socket.socket(socket.AF_INET)
1884 c = ssl.wrap_socket(c)
1885 c.settimeout(0.2)
1886 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001887 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001888 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001889 finally:
1890 c.close()
1891 finally:
1892 finish = True
1893 t.join()
1894 server.close()
1895
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001896 def test_server_accept(self):
1897 # Issue #16357: accept() on a SSLSocket created through
1898 # SSLContext.wrap_socket().
1899 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1900 context.verify_mode = ssl.CERT_REQUIRED
1901 context.load_verify_locations(CERTFILE)
1902 context.load_cert_chain(CERTFILE)
1903 server = socket.socket(socket.AF_INET)
1904 host = "127.0.0.1"
1905 port = support.bind_port(server)
1906 server = context.wrap_socket(server, server_side=True)
1907
1908 evt = threading.Event()
1909 remote = None
1910 peer = None
1911 def serve():
1912 nonlocal remote, peer
1913 server.listen(5)
1914 # Block on the accept and wait on the connection to close.
1915 evt.set()
1916 remote, peer = server.accept()
1917 remote.recv(1)
1918
1919 t = threading.Thread(target=serve)
1920 t.start()
1921 # Client wait until server setup and perform a connect.
1922 evt.wait()
1923 client = context.wrap_socket(socket.socket())
1924 client.connect((host, port))
1925 client_addr = client.getsockname()
1926 client.close()
1927 t.join()
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001928 remote.close()
1929 server.close()
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001930 # Sanity checks.
1931 self.assertIsInstance(remote, ssl.SSLSocket)
1932 self.assertEqual(peer, client_addr)
1933
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001934 def test_default_ciphers(self):
1935 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1936 try:
1937 # Force a set of weak ciphers on our client context
1938 context.set_ciphers("DES")
1939 except ssl.SSLError:
1940 self.skipTest("no DES cipher available")
1941 with ThreadedEchoServer(CERTFILE,
1942 ssl_version=ssl.PROTOCOL_SSLv23,
1943 chatty=False) as server:
Antoine Pitroue1ceb502013-01-12 21:54:44 +01001944 with context.wrap_socket(socket.socket()) as s:
Andrew Svetlov0832af62012-12-18 23:10:48 +02001945 with self.assertRaises(OSError):
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001946 s.connect((HOST, server.port))
1947 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1948
Antoine Pitroud6494802011-07-21 01:11:30 +02001949 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1950 "'tls-unique' channel binding not available")
1951 def test_tls_unique_channel_binding(self):
1952 """Test tls-unique channel binding."""
1953 if support.verbose:
1954 sys.stdout.write("\n")
1955
1956 server = ThreadedEchoServer(CERTFILE,
1957 certreqs=ssl.CERT_NONE,
1958 ssl_version=ssl.PROTOCOL_TLSv1,
1959 cacerts=CERTFILE,
1960 chatty=True,
1961 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001962 with server:
1963 s = ssl.wrap_socket(socket.socket(),
1964 server_side=False,
1965 certfile=CERTFILE,
1966 ca_certs=CERTFILE,
1967 cert_reqs=ssl.CERT_NONE,
1968 ssl_version=ssl.PROTOCOL_TLSv1)
1969 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001970 # get the data
1971 cb_data = s.get_channel_binding("tls-unique")
1972 if support.verbose:
1973 sys.stdout.write(" got channel binding data: {0!r}\n"
1974 .format(cb_data))
1975
1976 # check if it is sane
1977 self.assertIsNotNone(cb_data)
1978 self.assertEqual(len(cb_data), 12) # True for TLSv1
1979
1980 # and compare with the peers version
1981 s.write(b"CB tls-unique\n")
1982 peer_data_repr = s.read().strip()
1983 self.assertEqual(peer_data_repr,
1984 repr(cb_data).encode("us-ascii"))
1985 s.close()
1986
1987 # now, again
1988 s = ssl.wrap_socket(socket.socket(),
1989 server_side=False,
1990 certfile=CERTFILE,
1991 ca_certs=CERTFILE,
1992 cert_reqs=ssl.CERT_NONE,
1993 ssl_version=ssl.PROTOCOL_TLSv1)
1994 s.connect((HOST, server.port))
1995 new_cb_data = s.get_channel_binding("tls-unique")
1996 if support.verbose:
1997 sys.stdout.write(" got another channel binding data: {0!r}\n"
1998 .format(new_cb_data))
1999 # is it really unique
2000 self.assertNotEqual(cb_data, new_cb_data)
2001 self.assertIsNotNone(cb_data)
2002 self.assertEqual(len(cb_data), 12) # True for TLSv1
2003 s.write(b"CB tls-unique\n")
2004 peer_data_repr = s.read().strip()
2005 self.assertEqual(peer_data_repr,
2006 repr(new_cb_data).encode("us-ascii"))
2007 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00002008
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002009 def test_compression(self):
2010 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2011 context.load_cert_chain(CERTFILE)
2012 stats = server_params_test(context, context,
2013 chatty=True, connectionchatty=True)
2014 if support.verbose:
2015 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
2016 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
2017
2018 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
2019 "ssl.OP_NO_COMPRESSION needed for this test")
2020 def test_compression_disabled(self):
2021 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2022 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01002023 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002024 stats = server_params_test(context, context,
2025 chatty=True, connectionchatty=True)
2026 self.assertIs(stats['compression'], None)
2027
Antoine Pitrou0e576f12011-12-22 10:03:38 +01002028 def test_dh_params(self):
2029 # Check we can get a connection with ephemeral Diffie-Hellman
2030 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2031 context.load_cert_chain(CERTFILE)
2032 context.load_dh_params(DHFILE)
2033 context.set_ciphers("kEDH")
2034 stats = server_params_test(context, context,
2035 chatty=True, connectionchatty=True)
2036 cipher = stats["cipher"][0]
2037 parts = cipher.split("-")
2038 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
2039 self.fail("Non-DH cipher: " + cipher[0])
2040
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01002041 def test_selected_npn_protocol(self):
2042 # selected_npn_protocol() is None unless NPN is used
2043 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2044 context.load_cert_chain(CERTFILE)
2045 stats = server_params_test(context, context,
2046 chatty=True, connectionchatty=True)
2047 self.assertIs(stats['client_npn_protocol'], None)
2048
2049 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
2050 def test_npn_protocols(self):
2051 server_protocols = ['http/1.1', 'spdy/2']
2052 protocol_tests = [
2053 (['http/1.1', 'spdy/2'], 'http/1.1'),
2054 (['spdy/2', 'http/1.1'], 'http/1.1'),
2055 (['spdy/2', 'test'], 'spdy/2'),
2056 (['abc', 'def'], 'abc')
2057 ]
2058 for client_protocols, expected in protocol_tests:
2059 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2060 server_context.load_cert_chain(CERTFILE)
2061 server_context.set_npn_protocols(server_protocols)
2062 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2063 client_context.load_cert_chain(CERTFILE)
2064 client_context.set_npn_protocols(client_protocols)
2065 stats = server_params_test(client_context, server_context,
2066 chatty=True, connectionchatty=True)
2067
2068 msg = "failed trying %s (s) and %s (c).\n" \
2069 "was expecting %s, but got %%s from the %%s" \
2070 % (str(server_protocols), str(client_protocols),
2071 str(expected))
2072 client_result = stats['client_npn_protocol']
2073 self.assertEqual(client_result, expected, msg % (client_result, "client"))
2074 server_result = stats['server_npn_protocols'][-1] \
2075 if len(stats['server_npn_protocols']) else 'nothing'
2076 self.assertEqual(server_result, expected, msg % (server_result, "server"))
2077
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002078 def sni_contexts(self):
2079 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2080 server_context.load_cert_chain(SIGNED_CERTFILE)
2081 other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2082 other_context.load_cert_chain(SIGNED_CERTFILE2)
2083 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
2084 client_context.verify_mode = ssl.CERT_REQUIRED
2085 client_context.load_verify_locations(SIGNING_CA)
2086 return server_context, other_context, client_context
2087
2088 def check_common_name(self, stats, name):
2089 cert = stats['peercert']
2090 self.assertIn((('commonName', name),), cert['subject'])
2091
2092 @needs_sni
2093 def test_sni_callback(self):
2094 calls = []
2095 server_context, other_context, client_context = self.sni_contexts()
2096
2097 def servername_cb(ssl_sock, server_name, initial_context):
2098 calls.append((server_name, initial_context))
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002099 if server_name is not None:
2100 ssl_sock.context = other_context
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002101 server_context.set_servername_callback(servername_cb)
2102
2103 stats = server_params_test(client_context, server_context,
2104 chatty=True,
2105 sni_name='supermessage')
2106 # The hostname was fetched properly, and the certificate was
2107 # changed for the connection.
2108 self.assertEqual(calls, [("supermessage", server_context)])
2109 # CERTFILE4 was selected
2110 self.check_common_name(stats, 'fakehostname')
2111
Antoine Pitrou50b24d02013-04-11 20:48:42 +02002112 calls = []
2113 # The callback is called with server_name=None
2114 stats = server_params_test(client_context, server_context,
2115 chatty=True,
2116 sni_name=None)
2117 self.assertEqual(calls, [(None, server_context)])
2118 self.check_common_name(stats, 'localhost')
2119
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002120 # Check disabling the callback
2121 calls = []
2122 server_context.set_servername_callback(None)
2123
2124 stats = server_params_test(client_context, server_context,
2125 chatty=True,
2126 sni_name='notfunny')
2127 # Certificate didn't change
2128 self.check_common_name(stats, 'localhost')
2129 self.assertEqual(calls, [])
2130
2131 @needs_sni
2132 def test_sni_callback_alert(self):
2133 # Returning a TLS alert is reflected to the connecting client
2134 server_context, other_context, client_context = self.sni_contexts()
2135
2136 def cb_returning_alert(ssl_sock, server_name, initial_context):
2137 return ssl.ALERT_DESCRIPTION_ACCESS_DENIED
2138 server_context.set_servername_callback(cb_returning_alert)
2139
2140 with self.assertRaises(ssl.SSLError) as cm:
2141 stats = server_params_test(client_context, server_context,
2142 chatty=False,
2143 sni_name='supermessage')
2144 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED')
2145
2146 @needs_sni
2147 def test_sni_callback_raising(self):
2148 # Raising fails the connection with a TLS handshake failure alert.
2149 server_context, other_context, client_context = self.sni_contexts()
2150
2151 def cb_raising(ssl_sock, server_name, initial_context):
2152 1/0
2153 server_context.set_servername_callback(cb_raising)
2154
2155 with self.assertRaises(ssl.SSLError) as cm, \
2156 support.captured_stderr() as stderr:
2157 stats = server_params_test(client_context, server_context,
2158 chatty=False,
2159 sni_name='supermessage')
2160 self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE')
2161 self.assertIn("ZeroDivisionError", stderr.getvalue())
2162
2163 @needs_sni
2164 def test_sni_callback_wrong_return_type(self):
2165 # Returning the wrong return type terminates the TLS connection
2166 # with an internal error alert.
2167 server_context, other_context, client_context = self.sni_contexts()
2168
2169 def cb_wrong_return_type(ssl_sock, server_name, initial_context):
2170 return "foo"
2171 server_context.set_servername_callback(cb_wrong_return_type)
2172
2173 with self.assertRaises(ssl.SSLError) as cm, \
2174 support.captured_stderr() as stderr:
2175 stats = server_params_test(client_context, server_context,
2176 chatty=False,
2177 sni_name='supermessage')
2178 self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR')
2179 self.assertIn("TypeError", stderr.getvalue())
2180
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01002181
Thomas Woutersed03b412007-08-28 21:37:11 +00002182def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002183 if support.verbose:
2184 plats = {
2185 'Linux': platform.linux_distribution,
2186 'Mac': platform.mac_ver,
2187 'Windows': platform.win32_ver,
2188 }
2189 for name, func in plats.items():
2190 plat = func()
2191 if plat and plat[0]:
2192 plat = '%s %r' % (name, plat)
2193 break
2194 else:
2195 plat = repr(platform.platform())
2196 print("test_ssl: testing with %r %r" %
2197 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2198 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002199 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou609ef012013-03-29 18:09:06 +01002200 print(" OP_ALL = 0x%8x" % ssl.OP_ALL)
2201 try:
2202 print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1)
2203 except AttributeError:
2204 pass
Antoine Pitrou15cee622010-08-04 16:45:21 +00002205
Antoine Pitrou152efa22010-05-16 18:19:27 +00002206 for filename in [
2207 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2208 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +01002209 SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
Antoine Pitrou152efa22010-05-16 18:19:27 +00002210 BADCERT, BADKEY, EMPTYCERT]:
2211 if not os.path.exists(filename):
2212 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002213
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002214 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002215
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002216 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002217 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002218
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002219 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002220 thread_info = support.threading_setup()
Antoine Pitroudb5012a2013-01-12 22:00:09 +01002221 if thread_info:
Bill Janssen6e027db2007-11-15 22:23:56 +00002222 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002223
Antoine Pitrou480a1242010-04-28 21:37:09 +00002224 try:
2225 support.run_unittest(*tests)
2226 finally:
2227 if _have_threads:
2228 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002229
2230if __name__ == "__main__":
2231 test_main()