blob: 193978cb3d5bdcb2ff30b82d8c3b61aef1b684d1 [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):
Antoine Pitrou35544732010-08-14 17:26:19 +0000106 def setUp(self):
107 self.old_timeout = socket.getdefaulttimeout()
108 socket.setdefaulttimeout(30)
109
110 def tearDown(self):
111 socket.setdefaulttimeout(self.old_timeout)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000112
Antoine Pitrou91382d82010-04-28 21:39:56 +0000113 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
115 cert_reqs=ssl.CERT_NONE)
116 s.connect(("svn.python.org", 443))
117 c = s.getpeercert()
118 if c:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000119 self.fail("Peer cert %s shouldn't be here!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 s.close()
121
122 # this should fail because we have no verification certs
123 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
124 cert_reqs=ssl.CERT_REQUIRED)
Thomas Woutersed03b412007-08-28 21:37:11 +0000125 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000126 s.connect(("svn.python.org", 443))
127 except ssl.SSLError:
128 pass
129 finally:
130 s.close()
131
132 # this should succeed because we specify the root cert
133 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
134 cert_reqs=ssl.CERT_REQUIRED,
135 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
136 try:
137 s.connect(("svn.python.org", 443))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000138 finally:
139 s.close()
140
Antoine Pitroufe0f1172010-04-24 11:17:37 +0000141 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
142 def test_makefile_close(self):
143 # Issue #5238: creating a file-like object with makefile() shouldn't
144 # delay closing the underlying "real socket" (here tested with its
145 # file descriptor, hence skipping the test under Windows).
146 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
147 ss.connect(("svn.python.org", 443))
148 fd = ss.fileno()
149 f = ss.makefile()
150 f.close()
151 # The fd is still open
152 os.read(fd, 0)
153 # Closing the SSL socket should close the fd too
154 ss.close()
155 gc.collect()
156 try:
157 os.read(fd, 0)
158 except OSError as e:
159 self.assertEqual(e.errno, errno.EBADF)
160 else:
161 self.fail("OSError wasn't raised")
162
Antoine Pitrou91382d82010-04-28 21:39:56 +0000163 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000164 s = socket.socket(socket.AF_INET)
165 s.connect(("svn.python.org", 443))
166 s.setblocking(False)
167 s = ssl.wrap_socket(s,
168 cert_reqs=ssl.CERT_NONE,
169 do_handshake_on_connect=False)
170 count = 0
171 while True:
172 try:
173 count += 1
174 s.do_handshake()
175 break
176 except ssl.SSLError as err:
177 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
178 select.select([s], [], [])
179 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
180 select.select([], [s], [])
181 else:
182 raise
183 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000184 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000185 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000186
Antoine Pitrou91382d82010-04-28 21:39:56 +0000187 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000188 pem = ssl.get_server_certificate(("svn.python.org", 443))
189 if not pem:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000190 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000191
Bill Janssen54cc54c2007-12-14 22:08:56 +0000192 try:
193 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
194 except ssl.SSLError as x:
195 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000196 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000197 sys.stdout.write("%s\n" % x)
198 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000199 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000200
201 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
202 if not pem:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000203 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000204 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000205 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
206
Antoine Pitrou754b98c2010-04-22 18:47:06 +0000207 # Test disabled: OPENSSL_VERSION* not available in Python 3.1
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000208 def test_algorithms(self):
Antoine Pitrouae92a722010-04-22 18:46:16 +0000209 if support.verbose:
210 sys.stdout.write("test_algorithms disabled, "
211 "as it fails on some old OpenSSL versions")
212 return
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000213 # Issue #8484: all algorithms should be available when verifying a
214 # certificate.
Antoine Pitrouae92a722010-04-22 18:46:16 +0000215 # SHA256 was added in OpenSSL 0.9.8
216 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
217 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000218 # NOTE: https://sha256.tbs-internet.com is another possible test host
219 remote = ("sha2.hboeck.de", 443)
220 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
221 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
222 cert_reqs=ssl.CERT_REQUIRED,
223 ca_certs=sha256_cert,)
224 with support.transient_internet():
225 try:
226 s.connect(remote)
227 if support.verbose:
228 sys.stdout.write("\nCipher with %r is %r\n" %
229 (remote, s.cipher()))
230 sys.stdout.write("Certificate is:\n%s\n" %
231 pprint.pformat(s.getpeercert()))
232 finally:
233 s.close()
234
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000235
236try:
237 import threading
238except ImportError:
239 _have_threads = False
240else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000241 _have_threads = True
242
243 class ThreadedEchoServer(threading.Thread):
244
245 class ConnectionHandler(threading.Thread):
246
247 """A mildly complicated class, because we want it to work both
248 with and without the SSL wrapper around the socket connection, so
249 that we can test the STARTTLS functionality."""
250
Bill Janssen6e027db2007-11-15 22:23:56 +0000251 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000252 self.server = server
253 self.running = False
254 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000255 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000256 self.sock.setblocking(1)
257 self.sslconn = None
258 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000259 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000260
Antoine Pitrou91382d82010-04-28 21:39:56 +0000261 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000262 try:
263 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
264 certfile=self.server.certificate,
265 ssl_version=self.server.protocol,
266 ca_certs=self.server.cacerts,
267 cert_reqs=self.server.certreqs)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000268 except ssl.SSLError:
269 # XXX Various errors can have happened here, for example
270 # a mismatching protocol version, an invalid certificate,
271 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000272 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000273 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000274 self.running = False
275 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000276 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000277 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000278 else:
279 if self.server.certreqs == ssl.CERT_REQUIRED:
280 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000281 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000282 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
283 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000284 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000285 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
286 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000287 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000288 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
289 return True
290
291 def read(self):
292 if self.sslconn:
293 return self.sslconn.read()
294 else:
295 return self.sock.recv(1024)
296
297 def write(self, bytes):
298 if self.sslconn:
299 return self.sslconn.write(bytes)
300 else:
301 return self.sock.send(bytes)
302
303 def close(self):
304 if self.sslconn:
305 self.sslconn.close()
306 else:
307 self.sock.close()
308
Antoine Pitrou91382d82010-04-28 21:39:56 +0000309 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000310 self.running = True
311 if not self.server.starttls_server:
312 if not self.wrap_conn():
313 return
314 while self.running:
315 try:
316 msg = self.read()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000317 stripped = msg.strip()
318 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000319 # eof, so quit this handler
320 self.running = False
321 self.close()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000322 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000323 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000324 sys.stdout.write(" server: client closed connection\n")
325 self.close()
326 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000327 elif (self.server.starttls_server and
Antoine Pitroub1997962010-04-28 22:58:16 +0000328 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000329 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000330 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000331 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000332 if not self.wrap_conn():
333 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000334 elif (self.server.starttls_server and self.sslconn
Antoine Pitroub1997962010-04-28 22:58:16 +0000335 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000336 if support.verbose and self.server.connectionchatty:
337 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000338 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000339 self.sock = self.sslconn.unwrap()
340 self.sslconn = None
341 if support.verbose and self.server.connectionchatty:
342 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000343 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000344 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000345 self.server.connectionchatty):
346 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou91382d82010-04-28 21:39:56 +0000347 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
348 % (msg, ctype, msg.lower(), ctype))
349 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000350 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000351 if self.server.chatty:
352 handle_error("Test server failure:\n")
353 self.close()
354 self.running = False
355 # normally, we'd just stop here, but for the test
356 # harness, we want to stop the server
357 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000358
Trent Nelson78520002008-04-10 20:54:35 +0000359 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000360 certreqs=None, cacerts=None,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000361 chatty=True, connectionchatty=False, starttls_server=False):
362 if ssl_version is None:
363 ssl_version = ssl.PROTOCOL_TLSv1
364 if certreqs is None:
365 certreqs = ssl.CERT_NONE
366 self.certificate = certificate
367 self.protocol = ssl_version
368 self.certreqs = certreqs
369 self.cacerts = cacerts
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000370 self.chatty = chatty
371 self.connectionchatty = connectionchatty
372 self.starttls_server = starttls_server
373 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000374 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000375 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000376 self.active = False
377 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000378 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000379
Antoine Pitrou91382d82010-04-28 21:39:56 +0000380 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000381 self.flag = flag
382 threading.Thread.start(self)
383
Antoine Pitrou91382d82010-04-28 21:39:56 +0000384 def run(self):
Antoine Pitroube168132010-04-27 10:41:37 +0000385 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000386 self.sock.listen(5)
387 self.active = True
388 if self.flag:
389 # signal an event
390 self.flag.set()
391 while self.active:
392 try:
393 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000394 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000395 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000396 + repr(connaddr) + '\n')
397 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000398 handler.start()
399 except socket.timeout:
400 pass
401 except KeyboardInterrupt:
402 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000403 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000404
Antoine Pitrou91382d82010-04-28 21:39:56 +0000405 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000406 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000407
Bill Janssen54cc54c2007-12-14 22:08:56 +0000408 class OurHTTPSServer(threading.Thread):
409
410 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000411
412 class HTTPSServer(HTTPServer):
413
414 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000415 HTTPServer.__init__(self, server_address, RequestHandlerClass)
416 # we assume the certfile contains both private key and certificate
417 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000418 self.allow_reuse_address = True
419
Bill Janssen6e027db2007-11-15 22:23:56 +0000420 def __str__(self):
421 return ('<%s %s:%s>' %
422 (self.__class__.__name__,
423 self.server_name,
424 self.server_port))
425
Antoine Pitrou91382d82010-04-28 21:39:56 +0000426 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000427 # override this to wrap socket with SSL
428 sock, addr = self.socket.accept()
429 sslconn = ssl.wrap_socket(sock, server_side=True,
430 certfile=self.certfile)
431 return sslconn, addr
432
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000433 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000434 # need to override translate_path to get a known root,
435 # instead of using os.curdir, since the test could be
436 # run from anywhere
437
438 server_version = "TestHTTPS/1.0"
439
440 root = None
441
442 def translate_path(self, path):
443 """Translate a /-separated PATH to the local filename syntax.
444
445 Components that mean special things to the local file system
446 (e.g. drive or directory names) are ignored. (XXX They should
447 probably be diagnosed.)
448
449 """
450 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000451 path = urllib.parse.urlparse(path)[2]
452 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000453 words = path.split('/')
454 words = filter(None, words)
455 path = self.root
456 for word in words:
457 drive, word = os.path.splitdrive(word)
458 head, word = os.path.split(word)
459 if word in self.root: continue
460 path = os.path.join(path, word)
461 return path
462
463 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000464 # we override this to suppress logging unless "verbose"
465
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000466 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000467 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
468 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000469 self.server.server_port,
470 self.request.cipher(),
471 self.log_date_time_string(),
472 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000473
474
Trent Nelson78520002008-04-10 20:54:35 +0000475 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000476 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000477 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
478 self.server = self.HTTPSServer(
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000479 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
480 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000481 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000482 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000483
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000484 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000485 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000486
Antoine Pitrou91382d82010-04-28 21:39:56 +0000487 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000488 self.flag = flag
489 threading.Thread.start(self)
490
Antoine Pitrou91382d82010-04-28 21:39:56 +0000491 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000492 if self.flag:
493 self.flag.set()
Antoine Pitroube168132010-04-27 10:41:37 +0000494 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000495
Antoine Pitrou91382d82010-04-28 21:39:56 +0000496 def stop(self):
Antoine Pitroube168132010-04-27 10:41:37 +0000497 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000498
499
Bill Janssen54cc54c2007-12-14 22:08:56 +0000500 class AsyncoreEchoServer(threading.Thread):
501
502 # this one's based on asyncore.dispatcher
503
504 class EchoServer (asyncore.dispatcher):
505
506 class ConnectionHandler (asyncore.dispatcher_with_send):
507
508 def __init__(self, conn, certfile):
509 self.socket = ssl.wrap_socket(conn, server_side=True,
510 certfile=certfile,
511 do_handshake_on_connect=False)
512 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitrouec146182010-04-24 21:30:20 +0000513 self._ssl_accepting = True
514 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000515
516 def readable(self):
517 if isinstance(self.socket, ssl.SSLSocket):
518 while self.socket.pending() > 0:
519 self.handle_read_event()
520 return True
521
Antoine Pitrouec146182010-04-24 21:30:20 +0000522 def _do_ssl_handshake(self):
523 try:
524 self.socket.do_handshake()
525 except ssl.SSLError as err:
526 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
527 ssl.SSL_ERROR_WANT_WRITE):
528 return
529 elif err.args[0] == ssl.SSL_ERROR_EOF:
530 return self.handle_close()
531 raise
532 except socket.error as err:
533 if err.args[0] == errno.ECONNABORTED:
534 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000535 else:
Antoine Pitrouec146182010-04-24 21:30:20 +0000536 self._ssl_accepting = False
537
538 def handle_read(self):
539 if self._ssl_accepting:
540 self._do_ssl_handshake()
541 else:
542 data = self.recv(1024)
543 if support.verbose:
544 sys.stdout.write(" server: read %s from client\n" % repr(data))
545 if not data:
546 self.close()
547 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000548 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000549
550 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000551 self.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000552 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000553 sys.stdout.write(" server: closed connection %s\n" % self.socket)
554
555 def handle_error(self):
556 raise
557
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000558 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000559 self.certfile = certfile
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000560 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
561 self.port = support.bind_port(sock, '')
562 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000563 self.listen(5)
564
565 def handle_accept(self):
566 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000567 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000568 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
569 self.ConnectionHandler(sock_obj, self.certfile)
570
571 def handle_error(self):
572 raise
573
Trent Nelson78520002008-04-10 20:54:35 +0000574 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000575 self.flag = None
576 self.active = False
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000577 self.server = self.EchoServer(certfile)
578 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000579 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000580 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000581
582 def __str__(self):
583 return "<%s %s>" % (self.__class__.__name__, self.server)
584
585 def start (self, flag=None):
586 self.flag = flag
587 threading.Thread.start(self)
588
Antoine Pitrou91382d82010-04-28 21:39:56 +0000589 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000590 self.active = True
591 if self.flag:
592 self.flag.set()
593 while self.active:
594 try:
595 asyncore.loop(1)
596 except:
597 pass
598
Antoine Pitrou91382d82010-04-28 21:39:56 +0000599 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000600 self.active = False
601 self.server.close()
602
Antoine Pitrou91382d82010-04-28 21:39:56 +0000603 def bad_cert_test(certfile):
604 """
605 Launch a server with CERT_REQUIRED, and check that trying to
606 connect to it with the given client certificate fails.
607 """
Trent Nelson78520002008-04-10 20:54:35 +0000608 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000609 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000610 cacerts=CERTFILE, chatty=False,
611 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000612 flag = threading.Event()
613 server.start(flag)
614 # wait for it to start
615 flag.wait()
616 # try to connect
617 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000618 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000619 s = ssl.wrap_socket(socket.socket(),
620 certfile=certfile,
621 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000622 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000623 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000624 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000625 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou537bed62010-04-27 13:16:06 +0000626 except socket.error as x:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000627 if support.verbose:
Antoine Pitrou537bed62010-04-27 13:16:06 +0000628 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000629 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000630 self.fail("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000631 finally:
632 server.stop()
633 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000634
Antoine Pitrou91382d82010-04-28 21:39:56 +0000635 def server_params_test(certfile, protocol, certreqs, cacertsfile,
636 client_certfile, client_protocol=None, indata=b"FOO\n",
637 chatty=True, connectionchatty=False):
638 """
639 Launch a server, connect a client to it and try various reads
640 and writes.
641 """
Trent Nelson78520002008-04-10 20:54:35 +0000642 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000643 certreqs=certreqs,
644 ssl_version=protocol,
645 cacerts=cacertsfile,
646 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000647 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000648 flag = threading.Event()
649 server.start(flag)
650 # wait for it to start
651 flag.wait()
652 # try to connect
653 if client_protocol is None:
654 client_protocol = protocol
655 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000656 s = ssl.wrap_socket(socket.socket(),
657 certfile=client_certfile,
658 ca_certs=cacertsfile,
659 cert_reqs=certreqs,
660 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000661 s.connect((HOST, server.port))
Antoine Pitrou91382d82010-04-28 21:39:56 +0000662 arg = indata
Bill Janssen6e027db2007-11-15 22:23:56 +0000663 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000664 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000665 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000666 " client: sending %r...\n" % indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000667 s.write(arg)
Bill Janssen6e027db2007-11-15 22:23:56 +0000668 outdata = s.read()
669 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000670 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000671 sys.stdout.write(" client: read %r\n" % outdata)
Bill Janssen6e027db2007-11-15 22:23:56 +0000672 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000673 self.fail(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000674 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
675 % (outdata[:20], len(outdata),
676 indata[:20].lower(), len(indata)))
677 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000678 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000679 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000680 sys.stdout.write(" client: closing connection.\n")
681 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000682 finally:
683 server.stop()
684 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000685
Antoine Pitrou91382d82010-04-28 21:39:56 +0000686 def try_protocol_combo(server_protocol,
687 client_protocol,
688 expect_success,
689 certsreqs=None):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000690 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000691 certsreqs = ssl.CERT_NONE
Antoine Pitrou91382d82010-04-28 21:39:56 +0000692 certtype = {
693 ssl.CERT_NONE: "CERT_NONE",
694 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
695 ssl.CERT_REQUIRED: "CERT_REQUIRED",
696 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000697 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000698 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000699 sys.stdout.write(formatstr %
700 (ssl.get_protocol_name(client_protocol),
701 ssl.get_protocol_name(server_protocol),
702 certtype))
703 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000704 server_params_test(CERTFILE, server_protocol, certsreqs,
705 CERTFILE, CERTFILE, client_protocol,
706 chatty=False,
707 connectionchatty=False)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000708 # Protocol mismatch can result in either an SSLError, or a
709 # "Connection reset by peer" error.
710 except ssl.SSLError:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000711 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000712 raise
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000713 except socket.error as e:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000714 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000715 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000716 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000717 if not expect_success:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000718 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000719 "Client protocol %s succeeded with server protocol %s!"
720 % (ssl.get_protocol_name(client_protocol),
721 ssl.get_protocol_name(server_protocol)))
722
723
Bill Janssen6e027db2007-11-15 22:23:56 +0000724 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000725
Antoine Pitrou91382d82010-04-28 21:39:56 +0000726 def test_echo(self):
727 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000728 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000729 sys.stdout.write("\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000730 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
731 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
732 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000733
Antoine Pitrou91382d82010-04-28 21:39:56 +0000734 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000735 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000736 sys.stdout.write("\n")
737 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000738 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 certreqs=ssl.CERT_NONE,
740 ssl_version=ssl.PROTOCOL_SSLv23,
741 cacerts=CERTFILE,
742 chatty=False)
743 flag = threading.Event()
744 server.start(flag)
745 # wait for it to start
746 flag.wait()
747 # try to connect
748 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000749 s = ssl.wrap_socket(socket.socket(),
750 certfile=CERTFILE,
751 ca_certs=CERTFILE,
752 cert_reqs=ssl.CERT_REQUIRED,
753 ssl_version=ssl.PROTOCOL_SSLv23)
754 s.connect((HOST, server.port))
755 cert = s.getpeercert()
756 self.assertTrue(cert, "Can't get peer certificate.")
757 cipher = s.cipher()
758 if support.verbose:
759 sys.stdout.write(pprint.pformat(cert) + '\n')
760 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
761 if 'subject' not in cert:
762 self.fail("No subject field in certificate: %s." %
763 pprint.pformat(cert))
764 if ((('organizationName', 'Python Software Foundation'),)
765 not in cert['subject']):
766 self.fail(
767 "Missing or invalid 'organizationName' field in certificate subject; "
768 "should be 'Python Software Foundation'.")
769 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000770 finally:
771 server.stop()
772 server.join()
773
Antoine Pitrou91382d82010-04-28 21:39:56 +0000774 def test_empty_cert(self):
775 """Connecting with an empty cert file"""
776 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
777 "nullcert.pem"))
778 def test_malformed_cert(self):
779 """Connecting with a badly formatted certificate (syntax error)"""
780 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
781 "badcert.pem"))
782 def test_nonexisting_cert(self):
783 """Connecting with a non-existing cert file"""
784 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
785 "wrongcert.pem"))
786 def test_malformed_key(self):
787 """Connecting with a badly formatted key (syntax error)"""
788 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
789 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000790
Antoine Pitrou91382d82010-04-28 21:39:56 +0000791 def test_rude_shutdown(self):
792 """A brutal shutdown of an SSL server should raise an IOError
793 in the client when attempting handshake.
794 """
Trent Nelson6b240cd2008-04-10 20:12:06 +0000795 listener_ready = threading.Event()
796 listener_gone = threading.Event()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000797
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000798 s = socket.socket()
799 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000800
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000801 # `listener` runs in a thread. It sits in an accept() until
802 # the main thread connects. Then it rudely closes the socket,
803 # and sets Event `listener_gone` to let the main thread know
804 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000805 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000806 s.listen(5)
807 listener_ready.set()
808 s.accept()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000809 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000810 listener_gone.set()
811
812 def connector():
813 listener_ready.wait()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000814 c = socket.socket()
815 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000816 listener_gone.wait()
817 try:
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000818 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000819 except IOError:
820 pass
821 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000822 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +0000823
824 t = threading.Thread(target=listener)
825 t.start()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000826 try:
827 connector()
828 finally:
829 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000830
Antoine Pitrou91382d82010-04-28 21:39:56 +0000831 def test_protocol_sslv2(self):
832 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000833 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000834 sys.stdout.write("\ntest_protocol_sslv2 disabled, "
835 "as it fails on OpenSSL 1.0.0+")
836 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000837 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
838 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
839 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
840 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
841 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
842 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000843
Antoine Pitrou91382d82010-04-28 21:39:56 +0000844 def test_protocol_sslv23(self):
845 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000846 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000847 sys.stdout.write("\ntest_protocol_sslv23 disabled, "
848 "as it fails on OpenSSL 1.0.0+")
849 return
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000850 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000851 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000852 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000853 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000854 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000855 sys.stdout.write(
856 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
857 % str(x))
Antoine Pitrou91382d82010-04-28 21:39:56 +0000858 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
859 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
860 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
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_OPTIONAL)
863 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
864 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865
Antoine Pitrou91382d82010-04-28 21:39:56 +0000866 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
867 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
868 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000869
Antoine Pitrou91382d82010-04-28 21:39:56 +0000870 def test_protocol_sslv3(self):
871 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000872 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000873 sys.stdout.write("\ntest_protocol_sslv3 disabled, "
874 "as it fails on OpenSSL 1.0.0+")
875 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000876 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
877 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
878 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
879 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
880 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
881 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000882
Antoine Pitrou91382d82010-04-28 21:39:56 +0000883 def test_protocol_tlsv1(self):
884 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000885 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000886 sys.stdout.write("\ntest_protocol_tlsv1 disabled, "
887 "as it fails on OpenSSL 1.0.0+")
888 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000889 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
890 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
891 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
892 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
893 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
894 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895
Antoine Pitrou91382d82010-04-28 21:39:56 +0000896 def test_starttls(self):
897 """Switching from clear text to encrypted and back again."""
898 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 +0000899
Trent Nelson78520002008-04-10 20:54:35 +0000900 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000901 ssl_version=ssl.PROTOCOL_TLSv1,
902 starttls_server=True,
903 chatty=True,
904 connectionchatty=True)
905 flag = threading.Event()
906 server.start(flag)
907 # wait for it to start
908 flag.wait()
909 # try to connect
910 wrapped = False
911 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000912 s = socket.socket()
913 s.setblocking(1)
914 s.connect((HOST, server.port))
915 if support.verbose:
916 sys.stdout.write("\n")
917 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000918 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000919 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000920 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000921 if wrapped:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000922 conn.write(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000923 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000924 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000925 s.send(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000926 outdata = s.recv(1024)
Antoine Pitrou91382d82010-04-28 21:39:56 +0000927 msg = outdata.strip().lower()
928 if indata == b"STARTTLS" and msg.startswith(b"ok"):
929 # STARTTLS ok, switch to secure mode
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000930 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000931 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000932 " client: read %r from server, starting TLS...\n"
933 % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000934 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
935 wrapped = True
Antoine Pitrou91382d82010-04-28 21:39:56 +0000936 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
937 # ENDTLS ok, switch back to clear text
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000938 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000939 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000940 " client: read %r from server, ending TLS...\n"
941 % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000942 s = conn.unwrap()
943 wrapped = False
944 else:
945 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000946 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000947 " client: read %r from server\n" % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000948 if support.verbose:
949 sys.stdout.write(" client: closing connection.\n")
950 if wrapped:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000951 conn.write(b"over\n")
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000952 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000953 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000954 if wrapped:
955 conn.close()
956 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000957 s.close()
958 finally:
959 server.stop()
960 server.join()
961
Antoine Pitrou91382d82010-04-28 21:39:56 +0000962 def test_socketserver(self):
963 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +0000964 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000965 flag = threading.Event()
966 server.start(flag)
967 # wait for it to start
968 flag.wait()
969 # try to connect
970 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000971 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000972 sys.stdout.write('\n')
Antoine Pitrou91382d82010-04-28 21:39:56 +0000973 with open(CERTFILE, 'rb') as f:
974 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000975 d2 = ''
976 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +0000977 url = 'https://%s:%d/%s' % (
978 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000979 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +0000980 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 if dlen and (int(dlen) > 0):
982 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000983 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984 sys.stdout.write(
985 " client: read %d bytes from remote server '%s'\n"
986 % (len(d2), server))
987 f.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000988 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000989 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000990 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +0000991 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000992 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000993 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +0000994 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000995 server.join()
996
Antoine Pitrou91382d82010-04-28 21:39:56 +0000997 def test_asyncore_server(self):
998 """Check the example asyncore integration."""
999 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001000
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001001 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001002 sys.stdout.write("\n")
1003
Antoine Pitrou91382d82010-04-28 21:39:56 +00001004 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001005 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001006 flag = threading.Event()
1007 server.start(flag)
1008 # wait for it to start
1009 flag.wait()
1010 # try to connect
1011 try:
1012 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001013 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001014 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001015 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +00001016 " client: sending %r...\n" % indata)
1017 s.write(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001018 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001019 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001020 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001021 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001022 self.fail(
Antoine Pitrou91382d82010-04-28 21:39:56 +00001023 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1024 % (outdata[:20], len(outdata),
1025 indata[:20].lower(), len(indata)))
1026 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001027 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001028 sys.stdout.write(" client: closing connection.\n")
1029 s.close()
1030 finally:
1031 server.stop()
1032 server.join()
1033
Antoine Pitrou91382d82010-04-28 21:39:56 +00001034 def test_recv_send(self):
1035 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001036 if support.verbose:
1037 sys.stdout.write("\n")
1038
1039 server = ThreadedEchoServer(CERTFILE,
1040 certreqs=ssl.CERT_NONE,
1041 ssl_version=ssl.PROTOCOL_TLSv1,
1042 cacerts=CERTFILE,
1043 chatty=True,
1044 connectionchatty=False)
1045 flag = threading.Event()
1046 server.start(flag)
1047 # wait for it to start
1048 flag.wait()
1049 # try to connect
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001050 s = ssl.wrap_socket(socket.socket(),
1051 server_side=False,
1052 certfile=CERTFILE,
1053 ca_certs=CERTFILE,
1054 cert_reqs=ssl.CERT_NONE,
1055 ssl_version=ssl.PROTOCOL_TLSv1)
1056 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001057 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001058 # helper methods for standardising recv* method signatures
1059 def _recv_into():
1060 b = bytearray(b"\0"*100)
1061 count = s.recv_into(b)
1062 return b[:count]
1063
1064 def _recvfrom_into():
1065 b = bytearray(b"\0"*100)
1066 count, addr = s.recvfrom_into(b)
1067 return b[:count]
1068
1069 # (name, method, whether to expect success, *args)
1070 send_methods = [
1071 ('send', s.send, True, []),
1072 ('sendto', s.sendto, False, ["some.address"]),
1073 ('sendall', s.sendall, True, []),
1074 ]
1075 recv_methods = [
1076 ('recv', s.recv, True, []),
1077 ('recvfrom', s.recvfrom, False, ["some.address"]),
1078 ('recv_into', _recv_into, True, []),
1079 ('recvfrom_into', _recvfrom_into, False, []),
1080 ]
1081 data_prefix = "PREFIX_"
1082
1083 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001084 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001085 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001086 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001087 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001088 if outdata != indata.lower():
1089 raise support.TestFailed(
1090 "While sending with <<{name:s}>> bad data "
Antoine Pitrou91382d82010-04-28 21:39:56 +00001091 "<<{outdata:r}>> ({nout:d}) received; "
1092 "expected <<{indata:r}>> ({nin:d})\n".format(
1093 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001094 nout=len(outdata),
Antoine Pitrou91382d82010-04-28 21:39:56 +00001095 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001096 )
1097 )
1098 except ValueError as e:
1099 if expect_success:
1100 raise support.TestFailed(
1101 "Failed to send with method <<{name:s}>>; "
1102 "expected to succeed.\n".format(name=meth_name)
1103 )
1104 if not str(e).startswith(meth_name):
1105 raise support.TestFailed(
1106 "Method <<{name:s}>> failed with unexpected "
1107 "exception message: {exp:s}\n".format(
1108 name=meth_name, exp=e
1109 )
1110 )
1111
1112 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001113 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001114 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001115 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001116 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001117 if outdata != indata.lower():
1118 raise support.TestFailed(
1119 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou91382d82010-04-28 21:39:56 +00001120 "<<{outdata:r}>> ({nout:d}) received; "
1121 "expected <<{indata:r}>> ({nin:d})\n".format(
1122 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001123 nout=len(outdata),
Antoine Pitrou91382d82010-04-28 21:39:56 +00001124 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001125 )
1126 )
1127 except ValueError as e:
1128 if expect_success:
1129 raise support.TestFailed(
1130 "Failed to receive with method <<{name:s}>>; "
1131 "expected to succeed.\n".format(name=meth_name)
1132 )
1133 if not str(e).startswith(meth_name):
1134 raise support.TestFailed(
1135 "Method <<{name:s}>> failed with unexpected "
1136 "exception message: {exp:s}\n".format(
1137 name=meth_name, exp=e
1138 )
1139 )
1140 # consume data
1141 s.read()
1142
Antoine Pitrou91382d82010-04-28 21:39:56 +00001143 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001144 s.close()
1145 finally:
1146 server.stop()
1147 server.join()
1148
Antoine Pitrouec146182010-04-24 21:30:20 +00001149 def test_handshake_timeout(self):
1150 # Issue #5103: SSL handshake must respect the socket timeout
1151 server = socket.socket(socket.AF_INET)
1152 host = "127.0.0.1"
1153 port = support.bind_port(server)
1154 started = threading.Event()
1155 finish = False
1156
1157 def serve():
1158 server.listen(5)
1159 started.set()
1160 conns = []
1161 while not finish:
1162 r, w, e = select.select([server], [], [], 0.1)
1163 if server in r:
1164 # Let the socket hang around rather than having
1165 # it closed by garbage collection.
1166 conns.append(server.accept()[0])
1167
1168 t = threading.Thread(target=serve)
1169 t.start()
1170 started.wait()
1171
1172 try:
Antoine Pitrouc2203f92010-04-24 22:07:51 +00001173 try:
1174 c = socket.socket(socket.AF_INET)
1175 c.settimeout(0.2)
1176 c.connect((host, port))
1177 # Will attempt handshake and time out
1178 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1179 ssl.wrap_socket, c)
1180 finally:
1181 c.close()
Antoine Pitrouec146182010-04-24 21:30:20 +00001182 try:
1183 c = socket.socket(socket.AF_INET)
1184 c = ssl.wrap_socket(c)
1185 c.settimeout(0.2)
1186 # Will attempt handshake and time out
1187 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1188 c.connect, (host, port))
1189 finally:
1190 c.close()
1191 finally:
1192 finish = True
1193 t.join()
1194 server.close()
1195
Bill Janssen58afe4c2008-09-08 16:45:19 +00001196
Thomas Woutersed03b412007-08-28 21:37:11 +00001197def test_main(verbose=False):
1198 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001199 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001200
Trent Nelson78520002008-04-10 20:54:35 +00001201 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Thomas Woutersed03b412007-08-28 21:37:11 +00001202 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
1203 "keycert.pem")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001204 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1205 os.path.dirname(__file__) or os.curdir,
1206 "https_svn_python_org_root.pem")
1207
1208 if (not os.path.exists(CERTFILE) or
1209 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001210 raise support.TestFailed("Can't read certificate files!")
Bill Janssen6e027db2007-11-15 22:23:56 +00001211
Thomas Woutersed03b412007-08-28 21:37:11 +00001212 tests = [BasicTests]
1213
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001214 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001215 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001216
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001217 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001218 thread_info = support.threading_setup()
1219 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001220 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001221
Antoine Pitrou91382d82010-04-28 21:39:56 +00001222 try:
1223 support.run_unittest(*tests)
1224 finally:
1225 if _have_threads:
1226 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001227
1228if __name__ == "__main__":
1229 test_main()