blob: 0165de86b92c704dc868619557a777d43e2b8a76 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Woutersed03b412007-08-28 21:37:11 +00006import socket
Bill Janssen6e027db2007-11-15 22:23:56 +00007import select
Thomas Woutersed03b412007-08-28 21:37:11 +00008import errno
Thomas Woutersed03b412007-08-28 21:37:11 +00009import subprocess
10import time
Antoine Pitrou3b9b9ba2010-04-23 23:33:50 +000011import gc
Thomas Woutersed03b412007-08-28 21:37:11 +000012import os
Antoine Pitrou3b9b9ba2010-04-23 23:33:50 +000013import errno
Thomas Woutersed03b412007-08-28 21:37:11 +000014import pprint
Jeremy Hylton1afc1692008-06-18 20:49:58 +000015import urllib.parse, urllib.request
Thomas Woutersed03b412007-08-28 21:37:11 +000016import shutil
17import traceback
Bill Janssen54cc54c2007-12-14 22:08:56 +000018import asyncore
Antoine Pitrou78f4a9a2010-04-23 23:12:22 +000019import weakref
Thomas Woutersed03b412007-08-28 21:37:11 +000020
Georg Brandl24420152008-05-26 16:32:26 +000021from http.server import HTTPServer, SimpleHTTPRequestHandler
Thomas Wouters1b7f8912007-09-19 03:06:30 +000022
Thomas Woutersed03b412007-08-28 21:37:11 +000023# Optionally test SSL support, if we have it in the tested platform
24skip_expected = False
25try:
26 import ssl
27except ImportError:
28 skip_expected = True
29
Benjamin Petersonee8712c2008-05-20 21:35:26 +000030HOST = support.HOST
Thomas Woutersed03b412007-08-28 21:37:11 +000031CERTFILE = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +000032SVN_PYTHON_ORG_ROOT_CERT = None
Thomas Woutersed03b412007-08-28 21:37:11 +000033
Thomas Woutersed03b412007-08-28 21:37:11 +000034def handle_error(prefix):
35 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Benjamin Petersonee8712c2008-05-20 21:35:26 +000036 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000037 sys.stdout.write(prefix + exc_format)
Thomas Woutersed03b412007-08-28 21:37:11 +000038
39
40class BasicTests(unittest.TestCase):
41
Antoine Pitrou91382d82010-04-28 21:39:56 +000042 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000043 ssl.PROTOCOL_SSLv2
44 ssl.PROTOCOL_SSLv23
45 ssl.PROTOCOL_SSLv3
46 ssl.PROTOCOL_TLSv1
47 ssl.CERT_NONE
48 ssl.CERT_OPTIONAL
49 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000050
Antoine Pitrou91382d82010-04-28 21:39:56 +000051 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000052 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000053 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000054 sys.stdout.write("\n RAND_status is %d (%s)\n"
55 % (v, (v and "sufficient randomness") or
56 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000057 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000058 ssl.RAND_egd(1)
59 except TypeError:
60 pass
Thomas Woutersed03b412007-08-28 21:37:11 +000061 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000062 print("didn't raise TypeError")
63 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +000064
Antoine Pitrou91382d82010-04-28 21:39:56 +000065 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000066 # note that this uses an 'unofficial' function in _ssl.c,
67 # provided solely for this test, to exercise the certificate
68 # parsing code
69 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000070 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000071 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +000072
Antoine Pitrou91382d82010-04-28 21:39:56 +000073 def test_DER_to_PEM(self):
74 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
75 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +000076 d1 = ssl.PEM_cert_to_DER_cert(pem)
77 p2 = ssl.DER_cert_to_PEM_cert(d1)
78 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou66ffb262010-04-27 11:05:15 +000079 self.assertEqual(d1, d2)
Antoine Pitrou00f905e2010-04-27 22:09:05 +000080 if not p2.startswith(ssl.PEM_HEADER + '\n'):
81 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
82 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
83 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +000084
Antoine Pitrou78f4a9a2010-04-23 23:12:22 +000085 @support.cpython_only
86 def test_refcycle(self):
87 # Issue #7943: an SSL object doesn't create reference cycles with
88 # itself.
89 s = socket.socket(socket.AF_INET)
90 ss = ssl.wrap_socket(s)
91 wr = weakref.ref(ss)
92 del ss
93 self.assertEqual(wr(), None)
94
Antoine Pitrouc2203f92010-04-24 22:07:51 +000095 def test_timeout(self):
96 # Issue #8524: when creating an SSL socket, the timeout of the
97 # original socket should be retained.
98 for timeout in (None, 0.0, 5.0):
99 s = socket.socket(socket.AF_INET)
100 s.settimeout(timeout)
101 ss = ssl.wrap_socket(s)
102 self.assertEqual(timeout, ss.gettimeout())
103
Antoine Pitrou3b9b9ba2010-04-23 23:33:50 +0000104
Bill Janssen6e027db2007-11-15 22:23:56 +0000105class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106
Antoine Pitrou91382d82010-04-28 21:39:56 +0000107 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000108 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
109 cert_reqs=ssl.CERT_NONE)
110 s.connect(("svn.python.org", 443))
111 c = s.getpeercert()
112 if c:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000113 self.fail("Peer cert %s shouldn't be here!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 s.close()
115
116 # this should fail because we have no verification certs
117 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
118 cert_reqs=ssl.CERT_REQUIRED)
Thomas Woutersed03b412007-08-28 21:37:11 +0000119 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 s.connect(("svn.python.org", 443))
121 except ssl.SSLError:
122 pass
123 finally:
124 s.close()
125
126 # this should succeed because we specify the root cert
127 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
128 cert_reqs=ssl.CERT_REQUIRED,
129 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
130 try:
131 s.connect(("svn.python.org", 443))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000132 finally:
133 s.close()
134
Antoine Pitroufe0f1172010-04-24 11:17:37 +0000135 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
136 def test_makefile_close(self):
137 # Issue #5238: creating a file-like object with makefile() shouldn't
138 # delay closing the underlying "real socket" (here tested with its
139 # file descriptor, hence skipping the test under Windows).
140 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
141 ss.connect(("svn.python.org", 443))
142 fd = ss.fileno()
143 f = ss.makefile()
144 f.close()
145 # The fd is still open
146 os.read(fd, 0)
147 # Closing the SSL socket should close the fd too
148 ss.close()
149 gc.collect()
150 try:
151 os.read(fd, 0)
152 except OSError as e:
153 self.assertEqual(e.errno, errno.EBADF)
154 else:
155 self.fail("OSError wasn't raised")
156
Antoine Pitrou91382d82010-04-28 21:39:56 +0000157 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000158 s = socket.socket(socket.AF_INET)
159 s.connect(("svn.python.org", 443))
160 s.setblocking(False)
161 s = ssl.wrap_socket(s,
162 cert_reqs=ssl.CERT_NONE,
163 do_handshake_on_connect=False)
164 count = 0
165 while True:
166 try:
167 count += 1
168 s.do_handshake()
169 break
170 except ssl.SSLError as err:
171 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
172 select.select([s], [], [])
173 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
174 select.select([], [s], [])
175 else:
176 raise
177 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000178 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000179 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000180
Antoine Pitrou91382d82010-04-28 21:39:56 +0000181 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000182 pem = ssl.get_server_certificate(("svn.python.org", 443))
183 if not pem:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000184 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000185
186 return
187
188 try:
189 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
190 except ssl.SSLError as x:
191 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000192 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000193 sys.stdout.write("%s\n" % x)
194 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000195 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000196
197 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
198 if not pem:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000199 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000200 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000201 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
202
Antoine Pitrou754b98c2010-04-22 18:47:06 +0000203 # Test disabled: OPENSSL_VERSION* not available in Python 3.1
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000204 def test_algorithms(self):
Antoine Pitrouae92a722010-04-22 18:46:16 +0000205 if support.verbose:
206 sys.stdout.write("test_algorithms disabled, "
207 "as it fails on some old OpenSSL versions")
208 return
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000209 # Issue #8484: all algorithms should be available when verifying a
210 # certificate.
Antoine Pitrouae92a722010-04-22 18:46:16 +0000211 # SHA256 was added in OpenSSL 0.9.8
212 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
213 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000214 # NOTE: https://sha256.tbs-internet.com is another possible test host
215 remote = ("sha2.hboeck.de", 443)
216 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
217 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
218 cert_reqs=ssl.CERT_REQUIRED,
219 ca_certs=sha256_cert,)
220 with support.transient_internet():
221 try:
222 s.connect(remote)
223 if support.verbose:
224 sys.stdout.write("\nCipher with %r is %r\n" %
225 (remote, s.cipher()))
226 sys.stdout.write("Certificate is:\n%s\n" %
227 pprint.pformat(s.getpeercert()))
228 finally:
229 s.close()
230
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000231
232try:
233 import threading
234except ImportError:
235 _have_threads = False
236else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000237 _have_threads = True
238
239 class ThreadedEchoServer(threading.Thread):
240
241 class ConnectionHandler(threading.Thread):
242
243 """A mildly complicated class, because we want it to work both
244 with and without the SSL wrapper around the socket connection, so
245 that we can test the STARTTLS functionality."""
246
Bill Janssen6e027db2007-11-15 22:23:56 +0000247 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000248 self.server = server
249 self.running = False
250 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000251 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000252 self.sock.setblocking(1)
253 self.sslconn = None
254 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000255 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000256
Antoine Pitrou91382d82010-04-28 21:39:56 +0000257 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000258 try:
259 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
260 certfile=self.server.certificate,
261 ssl_version=self.server.protocol,
262 ca_certs=self.server.cacerts,
263 cert_reqs=self.server.certreqs)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000264 except ssl.SSLError:
265 # XXX Various errors can have happened here, for example
266 # a mismatching protocol version, an invalid certificate,
267 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000268 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000269 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000270 self.running = False
271 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000272 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000273 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000274 else:
275 if self.server.certreqs == ssl.CERT_REQUIRED:
276 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000277 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000278 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
279 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000280 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000281 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
282 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000283 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000284 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
285 return True
286
287 def read(self):
288 if self.sslconn:
289 return self.sslconn.read()
290 else:
291 return self.sock.recv(1024)
292
293 def write(self, bytes):
294 if self.sslconn:
295 return self.sslconn.write(bytes)
296 else:
297 return self.sock.send(bytes)
298
299 def close(self):
300 if self.sslconn:
301 self.sslconn.close()
302 else:
303 self.sock.close()
304
Antoine Pitrou91382d82010-04-28 21:39:56 +0000305 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000306 self.running = True
307 if not self.server.starttls_server:
308 if not self.wrap_conn():
309 return
310 while self.running:
311 try:
312 msg = self.read()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000313 stripped = msg.strip()
314 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000315 # eof, so quit this handler
316 self.running = False
317 self.close()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000318 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000319 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000320 sys.stdout.write(" server: client closed connection\n")
321 self.close()
322 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000323 elif (self.server.starttls_server and
Antoine Pitroub1997962010-04-28 22:58:16 +0000324 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000325 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000326 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000327 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000328 if not self.wrap_conn():
329 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000330 elif (self.server.starttls_server and self.sslconn
Antoine Pitroub1997962010-04-28 22:58:16 +0000331 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000332 if support.verbose and self.server.connectionchatty:
333 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000334 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000335 self.sock = self.sslconn.unwrap()
336 self.sslconn = None
337 if support.verbose and self.server.connectionchatty:
338 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000339 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000340 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000341 self.server.connectionchatty):
342 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou91382d82010-04-28 21:39:56 +0000343 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
344 % (msg, ctype, msg.lower(), ctype))
345 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000346 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000347 if self.server.chatty:
348 handle_error("Test server failure:\n")
349 self.close()
350 self.running = False
351 # normally, we'd just stop here, but for the test
352 # harness, we want to stop the server
353 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000354
Trent Nelson78520002008-04-10 20:54:35 +0000355 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000356 certreqs=None, cacerts=None,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000357 chatty=True, connectionchatty=False, starttls_server=False):
358 if ssl_version is None:
359 ssl_version = ssl.PROTOCOL_TLSv1
360 if certreqs is None:
361 certreqs = ssl.CERT_NONE
362 self.certificate = certificate
363 self.protocol = ssl_version
364 self.certreqs = certreqs
365 self.cacerts = cacerts
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000366 self.chatty = chatty
367 self.connectionchatty = connectionchatty
368 self.starttls_server = starttls_server
369 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000370 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000371 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000372 self.active = False
373 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000374 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000375
Antoine Pitrou91382d82010-04-28 21:39:56 +0000376 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000377 self.flag = flag
378 threading.Thread.start(self)
379
Antoine Pitrou91382d82010-04-28 21:39:56 +0000380 def run(self):
Antoine Pitroube168132010-04-27 10:41:37 +0000381 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000382 self.sock.listen(5)
383 self.active = True
384 if self.flag:
385 # signal an event
386 self.flag.set()
387 while self.active:
388 try:
389 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000390 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000391 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000392 + repr(connaddr) + '\n')
393 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000394 handler.start()
395 except socket.timeout:
396 pass
397 except KeyboardInterrupt:
398 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000399 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000400
Antoine Pitrou91382d82010-04-28 21:39:56 +0000401 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000402 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000403
Bill Janssen54cc54c2007-12-14 22:08:56 +0000404 class OurHTTPSServer(threading.Thread):
405
406 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000407
408 class HTTPSServer(HTTPServer):
409
410 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000411 HTTPServer.__init__(self, server_address, RequestHandlerClass)
412 # we assume the certfile contains both private key and certificate
413 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000414 self.allow_reuse_address = True
415
Bill Janssen6e027db2007-11-15 22:23:56 +0000416 def __str__(self):
417 return ('<%s %s:%s>' %
418 (self.__class__.__name__,
419 self.server_name,
420 self.server_port))
421
Antoine Pitrou91382d82010-04-28 21:39:56 +0000422 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000423 # override this to wrap socket with SSL
424 sock, addr = self.socket.accept()
425 sslconn = ssl.wrap_socket(sock, server_side=True,
426 certfile=self.certfile)
427 return sslconn, addr
428
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000429 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000430 # need to override translate_path to get a known root,
431 # instead of using os.curdir, since the test could be
432 # run from anywhere
433
434 server_version = "TestHTTPS/1.0"
435
436 root = None
437
438 def translate_path(self, path):
439 """Translate a /-separated PATH to the local filename syntax.
440
441 Components that mean special things to the local file system
442 (e.g. drive or directory names) are ignored. (XXX They should
443 probably be diagnosed.)
444
445 """
446 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000447 path = urllib.parse.urlparse(path)[2]
448 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000449 words = path.split('/')
450 words = filter(None, words)
451 path = self.root
452 for word in words:
453 drive, word = os.path.splitdrive(word)
454 head, word = os.path.split(word)
455 if word in self.root: continue
456 path = os.path.join(path, word)
457 return path
458
459 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000460 # we override this to suppress logging unless "verbose"
461
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000462 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000463 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
464 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000465 self.server.server_port,
466 self.request.cipher(),
467 self.log_date_time_string(),
468 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000469
470
Trent Nelson78520002008-04-10 20:54:35 +0000471 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000472 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000473 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
474 self.server = self.HTTPSServer(
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000475 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
476 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000477 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000478 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000479
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000480 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000481 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000482
Antoine Pitrou91382d82010-04-28 21:39:56 +0000483 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000484 self.flag = flag
485 threading.Thread.start(self)
486
Antoine Pitrou91382d82010-04-28 21:39:56 +0000487 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000488 if self.flag:
489 self.flag.set()
Antoine Pitroube168132010-04-27 10:41:37 +0000490 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000491
Antoine Pitrou91382d82010-04-28 21:39:56 +0000492 def stop(self):
Antoine Pitroube168132010-04-27 10:41:37 +0000493 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000494
495
Bill Janssen54cc54c2007-12-14 22:08:56 +0000496 class AsyncoreEchoServer(threading.Thread):
497
498 # this one's based on asyncore.dispatcher
499
500 class EchoServer (asyncore.dispatcher):
501
502 class ConnectionHandler (asyncore.dispatcher_with_send):
503
504 def __init__(self, conn, certfile):
505 self.socket = ssl.wrap_socket(conn, server_side=True,
506 certfile=certfile,
507 do_handshake_on_connect=False)
508 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitrouec146182010-04-24 21:30:20 +0000509 self._ssl_accepting = True
510 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000511
512 def readable(self):
513 if isinstance(self.socket, ssl.SSLSocket):
514 while self.socket.pending() > 0:
515 self.handle_read_event()
516 return True
517
Antoine Pitrouec146182010-04-24 21:30:20 +0000518 def _do_ssl_handshake(self):
519 try:
520 self.socket.do_handshake()
521 except ssl.SSLError as err:
522 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
523 ssl.SSL_ERROR_WANT_WRITE):
524 return
525 elif err.args[0] == ssl.SSL_ERROR_EOF:
526 return self.handle_close()
527 raise
528 except socket.error as err:
529 if err.args[0] == errno.ECONNABORTED:
530 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000531 else:
Antoine Pitrouec146182010-04-24 21:30:20 +0000532 self._ssl_accepting = False
533
534 def handle_read(self):
535 if self._ssl_accepting:
536 self._do_ssl_handshake()
537 else:
538 data = self.recv(1024)
539 if support.verbose:
540 sys.stdout.write(" server: read %s from client\n" % repr(data))
541 if not data:
542 self.close()
543 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000544 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000545
546 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000547 self.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000548 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000549 sys.stdout.write(" server: closed connection %s\n" % self.socket)
550
551 def handle_error(self):
552 raise
553
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000554 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000555 self.certfile = certfile
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000556 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
557 self.port = support.bind_port(sock, '')
558 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000559 self.listen(5)
560
561 def handle_accept(self):
562 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000563 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000564 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
565 self.ConnectionHandler(sock_obj, self.certfile)
566
567 def handle_error(self):
568 raise
569
Trent Nelson78520002008-04-10 20:54:35 +0000570 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000571 self.flag = None
572 self.active = False
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000573 self.server = self.EchoServer(certfile)
574 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000575 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000576 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000577
578 def __str__(self):
579 return "<%s %s>" % (self.__class__.__name__, self.server)
580
581 def start (self, flag=None):
582 self.flag = flag
583 threading.Thread.start(self)
584
Antoine Pitrou91382d82010-04-28 21:39:56 +0000585 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000586 self.active = True
587 if self.flag:
588 self.flag.set()
589 while self.active:
590 try:
591 asyncore.loop(1)
592 except:
593 pass
594
Antoine Pitrou91382d82010-04-28 21:39:56 +0000595 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000596 self.active = False
597 self.server.close()
598
Antoine Pitrou91382d82010-04-28 21:39:56 +0000599 def bad_cert_test(certfile):
600 """
601 Launch a server with CERT_REQUIRED, and check that trying to
602 connect to it with the given client certificate fails.
603 """
Trent Nelson78520002008-04-10 20:54:35 +0000604 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000605 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000606 cacerts=CERTFILE, chatty=False,
607 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000608 flag = threading.Event()
609 server.start(flag)
610 # wait for it to start
611 flag.wait()
612 # try to connect
613 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000614 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000615 s = ssl.wrap_socket(socket.socket(),
616 certfile=certfile,
617 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000618 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000619 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000620 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000621 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou537bed62010-04-27 13:16:06 +0000622 except socket.error as x:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000623 if support.verbose:
Antoine Pitrou537bed62010-04-27 13:16:06 +0000624 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000625 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000626 self.fail("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000627 finally:
628 server.stop()
629 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000630
Antoine Pitrou91382d82010-04-28 21:39:56 +0000631 def server_params_test(certfile, protocol, certreqs, cacertsfile,
632 client_certfile, client_protocol=None, indata=b"FOO\n",
633 chatty=True, connectionchatty=False):
634 """
635 Launch a server, connect a client to it and try various reads
636 and writes.
637 """
Trent Nelson78520002008-04-10 20:54:35 +0000638 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639 certreqs=certreqs,
640 ssl_version=protocol,
641 cacerts=cacertsfile,
642 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000643 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000644 flag = threading.Event()
645 server.start(flag)
646 # wait for it to start
647 flag.wait()
648 # try to connect
649 if client_protocol is None:
650 client_protocol = protocol
651 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000652 s = ssl.wrap_socket(socket.socket(),
653 certfile=client_certfile,
654 ca_certs=cacertsfile,
655 cert_reqs=certreqs,
656 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000657 s.connect((HOST, server.port))
Antoine Pitrou91382d82010-04-28 21:39:56 +0000658 arg = indata
Bill Janssen6e027db2007-11-15 22:23:56 +0000659 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000660 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000661 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000662 " client: sending %r...\n" % indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000663 s.write(arg)
Bill Janssen6e027db2007-11-15 22:23:56 +0000664 outdata = s.read()
665 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000666 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000667 sys.stdout.write(" client: read %r\n" % outdata)
Bill Janssen6e027db2007-11-15 22:23:56 +0000668 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000669 self.fail(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000670 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
671 % (outdata[:20], len(outdata),
672 indata[:20].lower(), len(indata)))
673 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000674 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000675 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000676 sys.stdout.write(" client: closing connection.\n")
677 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000678 finally:
679 server.stop()
680 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000681
Antoine Pitrou91382d82010-04-28 21:39:56 +0000682 def try_protocol_combo(server_protocol,
683 client_protocol,
684 expect_success,
685 certsreqs=None):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000686 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000687 certsreqs = ssl.CERT_NONE
Antoine Pitrou91382d82010-04-28 21:39:56 +0000688 certtype = {
689 ssl.CERT_NONE: "CERT_NONE",
690 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
691 ssl.CERT_REQUIRED: "CERT_REQUIRED",
692 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000693 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000694 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000695 sys.stdout.write(formatstr %
696 (ssl.get_protocol_name(client_protocol),
697 ssl.get_protocol_name(server_protocol),
698 certtype))
699 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000700 server_params_test(CERTFILE, server_protocol, certsreqs,
701 CERTFILE, CERTFILE, client_protocol,
702 chatty=False,
703 connectionchatty=False)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000704 # Protocol mismatch can result in either an SSLError, or a
705 # "Connection reset by peer" error.
706 except ssl.SSLError:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000707 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000708 raise
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000709 except socket.error as e:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000710 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000711 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000712 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000713 if not expect_success:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000714 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000715 "Client protocol %s succeeded with server protocol %s!"
716 % (ssl.get_protocol_name(client_protocol),
717 ssl.get_protocol_name(server_protocol)))
718
719
Bill Janssen6e027db2007-11-15 22:23:56 +0000720 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000721
Antoine Pitrou91382d82010-04-28 21:39:56 +0000722 def test_echo(self):
723 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000724 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000725 sys.stdout.write("\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000726 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
727 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
728 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000729
Antoine Pitrou91382d82010-04-28 21:39:56 +0000730 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000731 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000732 sys.stdout.write("\n")
733 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000734 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000735 certreqs=ssl.CERT_NONE,
736 ssl_version=ssl.PROTOCOL_SSLv23,
737 cacerts=CERTFILE,
738 chatty=False)
739 flag = threading.Event()
740 server.start(flag)
741 # wait for it to start
742 flag.wait()
743 # try to connect
744 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000745 s = ssl.wrap_socket(socket.socket(),
746 certfile=CERTFILE,
747 ca_certs=CERTFILE,
748 cert_reqs=ssl.CERT_REQUIRED,
749 ssl_version=ssl.PROTOCOL_SSLv23)
750 s.connect((HOST, server.port))
751 cert = s.getpeercert()
752 self.assertTrue(cert, "Can't get peer certificate.")
753 cipher = s.cipher()
754 if support.verbose:
755 sys.stdout.write(pprint.pformat(cert) + '\n')
756 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
757 if 'subject' not in cert:
758 self.fail("No subject field in certificate: %s." %
759 pprint.pformat(cert))
760 if ((('organizationName', 'Python Software Foundation'),)
761 not in cert['subject']):
762 self.fail(
763 "Missing or invalid 'organizationName' field in certificate subject; "
764 "should be 'Python Software Foundation'.")
765 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000766 finally:
767 server.stop()
768 server.join()
769
Antoine Pitrou91382d82010-04-28 21:39:56 +0000770 def test_empty_cert(self):
771 """Connecting with an empty cert file"""
772 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
773 "nullcert.pem"))
774 def test_malformed_cert(self):
775 """Connecting with a badly formatted certificate (syntax error)"""
776 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
777 "badcert.pem"))
778 def test_nonexisting_cert(self):
779 """Connecting with a non-existing cert file"""
780 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
781 "wrongcert.pem"))
782 def test_malformed_key(self):
783 """Connecting with a badly formatted key (syntax error)"""
784 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
785 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000786
Antoine Pitrou91382d82010-04-28 21:39:56 +0000787 def test_rude_shutdown(self):
788 """A brutal shutdown of an SSL server should raise an IOError
789 in the client when attempting handshake.
790 """
Trent Nelson6b240cd2008-04-10 20:12:06 +0000791 listener_ready = threading.Event()
792 listener_gone = threading.Event()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000793
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000794 s = socket.socket()
795 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000796
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000797 # `listener` runs in a thread. It sits in an accept() until
798 # the main thread connects. Then it rudely closes the socket,
799 # and sets Event `listener_gone` to let the main thread know
800 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000801 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000802 s.listen(5)
803 listener_ready.set()
804 s.accept()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000805 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000806 listener_gone.set()
807
808 def connector():
809 listener_ready.wait()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000810 c = socket.socket()
811 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000812 listener_gone.wait()
813 try:
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000814 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000815 except IOError:
816 pass
817 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000818 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +0000819
820 t = threading.Thread(target=listener)
821 t.start()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000822 try:
823 connector()
824 finally:
825 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000826
Antoine Pitrou91382d82010-04-28 21:39:56 +0000827 def test_protocol_sslv2(self):
828 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000829 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000830 sys.stdout.write("\ntest_protocol_sslv2 disabled, "
831 "as it fails on OpenSSL 1.0.0+")
832 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000833 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
834 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
835 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
836 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
837 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
838 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000839
Antoine Pitrou91382d82010-04-28 21:39:56 +0000840 def test_protocol_sslv23(self):
841 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000842 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000843 sys.stdout.write("\ntest_protocol_sslv23 disabled, "
844 "as it fails on OpenSSL 1.0.0+")
845 return
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000846 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000847 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000848 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000849 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000850 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000851 sys.stdout.write(
852 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
853 % str(x))
Antoine Pitrou91382d82010-04-28 21:39:56 +0000854 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
855 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
856 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000857
Antoine Pitrou91382d82010-04-28 21:39:56 +0000858 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
859 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
860 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861
Antoine Pitrou91382d82010-04-28 21:39:56 +0000862 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
863 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
864 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865
Antoine Pitrou91382d82010-04-28 21:39:56 +0000866 def test_protocol_sslv3(self):
867 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000868 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000869 sys.stdout.write("\ntest_protocol_sslv3 disabled, "
870 "as it fails on OpenSSL 1.0.0+")
871 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000872 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
873 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
874 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
875 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
876 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
877 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000878
Antoine Pitrou91382d82010-04-28 21:39:56 +0000879 def test_protocol_tlsv1(self):
880 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000881 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000882 sys.stdout.write("\ntest_protocol_tlsv1 disabled, "
883 "as it fails on OpenSSL 1.0.0+")
884 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000885 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
886 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
887 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
888 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
889 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
890 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000891
Antoine Pitrou91382d82010-04-28 21:39:56 +0000892 def test_starttls(self):
893 """Switching from clear text to encrypted and back again."""
894 msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895
Trent Nelson78520002008-04-10 20:54:35 +0000896 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000897 ssl_version=ssl.PROTOCOL_TLSv1,
898 starttls_server=True,
899 chatty=True,
900 connectionchatty=True)
901 flag = threading.Event()
902 server.start(flag)
903 # wait for it to start
904 flag.wait()
905 # try to connect
906 wrapped = False
907 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000908 s = socket.socket()
909 s.setblocking(1)
910 s.connect((HOST, server.port))
911 if support.verbose:
912 sys.stdout.write("\n")
913 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000914 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000915 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000916 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000917 if wrapped:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000918 conn.write(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000919 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000920 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000921 s.send(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000922 outdata = s.recv(1024)
Antoine Pitrou91382d82010-04-28 21:39:56 +0000923 msg = outdata.strip().lower()
924 if indata == b"STARTTLS" and msg.startswith(b"ok"):
925 # STARTTLS ok, switch to secure mode
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000926 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000927 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000928 " client: read %r from server, starting TLS...\n"
929 % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000930 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
931 wrapped = True
Antoine Pitrou91382d82010-04-28 21:39:56 +0000932 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
933 # ENDTLS ok, switch back to clear text
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000934 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000935 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000936 " client: read %r from server, ending TLS...\n"
937 % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000938 s = conn.unwrap()
939 wrapped = False
940 else:
941 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000942 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000943 " client: read %r from server\n" % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000944 if support.verbose:
945 sys.stdout.write(" client: closing connection.\n")
946 if wrapped:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000947 conn.write(b"over\n")
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000948 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000949 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000950 if wrapped:
951 conn.close()
952 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000953 s.close()
954 finally:
955 server.stop()
956 server.join()
957
Antoine Pitrou91382d82010-04-28 21:39:56 +0000958 def test_socketserver(self):
959 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +0000960 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000961 flag = threading.Event()
962 server.start(flag)
963 # wait for it to start
964 flag.wait()
965 # try to connect
966 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000967 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000968 sys.stdout.write('\n')
Antoine Pitrou91382d82010-04-28 21:39:56 +0000969 with open(CERTFILE, 'rb') as f:
970 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000971 d2 = ''
972 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +0000973 url = 'https://%s:%d/%s' % (
974 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000975 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +0000976 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000977 if dlen and (int(dlen) > 0):
978 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000979 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000980 sys.stdout.write(
981 " client: read %d bytes from remote server '%s'\n"
982 % (len(d2), server))
983 f.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000984 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000985 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000986 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +0000987 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000988 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000989 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +0000990 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991 server.join()
992
Antoine Pitrou91382d82010-04-28 21:39:56 +0000993 def test_asyncore_server(self):
994 """Check the example asyncore integration."""
995 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +0000996
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000997 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +0000998 sys.stdout.write("\n")
999
Antoine Pitrou91382d82010-04-28 21:39:56 +00001000 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001001 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001002 flag = threading.Event()
1003 server.start(flag)
1004 # wait for it to start
1005 flag.wait()
1006 # try to connect
1007 try:
1008 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001009 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001010 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001011 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +00001012 " client: sending %r...\n" % indata)
1013 s.write(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001014 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001015 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001016 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001017 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001018 self.fail(
Antoine Pitrou91382d82010-04-28 21:39:56 +00001019 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1020 % (outdata[:20], len(outdata),
1021 indata[:20].lower(), len(indata)))
1022 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001023 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001024 sys.stdout.write(" client: closing connection.\n")
1025 s.close()
1026 finally:
1027 server.stop()
1028 server.join()
1029
Antoine Pitrou91382d82010-04-28 21:39:56 +00001030 def test_recv_send(self):
1031 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001032 if support.verbose:
1033 sys.stdout.write("\n")
1034
1035 server = ThreadedEchoServer(CERTFILE,
1036 certreqs=ssl.CERT_NONE,
1037 ssl_version=ssl.PROTOCOL_TLSv1,
1038 cacerts=CERTFILE,
1039 chatty=True,
1040 connectionchatty=False)
1041 flag = threading.Event()
1042 server.start(flag)
1043 # wait for it to start
1044 flag.wait()
1045 # try to connect
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001046 s = ssl.wrap_socket(socket.socket(),
1047 server_side=False,
1048 certfile=CERTFILE,
1049 ca_certs=CERTFILE,
1050 cert_reqs=ssl.CERT_NONE,
1051 ssl_version=ssl.PROTOCOL_TLSv1)
1052 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001053 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001054 # helper methods for standardising recv* method signatures
1055 def _recv_into():
1056 b = bytearray(b"\0"*100)
1057 count = s.recv_into(b)
1058 return b[:count]
1059
1060 def _recvfrom_into():
1061 b = bytearray(b"\0"*100)
1062 count, addr = s.recvfrom_into(b)
1063 return b[:count]
1064
1065 # (name, method, whether to expect success, *args)
1066 send_methods = [
1067 ('send', s.send, True, []),
1068 ('sendto', s.sendto, False, ["some.address"]),
1069 ('sendall', s.sendall, True, []),
1070 ]
1071 recv_methods = [
1072 ('recv', s.recv, True, []),
1073 ('recvfrom', s.recvfrom, False, ["some.address"]),
1074 ('recv_into', _recv_into, True, []),
1075 ('recvfrom_into', _recvfrom_into, False, []),
1076 ]
1077 data_prefix = "PREFIX_"
1078
1079 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001080 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001081 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001082 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001083 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001084 if outdata != indata.lower():
1085 raise support.TestFailed(
1086 "While sending with <<{name:s}>> bad data "
Antoine Pitrou91382d82010-04-28 21:39:56 +00001087 "<<{outdata:r}>> ({nout:d}) received; "
1088 "expected <<{indata:r}>> ({nin:d})\n".format(
1089 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001090 nout=len(outdata),
Antoine Pitrou91382d82010-04-28 21:39:56 +00001091 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001092 )
1093 )
1094 except ValueError as e:
1095 if expect_success:
1096 raise support.TestFailed(
1097 "Failed to send with method <<{name:s}>>; "
1098 "expected to succeed.\n".format(name=meth_name)
1099 )
1100 if not str(e).startswith(meth_name):
1101 raise support.TestFailed(
1102 "Method <<{name:s}>> failed with unexpected "
1103 "exception message: {exp:s}\n".format(
1104 name=meth_name, exp=e
1105 )
1106 )
1107
1108 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001109 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001110 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001111 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001112 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001113 if outdata != indata.lower():
1114 raise support.TestFailed(
1115 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou91382d82010-04-28 21:39:56 +00001116 "<<{outdata:r}>> ({nout:d}) received; "
1117 "expected <<{indata:r}>> ({nin:d})\n".format(
1118 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001119 nout=len(outdata),
Antoine Pitrou91382d82010-04-28 21:39:56 +00001120 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001121 )
1122 )
1123 except ValueError as e:
1124 if expect_success:
1125 raise support.TestFailed(
1126 "Failed to receive with method <<{name:s}>>; "
1127 "expected to succeed.\n".format(name=meth_name)
1128 )
1129 if not str(e).startswith(meth_name):
1130 raise support.TestFailed(
1131 "Method <<{name:s}>> failed with unexpected "
1132 "exception message: {exp:s}\n".format(
1133 name=meth_name, exp=e
1134 )
1135 )
1136 # consume data
1137 s.read()
1138
Antoine Pitrou91382d82010-04-28 21:39:56 +00001139 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001140 s.close()
1141 finally:
1142 server.stop()
1143 server.join()
1144
Antoine Pitrouec146182010-04-24 21:30:20 +00001145 def test_handshake_timeout(self):
1146 # Issue #5103: SSL handshake must respect the socket timeout
1147 server = socket.socket(socket.AF_INET)
1148 host = "127.0.0.1"
1149 port = support.bind_port(server)
1150 started = threading.Event()
1151 finish = False
1152
1153 def serve():
1154 server.listen(5)
1155 started.set()
1156 conns = []
1157 while not finish:
1158 r, w, e = select.select([server], [], [], 0.1)
1159 if server in r:
1160 # Let the socket hang around rather than having
1161 # it closed by garbage collection.
1162 conns.append(server.accept()[0])
1163
1164 t = threading.Thread(target=serve)
1165 t.start()
1166 started.wait()
1167
1168 try:
Antoine Pitrouc2203f92010-04-24 22:07:51 +00001169 try:
1170 c = socket.socket(socket.AF_INET)
1171 c.settimeout(0.2)
1172 c.connect((host, port))
1173 # Will attempt handshake and time out
1174 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1175 ssl.wrap_socket, c)
1176 finally:
1177 c.close()
Antoine Pitrouec146182010-04-24 21:30:20 +00001178 try:
1179 c = socket.socket(socket.AF_INET)
1180 c = ssl.wrap_socket(c)
1181 c.settimeout(0.2)
1182 # Will attempt handshake and time out
1183 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1184 c.connect, (host, port))
1185 finally:
1186 c.close()
1187 finally:
1188 finish = True
1189 t.join()
1190 server.close()
1191
Bill Janssen58afe4c2008-09-08 16:45:19 +00001192
Thomas Woutersed03b412007-08-28 21:37:11 +00001193def test_main(verbose=False):
1194 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001195 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001196
Trent Nelson78520002008-04-10 20:54:35 +00001197 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Thomas Woutersed03b412007-08-28 21:37:11 +00001198 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
1199 "keycert.pem")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001200 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1201 os.path.dirname(__file__) or os.curdir,
1202 "https_svn_python_org_root.pem")
1203
1204 if (not os.path.exists(CERTFILE) or
1205 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001206 raise support.TestFailed("Can't read certificate files!")
Bill Janssen6e027db2007-11-15 22:23:56 +00001207
Thomas Woutersed03b412007-08-28 21:37:11 +00001208 tests = [BasicTests]
1209
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001210 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001211 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001212
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001213 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001214 thread_info = support.threading_setup()
1215 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001216 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001217
Antoine Pitrou91382d82010-04-28 21:39:56 +00001218 try:
1219 support.run_unittest(*tests)
1220 finally:
1221 if _have_threads:
1222 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001223
1224if __name__ == "__main__":
1225 test_main()