blob: 37261554bc47e6837f602d661b221d3863eaa981 [file] [log] [blame]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
5from test import test_support
Bill Janssen934b16d2008-06-28 22:19:33 +00006import asyncore
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00007import socket
Bill Janssen934b16d2008-06-28 22:19:33 +00008import select
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00009import time
Antoine Pitroub558f172010-04-23 23:25:45 +000010import gc
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000011import os
Antoine Pitroub558f172010-04-23 23:25:45 +000012import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000013import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000014import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import traceback
Antoine Pitroudfb299b2010-04-23 22:54:59 +000016import weakref
Antoine Pitroud75efd92010-08-04 17:38:33 +000017import functools
18import platform
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000019
Bill Janssen296a59d2007-09-16 22:06:00 +000020from BaseHTTPServer import HTTPServer
21from SimpleHTTPServer import SimpleHTTPRequestHandler
22
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +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
29
Trent Nelsone41b0062008-04-08 23:47:30 +000030HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000031CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000032SVN_PYTHON_ORG_ROOT_CERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000033
Neal Norwitz3e533c22007-08-27 01:03:18 +000034def handle_error(prefix):
35 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000036 if test_support.verbose:
37 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000038
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000039
40class BasicTests(unittest.TestCase):
41
Antoine Pitrou3945c862010-04-28 21:11:01 +000042 def test_sslwrap_simple(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +000043 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000044 try:
45 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
46 except IOError, e:
47 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
48 pass
49 else:
50 raise
51 try:
52 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
53 except IOError, e:
54 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
55 pass
56 else:
57 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000058
Antoine Pitroud75efd92010-08-04 17:38:33 +000059# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2
60def skip_if_broken_ubuntu_ssl(func):
61 # We need to access the lower-level wrapper in order to create an
62 # implicit SSL context without trying to connect or listen.
Antoine Pitrou969fbe32010-08-05 01:30:23 +000063 try:
64 import _ssl
65 except ImportError:
66 # The returned function won't get executed, just ignore the error
67 pass
Antoine Pitroud75efd92010-08-04 17:38:33 +000068 @functools.wraps(func)
69 def f(*args, **kwargs):
70 try:
71 s = socket.socket(socket.AF_INET)
72 _ssl.sslwrap(s._sock, 0, None, None,
73 ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None)
74 except ssl.SSLError as e:
75 if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and
76 platform.linux_distribution() == ('debian', 'squeeze/sid', '')
77 and 'Invalid SSL protocol variant specified' in str(e)):
78 raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour")
79 return func(*args, **kwargs)
80 return f
81
82
83class BasicSocketTests(unittest.TestCase):
84
Antoine Pitrou3945c862010-04-28 21:11:01 +000085 def test_constants(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000086 ssl.PROTOCOL_SSLv2
87 ssl.PROTOCOL_SSLv23
88 ssl.PROTOCOL_SSLv3
89 ssl.PROTOCOL_TLSv1
90 ssl.CERT_NONE
91 ssl.CERT_OPTIONAL
92 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000093
Antoine Pitrou3945c862010-04-28 21:11:01 +000094 def test_random(self):
Bill Janssen98d19da2007-09-10 21:51:02 +000095 v = ssl.RAND_status()
96 if test_support.verbose:
97 sys.stdout.write("\n RAND_status is %d (%s)\n"
98 % (v, (v and "sufficient randomness") or
99 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +0000100 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000101 ssl.RAND_egd(1)
102 except TypeError:
103 pass
Guido van Rossume4729332007-08-26 19:35:09 +0000104 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000105 print "didn't raise TypeError"
106 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000107
Antoine Pitrou3945c862010-04-28 21:11:01 +0000108 def test_parse_cert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +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)
113 if test_support.verbose:
114 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000115
Antoine Pitrou3945c862010-04-28 21:11:01 +0000116 def test_DER_to_PEM(self):
117 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
118 pem = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +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 Pitroudb187842010-04-27 10:32:58 +0000122 self.assertEqual(d1, d2)
Antoine Pitrou4c7bcf12010-04-27 22:03:37 +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)
Bill Janssen296a59d2007-09-16 22:06:00 +0000127
Antoine Pitrouf9de5342010-04-05 21:35: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, long))
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 Pitrou0a6373c2010-04-17 17:10:38 +0000155 def test_ciphers(self):
156 if not test_support.is_resource_enabled('network'):
157 return
158 remote = ("svn.python.org", 443)
159 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
160 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
161 s.connect(remote)
162 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
163 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
164 s.connect(remote)
165 # Error checking occurs when connecting, because the SSL context
166 # isn't created before.
167 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
168 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
169 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
170 s.connect(remote)
171
Antoine Pitroudfb299b2010-04-23 22:54:59 +0000172 @test_support.cpython_only
173 def test_refcycle(self):
174 # Issue #7943: an SSL object doesn't create reference cycles with
175 # itself.
176 s = socket.socket(socket.AF_INET)
177 ss = ssl.wrap_socket(s)
178 wr = weakref.ref(ss)
179 del ss
180 self.assertEqual(wr(), None)
181
Antoine Pitrouf7f390a2010-09-14 14:37:18 +0000182 def test_wrapped_unconnected(self):
183 # The _delegate_methods in socket.py are correctly delegated to by an
184 # unconnected SSLSocket, so they will raise a socket.error rather than
185 # something unexpected like TypeError.
186 s = socket.socket(socket.AF_INET)
187 ss = ssl.wrap_socket(s)
188 self.assertRaises(socket.error, ss.recv, 1)
189 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
190 self.assertRaises(socket.error, ss.recvfrom, 1)
191 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
192 self.assertRaises(socket.error, ss.send, b'x')
193 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
194
Antoine Pitrouf9de5342010-04-05 21:35:07 +0000195
Bill Janssen934b16d2008-06-28 22:19:33 +0000196class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000197
Antoine Pitrou3945c862010-04-28 21:11:01 +0000198 def test_connect(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000199 with test_support.transient_internet("svn.python.org"):
200 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
201 cert_reqs=ssl.CERT_NONE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000202 s.connect(("svn.python.org", 443))
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000203 c = s.getpeercert()
204 if c:
205 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000206 s.close()
207
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000208 # this should fail because we have no verification certs
209 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
210 cert_reqs=ssl.CERT_REQUIRED)
211 try:
212 s.connect(("svn.python.org", 443))
213 except ssl.SSLError:
214 pass
215 finally:
216 s.close()
217
218 # this should succeed because we specify the root cert
219 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
220 cert_reqs=ssl.CERT_REQUIRED,
221 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
222 try:
223 s.connect(("svn.python.org", 443))
224 finally:
225 s.close()
Bill Janssen296a59d2007-09-16 22:06:00 +0000226
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000227 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
228 def test_makefile_close(self):
229 # Issue #5238: creating a file-like object with makefile() shouldn't
230 # delay closing the underlying "real socket" (here tested with its
231 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000232 with test_support.transient_internet("svn.python.org"):
233 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
234 ss.connect(("svn.python.org", 443))
235 fd = ss.fileno()
236 f = ss.makefile()
237 f.close()
238 # The fd is still open
Antoine Pitrou55841ac2010-04-24 10:43:57 +0000239 os.read(fd, 0)
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000240 # Closing the SSL socket should close the fd too
241 ss.close()
242 gc.collect()
243 with self.assertRaises(OSError) as e:
244 os.read(fd, 0)
245 self.assertEqual(e.exception.errno, errno.EBADF)
Bill Janssen934b16d2008-06-28 22:19:33 +0000246
Antoine Pitrou3945c862010-04-28 21:11:01 +0000247 def test_non_blocking_handshake(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000248 with test_support.transient_internet("svn.python.org"):
249 s = socket.socket(socket.AF_INET)
250 s.connect(("svn.python.org", 443))
251 s.setblocking(False)
252 s = ssl.wrap_socket(s,
253 cert_reqs=ssl.CERT_NONE,
254 do_handshake_on_connect=False)
255 count = 0
256 while True:
257 try:
258 count += 1
259 s.do_handshake()
260 break
261 except ssl.SSLError, err:
262 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
263 select.select([s], [], [])
264 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
265 select.select([], [s], [])
266 else:
267 raise
268 s.close()
269 if test_support.verbose:
270 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Bill Janssen934b16d2008-06-28 22:19:33 +0000271
Antoine Pitrou3945c862010-04-28 21:11:01 +0000272 def test_get_server_certificate(self):
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000273 with test_support.transient_internet("svn.python.org"):
274 pem = ssl.get_server_certificate(("svn.python.org", 443))
275 if not pem:
276 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000277
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000278 try:
279 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
280 except ssl.SSLError:
281 #should fail
282 pass
283 else:
284 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000285
Antoine Pitrou4e406d82010-09-09 13:35:44 +0000286 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
287 if not pem:
288 self.fail("No server certificate on svn.python.org:443!")
289 if test_support.verbose:
290 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000291
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000292 def test_algorithms(self):
293 # Issue #8484: all algorithms should be available when verifying a
294 # certificate.
Antoine Pitrou9aed6042010-04-22 18:00:41 +0000295 # SHA256 was added in OpenSSL 0.9.8
296 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
297 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000298 # NOTE: https://sha256.tbs-internet.com is another possible test host
299 remote = ("sha2.hboeck.de", 443)
300 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrouc818ed42010-09-07 21:40:25 +0000301 with test_support.transient_internet("sha2.hboeck.de"):
302 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
303 cert_reqs=ssl.CERT_REQUIRED,
304 ca_certs=sha256_cert,)
Antoine Pitrouc715a9e2010-04-21 19:28:03 +0000305 try:
306 s.connect(remote)
307 if test_support.verbose:
308 sys.stdout.write("\nCipher with %r is %r\n" %
309 (remote, s.cipher()))
310 sys.stdout.write("Certificate is:\n%s\n" %
311 pprint.pformat(s.getpeercert()))
312 finally:
313 s.close()
314
Bill Janssen296a59d2007-09-16 22:06:00 +0000315
Bill Janssen98d19da2007-09-10 21:51:02 +0000316try:
317 import threading
318except ImportError:
319 _have_threads = False
320else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000321 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000322
Bill Janssen98d19da2007-09-10 21:51:02 +0000323 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000324
Bill Janssen98d19da2007-09-10 21:51:02 +0000325 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000326
Bill Janssen98d19da2007-09-10 21:51:02 +0000327 """A mildly complicated class, because we want it to work both
328 with and without the SSL wrapper around the socket connection, so
329 that we can test the STARTTLS functionality."""
330
331 def __init__(self, server, connsock):
332 self.server = server
333 self.running = False
334 self.sock = connsock
335 self.sock.setblocking(1)
336 self.sslconn = None
337 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000338 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000339
Bill Janssen934b16d2008-06-28 22:19:33 +0000340 def show_conn_details(self):
341 if self.server.certreqs == ssl.CERT_REQUIRED:
342 cert = self.sslconn.getpeercert()
343 if test_support.verbose and self.server.chatty:
344 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
345 cert_binary = self.sslconn.getpeercert(True)
346 if test_support.verbose and self.server.chatty:
347 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
348 cipher = self.sslconn.cipher()
349 if test_support.verbose and self.server.chatty:
350 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
351
Antoine Pitrou3945c862010-04-28 21:11:01 +0000352 def wrap_conn(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000353 try:
354 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
355 certfile=self.server.certificate,
356 ssl_version=self.server.protocol,
357 ca_certs=self.server.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000358 cert_reqs=self.server.certreqs,
359 ciphers=self.server.ciphers)
Antoine Pitroudb187842010-04-27 10:32:58 +0000360 except ssl.SSLError:
361 # XXX Various errors can have happened here, for example
362 # a mismatching protocol version, an invalid certificate,
363 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000364 if self.server.chatty:
365 handle_error("\n server: bad connection attempt from " +
366 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000367 self.close()
Antoine Pitroudb187842010-04-27 10:32:58 +0000368 self.running = False
369 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000370 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000371 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000372 return True
373
374 def read(self):
375 if self.sslconn:
376 return self.sslconn.read()
377 else:
378 return self.sock.recv(1024)
379
380 def write(self, bytes):
381 if self.sslconn:
382 return self.sslconn.write(bytes)
383 else:
384 return self.sock.send(bytes)
385
386 def close(self):
387 if self.sslconn:
388 self.sslconn.close()
389 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000390 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000391
Antoine Pitrou3945c862010-04-28 21:11:01 +0000392 def run(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000393 self.running = True
394 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000395 if isinstance(self.sock, ssl.SSLSocket):
396 self.sslconn = self.sock
397 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000398 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000399 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000400 while self.running:
401 try:
402 msg = self.read()
403 if not msg:
404 # eof, so quit this handler
405 self.running = False
406 self.close()
407 elif msg.strip() == 'over':
408 if test_support.verbose and self.server.connectionchatty:
409 sys.stdout.write(" server: client closed connection\n")
410 self.close()
411 return
412 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
413 if test_support.verbose and self.server.connectionchatty:
414 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
415 self.write("OK\n")
416 if not self.wrap_conn():
417 return
Bill Janssen39295c22008-08-12 16:31:21 +0000418 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
419 if test_support.verbose and self.server.connectionchatty:
420 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
421 self.write("OK\n")
422 self.sslconn.unwrap()
423 self.sslconn = None
424 if test_support.verbose and self.server.connectionchatty:
425 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000426 else:
427 if (test_support.verbose and
428 self.server.connectionchatty):
429 ctype = (self.sslconn and "encrypted") or "unencrypted"
430 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
431 % (repr(msg), ctype, repr(msg.lower()), ctype))
432 self.write(msg.lower())
433 except ssl.SSLError:
434 if self.server.chatty:
435 handle_error("Test server failure:\n")
436 self.close()
437 self.running = False
438 # normally, we'd just stop here, but for the test
439 # harness, we want to stop the server
440 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000441
Trent Nelsone41b0062008-04-08 23:47:30 +0000442 def __init__(self, certificate, ssl_version=None,
Antoine Pitroudb187842010-04-27 10:32:58 +0000443 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000444 chatty=True, connectionchatty=False, starttls_server=False,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000445 wrap_accepting_socket=False, ciphers=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000446
Bill Janssen98d19da2007-09-10 21:51:02 +0000447 if ssl_version is None:
448 ssl_version = ssl.PROTOCOL_TLSv1
449 if certreqs is None:
450 certreqs = ssl.CERT_NONE
451 self.certificate = certificate
452 self.protocol = ssl_version
453 self.certreqs = certreqs
454 self.cacerts = cacerts
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000455 self.ciphers = ciphers
Bill Janssen98d19da2007-09-10 21:51:02 +0000456 self.chatty = chatty
457 self.connectionchatty = connectionchatty
458 self.starttls_server = starttls_server
459 self.sock = socket.socket()
460 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000461 if wrap_accepting_socket:
462 self.sock = ssl.wrap_socket(self.sock, server_side=True,
463 certfile=self.certificate,
464 cert_reqs = self.certreqs,
465 ca_certs = self.cacerts,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000466 ssl_version = self.protocol,
467 ciphers = self.ciphers)
Bill Janssen934b16d2008-06-28 22:19:33 +0000468 if test_support.verbose and self.chatty:
469 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
470 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000471 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000472 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000473 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000474
Antoine Pitrou3945c862010-04-28 21:11:01 +0000475 def start(self, flag=None):
Bill Janssen98d19da2007-09-10 21:51:02 +0000476 self.flag = flag
477 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000478
Antoine Pitrou3945c862010-04-28 21:11:01 +0000479 def run(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000480 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000481 self.sock.listen(5)
482 self.active = True
483 if self.flag:
484 # signal an event
485 self.flag.set()
486 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000487 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000488 newconn, connaddr = self.sock.accept()
489 if test_support.verbose and self.chatty:
490 sys.stdout.write(' server: new connection from '
491 + str(connaddr) + '\n')
492 handler = self.ConnectionHandler(self, newconn)
493 handler.start()
494 except socket.timeout:
495 pass
496 except KeyboardInterrupt:
497 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000498 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000499
Antoine Pitrou3945c862010-04-28 21:11:01 +0000500 def stop(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000501 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000502
Bill Janssen934b16d2008-06-28 22:19:33 +0000503 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000504
Antoine Pitrou3945c862010-04-28 21:11:01 +0000505 class EchoServer(asyncore.dispatcher):
Bill Janssen934b16d2008-06-28 22:19:33 +0000506
Antoine Pitrou3945c862010-04-28 21:11:01 +0000507 class ConnectionHandler(asyncore.dispatcher_with_send):
Bill Janssen934b16d2008-06-28 22:19:33 +0000508
509 def __init__(self, conn, certfile):
510 asyncore.dispatcher_with_send.__init__(self, conn)
511 self.socket = ssl.wrap_socket(conn, server_side=True,
512 certfile=certfile,
Antoine Pitroufc69af12010-04-24 20:04:58 +0000513 do_handshake_on_connect=False)
514 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000515
516 def readable(self):
517 if isinstance(self.socket, ssl.SSLSocket):
518 while self.socket.pending() > 0:
519 self.handle_read_event()
520 return True
521
Antoine Pitroufc69af12010-04-24 20:04:58 +0000522 def _do_ssl_handshake(self):
523 try:
524 self.socket.do_handshake()
525 except ssl.SSLError, err:
526 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
527 ssl.SSL_ERROR_WANT_WRITE):
528 return
529 elif err.args[0] == ssl.SSL_ERROR_EOF:
530 return self.handle_close()
531 raise
532 except socket.error, err:
533 if err.args[0] == errno.ECONNABORTED:
534 return self.handle_close()
535 else:
536 self._ssl_accepting = False
537
Bill Janssen934b16d2008-06-28 22:19:33 +0000538 def handle_read(self):
Antoine Pitroufc69af12010-04-24 20:04:58 +0000539 if self._ssl_accepting:
540 self._do_ssl_handshake()
541 else:
542 data = self.recv(1024)
Antoine Pitroudb187842010-04-27 10:32:58 +0000543 if data and data.strip() != 'over':
544 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000545
546 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000547 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000548 if test_support.verbose:
549 sys.stdout.write(" server: closed connection %s\n" % self.socket)
550
551 def handle_error(self):
552 raise
553
554 def __init__(self, certfile):
555 self.certfile = certfile
556 asyncore.dispatcher.__init__(self)
557 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
558 self.port = test_support.bind_port(self.socket)
559 self.listen(5)
560
561 def handle_accept(self):
562 sock_obj, addr = self.accept()
563 if test_support.verbose:
564 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
565 self.ConnectionHandler(sock_obj, self.certfile)
566
567 def handle_error(self):
568 raise
569
570 def __init__(self, certfile):
571 self.flag = None
572 self.active = False
573 self.server = self.EchoServer(certfile)
574 self.port = self.server.port
575 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000576 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000577
578 def __str__(self):
579 return "<%s %s>" % (self.__class__.__name__, self.server)
580
Antoine Pitrou3945c862010-04-28 21:11:01 +0000581 def start(self, flag=None):
Bill Janssen934b16d2008-06-28 22:19:33 +0000582 self.flag = flag
583 threading.Thread.start(self)
584
Antoine Pitrou3945c862010-04-28 21:11:01 +0000585 def run(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000586 self.active = True
587 if self.flag:
588 self.flag.set()
589 while self.active:
Antoine Pitroudb187842010-04-27 10:32:58 +0000590 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000591
Antoine Pitrou3945c862010-04-28 21:11:01 +0000592 def stop(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000593 self.active = False
594 self.server.close()
595
596 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000597
598 class HTTPSServer(HTTPServer):
599
600 def __init__(self, server_address, RequestHandlerClass, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000601 HTTPServer.__init__(self, server_address, RequestHandlerClass)
602 # we assume the certfile contains both private key and certificate
603 self.certfile = certfile
Bill Janssen296a59d2007-09-16 22:06:00 +0000604 self.allow_reuse_address = True
605
Bill Janssen934b16d2008-06-28 22:19:33 +0000606 def __str__(self):
607 return ('<%s %s:%s>' %
608 (self.__class__.__name__,
609 self.server_name,
610 self.server_port))
611
Antoine Pitrou3945c862010-04-28 21:11:01 +0000612 def get_request(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000613 # override this to wrap socket with SSL
614 sock, addr = self.socket.accept()
615 sslconn = ssl.wrap_socket(sock, server_side=True,
616 certfile=self.certfile)
617 return sslconn, addr
618
Bill Janssen296a59d2007-09-16 22:06:00 +0000619 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Bill Janssen296a59d2007-09-16 22:06:00 +0000620 # need to override translate_path to get a known root,
621 # instead of using os.curdir, since the test could be
622 # run from anywhere
623
624 server_version = "TestHTTPS/1.0"
625
626 root = None
627
628 def translate_path(self, path):
629 """Translate a /-separated PATH to the local filename syntax.
630
631 Components that mean special things to the local file system
632 (e.g. drive or directory names) are ignored. (XXX They should
633 probably be diagnosed.)
634
635 """
636 # abandon query parameters
637 path = urlparse.urlparse(path)[2]
638 path = os.path.normpath(urllib.unquote(path))
639 words = path.split('/')
640 words = filter(None, words)
641 path = self.root
642 for word in words:
643 drive, word = os.path.splitdrive(word)
644 head, word = os.path.split(word)
645 if word in self.root: continue
646 path = os.path.join(path, word)
647 return path
648
649 def log_message(self, format, *args):
650
651 # we override this to suppress logging unless "verbose"
652
653 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000654 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
655 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000656 self.server.server_port,
657 self.request.cipher(),
658 self.log_date_time_string(),
659 format%args))
660
661
Trent Nelsone41b0062008-04-08 23:47:30 +0000662 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000663 self.flag = None
Bill Janssen296a59d2007-09-16 22:06:00 +0000664 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
665 self.server = self.HTTPSServer(
Antoine Pitrou150acda2010-04-27 08:40:51 +0000666 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
667 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000668 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000669 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000670
671 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000672 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000673
Antoine Pitrou3945c862010-04-28 21:11:01 +0000674 def start(self, flag=None):
Bill Janssen296a59d2007-09-16 22:06:00 +0000675 self.flag = flag
676 threading.Thread.start(self)
677
Antoine Pitrou3945c862010-04-28 21:11:01 +0000678 def run(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000679 if self.flag:
680 self.flag.set()
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000681 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000682
Antoine Pitrou3945c862010-04-28 21:11:01 +0000683 def stop(self):
Antoine Pitrou435ba0c2010-04-27 09:51:18 +0000684 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000685
686
Antoine Pitrou3945c862010-04-28 21:11:01 +0000687 def bad_cert_test(certfile):
688 """
689 Launch a server with CERT_REQUIRED, and check that trying to
690 connect to it with the given client certificate fails.
691 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000692 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000693 certreqs=ssl.CERT_REQUIRED,
694 cacerts=CERTFILE, chatty=False)
695 flag = threading.Event()
696 server.start(flag)
697 # wait for it to start
698 flag.wait()
699 # try to connect
700 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000701 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000702 s = ssl.wrap_socket(socket.socket(),
703 certfile=certfile,
704 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000705 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000706 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000707 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000708 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000709 except socket.error, x:
710 if test_support.verbose:
711 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000712 else:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000713 raise AssertionError("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000714 finally:
715 server.stop()
716 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000717
Antoine Pitrou3945c862010-04-28 21:11:01 +0000718 def server_params_test(certfile, protocol, certreqs, cacertsfile,
719 client_certfile, client_protocol=None, indata="FOO\n",
720 ciphers=None, chatty=True, connectionchatty=False,
721 wrap_accepting_socket=False):
722 """
723 Launch a server, connect a client to it and try various reads
724 and writes.
725 """
Trent Nelsone41b0062008-04-08 23:47:30 +0000726 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000727 certreqs=certreqs,
728 ssl_version=protocol,
729 cacerts=cacertsfile,
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000730 ciphers=ciphers,
Bill Janssen98d19da2007-09-10 21:51:02 +0000731 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000732 connectionchatty=connectionchatty,
733 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000734 flag = threading.Event()
735 server.start(flag)
736 # wait for it to start
737 flag.wait()
738 # try to connect
739 if client_protocol is None:
740 client_protocol = protocol
741 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000742 s = ssl.wrap_socket(socket.socket(),
743 certfile=client_certfile,
744 ca_certs=cacertsfile,
745 ciphers=ciphers,
746 cert_reqs=certreqs,
747 ssl_version=client_protocol)
748 s.connect((HOST, server.port))
749 for arg in [indata, bytearray(indata), memoryview(indata)]:
Bill Janssen98d19da2007-09-10 21:51:02 +0000750 if connectionchatty:
751 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +0000752 sys.stdout.write(
753 " client: sending %s...\n" % (repr(arg)))
754 s.write(arg)
755 outdata = s.read()
756 if connectionchatty:
757 if test_support.verbose:
758 sys.stdout.write(" client: read %s\n" % repr(outdata))
759 if outdata != indata.lower():
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000760 raise AssertionError(
Antoine Pitroudb187842010-04-27 10:32:58 +0000761 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
762 % (outdata[:min(len(outdata),20)], len(outdata),
763 indata[:min(len(indata),20)].lower(), len(indata)))
764 s.write("over\n")
765 if connectionchatty:
766 if test_support.verbose:
767 sys.stdout.write(" client: closing connection.\n")
768 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000769 finally:
770 server.stop()
771 server.join()
772
Antoine Pitrou3945c862010-04-28 21:11:01 +0000773 def try_protocol_combo(server_protocol,
774 client_protocol,
775 expect_success,
776 certsreqs=None):
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000777 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000778 certsreqs = ssl.CERT_NONE
Antoine Pitrou3945c862010-04-28 21:11:01 +0000779 certtype = {
780 ssl.CERT_NONE: "CERT_NONE",
781 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
782 ssl.CERT_REQUIRED: "CERT_REQUIRED",
783 }[certsreqs]
Bill Janssen98d19da2007-09-10 21:51:02 +0000784 if test_support.verbose:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000785 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Bill Janssen98d19da2007-09-10 21:51:02 +0000786 sys.stdout.write(formatstr %
787 (ssl.get_protocol_name(client_protocol),
788 ssl.get_protocol_name(server_protocol),
789 certtype))
790 try:
Antoine Pitrou0a6373c2010-04-17 17:10:38 +0000791 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
792 # will send an SSLv3 hello (rather than SSLv2) starting from
793 # OpenSSL 1.0.0 (see issue #8322).
Antoine Pitrou3945c862010-04-28 21:11:01 +0000794 server_params_test(CERTFILE, server_protocol, certsreqs,
795 CERTFILE, CERTFILE, client_protocol,
796 ciphers="ALL", chatty=False)
Antoine Pitroudb187842010-04-27 10:32:58 +0000797 # Protocol mismatch can result in either an SSLError, or a
798 # "Connection reset by peer" error.
799 except ssl.SSLError:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000800 if expect_success:
Bill Janssen98d19da2007-09-10 21:51:02 +0000801 raise
Antoine Pitroudb187842010-04-27 10:32:58 +0000802 except socket.error as e:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000803 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitroudb187842010-04-27 10:32:58 +0000804 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000805 else:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000806 if not expect_success:
Antoine Pitrou1bbb68d2010-05-06 14:11:23 +0000807 raise AssertionError(
Bill Janssen98d19da2007-09-10 21:51:02 +0000808 "Client protocol %s succeeded with server protocol %s!"
809 % (ssl.get_protocol_name(client_protocol),
810 ssl.get_protocol_name(server_protocol)))
811
812
Bill Janssen934b16d2008-06-28 22:19:33 +0000813 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000814
Antoine Pitrou3945c862010-04-28 21:11:01 +0000815 def test_rude_shutdown(self):
816 """A brutal shutdown of an SSL server should raise an IOError
817 in the client when attempting handshake.
818 """
Bill Janssen98d19da2007-09-10 21:51:02 +0000819 listener_ready = threading.Event()
820 listener_gone = threading.Event()
821
Antoine Pitrou150acda2010-04-27 08:40:51 +0000822 s = socket.socket()
823 port = test_support.bind_port(s, HOST)
824
825 # `listener` runs in a thread. It sits in an accept() until
826 # the main thread connects. Then it rudely closes the socket,
827 # and sets Event `listener_gone` to let the main thread know
828 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000829 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000830 s.listen(5)
831 listener_ready.set()
832 s.accept()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000833 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000834 listener_gone.set()
835
836 def connector():
837 listener_ready.wait()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000838 c = socket.socket()
839 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000840 listener_gone.wait()
841 try:
Antoine Pitrou150acda2010-04-27 08:40:51 +0000842 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000843 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000844 pass
845 else:
Antoine Pitroudb187842010-04-27 10:32:58 +0000846 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000847
848 t = threading.Thread(target=listener)
849 t.start()
Antoine Pitrou150acda2010-04-27 08:40:51 +0000850 try:
851 connector()
852 finally:
853 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000854
Antoine Pitroud75efd92010-08-04 17:38:33 +0000855 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000856 def test_echo(self):
857 """Basic test of an SSL client connecting to a server"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000858 if test_support.verbose:
859 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000860 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
861 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
862 chatty=True, connectionchatty=True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000863
Antoine Pitrou3945c862010-04-28 21:11:01 +0000864 def test_getpeercert(self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000865 if test_support.verbose:
866 sys.stdout.write("\n")
867 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000868 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000869 certreqs=ssl.CERT_NONE,
870 ssl_version=ssl.PROTOCOL_SSLv23,
871 cacerts=CERTFILE,
872 chatty=False)
873 flag = threading.Event()
874 server.start(flag)
875 # wait for it to start
876 flag.wait()
877 # try to connect
878 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000879 s = ssl.wrap_socket(socket.socket(),
880 certfile=CERTFILE,
881 ca_certs=CERTFILE,
882 cert_reqs=ssl.CERT_REQUIRED,
883 ssl_version=ssl.PROTOCOL_SSLv23)
884 s.connect((HOST, server.port))
885 cert = s.getpeercert()
886 self.assertTrue(cert, "Can't get peer certificate.")
887 cipher = s.cipher()
888 if test_support.verbose:
889 sys.stdout.write(pprint.pformat(cert) + '\n')
890 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
891 if 'subject' not in cert:
892 self.fail("No subject field in certificate: %s." %
893 pprint.pformat(cert))
894 if ((('organizationName', 'Python Software Foundation'),)
895 not in cert['subject']):
896 self.fail(
897 "Missing or invalid 'organizationName' field in certificate subject; "
898 "should be 'Python Software Foundation'.")
899 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000900 finally:
901 server.stop()
902 server.join()
903
Antoine Pitrou3945c862010-04-28 21:11:01 +0000904 def test_empty_cert(self):
905 """Connecting with an empty cert file"""
906 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
907 "nullcert.pem"))
908 def test_malformed_cert(self):
909 """Connecting with a badly formatted certificate (syntax error)"""
910 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
911 "badcert.pem"))
912 def test_nonexisting_cert(self):
913 """Connecting with a non-existing cert file"""
914 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
915 "wrongcert.pem"))
916 def test_malformed_key(self):
917 """Connecting with a badly formatted key (syntax error)"""
918 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
919 "badkey.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000920
Antoine Pitroud75efd92010-08-04 17:38:33 +0000921 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000922 def test_protocol_sslv2(self):
923 """Connecting to an SSLv2 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000924 if test_support.verbose:
925 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000926 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
927 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
928 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
929 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
930 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
931 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000932
Antoine Pitroud75efd92010-08-04 17:38:33 +0000933 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000934 def test_protocol_sslv23(self):
935 """Connecting to an SSLv23 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000936 if test_support.verbose:
937 sys.stdout.write("\n")
938 try:
Antoine Pitrou3945c862010-04-28 21:11:01 +0000939 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou9bf54252010-04-27 13:13:26 +0000940 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000941 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
942 if test_support.verbose:
943 sys.stdout.write(
944 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
945 % str(x))
Antoine Pitrou3945c862010-04-28 21:11:01 +0000946 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
947 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
948 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Bill Janssen98d19da2007-09-10 21:51:02 +0000949
Antoine Pitrou3945c862010-04-28 21:11:01 +0000950 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
951 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
952 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Bill Janssen98d19da2007-09-10 21:51:02 +0000953
Antoine Pitrou3945c862010-04-28 21:11:01 +0000954 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
955 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
956 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Bill Janssen98d19da2007-09-10 21:51:02 +0000957
Antoine Pitroud75efd92010-08-04 17:38:33 +0000958 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000959 def test_protocol_sslv3(self):
960 """Connecting to an SSLv3 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000961 if test_support.verbose:
962 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000963 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
964 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
965 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
966 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
967 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
968 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000969
Antoine Pitroud75efd92010-08-04 17:38:33 +0000970 @skip_if_broken_ubuntu_ssl
Antoine Pitrou3945c862010-04-28 21:11:01 +0000971 def test_protocol_tlsv1(self):
972 """Connecting to a TLSv1 server with various client options"""
Bill Janssen98d19da2007-09-10 21:51:02 +0000973 if test_support.verbose:
974 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +0000975 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
976 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
977 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
978 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
979 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
980 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Bill Janssen98d19da2007-09-10 21:51:02 +0000981
Antoine Pitrou3945c862010-04-28 21:11:01 +0000982 def test_starttls(self):
983 """Switching from clear text to encrypted and back again."""
Bill Janssen39295c22008-08-12 16:31:21 +0000984 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000985
Trent Nelsone41b0062008-04-08 23:47:30 +0000986 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000987 ssl_version=ssl.PROTOCOL_TLSv1,
988 starttls_server=True,
989 chatty=True,
990 connectionchatty=True)
991 flag = threading.Event()
992 server.start(flag)
993 # wait for it to start
994 flag.wait()
995 # try to connect
996 wrapped = False
997 try:
Antoine Pitroudb187842010-04-27 10:32:58 +0000998 s = socket.socket()
999 s.setblocking(1)
1000 s.connect((HOST, server.port))
1001 if test_support.verbose:
1002 sys.stdout.write("\n")
1003 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +00001004 if test_support.verbose:
Antoine Pitroudb187842010-04-27 10:32:58 +00001005 sys.stdout.write(
1006 " client: sending %s...\n" % repr(indata))
1007 if wrapped:
1008 conn.write(indata)
1009 outdata = conn.read()
1010 else:
1011 s.send(indata)
1012 outdata = s.recv(1024)
1013 if (indata == "STARTTLS" and
1014 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001015 # STARTTLS ok, switch to secure mode
Bill Janssen98d19da2007-09-10 21:51:02 +00001016 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001017 sys.stdout.write(
Antoine Pitroudb187842010-04-27 10:32:58 +00001018 " client: read %s from server, starting TLS...\n"
1019 % repr(outdata))
1020 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
1021 wrapped = True
1022 elif (indata == "ENDTLS" and
1023 outdata.strip().lower().startswith("ok")):
Antoine Pitrou3945c862010-04-28 21:11:01 +00001024 # ENDTLS ok, switch back to clear text
Antoine Pitroudb187842010-04-27 10:32:58 +00001025 if test_support.verbose:
1026 sys.stdout.write(
1027 " client: read %s from server, ending TLS...\n"
1028 % repr(outdata))
1029 s = conn.unwrap()
1030 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001031 else:
Antoine Pitroudb187842010-04-27 10:32:58 +00001032 if test_support.verbose:
1033 sys.stdout.write(
1034 " client: read %s from server\n" % repr(outdata))
1035 if test_support.verbose:
1036 sys.stdout.write(" client: closing connection.\n")
1037 if wrapped:
1038 conn.write("over\n")
1039 else:
1040 s.send("over\n")
1041 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +00001042 finally:
1043 server.stop()
1044 server.join()
1045
Antoine Pitrou3945c862010-04-28 21:11:01 +00001046 def test_socketserver(self):
1047 """Using a SocketServer to create and manage SSL connections."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001048 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001049 flag = threading.Event()
1050 server.start(flag)
1051 # wait for it to start
1052 flag.wait()
1053 # try to connect
1054 try:
1055 if test_support.verbose:
1056 sys.stdout.write('\n')
Antoine Pitrou3945c862010-04-28 21:11:01 +00001057 with open(CERTFILE, 'rb') as f:
1058 d1 = f.read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001059 d2 = ''
1060 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001061 url = 'https://127.0.0.1:%d/%s' % (
1062 server.port, os.path.split(CERTFILE)[1])
Florent Xicluna07627882010-03-21 01:14:24 +00001063 with test_support.check_py3k_warnings():
1064 f = urllib.urlopen(url)
Bill Janssen296a59d2007-09-16 22:06:00 +00001065 dlen = f.info().getheader("content-length")
1066 if dlen and (int(dlen) > 0):
1067 d2 = f.read(int(dlen))
1068 if test_support.verbose:
1069 sys.stdout.write(
1070 " client: read %d bytes from remote server '%s'\n"
1071 % (len(d2), server))
1072 f.close()
Antoine Pitroudb187842010-04-27 10:32:58 +00001073 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +00001074 finally:
1075 server.stop()
1076 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001077
Antoine Pitrou3945c862010-04-28 21:11:01 +00001078 def test_wrapped_accept(self):
1079 """Check the accept() method on SSL sockets."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001080 if test_support.verbose:
1081 sys.stdout.write("\n")
Antoine Pitrou3945c862010-04-28 21:11:01 +00001082 server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1083 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1084 chatty=True, connectionchatty=True,
1085 wrap_accepting_socket=True)
Bill Janssen934b16d2008-06-28 22:19:33 +00001086
Antoine Pitrou3945c862010-04-28 21:11:01 +00001087 def test_asyncore_server(self):
1088 """Check the example asyncore integration."""
Bill Janssen934b16d2008-06-28 22:19:33 +00001089 indata = "TEST MESSAGE of mixed case\n"
1090
1091 if test_support.verbose:
1092 sys.stdout.write("\n")
1093 server = AsyncoreEchoServer(CERTFILE)
1094 flag = threading.Event()
1095 server.start(flag)
1096 # wait for it to start
1097 flag.wait()
1098 # try to connect
1099 try:
Antoine Pitroudb187842010-04-27 10:32:58 +00001100 s = ssl.wrap_socket(socket.socket())
1101 s.connect(('127.0.0.1', server.port))
1102 if test_support.verbose:
1103 sys.stdout.write(
1104 " client: sending %s...\n" % (repr(indata)))
1105 s.write(indata)
1106 outdata = s.read()
1107 if test_support.verbose:
1108 sys.stdout.write(" client: read %s\n" % repr(outdata))
1109 if outdata != indata.lower():
1110 self.fail(
1111 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1112 % (outdata[:min(len(outdata),20)], len(outdata),
1113 indata[:min(len(indata),20)].lower(), len(indata)))
1114 s.write("over\n")
1115 if test_support.verbose:
1116 sys.stdout.write(" client: closing connection.\n")
1117 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001118 finally:
1119 server.stop()
1120 # wait for server thread to end
1121 server.join()
1122
Antoine Pitrou3945c862010-04-28 21:11:01 +00001123 def test_recv_send(self):
1124 """Test recv(), send() and friends."""
Bill Janssen61c001a2008-09-08 16:37:24 +00001125 if test_support.verbose:
1126 sys.stdout.write("\n")
1127
1128 server = ThreadedEchoServer(CERTFILE,
1129 certreqs=ssl.CERT_NONE,
1130 ssl_version=ssl.PROTOCOL_TLSv1,
1131 cacerts=CERTFILE,
1132 chatty=True,
1133 connectionchatty=False)
1134 flag = threading.Event()
1135 server.start(flag)
1136 # wait for it to start
1137 flag.wait()
1138 # try to connect
Antoine Pitroudb187842010-04-27 10:32:58 +00001139 s = ssl.wrap_socket(socket.socket(),
1140 server_side=False,
1141 certfile=CERTFILE,
1142 ca_certs=CERTFILE,
1143 cert_reqs=ssl.CERT_NONE,
1144 ssl_version=ssl.PROTOCOL_TLSv1)
1145 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001146 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001147 # helper methods for standardising recv* method signatures
1148 def _recv_into():
1149 b = bytearray("\0"*100)
1150 count = s.recv_into(b)
1151 return b[:count]
1152
1153 def _recvfrom_into():
1154 b = bytearray("\0"*100)
1155 count, addr = s.recvfrom_into(b)
1156 return b[:count]
1157
1158 # (name, method, whether to expect success, *args)
1159 send_methods = [
1160 ('send', s.send, True, []),
1161 ('sendto', s.sendto, False, ["some.address"]),
1162 ('sendall', s.sendall, True, []),
1163 ]
1164 recv_methods = [
1165 ('recv', s.recv, True, []),
1166 ('recvfrom', s.recvfrom, False, ["some.address"]),
1167 ('recv_into', _recv_into, True, []),
1168 ('recvfrom_into', _recvfrom_into, False, []),
1169 ]
1170 data_prefix = u"PREFIX_"
1171
1172 for meth_name, send_meth, expect_success, args in send_methods:
1173 indata = data_prefix + meth_name
1174 try:
1175 send_meth(indata.encode('ASCII', 'strict'), *args)
1176 outdata = s.read()
1177 outdata = outdata.decode('ASCII', 'strict')
1178 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001179 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001180 "While sending with <<%s>> bad data "
1181 "<<%r>> (%d) received; "
1182 "expected <<%r>> (%d)\n" % (
1183 meth_name, outdata[:20], len(outdata),
1184 indata[:20], len(indata)
1185 )
1186 )
1187 except ValueError as e:
1188 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001189 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001190 "Failed to send with method <<%s>>; "
1191 "expected to succeed.\n" % (meth_name,)
1192 )
1193 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001194 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001195 "Method <<%s>> failed with unexpected "
1196 "exception message: %s\n" % (
1197 meth_name, e
1198 )
1199 )
1200
1201 for meth_name, recv_meth, expect_success, args in recv_methods:
1202 indata = data_prefix + meth_name
1203 try:
1204 s.send(indata.encode('ASCII', 'strict'))
1205 outdata = recv_meth(*args)
1206 outdata = outdata.decode('ASCII', 'strict')
1207 if outdata != indata.lower():
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001208 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001209 "While receiving with <<%s>> bad data "
1210 "<<%r>> (%d) received; "
1211 "expected <<%r>> (%d)\n" % (
1212 meth_name, outdata[:20], len(outdata),
1213 indata[:20], len(indata)
1214 )
1215 )
1216 except ValueError as e:
1217 if expect_success:
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001218 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001219 "Failed to receive with method <<%s>>; "
1220 "expected to succeed.\n" % (meth_name,)
1221 )
1222 if not str(e).startswith(meth_name):
Georg Brandlc7ca56d2010-02-06 23:23:45 +00001223 self.fail(
Bill Janssen61c001a2008-09-08 16:37:24 +00001224 "Method <<%s>> failed with unexpected "
1225 "exception message: %s\n" % (
1226 meth_name, e
1227 )
1228 )
1229 # consume data
1230 s.read()
1231
1232 s.write("over\n".encode("ASCII", "strict"))
1233 s.close()
1234 finally:
1235 server.stop()
1236 server.join()
1237
Antoine Pitroufc69af12010-04-24 20:04:58 +00001238 def test_handshake_timeout(self):
1239 # Issue #5103: SSL handshake must respect the socket timeout
1240 server = socket.socket(socket.AF_INET)
1241 host = "127.0.0.1"
1242 port = test_support.bind_port(server)
1243 started = threading.Event()
1244 finish = False
1245
1246 def serve():
1247 server.listen(5)
1248 started.set()
1249 conns = []
1250 while not finish:
1251 r, w, e = select.select([server], [], [], 0.1)
1252 if server in r:
1253 # Let the socket hang around rather than having
1254 # it closed by garbage collection.
1255 conns.append(server.accept()[0])
1256
1257 t = threading.Thread(target=serve)
1258 t.start()
1259 started.wait()
1260
1261 try:
1262 try:
1263 c = socket.socket(socket.AF_INET)
1264 c.settimeout(0.2)
1265 c.connect((host, port))
1266 # Will attempt handshake and time out
1267 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1268 ssl.wrap_socket, c)
1269 finally:
1270 c.close()
1271 try:
1272 c = socket.socket(socket.AF_INET)
1273 c.settimeout(0.2)
1274 c = ssl.wrap_socket(c)
1275 # Will attempt handshake and time out
1276 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1277 c.connect, (host, port))
1278 finally:
1279 c.close()
1280 finally:
1281 finish = True
1282 t.join()
1283 server.close()
1284
Bill Janssen61c001a2008-09-08 16:37:24 +00001285
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001286def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001287 if skip_expected:
Benjamin Peterson888a39b2009-03-26 20:48:25 +00001288 raise unittest.SkipTest("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001289
Trent Nelsone41b0062008-04-08 23:47:30 +00001290 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001291 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001292 "keycert.pem")
1293 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1294 os.path.dirname(__file__) or os.curdir,
1295 "https_svn_python_org_root.pem")
1296
1297 if (not os.path.exists(CERTFILE) or
1298 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001299 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001300
Antoine Pitroude30f702010-09-14 12:54:08 +00001301 tests = [BasicTests, BasicSocketTests]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001302
Bill Janssen296a59d2007-09-16 22:06:00 +00001303 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001304 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001305
Bill Janssen98d19da2007-09-10 21:51:02 +00001306 if _have_threads:
1307 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001308 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001309 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001310
Antoine Pitrou3945c862010-04-28 21:11:01 +00001311 try:
1312 test_support.run_unittest(*tests)
1313 finally:
1314 if _have_threads:
1315 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001316
1317if __name__ == "__main__":
1318 test_main()