blob: 7eea4b8d4b0d19578b4433d3afd25c2aa08876aa [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 errno
Thomas Woutersed03b412007-08-28 21:37:11 +00009import subprocess
10import time
Antoine Pitrou3b9b9ba2010-04-23 23:33:50 +000011import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000012import os
Antoine Pitrou3b9b9ba2010-04-23 23:33:50 +000013import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000014import pprint
Jeremy Hylton1afc1692008-06-18 20:49:58 +000015import urllib.parse, urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000016import shutil
17import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000018import asyncore
Antoine Pitrou78f4a9a2010-04-23 23:12:22 +000019import weakref
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Georg Brandl24420152008-05-26 16:32:26 +000021from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000022
Thomas Woutersed03b412007-08-28 21:37:11 +000023# Optionally test SSL support, if we have it in the tested platform
24skip_expected = False
25try:
26 import ssl
27except ImportError:
28 skip_expected = True
29
Benjamin Petersonee8712c2008-05-20 21:35:26 +000030HOST = support.HOST
Thomas Woutersed03b412007-08-28 21:37:11 +000031CERTFILE = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +000032SVN_PYTHON_ORG_ROOT_CERT = None
Thomas Woutersed03b412007-08-28 21:37:11 +000033
Thomas Woutersed03b412007-08-28 21:37:11 +000034def handle_error(prefix):
35 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000036 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000037 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000038
39
40class BasicTests(unittest.TestCase):
41
Georg Brandlfceab5a2008-01-19 20:08:23 +000042 def testSSLconnect(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000043 if not support.is_resource_enabled('network'):
Georg Brandlfceab5a2008-01-19 20:08:23 +000044 return
45 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
46 cert_reqs=ssl.CERT_NONE)
47 s.connect(("svn.python.org", 443))
48 c = s.getpeercert()
49 if c:
Benjamin Petersonee8712c2008-05-20 21:35:26 +000050 raise support.TestFailed("Peer cert %s shouldn't be here!")
Georg Brandlfceab5a2008-01-19 20:08:23 +000051 s.close()
52
53 # this should fail because we have no verification certs
54 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
55 cert_reqs=ssl.CERT_REQUIRED)
56 try:
57 s.connect(("svn.python.org", 443))
58 except ssl.SSLError:
59 pass
60 finally:
61 s.close()
62
Thomas Wouters1b7f8912007-09-19 03:06:30 +000063 def testCrucialConstants(self):
64 ssl.PROTOCOL_SSLv2
65 ssl.PROTOCOL_SSLv23
66 ssl.PROTOCOL_SSLv3
67 ssl.PROTOCOL_TLSv1
68 ssl.CERT_NONE
69 ssl.CERT_OPTIONAL
70 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000071
Thomas Wouters1b7f8912007-09-19 03:06:30 +000072 def testRAND(self):
73 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000074 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000075 sys.stdout.write("\n RAND_status is %d (%s)\n"
76 % (v, (v and "sufficient randomness") or
77 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000078 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000079 ssl.RAND_egd(1)
80 except TypeError:
81 pass
Thomas Woutersed03b412007-08-28 21:37:11 +000082 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000083 print("didn't raise TypeError")
84 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +000085
Thomas Wouters1b7f8912007-09-19 03:06:30 +000086 def testParseCert(self):
87 # note that this uses an 'unofficial' function in _ssl.c,
88 # provided solely for this test, to exercise the certificate
89 # parsing code
90 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000091 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000092 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +000093
Thomas Wouters1b7f8912007-09-19 03:06:30 +000094 def testDERtoPEM(self):
95
96 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
97 d1 = ssl.PEM_cert_to_DER_cert(pem)
98 p2 = ssl.DER_cert_to_PEM_cert(d1)
99 d2 = ssl.PEM_cert_to_DER_cert(p2)
100 if (d1 != d2):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000101 raise support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000102
Antoine Pitrou78f4a9a2010-04-23 23:12:22 +0000103 @support.cpython_only
104 def test_refcycle(self):
105 # Issue #7943: an SSL object doesn't create reference cycles with
106 # itself.
107 s = socket.socket(socket.AF_INET)
108 ss = ssl.wrap_socket(s)
109 wr = weakref.ref(ss)
110 del ss
111 self.assertEqual(wr(), None)
112
Antoine Pitrouc2203f92010-04-24 22:07:51 +0000113 def test_timeout(self):
114 # Issue #8524: when creating an SSL socket, the timeout of the
115 # original socket should be retained.
116 for timeout in (None, 0.0, 5.0):
117 s = socket.socket(socket.AF_INET)
118 s.settimeout(timeout)
119 ss = ssl.wrap_socket(s)
120 self.assertEqual(timeout, ss.gettimeout())
121
Antoine Pitrou3b9b9ba2010-04-23 23:33:50 +0000122
Bill Janssen6e027db2007-11-15 22:23:56 +0000123class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000124
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000125 def testConnect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000126 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
127 cert_reqs=ssl.CERT_NONE)
128 s.connect(("svn.python.org", 443))
129 c = s.getpeercert()
130 if c:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000131 raise support.TestFailed("Peer cert %s shouldn't be here!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000132 s.close()
133
134 # this should fail because we have no verification certs
135 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
136 cert_reqs=ssl.CERT_REQUIRED)
Thomas Woutersed03b412007-08-28 21:37:11 +0000137 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 s.connect(("svn.python.org", 443))
139 except ssl.SSLError:
140 pass
141 finally:
142 s.close()
143
144 # this should succeed because we specify the root cert
145 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
146 cert_reqs=ssl.CERT_REQUIRED,
147 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
148 try:
149 s.connect(("svn.python.org", 443))
150 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000151 raise support.TestFailed("Unexpected exception %s" % x)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000152 finally:
153 s.close()
154
Antoine Pitroufe0f1172010-04-24 11:17:37 +0000155 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
156 def test_makefile_close(self):
157 # Issue #5238: creating a file-like object with makefile() shouldn't
158 # delay closing the underlying "real socket" (here tested with its
159 # file descriptor, hence skipping the test under Windows).
160 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
161 ss.connect(("svn.python.org", 443))
162 fd = ss.fileno()
163 f = ss.makefile()
164 f.close()
165 # The fd is still open
166 os.read(fd, 0)
167 # Closing the SSL socket should close the fd too
168 ss.close()
169 gc.collect()
170 try:
171 os.read(fd, 0)
172 except OSError as e:
173 self.assertEqual(e.errno, errno.EBADF)
174 else:
175 self.fail("OSError wasn't raised")
176
Bill Janssen6e027db2007-11-15 22:23:56 +0000177 def testNonBlockingHandshake(self):
178 s = socket.socket(socket.AF_INET)
179 s.connect(("svn.python.org", 443))
180 s.setblocking(False)
181 s = ssl.wrap_socket(s,
182 cert_reqs=ssl.CERT_NONE,
183 do_handshake_on_connect=False)
184 count = 0
185 while True:
186 try:
187 count += 1
188 s.do_handshake()
189 break
190 except ssl.SSLError as err:
191 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
192 select.select([s], [], [])
193 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
194 select.select([], [s], [])
195 else:
196 raise
197 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000198 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000199 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000200
Bill Janssen54cc54c2007-12-14 22:08:56 +0000201 def testFetchServerCert(self):
202
203 pem = ssl.get_server_certificate(("svn.python.org", 443))
204 if not pem:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000205 raise support.TestFailed("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000206
207 return
208
209 try:
210 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
211 except ssl.SSLError as x:
212 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000213 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000214 sys.stdout.write("%s\n" % x)
215 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000216 raise support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000217
218 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
219 if not pem:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000220 raise support.TestFailed("No server certificate on svn.python.org:443!")
221 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000222 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
223
Antoine Pitrou754b98c2010-04-22 18:47:06 +0000224 # Test disabled: OPENSSL_VERSION* not available in Python 3.1
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000225 def test_algorithms(self):
Antoine Pitrouae92a722010-04-22 18:46:16 +0000226 if support.verbose:
227 sys.stdout.write("test_algorithms disabled, "
228 "as it fails on some old OpenSSL versions")
229 return
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000230 # Issue #8484: all algorithms should be available when verifying a
231 # certificate.
Antoine Pitrouae92a722010-04-22 18:46:16 +0000232 # SHA256 was added in OpenSSL 0.9.8
233 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
234 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000235 # NOTE: https://sha256.tbs-internet.com is another possible test host
236 remote = ("sha2.hboeck.de", 443)
237 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
238 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
239 cert_reqs=ssl.CERT_REQUIRED,
240 ca_certs=sha256_cert,)
241 with support.transient_internet():
242 try:
243 s.connect(remote)
244 if support.verbose:
245 sys.stdout.write("\nCipher with %r is %r\n" %
246 (remote, s.cipher()))
247 sys.stdout.write("Certificate is:\n%s\n" %
248 pprint.pformat(s.getpeercert()))
249 finally:
250 s.close()
251
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000252
253try:
254 import threading
255except ImportError:
256 _have_threads = False
257else:
258
259 _have_threads = True
260
261 class ThreadedEchoServer(threading.Thread):
262
263 class ConnectionHandler(threading.Thread):
264
265 """A mildly complicated class, because we want it to work both
266 with and without the SSL wrapper around the socket connection, so
267 that we can test the STARTTLS functionality."""
268
Bill Janssen6e027db2007-11-15 22:23:56 +0000269 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000270 self.server = server
271 self.running = False
272 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000273 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000274 self.sock.setblocking(1)
275 self.sslconn = None
276 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000277 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000278
279 def wrap_conn (self):
280 try:
281 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
282 certfile=self.server.certificate,
283 ssl_version=self.server.protocol,
284 ca_certs=self.server.cacerts,
285 cert_reqs=self.server.certreqs)
286 except:
287 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000288 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000289 if not self.server.expect_bad_connects:
290 # here, we want to stop the server, because this shouldn't
291 # happen in the context of our test case
292 self.running = False
293 # normally, we'd just stop here, but for the test
294 # harness, we want to stop the server
295 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000296 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000297 return False
298
299 else:
300 if self.server.certreqs == ssl.CERT_REQUIRED:
301 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000302 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000303 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
304 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000305 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000306 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
307 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000308 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000309 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
310 return True
311
312 def read(self):
313 if self.sslconn:
314 return self.sslconn.read()
315 else:
316 return self.sock.recv(1024)
317
318 def write(self, bytes):
319 if self.sslconn:
320 return self.sslconn.write(bytes)
321 else:
322 return self.sock.send(bytes)
323
324 def close(self):
325 if self.sslconn:
326 self.sslconn.close()
327 else:
328 self.sock.close()
329
330 def run (self):
331 self.running = True
332 if not self.server.starttls_server:
333 if not self.wrap_conn():
334 return
335 while self.running:
336 try:
337 msg = self.read()
Bill Janssen6e027db2007-11-15 22:23:56 +0000338 amsg = (msg and str(msg, 'ASCII', 'strict')) or ''
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000339 if not msg:
340 # eof, so quit this handler
341 self.running = False
342 self.close()
Bill Janssen6e027db2007-11-15 22:23:56 +0000343 elif amsg.strip() == 'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000344 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000345 sys.stdout.write(" server: client closed connection\n")
346 self.close()
347 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000348 elif (self.server.starttls_server and
349 amsg.strip() == 'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000350 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000351 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000352 self.write("OK\n".encode("ASCII", "strict"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000353 if not self.wrap_conn():
354 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000355 elif (self.server.starttls_server and self.sslconn
356 and amsg.strip() == 'ENDTLS'):
357 if support.verbose and self.server.connectionchatty:
358 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
359 self.write("OK\n".encode("ASCII", "strict"))
360 self.sock = self.sslconn.unwrap()
361 self.sslconn = None
362 if support.verbose and self.server.connectionchatty:
363 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000364 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000365 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000366 self.server.connectionchatty):
367 ctype = (self.sslconn and "encrypted") or "unencrypted"
368 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
369 % (repr(msg), ctype, repr(msg.lower()), ctype))
Bill Janssen6e027db2007-11-15 22:23:56 +0000370 self.write(amsg.lower().encode('ASCII', 'strict'))
371 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000372 if self.server.chatty:
373 handle_error("Test server failure:\n")
374 self.close()
375 self.running = False
376 # normally, we'd just stop here, but for the test
377 # harness, we want to stop the server
378 self.server.stop()
379 except:
380 handle_error('')
381
Trent Nelson78520002008-04-10 20:54:35 +0000382 def __init__(self, certificate, ssl_version=None,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000383 certreqs=None, cacerts=None, expect_bad_connects=False,
384 chatty=True, connectionchatty=False, starttls_server=False):
385 if ssl_version is None:
386 ssl_version = ssl.PROTOCOL_TLSv1
387 if certreqs is None:
388 certreqs = ssl.CERT_NONE
389 self.certificate = certificate
390 self.protocol = ssl_version
391 self.certreqs = certreqs
392 self.cacerts = cacerts
393 self.expect_bad_connects = expect_bad_connects
394 self.chatty = chatty
395 self.connectionchatty = connectionchatty
396 self.starttls_server = starttls_server
397 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000398 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000399 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000400 self.active = False
401 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000402 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000403
404 def start (self, flag=None):
405 self.flag = flag
406 threading.Thread.start(self)
407
408 def run (self):
409 self.sock.settimeout(0.5)
410 self.sock.listen(5)
411 self.active = True
412 if self.flag:
413 # signal an event
414 self.flag.set()
415 while self.active:
416 try:
417 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000418 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000419 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000420 + repr(connaddr) + '\n')
421 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000422 handler.start()
423 except socket.timeout:
424 pass
425 except KeyboardInterrupt:
426 self.stop()
427 except:
428 if self.chatty:
429 handle_error("Test server failure:\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000430 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000431
432 def stop (self):
433 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000434
Bill Janssen54cc54c2007-12-14 22:08:56 +0000435 class OurHTTPSServer(threading.Thread):
436
437 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000438
439 class HTTPSServer(HTTPServer):
440
441 def __init__(self, server_address, RequestHandlerClass, certfile):
442
443 HTTPServer.__init__(self, server_address, RequestHandlerClass)
444 # we assume the certfile contains both private key and certificate
445 self.certfile = certfile
446 self.active = False
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000447 self.active_lock = threading.Lock()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000448 self.allow_reuse_address = True
449
Bill Janssen6e027db2007-11-15 22:23:56 +0000450 def __str__(self):
451 return ('<%s %s:%s>' %
452 (self.__class__.__name__,
453 self.server_name,
454 self.server_port))
455
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000456 def get_request (self):
457 # override this to wrap socket with SSL
458 sock, addr = self.socket.accept()
459 sslconn = ssl.wrap_socket(sock, server_side=True,
460 certfile=self.certfile)
461 return sslconn, addr
462
463 # The methods overridden below this are mainly so that we
464 # can run it in a thread and be able to stop it from another
465 # You probably wouldn't need them in other uses.
466
467 def server_activate(self):
468 # We want to run this in a thread for testing purposes,
469 # so we override this to set timeout, so that we get
470 # a chance to stop the server
471 self.socket.settimeout(0.5)
472 HTTPServer.server_activate(self)
473
474 def serve_forever(self):
475 # We want this to run in a thread, so we use a slightly
476 # modified version of "forever".
477 self.active = True
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000478 while 1:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000479 try:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000480 # We need to lock while handling the request.
481 # Another thread can close the socket after self.active
482 # has been checked and before the request is handled.
483 # This causes an exception when using the closed socket.
484 with self.active_lock:
485 if not self.active:
486 break
487 self.handle_request()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000488 except socket.timeout:
489 pass
490 except KeyboardInterrupt:
491 self.server_close()
492 return
493 except:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000494 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
495 break
Neal Norwitzf9ff5f02008-03-31 05:39:26 +0000496 time.sleep(0.1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000497
498 def server_close(self):
499 # Again, we want this to run in a thread, so we need to override
500 # close to clear the "active" flag, so that serve_forever() will
501 # terminate.
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000502 with self.active_lock:
503 HTTPServer.server_close(self)
504 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000505
506 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
507
508 # need to override translate_path to get a known root,
509 # instead of using os.curdir, since the test could be
510 # run from anywhere
511
512 server_version = "TestHTTPS/1.0"
513
514 root = None
515
516 def translate_path(self, path):
517 """Translate a /-separated PATH to the local filename syntax.
518
519 Components that mean special things to the local file system
520 (e.g. drive or directory names) are ignored. (XXX They should
521 probably be diagnosed.)
522
523 """
524 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000525 path = urllib.parse.urlparse(path)[2]
526 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000527 words = path.split('/')
528 words = filter(None, words)
529 path = self.root
530 for word in words:
531 drive, word = os.path.splitdrive(word)
532 head, word = os.path.split(word)
533 if word in self.root: continue
534 path = os.path.join(path, word)
535 return path
536
537 def log_message(self, format, *args):
538
539 # we override this to suppress logging unless "verbose"
540
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000541 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000542 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
543 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000544 self.server.server_port,
545 self.request.cipher(),
546 self.log_date_time_string(),
547 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000548
549
Trent Nelson78520002008-04-10 20:54:35 +0000550 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000551 self.flag = None
552 self.active = False
553 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000554 self.port = support.find_unused_port()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000555 self.server = self.HTTPSServer(
Trent Nelson78520002008-04-10 20:54:35 +0000556 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Thomas Woutersed03b412007-08-28 21:37:11 +0000557 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000558 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000559
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000560 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000561 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000562
563 def start (self, flag=None):
564 self.flag = flag
565 threading.Thread.start(self)
566
Thomas Woutersed03b412007-08-28 21:37:11 +0000567 def run (self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000568 self.active = True
569 if self.flag:
570 self.flag.set()
571 self.server.serve_forever()
572 self.active = False
573
574 def stop (self):
575 self.active = False
576 self.server.server_close()
577
578
Bill Janssen54cc54c2007-12-14 22:08:56 +0000579 class AsyncoreEchoServer(threading.Thread):
580
581 # this one's based on asyncore.dispatcher
582
583 class EchoServer (asyncore.dispatcher):
584
585 class ConnectionHandler (asyncore.dispatcher_with_send):
586
587 def __init__(self, conn, certfile):
588 self.socket = ssl.wrap_socket(conn, server_side=True,
589 certfile=certfile,
590 do_handshake_on_connect=False)
591 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitrouec146182010-04-24 21:30:20 +0000592 self._ssl_accepting = True
593 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000594
595 def readable(self):
596 if isinstance(self.socket, ssl.SSLSocket):
597 while self.socket.pending() > 0:
598 self.handle_read_event()
599 return True
600
Antoine Pitrouec146182010-04-24 21:30:20 +0000601 def _do_ssl_handshake(self):
602 try:
603 self.socket.do_handshake()
604 except ssl.SSLError as err:
605 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
606 ssl.SSL_ERROR_WANT_WRITE):
607 return
608 elif err.args[0] == ssl.SSL_ERROR_EOF:
609 return self.handle_close()
610 raise
611 except socket.error as err:
612 if err.args[0] == errno.ECONNABORTED:
613 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000614 else:
Antoine Pitrouec146182010-04-24 21:30:20 +0000615 self._ssl_accepting = False
616
617 def handle_read(self):
618 if self._ssl_accepting:
619 self._do_ssl_handshake()
620 else:
621 data = self.recv(1024)
622 if support.verbose:
623 sys.stdout.write(" server: read %s from client\n" % repr(data))
624 if not data:
625 self.close()
626 else:
627 self.send(str(data, 'ASCII', 'strict').lower().encode('ASCII', 'strict'))
Bill Janssen54cc54c2007-12-14 22:08:56 +0000628
629 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000630 self.close()
Antoine Pitrouec146182010-04-24 21:30:20 +0000631 if test_support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000632 sys.stdout.write(" server: closed connection %s\n" % self.socket)
633
634 def handle_error(self):
635 raise
636
637 def __init__(self, port, certfile):
638 self.port = port
639 self.certfile = certfile
640 asyncore.dispatcher.__init__(self)
641 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
642 self.bind(('', port))
643 self.listen(5)
644
645 def handle_accept(self):
646 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000647 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000648 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
649 self.ConnectionHandler(sock_obj, self.certfile)
650
651 def handle_error(self):
652 raise
653
Trent Nelson78520002008-04-10 20:54:35 +0000654 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000655 self.flag = None
656 self.active = False
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000657 self.port = support.find_unused_port()
Trent Nelson78520002008-04-10 20:54:35 +0000658 self.server = self.EchoServer(self.port, certfile)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000659 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000660 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000661
662 def __str__(self):
663 return "<%s %s>" % (self.__class__.__name__, self.server)
664
665 def start (self, flag=None):
666 self.flag = flag
667 threading.Thread.start(self)
668
669 def run (self):
670 self.active = True
671 if self.flag:
672 self.flag.set()
673 while self.active:
674 try:
675 asyncore.loop(1)
676 except:
677 pass
678
679 def stop (self):
680 self.active = False
681 self.server.close()
682
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000683 def badCertTest (certfile):
Trent Nelson78520002008-04-10 20:54:35 +0000684 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000685 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000686 cacerts=CERTFILE, chatty=False,
687 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000688 flag = threading.Event()
689 server.start(flag)
690 # wait for it to start
691 flag.wait()
692 # try to connect
693 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000694 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000695 s = ssl.wrap_socket(socket.socket(),
696 certfile=certfile,
697 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000698 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000699 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000700 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000701 sys.stdout.write("\nSSLError is %s\n" % x)
Bill Janssenddc56692008-07-17 18:17:20 +0000702 except socket.error as x:
703 if support.verbose:
704 sys.stdout.write("\nsocket.error is %s\n" % x)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000705 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000706 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000707 "Use of invalid cert should have failed!")
708 finally:
709 server.stop()
710 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000711
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000712 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
Bill Janssen6e027db2007-11-15 22:23:56 +0000713 client_certfile, client_protocol=None,
714 indata="FOO\n",
715 chatty=False, connectionchatty=False):
Thomas Woutersed03b412007-08-28 21:37:11 +0000716
Trent Nelson78520002008-04-10 20:54:35 +0000717 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000718 certreqs=certreqs,
719 ssl_version=protocol,
720 cacerts=cacertsfile,
721 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000722 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000723 flag = threading.Event()
724 server.start(flag)
725 # wait for it to start
726 flag.wait()
727 # try to connect
728 if client_protocol is None:
729 client_protocol = protocol
730 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000731 s = ssl.wrap_socket(socket.socket(),
Trent Nelson6b240cd2008-04-10 20:12:06 +0000732 server_side=False,
Bill Janssen6e027db2007-11-15 22:23:56 +0000733 certfile=client_certfile,
734 ca_certs=cacertsfile,
735 cert_reqs=certreqs,
736 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000737 s.connect((HOST, server.port))
Bill Janssen6e027db2007-11-15 22:23:56 +0000738 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000739 raise support.TestFailed("Unexpected SSL error: " + str(x))
Bill Janssen6e027db2007-11-15 22:23:56 +0000740 except Exception as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000741 raise support.TestFailed("Unexpected exception: " + str(x))
Bill Janssen6e027db2007-11-15 22:23:56 +0000742 else:
743 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000744 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000745 sys.stdout.write(
746 " client: sending %s...\n" % (repr(indata)))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000747 s.write(indata.encode('ASCII', 'strict'))
Bill Janssen6e027db2007-11-15 22:23:56 +0000748 outdata = s.read()
749 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000750 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000751 sys.stdout.write(" client: read %s\n" % repr(outdata))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000752 outdata = str(outdata, 'ASCII', 'strict')
Bill Janssen6e027db2007-11-15 22:23:56 +0000753 if outdata != indata.lower():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000754 raise support.TestFailed(
Bill Janssen6e027db2007-11-15 22:23:56 +0000755 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +0000756 % (repr(outdata[:min(len(outdata),20)]), len(outdata),
757 repr(indata[:min(len(indata),20)].lower()), len(indata)))
758 s.write("over\n".encode("ASCII", "strict"))
Bill Janssen6e027db2007-11-15 22:23:56 +0000759 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000760 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000761 sys.stdout.write(" client: closing connection.\n")
762 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000763 finally:
764 server.stop()
765 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000766
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000767 def tryProtocolCombo (server_protocol,
768 client_protocol,
769 expectedToWork,
770 certsreqs=None):
Thomas Woutersed03b412007-08-28 21:37:11 +0000771
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000772 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000773 certsreqs = ssl.CERT_NONE
Thomas Woutersed03b412007-08-28 21:37:11 +0000774
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000775 if certsreqs == ssl.CERT_NONE:
776 certtype = "CERT_NONE"
777 elif certsreqs == ssl.CERT_OPTIONAL:
778 certtype = "CERT_OPTIONAL"
779 elif certsreqs == ssl.CERT_REQUIRED:
780 certtype = "CERT_REQUIRED"
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000781 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000782 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
783 sys.stdout.write(formatstr %
784 (ssl.get_protocol_name(client_protocol),
785 ssl.get_protocol_name(server_protocol),
786 certtype))
787 try:
788 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000789 CERTFILE, CERTFILE, client_protocol,
790 chatty=False, connectionchatty=False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000791 except support.TestFailed:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000792 if expectedToWork:
793 raise
794 else:
795 if not expectedToWork:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000796 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000797 "Client protocol %s succeeded with server protocol %s!"
798 % (ssl.get_protocol_name(client_protocol),
799 ssl.get_protocol_name(server_protocol)))
800
801
Bill Janssen6e027db2007-11-15 22:23:56 +0000802 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000803
Trent Nelson6b240cd2008-04-10 20:12:06 +0000804 def testEcho (self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000805
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000806 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000807 sys.stdout.write("\n")
808 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
809 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
810 chatty=True, connectionchatty=True)
811
812 def testReadCert(self):
813
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000814 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000815 sys.stdout.write("\n")
816 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000817 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000818 certreqs=ssl.CERT_NONE,
819 ssl_version=ssl.PROTOCOL_SSLv23,
820 cacerts=CERTFILE,
821 chatty=False)
822 flag = threading.Event()
823 server.start(flag)
824 # wait for it to start
825 flag.wait()
826 # try to connect
827 try:
828 try:
829 s = ssl.wrap_socket(socket.socket(),
830 certfile=CERTFILE,
831 ca_certs=CERTFILE,
832 cert_reqs=ssl.CERT_REQUIRED,
833 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelson78520002008-04-10 20:54:35 +0000834 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000835 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000836 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000837 "Unexpected SSL error: " + str(x))
838 except Exception as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000839 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000840 "Unexpected exception: " + str(x))
841 else:
842 if not s:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000843 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000844 "Can't SSL-handshake with test server")
845 cert = s.getpeercert()
846 if not cert:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000847 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000848 "Can't get peer certificate.")
849 cipher = s.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000850 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000851 sys.stdout.write(pprint.pformat(cert) + '\n')
852 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Bill Janssen6e027db2007-11-15 22:23:56 +0000853 if 'subject' not in cert:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000854 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000855 "No subject field in certificate: %s." %
856 pprint.pformat(cert))
857 if ((('organizationName', 'Python Software Foundation'),)
858 not in cert['subject']):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000859 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 "Missing or invalid 'organizationName' field in certificate subject; "
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000861 "should be 'Python Software Foundation'.")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000862 s.close()
863 finally:
864 server.stop()
865 server.join()
866
867 def testNULLcert(self):
868 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
869 "nullcert.pem"))
870 def testMalformedCert(self):
871 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
872 "badcert.pem"))
Bill Janssen58afe4c2008-09-08 16:45:19 +0000873 def testWrongCert(self):
874 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
875 "wrongcert.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000876 def testMalformedKey(self):
877 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
878 "badkey.pem"))
879
Trent Nelson6b240cd2008-04-10 20:12:06 +0000880 def testRudeShutdown(self):
881
882 listener_ready = threading.Event()
883 listener_gone = threading.Event()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000884 port = support.find_unused_port()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000885
886 # `listener` runs in a thread. It opens a socket listening on
887 # PORT, and sits in an accept() until the main thread connects.
888 # Then it rudely closes the socket, and sets Event `listener_gone`
889 # to let the main thread know the socket is gone.
890 def listener():
891 s = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000892 s.bind((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000893 s.listen(5)
894 listener_ready.set()
895 s.accept()
896 s = None # reclaim the socket object, which also closes it
897 listener_gone.set()
898
899 def connector():
900 listener_ready.wait()
901 s = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000902 s.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000903 listener_gone.wait()
904 try:
905 ssl_sock = ssl.wrap_socket(s)
906 except IOError:
907 pass
908 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000909 raise support.TestFailed(
Trent Nelson6b240cd2008-04-10 20:12:06 +0000910 'connecting to closed SSL socket should have failed')
911
912 t = threading.Thread(target=listener)
913 t.start()
914 connector()
915 t.join()
916
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000917 def testProtocolSSL2(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000918 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000919 sys.stdout.write("\n")
920 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
921 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
922 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
923 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
924 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
925 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
926
927 def testProtocolSSL23(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000928 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000929 sys.stdout.write("\n")
930 try:
931 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000932 except support.TestFailed as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000933 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000934 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000935 sys.stdout.write(
936 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
937 % str(x))
938 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
939 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
940 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
941
942 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
943 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
944 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
945
946 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
947 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
948 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
949
950 def testProtocolSSL3(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000951 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000952 sys.stdout.write("\n")
953 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
954 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
955 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
956 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
957 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
958 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
959
960 def testProtocolTLS1(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000961 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000962 sys.stdout.write("\n")
963 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
964 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
965 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
966 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
967 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
968 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
969
970 def testSTARTTLS (self):
971
Bill Janssen40a0f662008-08-12 16:56:25 +0000972 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000973
Trent Nelson78520002008-04-10 20:54:35 +0000974 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000975 ssl_version=ssl.PROTOCOL_TLSv1,
976 starttls_server=True,
977 chatty=True,
978 connectionchatty=True)
979 flag = threading.Event()
980 server.start(flag)
981 # wait for it to start
982 flag.wait()
983 # try to connect
984 wrapped = False
985 try:
986 try:
987 s = socket.socket()
988 s.setblocking(1)
Trent Nelson78520002008-04-10 20:54:35 +0000989 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 except Exception as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000991 raise support.TestFailed("Unexpected exception: " + str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000992 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000993 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000994 sys.stdout.write("\n")
995 for indata in msgs:
Bill Janssen6e027db2007-11-15 22:23:56 +0000996 msg = indata.encode('ASCII', 'replace')
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000997 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 sys.stdout.write(
Bill Janssen6e027db2007-11-15 22:23:56 +0000999 " client: sending %s...\n" % repr(msg))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001000 if wrapped:
Bill Janssen6e027db2007-11-15 22:23:56 +00001001 conn.write(msg)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002 outdata = conn.read()
1003 else:
Bill Janssen6e027db2007-11-15 22:23:56 +00001004 s.send(msg)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001005 outdata = s.recv(1024)
1006 if (indata == "STARTTLS" and
Bill Janssen6e027db2007-11-15 22:23:56 +00001007 str(outdata, 'ASCII', 'replace').strip().lower().startswith("ok")):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001008 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001009 msg = str(outdata, 'ASCII', 'replace')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001010 sys.stdout.write(
1011 " client: read %s from server, starting TLS...\n"
Bill Janssen6e027db2007-11-15 22:23:56 +00001012 % repr(msg))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001013 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001014 wrapped = True
Bill Janssen40a0f662008-08-12 16:56:25 +00001015 elif (indata == "ENDTLS" and
1016 str(outdata, 'ASCII', 'replace').strip().lower().startswith("ok")):
1017 if support.verbose:
1018 msg = str(outdata, 'ASCII', 'replace')
1019 sys.stdout.write(
1020 " client: read %s from server, ending TLS...\n"
1021 % repr(msg))
1022 s = conn.unwrap()
1023 wrapped = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001024 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001025 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001026 msg = str(outdata, 'ASCII', 'replace')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001027 sys.stdout.write(
Bill Janssen6e027db2007-11-15 22:23:56 +00001028 " client: read %s from server\n" % repr(msg))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001029 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001030 sys.stdout.write(" client: closing connection.\n")
1031 if wrapped:
Bill Janssen6e027db2007-11-15 22:23:56 +00001032 conn.write("over\n".encode("ASCII", "strict"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001033 else:
Bill Janssen40a0f662008-08-12 16:56:25 +00001034 s.send("over\n".encode("ASCII", "strict"))
Bill Janssen6e027db2007-11-15 22:23:56 +00001035 if wrapped:
1036 conn.close()
1037 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001038 s.close()
1039 finally:
1040 server.stop()
1041 server.join()
1042
Bill Janssen54cc54c2007-12-14 22:08:56 +00001043 def testSocketServer(self):
Bill Janssen6e027db2007-11-15 22:23:56 +00001044
Trent Nelson78520002008-04-10 20:54:35 +00001045 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001046 flag = threading.Event()
1047 server.start(flag)
1048 # wait for it to start
1049 flag.wait()
1050 # try to connect
1051 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001052 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001053 sys.stdout.write('\n')
1054 d1 = open(CERTFILE, 'rb').read()
1055 d2 = ''
1056 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001057 url = 'https://%s:%d/%s' % (
1058 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001059 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001060 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001061 if dlen and (int(dlen) > 0):
1062 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001063 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001064 sys.stdout.write(
1065 " client: read %d bytes from remote server '%s'\n"
1066 % (len(d2), server))
1067 f.close()
1068 except:
1069 msg = ''.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001070 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001071 sys.stdout.write('\n' + msg)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001072 raise support.TestFailed(msg)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001073 else:
1074 if not (d1 == d2):
Bill Janssen6e027db2007-11-15 22:23:56 +00001075 print("d1 is", len(d1), repr(d1))
1076 print("d2 is", len(d2), repr(d2))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001077 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001078 "Couldn't fetch data from HTTPS server")
1079 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001080 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001081 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001082 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001083 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001084 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001085 server.join()
1086
Trent Nelson6b240cd2008-04-10 20:12:06 +00001087 def testAsyncoreServer(self):
1088
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001089 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001090 sys.stdout.write("\n")
1091
1092 indata="FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001093 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001094 flag = threading.Event()
1095 server.start(flag)
1096 # wait for it to start
1097 flag.wait()
1098 # try to connect
1099 try:
1100 s = ssl.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001101 s.connect((HOST, server.port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001102 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001103 raise support.TestFailed("Unexpected SSL error: " + str(x))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001104 except Exception as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001105 raise support.TestFailed("Unexpected exception: " + str(x))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001106 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001107 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001108 sys.stdout.write(
1109 " client: sending %s...\n" % (repr(indata)))
1110 s.sendall(indata.encode('ASCII', 'strict'))
1111 outdata = s.recv()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001112 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001113 sys.stdout.write(" client: read %s\n" % repr(outdata))
1114 outdata = str(outdata, 'ASCII', 'strict')
1115 if outdata != indata.lower():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001116 raise support.TestFailed(
Trent Nelson6b240cd2008-04-10 20:12:06 +00001117 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1118 % (repr(outdata[:min(len(outdata),20)]), len(outdata),
1119 repr(indata[:min(len(indata),20)].lower()), len(indata)))
1120 s.write("over\n".encode("ASCII", "strict"))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001121 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001122 sys.stdout.write(" client: closing connection.\n")
1123 s.close()
1124 finally:
1125 server.stop()
1126 server.join()
1127
Bill Janssen58afe4c2008-09-08 16:45:19 +00001128 def testAllRecvAndSendMethods(self):
1129
1130 if support.verbose:
1131 sys.stdout.write("\n")
1132
1133 server = ThreadedEchoServer(CERTFILE,
1134 certreqs=ssl.CERT_NONE,
1135 ssl_version=ssl.PROTOCOL_TLSv1,
1136 cacerts=CERTFILE,
1137 chatty=True,
1138 connectionchatty=False)
1139 flag = threading.Event()
1140 server.start(flag)
1141 # wait for it to start
1142 flag.wait()
1143 # try to connect
1144 try:
1145 s = ssl.wrap_socket(socket.socket(),
1146 server_side=False,
1147 certfile=CERTFILE,
1148 ca_certs=CERTFILE,
1149 cert_reqs=ssl.CERT_NONE,
1150 ssl_version=ssl.PROTOCOL_TLSv1)
1151 s.connect((HOST, server.port))
1152 except ssl.SSLError as x:
1153 raise support.TestFailed("Unexpected SSL error: " + str(x))
1154 except Exception as x:
1155 raise support.TestFailed("Unexpected exception: " + str(x))
1156 else:
1157 # helper methods for standardising recv* method signatures
1158 def _recv_into():
1159 b = bytearray(b"\0"*100)
1160 count = s.recv_into(b)
1161 return b[:count]
1162
1163 def _recvfrom_into():
1164 b = bytearray(b"\0"*100)
1165 count, addr = s.recvfrom_into(b)
1166 return b[:count]
1167
1168 # (name, method, whether to expect success, *args)
1169 send_methods = [
1170 ('send', s.send, True, []),
1171 ('sendto', s.sendto, False, ["some.address"]),
1172 ('sendall', s.sendall, True, []),
1173 ]
1174 recv_methods = [
1175 ('recv', s.recv, True, []),
1176 ('recvfrom', s.recvfrom, False, ["some.address"]),
1177 ('recv_into', _recv_into, True, []),
1178 ('recvfrom_into', _recvfrom_into, False, []),
1179 ]
1180 data_prefix = "PREFIX_"
1181
1182 for meth_name, send_meth, expect_success, args in send_methods:
1183 indata = data_prefix + meth_name
1184 try:
1185 send_meth(indata.encode('ASCII', 'strict'), *args)
1186 outdata = s.read()
1187 outdata = str(outdata, 'ASCII', 'strict')
1188 if outdata != indata.lower():
1189 raise support.TestFailed(
1190 "While sending with <<{name:s}>> bad data "
1191 "<<{outdata:s}>> ({nout:d}) received; "
1192 "expected <<{indata:s}>> ({nin:d})\n".format(
1193 name=meth_name, outdata=repr(outdata[:20]),
1194 nout=len(outdata),
1195 indata=repr(indata[:20]), nin=len(indata)
1196 )
1197 )
1198 except ValueError as e:
1199 if expect_success:
1200 raise support.TestFailed(
1201 "Failed to send with method <<{name:s}>>; "
1202 "expected to succeed.\n".format(name=meth_name)
1203 )
1204 if not str(e).startswith(meth_name):
1205 raise support.TestFailed(
1206 "Method <<{name:s}>> failed with unexpected "
1207 "exception message: {exp:s}\n".format(
1208 name=meth_name, exp=e
1209 )
1210 )
1211
1212 for meth_name, recv_meth, expect_success, args in recv_methods:
1213 indata = data_prefix + meth_name
1214 try:
1215 s.send(indata.encode('ASCII', 'strict'))
1216 outdata = recv_meth(*args)
1217 outdata = str(outdata, 'ASCII', 'strict')
1218 if outdata != indata.lower():
1219 raise support.TestFailed(
1220 "While receiving with <<{name:s}>> bad data "
1221 "<<{outdata:s}>> ({nout:d}) received; "
1222 "expected <<{indata:s}>> ({nin:d})\n".format(
1223 name=meth_name, outdata=repr(outdata[:20]),
1224 nout=len(outdata),
1225 indata=repr(indata[:20]), nin=len(indata)
1226 )
1227 )
1228 except ValueError as e:
1229 if expect_success:
1230 raise support.TestFailed(
1231 "Failed to receive with method <<{name:s}>>; "
1232 "expected to succeed.\n".format(name=meth_name)
1233 )
1234 if not str(e).startswith(meth_name):
1235 raise support.TestFailed(
1236 "Method <<{name:s}>> failed with unexpected "
1237 "exception message: {exp:s}\n".format(
1238 name=meth_name, exp=e
1239 )
1240 )
1241 # consume data
1242 s.read()
1243
1244 s.write("over\n".encode("ASCII", "strict"))
1245 s.close()
1246 finally:
1247 server.stop()
1248 server.join()
1249
Antoine Pitrouec146182010-04-24 21:30:20 +00001250 def test_handshake_timeout(self):
1251 # Issue #5103: SSL handshake must respect the socket timeout
1252 server = socket.socket(socket.AF_INET)
1253 host = "127.0.0.1"
1254 port = support.bind_port(server)
1255 started = threading.Event()
1256 finish = False
1257
1258 def serve():
1259 server.listen(5)
1260 started.set()
1261 conns = []
1262 while not finish:
1263 r, w, e = select.select([server], [], [], 0.1)
1264 if server in r:
1265 # Let the socket hang around rather than having
1266 # it closed by garbage collection.
1267 conns.append(server.accept()[0])
1268
1269 t = threading.Thread(target=serve)
1270 t.start()
1271 started.wait()
1272
1273 try:
Antoine Pitrouc2203f92010-04-24 22:07:51 +00001274 try:
1275 c = socket.socket(socket.AF_INET)
1276 c.settimeout(0.2)
1277 c.connect((host, port))
1278 # Will attempt handshake and time out
1279 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1280 ssl.wrap_socket, c)
1281 finally:
1282 c.close()
Antoine Pitrouec146182010-04-24 21:30:20 +00001283 try:
1284 c = socket.socket(socket.AF_INET)
1285 c = ssl.wrap_socket(c)
1286 c.settimeout(0.2)
1287 # Will attempt handshake and time out
1288 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1289 c.connect, (host, port))
1290 finally:
1291 c.close()
1292 finally:
1293 finish = True
1294 t.join()
1295 server.close()
1296
Bill Janssen58afe4c2008-09-08 16:45:19 +00001297
Thomas Woutersed03b412007-08-28 21:37:11 +00001298def test_main(verbose=False):
1299 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001300 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001301
Trent Nelson78520002008-04-10 20:54:35 +00001302 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Thomas Woutersed03b412007-08-28 21:37:11 +00001303 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
1304 "keycert.pem")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001305 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1306 os.path.dirname(__file__) or os.curdir,
1307 "https_svn_python_org_root.pem")
1308
1309 if (not os.path.exists(CERTFILE) or
1310 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001311 raise support.TestFailed("Can't read certificate files!")
Bill Janssen6e027db2007-11-15 22:23:56 +00001312
Thomas Woutersed03b412007-08-28 21:37:11 +00001313 tests = [BasicTests]
1314
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001315 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001316 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001317
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001318 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001319 thread_info = support.threading_setup()
1320 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001321 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001322
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001323 support.run_unittest(*tests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001324
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001325 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001326 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001327
1328if __name__ == "__main__":
1329 test_main()