blob: d76472a0fe884276b3c95f0a1c008774c003e3c1 [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_connect(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000043 if not support.is_resource_enabled('network'):
Georg Brandlfceab5a2008-01-19 20:08:23 +000044 return
45 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
46 cert_reqs=ssl.CERT_NONE)
47 s.connect(("svn.python.org", 443))
48 c = s.getpeercert()
49 if c:
Antoine Pitrou66ffb262010-04-27 11:05:15 +000050 self.fail("Peer cert %s shouldn't be here!")
Georg Brandlfceab5a2008-01-19 20:08:23 +000051 s.close()
52
53 # this should fail because we have no verification certs
54 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
55 cert_reqs=ssl.CERT_REQUIRED)
56 try:
57 s.connect(("svn.python.org", 443))
58 except ssl.SSLError:
59 pass
60 finally:
61 s.close()
62
Antoine Pitrou91382d82010-04-28 21:39:56 +000063 def test_constants(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000064 ssl.PROTOCOL_SSLv2
65 ssl.PROTOCOL_SSLv23
66 ssl.PROTOCOL_SSLv3
67 ssl.PROTOCOL_TLSv1
68 ssl.CERT_NONE
69 ssl.CERT_OPTIONAL
70 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000071
Antoine Pitrou91382d82010-04-28 21:39:56 +000072 def test_random(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000073 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000074 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000075 sys.stdout.write("\n RAND_status is %d (%s)\n"
76 % (v, (v and "sufficient randomness") or
77 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000078 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000079 ssl.RAND_egd(1)
80 except TypeError:
81 pass
Thomas Woutersed03b412007-08-28 21:37:11 +000082 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000083 print("didn't raise TypeError")
84 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +000085
Antoine Pitrou91382d82010-04-28 21:39:56 +000086 def test_parse_cert(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000087 # note that this uses an 'unofficial' function in _ssl.c,
88 # provided solely for this test, to exercise the certificate
89 # parsing code
90 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000091 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000092 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +000093
Antoine Pitrou91382d82010-04-28 21:39:56 +000094 def test_DER_to_PEM(self):
95 with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
96 pem = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +000097 d1 = ssl.PEM_cert_to_DER_cert(pem)
98 p2 = ssl.DER_cert_to_PEM_cert(d1)
99 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000100 self.assertEqual(d1, d2)
Antoine Pitrou00f905e2010-04-27 22:09:05 +0000101 if not p2.startswith(ssl.PEM_HEADER + '\n'):
102 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
103 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
104 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105
Antoine Pitrou78f4a9a2010-04-23 23:12:22 +0000106 @support.cpython_only
107 def test_refcycle(self):
108 # Issue #7943: an SSL object doesn't create reference cycles with
109 # itself.
110 s = socket.socket(socket.AF_INET)
111 ss = ssl.wrap_socket(s)
112 wr = weakref.ref(ss)
113 del ss
114 self.assertEqual(wr(), None)
115
Antoine Pitrouc2203f92010-04-24 22:07:51 +0000116 def test_timeout(self):
117 # Issue #8524: when creating an SSL socket, the timeout of the
118 # original socket should be retained.
119 for timeout in (None, 0.0, 5.0):
120 s = socket.socket(socket.AF_INET)
121 s.settimeout(timeout)
122 ss = ssl.wrap_socket(s)
123 self.assertEqual(timeout, ss.gettimeout())
124
Antoine Pitrou3b9b9ba2010-04-23 23:33:50 +0000125
Bill Janssen6e027db2007-11-15 22:23:56 +0000126class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000127
Antoine Pitrou91382d82010-04-28 21:39:56 +0000128 def test_connect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
130 cert_reqs=ssl.CERT_NONE)
131 s.connect(("svn.python.org", 443))
132 c = s.getpeercert()
133 if c:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000134 self.fail("Peer cert %s shouldn't be here!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000135 s.close()
136
137 # this should fail because we have no verification certs
138 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
139 cert_reqs=ssl.CERT_REQUIRED)
Thomas Woutersed03b412007-08-28 21:37:11 +0000140 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000141 s.connect(("svn.python.org", 443))
142 except ssl.SSLError:
143 pass
144 finally:
145 s.close()
146
147 # this should succeed because we specify the root cert
148 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
149 cert_reqs=ssl.CERT_REQUIRED,
150 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
151 try:
152 s.connect(("svn.python.org", 443))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000153 finally:
154 s.close()
155
Antoine Pitroufe0f1172010-04-24 11:17:37 +0000156 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
157 def test_makefile_close(self):
158 # Issue #5238: creating a file-like object with makefile() shouldn't
159 # delay closing the underlying "real socket" (here tested with its
160 # file descriptor, hence skipping the test under Windows).
161 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
162 ss.connect(("svn.python.org", 443))
163 fd = ss.fileno()
164 f = ss.makefile()
165 f.close()
166 # The fd is still open
167 os.read(fd, 0)
168 # Closing the SSL socket should close the fd too
169 ss.close()
170 gc.collect()
171 try:
172 os.read(fd, 0)
173 except OSError as e:
174 self.assertEqual(e.errno, errno.EBADF)
175 else:
176 self.fail("OSError wasn't raised")
177
Antoine Pitrou91382d82010-04-28 21:39:56 +0000178 def test_non_blocking_handshake(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000179 s = socket.socket(socket.AF_INET)
180 s.connect(("svn.python.org", 443))
181 s.setblocking(False)
182 s = ssl.wrap_socket(s,
183 cert_reqs=ssl.CERT_NONE,
184 do_handshake_on_connect=False)
185 count = 0
186 while True:
187 try:
188 count += 1
189 s.do_handshake()
190 break
191 except ssl.SSLError as err:
192 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
193 select.select([s], [], [])
194 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
195 select.select([], [s], [])
196 else:
197 raise
198 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000199 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000200 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000201
Antoine Pitrou91382d82010-04-28 21:39:56 +0000202 def test_get_server_certificate(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000203 pem = ssl.get_server_certificate(("svn.python.org", 443))
204 if not pem:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000205 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000206
207 return
208
209 try:
210 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
211 except ssl.SSLError as x:
212 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000213 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000214 sys.stdout.write("%s\n" % x)
215 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000216 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000217
218 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
219 if not pem:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000220 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000221 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000222 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
223
Antoine Pitrou754b98c2010-04-22 18:47:06 +0000224 # Test disabled: OPENSSL_VERSION* not available in Python 3.1
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000225 def test_algorithms(self):
Antoine Pitrouae92a722010-04-22 18:46:16 +0000226 if support.verbose:
227 sys.stdout.write("test_algorithms disabled, "
228 "as it fails on some old OpenSSL versions")
229 return
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000230 # Issue #8484: all algorithms should be available when verifying a
231 # certificate.
Antoine Pitrouae92a722010-04-22 18:46:16 +0000232 # SHA256 was added in OpenSSL 0.9.8
233 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
234 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000235 # NOTE: https://sha256.tbs-internet.com is another possible test host
236 remote = ("sha2.hboeck.de", 443)
237 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
238 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
239 cert_reqs=ssl.CERT_REQUIRED,
240 ca_certs=sha256_cert,)
241 with support.transient_internet():
242 try:
243 s.connect(remote)
244 if support.verbose:
245 sys.stdout.write("\nCipher with %r is %r\n" %
246 (remote, s.cipher()))
247 sys.stdout.write("Certificate is:\n%s\n" %
248 pprint.pformat(s.getpeercert()))
249 finally:
250 s.close()
251
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000252
253try:
254 import threading
255except ImportError:
256 _have_threads = False
257else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000258 _have_threads = True
259
260 class ThreadedEchoServer(threading.Thread):
261
262 class ConnectionHandler(threading.Thread):
263
264 """A mildly complicated class, because we want it to work both
265 with and without the SSL wrapper around the socket connection, so
266 that we can test the STARTTLS functionality."""
267
Bill Janssen6e027db2007-11-15 22:23:56 +0000268 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000269 self.server = server
270 self.running = False
271 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000272 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000273 self.sock.setblocking(1)
274 self.sslconn = None
275 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000276 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000277
Antoine Pitrou91382d82010-04-28 21:39:56 +0000278 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000279 try:
280 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
281 certfile=self.server.certificate,
282 ssl_version=self.server.protocol,
283 ca_certs=self.server.cacerts,
284 cert_reqs=self.server.certreqs)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000285 except ssl.SSLError:
286 # XXX Various errors can have happened here, for example
287 # a mismatching protocol version, an invalid certificate,
288 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000289 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000290 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000291 self.running = False
292 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000293 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000294 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000295 else:
296 if self.server.certreqs == ssl.CERT_REQUIRED:
297 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000298 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000299 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
300 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000301 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000302 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
303 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000304 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000305 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
306 return True
307
308 def read(self):
309 if self.sslconn:
310 return self.sslconn.read()
311 else:
312 return self.sock.recv(1024)
313
314 def write(self, bytes):
315 if self.sslconn:
316 return self.sslconn.write(bytes)
317 else:
318 return self.sock.send(bytes)
319
320 def close(self):
321 if self.sslconn:
322 self.sslconn.close()
323 else:
324 self.sock.close()
325
Antoine Pitrou91382d82010-04-28 21:39:56 +0000326 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000327 self.running = True
328 if not self.server.starttls_server:
329 if not self.wrap_conn():
330 return
331 while self.running:
332 try:
333 msg = self.read()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000334 stripped = msg.strip()
335 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000336 # eof, so quit this handler
337 self.running = False
338 self.close()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000339 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000340 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000341 sys.stdout.write(" server: client closed connection\n")
342 self.close()
343 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000344 elif (self.server.starttls_server and
Antoine Pitroub1997962010-04-28 22:58:16 +0000345 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000346 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000347 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000348 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000349 if not self.wrap_conn():
350 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000351 elif (self.server.starttls_server and self.sslconn
Antoine Pitroub1997962010-04-28 22:58:16 +0000352 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000353 if support.verbose and self.server.connectionchatty:
354 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000355 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000356 self.sock = self.sslconn.unwrap()
357 self.sslconn = None
358 if support.verbose and self.server.connectionchatty:
359 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000360 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000361 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000362 self.server.connectionchatty):
363 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou91382d82010-04-28 21:39:56 +0000364 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
365 % (msg, ctype, msg.lower(), ctype))
366 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000367 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000368 if self.server.chatty:
369 handle_error("Test server failure:\n")
370 self.close()
371 self.running = False
372 # normally, we'd just stop here, but for the test
373 # harness, we want to stop the server
374 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000375
Trent Nelson78520002008-04-10 20:54:35 +0000376 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000377 certreqs=None, cacerts=None,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000378 chatty=True, connectionchatty=False, starttls_server=False):
379 if ssl_version is None:
380 ssl_version = ssl.PROTOCOL_TLSv1
381 if certreqs is None:
382 certreqs = ssl.CERT_NONE
383 self.certificate = certificate
384 self.protocol = ssl_version
385 self.certreqs = certreqs
386 self.cacerts = cacerts
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000387 self.chatty = chatty
388 self.connectionchatty = connectionchatty
389 self.starttls_server = starttls_server
390 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000391 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000392 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000393 self.active = False
394 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000395 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000396
Antoine Pitrou91382d82010-04-28 21:39:56 +0000397 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000398 self.flag = flag
399 threading.Thread.start(self)
400
Antoine Pitrou91382d82010-04-28 21:39:56 +0000401 def run(self):
Antoine Pitroube168132010-04-27 10:41:37 +0000402 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000403 self.sock.listen(5)
404 self.active = True
405 if self.flag:
406 # signal an event
407 self.flag.set()
408 while self.active:
409 try:
410 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000411 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000412 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000413 + repr(connaddr) + '\n')
414 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000415 handler.start()
416 except socket.timeout:
417 pass
418 except KeyboardInterrupt:
419 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000420 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000421
Antoine Pitrou91382d82010-04-28 21:39:56 +0000422 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000423 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000424
Bill Janssen54cc54c2007-12-14 22:08:56 +0000425 class OurHTTPSServer(threading.Thread):
426
427 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000428
429 class HTTPSServer(HTTPServer):
430
431 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000432 HTTPServer.__init__(self, server_address, RequestHandlerClass)
433 # we assume the certfile contains both private key and certificate
434 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000435 self.allow_reuse_address = True
436
Bill Janssen6e027db2007-11-15 22:23:56 +0000437 def __str__(self):
438 return ('<%s %s:%s>' %
439 (self.__class__.__name__,
440 self.server_name,
441 self.server_port))
442
Antoine Pitrou91382d82010-04-28 21:39:56 +0000443 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000444 # override this to wrap socket with SSL
445 sock, addr = self.socket.accept()
446 sslconn = ssl.wrap_socket(sock, server_side=True,
447 certfile=self.certfile)
448 return sslconn, addr
449
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000450 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000451 # need to override translate_path to get a known root,
452 # instead of using os.curdir, since the test could be
453 # run from anywhere
454
455 server_version = "TestHTTPS/1.0"
456
457 root = None
458
459 def translate_path(self, path):
460 """Translate a /-separated PATH to the local filename syntax.
461
462 Components that mean special things to the local file system
463 (e.g. drive or directory names) are ignored. (XXX They should
464 probably be diagnosed.)
465
466 """
467 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000468 path = urllib.parse.urlparse(path)[2]
469 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000470 words = path.split('/')
471 words = filter(None, words)
472 path = self.root
473 for word in words:
474 drive, word = os.path.splitdrive(word)
475 head, word = os.path.split(word)
476 if word in self.root: continue
477 path = os.path.join(path, word)
478 return path
479
480 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000481 # we override this to suppress logging unless "verbose"
482
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000483 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000484 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
485 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000486 self.server.server_port,
487 self.request.cipher(),
488 self.log_date_time_string(),
489 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000490
491
Trent Nelson78520002008-04-10 20:54:35 +0000492 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000493 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000494 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
495 self.server = self.HTTPSServer(
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000496 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
497 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000498 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000499 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000500
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000501 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000502 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000503
Antoine Pitrou91382d82010-04-28 21:39:56 +0000504 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000505 self.flag = flag
506 threading.Thread.start(self)
507
Antoine Pitrou91382d82010-04-28 21:39:56 +0000508 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000509 if self.flag:
510 self.flag.set()
Antoine Pitroube168132010-04-27 10:41:37 +0000511 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000512
Antoine Pitrou91382d82010-04-28 21:39:56 +0000513 def stop(self):
Antoine Pitroube168132010-04-27 10:41:37 +0000514 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000515
516
Bill Janssen54cc54c2007-12-14 22:08:56 +0000517 class AsyncoreEchoServer(threading.Thread):
518
519 # this one's based on asyncore.dispatcher
520
521 class EchoServer (asyncore.dispatcher):
522
523 class ConnectionHandler (asyncore.dispatcher_with_send):
524
525 def __init__(self, conn, certfile):
526 self.socket = ssl.wrap_socket(conn, server_side=True,
527 certfile=certfile,
528 do_handshake_on_connect=False)
529 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitrouec146182010-04-24 21:30:20 +0000530 self._ssl_accepting = True
531 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000532
533 def readable(self):
534 if isinstance(self.socket, ssl.SSLSocket):
535 while self.socket.pending() > 0:
536 self.handle_read_event()
537 return True
538
Antoine Pitrouec146182010-04-24 21:30:20 +0000539 def _do_ssl_handshake(self):
540 try:
541 self.socket.do_handshake()
542 except ssl.SSLError as err:
543 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
544 ssl.SSL_ERROR_WANT_WRITE):
545 return
546 elif err.args[0] == ssl.SSL_ERROR_EOF:
547 return self.handle_close()
548 raise
549 except socket.error as err:
550 if err.args[0] == errno.ECONNABORTED:
551 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000552 else:
Antoine Pitrouec146182010-04-24 21:30:20 +0000553 self._ssl_accepting = False
554
555 def handle_read(self):
556 if self._ssl_accepting:
557 self._do_ssl_handshake()
558 else:
559 data = self.recv(1024)
560 if support.verbose:
561 sys.stdout.write(" server: read %s from client\n" % repr(data))
562 if not data:
563 self.close()
564 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000565 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000566
567 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000568 self.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000569 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000570 sys.stdout.write(" server: closed connection %s\n" % self.socket)
571
572 def handle_error(self):
573 raise
574
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000575 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000576 self.certfile = certfile
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000577 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
578 self.port = support.bind_port(sock, '')
579 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000580 self.listen(5)
581
582 def handle_accept(self):
583 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000584 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000585 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
586 self.ConnectionHandler(sock_obj, self.certfile)
587
588 def handle_error(self):
589 raise
590
Trent Nelson78520002008-04-10 20:54:35 +0000591 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000592 self.flag = None
593 self.active = False
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000594 self.server = self.EchoServer(certfile)
595 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000596 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000597 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000598
599 def __str__(self):
600 return "<%s %s>" % (self.__class__.__name__, self.server)
601
602 def start (self, flag=None):
603 self.flag = flag
604 threading.Thread.start(self)
605
Antoine Pitrou91382d82010-04-28 21:39:56 +0000606 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000607 self.active = True
608 if self.flag:
609 self.flag.set()
610 while self.active:
611 try:
612 asyncore.loop(1)
613 except:
614 pass
615
Antoine Pitrou91382d82010-04-28 21:39:56 +0000616 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000617 self.active = False
618 self.server.close()
619
Antoine Pitrou91382d82010-04-28 21:39:56 +0000620 def bad_cert_test(certfile):
621 """
622 Launch a server with CERT_REQUIRED, and check that trying to
623 connect to it with the given client certificate fails.
624 """
Trent Nelson78520002008-04-10 20:54:35 +0000625 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000626 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000627 cacerts=CERTFILE, chatty=False,
628 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000629 flag = threading.Event()
630 server.start(flag)
631 # wait for it to start
632 flag.wait()
633 # try to connect
634 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000635 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000636 s = ssl.wrap_socket(socket.socket(),
637 certfile=certfile,
638 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000639 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000640 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000641 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000642 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou537bed62010-04-27 13:16:06 +0000643 except socket.error as x:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000644 if support.verbose:
Antoine Pitrou537bed62010-04-27 13:16:06 +0000645 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000646 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000647 self.fail("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000648 finally:
649 server.stop()
650 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000651
Antoine Pitrou91382d82010-04-28 21:39:56 +0000652 def server_params_test(certfile, protocol, certreqs, cacertsfile,
653 client_certfile, client_protocol=None, indata=b"FOO\n",
654 chatty=True, connectionchatty=False):
655 """
656 Launch a server, connect a client to it and try various reads
657 and writes.
658 """
Trent Nelson78520002008-04-10 20:54:35 +0000659 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000660 certreqs=certreqs,
661 ssl_version=protocol,
662 cacerts=cacertsfile,
663 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000664 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665 flag = threading.Event()
666 server.start(flag)
667 # wait for it to start
668 flag.wait()
669 # try to connect
670 if client_protocol is None:
671 client_protocol = protocol
672 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000673 s = ssl.wrap_socket(socket.socket(),
674 certfile=client_certfile,
675 ca_certs=cacertsfile,
676 cert_reqs=certreqs,
677 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000678 s.connect((HOST, server.port))
Antoine Pitrou91382d82010-04-28 21:39:56 +0000679 arg = indata
Bill Janssen6e027db2007-11-15 22:23:56 +0000680 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000681 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000682 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000683 " client: sending %r...\n" % indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000684 s.write(arg)
Bill Janssen6e027db2007-11-15 22:23:56 +0000685 outdata = s.read()
686 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000687 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000688 sys.stdout.write(" client: read %r\n" % outdata)
Bill Janssen6e027db2007-11-15 22:23:56 +0000689 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000690 self.fail(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000691 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
692 % (outdata[:20], len(outdata),
693 indata[:20].lower(), len(indata)))
694 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000695 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000696 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000697 sys.stdout.write(" client: closing connection.\n")
698 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000699 finally:
700 server.stop()
701 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000702
Antoine Pitrou91382d82010-04-28 21:39:56 +0000703 def try_protocol_combo(server_protocol,
704 client_protocol,
705 expect_success,
706 certsreqs=None):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000707 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000708 certsreqs = ssl.CERT_NONE
Antoine Pitrou91382d82010-04-28 21:39:56 +0000709 certtype = {
710 ssl.CERT_NONE: "CERT_NONE",
711 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
712 ssl.CERT_REQUIRED: "CERT_REQUIRED",
713 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000714 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000715 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000716 sys.stdout.write(formatstr %
717 (ssl.get_protocol_name(client_protocol),
718 ssl.get_protocol_name(server_protocol),
719 certtype))
720 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000721 server_params_test(CERTFILE, server_protocol, certsreqs,
722 CERTFILE, CERTFILE, client_protocol,
723 chatty=False,
724 connectionchatty=False)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000725 # Protocol mismatch can result in either an SSLError, or a
726 # "Connection reset by peer" error.
727 except ssl.SSLError:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000728 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000729 raise
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000730 except socket.error as e:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000731 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000732 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000733 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000734 if not expect_success:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000735 self.fail(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000736 "Client protocol %s succeeded with server protocol %s!"
737 % (ssl.get_protocol_name(client_protocol),
738 ssl.get_protocol_name(server_protocol)))
739
740
Bill Janssen6e027db2007-11-15 22:23:56 +0000741 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000742
Antoine Pitrou91382d82010-04-28 21:39:56 +0000743 def test_echo(self):
744 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000745 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000746 sys.stdout.write("\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000747 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
748 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
749 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000750
Antoine Pitrou91382d82010-04-28 21:39:56 +0000751 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000752 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000753 sys.stdout.write("\n")
754 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000755 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000756 certreqs=ssl.CERT_NONE,
757 ssl_version=ssl.PROTOCOL_SSLv23,
758 cacerts=CERTFILE,
759 chatty=False)
760 flag = threading.Event()
761 server.start(flag)
762 # wait for it to start
763 flag.wait()
764 # try to connect
765 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000766 s = ssl.wrap_socket(socket.socket(),
767 certfile=CERTFILE,
768 ca_certs=CERTFILE,
769 cert_reqs=ssl.CERT_REQUIRED,
770 ssl_version=ssl.PROTOCOL_SSLv23)
771 s.connect((HOST, server.port))
772 cert = s.getpeercert()
773 self.assertTrue(cert, "Can't get peer certificate.")
774 cipher = s.cipher()
775 if support.verbose:
776 sys.stdout.write(pprint.pformat(cert) + '\n')
777 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
778 if 'subject' not in cert:
779 self.fail("No subject field in certificate: %s." %
780 pprint.pformat(cert))
781 if ((('organizationName', 'Python Software Foundation'),)
782 not in cert['subject']):
783 self.fail(
784 "Missing or invalid 'organizationName' field in certificate subject; "
785 "should be 'Python Software Foundation'.")
786 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000787 finally:
788 server.stop()
789 server.join()
790
Antoine Pitrou91382d82010-04-28 21:39:56 +0000791 def test_empty_cert(self):
792 """Connecting with an empty cert file"""
793 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
794 "nullcert.pem"))
795 def test_malformed_cert(self):
796 """Connecting with a badly formatted certificate (syntax error)"""
797 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
798 "badcert.pem"))
799 def test_nonexisting_cert(self):
800 """Connecting with a non-existing cert file"""
801 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
802 "wrongcert.pem"))
803 def test_malformed_key(self):
804 """Connecting with a badly formatted key (syntax error)"""
805 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
806 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000807
Antoine Pitrou91382d82010-04-28 21:39:56 +0000808 def test_rude_shutdown(self):
809 """A brutal shutdown of an SSL server should raise an IOError
810 in the client when attempting handshake.
811 """
Trent Nelson6b240cd2008-04-10 20:12:06 +0000812 listener_ready = threading.Event()
813 listener_gone = threading.Event()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000814
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000815 s = socket.socket()
816 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000817
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000818 # `listener` runs in a thread. It sits in an accept() until
819 # the main thread connects. Then it rudely closes the socket,
820 # and sets Event `listener_gone` to let the main thread know
821 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000822 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000823 s.listen(5)
824 listener_ready.set()
825 s.accept()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000826 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000827 listener_gone.set()
828
829 def connector():
830 listener_ready.wait()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000831 c = socket.socket()
832 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000833 listener_gone.wait()
834 try:
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000835 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000836 except IOError:
837 pass
838 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000839 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +0000840
841 t = threading.Thread(target=listener)
842 t.start()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000843 try:
844 connector()
845 finally:
846 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000847
Antoine Pitrou91382d82010-04-28 21:39:56 +0000848 def test_protocol_sslv2(self):
849 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000850 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000851 sys.stdout.write("\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000852 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
853 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
854 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
855 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
856 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
857 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000858
Antoine Pitrou91382d82010-04-28 21:39:56 +0000859 def test_protocol_sslv23(self):
860 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000861 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000862 sys.stdout.write("\n")
863 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000864 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000865 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000866 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000867 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000868 sys.stdout.write(
869 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
870 % str(x))
Antoine Pitrou91382d82010-04-28 21:39:56 +0000871 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
872 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
873 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000874
Antoine Pitrou91382d82010-04-28 21:39:56 +0000875 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
876 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
877 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000878
Antoine Pitrou91382d82010-04-28 21:39:56 +0000879 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
880 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
881 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000882
Antoine Pitrou91382d82010-04-28 21:39:56 +0000883 def test_protocol_sslv3(self):
884 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000885 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000886 sys.stdout.write("\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000887 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
888 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
889 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
890 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
891 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
892 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000893
Antoine Pitrou91382d82010-04-28 21:39:56 +0000894 def test_protocol_tlsv1(self):
895 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000896 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000897 sys.stdout.write("\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000898 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
899 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
900 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
901 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
902 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
903 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000904
Antoine Pitrou91382d82010-04-28 21:39:56 +0000905 def test_starttls(self):
906 """Switching from clear text to encrypted and back again."""
907 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 +0000908
Trent Nelson78520002008-04-10 20:54:35 +0000909 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000910 ssl_version=ssl.PROTOCOL_TLSv1,
911 starttls_server=True,
912 chatty=True,
913 connectionchatty=True)
914 flag = threading.Event()
915 server.start(flag)
916 # wait for it to start
917 flag.wait()
918 # try to connect
919 wrapped = False
920 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000921 s = socket.socket()
922 s.setblocking(1)
923 s.connect((HOST, server.port))
924 if support.verbose:
925 sys.stdout.write("\n")
926 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000927 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000928 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000929 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000930 if wrapped:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000931 conn.write(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000932 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000933 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000934 s.send(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000935 outdata = s.recv(1024)
Antoine Pitrou91382d82010-04-28 21:39:56 +0000936 msg = outdata.strip().lower()
937 if indata == b"STARTTLS" and msg.startswith(b"ok"):
938 # STARTTLS ok, switch to secure mode
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000939 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000940 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000941 " client: read %r from server, starting TLS...\n"
942 % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000943 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
944 wrapped = True
Antoine Pitrou91382d82010-04-28 21:39:56 +0000945 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
946 # ENDTLS ok, switch back to clear text
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000947 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000948 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000949 " client: read %r from server, ending TLS...\n"
950 % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000951 s = conn.unwrap()
952 wrapped = False
953 else:
954 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000955 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000956 " client: read %r from server\n" % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000957 if support.verbose:
958 sys.stdout.write(" client: closing connection.\n")
959 if wrapped:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000960 conn.write(b"over\n")
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000961 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000962 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000963 if wrapped:
964 conn.close()
965 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000966 s.close()
967 finally:
968 server.stop()
969 server.join()
970
Antoine Pitrou91382d82010-04-28 21:39:56 +0000971 def test_socketserver(self):
972 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +0000973 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000974 flag = threading.Event()
975 server.start(flag)
976 # wait for it to start
977 flag.wait()
978 # try to connect
979 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000980 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000981 sys.stdout.write('\n')
Antoine Pitrou91382d82010-04-28 21:39:56 +0000982 with open(CERTFILE, 'rb') as f:
983 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000984 d2 = ''
985 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +0000986 url = 'https://%s:%d/%s' % (
987 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000988 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +0000989 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 if dlen and (int(dlen) > 0):
991 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000992 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000993 sys.stdout.write(
994 " client: read %d bytes from remote server '%s'\n"
995 % (len(d2), server))
996 f.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000997 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000999 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001000 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001001 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001002 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001003 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001004 server.join()
1005
Antoine Pitrou91382d82010-04-28 21:39:56 +00001006 def test_asyncore_server(self):
1007 """Check the example asyncore integration."""
1008 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001009
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001010 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001011 sys.stdout.write("\n")
1012
Antoine Pitrou91382d82010-04-28 21:39:56 +00001013 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001014 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001015 flag = threading.Event()
1016 server.start(flag)
1017 # wait for it to start
1018 flag.wait()
1019 # try to connect
1020 try:
1021 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001022 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001023 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001024 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +00001025 " client: sending %r...\n" % indata)
1026 s.write(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001027 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001028 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001029 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001030 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001031 self.fail(
Antoine Pitrou91382d82010-04-28 21:39:56 +00001032 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1033 % (outdata[:20], len(outdata),
1034 indata[:20].lower(), len(indata)))
1035 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001036 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001037 sys.stdout.write(" client: closing connection.\n")
1038 s.close()
1039 finally:
1040 server.stop()
1041 server.join()
1042
Antoine Pitrou91382d82010-04-28 21:39:56 +00001043 def test_recv_send(self):
1044 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001045 if support.verbose:
1046 sys.stdout.write("\n")
1047
1048 server = ThreadedEchoServer(CERTFILE,
1049 certreqs=ssl.CERT_NONE,
1050 ssl_version=ssl.PROTOCOL_TLSv1,
1051 cacerts=CERTFILE,
1052 chatty=True,
1053 connectionchatty=False)
1054 flag = threading.Event()
1055 server.start(flag)
1056 # wait for it to start
1057 flag.wait()
1058 # try to connect
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001059 s = ssl.wrap_socket(socket.socket(),
1060 server_side=False,
1061 certfile=CERTFILE,
1062 ca_certs=CERTFILE,
1063 cert_reqs=ssl.CERT_NONE,
1064 ssl_version=ssl.PROTOCOL_TLSv1)
1065 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001066 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001067 # helper methods for standardising recv* method signatures
1068 def _recv_into():
1069 b = bytearray(b"\0"*100)
1070 count = s.recv_into(b)
1071 return b[:count]
1072
1073 def _recvfrom_into():
1074 b = bytearray(b"\0"*100)
1075 count, addr = s.recvfrom_into(b)
1076 return b[:count]
1077
1078 # (name, method, whether to expect success, *args)
1079 send_methods = [
1080 ('send', s.send, True, []),
1081 ('sendto', s.sendto, False, ["some.address"]),
1082 ('sendall', s.sendall, True, []),
1083 ]
1084 recv_methods = [
1085 ('recv', s.recv, True, []),
1086 ('recvfrom', s.recvfrom, False, ["some.address"]),
1087 ('recv_into', _recv_into, True, []),
1088 ('recvfrom_into', _recvfrom_into, False, []),
1089 ]
1090 data_prefix = "PREFIX_"
1091
1092 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001093 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001094 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001095 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001096 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001097 if outdata != indata.lower():
1098 raise support.TestFailed(
1099 "While sending with <<{name:s}>> bad data "
Antoine Pitrou91382d82010-04-28 21:39:56 +00001100 "<<{outdata:r}>> ({nout:d}) received; "
1101 "expected <<{indata:r}>> ({nin:d})\n".format(
1102 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001103 nout=len(outdata),
Antoine Pitrou91382d82010-04-28 21:39:56 +00001104 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001105 )
1106 )
1107 except ValueError as e:
1108 if expect_success:
1109 raise support.TestFailed(
1110 "Failed to send with method <<{name:s}>>; "
1111 "expected to succeed.\n".format(name=meth_name)
1112 )
1113 if not str(e).startswith(meth_name):
1114 raise support.TestFailed(
1115 "Method <<{name:s}>> failed with unexpected "
1116 "exception message: {exp:s}\n".format(
1117 name=meth_name, exp=e
1118 )
1119 )
1120
1121 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001122 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001123 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001124 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001125 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001126 if outdata != indata.lower():
1127 raise support.TestFailed(
1128 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou91382d82010-04-28 21:39:56 +00001129 "<<{outdata:r}>> ({nout:d}) received; "
1130 "expected <<{indata:r}>> ({nin:d})\n".format(
1131 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001132 nout=len(outdata),
Antoine Pitrou91382d82010-04-28 21:39:56 +00001133 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001134 )
1135 )
1136 except ValueError as e:
1137 if expect_success:
1138 raise support.TestFailed(
1139 "Failed to receive with method <<{name:s}>>; "
1140 "expected to succeed.\n".format(name=meth_name)
1141 )
1142 if not str(e).startswith(meth_name):
1143 raise support.TestFailed(
1144 "Method <<{name:s}>> failed with unexpected "
1145 "exception message: {exp:s}\n".format(
1146 name=meth_name, exp=e
1147 )
1148 )
1149 # consume data
1150 s.read()
1151
Antoine Pitrou91382d82010-04-28 21:39:56 +00001152 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001153 s.close()
1154 finally:
1155 server.stop()
1156 server.join()
1157
Antoine Pitrouec146182010-04-24 21:30:20 +00001158 def test_handshake_timeout(self):
1159 # Issue #5103: SSL handshake must respect the socket timeout
1160 server = socket.socket(socket.AF_INET)
1161 host = "127.0.0.1"
1162 port = support.bind_port(server)
1163 started = threading.Event()
1164 finish = False
1165
1166 def serve():
1167 server.listen(5)
1168 started.set()
1169 conns = []
1170 while not finish:
1171 r, w, e = select.select([server], [], [], 0.1)
1172 if server in r:
1173 # Let the socket hang around rather than having
1174 # it closed by garbage collection.
1175 conns.append(server.accept()[0])
1176
1177 t = threading.Thread(target=serve)
1178 t.start()
1179 started.wait()
1180
1181 try:
Antoine Pitrouc2203f92010-04-24 22:07:51 +00001182 try:
1183 c = socket.socket(socket.AF_INET)
1184 c.settimeout(0.2)
1185 c.connect((host, port))
1186 # Will attempt handshake and time out
1187 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1188 ssl.wrap_socket, c)
1189 finally:
1190 c.close()
Antoine Pitrouec146182010-04-24 21:30:20 +00001191 try:
1192 c = socket.socket(socket.AF_INET)
1193 c = ssl.wrap_socket(c)
1194 c.settimeout(0.2)
1195 # Will attempt handshake and time out
1196 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1197 c.connect, (host, port))
1198 finally:
1199 c.close()
1200 finally:
1201 finish = True
1202 t.join()
1203 server.close()
1204
Bill Janssen58afe4c2008-09-08 16:45:19 +00001205
Thomas Woutersed03b412007-08-28 21:37:11 +00001206def test_main(verbose=False):
1207 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001208 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001209
Trent Nelson78520002008-04-10 20:54:35 +00001210 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Thomas Woutersed03b412007-08-28 21:37:11 +00001211 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
1212 "keycert.pem")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001213 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1214 os.path.dirname(__file__) or os.curdir,
1215 "https_svn_python_org_root.pem")
1216
1217 if (not os.path.exists(CERTFILE) or
1218 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001219 raise support.TestFailed("Can't read certificate files!")
Bill Janssen6e027db2007-11-15 22:23:56 +00001220
Thomas Woutersed03b412007-08-28 21:37:11 +00001221 tests = [BasicTests]
1222
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001223 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001224 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001225
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001226 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001227 thread_info = support.threading_setup()
1228 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001229 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001230
Antoine Pitrou91382d82010-04-28 21:39:56 +00001231 try:
1232 support.run_unittest(*tests)
1233 finally:
1234 if _have_threads:
1235 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001236
1237if __name__ == "__main__":
1238 test_main()