blob: 53b71b9630b5e475ccc4361e88d7e43c4c388cd1 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import time
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +00009import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000010import os
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +000011import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000012import pprint
Jeremy Hylton1afc1692008-06-18 20:49:58 +000013import urllib.parse, urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000014import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000015import asyncore
Antoine Pitrou9d543662010-04-23 23:10:32 +000016import weakref
Thomas Woutersed03b412007-08-28 21:37:11 +000017
Georg Brandl24420152008-05-26 16:32:26 +000018from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000019
Thomas Woutersed03b412007-08-28 21:37:11 +000020# Optionally test SSL support, if we have it in the tested platform
21skip_expected = False
22try:
23 import ssl
24except ImportError:
25 skip_expected = True
26
Benjamin Petersonee8712c2008-05-20 21:35:26 +000027HOST = support.HOST
Thomas Woutersed03b412007-08-28 21:37:11 +000028CERTFILE = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +000029SVN_PYTHON_ORG_ROOT_CERT = None
Thomas Woutersed03b412007-08-28 21:37:11 +000030
Thomas Woutersed03b412007-08-28 21:37:11 +000031def handle_error(prefix):
32 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000033 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000034 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000035
36
37class BasicTests(unittest.TestCase):
38
Georg Brandlfceab5a2008-01-19 20:08:23 +000039 def testSSLconnect(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000040 if not support.is_resource_enabled('network'):
Georg Brandlfceab5a2008-01-19 20:08:23 +000041 return
42 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
43 cert_reqs=ssl.CERT_NONE)
44 s.connect(("svn.python.org", 443))
45 c = s.getpeercert()
46 if c:
Benjamin Petersonee8712c2008-05-20 21:35:26 +000047 raise support.TestFailed("Peer cert %s shouldn't be here!")
Georg Brandlfceab5a2008-01-19 20:08:23 +000048 s.close()
49
50 # this should fail because we have no verification certs
51 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
52 cert_reqs=ssl.CERT_REQUIRED)
53 try:
54 s.connect(("svn.python.org", 443))
55 except ssl.SSLError:
56 pass
57 finally:
58 s.close()
59
Thomas Wouters1b7f8912007-09-19 03:06:30 +000060 def testCrucialConstants(self):
61 ssl.PROTOCOL_SSLv2
62 ssl.PROTOCOL_SSLv23
63 ssl.PROTOCOL_SSLv3
64 ssl.PROTOCOL_TLSv1
65 ssl.CERT_NONE
66 ssl.CERT_OPTIONAL
67 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000068
Thomas Wouters1b7f8912007-09-19 03:06:30 +000069 def testRAND(self):
70 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000071 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000072 sys.stdout.write("\n RAND_status is %d (%s)\n"
73 % (v, (v and "sufficient randomness") or
74 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000075 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000076 ssl.RAND_egd(1)
77 except TypeError:
78 pass
Thomas Woutersed03b412007-08-28 21:37:11 +000079 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000080 print("didn't raise TypeError")
81 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +000082
Thomas Wouters1b7f8912007-09-19 03:06:30 +000083 def testParseCert(self):
84 # note that this uses an 'unofficial' function in _ssl.c,
85 # provided solely for this test, to exercise the certificate
86 # parsing code
87 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000088 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000089 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +000090
Thomas Wouters1b7f8912007-09-19 03:06:30 +000091 def testDERtoPEM(self):
92
93 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
94 d1 = ssl.PEM_cert_to_DER_cert(pem)
95 p2 = ssl.DER_cert_to_PEM_cert(d1)
96 d2 = ssl.PEM_cert_to_DER_cert(p2)
97 if (d1 != d2):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000098 raise support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
Thomas Wouters1b7f8912007-09-19 03:06:30 +000099
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000100 def test_openssl_version(self):
101 n = ssl.OPENSSL_VERSION_NUMBER
102 t = ssl.OPENSSL_VERSION_INFO
103 s = ssl.OPENSSL_VERSION
104 self.assertIsInstance(n, int)
105 self.assertIsInstance(t, tuple)
106 self.assertIsInstance(s, str)
107 # Some sanity checks follow
108 # >= 0.9
109 self.assertGreaterEqual(n, 0x900000)
110 # < 2.0
111 self.assertLess(n, 0x20000000)
112 major, minor, fix, patch, status = t
113 self.assertGreaterEqual(major, 0)
114 self.assertLess(major, 2)
115 self.assertGreaterEqual(minor, 0)
116 self.assertLess(minor, 256)
117 self.assertGreaterEqual(fix, 0)
118 self.assertLess(fix, 256)
119 self.assertGreaterEqual(patch, 0)
120 self.assertLessEqual(patch, 26)
121 self.assertGreaterEqual(status, 0)
122 self.assertLessEqual(status, 15)
123 # Version string as returned by OpenSSL, the format might change
124 self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
125 (s, t))
126
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000127 def test_ciphers(self):
128 if not support.is_resource_enabled('network'):
129 return
130 remote = ("svn.python.org", 443)
131 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
132 cert_reqs=ssl.CERT_NONE, ciphers="ALL")
133 s.connect(remote)
134 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
135 cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")
136 s.connect(remote)
137 # Error checking occurs when connecting, because the SSL context
138 # isn't created before.
139 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
140 cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx")
141 with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"):
142 s.connect(remote)
143
Antoine Pitrou9d543662010-04-23 23:10:32 +0000144 @support.cpython_only
145 def test_refcycle(self):
146 # Issue #7943: an SSL object doesn't create reference cycles with
147 # itself.
148 s = socket.socket(socket.AF_INET)
149 ss = ssl.wrap_socket(s)
150 wr = weakref.ref(ss)
151 del ss
152 self.assertEqual(wr(), None)
153
Antoine Pitroucfcd8ad2010-04-23 23:31:47 +0000154 def test_makefile_close(self):
155 # Issue #5238: creating a file-like object with makefile() shouldn't
156 # leak the underlying file descriptor.
157 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
158 fd = ss.fileno()
159 f = ss.makefile()
160 f.close()
161 # The fd is still open
162 os.read(fd, 0)
163 # Closing the SSL socket should close the fd too
164 ss.close()
165 gc.collect()
166 with self.assertRaises(OSError) as e:
167 os.read(fd, 0)
168 self.assertEqual(e.exception.errno, errno.EBADF)
169
Antoine Pitrou04f6a322010-04-05 21:40:07 +0000170
Bill Janssen6e027db2007-11-15 22:23:56 +0000171class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000172
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000173 def testConnect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000174 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
175 cert_reqs=ssl.CERT_NONE)
176 s.connect(("svn.python.org", 443))
177 c = s.getpeercert()
178 if c:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000179 raise support.TestFailed("Peer cert %s shouldn't be here!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000180 s.close()
181
182 # this should fail because we have no verification certs
183 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
184 cert_reqs=ssl.CERT_REQUIRED)
Thomas Woutersed03b412007-08-28 21:37:11 +0000185 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000186 s.connect(("svn.python.org", 443))
187 except ssl.SSLError:
188 pass
189 finally:
190 s.close()
191
192 # this should succeed because we specify the root cert
193 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
194 cert_reqs=ssl.CERT_REQUIRED,
195 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
196 try:
197 s.connect(("svn.python.org", 443))
198 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000199 raise support.TestFailed("Unexpected exception %s" % x)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000200 finally:
201 s.close()
202
Bill Janssen6e027db2007-11-15 22:23:56 +0000203 def testNonBlockingHandshake(self):
204 s = socket.socket(socket.AF_INET)
205 s.connect(("svn.python.org", 443))
206 s.setblocking(False)
207 s = ssl.wrap_socket(s,
208 cert_reqs=ssl.CERT_NONE,
209 do_handshake_on_connect=False)
210 count = 0
211 while True:
212 try:
213 count += 1
214 s.do_handshake()
215 break
216 except ssl.SSLError as err:
217 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
218 select.select([s], [], [])
219 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
220 select.select([], [s], [])
221 else:
222 raise
223 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000224 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000225 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000226
Bill Janssen54cc54c2007-12-14 22:08:56 +0000227 def testFetchServerCert(self):
228
229 pem = ssl.get_server_certificate(("svn.python.org", 443))
230 if not pem:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000231 raise support.TestFailed("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000232
233 return
234
235 try:
236 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
237 except ssl.SSLError as x:
238 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000239 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000240 sys.stdout.write("%s\n" % x)
241 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000242 raise support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000243
244 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
245 if not pem:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000246 raise support.TestFailed("No server certificate on svn.python.org:443!")
247 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000248 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
249
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000250 def test_algorithms(self):
251 # Issue #8484: all algorithms should be available when verifying a
252 # certificate.
Antoine Pitrou29619b22010-04-22 18:43:31 +0000253 # SHA256 was added in OpenSSL 0.9.8
254 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
255 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitroufec12ff2010-04-21 19:46:23 +0000256 # NOTE: https://sha256.tbs-internet.com is another possible test host
257 remote = ("sha2.hboeck.de", 443)
258 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
259 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
260 cert_reqs=ssl.CERT_REQUIRED,
261 ca_certs=sha256_cert,)
262 with support.transient_internet():
263 try:
264 s.connect(remote)
265 if support.verbose:
266 sys.stdout.write("\nCipher with %r is %r\n" %
267 (remote, s.cipher()))
268 sys.stdout.write("Certificate is:\n%s\n" %
269 pprint.pformat(s.getpeercert()))
270 finally:
271 s.close()
272
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000273
274try:
275 import threading
276except ImportError:
277 _have_threads = False
278else:
279
280 _have_threads = True
281
282 class ThreadedEchoServer(threading.Thread):
283
284 class ConnectionHandler(threading.Thread):
285
286 """A mildly complicated class, because we want it to work both
287 with and without the SSL wrapper around the socket connection, so
288 that we can test the STARTTLS functionality."""
289
Bill Janssen6e027db2007-11-15 22:23:56 +0000290 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000291 self.server = server
292 self.running = False
293 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000294 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000295 self.sock.setblocking(1)
296 self.sslconn = None
297 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000298 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000299
300 def wrap_conn (self):
301 try:
302 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
303 certfile=self.server.certificate,
304 ssl_version=self.server.protocol,
305 ca_certs=self.server.cacerts,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000306 cert_reqs=self.server.certreqs,
307 ciphers=self.server.ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000308 except:
309 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000310 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000311 if not self.server.expect_bad_connects:
312 # here, we want to stop the server, because this shouldn't
313 # happen in the context of our test case
314 self.running = False
315 # normally, we'd just stop here, but for the test
316 # harness, we want to stop the server
317 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000318 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000319 return False
320
321 else:
322 if self.server.certreqs == ssl.CERT_REQUIRED:
323 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000324 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000325 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
326 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000327 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000328 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
329 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000330 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000331 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
332 return True
333
334 def read(self):
335 if self.sslconn:
336 return self.sslconn.read()
337 else:
338 return self.sock.recv(1024)
339
340 def write(self, bytes):
341 if self.sslconn:
342 return self.sslconn.write(bytes)
343 else:
344 return self.sock.send(bytes)
345
346 def close(self):
347 if self.sslconn:
348 self.sslconn.close()
349 else:
350 self.sock.close()
351
352 def run (self):
353 self.running = True
354 if not self.server.starttls_server:
355 if not self.wrap_conn():
356 return
357 while self.running:
358 try:
359 msg = self.read()
Bill Janssen6e027db2007-11-15 22:23:56 +0000360 amsg = (msg and str(msg, 'ASCII', 'strict')) or ''
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000361 if not msg:
362 # eof, so quit this handler
363 self.running = False
364 self.close()
Bill Janssen6e027db2007-11-15 22:23:56 +0000365 elif amsg.strip() == 'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000366 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000367 sys.stdout.write(" server: client closed connection\n")
368 self.close()
369 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000370 elif (self.server.starttls_server and
371 amsg.strip() == 'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000372 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000373 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000374 self.write("OK\n".encode("ASCII", "strict"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000375 if not self.wrap_conn():
376 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000377 elif (self.server.starttls_server and self.sslconn
378 and amsg.strip() == 'ENDTLS'):
379 if support.verbose and self.server.connectionchatty:
380 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
381 self.write("OK\n".encode("ASCII", "strict"))
382 self.sock = self.sslconn.unwrap()
383 self.sslconn = None
384 if support.verbose and self.server.connectionchatty:
385 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000386 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000387 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000388 self.server.connectionchatty):
389 ctype = (self.sslconn and "encrypted") or "unencrypted"
390 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
391 % (repr(msg), ctype, repr(msg.lower()), ctype))
Bill Janssen6e027db2007-11-15 22:23:56 +0000392 self.write(amsg.lower().encode('ASCII', 'strict'))
393 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000394 if self.server.chatty:
395 handle_error("Test server failure:\n")
396 self.close()
397 self.running = False
398 # normally, we'd just stop here, but for the test
399 # harness, we want to stop the server
400 self.server.stop()
401 except:
402 handle_error('')
403
Trent Nelson78520002008-04-10 20:54:35 +0000404 def __init__(self, certificate, ssl_version=None,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000405 certreqs=None, cacerts=None, expect_bad_connects=False,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000406 chatty=True, connectionchatty=False, starttls_server=False,
407 ciphers=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000408 if ssl_version is None:
409 ssl_version = ssl.PROTOCOL_TLSv1
410 if certreqs is None:
411 certreqs = ssl.CERT_NONE
412 self.certificate = certificate
413 self.protocol = ssl_version
414 self.certreqs = certreqs
415 self.cacerts = cacerts
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000416 self.ciphers = ciphers
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000417 self.expect_bad_connects = expect_bad_connects
418 self.chatty = chatty
419 self.connectionchatty = connectionchatty
420 self.starttls_server = starttls_server
421 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000422 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000423 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000424 self.active = False
425 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000426 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000427
428 def start (self, flag=None):
429 self.flag = flag
430 threading.Thread.start(self)
431
432 def run (self):
433 self.sock.settimeout(0.5)
434 self.sock.listen(5)
435 self.active = True
436 if self.flag:
437 # signal an event
438 self.flag.set()
439 while self.active:
440 try:
441 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000442 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000443 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000444 + repr(connaddr) + '\n')
445 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000446 handler.start()
447 except socket.timeout:
448 pass
449 except KeyboardInterrupt:
450 self.stop()
451 except:
452 if self.chatty:
453 handle_error("Test server failure:\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000454 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000455
456 def stop (self):
457 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000458
Bill Janssen54cc54c2007-12-14 22:08:56 +0000459 class OurHTTPSServer(threading.Thread):
460
461 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000462
463 class HTTPSServer(HTTPServer):
464
465 def __init__(self, server_address, RequestHandlerClass, certfile):
466
467 HTTPServer.__init__(self, server_address, RequestHandlerClass)
468 # we assume the certfile contains both private key and certificate
469 self.certfile = certfile
470 self.active = False
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000471 self.active_lock = threading.Lock()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000472 self.allow_reuse_address = True
473
Bill Janssen6e027db2007-11-15 22:23:56 +0000474 def __str__(self):
475 return ('<%s %s:%s>' %
476 (self.__class__.__name__,
477 self.server_name,
478 self.server_port))
479
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000480 def get_request (self):
481 # override this to wrap socket with SSL
482 sock, addr = self.socket.accept()
483 sslconn = ssl.wrap_socket(sock, server_side=True,
484 certfile=self.certfile)
485 return sslconn, addr
486
487 # The methods overridden below this are mainly so that we
488 # can run it in a thread and be able to stop it from another
489 # You probably wouldn't need them in other uses.
490
491 def server_activate(self):
492 # We want to run this in a thread for testing purposes,
493 # so we override this to set timeout, so that we get
494 # a chance to stop the server
495 self.socket.settimeout(0.5)
496 HTTPServer.server_activate(self)
497
498 def serve_forever(self):
499 # We want this to run in a thread, so we use a slightly
500 # modified version of "forever".
501 self.active = True
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000502 while 1:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000503 try:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000504 # We need to lock while handling the request.
505 # Another thread can close the socket after self.active
506 # has been checked and before the request is handled.
507 # This causes an exception when using the closed socket.
508 with self.active_lock:
509 if not self.active:
510 break
511 self.handle_request()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000512 except socket.timeout:
513 pass
514 except KeyboardInterrupt:
515 self.server_close()
516 return
517 except:
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000518 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
519 break
Neal Norwitzf9ff5f02008-03-31 05:39:26 +0000520 time.sleep(0.1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000521
522 def server_close(self):
523 # Again, we want this to run in a thread, so we need to override
524 # close to clear the "active" flag, so that serve_forever() will
525 # terminate.
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000526 with self.active_lock:
527 HTTPServer.server_close(self)
528 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000529
530 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
531
532 # need to override translate_path to get a known root,
533 # instead of using os.curdir, since the test could be
534 # run from anywhere
535
536 server_version = "TestHTTPS/1.0"
537
538 root = None
539
540 def translate_path(self, path):
541 """Translate a /-separated PATH to the local filename syntax.
542
543 Components that mean special things to the local file system
544 (e.g. drive or directory names) are ignored. (XXX They should
545 probably be diagnosed.)
546
547 """
548 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000549 path = urllib.parse.urlparse(path)[2]
550 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000551 words = path.split('/')
552 words = filter(None, words)
553 path = self.root
554 for word in words:
555 drive, word = os.path.splitdrive(word)
556 head, word = os.path.split(word)
557 if word in self.root: continue
558 path = os.path.join(path, word)
559 return path
560
561 def log_message(self, format, *args):
562
563 # we override this to suppress logging unless "verbose"
564
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000565 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000566 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
567 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000568 self.server.server_port,
569 self.request.cipher(),
570 self.log_date_time_string(),
571 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000572
573
Trent Nelson78520002008-04-10 20:54:35 +0000574 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000575 self.flag = None
576 self.active = False
577 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000578 self.port = support.find_unused_port()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000579 self.server = self.HTTPSServer(
Trent Nelson78520002008-04-10 20:54:35 +0000580 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Thomas Woutersed03b412007-08-28 21:37:11 +0000581 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000582 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000583
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000584 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000585 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000586
587 def start (self, flag=None):
588 self.flag = flag
589 threading.Thread.start(self)
590
Thomas Woutersed03b412007-08-28 21:37:11 +0000591 def run (self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000592 self.active = True
593 if self.flag:
594 self.flag.set()
595 self.server.serve_forever()
596 self.active = False
597
598 def stop (self):
599 self.active = False
600 self.server.server_close()
601
602
Bill Janssen54cc54c2007-12-14 22:08:56 +0000603 class AsyncoreEchoServer(threading.Thread):
604
605 # this one's based on asyncore.dispatcher
606
607 class EchoServer (asyncore.dispatcher):
608
609 class ConnectionHandler (asyncore.dispatcher_with_send):
610
611 def __init__(self, conn, certfile):
612 self.socket = ssl.wrap_socket(conn, server_side=True,
613 certfile=certfile,
614 do_handshake_on_connect=False)
615 asyncore.dispatcher_with_send.__init__(self, self.socket)
616 # now we have to do the handshake
617 # we'll just do it the easy way, and block the connection
618 # till it's finished. If we were doing it right, we'd
619 # do this in multiple calls to handle_read...
620 self.do_handshake(block=True)
621
622 def readable(self):
623 if isinstance(self.socket, ssl.SSLSocket):
624 while self.socket.pending() > 0:
625 self.handle_read_event()
626 return True
627
628 def handle_read(self):
629 data = self.recv(1024)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000630 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000631 sys.stdout.write(" server: read %s from client\n" % repr(data))
632 if not data:
633 self.close()
634 else:
635 self.send(str(data, 'ASCII', 'strict').lower().encode('ASCII', 'strict'))
636
637 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000638 self.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000639 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000640 sys.stdout.write(" server: closed connection %s\n" % self.socket)
641
642 def handle_error(self):
643 raise
644
645 def __init__(self, port, certfile):
646 self.port = port
647 self.certfile = certfile
648 asyncore.dispatcher.__init__(self)
649 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
650 self.bind(('', port))
651 self.listen(5)
652
653 def handle_accept(self):
654 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000655 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000656 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
657 self.ConnectionHandler(sock_obj, self.certfile)
658
659 def handle_error(self):
660 raise
661
Trent Nelson78520002008-04-10 20:54:35 +0000662 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000663 self.flag = None
664 self.active = False
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000665 self.port = support.find_unused_port()
Trent Nelson78520002008-04-10 20:54:35 +0000666 self.server = self.EchoServer(self.port, certfile)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000667 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000668 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000669
670 def __str__(self):
671 return "<%s %s>" % (self.__class__.__name__, self.server)
672
673 def start (self, flag=None):
674 self.flag = flag
675 threading.Thread.start(self)
676
677 def run (self):
678 self.active = True
679 if self.flag:
680 self.flag.set()
681 while self.active:
682 try:
683 asyncore.loop(1)
684 except:
685 pass
686
687 def stop (self):
688 self.active = False
689 self.server.close()
690
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000691 def badCertTest (certfile):
Trent Nelson78520002008-04-10 20:54:35 +0000692 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000693 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000694 cacerts=CERTFILE, chatty=False,
695 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000696 flag = threading.Event()
697 server.start(flag)
698 # wait for it to start
699 flag.wait()
700 # try to connect
701 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000702 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000703 s = ssl.wrap_socket(socket.socket(),
704 certfile=certfile,
705 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000706 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000707 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000708 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000709 sys.stdout.write("\nSSLError is %s\n" % x)
Bill Janssenddc56692008-07-17 18:17:20 +0000710 except socket.error as x:
711 if support.verbose:
712 sys.stdout.write("\nsocket.error is %s\n" % x)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000713 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000714 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000715 "Use of invalid cert should have failed!")
716 finally:
717 server.stop()
718 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000719
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000720 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
Bill Janssen6e027db2007-11-15 22:23:56 +0000721 client_certfile, client_protocol=None,
722 indata="FOO\n",
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000723 ciphers=None, chatty=False, connectionchatty=False):
Thomas Woutersed03b412007-08-28 21:37:11 +0000724
Trent Nelson78520002008-04-10 20:54:35 +0000725 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000726 certreqs=certreqs,
727 ssl_version=protocol,
728 cacerts=cacertsfile,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000729 ciphers=ciphers,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000730 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000731 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000732 flag = threading.Event()
733 server.start(flag)
734 # wait for it to start
735 flag.wait()
736 # try to connect
737 if client_protocol is None:
738 client_protocol = protocol
739 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000740 s = ssl.wrap_socket(socket.socket(),
Trent Nelson6b240cd2008-04-10 20:12:06 +0000741 server_side=False,
Bill Janssen6e027db2007-11-15 22:23:56 +0000742 certfile=client_certfile,
743 ca_certs=cacertsfile,
744 cert_reqs=certreqs,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000745 ciphers=ciphers,
Bill Janssen6e027db2007-11-15 22:23:56 +0000746 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000747 s.connect((HOST, server.port))
Bill Janssen6e027db2007-11-15 22:23:56 +0000748 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000749 raise support.TestFailed("Unexpected SSL error: " + str(x))
Bill Janssen6e027db2007-11-15 22:23:56 +0000750 except Exception as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000751 raise support.TestFailed("Unexpected exception: " + str(x))
Bill Janssen6e027db2007-11-15 22:23:56 +0000752 else:
Antoine Pitrou7d7aede2009-11-25 18:55:32 +0000753 bindata = indata.encode('ASCII', 'strict')
754 for arg in [bindata, bytearray(bindata), memoryview(bindata)]:
755 if connectionchatty:
756 if support.verbose:
757 sys.stdout.write(
758 " client: sending %s...\n" % (repr(indata)))
759 s.write(arg)
760 outdata = s.read()
761 if connectionchatty:
762 if support.verbose:
763 sys.stdout.write(" client: read %s\n" % repr(outdata))
764 outdata = str(outdata, 'ASCII', 'strict')
765 if outdata != indata.lower():
766 raise support.TestFailed(
767 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
768 % (repr(outdata[:min(len(outdata),20)]), len(outdata),
769 repr(indata[:min(len(indata),20)].lower()), len(indata)))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000770 s.write("over\n".encode("ASCII", "strict"))
Bill Janssen6e027db2007-11-15 22:23:56 +0000771 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000772 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000773 sys.stdout.write(" client: closing connection.\n")
774 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000775 finally:
776 server.stop()
777 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000778
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000779 def tryProtocolCombo (server_protocol,
780 client_protocol,
781 expectedToWork,
782 certsreqs=None):
Thomas Woutersed03b412007-08-28 21:37:11 +0000783
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000784 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000785 certsreqs = ssl.CERT_NONE
Thomas Woutersed03b412007-08-28 21:37:11 +0000786
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000787 if certsreqs == ssl.CERT_NONE:
788 certtype = "CERT_NONE"
789 elif certsreqs == ssl.CERT_OPTIONAL:
790 certtype = "CERT_OPTIONAL"
791 elif certsreqs == ssl.CERT_REQUIRED:
792 certtype = "CERT_REQUIRED"
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000793 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000794 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
795 sys.stdout.write(formatstr %
796 (ssl.get_protocol_name(client_protocol),
797 ssl.get_protocol_name(server_protocol),
798 certtype))
799 try:
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000800 # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
801 # will send an SSLv3 hello (rather than SSLv2) starting from
802 # OpenSSL 1.0.0 (see issue #8322).
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000803 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000804 CERTFILE, CERTFILE, client_protocol,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000805 ciphers="ALL",
Bill Janssen6e027db2007-11-15 22:23:56 +0000806 chatty=False, connectionchatty=False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000807 except support.TestFailed:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000808 if expectedToWork:
809 raise
810 else:
811 if not expectedToWork:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000812 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000813 "Client protocol %s succeeded with server protocol %s!"
814 % (ssl.get_protocol_name(client_protocol),
815 ssl.get_protocol_name(server_protocol)))
816
817
Bill Janssen6e027db2007-11-15 22:23:56 +0000818 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000819
Trent Nelson6b240cd2008-04-10 20:12:06 +0000820 def testEcho (self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000821
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000822 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000823 sys.stdout.write("\n")
824 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
825 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
826 chatty=True, connectionchatty=True)
827
828 def testReadCert(self):
829
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000830 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000831 sys.stdout.write("\n")
832 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000833 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000834 certreqs=ssl.CERT_NONE,
835 ssl_version=ssl.PROTOCOL_SSLv23,
836 cacerts=CERTFILE,
837 chatty=False)
838 flag = threading.Event()
839 server.start(flag)
840 # wait for it to start
841 flag.wait()
842 # try to connect
843 try:
844 try:
845 s = ssl.wrap_socket(socket.socket(),
846 certfile=CERTFILE,
847 ca_certs=CERTFILE,
848 cert_reqs=ssl.CERT_REQUIRED,
849 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelson78520002008-04-10 20:54:35 +0000850 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000851 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000852 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000853 "Unexpected SSL error: " + str(x))
854 except Exception as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000855 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000856 "Unexpected exception: " + str(x))
857 else:
858 if not s:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000859 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 "Can't SSL-handshake with test server")
861 cert = s.getpeercert()
862 if not cert:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000863 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000864 "Can't get peer certificate.")
865 cipher = s.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000866 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000867 sys.stdout.write(pprint.pformat(cert) + '\n')
868 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
Bill Janssen6e027db2007-11-15 22:23:56 +0000869 if 'subject' not in cert:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000870 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000871 "No subject field in certificate: %s." %
872 pprint.pformat(cert))
873 if ((('organizationName', 'Python Software Foundation'),)
874 not in cert['subject']):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000875 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000876 "Missing or invalid 'organizationName' field in certificate subject; "
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000877 "should be 'Python Software Foundation'.")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000878 s.close()
879 finally:
880 server.stop()
881 server.join()
882
883 def testNULLcert(self):
884 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
885 "nullcert.pem"))
886 def testMalformedCert(self):
887 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
888 "badcert.pem"))
Bill Janssen58afe4c2008-09-08 16:45:19 +0000889 def testWrongCert(self):
890 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
891 "wrongcert.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000892 def testMalformedKey(self):
893 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
894 "badkey.pem"))
895
Trent Nelson6b240cd2008-04-10 20:12:06 +0000896 def testRudeShutdown(self):
897
898 listener_ready = threading.Event()
899 listener_gone = threading.Event()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000900 port = support.find_unused_port()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000901
902 # `listener` runs in a thread. It opens a socket listening on
903 # PORT, and sits in an accept() until the main thread connects.
904 # Then it rudely closes the socket, and sets Event `listener_gone`
905 # to let the main thread know the socket is gone.
906 def listener():
907 s = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000908 s.bind((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000909 s.listen(5)
910 listener_ready.set()
911 s.accept()
912 s = None # reclaim the socket object, which also closes it
913 listener_gone.set()
914
915 def connector():
916 listener_ready.wait()
917 s = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000918 s.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000919 listener_gone.wait()
920 try:
921 ssl_sock = ssl.wrap_socket(s)
922 except IOError:
923 pass
924 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000925 raise support.TestFailed(
Trent Nelson6b240cd2008-04-10 20:12:06 +0000926 'connecting to closed SSL socket should have failed')
927
928 t = threading.Thread(target=listener)
929 t.start()
930 connector()
931 t.join()
932
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000933 def testProtocolSSL2(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000934 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000935 sys.stdout.write("\n")
936 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
937 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
938 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
939 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
940 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
941 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
942
943 def testProtocolSSL23(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000944 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000945 sys.stdout.write("\n")
946 try:
947 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000948 except support.TestFailed as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000949 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000950 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000951 sys.stdout.write(
952 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
953 % str(x))
954 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
955 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
956 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
957
958 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
959 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
960 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
961
962 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
963 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
964 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
965
966 def testProtocolSSL3(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000967 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000968 sys.stdout.write("\n")
969 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
970 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
971 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
972 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
973 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
974 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
975
976 def testProtocolTLS1(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000977 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000978 sys.stdout.write("\n")
979 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
980 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
981 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
982 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
983 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
984 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
985
986 def testSTARTTLS (self):
987
Bill Janssen40a0f662008-08-12 16:56:25 +0000988 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000989
Trent Nelson78520002008-04-10 20:54:35 +0000990 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991 ssl_version=ssl.PROTOCOL_TLSv1,
992 starttls_server=True,
993 chatty=True,
994 connectionchatty=True)
995 flag = threading.Event()
996 server.start(flag)
997 # wait for it to start
998 flag.wait()
999 # try to connect
1000 wrapped = False
1001 try:
1002 try:
1003 s = socket.socket()
1004 s.setblocking(1)
Trent Nelson78520002008-04-10 20:54:35 +00001005 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001006 except Exception as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001007 raise support.TestFailed("Unexpected exception: " + str(x))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001008 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001009 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001010 sys.stdout.write("\n")
1011 for indata in msgs:
Bill Janssen6e027db2007-11-15 22:23:56 +00001012 msg = indata.encode('ASCII', 'replace')
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001013 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001014 sys.stdout.write(
Bill Janssen6e027db2007-11-15 22:23:56 +00001015 " client: sending %s...\n" % repr(msg))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001016 if wrapped:
Bill Janssen6e027db2007-11-15 22:23:56 +00001017 conn.write(msg)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001018 outdata = conn.read()
1019 else:
Bill Janssen6e027db2007-11-15 22:23:56 +00001020 s.send(msg)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001021 outdata = s.recv(1024)
1022 if (indata == "STARTTLS" and
Bill Janssen6e027db2007-11-15 22:23:56 +00001023 str(outdata, 'ASCII', 'replace').strip().lower().startswith("ok")):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001024 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001025 msg = str(outdata, 'ASCII', 'replace')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001026 sys.stdout.write(
1027 " client: read %s from server, starting TLS...\n"
Bill Janssen6e027db2007-11-15 22:23:56 +00001028 % repr(msg))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001029 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001030 wrapped = True
Bill Janssen40a0f662008-08-12 16:56:25 +00001031 elif (indata == "ENDTLS" and
1032 str(outdata, 'ASCII', 'replace').strip().lower().startswith("ok")):
1033 if support.verbose:
1034 msg = str(outdata, 'ASCII', 'replace')
1035 sys.stdout.write(
1036 " client: read %s from server, ending TLS...\n"
1037 % repr(msg))
1038 s = conn.unwrap()
1039 wrapped = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001040 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001041 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +00001042 msg = str(outdata, 'ASCII', 'replace')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001043 sys.stdout.write(
Bill Janssen6e027db2007-11-15 22:23:56 +00001044 " client: read %s from server\n" % repr(msg))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001045 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001046 sys.stdout.write(" client: closing connection.\n")
1047 if wrapped:
Bill Janssen6e027db2007-11-15 22:23:56 +00001048 conn.write("over\n".encode("ASCII", "strict"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001049 else:
Bill Janssen40a0f662008-08-12 16:56:25 +00001050 s.send("over\n".encode("ASCII", "strict"))
Bill Janssen6e027db2007-11-15 22:23:56 +00001051 if wrapped:
1052 conn.close()
1053 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001054 s.close()
1055 finally:
1056 server.stop()
1057 server.join()
1058
Bill Janssen54cc54c2007-12-14 22:08:56 +00001059 def testSocketServer(self):
Bill Janssen6e027db2007-11-15 22:23:56 +00001060
Trent Nelson78520002008-04-10 20:54:35 +00001061 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001062 flag = threading.Event()
1063 server.start(flag)
1064 # wait for it to start
1065 flag.wait()
1066 # try to connect
1067 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001068 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001069 sys.stdout.write('\n')
1070 d1 = open(CERTFILE, 'rb').read()
1071 d2 = ''
1072 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +00001073 url = 'https://%s:%d/%s' % (
1074 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +00001075 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +00001076 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001077 if dlen and (int(dlen) > 0):
1078 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001079 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001080 sys.stdout.write(
1081 " client: read %d bytes from remote server '%s'\n"
1082 % (len(d2), server))
1083 f.close()
1084 except:
1085 msg = ''.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001086 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001087 sys.stdout.write('\n' + msg)
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001088 raise support.TestFailed(msg)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001089 else:
1090 if not (d1 == d2):
Bill Janssen6e027db2007-11-15 22:23:56 +00001091 print("d1 is", len(d1), repr(d1))
1092 print("d2 is", len(d2), repr(d2))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001093 raise support.TestFailed(
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001094 "Couldn't fetch data from HTTPS server")
1095 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001096 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001097 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001098 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001099 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001100 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001101 server.join()
1102
Trent Nelson6b240cd2008-04-10 20:12:06 +00001103 def testAsyncoreServer(self):
1104
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001105 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001106 sys.stdout.write("\n")
1107
1108 indata="FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001109 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001110 flag = threading.Event()
1111 server.start(flag)
1112 # wait for it to start
1113 flag.wait()
1114 # try to connect
1115 try:
1116 s = ssl.wrap_socket(socket.socket())
Trent Nelson78520002008-04-10 20:54:35 +00001117 s.connect((HOST, server.port))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001118 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001119 raise support.TestFailed("Unexpected SSL error: " + str(x))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001120 except Exception as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001121 raise support.TestFailed("Unexpected exception: " + str(x))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001122 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001123 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001124 sys.stdout.write(
1125 " client: sending %s...\n" % (repr(indata)))
1126 s.sendall(indata.encode('ASCII', 'strict'))
1127 outdata = s.recv()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001128 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001129 sys.stdout.write(" client: read %s\n" % repr(outdata))
1130 outdata = str(outdata, 'ASCII', 'strict')
1131 if outdata != indata.lower():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001132 raise support.TestFailed(
Trent Nelson6b240cd2008-04-10 20:12:06 +00001133 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1134 % (repr(outdata[:min(len(outdata),20)]), len(outdata),
1135 repr(indata[:min(len(indata),20)].lower()), len(indata)))
1136 s.write("over\n".encode("ASCII", "strict"))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001137 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001138 sys.stdout.write(" client: closing connection.\n")
1139 s.close()
1140 finally:
1141 server.stop()
1142 server.join()
1143
Bill Janssen58afe4c2008-09-08 16:45:19 +00001144 def testAllRecvAndSendMethods(self):
1145
1146 if support.verbose:
1147 sys.stdout.write("\n")
1148
1149 server = ThreadedEchoServer(CERTFILE,
1150 certreqs=ssl.CERT_NONE,
1151 ssl_version=ssl.PROTOCOL_TLSv1,
1152 cacerts=CERTFILE,
1153 chatty=True,
1154 connectionchatty=False)
1155 flag = threading.Event()
1156 server.start(flag)
1157 # wait for it to start
1158 flag.wait()
1159 # try to connect
1160 try:
1161 s = ssl.wrap_socket(socket.socket(),
1162 server_side=False,
1163 certfile=CERTFILE,
1164 ca_certs=CERTFILE,
1165 cert_reqs=ssl.CERT_NONE,
1166 ssl_version=ssl.PROTOCOL_TLSv1)
1167 s.connect((HOST, server.port))
1168 except ssl.SSLError as x:
Georg Brandl89fad142010-03-14 10:23:39 +00001169 self.fail("Unexpected SSL error: " + str(x))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001170 except Exception as x:
Georg Brandl89fad142010-03-14 10:23:39 +00001171 self.fail("Unexpected exception: " + str(x))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001172 else:
1173 # helper methods for standardising recv* method signatures
1174 def _recv_into():
1175 b = bytearray(b"\0"*100)
1176 count = s.recv_into(b)
1177 return b[:count]
1178
1179 def _recvfrom_into():
1180 b = bytearray(b"\0"*100)
1181 count, addr = s.recvfrom_into(b)
1182 return b[:count]
1183
1184 # (name, method, whether to expect success, *args)
1185 send_methods = [
1186 ('send', s.send, True, []),
1187 ('sendto', s.sendto, False, ["some.address"]),
1188 ('sendall', s.sendall, True, []),
1189 ]
1190 recv_methods = [
1191 ('recv', s.recv, True, []),
1192 ('recvfrom', s.recvfrom, False, ["some.address"]),
1193 ('recv_into', _recv_into, True, []),
1194 ('recvfrom_into', _recvfrom_into, False, []),
1195 ]
1196 data_prefix = "PREFIX_"
1197
1198 for meth_name, send_meth, expect_success, args in send_methods:
1199 indata = data_prefix + meth_name
1200 try:
1201 send_meth(indata.encode('ASCII', 'strict'), *args)
1202 outdata = s.read()
1203 outdata = str(outdata, 'ASCII', 'strict')
1204 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001205 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001206 "While sending with <<{name:s}>> bad data "
1207 "<<{outdata:s}>> ({nout:d}) received; "
1208 "expected <<{indata:s}>> ({nin:d})\n".format(
1209 name=meth_name, outdata=repr(outdata[:20]),
1210 nout=len(outdata),
1211 indata=repr(indata[:20]), nin=len(indata)
1212 )
1213 )
1214 except ValueError as e:
1215 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001216 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001217 "Failed to send with method <<{name:s}>>; "
1218 "expected to succeed.\n".format(name=meth_name)
1219 )
1220 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001221 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001222 "Method <<{name:s}>> failed with unexpected "
1223 "exception message: {exp:s}\n".format(
1224 name=meth_name, exp=e
1225 )
1226 )
1227
1228 for meth_name, recv_meth, expect_success, args in recv_methods:
1229 indata = data_prefix + meth_name
1230 try:
1231 s.send(indata.encode('ASCII', 'strict'))
1232 outdata = recv_meth(*args)
1233 outdata = str(outdata, 'ASCII', 'strict')
1234 if outdata != indata.lower():
Georg Brandl89fad142010-03-14 10:23:39 +00001235 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001236 "While receiving with <<{name:s}>> bad data "
1237 "<<{outdata:s}>> ({nout:d}) received; "
1238 "expected <<{indata:s}>> ({nin:d})\n".format(
1239 name=meth_name, outdata=repr(outdata[:20]),
1240 nout=len(outdata),
1241 indata=repr(indata[:20]), nin=len(indata)
1242 )
1243 )
1244 except ValueError as e:
1245 if expect_success:
Georg Brandl89fad142010-03-14 10:23:39 +00001246 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001247 "Failed to receive with method <<{name:s}>>; "
1248 "expected to succeed.\n".format(name=meth_name)
1249 )
1250 if not str(e).startswith(meth_name):
Georg Brandl89fad142010-03-14 10:23:39 +00001251 self.fail(
Bill Janssen58afe4c2008-09-08 16:45:19 +00001252 "Method <<{name:s}>> failed with unexpected "
1253 "exception message: {exp:s}\n".format(
1254 name=meth_name, exp=e
1255 )
1256 )
1257 # consume data
1258 s.read()
1259
1260 s.write("over\n".encode("ASCII", "strict"))
1261 s.close()
1262 finally:
1263 server.stop()
1264 server.join()
1265
1266
Thomas Woutersed03b412007-08-28 21:37:11 +00001267def test_main(verbose=False):
1268 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001269 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001270
Trent Nelson78520002008-04-10 20:54:35 +00001271 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Thomas Woutersed03b412007-08-28 21:37:11 +00001272 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
1273 "keycert.pem")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001274 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1275 os.path.dirname(__file__) or os.curdir,
1276 "https_svn_python_org_root.pem")
1277
1278 if (not os.path.exists(CERTFILE) or
1279 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001280 raise support.TestFailed("Can't read certificate files!")
Bill Janssen6e027db2007-11-15 22:23:56 +00001281
Thomas Woutersed03b412007-08-28 21:37:11 +00001282 tests = [BasicTests]
1283
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001284 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001285 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001286
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001287 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001288 thread_info = support.threading_setup()
1289 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001290 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001291
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001292 support.run_unittest(*tests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001293
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001294 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001295 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001296
1297if __name__ == "__main__":
1298 test_main()