blob: bb9cebf76b41ee52b8dd84505715ecddf0dbabf2 [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 = [
24 ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3,
25 ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
26]
Thomas Woutersed03b412007-08-28 21:37:11 +000027
Benjamin Petersonee8712c2008-05-20 21:35:26 +000028HOST = support.HOST
Antoine Pitrou152efa22010-05-16 18:19:27 +000029
30data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
Antoine Pitrou152efa22010-05-16 18:19:27 +000031
Antoine Pitrou81564092010-10-08 23:06:24 +000032# The custom key and certificate files used in test_ssl are generated
33# using Lib/test/make_ssl_certs.py.
34# Other certificates are simply fetched from the Internet servers they
35# are meant to authenticate.
36
Antoine Pitrou152efa22010-05-16 18:19:27 +000037CERTFILE = data_file("keycert.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000038BYTES_CERTFILE = os.fsencode(CERTFILE)
Antoine Pitrou152efa22010-05-16 18:19:27 +000039ONLYCERT = data_file("ssl_cert.pem")
40ONLYKEY = data_file("ssl_key.pem")
Victor Stinner313a1202010-06-11 23:56:51 +000041BYTES_ONLYCERT = os.fsencode(ONLYCERT)
42BYTES_ONLYKEY = os.fsencode(ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +000043CAPATH = data_file("capath")
Victor Stinner313a1202010-06-11 23:56:51 +000044BYTES_CAPATH = os.fsencode(CAPATH)
Antoine Pitrou152efa22010-05-16 18:19:27 +000045
46SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
47
48EMPTYCERT = data_file("nullcert.pem")
49BADCERT = data_file("badcert.pem")
50WRONGCERT = data_file("XXXnonexisting.pem")
51BADKEY = data_file("badkey.pem")
52
Thomas Woutersed03b412007-08-28 21:37:11 +000053
Thomas Woutersed03b412007-08-28 21:37:11 +000054def handle_error(prefix):
55 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000056 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000057 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000058
Antoine Pitroub5218772010-05-21 09:56:06 +000059def can_clear_options():
60 # 0.9.8m or higher
61 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15)
62
63def no_sslv2_implies_sslv3_hello():
64 # 0.9.7h or higher
65 return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
66
Thomas Woutersed03b412007-08-28 21:37:11 +000067
Antoine Pitrou23df4832010-08-04 17:14:06 +000068# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
69def skip_if_broken_ubuntu_ssl(func):
70 @functools.wraps(func)
71 def f(*args, **kwargs):
72 try:
73 ssl.SSLContext(ssl.PROTOCOL_SSLv2)
74 except ssl.SSLError:
75 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
76 platform.linux_distribution() == ('debian', 'squeeze/sid', '')):
77 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
78 return func(*args, **kwargs)
79 return f
80
81
Antoine Pitrou152efa22010-05-16 18:19:27 +000082class BasicSocketTests(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000083
Antoine Pitrou480a1242010-04-28 21:37:09 +000084 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000085 ssl.PROTOCOL_SSLv2
86 ssl.PROTOCOL_SSLv23
87 ssl.PROTOCOL_SSLv3
88 ssl.PROTOCOL_TLSv1
89 ssl.CERT_NONE
90 ssl.CERT_OPTIONAL
91 ssl.CERT_REQUIRED
Antoine Pitroud5323212010-10-22 18:19:07 +000092 self.assertIn(ssl.HAS_SNI, {True, False})
Thomas Woutersed03b412007-08-28 21:37:11 +000093
Antoine Pitrou480a1242010-04-28 21:37:09 +000094 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000095 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000096 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000097 sys.stdout.write("\n RAND_status is %d (%s)\n"
98 % (v, (v and "sufficient randomness") or
99 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +0000100 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000101 ssl.RAND_egd(1)
102 except TypeError:
103 pass
Thomas Woutersed03b412007-08-28 21:37:11 +0000104 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105 print("didn't raise TypeError")
106 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +0000107
Antoine Pitrou480a1242010-04-28 21:37:09 +0000108 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000109 # note that this uses an 'unofficial' function in _ssl.c,
110 # provided solely for this test, to exercise the certificate
111 # parsing code
112 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000113 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +0000115
Antoine Pitrou480a1242010-04-28 21:37:09 +0000116 def test_DER_to_PEM(self):
117 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
118 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000119 d1 = ssl.PEM_cert_to_DER_cert(pem)
120 p2 = ssl.DER_cert_to_PEM_cert(d1)
121 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000122 self.assertEqual(d1, d2)
Antoine Pitrou9bfbe612010-04-27 22:08:08 +0000123 if not p2.startswith(ssl.PEM_HEADER + '\n'):
124 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
125 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
126 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000127
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000128 def test_openssl_version(self):
129 n = ssl.OPENSSL_VERSION_NUMBER
130 t = ssl.OPENSSL_VERSION_INFO
131 s = ssl.OPENSSL_VERSION
132 self.assertIsInstance(n, int)
133 self.assertIsInstance(t, tuple)
134 self.assertIsInstance(s, str)
135 # Some sanity checks follow
136 # >= 0.9
137 self.assertGreaterEqual(n, 0x900000)
138 # < 2.0
139 self.assertLess(n, 0x20000000)
140 major, minor, fix, patch, status = t
141 self.assertGreaterEqual(major, 0)
142 self.assertLess(major, 2)
143 self.assertGreaterEqual(minor, 0)
144 self.assertLess(minor, 256)
145 self.assertGreaterEqual(fix, 0)
146 self.assertLess(fix, 256)
147 self.assertGreaterEqual(patch, 0)
148 self.assertLessEqual(patch, 26)
149 self.assertGreaterEqual(status, 0)
150 self.assertLessEqual(status, 15)
151 # Version string as returned by OpenSSL, the format might change
152 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
153 (s, t))
154
Antoine Pitrou9d543662010-04-23 23:10:32 +0000155 @support.cpython_only
156 def test_refcycle(self):
157 # Issue #7943: an SSL object doesn't create reference cycles with
158 # itself.
159 s = socket.socket(socket.AF_INET)
160 ss = ssl.wrap_socket(s)
161 wr = weakref.ref(ss)
162 del ss
163 self.assertEqual(wr(), None)
164
Antoine Pitroua468adc2010-09-14 14:43:44 +0000165 def test_wrapped_unconnected(self):
166 # Methods on an unconnected SSLSocket propagate the original
167 # socket.error raise by the underlying socket object.
168 s = socket.socket(socket.AF_INET)
169 ss = ssl.wrap_socket(s)
170 self.assertRaises(socket.error, ss.recv, 1)
171 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
172 self.assertRaises(socket.error, ss.recvfrom, 1)
173 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
174 self.assertRaises(socket.error, ss.send, b'x')
175 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
176
Antoine Pitrou40f08742010-04-24 22:04:40 +0000177 def test_timeout(self):
178 # Issue #8524: when creating an SSL socket, the timeout of the
179 # original socket should be retained.
180 for timeout in (None, 0.0, 5.0):
181 s = socket.socket(socket.AF_INET)
182 s.settimeout(timeout)
183 ss = ssl.wrap_socket(s)
184 self.assertEqual(timeout, ss.gettimeout())
185
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000186 def test_errors(self):
187 sock = socket.socket()
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000188 self.assertRaisesRegexp(ValueError,
189 "certfile must be specified",
190 ssl.wrap_socket, sock, keyfile=CERTFILE)
191 self.assertRaisesRegexp(ValueError,
192 "certfile must be specified for server-side operations",
193 ssl.wrap_socket, sock, server_side=True)
194 self.assertRaisesRegexp(ValueError,
195 "certfile must be specified for server-side operations",
196 ssl.wrap_socket, sock, server_side=True, certfile="")
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000197 s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
198 self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
199 s.connect, (HOST, 8080))
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000200 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000201 with socket.socket() as sock:
202 ssl.wrap_socket(sock, 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:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000205 with socket.socket() as sock:
206 ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
Giampaolo Rodolà8b7da622010-08-30 18:28:05 +0000207 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000208 with self.assertRaises(IOError) as cm:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000209 with socket.socket() as sock:
210 ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000211 self.assertEqual(cm.exception.errno, errno.ENOENT)
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000212
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000213 def test_match_hostname(self):
214 def ok(cert, hostname):
215 ssl.match_hostname(cert, hostname)
216 def fail(cert, hostname):
217 self.assertRaises(ssl.CertificateError,
218 ssl.match_hostname, cert, hostname)
219
220 cert = {'subject': ((('commonName', 'example.com'),),)}
221 ok(cert, 'example.com')
222 ok(cert, 'ExAmple.cOm')
223 fail(cert, 'www.example.com')
224 fail(cert, '.example.com')
225 fail(cert, 'example.org')
226 fail(cert, 'exampleXcom')
227
228 cert = {'subject': ((('commonName', '*.a.com'),),)}
229 ok(cert, 'foo.a.com')
230 fail(cert, 'bar.foo.a.com')
231 fail(cert, 'a.com')
232 fail(cert, 'Xa.com')
233 fail(cert, '.a.com')
234
235 cert = {'subject': ((('commonName', 'a.*.com'),),)}
236 ok(cert, 'a.foo.com')
237 fail(cert, 'a..com')
238 fail(cert, 'a.com')
239
240 cert = {'subject': ((('commonName', 'f*.com'),),)}
241 ok(cert, 'foo.com')
242 ok(cert, 'f.com')
243 fail(cert, 'bar.com')
244 fail(cert, 'foo.a.com')
245 fail(cert, 'bar.foo.com')
246
247 # Slightly fake real-world example
248 cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT',
249 'subject': ((('commonName', 'linuxfrz.org'),),),
250 'subjectAltName': (('DNS', 'linuxfr.org'),
251 ('DNS', 'linuxfr.com'),
252 ('othername', '<unsupported>'))}
253 ok(cert, 'linuxfr.org')
254 ok(cert, 'linuxfr.com')
255 # Not a "DNS" entry
256 fail(cert, '<unsupported>')
257 # When there is a subjectAltName, commonName isn't used
258 fail(cert, 'linuxfrz.org')
259
260 # A pristine real-world example
261 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
262 'subject': ((('countryName', 'US'),),
263 (('stateOrProvinceName', 'California'),),
264 (('localityName', 'Mountain View'),),
265 (('organizationName', 'Google Inc'),),
266 (('commonName', 'mail.google.com'),))}
267 ok(cert, 'mail.google.com')
268 fail(cert, 'gmail.com')
269 # Only commonName is considered
270 fail(cert, 'California')
271
272 # Neither commonName nor subjectAltName
273 cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT',
274 'subject': ((('countryName', 'US'),),
275 (('stateOrProvinceName', 'California'),),
276 (('localityName', 'Mountain View'),),
277 (('organizationName', 'Google Inc'),))}
278 fail(cert, 'mail.google.com')
279
280 # Empty cert / no cert
281 self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com')
282 self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com')
283
Antoine Pitroud5323212010-10-22 18:19:07 +0000284 def test_server_side(self):
285 # server_hostname doesn't work for server sockets
286 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Antoine Pitroud2eca372010-10-29 23:41:37 +0000287 with socket.socket() as sock:
288 self.assertRaises(ValueError, ctx.wrap_socket, sock, True,
289 server_hostname="some.hostname")
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000290
Antoine Pitrou152efa22010-05-16 18:19:27 +0000291class ContextTests(unittest.TestCase):
292
Antoine Pitrou23df4832010-08-04 17:14:06 +0000293 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000294 def test_constructor(self):
295 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
296 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
297 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
298 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
299 self.assertRaises(TypeError, ssl.SSLContext)
300 self.assertRaises(ValueError, ssl.SSLContext, -1)
301 self.assertRaises(ValueError, ssl.SSLContext, 42)
302
Antoine Pitrou23df4832010-08-04 17:14:06 +0000303 @skip_if_broken_ubuntu_ssl
Antoine Pitrou152efa22010-05-16 18:19:27 +0000304 def test_protocol(self):
305 for proto in PROTOCOLS:
306 ctx = ssl.SSLContext(proto)
307 self.assertEqual(ctx.protocol, proto)
308
309 def test_ciphers(self):
310 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
311 ctx.set_ciphers("ALL")
312 ctx.set_ciphers("DEFAULT")
313 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitrou30474062010-05-16 23:46:26 +0000314 ctx.set_ciphers("^$:,;?*'dorothyx")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000315
Antoine Pitrou23df4832010-08-04 17:14:06 +0000316 @skip_if_broken_ubuntu_ssl
Antoine Pitroub5218772010-05-21 09:56:06 +0000317 def test_options(self):
318 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
319 # OP_ALL is the default value
320 self.assertEqual(ssl.OP_ALL, ctx.options)
321 ctx.options |= ssl.OP_NO_SSLv2
322 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2,
323 ctx.options)
324 ctx.options |= ssl.OP_NO_SSLv3
325 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
326 ctx.options)
327 if can_clear_options():
328 ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
329 self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
330 ctx.options)
331 ctx.options = 0
332 self.assertEqual(0, ctx.options)
333 else:
334 with self.assertRaises(ValueError):
335 ctx.options = 0
336
Antoine Pitrou152efa22010-05-16 18:19:27 +0000337 def test_verify(self):
338 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
339 # Default value
340 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
341 ctx.verify_mode = ssl.CERT_OPTIONAL
342 self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
343 ctx.verify_mode = ssl.CERT_REQUIRED
344 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
345 ctx.verify_mode = ssl.CERT_NONE
346 self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
347 with self.assertRaises(TypeError):
348 ctx.verify_mode = None
349 with self.assertRaises(ValueError):
350 ctx.verify_mode = 42
351
352 def test_load_cert_chain(self):
353 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
354 # Combined key and cert in a single file
355 ctx.load_cert_chain(CERTFILE)
356 ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
357 self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000358 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000359 ctx.load_cert_chain(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000360 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000361 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
362 ctx.load_cert_chain(BADCERT)
363 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
364 ctx.load_cert_chain(EMPTYCERT)
365 # Separate key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000366 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000367 ctx.load_cert_chain(ONLYCERT, ONLYKEY)
368 ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY)
369 ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY)
370 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
371 ctx.load_cert_chain(ONLYCERT)
372 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
373 ctx.load_cert_chain(ONLYKEY)
374 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
375 ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT)
376 # Mismatching key and cert
Antoine Pitroud0919502010-05-17 10:30:00 +0000377 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000378 with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"):
Antoine Pitrou81564092010-10-08 23:06:24 +0000379 ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000380
381 def test_load_verify_locations(self):
382 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
383 ctx.load_verify_locations(CERTFILE)
384 ctx.load_verify_locations(cafile=CERTFILE, capath=None)
385 ctx.load_verify_locations(BYTES_CERTFILE)
386 ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
387 self.assertRaises(TypeError, ctx.load_verify_locations)
388 self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000389 with self.assertRaises(IOError) as cm:
Antoine Pitrou152efa22010-05-16 18:19:27 +0000390 ctx.load_verify_locations(WRONGCERT)
Giampaolo Rodolà4a656eb2010-08-29 22:50:39 +0000391 self.assertEqual(cm.exception.errno, errno.ENOENT)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000392 with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
393 ctx.load_verify_locations(BADCERT)
394 ctx.load_verify_locations(CERTFILE, CAPATH)
395 ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
396
Antoine Pitroueb585ad2010-10-22 18:24:20 +0000397 @skip_if_broken_ubuntu_ssl
Antoine Pitroub0182c82010-10-12 20:09:02 +0000398 def test_session_stats(self):
399 for proto in PROTOCOLS:
400 ctx = ssl.SSLContext(proto)
401 self.assertEqual(ctx.session_stats(), {
402 'number': 0,
403 'connect': 0,
404 'connect_good': 0,
405 'connect_renegotiate': 0,
406 'accept': 0,
407 'accept_good': 0,
408 'accept_renegotiate': 0,
409 'hits': 0,
410 'misses': 0,
411 'timeouts': 0,
412 'cache_full': 0,
413 })
414
Antoine Pitrou152efa22010-05-16 18:19:27 +0000415
Bill Janssen6e027db2007-11-15 22:23:56 +0000416class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000417
Antoine Pitrou480a1242010-04-28 21:37:09 +0000418 def test_connect(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000419 with support.transient_internet("svn.python.org"):
420 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
421 cert_reqs=ssl.CERT_NONE)
422 try:
423 s.connect(("svn.python.org", 443))
424 self.assertEqual({}, s.getpeercert())
425 finally:
426 s.close()
427
428 # this should fail because we have no verification certs
429 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
430 cert_reqs=ssl.CERT_REQUIRED)
431 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
432 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000433 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000434
Antoine Pitrou350c7222010-09-09 13:31:46 +0000435 # this should succeed because we specify the root cert
436 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
437 cert_reqs=ssl.CERT_REQUIRED,
438 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
439 try:
440 s.connect(("svn.python.org", 443))
441 self.assertTrue(s.getpeercert())
442 finally:
443 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000444
445 def test_connect_with_context(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000446 with support.transient_internet("svn.python.org"):
447 # Same as test_connect, but with a separately created context
448 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
449 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
450 s.connect(("svn.python.org", 443))
451 try:
452 self.assertEqual({}, s.getpeercert())
453 finally:
454 s.close()
Antoine Pitroud5323212010-10-22 18:19:07 +0000455 # Same with a server hostname
456 s = ctx.wrap_socket(socket.socket(socket.AF_INET),
457 server_hostname="svn.python.org")
458 if ssl.HAS_SNI:
459 s.connect(("svn.python.org", 443))
460 s.close()
461 else:
462 self.assertRaises(ValueError, s.connect, ("svn.python.org", 443))
Antoine Pitrou350c7222010-09-09 13:31:46 +0000463 # This should fail because we have no verification certs
464 ctx.verify_mode = ssl.CERT_REQUIRED
465 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
466 self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed",
467 s.connect, ("svn.python.org", 443))
Antoine Pitrou152efa22010-05-16 18:19:27 +0000468 s.close()
Antoine Pitrou350c7222010-09-09 13:31:46 +0000469 # This should succeed because we specify the root cert
470 ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
471 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
472 s.connect(("svn.python.org", 443))
473 try:
474 cert = s.getpeercert()
475 self.assertTrue(cert)
476 finally:
477 s.close()
Antoine Pitrou152efa22010-05-16 18:19:27 +0000478
479 def test_connect_capath(self):
480 # Verify server certificates using the `capath` argument
Antoine Pitrou467f28d2010-05-16 19:22:44 +0000481 # NOTE: the subject hashing algorithm has been changed between
482 # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
483 # contain both versions of each certificate (same content, different
Antoine Pitroud7e4c1c2010-05-17 14:13:10 +0000484 # filename) for this test to be portable across OpenSSL releases.
Antoine Pitrou350c7222010-09-09 13:31:46 +0000485 with support.transient_internet("svn.python.org"):
486 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
487 ctx.verify_mode = ssl.CERT_REQUIRED
488 ctx.load_verify_locations(capath=CAPATH)
489 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
490 s.connect(("svn.python.org", 443))
491 try:
492 cert = s.getpeercert()
493 self.assertTrue(cert)
494 finally:
495 s.close()
496 # Same with a bytes `capath` argument
497 ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
498 ctx.verify_mode = ssl.CERT_REQUIRED
499 ctx.load_verify_locations(capath=BYTES_CAPATH)
500 s = ctx.wrap_socket(socket.socket(socket.AF_INET))
501 s.connect(("svn.python.org", 443))
502 try:
503 cert = s.getpeercert()
504 self.assertTrue(cert)
505 finally:
506 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000507
Antoine Pitroue3220242010-04-24 11:13:53 +0000508 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
509 def test_makefile_close(self):
510 # Issue #5238: creating a file-like object with makefile() shouldn't
511 # delay closing the underlying "real socket" (here tested with its
512 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou350c7222010-09-09 13:31:46 +0000513 with support.transient_internet("svn.python.org"):
514 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
515 ss.connect(("svn.python.org", 443))
516 fd = ss.fileno()
517 f = ss.makefile()
518 f.close()
519 # The fd is still open
Antoine Pitroue3220242010-04-24 11:13:53 +0000520 os.read(fd, 0)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000521 # Closing the SSL socket should close the fd too
522 ss.close()
523 gc.collect()
524 with self.assertRaises(OSError) as e:
525 os.read(fd, 0)
526 self.assertEqual(e.exception.errno, errno.EBADF)
Antoine Pitroue3220242010-04-24 11:13:53 +0000527
Antoine Pitrou480a1242010-04-28 21:37:09 +0000528 def test_non_blocking_handshake(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000529 with support.transient_internet("svn.python.org"):
530 s = socket.socket(socket.AF_INET)
531 s.connect(("svn.python.org", 443))
532 s.setblocking(False)
533 s = ssl.wrap_socket(s,
534 cert_reqs=ssl.CERT_NONE,
535 do_handshake_on_connect=False)
536 count = 0
537 while True:
538 try:
539 count += 1
540 s.do_handshake()
541 break
542 except ssl.SSLError as err:
543 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
544 select.select([s], [], [])
545 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
546 select.select([], [s], [])
547 else:
548 raise
549 s.close()
550 if support.verbose:
551 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000552
Antoine Pitrou480a1242010-04-28 21:37:09 +0000553 def test_get_server_certificate(self):
Antoine Pitrou350c7222010-09-09 13:31:46 +0000554 with support.transient_internet("svn.python.org"):
555 pem = ssl.get_server_certificate(("svn.python.org", 443))
556 if not pem:
557 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000558
Antoine Pitrou350c7222010-09-09 13:31:46 +0000559 try:
560 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
561 except ssl.SSLError as x:
562 #should fail
563 if support.verbose:
564 sys.stdout.write("%s\n" % x)
565 else:
566 self.fail("Got server certificate %s for svn.python.org!" % pem)
567
568 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
569 if not pem:
570 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000571 if support.verbose:
Antoine Pitrou350c7222010-09-09 13:31:46 +0000572 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000573
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000574 def test_ciphers(self):
575 remote = ("svn.python.org", 443)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000576 with support.transient_internet(remote[0]):
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000577 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
Antoine Pitrou350c7222010-09-09 13:31:46 +0000578 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000579 s.connect(remote)
Antoine Pitrou350c7222010-09-09 13:31:46 +0000580 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
581 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
582 s.connect(remote)
583 # Error checking can happen at instantiation or when connecting
584 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
Antoine Pitroud2eca372010-10-29 23:41:37 +0000585 with socket.socket(socket.AF_INET) as sock:
586 s = ssl.wrap_socket(sock,
587 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
588 s.connect(remote)
Antoine Pitrouf4c7bad2010-08-15 23:02:22 +0000589
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000590 def test_algorithms(self):
591 # Issue #8484: all algorithms should be available when verifying a
592 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000593 # SHA256 was added in OpenSSL 0.9.8
594 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
595 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000596 # NOTE: https://sha256.tbs-internet.com is another possible test host
597 remote = ("sha2.hboeck.de", 443)
598 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitroua88c83c2010-09-07 20:42:19 +0000599 with support.transient_internet("sha2.hboeck.de"):
600 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
601 cert_reqs=ssl.CERT_REQUIRED,
602 ca_certs=sha256_cert,)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000603 try:
604 s.connect(remote)
605 if support.verbose:
606 sys.stdout.write("\nCipher with %r is %r\n" %
607 (remote, s.cipher()))
608 sys.stdout.write("Certificate is:\n%s\n" %
609 pprint.pformat(s.getpeercert()))
610 finally:
611 s.close()
612
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000613
614try:
615 import threading
616except ImportError:
617 _have_threads = False
618else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000619 _have_threads = True
620
Antoine Pitrou803e6d62010-10-13 10:36:15 +0000621 from test.ssl_servers import make_https_server
622
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000623 class ThreadedEchoServer(threading.Thread):
624
625 class ConnectionHandler(threading.Thread):
626
627 """A mildly complicated class, because we want it to work both
628 with and without the SSL wrapper around the socket connection, so
629 that we can test the STARTTLS functionality."""
630
Bill Janssen6e027db2007-11-15 22:23:56 +0000631 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000632 self.server = server
633 self.running = False
634 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000635 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000636 self.sock.setblocking(1)
637 self.sslconn = None
638 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000639 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000640
Antoine Pitrou480a1242010-04-28 21:37:09 +0000641 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000642 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000643 self.sslconn = self.server.context.wrap_socket(
644 self.sock, server_side=True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000645 except ssl.SSLError:
646 # XXX Various errors can have happened here, for example
647 # a mismatching protocol version, an invalid certificate,
648 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000649 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000650 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000651 self.running = False
652 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000653 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000654 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000655 else:
Antoine Pitroub5218772010-05-21 09:56:06 +0000656 if self.server.context.verify_mode == ssl.CERT_REQUIRED:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000657 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000658 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000659 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
660 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000661 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000662 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
663 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000664 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
666 return True
667
668 def read(self):
669 if self.sslconn:
670 return self.sslconn.read()
671 else:
672 return self.sock.recv(1024)
673
674 def write(self, bytes):
675 if self.sslconn:
676 return self.sslconn.write(bytes)
677 else:
678 return self.sock.send(bytes)
679
680 def close(self):
681 if self.sslconn:
682 self.sslconn.close()
683 else:
684 self.sock.close()
685
Antoine Pitrou480a1242010-04-28 21:37:09 +0000686 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000687 self.running = True
688 if not self.server.starttls_server:
689 if not self.wrap_conn():
690 return
691 while self.running:
692 try:
693 msg = self.read()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000694 stripped = msg.strip()
695 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000696 # eof, so quit this handler
697 self.running = False
698 self.close()
Antoine Pitrou480a1242010-04-28 21:37:09 +0000699 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000700 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000701 sys.stdout.write(" server: client closed connection\n")
702 self.close()
703 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000704 elif (self.server.starttls_server and
Antoine Pitrou764b8782010-04-28 22:57:15 +0000705 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000706 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000707 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000708 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000709 if not self.wrap_conn():
710 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000711 elif (self.server.starttls_server and self.sslconn
Antoine Pitrou764b8782010-04-28 22:57:15 +0000712 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000713 if support.verbose and self.server.connectionchatty:
714 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +0000715 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000716 self.sock = self.sslconn.unwrap()
717 self.sslconn = None
718 if support.verbose and self.server.connectionchatty:
719 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000720 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000721 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000722 self.server.connectionchatty):
723 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou480a1242010-04-28 21:37:09 +0000724 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
725 % (msg, ctype, msg.lower(), ctype))
726 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000727 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000728 if self.server.chatty:
729 handle_error("Test server failure:\n")
730 self.close()
731 self.running = False
732 # normally, we'd just stop here, but for the test
733 # harness, we want to stop the server
734 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000735
Antoine Pitroub5218772010-05-21 09:56:06 +0000736 def __init__(self, certificate=None, ssl_version=None,
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000737 certreqs=None, cacerts=None,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000738 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitroub5218772010-05-21 09:56:06 +0000739 ciphers=None, context=None):
740 if context:
741 self.context = context
742 else:
743 self.context = ssl.SSLContext(ssl_version
744 if ssl_version is not None
745 else ssl.PROTOCOL_TLSv1)
746 self.context.verify_mode = (certreqs if certreqs is not None
747 else ssl.CERT_NONE)
748 if cacerts:
749 self.context.load_verify_locations(cacerts)
750 if certificate:
751 self.context.load_cert_chain(certificate)
752 if ciphers:
753 self.context.set_ciphers(ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000754 self.chatty = chatty
755 self.connectionchatty = connectionchatty
756 self.starttls_server = starttls_server
757 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000758 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000759 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000760 self.active = False
761 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000762 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000763
Antoine Pitrou480a1242010-04-28 21:37:09 +0000764 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000765 self.flag = flag
766 threading.Thread.start(self)
767
Antoine Pitrou480a1242010-04-28 21:37:09 +0000768 def run(self):
Antoine Pitrouaf7c6022010-04-27 09:56:02 +0000769 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000770 self.sock.listen(5)
771 self.active = True
772 if self.flag:
773 # signal an event
774 self.flag.set()
775 while self.active:
776 try:
777 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000778 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000779 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000780 + repr(connaddr) + '\n')
781 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000782 handler.start()
783 except socket.timeout:
784 pass
785 except KeyboardInterrupt:
786 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000787 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000788
Antoine Pitrou480a1242010-04-28 21:37:09 +0000789 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000790 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000791
Bill Janssen54cc54c2007-12-14 22:08:56 +0000792 class AsyncoreEchoServer(threading.Thread):
793
794 # this one's based on asyncore.dispatcher
795
796 class EchoServer (asyncore.dispatcher):
797
798 class ConnectionHandler (asyncore.dispatcher_with_send):
799
800 def __init__(self, conn, certfile):
801 self.socket = ssl.wrap_socket(conn, server_side=True,
802 certfile=certfile,
803 do_handshake_on_connect=False)
804 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000805 self._ssl_accepting = True
806 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000807
808 def readable(self):
809 if isinstance(self.socket, ssl.SSLSocket):
810 while self.socket.pending() > 0:
811 self.handle_read_event()
812 return True
813
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000814 def _do_ssl_handshake(self):
815 try:
816 self.socket.do_handshake()
817 except ssl.SSLError as err:
818 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
819 ssl.SSL_ERROR_WANT_WRITE):
820 return
821 elif err.args[0] == ssl.SSL_ERROR_EOF:
822 return self.handle_close()
823 raise
824 except socket.error as err:
825 if err.args[0] == errno.ECONNABORTED:
826 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000827 else:
Antoine Pitroud3f8ab82010-04-24 21:26:44 +0000828 self._ssl_accepting = False
829
830 def handle_read(self):
831 if self._ssl_accepting:
832 self._do_ssl_handshake()
833 else:
834 data = self.recv(1024)
835 if support.verbose:
836 sys.stdout.write(" server: read %s from client\n" % repr(data))
837 if not data:
838 self.close()
839 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000840 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000841
842 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000843 self.close()
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000844 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000845 sys.stdout.write(" server: closed connection %s\n" % self.socket)
846
847 def handle_error(self):
848 raise
849
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000850 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000851 self.certfile = certfile
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000852 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
853 self.port = support.bind_port(sock, '')
854 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000855 self.listen(5)
856
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000857 def handle_accepted(self, sock_obj, addr):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000858 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000859 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
860 self.ConnectionHandler(sock_obj, self.certfile)
861
862 def handle_error(self):
863 raise
864
Trent Nelson78520002008-04-10 20:54:35 +0000865 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000866 self.flag = None
867 self.active = False
Antoine Pitrou773b5db2010-04-27 08:53:36 +0000868 self.server = self.EchoServer(certfile)
869 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000870 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000871 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000872
873 def __str__(self):
874 return "<%s %s>" % (self.__class__.__name__, self.server)
875
876 def start (self, flag=None):
877 self.flag = flag
878 threading.Thread.start(self)
879
Antoine Pitrou480a1242010-04-28 21:37:09 +0000880 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000881 self.active = True
882 if self.flag:
883 self.flag.set()
884 while self.active:
885 try:
886 asyncore.loop(1)
887 except:
888 pass
889
Antoine Pitrou480a1242010-04-28 21:37:09 +0000890 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000891 self.active = False
892 self.server.close()
893
Antoine Pitrou480a1242010-04-28 21:37:09 +0000894 def bad_cert_test(certfile):
895 """
896 Launch a server with CERT_REQUIRED, and check that trying to
897 connect to it with the given client certificate fails.
898 """
Trent Nelson78520002008-04-10 20:54:35 +0000899 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000900 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000901 cacerts=CERTFILE, chatty=False,
902 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000903 flag = threading.Event()
904 server.start(flag)
905 # wait for it to start
906 flag.wait()
907 # try to connect
908 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000909 try:
Antoine Pitroud2eca372010-10-29 23:41:37 +0000910 with socket.socket() as sock:
911 s = ssl.wrap_socket(sock,
912 certfile=certfile,
913 ssl_version=ssl.PROTOCOL_TLSv1)
914 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000916 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +0000917 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou05830aa2010-04-27 13:15:18 +0000918 except socket.error as x:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000919 if support.verbose:
Georg Brandlb75b6392010-10-24 14:20:22 +0000920 sys.stdout.write("\nsocket.error is %s\n" % x.args[1])
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000921 except IOError as x:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000922 if x.errno != errno.ENOENT:
923 raise
Giampaolo Rodolà745ab382010-08-29 19:25:49 +0000924 if support.verbose:
Giampaolo Rodolàcd9dfb92010-08-29 20:56:56 +0000925 sys.stdout.write("\IOError is %s\n" % str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000926 else:
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000927 raise AssertionError("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000928 finally:
929 server.stop()
930 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000931
Antoine Pitroub5218772010-05-21 09:56:06 +0000932 def server_params_test(client_context, server_context, indata=b"FOO\n",
933 chatty=True, connectionchatty=False):
Antoine Pitrou480a1242010-04-28 21:37:09 +0000934 """
935 Launch a server, connect a client to it and try various reads
936 and writes.
937 """
Antoine Pitroub5218772010-05-21 09:56:06 +0000938 server = ThreadedEchoServer(context=server_context,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000939 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000940 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000941 flag = threading.Event()
942 server.start(flag)
943 # wait for it to start
944 flag.wait()
945 # try to connect
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000946 try:
Antoine Pitroub5218772010-05-21 09:56:06 +0000947 s = client_context.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +0000948 s.connect((HOST, server.port))
Antoine Pitrou480a1242010-04-28 21:37:09 +0000949 for arg in [indata, bytearray(indata), memoryview(indata)]:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000950 if connectionchatty:
951 if support.verbose:
952 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000953 " client: sending %r...\n" % indata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000954 s.write(arg)
955 outdata = s.read()
956 if connectionchatty:
957 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000958 sys.stdout.write(" client: read %r\n" % outdata)
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000959 if outdata != indata.lower():
Antoine Pitroud75b2a92010-05-06 14:15:10 +0000960 raise AssertionError(
Antoine Pitrou480a1242010-04-28 21:37:09 +0000961 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
962 % (outdata[:20], len(outdata),
963 indata[:20].lower(), len(indata)))
964 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000965 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000966 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000967 sys.stdout.write(" client: closing connection.\n")
968 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000969 finally:
970 server.stop()
971 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000972
Antoine Pitroub5218772010-05-21 09:56:06 +0000973 def try_protocol_combo(server_protocol, client_protocol, expect_success,
974 certsreqs=None, server_options=0, client_options=0):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000975 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000976 certsreqs = ssl.CERT_NONE
Antoine Pitrou480a1242010-04-28 21:37:09 +0000977 certtype = {
978 ssl.CERT_NONE: "CERT_NONE",
979 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
980 ssl.CERT_REQUIRED: "CERT_REQUIRED",
981 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000982 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +0000983 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984 sys.stdout.write(formatstr %
985 (ssl.get_protocol_name(client_protocol),
986 ssl.get_protocol_name(server_protocol),
987 certtype))
Antoine Pitroub5218772010-05-21 09:56:06 +0000988 client_context = ssl.SSLContext(client_protocol)
989 client_context.options = ssl.OP_ALL | client_options
990 server_context = ssl.SSLContext(server_protocol)
991 server_context.options = ssl.OP_ALL | server_options
992 for ctx in (client_context, server_context):
993 ctx.verify_mode = certsreqs
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000994 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
995 # will send an SSLv3 hello (rather than SSLv2) starting from
996 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitroub5218772010-05-21 09:56:06 +0000997 ctx.set_ciphers("ALL")
998 ctx.load_cert_chain(CERTFILE)
999 ctx.load_verify_locations(CERTFILE)
1000 try:
1001 server_params_test(client_context, server_context,
1002 chatty=False, connectionchatty=False)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001003 # Protocol mismatch can result in either an SSLError, or a
1004 # "Connection reset by peer" error.
1005 except ssl.SSLError:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001006 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001007 raise
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001008 except socket.error as e:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001009 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001010 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001011 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001012 if not expect_success:
Antoine Pitroud75b2a92010-05-06 14:15:10 +00001013 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001014 "Client protocol %s succeeded with server protocol %s!"
1015 % (ssl.get_protocol_name(client_protocol),
1016 ssl.get_protocol_name(server_protocol)))
1017
1018
Bill Janssen6e027db2007-11-15 22:23:56 +00001019 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001020
Antoine Pitrou23df4832010-08-04 17:14:06 +00001021 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001022 def test_echo(self):
1023 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001024 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001025 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001026 for protocol in PROTOCOLS:
1027 context = ssl.SSLContext(protocol)
1028 context.load_cert_chain(CERTFILE)
1029 server_params_test(context, context,
1030 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001031
Antoine Pitrou480a1242010-04-28 21:37:09 +00001032 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001033 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001034 sys.stdout.write("\n")
Antoine Pitroub5218772010-05-21 09:56:06 +00001035 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1036 context.verify_mode = ssl.CERT_REQUIRED
1037 context.load_verify_locations(CERTFILE)
1038 context.load_cert_chain(CERTFILE)
1039 server = ThreadedEchoServer(context=context, chatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001040 flag = threading.Event()
1041 server.start(flag)
1042 # wait for it to start
1043 flag.wait()
1044 # try to connect
1045 try:
Antoine Pitroub5218772010-05-21 09:56:06 +00001046 s = context.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001047 s.connect((HOST, server.port))
1048 cert = s.getpeercert()
1049 self.assertTrue(cert, "Can't get peer certificate.")
1050 cipher = s.cipher()
1051 if support.verbose:
1052 sys.stdout.write(pprint.pformat(cert) + '\n')
1053 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
1054 if 'subject' not in cert:
1055 self.fail("No subject field in certificate: %s." %
1056 pprint.pformat(cert))
1057 if ((('organizationName', 'Python Software Foundation'),)
1058 not in cert['subject']):
1059 self.fail(
1060 "Missing or invalid 'organizationName' field in certificate subject; "
1061 "should be 'Python Software Foundation'.")
1062 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001063 finally:
1064 server.stop()
1065 server.join()
1066
Antoine Pitrou480a1242010-04-28 21:37:09 +00001067 def test_empty_cert(self):
1068 """Connecting with an empty cert file"""
1069 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1070 "nullcert.pem"))
1071 def test_malformed_cert(self):
1072 """Connecting with a badly formatted certificate (syntax error)"""
1073 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1074 "badcert.pem"))
1075 def test_nonexisting_cert(self):
1076 """Connecting with a non-existing cert file"""
1077 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1078 "wrongcert.pem"))
1079 def test_malformed_key(self):
1080 """Connecting with a badly formatted key (syntax error)"""
1081 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
1082 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001083
Antoine Pitrou480a1242010-04-28 21:37:09 +00001084 def test_rude_shutdown(self):
1085 """A brutal shutdown of an SSL server should raise an IOError
1086 in the client when attempting handshake.
1087 """
Trent Nelson6b240cd2008-04-10 20:12:06 +00001088 listener_ready = threading.Event()
1089 listener_gone = threading.Event()
Antoine Pitrou480a1242010-04-28 21:37:09 +00001090
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001091 s = socket.socket()
1092 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001093
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001094 # `listener` runs in a thread. It sits in an accept() until
1095 # the main thread connects. Then it rudely closes the socket,
1096 # and sets Event `listener_gone` to let the main thread know
1097 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +00001098 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +00001099 s.listen(5)
1100 listener_ready.set()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001101 newsock, addr = s.accept()
1102 newsock.close()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001103 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001104 listener_gone.set()
1105
1106 def connector():
1107 listener_ready.wait()
Antoine Pitroud2eca372010-10-29 23:41:37 +00001108 with socket.socket() as c:
1109 c.connect((HOST, port))
1110 listener_gone.wait()
1111 try:
1112 ssl_sock = ssl.wrap_socket(c)
1113 except IOError:
1114 pass
1115 else:
1116 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +00001117
1118 t = threading.Thread(target=listener)
1119 t.start()
Antoine Pitrou773b5db2010-04-27 08:53:36 +00001120 try:
1121 connector()
1122 finally:
1123 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +00001124
Antoine Pitrou23df4832010-08-04 17:14:06 +00001125 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001126 def test_protocol_sslv2(self):
1127 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001128 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001129 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001130 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
1131 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
1132 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
1133 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
1134 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
1135 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001136 # SSLv23 client with specific SSL options
1137 if no_sslv2_implies_sslv3_hello():
1138 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1139 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False,
1140 client_options=ssl.OP_NO_SSLv2)
1141 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1142 client_options=ssl.OP_NO_SSLv3)
1143 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True,
1144 client_options=ssl.OP_NO_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001145
Antoine Pitrou23df4832010-08-04 17:14:06 +00001146 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001147 def test_protocol_sslv23(self):
1148 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001149 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001150 sys.stdout.write("\n")
1151 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001152 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001153 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001154 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001155 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001156 sys.stdout.write(
1157 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
1158 % str(x))
Antoine Pitrou480a1242010-04-28 21:37:09 +00001159 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
1160 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
1161 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001162
Antoine Pitrou480a1242010-04-28 21:37:09 +00001163 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1164 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
1165 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166
Antoine Pitrou480a1242010-04-28 21:37:09 +00001167 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1168 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
1169 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001170
Antoine Pitroub5218772010-05-21 09:56:06 +00001171 # Server with specific SSL options
1172 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False,
1173 server_options=ssl.OP_NO_SSLv3)
1174 # Will choose TLSv1
1175 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True,
1176 server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
1177 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False,
1178 server_options=ssl.OP_NO_TLSv1)
1179
1180
Antoine Pitrou23df4832010-08-04 17:14:06 +00001181 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001182 def test_protocol_sslv3(self):
1183 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001184 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001185 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001186 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
1187 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
1188 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
1189 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
1190 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
1191 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Antoine Pitroub5218772010-05-21 09:56:06 +00001192 if no_sslv2_implies_sslv3_hello():
1193 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
1194 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True,
1195 client_options=ssl.OP_NO_SSLv2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001196
Antoine Pitrou23df4832010-08-04 17:14:06 +00001197 @skip_if_broken_ubuntu_ssl
Antoine Pitrou480a1242010-04-28 21:37:09 +00001198 def test_protocol_tlsv1(self):
1199 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001200 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001201 sys.stdout.write("\n")
Antoine Pitrou480a1242010-04-28 21:37:09 +00001202 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
1203 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
1204 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
1205 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
1206 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
1207 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001208
Antoine Pitrou480a1242010-04-28 21:37:09 +00001209 def test_starttls(self):
1210 """Switching from clear text to encrypted and back again."""
1211 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 +00001212
Trent Nelson78520002008-04-10 20:54:35 +00001213 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001214 ssl_version=ssl.PROTOCOL_TLSv1,
1215 starttls_server=True,
1216 chatty=True,
1217 connectionchatty=True)
1218 flag = threading.Event()
1219 server.start(flag)
1220 # wait for it to start
1221 flag.wait()
1222 # try to connect
1223 wrapped = False
1224 try:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001225 s = socket.socket()
1226 s.setblocking(1)
1227 s.connect((HOST, server.port))
1228 if support.verbose:
1229 sys.stdout.write("\n")
1230 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001231 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001232 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001233 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001234 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001235 conn.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001236 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001237 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001238 s.send(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001239 outdata = s.recv(1024)
Antoine Pitrou480a1242010-04-28 21:37:09 +00001240 msg = outdata.strip().lower()
1241 if indata == b"STARTTLS" and msg.startswith(b"ok"):
1242 # STARTTLS ok, switch to secure mode
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001243 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001244 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001245 " client: read %r from server, starting TLS...\n"
1246 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001247 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1248 wrapped = True
Antoine Pitrou480a1242010-04-28 21:37:09 +00001249 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
1250 # ENDTLS ok, switch back to clear text
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001251 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001252 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001253 " client: read %r from server, ending TLS...\n"
1254 % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001255 s = conn.unwrap()
1256 wrapped = False
1257 else:
1258 if support.verbose:
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001259 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001260 " client: read %r from server\n" % msg)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001261 if support.verbose:
1262 sys.stdout.write(" client: closing connection.\n")
1263 if wrapped:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001264 conn.write(b"over\n")
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001265 else:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001266 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +00001267 if wrapped:
1268 conn.close()
1269 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001270 s.close()
1271 finally:
1272 server.stop()
1273 server.join()
1274
Antoine Pitrou480a1242010-04-28 21:37:09 +00001275 def test_socketserver(self):
1276 """Using a SocketServer to create and manage SSL connections."""
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001277 server = make_https_server(self, CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001278 # try to connect
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001279 if support.verbose:
1280 sys.stdout.write('\n')
1281 with open(CERTFILE, 'rb') as f:
1282 d1 = f.read()
1283 d2 = ''
1284 # now fetch the same data from the HTTPS server
1285 url = 'https://%s:%d/%s' % (
1286 HOST, server.port, os.path.split(CERTFILE)[1])
1287 f = urllib.request.urlopen(url)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001288 try:
Barry Warsaw820c1202008-06-12 04:06:45 +00001289 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001290 if dlen and (int(dlen) > 0):
1291 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001292 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001293 sys.stdout.write(
1294 " client: read %d bytes from remote server '%s'\n"
1295 % (len(d2), server))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001296 finally:
Antoine Pitrou803e6d62010-10-13 10:36:15 +00001297 f.close()
1298 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001299
Antoine Pitrou480a1242010-04-28 21:37:09 +00001300 def test_asyncore_server(self):
1301 """Check the example asyncore integration."""
1302 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001303
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001304 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001305 sys.stdout.write("\n")
1306
Antoine Pitrou480a1242010-04-28 21:37:09 +00001307 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001308 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001309 flag = threading.Event()
1310 server.start(flag)
1311 # wait for it to start
1312 flag.wait()
1313 # try to connect
1314 try:
1315 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001316 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001317 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001318 sys.stdout.write(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001319 " client: sending %r...\n" % indata)
1320 s.write(indata)
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001321 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001322 if support.verbose:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001323 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001324 if outdata != indata.lower():
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001325 self.fail(
Antoine Pitrou480a1242010-04-28 21:37:09 +00001326 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1327 % (outdata[:20], len(outdata),
1328 indata[:20].lower(), len(indata)))
1329 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001330 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001331 sys.stdout.write(" client: closing connection.\n")
1332 s.close()
Antoine Pitroued986362010-08-15 23:28:10 +00001333 if support.verbose:
1334 sys.stdout.write(" client: connection closed.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001335 finally:
Antoine Pitroued986362010-08-15 23:28:10 +00001336 if support.verbose:
1337 sys.stdout.write(" cleanup: stopping server.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001338 server.stop()
Antoine Pitroued986362010-08-15 23:28:10 +00001339 if support.verbose:
1340 sys.stdout.write(" cleanup: joining server thread.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001341 server.join()
Antoine Pitroued986362010-08-15 23:28:10 +00001342 if support.verbose:
1343 sys.stdout.write(" cleanup: successfully joined.\n")
Trent Nelson6b240cd2008-04-10 20:12:06 +00001344
Antoine Pitrou480a1242010-04-28 21:37:09 +00001345 def test_recv_send(self):
1346 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001347 if support.verbose:
1348 sys.stdout.write("\n")
1349
1350 server = ThreadedEchoServer(CERTFILE,
1351 certreqs=ssl.CERT_NONE,
1352 ssl_version=ssl.PROTOCOL_TLSv1,
1353 cacerts=CERTFILE,
1354 chatty=True,
1355 connectionchatty=False)
1356 flag = threading.Event()
1357 server.start(flag)
1358 # wait for it to start
1359 flag.wait()
1360 # try to connect
Antoine Pitrou18c913e2010-04-27 10:59:39 +00001361 s = ssl.wrap_socket(socket.socket(),
1362 server_side=False,
1363 certfile=CERTFILE,
1364 ca_certs=CERTFILE,
1365 cert_reqs=ssl.CERT_NONE,
1366 ssl_version=ssl.PROTOCOL_TLSv1)
1367 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001368 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001369 # helper methods for standardising recv* method signatures
1370 def _recv_into():
1371 b = bytearray(b"\0"*100)
1372 count = s.recv_into(b)
1373 return b[:count]
1374
1375 def _recvfrom_into():
1376 b = bytearray(b"\0"*100)
1377 count, addr = s.recvfrom_into(b)
1378 return b[:count]
1379
1380 # (name, method, whether to expect success, *args)
1381 send_methods = [
1382 ('send', s.send, True, []),
1383 ('sendto', s.sendto, False, ["some.address"]),
1384 ('sendall', s.sendall, True, []),
1385 ]
1386 recv_methods = [
1387 ('recv', s.recv, True, []),
1388 ('recvfrom', s.recvfrom, False, ["some.address"]),
1389 ('recv_into', _recv_into, True, []),
1390 ('recvfrom_into', _recvfrom_into, False, []),
1391 ]
1392 data_prefix = "PREFIX_"
1393
1394 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001395 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001396 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001397 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001398 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001399 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001400 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001401 "While sending with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001402 "<<{outdata:r}>> ({nout:d}) received; "
1403 "expected <<{indata:r}>> ({nin:d})\n".format(
1404 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001405 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001406 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001407 )
1408 )
1409 except ValueError as e:
1410 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001411 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001412 "Failed to send with method <<{name:s}>>; "
1413 "expected to succeed.\n".format(name=meth_name)
1414 )
1415 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001416 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001417 "Method <<{name:s}>> failed with unexpected "
1418 "exception message: {exp:s}\n".format(
1419 name=meth_name, exp=e
1420 )
1421 )
1422
1423 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001424 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001425 try:
Antoine Pitrou480a1242010-04-28 21:37:09 +00001426 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001427 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001428 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001429 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001430 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou480a1242010-04-28 21:37:09 +00001431 "<<{outdata:r}>> ({nout:d}) received; "
1432 "expected <<{indata:r}>> ({nin:d})\n".format(
1433 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001434 nout=len(outdata),
Antoine Pitrou480a1242010-04-28 21:37:09 +00001435 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001436 )
1437 )
1438 except ValueError as e:
1439 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001440 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001441 "Failed to receive with method <<{name:s}>>; "
1442 "expected to succeed.\n".format(name=meth_name)
1443 )
1444 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001445 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001446 "Method <<{name:s}>> failed with unexpected "
1447 "exception message: {exp:s}\n".format(
1448 name=meth_name, exp=e
1449 )
1450 )
1451 # consume data
1452 s.read()
1453
Antoine Pitrou480a1242010-04-28 21:37:09 +00001454 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001455 s.close()
1456 finally:
1457 server.stop()
1458 server.join()
1459
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001460 def test_handshake_timeout(self):
1461 # Issue #5103: SSL handshake must respect the socket timeout
1462 server = socket.socket(socket.AF_INET)
1463 host = "127.0.0.1"
1464 port = support.bind_port(server)
1465 started = threading.Event()
1466 finish = False
1467
1468 def serve():
1469 server.listen(5)
1470 started.set()
1471 conns = []
1472 while not finish:
1473 r, w, e = select.select([server], [], [], 0.1)
1474 if server in r:
1475 # Let the socket hang around rather than having
1476 # it closed by garbage collection.
1477 conns.append(server.accept()[0])
Antoine Pitroud2eca372010-10-29 23:41:37 +00001478 for sock in conns:
1479 sock.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001480
1481 t = threading.Thread(target=serve)
1482 t.start()
1483 started.wait()
1484
1485 try:
Antoine Pitrou40f08742010-04-24 22:04:40 +00001486 try:
1487 c = socket.socket(socket.AF_INET)
1488 c.settimeout(0.2)
1489 c.connect((host, port))
1490 # Will attempt handshake and time out
1491 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1492 ssl.wrap_socket, c)
1493 finally:
1494 c.close()
Antoine Pitroud3f8ab82010-04-24 21:26:44 +00001495 try:
1496 c = socket.socket(socket.AF_INET)
1497 c = ssl.wrap_socket(c)
1498 c.settimeout(0.2)
1499 # Will attempt handshake and time out
1500 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1501 c.connect, (host, port))
1502 finally:
1503 c.close()
1504 finally:
1505 finish = True
1506 t.join()
1507 server.close()
1508
Bill Janssen58afe4c2008-09-08 16:45:19 +00001509
Thomas Woutersed03b412007-08-28 21:37:11 +00001510def test_main(verbose=False):
Antoine Pitrou15cee622010-08-04 16:45:21 +00001511 if support.verbose:
1512 plats = {
1513 'Linux': platform.linux_distribution,
1514 'Mac': platform.mac_ver,
1515 'Windows': platform.win32_ver,
1516 }
1517 for name, func in plats.items():
1518 plat = func()
1519 if plat and plat[0]:
1520 plat = '%s %r' % (name, plat)
1521 break
1522 else:
1523 plat = repr(platform.platform())
1524 print("test_ssl: testing with %r %r" %
1525 (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO))
1526 print(" under %s" % plat)
Antoine Pitroud5323212010-10-22 18:19:07 +00001527 print(" HAS_SNI = %r" % ssl.HAS_SNI)
Antoine Pitrou15cee622010-08-04 16:45:21 +00001528
Antoine Pitrou152efa22010-05-16 18:19:27 +00001529 for filename in [
1530 CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
1531 ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
1532 BADCERT, BADKEY, EMPTYCERT]:
1533 if not os.path.exists(filename):
1534 raise support.TestFailed("Can't read certificate file %r" % filename)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001535
Antoine Pitrou152efa22010-05-16 18:19:27 +00001536 tests = [ContextTests, BasicSocketTests]
Thomas Woutersed03b412007-08-28 21:37:11 +00001537
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001538 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001539 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001540
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001541 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001542 thread_info = support.threading_setup()
1543 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001544 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001545
Antoine Pitrou480a1242010-04-28 21:37:09 +00001546 try:
1547 support.run_unittest(*tests)
1548 finally:
1549 if _have_threads:
1550 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001551
1552if __name__ == "__main__":
1553 test_main()