blob: 4f29a647b882b69f6fab7c8352912a23221791af [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
Jeremy Hylton1afc1692008-06-18 20:49:58 +000014import urllib.parse, 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
Georg Brandl24420152008-05-26 16:32:26 +000021from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000022
Thomas Woutersed03b412007-08-28 21:37:11 +000023# Optionally test SSL support, if we have it in the tested platform
24skip_expected = False
25try:
26 import ssl
27except ImportError:
28 skip_expected = True
Antoine Pitrou27ba6382010-05-16 20:35:03 +000029else:
30 PROTOCOLS = [
31 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
32 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
33 ]
Thomas Woutersed03b412007-08-28 21:37:11 +000034
Benjamin Petersonee8712c2008-05-20 21:35:26 +000035HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000036
37data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000038
39CERTFILE = 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 Pitrou152efa22010-05-16 18:19:27 +000045CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000046BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000047
48SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
49
50EMPTYCERT = data_file("nullcert.pem")
51BADCERT = data_file("badcert.pem")
52WRONGCERT = data_file("XXXnonexisting.pem")
53BADKEY = data_file("badkey.pem")
54
Thomas Woutersed03b412007-08-28 21:37:11 +000055
Thomas Woutersed03b412007-08-28 21:37:11 +000056def handle_error(prefix):
57 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000058 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000059 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000060
Antoine Pitroub5218772010-05-21 09:56:06 +000061def can_clear_options():
62 # 0.9.8m or higher
63 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
64
65def no_sslv2_implies_sslv3_hello():
66 # 0.9.7h or higher
67 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
68
Thomas Woutersed03b412007-08-28 21:37:11 +000069
Antoine Pitrou23df4832010-08-04 17:14:06 +000070# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
71def skip_if_broken_ubuntu_ssl(func):
72 @functools.wraps(func)
73 def f(*args, **kwargs):
74 try:
75 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
76 except ssl.SSLError:
77 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
78 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
79 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
80 return func(*args, **kwargs)
81 return f
82
83
Antoine Pitrou152efa22010-05-16 18:19:27 +000084class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000085
Antoine Pitrou480a1242010-04-28 21:37:09 +000086 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000087 ssl.PROTOCOL_SSLv2
88 ssl.PROTOCOL_SSLv23
89 ssl.PROTOCOL_SSLv3
90 ssl.PROTOCOL_TLSv1
91 ssl.CERT_NONE
92 ssl.CERT_OPTIONAL
93 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000094
Antoine Pitrou480a1242010-04-28 21:37:09 +000095 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000096 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000097 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098 sys.stdout.write("\n RAND_status is %d (%s)\n"
99 % (v, (v and "sufficient randomness") or
100 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000101 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000102 ssl.RAND_egd(1)
103 except TypeError:
104 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000105 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 print("didn't raise TypeError")
107 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000108
Antoine Pitrou480a1242010-04-28 21:37:09 +0000109 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000110 # note that this uses an 'unofficial' function in _ssl.c,
111 # provided solely for this test, to exercise the certificate
112 # parsing code
113 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000114 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000116
Antoine Pitrou480a1242010-04-28 21:37:09 +0000117 def test_DER_to_PEM(self):
118 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
119 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 d1 = ssl.PEM_cert_to_DER_cert(pem)
121 p2 = ssl.DER_cert_to_PEM_cert(d1)
122 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000123 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000124 if not p2.startswith(ssl.PEM_HEADER + '\n'):
125 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
126 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
127 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000129 def test_openssl_version(self):
130 n = ssl.OPENSSL_VERSION_NUMBER
131 t = ssl.OPENSSL_VERSION_INFO
132 s = ssl.OPENSSL_VERSION
133 self.assertIsInstance(n, int)
134 self.assertIsInstance(t, tuple)
135 self.assertIsInstance(s, str)
136 # Some sanity checks follow
137 # >= 0.9
138 self.assertGreaterEqual(n, 0x900000)
139 # < 2.0
140 self.assertLess(n, 0x20000000)
141 major, minor, fix, patch, status = t
142 self.assertGreaterEqual(major, 0)
143 self.assertLess(major, 2)
144 self.assertGreaterEqual(minor, 0)
145 self.assertLess(minor, 256)
146 self.assertGreaterEqual(fix, 0)
147 self.assertLess(fix, 256)
148 self.assertGreaterEqual(patch, 0)
149 self.assertLessEqual(patch, 26)
150 self.assertGreaterEqual(status, 0)
151 self.assertLessEqual(status, 15)
152 # Version string as returned by OpenSSL, the format might change
153 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
154 (s, t))
155
Antoine Pitrou9d543662010-04-23 23:10:32 +0000156 @support.cpython_only
157 def test_refcycle(self):
158 # Issue #7943: an SSL object doesn't create reference cycles with
159 # itself.
160 s = socket.socket(socket.AF_INET)
161 ss = ssl.wrap_socket(s)
162 wr = weakref.ref(ss)
163 del ss
164 self.assertEqual(wr(), None)
165
Antoine Pitroua468adc2010-09-14 14:43:44 +0000166 def test_wrapped_unconnected(self):
167 # Methods on an unconnected SSLSocket propagate the original
168 # socket.error raise by the underlying socket object.
169 s = socket.socket(socket.AF_INET)
170 ss = ssl.wrap_socket(s)
171 self.assertRaises(socket.error, ss.recv, 1)
172 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
173 self.assertRaises(socket.error, ss.recvfrom, 1)
174 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
175 self.assertRaises(socket.error, ss.send, b'x')
176 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
177
Antoine Pitrou40f08742010-04-24 22:04:40 +0000178 def test_timeout(self):
179 # Issue #8524: when creating an SSL socket, the timeout of the
180 # original socket should be retained.
181 for timeout in (None, 0.0, 5.0):
182 s = socket.socket(socket.AF_INET)
183 s.settimeout(timeout)
184 ss = ssl.wrap_socket(s)
185 self.assertEqual(timeout, ss.gettimeout())
186
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000187 def test_errors(self):
188 sock = socket.socket()
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000189 self.assertRaisesRegexp(ValueError,
190 "certfile must be specified",
191 ssl.wrap_socket, sock, keyfile=CERTFILE)
192 self.assertRaisesRegexp(ValueError,
193 "certfile must be specified for server-side operations",
194 ssl.wrap_socket, sock, server_side=True)
195 self.assertRaisesRegexp(ValueError,
196 "certfile must be specified for server-side operations",
197 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000198 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
199 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
200 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000201 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000202 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000203 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000204 with self.assertRaises(IOError) as cm:
205 ssl.wrap_socket(socket.socket(), certfile=CERTFILE, keyfile=WRONGCERT)
206 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000207 with self.assertRaises(IOError) as cm:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000208 ssl.wrap_socket(socket.socket(), certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000209 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000210
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000211
Antoine Pitrou152efa22010-05-16 18:19:27 +0000212class ContextTests(unittest.TestCase):
213
Antoine Pitrou23df4832010-08-04 17:14:06 +0000214 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000215 def test_constructor(self):
216 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
217 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
218 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
219 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
220 self.assertRaises(TypeError, ssl.SSLContext)
221 self.assertRaises(ValueError, ssl.SSLContext, -1)
222 self.assertRaises(ValueError, ssl.SSLContext, 42)
223
Antoine Pitrou23df4832010-08-04 17:14:06 +0000224 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000225 def test_protocol(self):
226 for proto in PROTOCOLS:
227 ctx = ssl.SSLContext(proto)
228 self.assertEqual(ctx.protocol, proto)
229
230 def test_ciphers(self):
231 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
232 ctx.set_ciphers("ALL")
233 ctx.set_ciphers("DEFAULT")
234 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000235 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000236
Antoine Pitrou23df4832010-08-04 17:14:06 +0000237 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000238 def test_options(self):
239 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
240 # OP_ALL is the default value
241 self.assertEqual(ssl.OP_ALL, ctx.options)
242 ctx.options |= ssl.OP_NO_SSLv2
243 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
244 ctx.options)
245 ctx.options |= ssl.OP_NO_SSLv3
246 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
247 ctx.options)
248 if can_clear_options():
249 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
250 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
251 ctx.options)
252 ctx.options = 0
253 self.assertEqual(0, ctx.options)
254 else:
255 with self.assertRaises(ValueError):
256 ctx.options = 0
257
Antoine Pitrou152efa22010-05-16 18:19:27 +0000258 def test_verify(self):
259 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
260 # Default value
261 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
262 ctx.verify_mode = ssl.CERT_OPTIONAL
263 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
264 ctx.verify_mode = ssl.CERT_REQUIRED
265 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
266 ctx.verify_mode = ssl.CERT_NONE
267 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
268 with self.assertRaises(TypeError):
269 ctx.verify_mode = None
270 with self.assertRaises(ValueError):
271 ctx.verify_mode = 42
272
273 def test_load_cert_chain(self):
274 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
275 # Combined key and cert in a single file
276 ctx.load_cert_chain(CERTFILE)
277 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
278 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000279 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000280 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000281 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000282 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
283 ctx.load_cert_chain(BADCERT)
284 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
285 ctx.load_cert_chain(EMPTYCERT)
286 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000287 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000288 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
289 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
290 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
291 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
292 ctx.load_cert_chain(ONLYCERT)
293 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
294 ctx.load_cert_chain(ONLYKEY)
295 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
296 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
297 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000298 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000299 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
300 ctx.load_cert_chain(CERTFILE, ONLYKEY)
301
302 def test_load_verify_locations(self):
303 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
304 ctx.load_verify_locations(CERTFILE)
305 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
306 ctx.load_verify_locations(BYTES_CERTFILE)
307 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
308 self.assertRaises(TypeError, ctx.load_verify_locations)
309 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000310 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000311 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000312 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000313 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
314 ctx.load_verify_locations(BADCERT)
315 ctx.load_verify_locations(CERTFILE, CAPATH)
316 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
317
318
Bill Janssen6e027db2007-11-15 22:23:56 +0000319class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000320
Antoine Pitrou480a1242010-04-28 21:37:09 +0000321 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000322 with support.transient_internet("svn.python.org"):
323 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
324 cert_reqs=ssl.CERT_NONE)
325 try:
326 s.connect(("svn.python.org", 443))
327 self.assertEqual({}, s.getpeercert())
328 finally:
329 s.close()
330
331 # this should fail because we have no verification certs
332 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
333 cert_reqs=ssl.CERT_REQUIRED)
334 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
335 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000336 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000337
Antoine Pitrou350c7222010-09-09 13:31:46 +0000338 # this should succeed because we specify the root cert
339 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
340 cert_reqs=ssl.CERT_REQUIRED,
341 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
342 try:
343 s.connect(("svn.python.org", 443))
344 self.assertTrue(s.getpeercert())
345 finally:
346 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000347
348 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000349 with support.transient_internet("svn.python.org"):
350 # Same as test_connect, but with a separately created context
351 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
352 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
353 s.connect(("svn.python.org", 443))
354 try:
355 self.assertEqual({}, s.getpeercert())
356 finally:
357 s.close()
358 # This should fail because we have no verification certs
359 ctx.verify_mode = ssl.CERT_REQUIRED
360 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
361 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
362 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000363 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000364 # This should succeed because we specify the root cert
365 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
366 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
367 s.connect(("svn.python.org", 443))
368 try:
369 cert = s.getpeercert()
370 self.assertTrue(cert)
371 finally:
372 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000373
374 def test_connect_capath(self):
375 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000376 # NOTE: the subject hashing algorithm has been changed between
377 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
378 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000379 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000380 with support.transient_internet("svn.python.org"):
381 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
382 ctx.verify_mode = ssl.CERT_REQUIRED
383 ctx.load_verify_locations(capath=CAPATH)
384 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
385 s.connect(("svn.python.org", 443))
386 try:
387 cert = s.getpeercert()
388 self.assertTrue(cert)
389 finally:
390 s.close()
391 # Same with a bytes `capath` argument
392 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
393 ctx.verify_mode = ssl.CERT_REQUIRED
394 ctx.load_verify_locations(capath=BYTES_CAPATH)
395 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
396 s.connect(("svn.python.org", 443))
397 try:
398 cert = s.getpeercert()
399 self.assertTrue(cert)
400 finally:
401 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000402
Antoine Pitroue3220242010-04-24 11:13:53 +0000403 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
404 def test_makefile_close(self):
405 # Issue #5238: creating a file-like object with makefile() shouldn't
406 # delay closing the underlying "real socket" (here tested with its
407 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000408 with support.transient_internet("svn.python.org"):
409 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
410 ss.connect(("svn.python.org", 443))
411 fd = ss.fileno()
412 f = ss.makefile()
413 f.close()
414 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000415 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000416 # Closing the SSL socket should close the fd too
417 ss.close()
418 gc.collect()
419 with self.assertRaises(OSError) as e:
420 os.read(fd, 0)
421 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000422
Antoine Pitrou480a1242010-04-28 21:37:09 +0000423 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000424 with support.transient_internet("svn.python.org"):
425 s = socket.socket(socket.AF_INET)
426 s.connect(("svn.python.org", 443))
427 s.setblocking(False)
428 s = ssl.wrap_socket(s,
429 cert_reqs=ssl.CERT_NONE,
430 do_handshake_on_connect=False)
431 count = 0
432 while True:
433 try:
434 count += 1
435 s.do_handshake()
436 break
437 except ssl.SSLError as err:
438 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
439 select.select([s], [], [])
440 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
441 select.select([], [s], [])
442 else:
443 raise
444 s.close()
445 if support.verbose:
446 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000447
Antoine Pitrou480a1242010-04-28 21:37:09 +0000448 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000449 with support.transient_internet("svn.python.org"):
450 pem = ssl.get_server_certificate(("svn.python.org", 443))
451 if not pem:
452 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000453
Antoine Pitrou350c7222010-09-09 13:31:46 +0000454 try:
455 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
456 except ssl.SSLError as x:
457 #should fail
458 if support.verbose:
459 sys.stdout.write("%s\n" % x)
460 else:
461 self.fail("Got server certificate %s for svn.python.org!" % pem)
462
463 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
464 if not pem:
465 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000466 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000467 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000468
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000469 def test_ciphers(self):
470 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000471 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000472 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000473 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000474 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000475 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
476 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
477 s.connect(remote)
478 # Error checking can happen at instantiation or when connecting
479 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
480 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
481 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
482 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000483
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000484 def test_algorithms(self):
485 # Issue #8484: all algorithms should be available when verifying a
486 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000487 # SHA256 was added in OpenSSL 0.9.8
488 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
489 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000490 # NOTE: https://sha256.tbs-internet.com is another possible test host
491 remote = ("sha2.hboeck.de", 443)
492 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000493 with support.transient_internet("sha2.hboeck.de"):
494 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
495 cert_reqs=ssl.CERT_REQUIRED,
496 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000497 try:
498 s.connect(remote)
499 if support.verbose:
500 sys.stdout.write("\nCipher with %r is %r\n" %
501 (remote, s.cipher()))
502 sys.stdout.write("Certificate is:\n%s\n" %
503 pprint.pformat(s.getpeercert()))
504 finally:
505 s.close()
506
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000507
508try:
509 import threading
510except ImportError:
511 _have_threads = False
512else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000513 _have_threads = True
514
515 class ThreadedEchoServer(threading.Thread):
516
517 class ConnectionHandler(threading.Thread):
518
519 """A mildly complicated class, because we want it to work both
520 with and without the SSL wrapper around the socket connection, so
521 that we can test the STARTTLS functionality."""
522
Bill Janssen6e027db2007-11-15 22:23:56 +0000523 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000524 self.server = server
525 self.running = False
526 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000527 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000528 self.sock.setblocking(1)
529 self.sslconn = None
530 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000531 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000532
Antoine Pitrou480a1242010-04-28 21:37:09 +0000533 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000534 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000535 self.sslconn = self.server.context.wrap_socket(
536 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000537 except ssl.SSLError:
538 # XXX Various errors can have happened here, for example
539 # a mismatching protocol version, an invalid certificate,
540 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000541 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000542 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000543 self.running = False
544 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000545 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000546 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000547 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000548 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000549 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000550 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000551 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
552 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000553 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000554 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
555 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000556 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000557 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
558 return True
559
560 def read(self):
561 if self.sslconn:
562 return self.sslconn.read()
563 else:
564 return self.sock.recv(1024)
565
566 def write(self, bytes):
567 if self.sslconn:
568 return self.sslconn.write(bytes)
569 else:
570 return self.sock.send(bytes)
571
572 def close(self):
573 if self.sslconn:
574 self.sslconn.close()
575 else:
576 self.sock.close()
577
Antoine Pitrou480a1242010-04-28 21:37:09 +0000578 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000579 self.running = True
580 if not self.server.starttls_server:
581 if not self.wrap_conn():
582 return
583 while self.running:
584 try:
585 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000586 stripped = msg.strip()
587 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000588 # eof, so quit this handler
589 self.running = False
590 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000591 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000592 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000593 sys.stdout.write(" server: client closed connection\n")
594 self.close()
595 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000596 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000597 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000598 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000599 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000600 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000601 if not self.wrap_conn():
602 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000603 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000604 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000605 if support.verbose and self.server.connectionchatty:
606 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000607 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000608 self.sock = self.sslconn.unwrap()
609 self.sslconn = None
610 if support.verbose and self.server.connectionchatty:
611 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000612 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000613 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000614 self.server.connectionchatty):
615 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000616 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
617 % (msg, ctype, msg.lower(), ctype))
618 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000619 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000620 if self.server.chatty:
621 handle_error("Test server failure:\n")
622 self.close()
623 self.running = False
624 # normally, we'd just stop here, but for the test
625 # harness, we want to stop the server
626 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000627
Antoine Pitroub5218772010-05-21 09:56:06 +0000628 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000629 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000630 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000631 ciphers=None, context=None):
632 if context:
633 self.context = context
634 else:
635 self.context = ssl.SSLContext(ssl_version
636 if ssl_version is not None
637 else ssl.PROTOCOL_TLSv1)
638 self.context.verify_mode = (certreqs if certreqs is not None
639 else ssl.CERT_NONE)
640 if cacerts:
641 self.context.load_verify_locations(cacerts)
642 if certificate:
643 self.context.load_cert_chain(certificate)
644 if ciphers:
645 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000646 self.chatty = chatty
647 self.connectionchatty = connectionchatty
648 self.starttls_server = starttls_server
649 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000650 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000651 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000652 self.active = False
653 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000654 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000655
Antoine Pitrou480a1242010-04-28 21:37:09 +0000656 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000657 self.flag = flag
658 threading.Thread.start(self)
659
Antoine Pitrou480a1242010-04-28 21:37:09 +0000660 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000661 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000662 self.sock.listen(5)
663 self.active = True
664 if self.flag:
665 # signal an event
666 self.flag.set()
667 while self.active:
668 try:
669 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000670 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000671 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000672 + repr(connaddr) + '\n')
673 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000674 handler.start()
675 except socket.timeout:
676 pass
677 except KeyboardInterrupt:
678 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000679 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000680
Antoine Pitrou480a1242010-04-28 21:37:09 +0000681 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000682 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000683
Bill Janssen54cc54c2007-12-14 22:08:56 +0000684 class OurHTTPSServer(threading.Thread):
685
686 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000687
688 class HTTPSServer(HTTPServer):
689
690 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000691 HTTPServer.__init__(self, server_address, RequestHandlerClass)
692 # we assume the certfile contains both private key and certificate
693 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000694 self.allow_reuse_address = True
695
Bill Janssen6e027db2007-11-15 22:23:56 +0000696 def __str__(self):
697 return ('<%s %s:%s>' %
698 (self.__class__.__name__,
699 self.server_name,
700 self.server_port))
701
Antoine Pitrou480a1242010-04-28 21:37:09 +0000702 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000703 # override this to wrap socket with SSL
704 sock, addr = self.socket.accept()
705 sslconn = ssl.wrap_socket(sock, server_side=True,
706 certfile=self.certfile)
707 return sslconn, addr
708
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000709 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000710 # need to override translate_path to get a known root,
711 # instead of using os.curdir, since the test could be
712 # run from anywhere
713
714 server_version = "TestHTTPS/1.0"
715
716 root = None
717
718 def translate_path(self, path):
719 """Translate a /-separated PATH to the local filename syntax.
720
721 Components that mean special things to the local file system
722 (e.g. drive or directory names) are ignored. (XXX They should
723 probably be diagnosed.)
724
725 """
726 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000727 path = urllib.parse.urlparse(path)[2]
728 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000729 words = path.split('/')
730 words = filter(None, words)
731 path = self.root
732 for word in words:
733 drive, word = os.path.splitdrive(word)
734 head, word = os.path.split(word)
735 if word in self.root: continue
736 path = os.path.join(path, word)
737 return path
738
739 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000740 # we override this to suppress logging unless "verbose"
741
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000742 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000743 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
744 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000745 self.server.server_port,
746 self.request.cipher(),
747 self.log_date_time_string(),
748 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000749
750
Trent Nelson78520002008-04-10 20:54:35 +0000751 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000752 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000753 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
754 self.server = self.HTTPSServer(
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000755 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
756 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000757 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000758 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000759
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000760 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000761 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000762
Antoine Pitrou480a1242010-04-28 21:37:09 +0000763 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000764 self.flag = flag
765 threading.Thread.start(self)
766
Antoine Pitrou480a1242010-04-28 21:37:09 +0000767 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000768 if self.flag:
769 self.flag.set()
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000770 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000771
Antoine Pitrou480a1242010-04-28 21:37:09 +0000772 def stop(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000773 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000774
775
Bill Janssen54cc54c2007-12-14 22:08:56 +0000776 class AsyncoreEchoServer(threading.Thread):
777
778 # this one's based on asyncore.dispatcher
779
780 class EchoServer (asyncore.dispatcher):
781
782 class ConnectionHandler (asyncore.dispatcher_with_send):
783
784 def __init__(self, conn, certfile):
785 self.socket = ssl.wrap_socket(conn, server_side=True,
786 certfile=certfile,
787 do_handshake_on_connect=False)
788 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000789 self._ssl_accepting = True
790 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000791
792 def readable(self):
793 if isinstance(self.socket, ssl.SSLSocket):
794 while self.socket.pending() > 0:
795 self.handle_read_event()
796 return True
797
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000798 def _do_ssl_handshake(self):
799 try:
800 self.socket.do_handshake()
801 except ssl.SSLError as err:
802 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
803 ssl.SSL_ERROR_WANT_WRITE):
804 return
805 elif err.args[0] == ssl.SSL_ERROR_EOF:
806 return self.handle_close()
807 raise
808 except socket.error as err:
809 if err.args[0] == errno.ECONNABORTED:
810 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000811 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000812 self._ssl_accepting = False
813
814 def handle_read(self):
815 if self._ssl_accepting:
816 self._do_ssl_handshake()
817 else:
818 data = self.recv(1024)
819 if support.verbose:
820 sys.stdout.write(" server: read %s from client\n" % repr(data))
821 if not data:
822 self.close()
823 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000824 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000825
826 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000827 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000828 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000829 sys.stdout.write(" server: closed connection %s\n" % self.socket)
830
831 def handle_error(self):
832 raise
833
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000834 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000835 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000836 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
837 self.port = support.bind_port(sock, '')
838 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000839 self.listen(5)
840
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000841 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000842 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000843 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
844 self.ConnectionHandler(sock_obj, self.certfile)
845
846 def handle_error(self):
847 raise
848
Trent Nelson78520002008-04-10 20:54:35 +0000849 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000850 self.flag = None
851 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000852 self.server = self.EchoServer(certfile)
853 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000854 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000855 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000856
857 def __str__(self):
858 return "<%s %s>" % (self.__class__.__name__, self.server)
859
860 def start (self, flag=None):
861 self.flag = flag
862 threading.Thread.start(self)
863
Antoine Pitrou480a1242010-04-28 21:37:09 +0000864 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000865 self.active = True
866 if self.flag:
867 self.flag.set()
868 while self.active:
869 try:
870 asyncore.loop(1)
871 except:
872 pass
873
Antoine Pitrou480a1242010-04-28 21:37:09 +0000874 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000875 self.active = False
876 self.server.close()
877
Antoine Pitrou480a1242010-04-28 21:37:09 +0000878 def bad_cert_test(certfile):
879 """
880 Launch a server with CERT_REQUIRED, and check that trying to
881 connect to it with the given client certificate fails.
882 """
Trent Nelson78520002008-04-10 20:54:35 +0000883 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000884 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000885 cacerts=CERTFILE, chatty=False,
886 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000887 flag = threading.Event()
888 server.start(flag)
889 # wait for it to start
890 flag.wait()
891 # try to connect
892 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000893 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000894 s = ssl.wrap_socket(socket.socket(),
895 certfile=certfile,
896 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000897 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000898 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000899 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000900 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000901 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000902 if support.verbose:
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000903 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000904 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000905 if x.errno != errno.ENOENT:
906 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000907 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000908 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000910 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000911 finally:
912 server.stop()
913 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000914
Antoine Pitroub5218772010-05-21 09:56:06 +0000915 def server_params_test(client_context, server_context, indata=b"FOO\n",
916 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000917 """
918 Launch a server, connect a client to it and try various reads
919 and writes.
920 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000921 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000922 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000923 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000924 flag = threading.Event()
925 server.start(flag)
926 # wait for it to start
927 flag.wait()
928 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000929 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000930 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000931 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000932 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000933 if connectionchatty:
934 if support.verbose:
935 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000936 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000937 s.write(arg)
938 outdata = s.read()
939 if connectionchatty:
940 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000941 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000942 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000943 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000944 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
945 % (outdata[:20], len(outdata),
946 indata[:20].lower(), len(indata)))
947 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000948 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000949 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000950 sys.stdout.write(" client: closing connection.\n")
951 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000952 finally:
953 server.stop()
954 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000955
Antoine Pitroub5218772010-05-21 09:56:06 +0000956 def try_protocol_combo(server_protocol, client_protocol, expect_success,
957 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000958 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000959 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000960 certtype = {
961 ssl.CERT_NONE: "CERT_NONE",
962 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
963 ssl.CERT_REQUIRED: "CERT_REQUIRED",
964 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000965 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000966 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000967 sys.stdout.write(formatstr %
968 (ssl.get_protocol_name(client_protocol),
969 ssl.get_protocol_name(server_protocol),
970 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000971 client_context = ssl.SSLContext(client_protocol)
972 client_context.options = ssl.OP_ALL | client_options
973 server_context = ssl.SSLContext(server_protocol)
974 server_context.options = ssl.OP_ALL | server_options
975 for ctx in (client_context, server_context):
976 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000977 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
978 # will send an SSLv3 hello (rather than SSLv2) starting from
979 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000980 ctx.set_ciphers("ALL")
981 ctx.load_cert_chain(CERTFILE)
982 ctx.load_verify_locations(CERTFILE)
983 try:
984 server_params_test(client_context, server_context,
985 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000986 # Protocol mismatch can result in either an SSLError, or a
987 # "Connection reset by peer" error.
988 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000989 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000991 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000992 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000993 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000994 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000995 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000996 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000997 "Client protocol %s succeeded with server protocol %s!"
998 % (ssl.get_protocol_name(client_protocol),
999 ssl.get_protocol_name(server_protocol)))
1000
1001
Bill Janssen6e027db2007-11-15 22:23:56 +00001002 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003
Antoine Pitrou23df4832010-08-04 17:14:06 +00001004 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001005 def test_echo(self):
1006 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001007 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001008 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001009 for protocol in PROTOCOLS:
1010 context = ssl.SSLContext(protocol)
1011 context.load_cert_chain(CERTFILE)
1012 server_params_test(context, context,
1013 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001014
Antoine Pitrou480a1242010-04-28 21:37:09 +00001015 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001016 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001017 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001018 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1019 context.verify_mode = ssl.CERT_REQUIRED
1020 context.load_verify_locations(CERTFILE)
1021 context.load_cert_chain(CERTFILE)
1022 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001023 flag = threading.Event()
1024 server.start(flag)
1025 # wait for it to start
1026 flag.wait()
1027 # try to connect
1028 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001029 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001030 s.connect((HOST, server.port))
1031 cert = s.getpeercert()
1032 self.assertTrue(cert, "Can't get peer certificate.")
1033 cipher = s.cipher()
1034 if support.verbose:
1035 sys.stdout.write(pprint.pformat(cert) + '\n')
1036 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1037 if 'subject' not in cert:
1038 self.fail("No subject field in certificate: %s." %
1039 pprint.pformat(cert))
1040 if ((('organizationName', 'Python Software Foundation'),)
1041 not in cert['subject']):
1042 self.fail(
1043 "Missing or invalid 'organizationName' field in certificate subject; "
1044 "should be 'Python Software Foundation'.")
1045 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001046 finally:
1047 server.stop()
1048 server.join()
1049
Antoine Pitrou480a1242010-04-28 21:37:09 +00001050 def test_empty_cert(self):
1051 """Connecting with an empty cert file"""
1052 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1053 "nullcert.pem"))
1054 def test_malformed_cert(self):
1055 """Connecting with a badly formatted certificate (syntax error)"""
1056 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1057 "badcert.pem"))
1058 def test_nonexisting_cert(self):
1059 """Connecting with a non-existing cert file"""
1060 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1061 "wrongcert.pem"))
1062 def test_malformed_key(self):
1063 """Connecting with a badly formatted key (syntax error)"""
1064 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1065 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001066
Antoine Pitrou480a1242010-04-28 21:37:09 +00001067 def test_rude_shutdown(self):
1068 """A brutal shutdown of an SSL server should raise an IOError
1069 in the client when attempting handshake.
1070 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001071 listener_ready = threading.Event()
1072 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001073
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001074 s = socket.socket()
1075 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001076
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001077 # `listener` runs in a thread. It sits in an accept() until
1078 # the main thread connects. Then it rudely closes the socket,
1079 # and sets Event `listener_gone` to let the main thread know
1080 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001081 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001082 s.listen(5)
1083 listener_ready.set()
1084 s.accept()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001085 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001086 listener_gone.set()
1087
1088 def connector():
1089 listener_ready.wait()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001090 c = socket.socket()
1091 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001092 listener_gone.wait()
1093 try:
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001094 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001095 except IOError:
1096 pass
1097 else:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001098 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001099
1100 t = threading.Thread(target=listener)
1101 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001102 try:
1103 connector()
1104 finally:
1105 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001106
Antoine Pitrou23df4832010-08-04 17:14:06 +00001107 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001108 def test_protocol_sslv2(self):
1109 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001110 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001111 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001112 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1113 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1114 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1115 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1116 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1117 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001118 # SSLv23 client with specific SSL options
1119 if no_sslv2_implies_sslv3_hello():
1120 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1121 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1122 client_options=ssl.OP_NO_SSLv2)
1123 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1124 client_options=ssl.OP_NO_SSLv3)
1125 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1126 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001127
Antoine Pitrou23df4832010-08-04 17:14:06 +00001128 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001129 def test_protocol_sslv23(self):
1130 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001131 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001132 sys.stdout.write("\n")
1133 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001134 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001135 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001136 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001137 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001138 sys.stdout.write(
1139 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1140 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001141 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1142 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1143 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001144
Antoine Pitrou480a1242010-04-28 21:37:09 +00001145 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1146 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1147 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001148
Antoine Pitrou480a1242010-04-28 21:37:09 +00001149 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1150 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1151 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001152
Antoine Pitroub5218772010-05-21 09:56:06 +00001153 # Server with specific SSL options
1154 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1155 server_options=ssl.OP_NO_SSLv3)
1156 # Will choose TLSv1
1157 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1158 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1159 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1160 server_options=ssl.OP_NO_TLSv1)
1161
1162
Antoine Pitrou23df4832010-08-04 17:14:06 +00001163 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001164 def test_protocol_sslv3(self):
1165 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001166 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001167 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001168 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1169 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1170 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1171 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1172 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1173 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001174 if no_sslv2_implies_sslv3_hello():
1175 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1176 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1177 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001178
Antoine Pitrou23df4832010-08-04 17:14:06 +00001179 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001180 def test_protocol_tlsv1(self):
1181 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001182 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001183 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001184 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1185 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1186 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1187 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1188 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1189 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001190
Antoine Pitrou480a1242010-04-28 21:37:09 +00001191 def test_starttls(self):
1192 """Switching from clear text to encrypted and back again."""
1193 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 +00001194
Trent Nelson78520002008-04-10 20:54:35 +00001195 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001196 ssl_version=ssl.PROTOCOL_TLSv1,
1197 starttls_server=True,
1198 chatty=True,
1199 connectionchatty=True)
1200 flag = threading.Event()
1201 server.start(flag)
1202 # wait for it to start
1203 flag.wait()
1204 # try to connect
1205 wrapped = False
1206 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001207 s = socket.socket()
1208 s.setblocking(1)
1209 s.connect((HOST, server.port))
1210 if support.verbose:
1211 sys.stdout.write("\n")
1212 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001213 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001214 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001215 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001216 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001217 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001218 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001219 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001220 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001221 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001222 msg = outdata.strip().lower()
1223 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1224 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001225 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001226 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001227 " client: read %r from server, starting TLS...\n"
1228 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001229 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1230 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001231 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1232 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001233 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001234 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001235 " client: read %r from server, ending TLS...\n"
1236 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001237 s = conn.unwrap()
1238 wrapped = False
1239 else:
1240 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001241 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001242 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001243 if support.verbose:
1244 sys.stdout.write(" client: closing connection.\n")
1245 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001246 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001247 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001248 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001249 if wrapped:
1250 conn.close()
1251 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001252 s.close()
1253 finally:
1254 server.stop()
1255 server.join()
1256
Antoine Pitrou480a1242010-04-28 21:37:09 +00001257 def test_socketserver(self):
1258 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +00001259 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001260 flag = threading.Event()
1261 server.start(flag)
1262 # wait for it to start
1263 flag.wait()
1264 # try to connect
1265 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001266 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001267 sys.stdout.write('\n')
Antoine Pitrou480a1242010-04-28 21:37:09 +00001268 with open(CERTFILE, 'rb') as f:
1269 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001270 d2 = ''
1271 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001272 url = 'https://%s:%d/%s' % (
1273 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001274 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001275 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001276 if dlen and (int(dlen) > 0):
1277 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001278 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001279 sys.stdout.write(
1280 " client: read %d bytes from remote server '%s'\n"
1281 % (len(d2), server))
1282 f.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001283 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001284 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001285 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001286 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001287 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001288 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001289 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001290 server.join()
1291
Antoine Pitrou480a1242010-04-28 21:37:09 +00001292 def test_asyncore_server(self):
1293 """Check the example asyncore integration."""
1294 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001295
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001296 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001297 sys.stdout.write("\n")
1298
Antoine Pitrou480a1242010-04-28 21:37:09 +00001299 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001300 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001301 flag = threading.Event()
1302 server.start(flag)
1303 # wait for it to start
1304 flag.wait()
1305 # try to connect
1306 try:
1307 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001308 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001309 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001310 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001311 " client: sending %r...\n" % indata)
1312 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001313 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001314 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001315 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001316 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001317 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001318 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1319 % (outdata[:20], len(outdata),
1320 indata[:20].lower(), len(indata)))
1321 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001322 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001323 sys.stdout.write(" client: closing connection.\n")
1324 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001325 if support.verbose:
1326 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001327 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001328 if support.verbose:
1329 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001330 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001331 if support.verbose:
1332 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001333 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001334 if support.verbose:
1335 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001336
Antoine Pitrou480a1242010-04-28 21:37:09 +00001337 def test_recv_send(self):
1338 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001339 if support.verbose:
1340 sys.stdout.write("\n")
1341
1342 server = ThreadedEchoServer(CERTFILE,
1343 certreqs=ssl.CERT_NONE,
1344 ssl_version=ssl.PROTOCOL_TLSv1,
1345 cacerts=CERTFILE,
1346 chatty=True,
1347 connectionchatty=False)
1348 flag = threading.Event()
1349 server.start(flag)
1350 # wait for it to start
1351 flag.wait()
1352 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001353 s = ssl.wrap_socket(socket.socket(),
1354 server_side=False,
1355 certfile=CERTFILE,
1356 ca_certs=CERTFILE,
1357 cert_reqs=ssl.CERT_NONE,
1358 ssl_version=ssl.PROTOCOL_TLSv1)
1359 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001360 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001361 # helper methods for standardising recv* method signatures
1362 def _recv_into():
1363 b = bytearray(b"\0"*100)
1364 count = s.recv_into(b)
1365 return b[:count]
1366
1367 def _recvfrom_into():
1368 b = bytearray(b"\0"*100)
1369 count, addr = s.recvfrom_into(b)
1370 return b[:count]
1371
1372 # (name, method, whether to expect success, *args)
1373 send_methods = [
1374 ('send', s.send, True, []),
1375 ('sendto', s.sendto, False, ["some.address"]),
1376 ('sendall', s.sendall, True, []),
1377 ]
1378 recv_methods = [
1379 ('recv', s.recv, True, []),
1380 ('recvfrom', s.recvfrom, False, ["some.address"]),
1381 ('recv_into', _recv_into, True, []),
1382 ('recvfrom_into', _recvfrom_into, False, []),
1383 ]
1384 data_prefix = "PREFIX_"
1385
1386 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001387 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001388 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001389 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001390 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001391 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001392 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001393 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001394 "<<{outdata:r}>> ({nout:d}) received; "
1395 "expected <<{indata:r}>> ({nin:d})\n".format(
1396 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001397 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001398 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001399 )
1400 )
1401 except ValueError as e:
1402 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001403 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001404 "Failed to send with method <<{name:s}>>; "
1405 "expected to succeed.\n".format(name=meth_name)
1406 )
1407 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001408 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001409 "Method <<{name:s}>> failed with unexpected "
1410 "exception message: {exp:s}\n".format(
1411 name=meth_name, exp=e
1412 )
1413 )
1414
1415 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001416 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001417 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001418 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001419 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001420 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001421 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001422 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001423 "<<{outdata:r}>> ({nout:d}) received; "
1424 "expected <<{indata:r}>> ({nin:d})\n".format(
1425 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001426 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001427 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001428 )
1429 )
1430 except ValueError as e:
1431 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001432 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001433 "Failed to receive with method <<{name:s}>>; "
1434 "expected to succeed.\n".format(name=meth_name)
1435 )
1436 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001437 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001438 "Method <<{name:s}>> failed with unexpected "
1439 "exception message: {exp:s}\n".format(
1440 name=meth_name, exp=e
1441 )
1442 )
1443 # consume data
1444 s.read()
1445
Antoine Pitrou480a1242010-04-28 21:37:09 +00001446 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001447 s.close()
1448 finally:
1449 server.stop()
1450 server.join()
1451
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001452 def test_handshake_timeout(self):
1453 # Issue #5103: SSL handshake must respect the socket timeout
1454 server = socket.socket(socket.AF_INET)
1455 host = "127.0.0.1"
1456 port = support.bind_port(server)
1457 started = threading.Event()
1458 finish = False
1459
1460 def serve():
1461 server.listen(5)
1462 started.set()
1463 conns = []
1464 while not finish:
1465 r, w, e = select.select([server], [], [], 0.1)
1466 if server in r:
1467 # Let the socket hang around rather than having
1468 # it closed by garbage collection.
1469 conns.append(server.accept()[0])
1470
1471 t = threading.Thread(target=serve)
1472 t.start()
1473 started.wait()
1474
1475 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001476 try:
1477 c = socket.socket(socket.AF_INET)
1478 c.settimeout(0.2)
1479 c.connect((host, port))
1480 # Will attempt handshake and time out
1481 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1482 ssl.wrap_socket, c)
1483 finally:
1484 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001485 try:
1486 c = socket.socket(socket.AF_INET)
1487 c = ssl.wrap_socket(c)
1488 c.settimeout(0.2)
1489 # Will attempt handshake and time out
1490 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1491 c.connect, (host, port))
1492 finally:
1493 c.close()
1494 finally:
1495 finish = True
1496 t.join()
1497 server.close()
1498
Bill Janssen58afe4c2008-09-08 16:45:19 +00001499
Thomas Woutersed03b412007-08-28 21:37:11 +00001500def test_main(verbose=False):
1501 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001502 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001503
Antoine Pitrou15cee622010-08-04 16:45:21 +00001504 if support.verbose:
1505 plats = {
1506 'Linux': platform.linux_distribution,
1507 'Mac': platform.mac_ver,
1508 'Windows': platform.win32_ver,
1509 }
1510 for name, func in plats.items():
1511 plat = func()
1512 if plat and plat[0]:
1513 plat = '%s %r' % (name, plat)
1514 break
1515 else:
1516 plat = repr(platform.platform())
1517 print("test_ssl: testing with %r %r" %
1518 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1519 print(" under %s" % plat)
1520
Antoine Pitrou152efa22010-05-16 18:19:27 +00001521 for filename in [
1522 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1523 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1524 BADCERT, BADKEY, EMPTYCERT]:
1525 if not os.path.exists(filename):
1526 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001527
Antoine Pitrou152efa22010-05-16 18:19:27 +00001528 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001529
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001530 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001531 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001532
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001533 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001534 thread_info = support.threading_setup()
1535 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001536 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001537
Antoine Pitrou480a1242010-04-28 21:37:09 +00001538 try:
1539 support.run_unittest(*tests)
1540 finally:
1541 if _have_threads:
1542 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001543
1544if __name__ == "__main__":
1545 test_main()