blob: 2f63eaa110069f294a2308bf8dfeae44a52cca28 [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
23PROTOCOLS = [
Victor Stinner3de49192011-05-09 00:42:58 +020024 ssl.PROTOCOL_SSLv3,
Antoine Pitrou05d936d2010-10-13 11:38:36 +000025 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Victor Stinner3de49192011-05-09 00:42:58 +020027if hasattr(ssl, 'PROTOCOL_SSLv2'):
28 PROTOCOLS.append(ssl.PROTOCOL_SSLv2)
Thomas Woutersed03b412007-08-28 21:37:11 +000029
Benjamin Petersonee8712c2008-05-20 21:35:26 +000030HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000031
32data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000033
Antoine Pitrou81564092010-10-08 23:06:24 +000034# The custom key and certificate files used in test_ssl are generated
35# using Lib/test/make_ssl_certs.py.
36# Other certificates are simply fetched from the Internet servers they
37# are meant to authenticate.
38
Antoine Pitrou152efa22010-05-16 18:19:27 +000039CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000040BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000041ONLYCERT = data_file("ssl_cert.pem")
42ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000043BYTES_ONLYCERT = os.fsencode(ONLYCERT)
44BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +020045CERTFILE_PROTECTED = data_file("keycert.passwd.pem")
46ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem")
47KEY_PASSWORD = "somepass"
Antoine Pitrou152efa22010-05-16 18:19:27 +000048CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000049BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000050
51SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
52
53EMPTYCERT = data_file("nullcert.pem")
54BADCERT = data_file("badcert.pem")
55WRONGCERT = data_file("XXXnonexisting.pem")
56BADKEY = data_file("badkey.pem")
Antoine Pitroud8c347a2011-10-01 19:20:25 +020057NOKIACERT = data_file("nokia.pem")
Antoine Pitrou152efa22010-05-16 18:19:27 +000058
Antoine Pitrou0e576f12011-12-22 10:03:38 +010059DHFILE = data_file("dh512.pem")
60BYTES_DHFILE = os.fsencode(DHFILE)
Thomas Woutersed03b412007-08-28 21:37:11 +000061
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
92
Antoine Pitrou152efa22010-05-16 18:19:27 +000093class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000094
Antoine Pitrou480a1242010-04-28 21:37:09 +000095 def test_constants(self):
Victor Stinner3de49192011-05-09 00:42:58 +020096 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000097 ssl.PROTOCOL_SSLv23
98 ssl.PROTOCOL_SSLv3
99 ssl.PROTOCOL_TLSv1
100 ssl.CERT_NONE
101 ssl.CERT_OPTIONAL
102 ssl.CERT_REQUIRED
Antoine Pitrou6db49442011-12-19 13:27:11 +0100103 ssl.OP_CIPHER_SERVER_PREFERENCE
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100104 ssl.OP_SINGLE_DH_USE
Antoine Pitrouc135fa42012-02-19 21:22:39 +0100105 if ssl.HAS_ECDH:
106 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100107 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
108 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000109 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100110 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000111
Antoine Pitrou480a1242010-04-28 21:37:09 +0000112 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000113 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 sys.stdout.write("\n RAND_status is %d (%s)\n"
116 % (v, (v and "sufficient randomness") or
117 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200118
119 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
120 self.assertEqual(len(data), 16)
121 self.assertEqual(is_cryptographic, v == 1)
122 if v:
123 data = ssl.RAND_bytes(16)
124 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200125 else:
126 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200127
Jesus Ceac8754a12012-09-11 02:00:58 +0200128 self.assertRaises(TypeError, ssl.RAND_egd, 1)
129 self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000130 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000131
Antoine Pitrou480a1242010-04-28 21:37:09 +0000132 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000133 # note that this uses an 'unofficial' function in _ssl.c,
134 # provided solely for this test, to exercise the certificate
135 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000136 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000137 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200139 self.assertEqual(p['issuer'],
140 ((('countryName', 'XY'),),
141 (('localityName', 'Castle Anthrax'),),
142 (('organizationName', 'Python Software Foundation'),),
143 (('commonName', 'localhost'),))
144 )
145 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
146 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
147 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
148 self.assertEqual(p['subject'],
149 ((('countryName', 'XY'),),
150 (('localityName', 'Castle Anthrax'),),
151 (('organizationName', 'Python Software Foundation'),),
152 (('commonName', 'localhost'),))
153 )
154 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
155 # Issue #13034: the subjectAltName in some certificates
156 # (notably projects.developer.nokia.com:443) wasn't parsed
157 p = ssl._ssl._test_decode_cert(NOKIACERT)
158 if support.verbose:
159 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
160 self.assertEqual(p['subjectAltName'],
161 (('DNS', 'projects.developer.nokia.com'),
162 ('DNS', 'projects.forum.nokia.com'))
163 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000164
Antoine Pitrou480a1242010-04-28 21:37:09 +0000165 def test_DER_to_PEM(self):
166 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
167 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000168 d1 = ssl.PEM_cert_to_DER_cert(pem)
169 p2 = ssl.DER_cert_to_PEM_cert(d1)
170 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000171 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000172 if not p2.startswith(ssl.PEM_HEADER + '\n'):
173 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
174 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
175 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000176
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000177 def test_openssl_version(self):
178 n = ssl.OPENSSL_VERSION_NUMBER
179 t = ssl.OPENSSL_VERSION_INFO
180 s = ssl.OPENSSL_VERSION
181 self.assertIsInstance(n, int)
182 self.assertIsInstance(t, tuple)
183 self.assertIsInstance(s, str)
184 # Some sanity checks follow
185 # >= 0.9
186 self.assertGreaterEqual(n, 0x900000)
187 # < 2.0
188 self.assertLess(n, 0x20000000)
189 major, minor, fix, patch, status = t
190 self.assertGreaterEqual(major, 0)
191 self.assertLess(major, 2)
192 self.assertGreaterEqual(minor, 0)
193 self.assertLess(minor, 256)
194 self.assertGreaterEqual(fix, 0)
195 self.assertLess(fix, 256)
196 self.assertGreaterEqual(patch, 0)
197 self.assertLessEqual(patch, 26)
198 self.assertGreaterEqual(status, 0)
199 self.assertLessEqual(status, 15)
200 # Version string as returned by OpenSSL, the format might change
201 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
202 (s, t))
203
Antoine Pitrou9d543662010-04-23 23:10:32 +0000204 @support.cpython_only
205 def test_refcycle(self):
206 # Issue #7943: an SSL object doesn't create reference cycles with
207 # itself.
208 s = socket.socket(socket.AF_INET)
209 ss = ssl.wrap_socket(s)
210 wr = weakref.ref(ss)
211 del ss
212 self.assertEqual(wr(), None)
213
Antoine Pitroua468adc2010-09-14 14:43:44 +0000214 def test_wrapped_unconnected(self):
215 # Methods on an unconnected SSLSocket propagate the original
216 # socket.error raise by the underlying socket object.
217 s = socket.socket(socket.AF_INET)
218 ss = ssl.wrap_socket(s)
219 self.assertRaises(socket.error, ss.recv, 1)
220 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
221 self.assertRaises(socket.error, ss.recvfrom, 1)
222 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
223 self.assertRaises(socket.error, ss.send, b'x')
224 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
225
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)
232 ss = ssl.wrap_socket(s)
233 self.assertEqual(timeout, ss.gettimeout())
234
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="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000246 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000247 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000248 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000249 with self.assertRaises(IOError) 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)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000253 with self.assertRaises(IOError) 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)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000257 with self.assertRaises(IOError) 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)
361 ss = ssl.wrap_socket(s)
362 with self.assertRaises(ValueError):
363 ss.get_channel_binding("unknown-type")
364
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)
370 ss = ssl.wrap_socket(s)
371 self.assertIsNone(ss.get_channel_binding("tls-unique"))
372 # the same for server-side
373 s = socket.socket(socket.AF_INET)
374 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
375 self.assertIsNone(ss.get_channel_binding("tls-unique"))
376
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):
Victor Stinner3de49192011-05-09 00:42:58 +0200389 if hasattr(ssl, 'PROTOCOL_SSLv2'):
390 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000391 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
392 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
393 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
394 self.assertRaises(TypeError, ssl.SSLContext)
395 self.assertRaises(ValueError, ssl.SSLContext, -1)
396 self.assertRaises(ValueError, ssl.SSLContext, 42)
397
Antoine Pitrou23df4832010-08-04 17:14:06 +0000398 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000399 def test_protocol(self):
400 for proto in PROTOCOLS:
401 ctx = ssl.SSLContext(proto)
402 self.assertEqual(ctx.protocol, proto)
403
404 def test_ciphers(self):
405 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
406 ctx.set_ciphers("ALL")
407 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000408 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000409 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000410
Antoine Pitrou23df4832010-08-04 17:14:06 +0000411 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000412 def test_options(self):
413 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
414 # OP_ALL is the default value
415 self.assertEqual(ssl.OP_ALL, ctx.options)
416 ctx.options |= ssl.OP_NO_SSLv2
417 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
418 ctx.options)
419 ctx.options |= ssl.OP_NO_SSLv3
420 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
421 ctx.options)
422 if can_clear_options():
423 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
424 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
425 ctx.options)
426 ctx.options = 0
427 self.assertEqual(0, ctx.options)
428 else:
429 with self.assertRaises(ValueError):
430 ctx.options = 0
431
Antoine Pitrou152efa22010-05-16 18:19:27 +0000432 def test_verify(self):
433 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
434 # Default value
435 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
436 ctx.verify_mode = ssl.CERT_OPTIONAL
437 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
438 ctx.verify_mode = ssl.CERT_REQUIRED
439 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
440 ctx.verify_mode = ssl.CERT_NONE
441 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
442 with self.assertRaises(TypeError):
443 ctx.verify_mode = None
444 with self.assertRaises(ValueError):
445 ctx.verify_mode = 42
446
447 def test_load_cert_chain(self):
448 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
449 # Combined key and cert in a single file
450 ctx.load_cert_chain(CERTFILE)
451 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
452 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000453 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000454 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000455 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000456 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000457 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000458 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000459 ctx.load_cert_chain(EMPTYCERT)
460 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000461 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000462 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
463 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
464 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000465 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000466 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000467 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000468 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000469 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000470 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
471 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000472 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000473 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000474 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200475 # Password protected key and cert
476 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
477 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
478 ctx.load_cert_chain(CERTFILE_PROTECTED,
479 password=bytearray(KEY_PASSWORD.encode()))
480 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
481 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
482 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
483 bytearray(KEY_PASSWORD.encode()))
484 with self.assertRaisesRegex(TypeError, "should be a string"):
485 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
486 with self.assertRaises(ssl.SSLError):
487 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
488 with self.assertRaisesRegex(ValueError, "cannot be longer"):
489 # openssl has a fixed limit on the password buffer.
490 # PEM_BUFSIZE is generally set to 1kb.
491 # Return a string larger than this.
492 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
493 # Password callback
494 def getpass_unicode():
495 return KEY_PASSWORD
496 def getpass_bytes():
497 return KEY_PASSWORD.encode()
498 def getpass_bytearray():
499 return bytearray(KEY_PASSWORD.encode())
500 def getpass_badpass():
501 return "badpass"
502 def getpass_huge():
503 return b'a' * (1024 * 1024)
504 def getpass_bad_type():
505 return 9
506 def getpass_exception():
507 raise Exception('getpass error')
508 class GetPassCallable:
509 def __call__(self):
510 return KEY_PASSWORD
511 def getpass(self):
512 return KEY_PASSWORD
513 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
514 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
515 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
516 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
517 ctx.load_cert_chain(CERTFILE_PROTECTED,
518 password=GetPassCallable().getpass)
519 with self.assertRaises(ssl.SSLError):
520 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
521 with self.assertRaisesRegex(ValueError, "cannot be longer"):
522 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
523 with self.assertRaisesRegex(TypeError, "must return a string"):
524 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
525 with self.assertRaisesRegex(Exception, "getpass error"):
526 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
527 # Make sure the password function isn't called if it isn't needed
528 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000529
530 def test_load_verify_locations(self):
531 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
532 ctx.load_verify_locations(CERTFILE)
533 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
534 ctx.load_verify_locations(BYTES_CERTFILE)
535 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
536 self.assertRaises(TypeError, ctx.load_verify_locations)
537 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000538 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000539 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000540 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000541 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000542 ctx.load_verify_locations(BADCERT)
543 ctx.load_verify_locations(CERTFILE, CAPATH)
544 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
545
Victor Stinner80f75e62011-01-29 11:31:20 +0000546 # Issue #10989: crash if the second argument type is invalid
547 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
548
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100549 def test_load_dh_params(self):
550 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
551 ctx.load_dh_params(DHFILE)
552 if os.name != 'nt':
553 ctx.load_dh_params(BYTES_DHFILE)
554 self.assertRaises(TypeError, ctx.load_dh_params)
555 self.assertRaises(TypeError, ctx.load_dh_params, None)
556 with self.assertRaises(FileNotFoundError) as cm:
557 ctx.load_dh_params(WRONGCERT)
558 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200559 with self.assertRaises(ssl.SSLError) as cm:
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100560 ctx.load_dh_params(CERTFILE)
561
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000562 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000563 def test_session_stats(self):
564 for proto in PROTOCOLS:
565 ctx = ssl.SSLContext(proto)
566 self.assertEqual(ctx.session_stats(), {
567 'number': 0,
568 'connect': 0,
569 'connect_good': 0,
570 'connect_renegotiate': 0,
571 'accept': 0,
572 'accept_good': 0,
573 'accept_renegotiate': 0,
574 'hits': 0,
575 'misses': 0,
576 'timeouts': 0,
577 'cache_full': 0,
578 })
579
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000580 def test_set_default_verify_paths(self):
581 # There's not much we can do to test that it acts as expected,
582 # so just check it doesn't crash or raise an exception.
583 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
584 ctx.set_default_verify_paths()
585
Antoine Pitrou501da612011-12-21 09:27:41 +0100586 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100587 def test_set_ecdh_curve(self):
588 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
589 ctx.set_ecdh_curve("prime256v1")
590 ctx.set_ecdh_curve(b"prime256v1")
591 self.assertRaises(TypeError, ctx.set_ecdh_curve)
592 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
593 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
594 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
595
Antoine Pitrou152efa22010-05-16 18:19:27 +0000596
Antoine Pitrou3b36fb12012-06-22 21:11:52 +0200597class SSLErrorTests(unittest.TestCase):
598
599 def test_str(self):
600 # The str() of a SSLError doesn't include the errno
601 e = ssl.SSLError(1, "foo")
602 self.assertEqual(str(e), "foo")
603 self.assertEqual(e.errno, 1)
604 # Same for a subclass
605 e = ssl.SSLZeroReturnError(1, "foo")
606 self.assertEqual(str(e), "foo")
607 self.assertEqual(e.errno, 1)
608
609 def test_lib_reason(self):
610 # Test the library and reason attributes
611 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
612 with self.assertRaises(ssl.SSLError) as cm:
613 ctx.load_dh_params(CERTFILE)
614 self.assertEqual(cm.exception.library, 'PEM')
615 self.assertEqual(cm.exception.reason, 'NO_START_LINE')
616 s = str(cm.exception)
617 self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
618
619 def test_subclass(self):
620 # Check that the appropriate SSLError subclass is raised
621 # (this only tests one of them)
622 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
623 with socket.socket() as s:
624 s.bind(("127.0.0.1", 0))
625 s.listen(5)
626 with socket.socket() as c:
627 c.connect(s.getsockname())
628 c.setblocking(False)
629 c = ctx.wrap_socket(c, False, do_handshake_on_connect=False)
630 with self.assertRaises(ssl.SSLWantReadError) as cm:
631 c.do_handshake()
632 s = str(cm.exception)
633 self.assertTrue(s.startswith("The operation did not complete (read)"), s)
634 # For compatibility
635 self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
636
637
Bill Janssen6e027db2007-11-15 22:23:56 +0000638class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639
Antoine Pitrou480a1242010-04-28 21:37:09 +0000640 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000641 with support.transient_internet("svn.python.org"):
642 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
643 cert_reqs=ssl.CERT_NONE)
644 try:
645 s.connect(("svn.python.org", 443))
646 self.assertEqual({}, s.getpeercert())
647 finally:
648 s.close()
649
650 # this should fail because we have no verification certs
651 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
652 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000653 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
654 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000655 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000656
Antoine Pitrou350c7222010-09-09 13:31:46 +0000657 # this should succeed because we specify the root cert
658 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
659 cert_reqs=ssl.CERT_REQUIRED,
660 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
661 try:
662 s.connect(("svn.python.org", 443))
663 self.assertTrue(s.getpeercert())
664 finally:
665 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000666
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000667 def test_connect_ex(self):
668 # Issue #11326: check connect_ex() implementation
669 with support.transient_internet("svn.python.org"):
670 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
671 cert_reqs=ssl.CERT_REQUIRED,
672 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
673 try:
674 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
675 self.assertTrue(s.getpeercert())
676 finally:
677 s.close()
678
679 def test_non_blocking_connect_ex(self):
680 # Issue #11326: non-blocking connect_ex() should allow handshake
681 # to proceed after the socket gets ready.
682 with support.transient_internet("svn.python.org"):
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 do_handshake_on_connect=False)
687 try:
688 s.setblocking(False)
689 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000690 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
691 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000692 # Wait for connect to finish
693 select.select([], [s], [], 5.0)
694 # Non-blocking handshake
695 while True:
696 try:
697 s.do_handshake()
698 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200699 except ssl.SSLWantReadError:
700 select.select([s], [], [], 5.0)
701 except ssl.SSLWantWriteError:
702 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000703 # SSL established
704 self.assertTrue(s.getpeercert())
705 finally:
706 s.close()
707
Antoine Pitroub4410db2011-05-18 18:51:06 +0200708 def test_timeout_connect_ex(self):
709 # Issue #12065: on a timeout, connect_ex() should return the original
710 # errno (mimicking the behaviour of non-SSL sockets).
711 with support.transient_internet("svn.python.org"):
712 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
713 cert_reqs=ssl.CERT_REQUIRED,
714 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
715 do_handshake_on_connect=False)
716 try:
717 s.settimeout(0.0000001)
718 rc = s.connect_ex(('svn.python.org', 443))
719 if rc == 0:
720 self.skipTest("svn.python.org responded too quickly")
721 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
722 finally:
723 s.close()
724
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100725 def test_connect_ex_error(self):
Antoine Pitrouddb87ab2012-12-28 19:07:43 +0100726 with support.transient_internet("svn.python.org"):
Antoine Pitrou40f12ab2012-12-28 19:03:43 +0100727 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
728 cert_reqs=ssl.CERT_REQUIRED,
729 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
730 try:
731 self.assertEqual(errno.ECONNREFUSED,
732 s.connect_ex(("svn.python.org", 444)))
733 finally:
734 s.close()
735
Antoine Pitrou152efa22010-05-16 18:19:27 +0000736 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000737 with support.transient_internet("svn.python.org"):
738 # Same as test_connect, but with a separately created context
739 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
740 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
741 s.connect(("svn.python.org", 443))
742 try:
743 self.assertEqual({}, s.getpeercert())
744 finally:
745 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000746 # Same with a server hostname
747 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
748 server_hostname="svn.python.org")
749 if ssl.HAS_SNI:
750 s.connect(("svn.python.org", 443))
751 s.close()
752 else:
753 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000754 # This should fail because we have no verification certs
755 ctx.verify_mode = ssl.CERT_REQUIRED
756 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000757 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000758 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000759 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000760 # This should succeed because we specify the root cert
761 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
762 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
763 s.connect(("svn.python.org", 443))
764 try:
765 cert = s.getpeercert()
766 self.assertTrue(cert)
767 finally:
768 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000769
770 def test_connect_capath(self):
771 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000772 # NOTE: the subject hashing algorithm has been changed between
773 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
774 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000775 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000776 with support.transient_internet("svn.python.org"):
777 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
778 ctx.verify_mode = ssl.CERT_REQUIRED
779 ctx.load_verify_locations(capath=CAPATH)
780 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
781 s.connect(("svn.python.org", 443))
782 try:
783 cert = s.getpeercert()
784 self.assertTrue(cert)
785 finally:
786 s.close()
787 # Same with a bytes `capath` argument
788 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
789 ctx.verify_mode = ssl.CERT_REQUIRED
790 ctx.load_verify_locations(capath=BYTES_CAPATH)
791 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
792 s.connect(("svn.python.org", 443))
793 try:
794 cert = s.getpeercert()
795 self.assertTrue(cert)
796 finally:
797 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000798
Antoine Pitroue3220242010-04-24 11:13:53 +0000799 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
800 def test_makefile_close(self):
801 # Issue #5238: creating a file-like object with makefile() shouldn't
802 # delay closing the underlying "real socket" (here tested with its
803 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000804 with support.transient_internet("svn.python.org"):
805 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
806 ss.connect(("svn.python.org", 443))
807 fd = ss.fileno()
808 f = ss.makefile()
809 f.close()
810 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000811 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000812 # Closing the SSL socket should close the fd too
813 ss.close()
814 gc.collect()
815 with self.assertRaises(OSError) as e:
816 os.read(fd, 0)
817 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000818
Antoine Pitrou480a1242010-04-28 21:37:09 +0000819 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000820 with support.transient_internet("svn.python.org"):
821 s = socket.socket(socket.AF_INET)
822 s.connect(("svn.python.org", 443))
823 s.setblocking(False)
824 s = ssl.wrap_socket(s,
825 cert_reqs=ssl.CERT_NONE,
826 do_handshake_on_connect=False)
827 count = 0
828 while True:
829 try:
830 count += 1
831 s.do_handshake()
832 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200833 except ssl.SSLWantReadError:
834 select.select([s], [], [])
835 except ssl.SSLWantWriteError:
836 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000837 s.close()
838 if support.verbose:
839 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000840
Antoine Pitrou480a1242010-04-28 21:37:09 +0000841 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200842 def _test_get_server_certificate(host, port, cert=None):
843 with support.transient_internet(host):
844 pem = ssl.get_server_certificate((host, port))
845 if not pem:
846 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200847
Antoine Pitrou15399c32011-04-28 19:23:55 +0200848 try:
849 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
850 except ssl.SSLError as x:
851 #should fail
852 if support.verbose:
853 sys.stdout.write("%s\n" % x)
854 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200855 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
856
Antoine Pitrou15399c32011-04-28 19:23:55 +0200857 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
858 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200859 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000860 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200861 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000862
Antoine Pitrou15399c32011-04-28 19:23:55 +0200863 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
864 if support.IPV6_ENABLED:
865 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000866
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000867 def test_ciphers(self):
868 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000869 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000870 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000871 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000872 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000873 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
874 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
875 s.connect(remote)
876 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000877 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000878 with socket.socket(socket.AF_INET) as sock:
879 s = ssl.wrap_socket(sock,
880 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
881 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000882
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000883 def test_algorithms(self):
884 # Issue #8484: all algorithms should be available when verifying a
885 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000886 # SHA256 was added in OpenSSL 0.9.8
887 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
888 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200889 # sha256.tbs-internet.com needs SNI to use the correct certificate
890 if not ssl.HAS_SNI:
891 self.skipTest("SNI needed for this test")
Victor Stinnerf332abb2011-01-08 03:16:05 +0000892 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
893 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000894 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000895 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou16f6f832012-05-04 16:26:02 +0200896 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
897 ctx.verify_mode = ssl.CERT_REQUIRED
898 ctx.load_verify_locations(sha256_cert)
899 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
900 server_hostname="sha256.tbs-internet.com")
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000901 try:
902 s.connect(remote)
903 if support.verbose:
904 sys.stdout.write("\nCipher with %r is %r\n" %
905 (remote, s.cipher()))
906 sys.stdout.write("Certificate is:\n%s\n" %
907 pprint.pformat(s.getpeercert()))
908 finally:
909 s.close()
910
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000911
912try:
913 import threading
914except ImportError:
915 _have_threads = False
916else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000917 _have_threads = True
918
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000919 from test.ssl_servers import make_https_server
920
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000921 class ThreadedEchoServer(threading.Thread):
922
923 class ConnectionHandler(threading.Thread):
924
925 """A mildly complicated class, because we want it to work both
926 with and without the SSL wrapper around the socket connection, so
927 that we can test the STARTTLS functionality."""
928
Bill Janssen6e027db2007-11-15 22:23:56 +0000929 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000930 self.server = server
931 self.running = False
932 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000933 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000934 self.sock.setblocking(1)
935 self.sslconn = None
936 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000937 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000938
Antoine Pitrou480a1242010-04-28 21:37:09 +0000939 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000940 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000941 self.sslconn = self.server.context.wrap_socket(
942 self.sock, server_side=True)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100943 self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100944 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000945 # XXX Various errors can have happened here, for example
946 # a mismatching protocol version, an invalid certificate,
947 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100948 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000950 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000951 self.running = False
952 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000953 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000954 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000955 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000956 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000957 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000958 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000959 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
960 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000961 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000962 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
963 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000964 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000965 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100966 sys.stdout.write(" server: selected protocol is now "
967 + str(self.sslconn.selected_npn_protocol()) + "\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000968 return True
969
970 def read(self):
971 if self.sslconn:
972 return self.sslconn.read()
973 else:
974 return self.sock.recv(1024)
975
976 def write(self, bytes):
977 if self.sslconn:
978 return self.sslconn.write(bytes)
979 else:
980 return self.sock.send(bytes)
981
982 def close(self):
983 if self.sslconn:
984 self.sslconn.close()
985 else:
986 self.sock.close()
987
Antoine Pitrou480a1242010-04-28 21:37:09 +0000988 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000989 self.running = True
990 if not self.server.starttls_server:
991 if not self.wrap_conn():
992 return
993 while self.running:
994 try:
995 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000996 stripped = msg.strip()
997 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 # eof, so quit this handler
999 self.running = False
1000 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001001 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001002 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003 sys.stdout.write(" server: client closed connection\n")
1004 self.close()
1005 return
Bill Janssen6e027db2007-11-15 22:23:56 +00001006 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +00001007 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001008 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001009 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001010 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001011 if not self.wrap_conn():
1012 return
Bill Janssen40a0f662008-08-12 16:56:25 +00001013 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +00001014 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +00001015 if support.verbose and self.server.connectionchatty:
1016 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001017 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +00001018 self.sock = self.sslconn.unwrap()
1019 self.sslconn = None
1020 if support.verbose and self.server.connectionchatty:
1021 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +02001022 elif stripped == b'CB tls-unique':
1023 if support.verbose and self.server.connectionchatty:
1024 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
1025 data = self.sslconn.get_channel_binding("tls-unique")
1026 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001027 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001028 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001029 self.server.connectionchatty):
1030 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +00001031 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
1032 % (msg, ctype, msg.lower(), ctype))
1033 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +00001034 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001035 if self.server.chatty:
1036 handle_error("Test server failure:\n")
1037 self.close()
1038 self.running = False
1039 # normally, we'd just stop here, but for the test
1040 # harness, we want to stop the server
1041 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001042
Antoine Pitroub5218772010-05-21 09:56:06 +00001043 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001044 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001045 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001046 npn_protocols=None, ciphers=None, context=None):
Antoine Pitroub5218772010-05-21 09:56:06 +00001047 if context:
1048 self.context = context
1049 else:
1050 self.context = ssl.SSLContext(ssl_version
1051 if ssl_version is not None
1052 else ssl.PROTOCOL_TLSv1)
1053 self.context.verify_mode = (certreqs if certreqs is not None
1054 else ssl.CERT_NONE)
1055 if cacerts:
1056 self.context.load_verify_locations(cacerts)
1057 if certificate:
1058 self.context.load_cert_chain(certificate)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001059 if npn_protocols:
1060 self.context.set_npn_protocols(npn_protocols)
Antoine Pitroub5218772010-05-21 09:56:06 +00001061 if ciphers:
1062 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001063 self.chatty = chatty
1064 self.connectionchatty = connectionchatty
1065 self.starttls_server = starttls_server
1066 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001067 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001068 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001069 self.active = False
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001070 self.selected_protocols = []
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001071 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001072 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001073 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001074
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001075 def __enter__(self):
1076 self.start(threading.Event())
1077 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001078 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001079
1080 def __exit__(self, *args):
1081 self.stop()
1082 self.join()
1083
Antoine Pitrou480a1242010-04-28 21:37:09 +00001084 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001085 self.flag = flag
1086 threading.Thread.start(self)
1087
Antoine Pitrou480a1242010-04-28 21:37:09 +00001088 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001089 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001090 self.sock.listen(5)
1091 self.active = True
1092 if self.flag:
1093 # signal an event
1094 self.flag.set()
1095 while self.active:
1096 try:
1097 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001098 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001099 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001100 + repr(connaddr) + '\n')
1101 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001102 handler.start()
Antoine Pitroueced82e2012-01-27 17:33:01 +01001103 handler.join()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001104 except socket.timeout:
1105 pass
1106 except KeyboardInterrupt:
1107 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001108 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001109
Antoine Pitrou480a1242010-04-28 21:37:09 +00001110 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001111 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001112
Bill Janssen54cc54c2007-12-14 22:08:56 +00001113 class AsyncoreEchoServer(threading.Thread):
1114
1115 # this one's based on asyncore.dispatcher
1116
1117 class EchoServer (asyncore.dispatcher):
1118
1119 class ConnectionHandler (asyncore.dispatcher_with_send):
1120
1121 def __init__(self, conn, certfile):
1122 self.socket = ssl.wrap_socket(conn, server_side=True,
1123 certfile=certfile,
1124 do_handshake_on_connect=False)
1125 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001126 self._ssl_accepting = True
1127 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001128
1129 def readable(self):
1130 if isinstance(self.socket, ssl.SSLSocket):
1131 while self.socket.pending() > 0:
1132 self.handle_read_event()
1133 return True
1134
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001135 def _do_ssl_handshake(self):
1136 try:
1137 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001138 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1139 return
1140 except ssl.SSLEOFError:
1141 return self.handle_close()
1142 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001143 raise
1144 except socket.error as err:
1145 if err.args[0] == errno.ECONNABORTED:
1146 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001147 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001148 self._ssl_accepting = False
1149
1150 def handle_read(self):
1151 if self._ssl_accepting:
1152 self._do_ssl_handshake()
1153 else:
1154 data = self.recv(1024)
1155 if support.verbose:
1156 sys.stdout.write(" server: read %s from client\n" % repr(data))
1157 if not data:
1158 self.close()
1159 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001160 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001161
1162 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001163 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001164 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001165 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1166
1167 def handle_error(self):
1168 raise
1169
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001170 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001171 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001172 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1173 self.port = support.bind_port(sock, '')
1174 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001175 self.listen(5)
1176
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001177 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001178 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001179 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1180 self.ConnectionHandler(sock_obj, self.certfile)
1181
1182 def handle_error(self):
1183 raise
1184
Trent Nelson78520002008-04-10 20:54:35 +00001185 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001186 self.flag = None
1187 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001188 self.server = self.EchoServer(certfile)
1189 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001190 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001191 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001192
1193 def __str__(self):
1194 return "<%s %s>" % (self.__class__.__name__, self.server)
1195
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001196 def __enter__(self):
1197 self.start(threading.Event())
1198 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001199 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001200
1201 def __exit__(self, *args):
1202 if support.verbose:
1203 sys.stdout.write(" cleanup: stopping server.\n")
1204 self.stop()
1205 if support.verbose:
1206 sys.stdout.write(" cleanup: joining server thread.\n")
1207 self.join()
1208 if support.verbose:
1209 sys.stdout.write(" cleanup: successfully joined.\n")
1210
Bill Janssen54cc54c2007-12-14 22:08:56 +00001211 def start (self, flag=None):
1212 self.flag = flag
1213 threading.Thread.start(self)
1214
Antoine Pitrou480a1242010-04-28 21:37:09 +00001215 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001216 self.active = True
1217 if self.flag:
1218 self.flag.set()
1219 while self.active:
1220 try:
1221 asyncore.loop(1)
1222 except:
1223 pass
1224
Antoine Pitrou480a1242010-04-28 21:37:09 +00001225 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001226 self.active = False
1227 self.server.close()
1228
Antoine Pitrou480a1242010-04-28 21:37:09 +00001229 def bad_cert_test(certfile):
1230 """
1231 Launch a server with CERT_REQUIRED, and check that trying to
1232 connect to it with the given client certificate fails.
1233 """
Trent Nelson78520002008-04-10 20:54:35 +00001234 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001235 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001236 cacerts=CERTFILE, chatty=False,
1237 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001238 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001239 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001240 with socket.socket() as sock:
1241 s = ssl.wrap_socket(sock,
1242 certfile=certfile,
1243 ssl_version=ssl.PROTOCOL_TLSv1)
1244 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001245 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001246 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001247 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001248 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001249 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001250 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001251 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001252 if x.errno != errno.ENOENT:
1253 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001254 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001255 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001256 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001257 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001258
Antoine Pitroub5218772010-05-21 09:56:06 +00001259 def server_params_test(client_context, server_context, indata=b"FOO\n",
1260 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001261 """
1262 Launch a server, connect a client to it and try various reads
1263 and writes.
1264 """
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001265 stats = {}
Antoine Pitroub5218772010-05-21 09:56:06 +00001266 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001267 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001268 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001269 with server:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001270 with client_context.wrap_socket(socket.socket()) as s:
1271 s.connect((HOST, server.port))
1272 for arg in [indata, bytearray(indata), memoryview(indata)]:
1273 if connectionchatty:
1274 if support.verbose:
1275 sys.stdout.write(
1276 " client: sending %r...\n" % indata)
1277 s.write(arg)
1278 outdata = s.read()
1279 if connectionchatty:
1280 if support.verbose:
1281 sys.stdout.write(" client: read %r\n" % outdata)
1282 if outdata != indata.lower():
1283 raise AssertionError(
1284 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1285 % (outdata[:20], len(outdata),
1286 indata[:20].lower(), len(indata)))
1287 s.write(b"over\n")
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001288 if connectionchatty:
1289 if support.verbose:
Antoine Pitroueba63c42012-01-28 17:38:34 +01001290 sys.stdout.write(" client: closing connection.\n")
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001291 stats.update({
Antoine Pitrouce816a52012-01-28 17:40:23 +01001292 'compression': s.compression(),
1293 'cipher': s.cipher(),
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001294 'client_npn_protocol': s.selected_npn_protocol()
1295 })
Antoine Pitroueba63c42012-01-28 17:38:34 +01001296 s.close()
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001297 stats['server_npn_protocols'] = server.selected_protocols
1298 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001299
Antoine Pitroub5218772010-05-21 09:56:06 +00001300 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1301 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001302 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001303 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001304 certtype = {
1305 ssl.CERT_NONE: "CERT_NONE",
1306 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1307 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1308 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001309 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001310 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001311 sys.stdout.write(formatstr %
1312 (ssl.get_protocol_name(client_protocol),
1313 ssl.get_protocol_name(server_protocol),
1314 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001315 client_context = ssl.SSLContext(client_protocol)
1316 client_context.options = ssl.OP_ALL | client_options
1317 server_context = ssl.SSLContext(server_protocol)
1318 server_context.options = ssl.OP_ALL | server_options
1319 for ctx in (client_context, server_context):
1320 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001321 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1322 # will send an SSLv3 hello (rather than SSLv2) starting from
1323 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001324 ctx.set_ciphers("ALL")
1325 ctx.load_cert_chain(CERTFILE)
1326 ctx.load_verify_locations(CERTFILE)
1327 try:
1328 server_params_test(client_context, server_context,
1329 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001330 # Protocol mismatch can result in either an SSLError, or a
1331 # "Connection reset by peer" error.
1332 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001333 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001334 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001335 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001336 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001337 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001338 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001339 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001340 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001341 "Client protocol %s succeeded with server protocol %s!"
1342 % (ssl.get_protocol_name(client_protocol),
1343 ssl.get_protocol_name(server_protocol)))
1344
1345
Bill Janssen6e027db2007-11-15 22:23:56 +00001346 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001347
Antoine Pitrou23df4832010-08-04 17:14:06 +00001348 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001349 def test_echo(self):
1350 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001351 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001352 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001353 for protocol in PROTOCOLS:
1354 context = ssl.SSLContext(protocol)
1355 context.load_cert_chain(CERTFILE)
1356 server_params_test(context, context,
1357 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001358
Antoine Pitrou480a1242010-04-28 21:37:09 +00001359 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001360 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001361 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001362 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1363 context.verify_mode = ssl.CERT_REQUIRED
1364 context.load_verify_locations(CERTFILE)
1365 context.load_cert_chain(CERTFILE)
1366 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001367 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001368 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001369 s.connect((HOST, server.port))
1370 cert = s.getpeercert()
1371 self.assertTrue(cert, "Can't get peer certificate.")
1372 cipher = s.cipher()
1373 if support.verbose:
1374 sys.stdout.write(pprint.pformat(cert) + '\n')
1375 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1376 if 'subject' not in cert:
1377 self.fail("No subject field in certificate: %s." %
1378 pprint.pformat(cert))
1379 if ((('organizationName', 'Python Software Foundation'),)
1380 not in cert['subject']):
1381 self.fail(
1382 "Missing or invalid 'organizationName' field in certificate subject; "
1383 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001384 self.assertIn('notBefore', cert)
1385 self.assertIn('notAfter', cert)
1386 before = ssl.cert_time_to_seconds(cert['notBefore'])
1387 after = ssl.cert_time_to_seconds(cert['notAfter'])
1388 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001389 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001390
Antoine Pitrou480a1242010-04-28 21:37:09 +00001391 def test_empty_cert(self):
1392 """Connecting with an empty cert file"""
1393 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1394 "nullcert.pem"))
1395 def test_malformed_cert(self):
1396 """Connecting with a badly formatted certificate (syntax error)"""
1397 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1398 "badcert.pem"))
1399 def test_nonexisting_cert(self):
1400 """Connecting with a non-existing cert file"""
1401 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1402 "wrongcert.pem"))
1403 def test_malformed_key(self):
1404 """Connecting with a badly formatted key (syntax error)"""
1405 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1406 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001407
Antoine Pitrou480a1242010-04-28 21:37:09 +00001408 def test_rude_shutdown(self):
1409 """A brutal shutdown of an SSL server should raise an IOError
1410 in the client when attempting handshake.
1411 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001412 listener_ready = threading.Event()
1413 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001414
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001415 s = socket.socket()
1416 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001417
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001418 # `listener` runs in a thread. It sits in an accept() until
1419 # the main thread connects. Then it rudely closes the socket,
1420 # and sets Event `listener_gone` to let the main thread know
1421 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001422 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001423 s.listen(5)
1424 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001425 newsock, addr = s.accept()
1426 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001427 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001428 listener_gone.set()
1429
1430 def connector():
1431 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001432 with socket.socket() as c:
1433 c.connect((HOST, port))
1434 listener_gone.wait()
1435 try:
1436 ssl_sock = ssl.wrap_socket(c)
1437 except IOError:
1438 pass
1439 else:
1440 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001441
1442 t = threading.Thread(target=listener)
1443 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001444 try:
1445 connector()
1446 finally:
1447 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001448
Antoine Pitrou23df4832010-08-04 17:14:06 +00001449 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001450 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1451 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001452 def test_protocol_sslv2(self):
1453 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001454 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001455 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001456 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1457 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1458 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1459 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1460 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1461 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001462 # SSLv23 client with specific SSL options
1463 if no_sslv2_implies_sslv3_hello():
1464 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1465 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1466 client_options=ssl.OP_NO_SSLv2)
1467 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1468 client_options=ssl.OP_NO_SSLv3)
1469 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1470 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001471
Antoine Pitrou23df4832010-08-04 17:14:06 +00001472 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001473 def test_protocol_sslv23(self):
1474 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001475 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001476 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001477 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1478 try:
1479 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1480 except (ssl.SSLError, socket.error) as x:
1481 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1482 if support.verbose:
1483 sys.stdout.write(
1484 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1485 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001486 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1487 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1488 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001489
Antoine Pitrou480a1242010-04-28 21:37:09 +00001490 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1491 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1492 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001493
Antoine Pitrou480a1242010-04-28 21:37:09 +00001494 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1495 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1496 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001497
Antoine Pitroub5218772010-05-21 09:56:06 +00001498 # Server with specific SSL options
1499 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1500 server_options=ssl.OP_NO_SSLv3)
1501 # Will choose TLSv1
1502 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1503 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1504 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1505 server_options=ssl.OP_NO_TLSv1)
1506
1507
Antoine Pitrou23df4832010-08-04 17:14:06 +00001508 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001509 def test_protocol_sslv3(self):
1510 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001511 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001512 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001513 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1514 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1515 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001516 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1517 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001518 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1519 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001520 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001521 if no_sslv2_implies_sslv3_hello():
1522 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1523 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1524 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001525
Antoine Pitrou23df4832010-08-04 17:14:06 +00001526 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001527 def test_protocol_tlsv1(self):
1528 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001529 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001530 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001531 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1532 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1533 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001534 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1535 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001536 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001537 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1538 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001539
Antoine Pitrou480a1242010-04-28 21:37:09 +00001540 def test_starttls(self):
1541 """Switching from clear text to encrypted and back again."""
1542 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 +00001543
Trent Nelson78520002008-04-10 20:54:35 +00001544 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001545 ssl_version=ssl.PROTOCOL_TLSv1,
1546 starttls_server=True,
1547 chatty=True,
1548 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001549 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001550 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001551 s = socket.socket()
1552 s.setblocking(1)
1553 s.connect((HOST, server.port))
1554 if support.verbose:
1555 sys.stdout.write("\n")
1556 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001557 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001558 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001559 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001560 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001561 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001562 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001563 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001564 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001565 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001566 msg = outdata.strip().lower()
1567 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1568 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001569 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001570 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001571 " client: read %r from server, starting TLS...\n"
1572 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001573 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1574 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001575 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1576 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001577 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001578 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001579 " client: read %r from server, ending TLS...\n"
1580 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001581 s = conn.unwrap()
1582 wrapped = False
1583 else:
1584 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001585 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001586 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001587 if support.verbose:
1588 sys.stdout.write(" client: closing connection.\n")
1589 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001590 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001591 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001592 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001593 if wrapped:
1594 conn.close()
1595 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001596 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001597
Antoine Pitrou480a1242010-04-28 21:37:09 +00001598 def test_socketserver(self):
1599 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001600 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001601 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001602 if support.verbose:
1603 sys.stdout.write('\n')
1604 with open(CERTFILE, 'rb') as f:
1605 d1 = f.read()
1606 d2 = ''
1607 # now fetch the same data from the HTTPS server
1608 url = 'https://%s:%d/%s' % (
1609 HOST, server.port, os.path.split(CERTFILE)[1])
1610 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001611 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001612 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001613 if dlen and (int(dlen) > 0):
1614 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001615 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001616 sys.stdout.write(
1617 " client: read %d bytes from remote server '%s'\n"
1618 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001619 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001620 f.close()
1621 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001622
Antoine Pitrou480a1242010-04-28 21:37:09 +00001623 def test_asyncore_server(self):
1624 """Check the example asyncore integration."""
1625 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001626
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001627 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001628 sys.stdout.write("\n")
1629
Antoine Pitrou480a1242010-04-28 21:37:09 +00001630 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001631 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001632 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001633 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001634 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001635 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001636 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001637 " client: sending %r...\n" % indata)
1638 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001639 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001640 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001641 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001642 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001643 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001644 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1645 % (outdata[:20], len(outdata),
1646 indata[:20].lower(), len(indata)))
1647 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001648 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001649 sys.stdout.write(" client: closing connection.\n")
1650 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001651 if support.verbose:
1652 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001653
Antoine Pitrou480a1242010-04-28 21:37:09 +00001654 def test_recv_send(self):
1655 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001656 if support.verbose:
1657 sys.stdout.write("\n")
1658
1659 server = ThreadedEchoServer(CERTFILE,
1660 certreqs=ssl.CERT_NONE,
1661 ssl_version=ssl.PROTOCOL_TLSv1,
1662 cacerts=CERTFILE,
1663 chatty=True,
1664 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001665 with server:
1666 s = ssl.wrap_socket(socket.socket(),
1667 server_side=False,
1668 certfile=CERTFILE,
1669 ca_certs=CERTFILE,
1670 cert_reqs=ssl.CERT_NONE,
1671 ssl_version=ssl.PROTOCOL_TLSv1)
1672 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001673 # helper methods for standardising recv* method signatures
1674 def _recv_into():
1675 b = bytearray(b"\0"*100)
1676 count = s.recv_into(b)
1677 return b[:count]
1678
1679 def _recvfrom_into():
1680 b = bytearray(b"\0"*100)
1681 count, addr = s.recvfrom_into(b)
1682 return b[:count]
1683
1684 # (name, method, whether to expect success, *args)
1685 send_methods = [
1686 ('send', s.send, True, []),
1687 ('sendto', s.sendto, False, ["some.address"]),
1688 ('sendall', s.sendall, True, []),
1689 ]
1690 recv_methods = [
1691 ('recv', s.recv, True, []),
1692 ('recvfrom', s.recvfrom, False, ["some.address"]),
1693 ('recv_into', _recv_into, True, []),
1694 ('recvfrom_into', _recvfrom_into, False, []),
1695 ]
1696 data_prefix = "PREFIX_"
1697
1698 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001699 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001700 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001701 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001702 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001703 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001704 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001705 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001706 "<<{outdata:r}>> ({nout:d}) received; "
1707 "expected <<{indata:r}>> ({nin:d})\n".format(
1708 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001709 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001710 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001711 )
1712 )
1713 except ValueError as e:
1714 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001715 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001716 "Failed to send with method <<{name:s}>>; "
1717 "expected to succeed.\n".format(name=meth_name)
1718 )
1719 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001720 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001721 "Method <<{name:s}>> failed with unexpected "
1722 "exception message: {exp:s}\n".format(
1723 name=meth_name, exp=e
1724 )
1725 )
1726
1727 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001728 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001729 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001730 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001731 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001732 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001733 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001734 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001735 "<<{outdata:r}>> ({nout:d}) received; "
1736 "expected <<{indata:r}>> ({nin:d})\n".format(
1737 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001738 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001739 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001740 )
1741 )
1742 except ValueError as e:
1743 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001744 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001745 "Failed to receive with method <<{name:s}>>; "
1746 "expected to succeed.\n".format(name=meth_name)
1747 )
1748 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001749 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001750 "Method <<{name:s}>> failed with unexpected "
1751 "exception message: {exp:s}\n".format(
1752 name=meth_name, exp=e
1753 )
1754 )
1755 # consume data
1756 s.read()
1757
Nick Coghlan513886a2011-08-28 00:00:27 +10001758 # Make sure sendmsg et al are disallowed to avoid
1759 # inadvertent disclosure of data and/or corruption
1760 # of the encrypted data stream
1761 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1762 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1763 self.assertRaises(NotImplementedError,
1764 s.recvmsg_into, bytearray(100))
1765
Antoine Pitrou480a1242010-04-28 21:37:09 +00001766 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001767 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001768
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001769 def test_handshake_timeout(self):
1770 # Issue #5103: SSL handshake must respect the socket timeout
1771 server = socket.socket(socket.AF_INET)
1772 host = "127.0.0.1"
1773 port = support.bind_port(server)
1774 started = threading.Event()
1775 finish = False
1776
1777 def serve():
1778 server.listen(5)
1779 started.set()
1780 conns = []
1781 while not finish:
1782 r, w, e = select.select([server], [], [], 0.1)
1783 if server in r:
1784 # Let the socket hang around rather than having
1785 # it closed by garbage collection.
1786 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001787 for sock in conns:
1788 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001789
1790 t = threading.Thread(target=serve)
1791 t.start()
1792 started.wait()
1793
1794 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001795 try:
1796 c = socket.socket(socket.AF_INET)
1797 c.settimeout(0.2)
1798 c.connect((host, port))
1799 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001800 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001801 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001802 finally:
1803 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001804 try:
1805 c = socket.socket(socket.AF_INET)
1806 c = ssl.wrap_socket(c)
1807 c.settimeout(0.2)
1808 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001809 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001810 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001811 finally:
1812 c.close()
1813 finally:
1814 finish = True
1815 t.join()
1816 server.close()
1817
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +01001818 def test_server_accept(self):
1819 # Issue #16357: accept() on a SSLSocket created through
1820 # SSLContext.wrap_socket().
1821 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1822 context.verify_mode = ssl.CERT_REQUIRED
1823 context.load_verify_locations(CERTFILE)
1824 context.load_cert_chain(CERTFILE)
1825 server = socket.socket(socket.AF_INET)
1826 host = "127.0.0.1"
1827 port = support.bind_port(server)
1828 server = context.wrap_socket(server, server_side=True)
1829
1830 evt = threading.Event()
1831 remote = None
1832 peer = None
1833 def serve():
1834 nonlocal remote, peer
1835 server.listen(5)
1836 # Block on the accept and wait on the connection to close.
1837 evt.set()
1838 remote, peer = server.accept()
1839 remote.recv(1)
1840
1841 t = threading.Thread(target=serve)
1842 t.start()
1843 # Client wait until server setup and perform a connect.
1844 evt.wait()
1845 client = context.wrap_socket(socket.socket())
1846 client.connect((host, port))
1847 client_addr = client.getsockname()
1848 client.close()
1849 t.join()
1850 # Sanity checks.
1851 self.assertIsInstance(remote, ssl.SSLSocket)
1852 self.assertEqual(peer, client_addr)
1853
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001854 def test_default_ciphers(self):
1855 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1856 try:
1857 # Force a set of weak ciphers on our client context
1858 context.set_ciphers("DES")
1859 except ssl.SSLError:
1860 self.skipTest("no DES cipher available")
1861 with ThreadedEchoServer(CERTFILE,
1862 ssl_version=ssl.PROTOCOL_SSLv23,
1863 chatty=False) as server:
1864 with socket.socket() as sock:
1865 s = context.wrap_socket(sock)
1866 with self.assertRaises((OSError, ssl.SSLError)):
1867 s.connect((HOST, server.port))
1868 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1869
Antoine Pitroud6494802011-07-21 01:11:30 +02001870 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1871 "'tls-unique' channel binding not available")
1872 def test_tls_unique_channel_binding(self):
1873 """Test tls-unique channel binding."""
1874 if support.verbose:
1875 sys.stdout.write("\n")
1876
1877 server = ThreadedEchoServer(CERTFILE,
1878 certreqs=ssl.CERT_NONE,
1879 ssl_version=ssl.PROTOCOL_TLSv1,
1880 cacerts=CERTFILE,
1881 chatty=True,
1882 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001883 with server:
1884 s = ssl.wrap_socket(socket.socket(),
1885 server_side=False,
1886 certfile=CERTFILE,
1887 ca_certs=CERTFILE,
1888 cert_reqs=ssl.CERT_NONE,
1889 ssl_version=ssl.PROTOCOL_TLSv1)
1890 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001891 # get the data
1892 cb_data = s.get_channel_binding("tls-unique")
1893 if support.verbose:
1894 sys.stdout.write(" got channel binding data: {0!r}\n"
1895 .format(cb_data))
1896
1897 # check if it is sane
1898 self.assertIsNotNone(cb_data)
1899 self.assertEqual(len(cb_data), 12) # True for TLSv1
1900
1901 # and compare with the peers version
1902 s.write(b"CB tls-unique\n")
1903 peer_data_repr = s.read().strip()
1904 self.assertEqual(peer_data_repr,
1905 repr(cb_data).encode("us-ascii"))
1906 s.close()
1907
1908 # now, again
1909 s = ssl.wrap_socket(socket.socket(),
1910 server_side=False,
1911 certfile=CERTFILE,
1912 ca_certs=CERTFILE,
1913 cert_reqs=ssl.CERT_NONE,
1914 ssl_version=ssl.PROTOCOL_TLSv1)
1915 s.connect((HOST, server.port))
1916 new_cb_data = s.get_channel_binding("tls-unique")
1917 if support.verbose:
1918 sys.stdout.write(" got another channel binding data: {0!r}\n"
1919 .format(new_cb_data))
1920 # is it really unique
1921 self.assertNotEqual(cb_data, new_cb_data)
1922 self.assertIsNotNone(cb_data)
1923 self.assertEqual(len(cb_data), 12) # True for TLSv1
1924 s.write(b"CB tls-unique\n")
1925 peer_data_repr = s.read().strip()
1926 self.assertEqual(peer_data_repr,
1927 repr(new_cb_data).encode("us-ascii"))
1928 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001929
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001930 def test_compression(self):
1931 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1932 context.load_cert_chain(CERTFILE)
1933 stats = server_params_test(context, context,
1934 chatty=True, connectionchatty=True)
1935 if support.verbose:
1936 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1937 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1938
1939 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1940 "ssl.OP_NO_COMPRESSION needed for this test")
1941 def test_compression_disabled(self):
1942 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1943 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001944 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001945 stats = server_params_test(context, context,
1946 chatty=True, connectionchatty=True)
1947 self.assertIs(stats['compression'], None)
1948
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001949 def test_dh_params(self):
1950 # Check we can get a connection with ephemeral Diffie-Hellman
1951 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1952 context.load_cert_chain(CERTFILE)
1953 context.load_dh_params(DHFILE)
1954 context.set_ciphers("kEDH")
1955 stats = server_params_test(context, context,
1956 chatty=True, connectionchatty=True)
1957 cipher = stats["cipher"][0]
1958 parts = cipher.split("-")
1959 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1960 self.fail("Non-DH cipher: " + cipher[0])
1961
Antoine Pitroud5d17eb2012-03-22 00:23:03 +01001962 def test_selected_npn_protocol(self):
1963 # selected_npn_protocol() is None unless NPN is used
1964 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1965 context.load_cert_chain(CERTFILE)
1966 stats = server_params_test(context, context,
1967 chatty=True, connectionchatty=True)
1968 self.assertIs(stats['client_npn_protocol'], None)
1969
1970 @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
1971 def test_npn_protocols(self):
1972 server_protocols = ['http/1.1', 'spdy/2']
1973 protocol_tests = [
1974 (['http/1.1', 'spdy/2'], 'http/1.1'),
1975 (['spdy/2', 'http/1.1'], 'http/1.1'),
1976 (['spdy/2', 'test'], 'spdy/2'),
1977 (['abc', 'def'], 'abc')
1978 ]
1979 for client_protocols, expected in protocol_tests:
1980 server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1981 server_context.load_cert_chain(CERTFILE)
1982 server_context.set_npn_protocols(server_protocols)
1983 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1984 client_context.load_cert_chain(CERTFILE)
1985 client_context.set_npn_protocols(client_protocols)
1986 stats = server_params_test(client_context, server_context,
1987 chatty=True, connectionchatty=True)
1988
1989 msg = "failed trying %s (s) and %s (c).\n" \
1990 "was expecting %s, but got %%s from the %%s" \
1991 % (str(server_protocols), str(client_protocols),
1992 str(expected))
1993 client_result = stats['client_npn_protocol']
1994 self.assertEqual(client_result, expected, msg % (client_result, "client"))
1995 server_result = stats['server_npn_protocols'][-1] \
1996 if len(stats['server_npn_protocols']) else 'nothing'
1997 self.assertEqual(server_result, expected, msg % (server_result, "server"))
1998
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001999
Thomas Woutersed03b412007-08-28 21:37:11 +00002000def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00002001 if support.verbose:
2002 plats = {
2003 'Linux': platform.linux_distribution,
2004 'Mac': platform.mac_ver,
2005 'Windows': platform.win32_ver,
2006 }
2007 for name, func in plats.items():
2008 plat = func()
2009 if plat and plat[0]:
2010 plat = '%s %r' % (name, plat)
2011 break
2012 else:
2013 plat = repr(platform.platform())
2014 print("test_ssl: testing with %r %r" %
2015 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
2016 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00002017 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00002018
Antoine Pitrou152efa22010-05-16 18:19:27 +00002019 for filename in [
2020 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
2021 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
2022 BADCERT, BADKEY, EMPTYCERT]:
2023 if not os.path.exists(filename):
2024 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002025
Antoine Pitrou3b36fb12012-06-22 21:11:52 +02002026 tests = [ContextTests, BasicSocketTests, SSLErrorTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00002027
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002028 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002029 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002030
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002031 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002032 thread_info = support.threading_setup()
2033 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00002034 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00002035
Antoine Pitrou480a1242010-04-28 21:37:09 +00002036 try:
2037 support.run_unittest(*tests)
2038 finally:
2039 if _have_threads:
2040 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00002041
2042if __name__ == "__main__":
2043 test_main()