blob: 79dad649ce668358a970e93430940c63d77285b7 [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 errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000010import subprocess
11import time
12import os
13import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000014import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import shutil
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000016import traceback
17
Bill Janssen296a59d2007-09-16 22:06:00 +000018from BaseHTTPServer import HTTPServer
19from SimpleHTTPServer import SimpleHTTPRequestHandler
20
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000021# Optionally test SSL support, if we have it in the tested platform
22skip_expected = False
23try:
24 import ssl
25except ImportError:
26 skip_expected = True
27
Trent Nelsone41b0062008-04-08 23:47:30 +000028HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000029CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000030SVN_PYTHON_ORG_ROOT_CERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000031
Neal Norwitz3e533c22007-08-27 01:03:18 +000032def handle_error(prefix):
33 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000034 if test_support.verbose:
35 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000036
37
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000038class BasicTests(unittest.TestCase):
39
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000040 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000041 if not test_support.is_resource_enabled('network'):
42 return
Bill Janssen296a59d2007-09-16 22:06:00 +000043 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
44 cert_reqs=ssl.CERT_NONE)
45 s.connect(("svn.python.org", 443))
46 c = s.getpeercert()
47 if c:
48 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
49 s.close()
50
51 # this should fail because we have no verification certs
52 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
53 cert_reqs=ssl.CERT_REQUIRED)
54 try:
55 s.connect(("svn.python.org", 443))
56 except ssl.SSLError:
57 pass
58 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000059 s.close()
60
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000061
Bill Janssen98d19da2007-09-10 21:51:02 +000062 def testCrucialConstants(self):
63 ssl.PROTOCOL_SSLv2
64 ssl.PROTOCOL_SSLv23
65 ssl.PROTOCOL_SSLv3
66 ssl.PROTOCOL_TLSv1
67 ssl.CERT_NONE
68 ssl.CERT_OPTIONAL
69 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000070
Bill Janssen98d19da2007-09-10 21:51:02 +000071 def testRAND(self):
72 v = ssl.RAND_status()
73 if test_support.verbose:
74 sys.stdout.write("\n RAND_status is %d (%s)\n"
75 % (v, (v and "sufficient randomness") or
76 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000077 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000078 ssl.RAND_egd(1)
79 except TypeError:
80 pass
Guido van Rossume4729332007-08-26 19:35:09 +000081 else:
Bill Janssen98d19da2007-09-10 21:51:02 +000082 print "didn't raise TypeError"
83 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000084
Bill Janssen98d19da2007-09-10 21:51:02 +000085 def testParseCert(self):
86 # note that this uses an 'unofficial' function in _ssl.c,
87 # provided solely for this test, to exercise the certificate
88 # parsing code
89 p = ssl._ssl._test_decode_cert(CERTFILE, False)
90 if test_support.verbose:
91 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000092
Bill Janssen296a59d2007-09-16 22:06:00 +000093 def testDERtoPEM(self):
94
95 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
96 d1 = ssl.PEM_cert_to_DER_cert(pem)
97 p2 = ssl.DER_cert_to_PEM_cert(d1)
98 d2 = ssl.PEM_cert_to_DER_cert(p2)
99 if (d1 != d2):
100 raise test_support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
101
Bill Janssen934b16d2008-06-28 22:19:33 +0000102class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000103
104 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000105 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
106 cert_reqs=ssl.CERT_NONE)
107 s.connect(("svn.python.org", 443))
108 c = s.getpeercert()
109 if c:
110 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
111 s.close()
112
113 # this should fail because we have no verification certs
114 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
115 cert_reqs=ssl.CERT_REQUIRED)
116 try:
117 s.connect(("svn.python.org", 443))
118 except ssl.SSLError:
119 pass
120 finally:
121 s.close()
122
123 # this should succeed because we specify the root cert
124 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
125 cert_reqs=ssl.CERT_REQUIRED,
126 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
127 try:
128 s.connect(("svn.python.org", 443))
129 except ssl.SSLError, x:
130 raise test_support.TestFailed("Unexpected exception %s" % x)
131 finally:
132 s.close()
133
Bill Janssen934b16d2008-06-28 22:19:33 +0000134
135 def testNonBlockingHandshake(self):
136 s = socket.socket(socket.AF_INET)
137 s.connect(("svn.python.org", 443))
138 s.setblocking(False)
139 s = ssl.wrap_socket(s,
140 cert_reqs=ssl.CERT_NONE,
141 do_handshake_on_connect=False)
142 count = 0
143 while True:
144 try:
145 count += 1
146 s.do_handshake()
147 break
148 except ssl.SSLError, err:
149 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
150 select.select([s], [], [])
151 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
152 select.select([], [s], [])
153 else:
154 raise
155 s.close()
156 if test_support.verbose:
157 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
158
Bill Janssen296a59d2007-09-16 22:06:00 +0000159 def testFetchServerCert(self):
160
161 pem = ssl.get_server_certificate(("svn.python.org", 443))
162 if not pem:
163 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
164
165 try:
166 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
167 except ssl.SSLError:
168 #should fail
169 pass
170 else:
171 raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
172
173 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
174 if not pem:
175 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
176 if test_support.verbose:
177 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
178
179
Bill Janssen98d19da2007-09-10 21:51:02 +0000180try:
181 import threading
182except ImportError:
183 _have_threads = False
184else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000185
Bill Janssen98d19da2007-09-10 21:51:02 +0000186 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000187
Bill Janssen98d19da2007-09-10 21:51:02 +0000188 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000189
Bill Janssen98d19da2007-09-10 21:51:02 +0000190 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000191
Bill Janssen98d19da2007-09-10 21:51:02 +0000192 """A mildly complicated class, because we want it to work both
193 with and without the SSL wrapper around the socket connection, so
194 that we can test the STARTTLS functionality."""
195
196 def __init__(self, server, connsock):
197 self.server = server
198 self.running = False
199 self.sock = connsock
200 self.sock.setblocking(1)
201 self.sslconn = None
202 threading.Thread.__init__(self)
203 self.setDaemon(True)
204
Bill Janssen934b16d2008-06-28 22:19:33 +0000205 def show_conn_details(self):
206 if self.server.certreqs == ssl.CERT_REQUIRED:
207 cert = self.sslconn.getpeercert()
208 if test_support.verbose and self.server.chatty:
209 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
210 cert_binary = self.sslconn.getpeercert(True)
211 if test_support.verbose and self.server.chatty:
212 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
213 cipher = self.sslconn.cipher()
214 if test_support.verbose and self.server.chatty:
215 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
216
Bill Janssen98d19da2007-09-10 21:51:02 +0000217 def wrap_conn (self):
218 try:
219 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
220 certfile=self.server.certificate,
221 ssl_version=self.server.protocol,
222 ca_certs=self.server.cacerts,
223 cert_reqs=self.server.certreqs)
224 except:
225 if self.server.chatty:
226 handle_error("\n server: bad connection attempt from " +
227 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000228 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000229 if not self.server.expect_bad_connects:
230 # here, we want to stop the server, because this shouldn't
231 # happen in the context of our test case
232 self.running = False
233 # normally, we'd just stop here, but for the test
234 # harness, we want to stop the server
235 self.server.stop()
236 return False
237
238 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000239 return True
240
241 def read(self):
242 if self.sslconn:
243 return self.sslconn.read()
244 else:
245 return self.sock.recv(1024)
246
247 def write(self, bytes):
248 if self.sslconn:
249 return self.sslconn.write(bytes)
250 else:
251 return self.sock.send(bytes)
252
253 def close(self):
254 if self.sslconn:
255 self.sslconn.close()
256 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000257 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000258
259 def run (self):
260 self.running = True
261 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000262 if isinstance(self.sock, ssl.SSLSocket):
263 self.sslconn = self.sock
264 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000265 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000266 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000267 while self.running:
268 try:
269 msg = self.read()
270 if not msg:
271 # eof, so quit this handler
272 self.running = False
273 self.close()
274 elif msg.strip() == 'over':
275 if test_support.verbose and self.server.connectionchatty:
276 sys.stdout.write(" server: client closed connection\n")
277 self.close()
278 return
279 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
280 if test_support.verbose and self.server.connectionchatty:
281 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
282 self.write("OK\n")
283 if not self.wrap_conn():
284 return
285 else:
286 if (test_support.verbose and
287 self.server.connectionchatty):
288 ctype = (self.sslconn and "encrypted") or "unencrypted"
289 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
290 % (repr(msg), ctype, repr(msg.lower()), ctype))
291 self.write(msg.lower())
292 except ssl.SSLError:
293 if self.server.chatty:
294 handle_error("Test server failure:\n")
295 self.close()
296 self.running = False
297 # normally, we'd just stop here, but for the test
298 # harness, we want to stop the server
299 self.server.stop()
300 except:
301 handle_error('')
302
Trent Nelsone41b0062008-04-08 23:47:30 +0000303 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000304 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000305 chatty=True, connectionchatty=False, starttls_server=False,
306 wrap_accepting_socket=False):
307
Bill Janssen98d19da2007-09-10 21:51:02 +0000308 if ssl_version is None:
309 ssl_version = ssl.PROTOCOL_TLSv1
310 if certreqs is None:
311 certreqs = ssl.CERT_NONE
312 self.certificate = certificate
313 self.protocol = ssl_version
314 self.certreqs = certreqs
315 self.cacerts = cacerts
316 self.expect_bad_connects = expect_bad_connects
317 self.chatty = chatty
318 self.connectionchatty = connectionchatty
319 self.starttls_server = starttls_server
320 self.sock = socket.socket()
321 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000322 if wrap_accepting_socket:
323 self.sock = ssl.wrap_socket(self.sock, server_side=True,
324 certfile=self.certificate,
325 cert_reqs = self.certreqs,
326 ca_certs = self.cacerts,
327 ssl_version = self.protocol)
328 if test_support.verbose and self.chatty:
329 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
330 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000331 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000332 threading.Thread.__init__(self)
Bill Janssen98d19da2007-09-10 21:51:02 +0000333 self.setDaemon(False)
334
335 def start (self, flag=None):
336 self.flag = flag
337 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000338
339 def run (self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000340 self.sock.settimeout(0.5)
341 self.sock.listen(5)
342 self.active = True
343 if self.flag:
344 # signal an event
345 self.flag.set()
346 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000347 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000348 newconn, connaddr = self.sock.accept()
349 if test_support.verbose and self.chatty:
350 sys.stdout.write(' server: new connection from '
351 + str(connaddr) + '\n')
352 handler = self.ConnectionHandler(self, newconn)
353 handler.start()
354 except socket.timeout:
355 pass
356 except KeyboardInterrupt:
357 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000358 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000359 if self.chatty:
360 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000361 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000362
Bill Janssen98d19da2007-09-10 21:51:02 +0000363 def stop (self):
364 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000365
Bill Janssen934b16d2008-06-28 22:19:33 +0000366 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000367
Bill Janssen934b16d2008-06-28 22:19:33 +0000368 class EchoServer (asyncore.dispatcher):
369
370 class ConnectionHandler (asyncore.dispatcher_with_send):
371
372 def __init__(self, conn, certfile):
373 asyncore.dispatcher_with_send.__init__(self, conn)
374 self.socket = ssl.wrap_socket(conn, server_side=True,
375 certfile=certfile,
376 do_handshake_on_connect=True)
377
378 def readable(self):
379 if isinstance(self.socket, ssl.SSLSocket):
380 while self.socket.pending() > 0:
381 self.handle_read_event()
382 return True
383
384 def handle_read(self):
385 data = self.recv(1024)
386 self.send(data.lower())
387
388 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000389 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000390 if test_support.verbose:
391 sys.stdout.write(" server: closed connection %s\n" % self.socket)
392
393 def handle_error(self):
394 raise
395
396 def __init__(self, certfile):
397 self.certfile = certfile
398 asyncore.dispatcher.__init__(self)
399 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
400 self.port = test_support.bind_port(self.socket)
401 self.listen(5)
402
403 def handle_accept(self):
404 sock_obj, addr = self.accept()
405 if test_support.verbose:
406 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
407 self.ConnectionHandler(sock_obj, self.certfile)
408
409 def handle_error(self):
410 raise
411
412 def __init__(self, certfile):
413 self.flag = None
414 self.active = False
415 self.server = self.EchoServer(certfile)
416 self.port = self.server.port
417 threading.Thread.__init__(self)
418 self.setDaemon(True)
419
420 def __str__(self):
421 return "<%s %s>" % (self.__class__.__name__, self.server)
422
423 def start (self, flag=None):
424 self.flag = flag
425 threading.Thread.start(self)
426
427 def run (self):
428 self.active = True
429 if self.flag:
430 self.flag.set()
431 while self.active:
432 try:
433 asyncore.loop(1)
434 except:
435 pass
436
437 def stop (self):
438 self.active = False
439 self.server.close()
440
441 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000442
443 class HTTPSServer(HTTPServer):
444
445 def __init__(self, server_address, RequestHandlerClass, certfile):
446
447 HTTPServer.__init__(self, server_address, RequestHandlerClass)
448 # we assume the certfile contains both private key and certificate
449 self.certfile = certfile
450 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000451 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000452 self.allow_reuse_address = True
453
Bill Janssen934b16d2008-06-28 22:19:33 +0000454 def __str__(self):
455 return ('<%s %s:%s>' %
456 (self.__class__.__name__,
457 self.server_name,
458 self.server_port))
459
Bill Janssen296a59d2007-09-16 22:06:00 +0000460 def get_request (self):
461 # override this to wrap socket with SSL
462 sock, addr = self.socket.accept()
463 sslconn = ssl.wrap_socket(sock, server_side=True,
464 certfile=self.certfile)
465 return sslconn, addr
466
467 # The methods overridden below this are mainly so that we
468 # can run it in a thread and be able to stop it from another
469 # You probably wouldn't need them in other uses.
470
471 def server_activate(self):
472 # We want to run this in a thread for testing purposes,
473 # so we override this to set timeout, so that we get
474 # a chance to stop the server
475 self.socket.settimeout(0.5)
476 HTTPServer.server_activate(self)
477
478 def serve_forever(self):
479 # We want this to run in a thread, so we use a slightly
480 # modified version of "forever".
481 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000482 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000483 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000484 # We need to lock while handling the request.
485 # Another thread can close the socket after self.active
486 # has been checked and before the request is handled.
487 # This causes an exception when using the closed socket.
488 with self.active_lock:
489 if not self.active:
490 break
491 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000492 except socket.timeout:
493 pass
494 except KeyboardInterrupt:
495 self.server_close()
496 return
497 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000498 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
499 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000500 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000501
502 def server_close(self):
503 # Again, we want this to run in a thread, so we need to override
504 # close to clear the "active" flag, so that serve_forever() will
505 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000506 with self.active_lock:
507 HTTPServer.server_close(self)
508 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000509
510 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
511
512 # need to override translate_path to get a known root,
513 # instead of using os.curdir, since the test could be
514 # run from anywhere
515
516 server_version = "TestHTTPS/1.0"
517
518 root = None
519
520 def translate_path(self, path):
521 """Translate a /-separated PATH to the local filename syntax.
522
523 Components that mean special things to the local file system
524 (e.g. drive or directory names) are ignored. (XXX They should
525 probably be diagnosed.)
526
527 """
528 # abandon query parameters
529 path = urlparse.urlparse(path)[2]
530 path = os.path.normpath(urllib.unquote(path))
531 words = path.split('/')
532 words = filter(None, words)
533 path = self.root
534 for word in words:
535 drive, word = os.path.splitdrive(word)
536 head, word = os.path.split(word)
537 if word in self.root: continue
538 path = os.path.join(path, word)
539 return path
540
541 def log_message(self, format, *args):
542
543 # we override this to suppress logging unless "verbose"
544
545 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000546 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
547 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000548 self.server.server_port,
549 self.request.cipher(),
550 self.log_date_time_string(),
551 format%args))
552
553
Trent Nelsone41b0062008-04-08 23:47:30 +0000554 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000555 self.flag = None
556 self.active = False
557 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Trent Nelsone41b0062008-04-08 23:47:30 +0000558 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000559 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000560 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Bill Janssen296a59d2007-09-16 22:06:00 +0000561 threading.Thread.__init__(self)
562 self.setDaemon(True)
563
564 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000565 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000566
567 def start (self, flag=None):
568 self.flag = flag
569 threading.Thread.start(self)
570
571 def run (self):
572 self.active = True
573 if self.flag:
574 self.flag.set()
575 self.server.serve_forever()
576 self.active = False
577
578 def stop (self):
579 self.active = False
580 self.server.server_close()
581
582
Bill Janssen98d19da2007-09-10 21:51:02 +0000583 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000584 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000585 certreqs=ssl.CERT_REQUIRED,
586 cacerts=CERTFILE, chatty=False)
587 flag = threading.Event()
588 server.start(flag)
589 # wait for it to start
590 flag.wait()
591 # try to connect
592 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000593 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000594 s = ssl.wrap_socket(socket.socket(),
595 certfile=certfile,
596 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000597 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000598 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000599 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000600 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000601 except socket.error, x:
602 if test_support.verbose:
603 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000604 else:
605 raise test_support.TestFailed(
606 "Use of invalid cert should have failed!")
607 finally:
608 server.stop()
609 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000610
Bill Janssen98d19da2007-09-10 21:51:02 +0000611 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
612 client_certfile, client_protocol=None, indata="FOO\n",
Bill Janssen934b16d2008-06-28 22:19:33 +0000613 chatty=True, connectionchatty=False,
614 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000615
Trent Nelsone41b0062008-04-08 23:47:30 +0000616 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000617 certreqs=certreqs,
618 ssl_version=protocol,
619 cacerts=cacertsfile,
620 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000621 connectionchatty=connectionchatty,
622 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000623 flag = threading.Event()
624 server.start(flag)
625 # wait for it to start
626 flag.wait()
627 # try to connect
628 if client_protocol is None:
629 client_protocol = protocol
630 try:
631 try:
632 s = ssl.wrap_socket(socket.socket(),
633 certfile=client_certfile,
634 ca_certs=cacertsfile,
635 cert_reqs=certreqs,
636 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000637 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000638 except ssl.SSLError, x:
639 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
640 except Exception, x:
641 raise test_support.TestFailed("Unexpected exception: " + str(x))
642 else:
643 if connectionchatty:
644 if test_support.verbose:
645 sys.stdout.write(
646 " client: sending %s...\n" % (repr(indata)))
647 s.write(indata)
648 outdata = s.read()
649 if connectionchatty:
650 if test_support.verbose:
651 sys.stdout.write(" client: read %s\n" % repr(outdata))
652 if outdata != indata.lower():
653 raise test_support.TestFailed(
654 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
655 % (outdata[:min(len(outdata),20)], len(outdata),
656 indata[:min(len(indata),20)].lower(), len(indata)))
657 s.write("over\n")
658 if connectionchatty:
659 if test_support.verbose:
660 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000661 s.close()
662 finally:
663 server.stop()
664 server.join()
665
666 def tryProtocolCombo (server_protocol,
667 client_protocol,
668 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000669 certsreqs=None):
670
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000671 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000672 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000673
674 if certsreqs == ssl.CERT_NONE:
675 certtype = "CERT_NONE"
676 elif certsreqs == ssl.CERT_OPTIONAL:
677 certtype = "CERT_OPTIONAL"
678 elif certsreqs == ssl.CERT_REQUIRED:
679 certtype = "CERT_REQUIRED"
680 if test_support.verbose:
681 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
682 sys.stdout.write(formatstr %
683 (ssl.get_protocol_name(client_protocol),
684 ssl.get_protocol_name(server_protocol),
685 certtype))
686 try:
687 serverParamsTest(CERTFILE, server_protocol, certsreqs,
688 CERTFILE, CERTFILE, client_protocol, chatty=False)
689 except test_support.TestFailed:
690 if expectedToWork:
691 raise
692 else:
693 if not expectedToWork:
694 raise test_support.TestFailed(
695 "Client protocol %s succeeded with server protocol %s!"
696 % (ssl.get_protocol_name(client_protocol),
697 ssl.get_protocol_name(server_protocol)))
698
699
Bill Janssen934b16d2008-06-28 22:19:33 +0000700 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000701
702 def testRudeShutdown(self):
703
704 listener_ready = threading.Event()
705 listener_gone = threading.Event()
Trent Nelsone41b0062008-04-08 23:47:30 +0000706 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000707
708 # `listener` runs in a thread. It opens a socket listening on
709 # PORT, and sits in an accept() until the main thread connects.
710 # Then it rudely closes the socket, and sets Event `listener_gone`
711 # to let the main thread know the socket is gone.
712 def listener():
713 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000714 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000715 s.listen(5)
716 listener_ready.set()
717 s.accept()
718 s = None # reclaim the socket object, which also closes it
719 listener_gone.set()
720
721 def connector():
722 listener_ready.wait()
723 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000724 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000725 listener_gone.wait()
726 try:
727 ssl_sock = ssl.wrap_socket(s)
Bill Janssen934b16d2008-06-28 22:19:33 +0000728 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000729 pass
730 else:
731 raise test_support.TestFailed(
732 'connecting to closed SSL socket should have failed')
733
734 t = threading.Thread(target=listener)
735 t.start()
736 connector()
737 t.join()
738
739 def testEcho (self):
740
741 if test_support.verbose:
742 sys.stdout.write("\n")
743 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
744 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
745 chatty=True, connectionchatty=True)
746
747 def testReadCert(self):
748
749 if test_support.verbose:
750 sys.stdout.write("\n")
751 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000752 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000753 certreqs=ssl.CERT_NONE,
754 ssl_version=ssl.PROTOCOL_SSLv23,
755 cacerts=CERTFILE,
756 chatty=False)
757 flag = threading.Event()
758 server.start(flag)
759 # wait for it to start
760 flag.wait()
761 # try to connect
762 try:
763 try:
764 s = ssl.wrap_socket(socket.socket(),
765 certfile=CERTFILE,
766 ca_certs=CERTFILE,
767 cert_reqs=ssl.CERT_REQUIRED,
768 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000769 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000770 except ssl.SSLError, x:
771 raise test_support.TestFailed(
772 "Unexpected SSL error: " + str(x))
773 except Exception, x:
774 raise test_support.TestFailed(
775 "Unexpected exception: " + str(x))
776 else:
777 if not s:
778 raise test_support.TestFailed(
779 "Can't SSL-handshake with test server")
780 cert = s.getpeercert()
781 if not cert:
782 raise test_support.TestFailed(
783 "Can't get peer certificate.")
784 cipher = s.cipher()
785 if test_support.verbose:
786 sys.stdout.write(pprint.pformat(cert) + '\n')
787 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
788 if not cert.has_key('subject'):
789 raise test_support.TestFailed(
790 "No subject field in certificate: %s." %
791 pprint.pformat(cert))
792 if ((('organizationName', 'Python Software Foundation'),)
793 not in cert['subject']):
794 raise test_support.TestFailed(
795 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000796 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000797 s.close()
798 finally:
799 server.stop()
800 server.join()
801
802 def testNULLcert(self):
803 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
804 "nullcert.pem"))
805 def testMalformedCert(self):
806 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
807 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000808 def testWrongCert(self):
809 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
810 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000811 def testMalformedKey(self):
812 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
813 "badkey.pem"))
814
815 def testProtocolSSL2(self):
816 if test_support.verbose:
817 sys.stdout.write("\n")
818 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
819 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
820 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
821 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
822 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
823 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
824
825 def testProtocolSSL23(self):
826 if test_support.verbose:
827 sys.stdout.write("\n")
828 try:
829 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
830 except test_support.TestFailed, x:
831 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
832 if test_support.verbose:
833 sys.stdout.write(
834 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
835 % str(x))
836 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
837 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
838 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
839
840 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
841 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
842 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
843
844 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
845 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
846 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
847
848 def testProtocolSSL3(self):
849 if test_support.verbose:
850 sys.stdout.write("\n")
851 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
852 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
853 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
854 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
855 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
856 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
857
858 def testProtocolTLS1(self):
859 if test_support.verbose:
860 sys.stdout.write("\n")
861 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
862 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
863 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
864 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
865 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
866 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
867
868 def testSTARTTLS (self):
869
870 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4")
871
Trent Nelsone41b0062008-04-08 23:47:30 +0000872 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000873 ssl_version=ssl.PROTOCOL_TLSv1,
874 starttls_server=True,
875 chatty=True,
876 connectionchatty=True)
877 flag = threading.Event()
878 server.start(flag)
879 # wait for it to start
880 flag.wait()
881 # try to connect
882 wrapped = False
883 try:
884 try:
885 s = socket.socket()
886 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000887 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000888 except Exception, x:
889 raise test_support.TestFailed("Unexpected exception: " + str(x))
890 else:
891 if test_support.verbose:
892 sys.stdout.write("\n")
893 for indata in msgs:
894 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000895 sys.stdout.write(
896 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000897 if wrapped:
898 conn.write(indata)
899 outdata = conn.read()
900 else:
901 s.send(indata)
902 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +0000903 if (indata == "STARTTLS" and
904 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000905 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000906 sys.stdout.write(
907 " client: read %s from server, starting TLS...\n"
908 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000909 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
910
911 wrapped = True
912 else:
913 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000914 sys.stdout.write(
915 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000916 if test_support.verbose:
917 sys.stdout.write(" client: closing connection.\n")
918 if wrapped:
919 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000920 else:
921 s.send("over\n")
922 s.close()
923 finally:
924 server.stop()
925 server.join()
926
Bill Janssen934b16d2008-06-28 22:19:33 +0000927 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000928
Bill Janssen934b16d2008-06-28 22:19:33 +0000929 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000930 flag = threading.Event()
931 server.start(flag)
932 # wait for it to start
933 flag.wait()
934 # try to connect
935 try:
936 if test_support.verbose:
937 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +0000938 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000939 d2 = ''
940 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +0000941 url = 'https://127.0.0.1:%d/%s' % (
942 server.port, os.path.split(CERTFILE)[1])
Bill Janssen296a59d2007-09-16 22:06:00 +0000943 f = urllib.urlopen(url)
944 dlen = f.info().getheader("content-length")
945 if dlen and (int(dlen) > 0):
946 d2 = f.read(int(dlen))
947 if test_support.verbose:
948 sys.stdout.write(
949 " client: read %d bytes from remote server '%s'\n"
950 % (len(d2), server))
951 f.close()
952 except:
953 msg = ''.join(traceback.format_exception(*sys.exc_info()))
954 if test_support.verbose:
955 sys.stdout.write('\n' + msg)
956 raise test_support.TestFailed(msg)
957 else:
958 if not (d1 == d2):
959 raise test_support.TestFailed(
960 "Couldn't fetch data from HTTPS server")
961 finally:
962 server.stop()
963 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +0000964
Bill Janssen934b16d2008-06-28 22:19:33 +0000965 def testWrappedAccept (self):
966
967 if test_support.verbose:
968 sys.stdout.write("\n")
969 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
970 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
971 chatty=True, connectionchatty=True,
972 wrap_accepting_socket=True)
973
974
975 def testAsyncoreServer (self):
976
977 indata = "TEST MESSAGE of mixed case\n"
978
979 if test_support.verbose:
980 sys.stdout.write("\n")
981 server = AsyncoreEchoServer(CERTFILE)
982 flag = threading.Event()
983 server.start(flag)
984 # wait for it to start
985 flag.wait()
986 # try to connect
987 try:
988 try:
989 s = ssl.wrap_socket(socket.socket())
990 s.connect(('127.0.0.1', server.port))
991 except ssl.SSLError, x:
992 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
993 except Exception, x:
994 raise test_support.TestFailed("Unexpected exception: " + str(x))
995 else:
996 if test_support.verbose:
997 sys.stdout.write(
998 " client: sending %s...\n" % (repr(indata)))
999 s.write(indata)
1000 outdata = s.read()
1001 if test_support.verbose:
1002 sys.stdout.write(" client: read %s\n" % repr(outdata))
1003 if outdata != indata.lower():
1004 raise test_support.TestFailed(
1005 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1006 % (outdata[:min(len(outdata),20)], len(outdata),
1007 indata[:min(len(indata),20)].lower(), len(indata)))
1008 s.write("over\n")
1009 if test_support.verbose:
1010 sys.stdout.write(" client: closing connection.\n")
1011 s.close()
1012 finally:
1013 server.stop()
1014 # wait for server thread to end
1015 server.join()
1016
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001017
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001018def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001019 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001020 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001021
Trent Nelsone41b0062008-04-08 23:47:30 +00001022 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001023 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001024 "keycert.pem")
1025 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1026 os.path.dirname(__file__) or os.curdir,
1027 "https_svn_python_org_root.pem")
1028
1029 if (not os.path.exists(CERTFILE) or
1030 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001031 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001032
Bill Janssen934b16d2008-06-28 22:19:33 +00001033 TESTPORT = test_support.find_unused_port()
1034 if not TESTPORT:
1035 raise test_support.TestFailed("Can't find open port to test servers on!")
1036
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001037 tests = [BasicTests]
1038
Bill Janssen296a59d2007-09-16 22:06:00 +00001039 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001040 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001041
Bill Janssen98d19da2007-09-10 21:51:02 +00001042 if _have_threads:
1043 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001044 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001045 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001046
Bill Janssen98d19da2007-09-10 21:51:02 +00001047 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001048
Bill Janssen98d19da2007-09-10 21:51:02 +00001049 if _have_threads:
1050 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001051
1052if __name__ == "__main__":
1053 test_main()