blob: 86d1cd8df700dfee5bd8c28902055e1e35047ae1 [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 Pitrou923df6f2011-12-19 17:16:51 +0100105 ssl.OP_SINGLE_ECDH_USE
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100106 if ssl.OPENSSL_VERSION_INFO >= (1, 0):
107 ssl.OP_NO_COMPRESSION
Antoine Pitroud5323212010-10-22 18:19:07 +0000108 self.assertIn(ssl.HAS_SNI, {True, False})
Antoine Pitrou501da612011-12-21 09:27:41 +0100109 self.assertIn(ssl.HAS_ECDH, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +0000110
Antoine Pitrou480a1242010-04-28 21:37:09 +0000111 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000112 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000113 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 sys.stdout.write("\n RAND_status is %d (%s)\n"
115 % (v, (v and "sufficient randomness") or
116 "insufficient randomness"))
Victor Stinner99c8b162011-05-24 12:05:19 +0200117
118 data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
119 self.assertEqual(len(data), 16)
120 self.assertEqual(is_cryptographic, v == 1)
121 if v:
122 data = ssl.RAND_bytes(16)
123 self.assertEqual(len(data), 16)
Victor Stinner2e2baa92011-05-25 11:15:16 +0200124 else:
125 self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16)
Victor Stinner99c8b162011-05-24 12:05:19 +0200126
Thomas Woutersed03b412007-08-28 21:37:11 +0000127 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128 ssl.RAND_egd(1)
129 except TypeError:
130 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000131 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000132 print("didn't raise TypeError")
133 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000134
Antoine Pitrou480a1242010-04-28 21:37:09 +0000135 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000136 # note that this uses an 'unofficial' function in _ssl.c,
137 # provided solely for this test, to exercise the certificate
138 # parsing code
Antoine Pitroufb046912010-11-09 20:21:19 +0000139 p = ssl._ssl._test_decode_cert(CERTFILE)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000140 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000141 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Antoine Pitroud8c347a2011-10-01 19:20:25 +0200142 self.assertEqual(p['issuer'],
143 ((('countryName', 'XY'),),
144 (('localityName', 'Castle Anthrax'),),
145 (('organizationName', 'Python Software Foundation'),),
146 (('commonName', 'localhost'),))
147 )
148 self.assertEqual(p['notAfter'], 'Oct 5 23:01:56 2020 GMT')
149 self.assertEqual(p['notBefore'], 'Oct 8 23:01:56 2010 GMT')
150 self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E')
151 self.assertEqual(p['subject'],
152 ((('countryName', 'XY'),),
153 (('localityName', 'Castle Anthrax'),),
154 (('organizationName', 'Python Software Foundation'),),
155 (('commonName', 'localhost'),))
156 )
157 self.assertEqual(p['subjectAltName'], (('DNS', 'localhost'),))
158 # Issue #13034: the subjectAltName in some certificates
159 # (notably projects.developer.nokia.com:443) wasn't parsed
160 p = ssl._ssl._test_decode_cert(NOKIACERT)
161 if support.verbose:
162 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
163 self.assertEqual(p['subjectAltName'],
164 (('DNS', 'projects.developer.nokia.com'),
165 ('DNS', 'projects.forum.nokia.com'))
166 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000167
Antoine Pitrou480a1242010-04-28 21:37:09 +0000168 def test_DER_to_PEM(self):
169 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
170 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000171 d1 = ssl.PEM_cert_to_DER_cert(pem)
172 p2 = ssl.DER_cert_to_PEM_cert(d1)
173 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000174 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000175 if not p2.startswith(ssl.PEM_HEADER + '\n'):
176 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
177 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
178 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000179
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000180 def test_openssl_version(self):
181 n = ssl.OPENSSL_VERSION_NUMBER
182 t = ssl.OPENSSL_VERSION_INFO
183 s = ssl.OPENSSL_VERSION
184 self.assertIsInstance(n, int)
185 self.assertIsInstance(t, tuple)
186 self.assertIsInstance(s, str)
187 # Some sanity checks follow
188 # >= 0.9
189 self.assertGreaterEqual(n, 0x900000)
190 # < 2.0
191 self.assertLess(n, 0x20000000)
192 major, minor, fix, patch, status = t
193 self.assertGreaterEqual(major, 0)
194 self.assertLess(major, 2)
195 self.assertGreaterEqual(minor, 0)
196 self.assertLess(minor, 256)
197 self.assertGreaterEqual(fix, 0)
198 self.assertLess(fix, 256)
199 self.assertGreaterEqual(patch, 0)
200 self.assertLessEqual(patch, 26)
201 self.assertGreaterEqual(status, 0)
202 self.assertLessEqual(status, 15)
203 # Version string as returned by OpenSSL, the format might change
204 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
205 (s, t))
206
Antoine Pitrou9d543662010-04-23 23:10:32 +0000207 @support.cpython_only
208 def test_refcycle(self):
209 # Issue #7943: an SSL object doesn't create reference cycles with
210 # itself.
211 s = socket.socket(socket.AF_INET)
212 ss = ssl.wrap_socket(s)
213 wr = weakref.ref(ss)
214 del ss
215 self.assertEqual(wr(), None)
216
Antoine Pitroua468adc2010-09-14 14:43:44 +0000217 def test_wrapped_unconnected(self):
218 # Methods on an unconnected SSLSocket propagate the original
219 # socket.error raise by the underlying socket object.
220 s = socket.socket(socket.AF_INET)
221 ss = ssl.wrap_socket(s)
222 self.assertRaises(socket.error, ss.recv, 1)
223 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
224 self.assertRaises(socket.error, ss.recvfrom, 1)
225 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
226 self.assertRaises(socket.error, ss.send, b'x')
227 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
228
Antoine Pitrou40f08742010-04-24 22:04:40 +0000229 def test_timeout(self):
230 # Issue #8524: when creating an SSL socket, the timeout of the
231 # original socket should be retained.
232 for timeout in (None, 0.0, 5.0):
233 s = socket.socket(socket.AF_INET)
234 s.settimeout(timeout)
235 ss = ssl.wrap_socket(s)
236 self.assertEqual(timeout, ss.gettimeout())
237
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000238 def test_errors(self):
239 sock = socket.socket()
Ezio Melottied3a7d22010-12-01 02:32:32 +0000240 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000241 "certfile must be specified",
242 ssl.wrap_socket, sock, keyfile=CERTFILE)
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)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000246 self.assertRaisesRegex(ValueError,
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000247 "certfile must be specified for server-side operations",
248 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000249 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000250 self.assertRaisesRegex(ValueError, "can't connect in server-side mode",
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000251 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000252 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000253 with socket.socket() as sock:
254 ssl.wrap_socket(sock, certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000255 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000256 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000257 with socket.socket() as sock:
258 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000259 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000260 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000261 with socket.socket() as sock:
262 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000263 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000264
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000265 def test_match_hostname(self):
266 def ok(cert, hostname):
267 ssl.match_hostname(cert, hostname)
268 def fail(cert, hostname):
269 self.assertRaises(ssl.CertificateError,
270 ssl.match_hostname, cert, hostname)
271
272 cert = {'subject': ((('commonName', 'example.com'),),)}
273 ok(cert, 'example.com')
274 ok(cert, 'ExAmple.cOm')
275 fail(cert, 'www.example.com')
276 fail(cert, '.example.com')
277 fail(cert, 'example.org')
278 fail(cert, 'exampleXcom')
279
280 cert = {'subject': ((('commonName', '*.a.com'),),)}
281 ok(cert, 'foo.a.com')
282 fail(cert, 'bar.foo.a.com')
283 fail(cert, 'a.com')
284 fail(cert, 'Xa.com')
285 fail(cert, '.a.com')
286
287 cert = {'subject': ((('commonName', 'a.*.com'),),)}
288 ok(cert, 'a.foo.com')
289 fail(cert, 'a..com')
290 fail(cert, 'a.com')
291
292 cert = {'subject': ((('commonName', 'f*.com'),),)}
293 ok(cert, 'foo.com')
294 ok(cert, 'f.com')
295 fail(cert, 'bar.com')
296 fail(cert, 'foo.a.com')
297 fail(cert, 'bar.foo.com')
298
299 # Slightly fake real-world example
300 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
301 'subject': ((('commonName', 'linuxfrz.org'),),),
302 'subjectAltName': (('DNS', 'linuxfr.org'),
303 ('DNS', 'linuxfr.com'),
304 ('othername', '<unsupported>'))}
305 ok(cert, 'linuxfr.org')
306 ok(cert, 'linuxfr.com')
307 # Not a "DNS" entry
308 fail(cert, '<unsupported>')
309 # When there is a subjectAltName, commonName isn't used
310 fail(cert, 'linuxfrz.org')
311
312 # A pristine real-world example
313 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
314 'subject': ((('countryName', 'US'),),
315 (('stateOrProvinceName', 'California'),),
316 (('localityName', 'Mountain View'),),
317 (('organizationName', 'Google Inc'),),
318 (('commonName', 'mail.google.com'),))}
319 ok(cert, 'mail.google.com')
320 fail(cert, 'gmail.com')
321 # Only commonName is considered
322 fail(cert, 'California')
323
324 # Neither commonName nor subjectAltName
325 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
326 'subject': ((('countryName', 'US'),),
327 (('stateOrProvinceName', 'California'),),
328 (('localityName', 'Mountain View'),),
329 (('organizationName', 'Google Inc'),))}
330 fail(cert, 'mail.google.com')
331
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200332 # No DNS entry in subjectAltName but a commonName
333 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
334 'subject': ((('countryName', 'US'),),
335 (('stateOrProvinceName', 'California'),),
336 (('localityName', 'Mountain View'),),
337 (('commonName', 'mail.google.com'),)),
338 'subjectAltName': (('othername', 'blabla'), )}
339 ok(cert, 'mail.google.com')
340
341 # No DNS entry subjectAltName and no commonName
342 cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT',
343 'subject': ((('countryName', 'US'),),
344 (('stateOrProvinceName', 'California'),),
345 (('localityName', 'Mountain View'),),
346 (('organizationName', 'Google Inc'),)),
347 'subjectAltName': (('othername', 'blabla'),)}
348 fail(cert, 'google.com')
349
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000350 # Empty cert / no cert
351 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
352 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
353
Antoine Pitroud5323212010-10-22 18:19:07 +0000354 def test_server_side(self):
355 # server_hostname doesn't work for server sockets
356 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000357 with socket.socket() as sock:
358 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
359 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000360
Antoine Pitroud6494802011-07-21 01:11:30 +0200361 def test_unknown_channel_binding(self):
362 # should raise ValueError for unknown type
363 s = socket.socket(socket.AF_INET)
364 ss = ssl.wrap_socket(s)
365 with self.assertRaises(ValueError):
366 ss.get_channel_binding("unknown-type")
367
368 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
369 "'tls-unique' channel binding not available")
370 def test_tls_unique_channel_binding(self):
371 # unconnected should return None for known type
372 s = socket.socket(socket.AF_INET)
373 ss = ssl.wrap_socket(s)
374 self.assertIsNone(ss.get_channel_binding("tls-unique"))
375 # the same for server-side
376 s = socket.socket(socket.AF_INET)
377 ss = ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)
378 self.assertIsNone(ss.get_channel_binding("tls-unique"))
379
Antoine Pitrou152efa22010-05-16 18:19:27 +0000380class ContextTests(unittest.TestCase):
381
Antoine Pitrou23df4832010-08-04 17:14:06 +0000382 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000383 def test_constructor(self):
Victor Stinner3de49192011-05-09 00:42:58 +0200384 if hasattr(ssl, 'PROTOCOL_SSLv2'):
385 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000386 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
387 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
388 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
389 self.assertRaises(TypeError, ssl.SSLContext)
390 self.assertRaises(ValueError, ssl.SSLContext, -1)
391 self.assertRaises(ValueError, ssl.SSLContext, 42)
392
Antoine Pitrou23df4832010-08-04 17:14:06 +0000393 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000394 def test_protocol(self):
395 for proto in PROTOCOLS:
396 ctx = ssl.SSLContext(proto)
397 self.assertEqual(ctx.protocol, proto)
398
399 def test_ciphers(self):
400 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
401 ctx.set_ciphers("ALL")
402 ctx.set_ciphers("DEFAULT")
Ezio Melottied3a7d22010-12-01 02:32:32 +0000403 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000404 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000405
Antoine Pitrou23df4832010-08-04 17:14:06 +0000406 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000407 def test_options(self):
408 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
409 # OP_ALL is the default value
410 self.assertEqual(ssl.OP_ALL, ctx.options)
411 ctx.options |= ssl.OP_NO_SSLv2
412 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
413 ctx.options)
414 ctx.options |= ssl.OP_NO_SSLv3
415 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
416 ctx.options)
417 if can_clear_options():
418 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
419 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
420 ctx.options)
421 ctx.options = 0
422 self.assertEqual(0, ctx.options)
423 else:
424 with self.assertRaises(ValueError):
425 ctx.options = 0
426
Antoine Pitrou152efa22010-05-16 18:19:27 +0000427 def test_verify(self):
428 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
429 # Default value
430 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
431 ctx.verify_mode = ssl.CERT_OPTIONAL
432 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
433 ctx.verify_mode = ssl.CERT_REQUIRED
434 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
435 ctx.verify_mode = ssl.CERT_NONE
436 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
437 with self.assertRaises(TypeError):
438 ctx.verify_mode = None
439 with self.assertRaises(ValueError):
440 ctx.verify_mode = 42
441
442 def test_load_cert_chain(self):
443 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
444 # Combined key and cert in a single file
445 ctx.load_cert_chain(CERTFILE)
446 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
447 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000448 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000449 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000450 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000451 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000452 ctx.load_cert_chain(BADCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000453 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000454 ctx.load_cert_chain(EMPTYCERT)
455 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000456 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000457 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
458 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
459 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000460 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000461 ctx.load_cert_chain(ONLYCERT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000462 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000463 ctx.load_cert_chain(ONLYKEY)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000464 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000465 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
466 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000467 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000468 with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000469 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou4fd1e6a2011-08-25 14:39:44 +0200470 # Password protected key and cert
471 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
472 ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
473 ctx.load_cert_chain(CERTFILE_PROTECTED,
474 password=bytearray(KEY_PASSWORD.encode()))
475 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD)
476 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode())
477 ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED,
478 bytearray(KEY_PASSWORD.encode()))
479 with self.assertRaisesRegex(TypeError, "should be a string"):
480 ctx.load_cert_chain(CERTFILE_PROTECTED, password=True)
481 with self.assertRaises(ssl.SSLError):
482 ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass")
483 with self.assertRaisesRegex(ValueError, "cannot be longer"):
484 # openssl has a fixed limit on the password buffer.
485 # PEM_BUFSIZE is generally set to 1kb.
486 # Return a string larger than this.
487 ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400)
488 # Password callback
489 def getpass_unicode():
490 return KEY_PASSWORD
491 def getpass_bytes():
492 return KEY_PASSWORD.encode()
493 def getpass_bytearray():
494 return bytearray(KEY_PASSWORD.encode())
495 def getpass_badpass():
496 return "badpass"
497 def getpass_huge():
498 return b'a' * (1024 * 1024)
499 def getpass_bad_type():
500 return 9
501 def getpass_exception():
502 raise Exception('getpass error')
503 class GetPassCallable:
504 def __call__(self):
505 return KEY_PASSWORD
506 def getpass(self):
507 return KEY_PASSWORD
508 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode)
509 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes)
510 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray)
511 ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable())
512 ctx.load_cert_chain(CERTFILE_PROTECTED,
513 password=GetPassCallable().getpass)
514 with self.assertRaises(ssl.SSLError):
515 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass)
516 with self.assertRaisesRegex(ValueError, "cannot be longer"):
517 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge)
518 with self.assertRaisesRegex(TypeError, "must return a string"):
519 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type)
520 with self.assertRaisesRegex(Exception, "getpass error"):
521 ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception)
522 # Make sure the password function isn't called if it isn't needed
523 ctx.load_cert_chain(CERTFILE, password=getpass_exception)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000524
525 def test_load_verify_locations(self):
526 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
527 ctx.load_verify_locations(CERTFILE)
528 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
529 ctx.load_verify_locations(BYTES_CERTFILE)
530 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
531 self.assertRaises(TypeError, ctx.load_verify_locations)
532 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000533 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000534 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000535 self.assertEqual(cm.exception.errno, errno.ENOENT)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000536 with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000537 ctx.load_verify_locations(BADCERT)
538 ctx.load_verify_locations(CERTFILE, CAPATH)
539 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
540
Victor Stinner80f75e62011-01-29 11:31:20 +0000541 # Issue #10989: crash if the second argument type is invalid
542 self.assertRaises(TypeError, ctx.load_verify_locations, None, True)
543
Antoine Pitrou0e576f12011-12-22 10:03:38 +0100544 def test_load_dh_params(self):
545 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
546 ctx.load_dh_params(DHFILE)
547 if os.name != 'nt':
548 ctx.load_dh_params(BYTES_DHFILE)
549 self.assertRaises(TypeError, ctx.load_dh_params)
550 self.assertRaises(TypeError, ctx.load_dh_params, None)
551 with self.assertRaises(FileNotFoundError) as cm:
552 ctx.load_dh_params(WRONGCERT)
553 self.assertEqual(cm.exception.errno, errno.ENOENT)
554 with self.assertRaisesRegex(ssl.SSLError, "PEM routines"):
555 ctx.load_dh_params(CERTFILE)
556
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000557 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000558 def test_session_stats(self):
559 for proto in PROTOCOLS:
560 ctx = ssl.SSLContext(proto)
561 self.assertEqual(ctx.session_stats(), {
562 'number': 0,
563 'connect': 0,
564 'connect_good': 0,
565 'connect_renegotiate': 0,
566 'accept': 0,
567 'accept_good': 0,
568 'accept_renegotiate': 0,
569 'hits': 0,
570 'misses': 0,
571 'timeouts': 0,
572 'cache_full': 0,
573 })
574
Antoine Pitrou664c2d12010-11-17 20:29:42 +0000575 def test_set_default_verify_paths(self):
576 # There's not much we can do to test that it acts as expected,
577 # so just check it doesn't crash or raise an exception.
578 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
579 ctx.set_default_verify_paths()
580
Antoine Pitrou501da612011-12-21 09:27:41 +0100581 @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
Antoine Pitrou923df6f2011-12-19 17:16:51 +0100582 def test_set_ecdh_curve(self):
583 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
584 ctx.set_ecdh_curve("prime256v1")
585 ctx.set_ecdh_curve(b"prime256v1")
586 self.assertRaises(TypeError, ctx.set_ecdh_curve)
587 self.assertRaises(TypeError, ctx.set_ecdh_curve, None)
588 self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo")
589 self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
590
Antoine Pitrou152efa22010-05-16 18:19:27 +0000591
Bill Janssen6e027db2007-11-15 22:23:56 +0000592class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000593
Antoine Pitrou480a1242010-04-28 21:37:09 +0000594 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000595 with support.transient_internet("svn.python.org"):
596 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
597 cert_reqs=ssl.CERT_NONE)
598 try:
599 s.connect(("svn.python.org", 443))
600 self.assertEqual({}, s.getpeercert())
601 finally:
602 s.close()
603
604 # this should fail because we have no verification certs
605 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
606 cert_reqs=ssl.CERT_REQUIRED)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000607 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
608 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000609 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000610
Antoine Pitrou350c7222010-09-09 13:31:46 +0000611 # this should succeed because we specify the root cert
612 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
613 cert_reqs=ssl.CERT_REQUIRED,
614 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
615 try:
616 s.connect(("svn.python.org", 443))
617 self.assertTrue(s.getpeercert())
618 finally:
619 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000620
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000621 def test_connect_ex(self):
622 # Issue #11326: check connect_ex() implementation
623 with support.transient_internet("svn.python.org"):
624 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
625 cert_reqs=ssl.CERT_REQUIRED,
626 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
627 try:
628 self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
629 self.assertTrue(s.getpeercert())
630 finally:
631 s.close()
632
633 def test_non_blocking_connect_ex(self):
634 # Issue #11326: non-blocking connect_ex() should allow handshake
635 # to proceed after the socket gets ready.
636 with support.transient_internet("svn.python.org"):
637 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
638 cert_reqs=ssl.CERT_REQUIRED,
639 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
640 do_handshake_on_connect=False)
641 try:
642 s.setblocking(False)
643 rc = s.connect_ex(('svn.python.org', 443))
Antoine Pitrou8a14a0c2011-02-27 15:44:12 +0000644 # EWOULDBLOCK under Windows, EINPROGRESS elsewhere
645 self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000646 # Wait for connect to finish
647 select.select([], [s], [], 5.0)
648 # Non-blocking handshake
649 while True:
650 try:
651 s.do_handshake()
652 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200653 except ssl.SSLWantReadError:
654 select.select([s], [], [], 5.0)
655 except ssl.SSLWantWriteError:
656 select.select([], [s], [], 5.0)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000657 # SSL established
658 self.assertTrue(s.getpeercert())
659 finally:
660 s.close()
661
Antoine Pitroub4410db2011-05-18 18:51:06 +0200662 def test_timeout_connect_ex(self):
663 # Issue #12065: on a timeout, connect_ex() should return the original
664 # errno (mimicking the behaviour of non-SSL sockets).
665 with support.transient_internet("svn.python.org"):
666 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
667 cert_reqs=ssl.CERT_REQUIRED,
668 ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
669 do_handshake_on_connect=False)
670 try:
671 s.settimeout(0.0000001)
672 rc = s.connect_ex(('svn.python.org', 443))
673 if rc == 0:
674 self.skipTest("svn.python.org responded too quickly")
675 self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
676 finally:
677 s.close()
678
Antoine Pitrou152efa22010-05-16 18:19:27 +0000679 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000680 with support.transient_internet("svn.python.org"):
681 # Same as test_connect, but with a separately created context
682 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
683 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
684 s.connect(("svn.python.org", 443))
685 try:
686 self.assertEqual({}, s.getpeercert())
687 finally:
688 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000689 # Same with a server hostname
690 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
691 server_hostname="svn.python.org")
692 if ssl.HAS_SNI:
693 s.connect(("svn.python.org", 443))
694 s.close()
695 else:
696 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000697 # This should fail because we have no verification certs
698 ctx.verify_mode = ssl.CERT_REQUIRED
699 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
Ezio Melottied3a7d22010-12-01 02:32:32 +0000700 self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
Antoine Pitrou350c7222010-09-09 13:31:46 +0000701 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000702 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000703 # This should succeed because we specify the root cert
704 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
705 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
706 s.connect(("svn.python.org", 443))
707 try:
708 cert = s.getpeercert()
709 self.assertTrue(cert)
710 finally:
711 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000712
713 def test_connect_capath(self):
714 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000715 # NOTE: the subject hashing algorithm has been changed between
716 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
717 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000718 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000719 with support.transient_internet("svn.python.org"):
720 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
721 ctx.verify_mode = ssl.CERT_REQUIRED
722 ctx.load_verify_locations(capath=CAPATH)
723 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
724 s.connect(("svn.python.org", 443))
725 try:
726 cert = s.getpeercert()
727 self.assertTrue(cert)
728 finally:
729 s.close()
730 # Same with a bytes `capath` argument
731 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
732 ctx.verify_mode = ssl.CERT_REQUIRED
733 ctx.load_verify_locations(capath=BYTES_CAPATH)
734 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
735 s.connect(("svn.python.org", 443))
736 try:
737 cert = s.getpeercert()
738 self.assertTrue(cert)
739 finally:
740 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000741
Antoine Pitroue3220242010-04-24 11:13:53 +0000742 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
743 def test_makefile_close(self):
744 # Issue #5238: creating a file-like object with makefile() shouldn't
745 # delay closing the underlying "real socket" (here tested with its
746 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000747 with support.transient_internet("svn.python.org"):
748 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
749 ss.connect(("svn.python.org", 443))
750 fd = ss.fileno()
751 f = ss.makefile()
752 f.close()
753 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000754 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000755 # Closing the SSL socket should close the fd too
756 ss.close()
757 gc.collect()
758 with self.assertRaises(OSError) as e:
759 os.read(fd, 0)
760 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000761
Antoine Pitrou480a1242010-04-28 21:37:09 +0000762 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000763 with support.transient_internet("svn.python.org"):
764 s = socket.socket(socket.AF_INET)
765 s.connect(("svn.python.org", 443))
766 s.setblocking(False)
767 s = ssl.wrap_socket(s,
768 cert_reqs=ssl.CERT_NONE,
769 do_handshake_on_connect=False)
770 count = 0
771 while True:
772 try:
773 count += 1
774 s.do_handshake()
775 break
Antoine Pitrou41032a62011-10-27 23:56:55 +0200776 except ssl.SSLWantReadError:
777 select.select([s], [], [])
778 except ssl.SSLWantWriteError:
779 select.select([], [s], [])
Antoine Pitrou350c7222010-09-09 13:31:46 +0000780 s.close()
781 if support.verbose:
782 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000783
Antoine Pitrou480a1242010-04-28 21:37:09 +0000784 def test_get_server_certificate(self):
Antoine Pitrou15399c32011-04-28 19:23:55 +0200785 def _test_get_server_certificate(host, port, cert=None):
786 with support.transient_internet(host):
787 pem = ssl.get_server_certificate((host, port))
788 if not pem:
789 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200790
Antoine Pitrou15399c32011-04-28 19:23:55 +0200791 try:
792 pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
793 except ssl.SSLError as x:
794 #should fail
795 if support.verbose:
796 sys.stdout.write("%s\n" % x)
797 else:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200798 self.fail("Got server certificate %s for %s:%s!" % (pem, host, port))
799
Antoine Pitrou15399c32011-04-28 19:23:55 +0200800 pem = ssl.get_server_certificate((host, port), ca_certs=cert)
801 if not pem:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200802 self.fail("No server certificate on %s:%s!" % (host, port))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000803 if support.verbose:
Antoine Pitrou5aefa662011-04-28 19:24:46 +0200804 sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000805
Antoine Pitrou15399c32011-04-28 19:23:55 +0200806 _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
807 if support.IPV6_ENABLED:
808 _test_get_server_certificate('ipv6.google.com', 443)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000809
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000810 def test_ciphers(self):
811 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000812 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000813 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000814 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000815 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000816 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
817 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
818 s.connect(remote)
819 # Error checking can happen at instantiation or when connecting
Ezio Melottied3a7d22010-12-01 02:32:32 +0000820 with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000821 with socket.socket(socket.AF_INET) as sock:
822 s = ssl.wrap_socket(sock,
823 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
824 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000825
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000826 def test_algorithms(self):
827 # Issue #8484: all algorithms should be available when verifying a
828 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000829 # SHA256 was added in OpenSSL 0.9.8
830 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
831 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Victor Stinnerf332abb2011-01-08 03:16:05 +0000832 # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host)
833 remote = ("sha256.tbs-internet.com", 443)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000834 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou160fd932011-01-08 10:23:29 +0000835 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000836 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
837 cert_reqs=ssl.CERT_REQUIRED,
838 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000839 try:
840 s.connect(remote)
841 if support.verbose:
842 sys.stdout.write("\nCipher with %r is %r\n" %
843 (remote, s.cipher()))
844 sys.stdout.write("Certificate is:\n%s\n" %
845 pprint.pformat(s.getpeercert()))
846 finally:
847 s.close()
848
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000849
850try:
851 import threading
852except ImportError:
853 _have_threads = False
854else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000855 _have_threads = True
856
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000857 from test.ssl_servers import make_https_server
858
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000859 class ThreadedEchoServer(threading.Thread):
860
861 class ConnectionHandler(threading.Thread):
862
863 """A mildly complicated class, because we want it to work both
864 with and without the SSL wrapper around the socket connection, so
865 that we can test the STARTTLS functionality."""
866
Bill Janssen6e027db2007-11-15 22:23:56 +0000867 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000868 self.server = server
869 self.running = False
870 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000871 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000872 self.sock.setblocking(1)
873 self.sslconn = None
874 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000875 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000876
Antoine Pitrou480a1242010-04-28 21:37:09 +0000877 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000878 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000879 self.sslconn = self.server.context.wrap_socket(
880 self.sock, server_side=True)
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100881 except ssl.SSLError as e:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000882 # XXX Various errors can have happened here, for example
883 # a mismatching protocol version, an invalid certificate,
884 # or a low-level bug. This should be made more discriminating.
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100885 self.server.conn_errors.append(e)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000886 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000887 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000888 self.running = False
889 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000890 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000891 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000892 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000893 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000894 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000895 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000896 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
897 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000898 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000899 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
900 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000901 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000902 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
903 return True
904
905 def read(self):
906 if self.sslconn:
907 return self.sslconn.read()
908 else:
909 return self.sock.recv(1024)
910
911 def write(self, bytes):
912 if self.sslconn:
913 return self.sslconn.write(bytes)
914 else:
915 return self.sock.send(bytes)
916
917 def close(self):
918 if self.sslconn:
919 self.sslconn.close()
920 else:
921 self.sock.close()
922
Antoine Pitrou480a1242010-04-28 21:37:09 +0000923 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000924 self.running = True
925 if not self.server.starttls_server:
926 if not self.wrap_conn():
927 return
928 while self.running:
929 try:
930 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000931 stripped = msg.strip()
932 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000933 # eof, so quit this handler
934 self.running = False
935 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000936 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000937 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000938 sys.stdout.write(" server: client closed connection\n")
939 self.close()
940 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000941 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000942 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000943 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000944 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000945 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000946 if not self.wrap_conn():
947 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000948 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000949 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000950 if support.verbose and self.server.connectionchatty:
951 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000952 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000953 self.sock = self.sslconn.unwrap()
954 self.sslconn = None
955 if support.verbose and self.server.connectionchatty:
956 sys.stdout.write(" server: connection is now unencrypted...\n")
Antoine Pitroud6494802011-07-21 01:11:30 +0200957 elif stripped == b'CB tls-unique':
958 if support.verbose and self.server.connectionchatty:
959 sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n")
960 data = self.sslconn.get_channel_binding("tls-unique")
961 self.write(repr(data).encode("us-ascii") + b"\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000962 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000963 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000964 self.server.connectionchatty):
965 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000966 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
967 % (msg, ctype, msg.lower(), ctype))
968 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000969 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000970 if self.server.chatty:
971 handle_error("Test server failure:\n")
972 self.close()
973 self.running = False
974 # normally, we'd just stop here, but for the test
975 # harness, we want to stop the server
976 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000977
Antoine Pitroub5218772010-05-21 09:56:06 +0000978 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000979 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000980 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000981 ciphers=None, context=None):
982 if context:
983 self.context = context
984 else:
985 self.context = ssl.SSLContext(ssl_version
986 if ssl_version is not None
987 else ssl.PROTOCOL_TLSv1)
988 self.context.verify_mode = (certreqs if certreqs is not None
989 else ssl.CERT_NONE)
990 if cacerts:
991 self.context.load_verify_locations(cacerts)
992 if certificate:
993 self.context.load_cert_chain(certificate)
994 if ciphers:
995 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000996 self.chatty = chatty
997 self.connectionchatty = connectionchatty
998 self.starttls_server = starttls_server
999 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001000 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001001 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002 self.active = False
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001003 self.conn_errors = []
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001004 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001005 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001006
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001007 def __enter__(self):
1008 self.start(threading.Event())
1009 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001010 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001011
1012 def __exit__(self, *args):
1013 self.stop()
1014 self.join()
1015
Antoine Pitrou480a1242010-04-28 21:37:09 +00001016 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001017 self.flag = flag
1018 threading.Thread.start(self)
1019
Antoine Pitrou480a1242010-04-28 21:37:09 +00001020 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +00001021 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001022 self.sock.listen(5)
1023 self.active = True
1024 if self.flag:
1025 # signal an event
1026 self.flag.set()
1027 while self.active:
1028 try:
1029 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001030 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001031 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +00001032 + repr(connaddr) + '\n')
1033 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034 handler.start()
1035 except socket.timeout:
1036 pass
1037 except KeyboardInterrupt:
1038 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +00001039 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001040
Antoine Pitrou480a1242010-04-28 21:37:09 +00001041 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001042 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001043
Bill Janssen54cc54c2007-12-14 22:08:56 +00001044 class AsyncoreEchoServer(threading.Thread):
1045
1046 # this one's based on asyncore.dispatcher
1047
1048 class EchoServer (asyncore.dispatcher):
1049
1050 class ConnectionHandler (asyncore.dispatcher_with_send):
1051
1052 def __init__(self, conn, certfile):
1053 self.socket = ssl.wrap_socket(conn, server_side=True,
1054 certfile=certfile,
1055 do_handshake_on_connect=False)
1056 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001057 self._ssl_accepting = True
1058 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001059
1060 def readable(self):
1061 if isinstance(self.socket, ssl.SSLSocket):
1062 while self.socket.pending() > 0:
1063 self.handle_read_event()
1064 return True
1065
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001066 def _do_ssl_handshake(self):
1067 try:
1068 self.socket.do_handshake()
Antoine Pitrou41032a62011-10-27 23:56:55 +02001069 except (ssl.SSLWantReadError, ssl.SSLWantWriteError):
1070 return
1071 except ssl.SSLEOFError:
1072 return self.handle_close()
1073 except ssl.SSLError:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001074 raise
1075 except socket.error as err:
1076 if err.args[0] == errno.ECONNABORTED:
1077 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +00001078 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001079 self._ssl_accepting = False
1080
1081 def handle_read(self):
1082 if self._ssl_accepting:
1083 self._do_ssl_handshake()
1084 else:
1085 data = self.recv(1024)
1086 if support.verbose:
1087 sys.stdout.write(" server: read %s from client\n" % repr(data))
1088 if not data:
1089 self.close()
1090 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001091 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +00001092
1093 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +00001094 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001095 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001096 sys.stdout.write(" server: closed connection %s\n" % self.socket)
1097
1098 def handle_error(self):
1099 raise
1100
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001101 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001102 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001103 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1104 self.port = support.bind_port(sock, '')
1105 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +00001106 self.listen(5)
1107
Giampaolo Rodolà977c7072010-10-04 21:08:36 +00001108 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001109 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +00001110 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
1111 self.ConnectionHandler(sock_obj, self.certfile)
1112
1113 def handle_error(self):
1114 raise
1115
Trent Nelson78520002008-04-10 20:54:35 +00001116 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001117 self.flag = None
1118 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001119 self.server = self.EchoServer(certfile)
1120 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +00001121 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +00001122 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +00001123
1124 def __str__(self):
1125 return "<%s %s>" % (self.__class__.__name__, self.server)
1126
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001127 def __enter__(self):
1128 self.start(threading.Event())
1129 self.flag.wait()
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001130 return self
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001131
1132 def __exit__(self, *args):
1133 if support.verbose:
1134 sys.stdout.write(" cleanup: stopping server.\n")
1135 self.stop()
1136 if support.verbose:
1137 sys.stdout.write(" cleanup: joining server thread.\n")
1138 self.join()
1139 if support.verbose:
1140 sys.stdout.write(" cleanup: successfully joined.\n")
1141
Bill Janssen54cc54c2007-12-14 22:08:56 +00001142 def start (self, flag=None):
1143 self.flag = flag
1144 threading.Thread.start(self)
1145
Antoine Pitrou480a1242010-04-28 21:37:09 +00001146 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001147 self.active = True
1148 if self.flag:
1149 self.flag.set()
1150 while self.active:
1151 try:
1152 asyncore.loop(1)
1153 except:
1154 pass
1155
Antoine Pitrou480a1242010-04-28 21:37:09 +00001156 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +00001157 self.active = False
1158 self.server.close()
1159
Antoine Pitrou480a1242010-04-28 21:37:09 +00001160 def bad_cert_test(certfile):
1161 """
1162 Launch a server with CERT_REQUIRED, and check that trying to
1163 connect to it with the given client certificate fails.
1164 """
Trent Nelson78520002008-04-10 20:54:35 +00001165 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +00001167 cacerts=CERTFILE, chatty=False,
1168 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001169 with server:
Thomas Woutersed03b412007-08-28 21:37:11 +00001170 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +00001171 with socket.socket() as sock:
1172 s = ssl.wrap_socket(sock,
1173 certfile=certfile,
1174 ssl_version=ssl.PROTOCOL_TLSv1)
1175 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001176 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001177 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001178 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +00001179 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001180 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +00001181 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001182 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001183 if x.errno != errno.ENOENT:
1184 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +00001185 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +00001186 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001187 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001188 raise AssertionError("Use of invalid cert should have failed!")
Thomas Woutersed03b412007-08-28 21:37:11 +00001189
Antoine Pitroub5218772010-05-21 09:56:06 +00001190 def server_params_test(client_context, server_context, indata=b"FOO\n",
1191 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +00001192 """
1193 Launch a server, connect a client to it and try various reads
1194 and writes.
1195 """
Antoine Pitroub5218772010-05-21 09:56:06 +00001196 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001197 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +00001198 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001199 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001200 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001201 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001202 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001203 if connectionchatty:
1204 if support.verbose:
1205 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001206 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001207 s.write(arg)
1208 outdata = s.read()
1209 if connectionchatty:
1210 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001211 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +00001212 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001213 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001214 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1215 % (outdata[:20], len(outdata),
1216 indata[:20].lower(), len(indata)))
1217 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001218 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001219 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001220 sys.stdout.write(" client: closing connection.\n")
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001221 stats = {
1222 'compression': s.compression(),
1223 'cipher': s.cipher(),
1224 }
Bill Janssen6e027db2007-11-15 22:23:56 +00001225 s.close()
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001226 return stats
Thomas Woutersed03b412007-08-28 21:37:11 +00001227
Antoine Pitroub5218772010-05-21 09:56:06 +00001228 def try_protocol_combo(server_protocol, client_protocol, expect_success,
1229 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +00001230 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001231 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +00001232 certtype = {
1233 ssl.CERT_NONE: "CERT_NONE",
1234 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
1235 ssl.CERT_REQUIRED: "CERT_REQUIRED",
1236 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001237 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001238 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001239 sys.stdout.write(formatstr %
1240 (ssl.get_protocol_name(client_protocol),
1241 ssl.get_protocol_name(server_protocol),
1242 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +00001243 client_context = ssl.SSLContext(client_protocol)
1244 client_context.options = ssl.OP_ALL | client_options
1245 server_context = ssl.SSLContext(server_protocol)
1246 server_context.options = ssl.OP_ALL | server_options
1247 for ctx in (client_context, server_context):
1248 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +00001249 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
1250 # will send an SSLv3 hello (rather than SSLv2) starting from
1251 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +00001252 ctx.set_ciphers("ALL")
1253 ctx.load_cert_chain(CERTFILE)
1254 ctx.load_verify_locations(CERTFILE)
1255 try:
1256 server_params_test(client_context, server_context,
1257 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001258 # Protocol mismatch can result in either an SSLError, or a
1259 # "Connection reset by peer" error.
1260 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001261 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001262 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001263 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001264 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001265 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001266 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001267 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001268 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001269 "Client protocol %s succeeded with server protocol %s!"
1270 % (ssl.get_protocol_name(client_protocol),
1271 ssl.get_protocol_name(server_protocol)))
1272
1273
Bill Janssen6e027db2007-11-15 22:23:56 +00001274 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001275
Antoine Pitrou23df4832010-08-04 17:14:06 +00001276 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001277 def test_echo(self):
1278 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001279 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001280 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001281 for protocol in PROTOCOLS:
1282 context = ssl.SSLContext(protocol)
1283 context.load_cert_chain(CERTFILE)
1284 server_params_test(context, context,
1285 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001286
Antoine Pitrou480a1242010-04-28 21:37:09 +00001287 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001288 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001289 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001290 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1291 context.verify_mode = ssl.CERT_REQUIRED
1292 context.load_verify_locations(CERTFILE)
1293 context.load_cert_chain(CERTFILE)
1294 server = ThreadedEchoServer(context=context, chatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001295 with server:
Antoine Pitroub5218772010-05-21 09:56:06 +00001296 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001297 s.connect((HOST, server.port))
1298 cert = s.getpeercert()
1299 self.assertTrue(cert, "Can't get peer certificate.")
1300 cipher = s.cipher()
1301 if support.verbose:
1302 sys.stdout.write(pprint.pformat(cert) + '\n')
1303 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1304 if 'subject' not in cert:
1305 self.fail("No subject field in certificate: %s." %
1306 pprint.pformat(cert))
1307 if ((('organizationName', 'Python Software Foundation'),)
1308 not in cert['subject']):
1309 self.fail(
1310 "Missing or invalid 'organizationName' field in certificate subject; "
1311 "should be 'Python Software Foundation'.")
Antoine Pitroufb046912010-11-09 20:21:19 +00001312 self.assertIn('notBefore', cert)
1313 self.assertIn('notAfter', cert)
1314 before = ssl.cert_time_to_seconds(cert['notBefore'])
1315 after = ssl.cert_time_to_seconds(cert['notAfter'])
1316 self.assertLess(before, after)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001317 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001318
Antoine Pitrou480a1242010-04-28 21:37:09 +00001319 def test_empty_cert(self):
1320 """Connecting with an empty cert file"""
1321 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1322 "nullcert.pem"))
1323 def test_malformed_cert(self):
1324 """Connecting with a badly formatted certificate (syntax error)"""
1325 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1326 "badcert.pem"))
1327 def test_nonexisting_cert(self):
1328 """Connecting with a non-existing cert file"""
1329 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1330 "wrongcert.pem"))
1331 def test_malformed_key(self):
1332 """Connecting with a badly formatted key (syntax error)"""
1333 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1334 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001335
Antoine Pitrou480a1242010-04-28 21:37:09 +00001336 def test_rude_shutdown(self):
1337 """A brutal shutdown of an SSL server should raise an IOError
1338 in the client when attempting handshake.
1339 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001340 listener_ready = threading.Event()
1341 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001342
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001343 s = socket.socket()
1344 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001345
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001346 # `listener` runs in a thread. It sits in an accept() until
1347 # the main thread connects. Then it rudely closes the socket,
1348 # and sets Event `listener_gone` to let the main thread know
1349 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001350 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001351 s.listen(5)
1352 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001353 newsock, addr = s.accept()
1354 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001355 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001356 listener_gone.set()
1357
1358 def connector():
1359 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001360 with socket.socket() as c:
1361 c.connect((HOST, port))
1362 listener_gone.wait()
1363 try:
1364 ssl_sock = ssl.wrap_socket(c)
1365 except IOError:
1366 pass
1367 else:
1368 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001369
1370 t = threading.Thread(target=listener)
1371 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001372 try:
1373 connector()
1374 finally:
1375 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001376
Antoine Pitrou23df4832010-08-04 17:14:06 +00001377 @skip_if_broken_ubuntu_ssl
Victor Stinner3de49192011-05-09 00:42:58 +02001378 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
1379 "OpenSSL is compiled without SSLv2 support")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001380 def test_protocol_sslv2(self):
1381 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001382 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001383 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001384 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1385 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1386 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1387 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1388 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1389 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001390 # SSLv23 client with specific SSL options
1391 if no_sslv2_implies_sslv3_hello():
1392 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1393 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1394 client_options=ssl.OP_NO_SSLv2)
1395 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1396 client_options=ssl.OP_NO_SSLv3)
1397 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1398 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001399
Antoine Pitrou23df4832010-08-04 17:14:06 +00001400 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001401 def test_protocol_sslv23(self):
1402 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001403 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001404 sys.stdout.write("\n")
Victor Stinner3de49192011-05-09 00:42:58 +02001405 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1406 try:
1407 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
1408 except (ssl.SSLError, socket.error) as x:
1409 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
1410 if support.verbose:
1411 sys.stdout.write(
1412 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1413 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001414 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1415 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1416 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001417
Antoine Pitrou480a1242010-04-28 21:37:09 +00001418 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1419 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1420 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001421
Antoine Pitrou480a1242010-04-28 21:37:09 +00001422 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1423 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1424 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001425
Antoine Pitroub5218772010-05-21 09:56:06 +00001426 # Server with specific SSL options
1427 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1428 server_options=ssl.OP_NO_SSLv3)
1429 # Will choose TLSv1
1430 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1431 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1432 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1433 server_options=ssl.OP_NO_TLSv1)
1434
1435
Antoine Pitrou23df4832010-08-04 17:14:06 +00001436 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001437 def test_protocol_sslv3(self):
1438 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001439 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001440 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001441 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1442 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1443 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001444 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1445 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001446 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
1447 client_options=ssl.OP_NO_SSLv3)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001448 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001449 if no_sslv2_implies_sslv3_hello():
1450 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1451 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1452 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001453
Antoine Pitrou23df4832010-08-04 17:14:06 +00001454 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001455 def test_protocol_tlsv1(self):
1456 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001457 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001458 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001459 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1460 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1461 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinner3de49192011-05-09 00:42:58 +02001462 if hasattr(ssl, 'PROTOCOL_SSLv2'):
1463 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001464 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
Barry Warsaw46ae0ef2011-10-28 16:52:17 -04001465 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
1466 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001467
Antoine Pitrou480a1242010-04-28 21:37:09 +00001468 def test_starttls(self):
1469 """Switching from clear text to encrypted and back again."""
1470 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 +00001471
Trent Nelson78520002008-04-10 20:54:35 +00001472 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001473 ssl_version=ssl.PROTOCOL_TLSv1,
1474 starttls_server=True,
1475 chatty=True,
1476 connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001477 wrapped = False
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001478 with server:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001479 s = socket.socket()
1480 s.setblocking(1)
1481 s.connect((HOST, server.port))
1482 if support.verbose:
1483 sys.stdout.write("\n")
1484 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001485 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001486 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001487 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001488 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001489 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001490 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001491 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001492 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001493 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001494 msg = outdata.strip().lower()
1495 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1496 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001497 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001498 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001499 " client: read %r from server, starting TLS...\n"
1500 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001501 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1502 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001503 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1504 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001505 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001506 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001507 " client: read %r from server, ending TLS...\n"
1508 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001509 s = conn.unwrap()
1510 wrapped = False
1511 else:
1512 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001513 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001514 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001515 if support.verbose:
1516 sys.stdout.write(" client: closing connection.\n")
1517 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001518 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001519 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001520 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001521 if wrapped:
1522 conn.close()
1523 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001524 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001525
Antoine Pitrou480a1242010-04-28 21:37:09 +00001526 def test_socketserver(self):
1527 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001528 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001529 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001530 if support.verbose:
1531 sys.stdout.write('\n')
1532 with open(CERTFILE, 'rb') as f:
1533 d1 = f.read()
1534 d2 = ''
1535 # now fetch the same data from the HTTPS server
1536 url = 'https://%s:%d/%s' % (
1537 HOST, server.port, os.path.split(CERTFILE)[1])
1538 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001539 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001540 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001541 if dlen and (int(dlen) > 0):
1542 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001543 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001544 sys.stdout.write(
1545 " client: read %d bytes from remote server '%s'\n"
1546 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001547 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001548 f.close()
1549 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001550
Antoine Pitrou480a1242010-04-28 21:37:09 +00001551 def test_asyncore_server(self):
1552 """Check the example asyncore integration."""
1553 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001554
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001555 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001556 sys.stdout.write("\n")
1557
Antoine Pitrou480a1242010-04-28 21:37:09 +00001558 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001559 server = AsyncoreEchoServer(CERTFILE)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001560 with server:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001561 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001562 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001563 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001564 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001565 " client: sending %r...\n" % indata)
1566 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001567 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001568 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001569 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001570 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001571 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001572 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1573 % (outdata[:20], len(outdata),
1574 indata[:20].lower(), len(indata)))
1575 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001576 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001577 sys.stdout.write(" client: closing connection.\n")
1578 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001579 if support.verbose:
1580 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001581
Antoine Pitrou480a1242010-04-28 21:37:09 +00001582 def test_recv_send(self):
1583 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001584 if support.verbose:
1585 sys.stdout.write("\n")
1586
1587 server = ThreadedEchoServer(CERTFILE,
1588 certreqs=ssl.CERT_NONE,
1589 ssl_version=ssl.PROTOCOL_TLSv1,
1590 cacerts=CERTFILE,
1591 chatty=True,
1592 connectionchatty=False)
Antoine Pitrou65a3f4b2011-12-21 16:52:40 +01001593 with server:
1594 s = ssl.wrap_socket(socket.socket(),
1595 server_side=False,
1596 certfile=CERTFILE,
1597 ca_certs=CERTFILE,
1598 cert_reqs=ssl.CERT_NONE,
1599 ssl_version=ssl.PROTOCOL_TLSv1)
1600 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001601 # helper methods for standardising recv* method signatures
1602 def _recv_into():
1603 b = bytearray(b"\0"*100)
1604 count = s.recv_into(b)
1605 return b[:count]
1606
1607 def _recvfrom_into():
1608 b = bytearray(b"\0"*100)
1609 count, addr = s.recvfrom_into(b)
1610 return b[:count]
1611
1612 # (name, method, whether to expect success, *args)
1613 send_methods = [
1614 ('send', s.send, True, []),
1615 ('sendto', s.sendto, False, ["some.address"]),
1616 ('sendall', s.sendall, True, []),
1617 ]
1618 recv_methods = [
1619 ('recv', s.recv, True, []),
1620 ('recvfrom', s.recvfrom, False, ["some.address"]),
1621 ('recv_into', _recv_into, True, []),
1622 ('recvfrom_into', _recvfrom_into, False, []),
1623 ]
1624 data_prefix = "PREFIX_"
1625
1626 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001627 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001628 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001629 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001630 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001631 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001632 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001633 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001634 "<<{outdata:r}>> ({nout:d}) received; "
1635 "expected <<{indata:r}>> ({nin:d})\n".format(
1636 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001637 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001638 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001639 )
1640 )
1641 except ValueError as e:
1642 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001643 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001644 "Failed to send with method <<{name:s}>>; "
1645 "expected to succeed.\n".format(name=meth_name)
1646 )
1647 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001648 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001649 "Method <<{name:s}>> failed with unexpected "
1650 "exception message: {exp:s}\n".format(
1651 name=meth_name, exp=e
1652 )
1653 )
1654
1655 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001656 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001657 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001658 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001659 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001660 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001661 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001662 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001663 "<<{outdata:r}>> ({nout:d}) received; "
1664 "expected <<{indata:r}>> ({nin:d})\n".format(
1665 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001666 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001667 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001668 )
1669 )
1670 except ValueError as e:
1671 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001672 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001673 "Failed to receive with method <<{name:s}>>; "
1674 "expected to succeed.\n".format(name=meth_name)
1675 )
1676 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001677 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001678 "Method <<{name:s}>> failed with unexpected "
1679 "exception message: {exp:s}\n".format(
1680 name=meth_name, exp=e
1681 )
1682 )
1683 # consume data
1684 s.read()
1685
Nick Coghlan513886a2011-08-28 00:00:27 +10001686 # Make sure sendmsg et al are disallowed to avoid
1687 # inadvertent disclosure of data and/or corruption
1688 # of the encrypted data stream
1689 self.assertRaises(NotImplementedError, s.sendmsg, [b"data"])
1690 self.assertRaises(NotImplementedError, s.recvmsg, 100)
1691 self.assertRaises(NotImplementedError,
1692 s.recvmsg_into, bytearray(100))
1693
Antoine Pitrou480a1242010-04-28 21:37:09 +00001694 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001695 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001696
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001697 def test_handshake_timeout(self):
1698 # Issue #5103: SSL handshake must respect the socket timeout
1699 server = socket.socket(socket.AF_INET)
1700 host = "127.0.0.1"
1701 port = support.bind_port(server)
1702 started = threading.Event()
1703 finish = False
1704
1705 def serve():
1706 server.listen(5)
1707 started.set()
1708 conns = []
1709 while not finish:
1710 r, w, e = select.select([server], [], [], 0.1)
1711 if server in r:
1712 # Let the socket hang around rather than having
1713 # it closed by garbage collection.
1714 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001715 for sock in conns:
1716 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001717
1718 t = threading.Thread(target=serve)
1719 t.start()
1720 started.wait()
1721
1722 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001723 try:
1724 c = socket.socket(socket.AF_INET)
1725 c.settimeout(0.2)
1726 c.connect((host, port))
1727 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001728 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001729 ssl.wrap_socket, c)
Antoine Pitrou40f08742010-04-24 22:04:40 +00001730 finally:
1731 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001732 try:
1733 c = socket.socket(socket.AF_INET)
1734 c = ssl.wrap_socket(c)
1735 c.settimeout(0.2)
1736 # Will attempt handshake and time out
Antoine Pitrouc4df7842010-12-03 19:59:41 +00001737 self.assertRaisesRegex(socket.timeout, "timed out",
Ezio Melottied3a7d22010-12-01 02:32:32 +00001738 c.connect, (host, port))
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001739 finally:
1740 c.close()
1741 finally:
1742 finish = True
1743 t.join()
1744 server.close()
1745
Antoine Pitrou8f85f902012-01-03 22:46:48 +01001746 def test_default_ciphers(self):
1747 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1748 try:
1749 # Force a set of weak ciphers on our client context
1750 context.set_ciphers("DES")
1751 except ssl.SSLError:
1752 self.skipTest("no DES cipher available")
1753 with ThreadedEchoServer(CERTFILE,
1754 ssl_version=ssl.PROTOCOL_SSLv23,
1755 chatty=False) as server:
1756 with socket.socket() as sock:
1757 s = context.wrap_socket(sock)
1758 with self.assertRaises((OSError, ssl.SSLError)):
1759 s.connect((HOST, server.port))
1760 self.assertIn("no shared cipher", str(server.conn_errors[0]))
1761
Antoine Pitroud6494802011-07-21 01:11:30 +02001762 @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES,
1763 "'tls-unique' channel binding not available")
1764 def test_tls_unique_channel_binding(self):
1765 """Test tls-unique channel binding."""
1766 if support.verbose:
1767 sys.stdout.write("\n")
1768
1769 server = ThreadedEchoServer(CERTFILE,
1770 certreqs=ssl.CERT_NONE,
1771 ssl_version=ssl.PROTOCOL_TLSv1,
1772 cacerts=CERTFILE,
1773 chatty=True,
1774 connectionchatty=False)
Antoine Pitrou6b15c902011-12-21 16:54:45 +01001775 with server:
1776 s = ssl.wrap_socket(socket.socket(),
1777 server_side=False,
1778 certfile=CERTFILE,
1779 ca_certs=CERTFILE,
1780 cert_reqs=ssl.CERT_NONE,
1781 ssl_version=ssl.PROTOCOL_TLSv1)
1782 s.connect((HOST, server.port))
Antoine Pitroud6494802011-07-21 01:11:30 +02001783 # get the data
1784 cb_data = s.get_channel_binding("tls-unique")
1785 if support.verbose:
1786 sys.stdout.write(" got channel binding data: {0!r}\n"
1787 .format(cb_data))
1788
1789 # check if it is sane
1790 self.assertIsNotNone(cb_data)
1791 self.assertEqual(len(cb_data), 12) # True for TLSv1
1792
1793 # and compare with the peers version
1794 s.write(b"CB tls-unique\n")
1795 peer_data_repr = s.read().strip()
1796 self.assertEqual(peer_data_repr,
1797 repr(cb_data).encode("us-ascii"))
1798 s.close()
1799
1800 # now, again
1801 s = ssl.wrap_socket(socket.socket(),
1802 server_side=False,
1803 certfile=CERTFILE,
1804 ca_certs=CERTFILE,
1805 cert_reqs=ssl.CERT_NONE,
1806 ssl_version=ssl.PROTOCOL_TLSv1)
1807 s.connect((HOST, server.port))
1808 new_cb_data = s.get_channel_binding("tls-unique")
1809 if support.verbose:
1810 sys.stdout.write(" got another channel binding data: {0!r}\n"
1811 .format(new_cb_data))
1812 # is it really unique
1813 self.assertNotEqual(cb_data, new_cb_data)
1814 self.assertIsNotNone(cb_data)
1815 self.assertEqual(len(cb_data), 12) # True for TLSv1
1816 s.write(b"CB tls-unique\n")
1817 peer_data_repr = s.read().strip()
1818 self.assertEqual(peer_data_repr,
1819 repr(new_cb_data).encode("us-ascii"))
1820 s.close()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001821
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001822 def test_compression(self):
1823 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1824 context.load_cert_chain(CERTFILE)
1825 stats = server_params_test(context, context,
1826 chatty=True, connectionchatty=True)
1827 if support.verbose:
1828 sys.stdout.write(" got compression: {!r}\n".format(stats['compression']))
1829 self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' })
1830
1831 @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'),
1832 "ssl.OP_NO_COMPRESSION needed for this test")
1833 def test_compression_disabled(self):
1834 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1835 context.load_cert_chain(CERTFILE)
Antoine Pitrou8691bff2011-12-20 10:47:42 +01001836 context.options |= ssl.OP_NO_COMPRESSION
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001837 stats = server_params_test(context, context,
1838 chatty=True, connectionchatty=True)
1839 self.assertIs(stats['compression'], None)
1840
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001841 def test_dh_params(self):
1842 # Check we can get a connection with ephemeral Diffie-Hellman
1843 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
1844 context.load_cert_chain(CERTFILE)
1845 context.load_dh_params(DHFILE)
1846 context.set_ciphers("kEDH")
1847 stats = server_params_test(context, context,
1848 chatty=True, connectionchatty=True)
1849 cipher = stats["cipher"][0]
1850 parts = cipher.split("-")
1851 if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
1852 self.fail("Non-DH cipher: " + cipher[0])
1853
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +01001854
Thomas Woutersed03b412007-08-28 21:37:11 +00001855def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001856 if support.verbose:
1857 plats = {
1858 'Linux': platform.linux_distribution,
1859 'Mac': platform.mac_ver,
1860 'Windows': platform.win32_ver,
1861 }
1862 for name, func in plats.items():
1863 plat = func()
1864 if plat and plat[0]:
1865 plat = '%s %r' % (name, plat)
1866 break
1867 else:
1868 plat = repr(platform.platform())
1869 print("test_ssl: testing with %r %r" %
1870 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1871 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001872 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001873
Antoine Pitrou152efa22010-05-16 18:19:27 +00001874 for filename in [
1875 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1876 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1877 BADCERT, BADKEY, EMPTYCERT]:
1878 if not os.path.exists(filename):
1879 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001880
Antoine Pitrou152efa22010-05-16 18:19:27 +00001881 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001882
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001883 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001884 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001885
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001886 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001887 thread_info = support.threading_setup()
1888 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001889 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001890
Antoine Pitrou480a1242010-04-28 21:37:09 +00001891 try:
1892 support.run_unittest(*tests)
1893 finally:
1894 if _have_threads:
1895 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001896
1897if __name__ == "__main__":
1898 test_main()