blob: 987a4259b39a2d0868f359afe6b7c69988a09eb6 [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 Pitrou5974cdd2010-09-14 14:47:08 +000095 def test_wrapped_unconnected(self):
96 # Methods on an unconnected SSLSocket propagate the original
97 # socket.error raise by the underlying socket object.
98 s = socket.socket(socket.AF_INET)
99 ss = ssl.wrap_socket(s)
100 self.assertRaises(socket.error, ss.recv, 1)
101 self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
102 self.assertRaises(socket.error, ss.recvfrom, 1)
103 self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
104 self.assertRaises(socket.error, ss.send, b'x')
105 self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
106
Antoine Pitrouc2203f92010-04-24 22:07:51 +0000107 def test_timeout(self):
108 # Issue #8524: when creating an SSL socket, the timeout of the
109 # original socket should be retained.
110 for timeout in (None, 0.0, 5.0):
111 s = socket.socket(socket.AF_INET)
112 s.settimeout(timeout)
113 ss = ssl.wrap_socket(s)
114 self.assertEqual(timeout, ss.gettimeout())
115
Antoine Pitrou3b9b9ba2010-04-23 23:33:50 +0000116
Bill Janssen6e027db2007-11-15 22:23:56 +0000117class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000118
Antoine Pitrou91382d82010-04-28 21:39:56 +0000119 def test_connect(self):
Antoine Pitrou78d89462010-09-09 13:33:33 +0000120 with support.transient_internet("svn.python.org"):
121 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
122 cert_reqs=ssl.CERT_NONE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000123 s.connect(("svn.python.org", 443))
Antoine Pitrou78d89462010-09-09 13:33:33 +0000124 c = s.getpeercert()
125 if c:
126 self.fail("Peer cert %s shouldn't be here!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000127 s.close()
128
Antoine Pitrou78d89462010-09-09 13:33:33 +0000129 # this should fail because we have no verification certs
130 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
131 cert_reqs=ssl.CERT_REQUIRED)
132 try:
133 s.connect(("svn.python.org", 443))
134 except ssl.SSLError:
135 pass
136 finally:
137 s.close()
138
139 # this should succeed because we specify the root cert
140 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
141 cert_reqs=ssl.CERT_REQUIRED,
142 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
143 try:
144 s.connect(("svn.python.org", 443))
145 finally:
146 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000147
Antoine Pitroufe0f1172010-04-24 11:17:37 +0000148 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
149 def test_makefile_close(self):
150 # Issue #5238: creating a file-like object with makefile() shouldn't
151 # delay closing the underlying "real socket" (here tested with its
152 # file descriptor, hence skipping the test under Windows).
Antoine Pitrou78d89462010-09-09 13:33:33 +0000153 with support.transient_internet("svn.python.org"):
154 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
155 ss.connect(("svn.python.org", 443))
156 fd = ss.fileno()
157 f = ss.makefile()
158 f.close()
159 # The fd is still open
Antoine Pitroufe0f1172010-04-24 11:17:37 +0000160 os.read(fd, 0)
Antoine Pitrou78d89462010-09-09 13:33:33 +0000161 # Closing the SSL socket should close the fd too
162 ss.close()
163 gc.collect()
164 try:
165 os.read(fd, 0)
166 except OSError as e:
167 self.assertEqual(e.errno, errno.EBADF)
168 else:
169 self.fail("OSError wasn't raised")
Antoine Pitroufe0f1172010-04-24 11:17:37 +0000170
Antoine Pitrou91382d82010-04-28 21:39:56 +0000171 def test_non_blocking_handshake(self):
Antoine Pitrou78d89462010-09-09 13:33:33 +0000172 with support.transient_internet("svn.python.org"):
173 s = socket.socket(socket.AF_INET)
174 s.connect(("svn.python.org", 443))
175 s.setblocking(False)
176 s = ssl.wrap_socket(s,
177 cert_reqs=ssl.CERT_NONE,
178 do_handshake_on_connect=False)
179 count = 0
180 while True:
181 try:
182 count += 1
183 s.do_handshake()
184 break
185 except ssl.SSLError as err:
186 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
187 select.select([s], [], [])
188 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
189 select.select([], [s], [])
190 else:
191 raise
192 s.close()
193 if support.verbose:
194 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000195
Antoine Pitrou91382d82010-04-28 21:39:56 +0000196 def test_get_server_certificate(self):
Antoine Pitrou78d89462010-09-09 13:33:33 +0000197 with support.transient_internet("svn.python.org"):
198 pem = ssl.get_server_certificate(("svn.python.org", 443))
199 if not pem:
200 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000201
Antoine Pitrou78d89462010-09-09 13:33:33 +0000202 try:
203 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
204 except ssl.SSLError as x:
205 #should fail
206 if support.verbose:
207 sys.stdout.write("%s\n" % x)
208 else:
209 self.fail("Got server certificate %s for svn.python.org!" % pem)
210
211 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
212 if not pem:
213 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000214 if support.verbose:
Antoine Pitrou78d89462010-09-09 13:33:33 +0000215 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000216
Antoine Pitrou754b98c2010-04-22 18:47:06 +0000217 # Test disabled: OPENSSL_VERSION* not available in Python 3.1
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000218 def test_algorithms(self):
Antoine Pitrouae92a722010-04-22 18:46:16 +0000219 if support.verbose:
220 sys.stdout.write("test_algorithms disabled, "
221 "as it fails on some old OpenSSL versions")
222 return
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000223 # Issue #8484: all algorithms should be available when verifying a
224 # certificate.
Antoine Pitrouae92a722010-04-22 18:46:16 +0000225 # SHA256 was added in OpenSSL 0.9.8
226 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
227 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000228 # NOTE: https://sha256.tbs-internet.com is another possible test host
229 remote = ("sha2.hboeck.de", 443)
230 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
Antoine Pitrou4d7979b2010-09-07 21:22:56 +0000231 with support.transient_internet("sha2.hboeck.de"):
232 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
233 cert_reqs=ssl.CERT_REQUIRED,
234 ca_certs=sha256_cert,)
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000235 try:
236 s.connect(remote)
237 if support.verbose:
238 sys.stdout.write("\nCipher with %r is %r\n" %
239 (remote, s.cipher()))
240 sys.stdout.write("Certificate is:\n%s\n" %
241 pprint.pformat(s.getpeercert()))
242 finally:
243 s.close()
244
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000245
246try:
247 import threading
248except ImportError:
249 _have_threads = False
250else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000251 _have_threads = True
252
253 class ThreadedEchoServer(threading.Thread):
254
255 class ConnectionHandler(threading.Thread):
256
257 """A mildly complicated class, because we want it to work both
258 with and without the SSL wrapper around the socket connection, so
259 that we can test the STARTTLS functionality."""
260
Bill Janssen6e027db2007-11-15 22:23:56 +0000261 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000262 self.server = server
263 self.running = False
264 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000265 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000266 self.sock.setblocking(1)
267 self.sslconn = None
268 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000269 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000270
Antoine Pitrou91382d82010-04-28 21:39:56 +0000271 def wrap_conn(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000272 try:
273 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
274 certfile=self.server.certificate,
275 ssl_version=self.server.protocol,
276 ca_certs=self.server.cacerts,
277 cert_reqs=self.server.certreqs)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000278 except ssl.SSLError:
279 # XXX Various errors can have happened here, for example
280 # a mismatching protocol version, an invalid certificate,
281 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000282 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000283 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000284 self.running = False
285 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000286 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000287 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000288 else:
289 if self.server.certreqs == ssl.CERT_REQUIRED:
290 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000291 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000292 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
293 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000294 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000295 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
296 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000297 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000298 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
299 return True
300
301 def read(self):
302 if self.sslconn:
303 return self.sslconn.read()
304 else:
305 return self.sock.recv(1024)
306
307 def write(self, bytes):
308 if self.sslconn:
309 return self.sslconn.write(bytes)
310 else:
311 return self.sock.send(bytes)
312
313 def close(self):
314 if self.sslconn:
315 self.sslconn.close()
316 else:
317 self.sock.close()
318
Antoine Pitrou91382d82010-04-28 21:39:56 +0000319 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000320 self.running = True
321 if not self.server.starttls_server:
322 if not self.wrap_conn():
323 return
324 while self.running:
325 try:
326 msg = self.read()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000327 stripped = msg.strip()
328 if not stripped:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000329 # eof, so quit this handler
330 self.running = False
331 self.close()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000332 elif stripped == b'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000333 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000334 sys.stdout.write(" server: client closed connection\n")
335 self.close()
336 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000337 elif (self.server.starttls_server and
Antoine Pitroub1997962010-04-28 22:58:16 +0000338 stripped == b'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000339 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000340 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000341 self.write(b"OK\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000342 if not self.wrap_conn():
343 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000344 elif (self.server.starttls_server and self.sslconn
Antoine Pitroub1997962010-04-28 22:58:16 +0000345 and stripped == b'ENDTLS'):
Bill Janssen40a0f662008-08-12 16:56:25 +0000346 if support.verbose and self.server.connectionchatty:
347 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000348 self.write(b"OK\n")
Bill Janssen40a0f662008-08-12 16:56:25 +0000349 self.sock = self.sslconn.unwrap()
350 self.sslconn = None
351 if support.verbose and self.server.connectionchatty:
352 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000353 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000354 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000355 self.server.connectionchatty):
356 ctype = (self.sslconn and "encrypted") or "unencrypted"
Antoine Pitrou91382d82010-04-28 21:39:56 +0000357 sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n"
358 % (msg, ctype, msg.lower(), ctype))
359 self.write(msg.lower())
Bill Janssen6e027db2007-11-15 22:23:56 +0000360 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000361 if self.server.chatty:
362 handle_error("Test server failure:\n")
363 self.close()
364 self.running = False
365 # normally, we'd just stop here, but for the test
366 # harness, we want to stop the server
367 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000368
Trent Nelson78520002008-04-10 20:54:35 +0000369 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000370 certreqs=None, cacerts=None,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000371 chatty=True, connectionchatty=False, starttls_server=False):
372 if ssl_version is None:
373 ssl_version = ssl.PROTOCOL_TLSv1
374 if certreqs is None:
375 certreqs = ssl.CERT_NONE
376 self.certificate = certificate
377 self.protocol = ssl_version
378 self.certreqs = certreqs
379 self.cacerts = cacerts
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000380 self.chatty = chatty
381 self.connectionchatty = connectionchatty
382 self.starttls_server = starttls_server
383 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000384 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000385 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000386 self.active = False
387 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000388 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000389
Antoine Pitrou91382d82010-04-28 21:39:56 +0000390 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000391 self.flag = flag
392 threading.Thread.start(self)
393
Antoine Pitrou91382d82010-04-28 21:39:56 +0000394 def run(self):
Antoine Pitroube168132010-04-27 10:41:37 +0000395 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000396 self.sock.listen(5)
397 self.active = True
398 if self.flag:
399 # signal an event
400 self.flag.set()
401 while self.active:
402 try:
403 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000404 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000405 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000406 + repr(connaddr) + '\n')
407 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000408 handler.start()
409 except socket.timeout:
410 pass
411 except KeyboardInterrupt:
412 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000413 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000414
Antoine Pitrou91382d82010-04-28 21:39:56 +0000415 def stop(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000416 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000417
Bill Janssen54cc54c2007-12-14 22:08:56 +0000418 class OurHTTPSServer(threading.Thread):
419
420 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000421
422 class HTTPSServer(HTTPServer):
423
424 def __init__(self, server_address, RequestHandlerClass, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000425 HTTPServer.__init__(self, server_address, RequestHandlerClass)
426 # we assume the certfile contains both private key and certificate
427 self.certfile = certfile
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000428 self.allow_reuse_address = True
429
Bill Janssen6e027db2007-11-15 22:23:56 +0000430 def __str__(self):
431 return ('<%s %s:%s>' %
432 (self.__class__.__name__,
433 self.server_name,
434 self.server_port))
435
Antoine Pitrou91382d82010-04-28 21:39:56 +0000436 def get_request(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000437 # override this to wrap socket with SSL
438 sock, addr = self.socket.accept()
439 sslconn = ssl.wrap_socket(sock, server_side=True,
440 certfile=self.certfile)
441 return sslconn, addr
442
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000443 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000444 # need to override translate_path to get a known root,
445 # instead of using os.curdir, since the test could be
446 # run from anywhere
447
448 server_version = "TestHTTPS/1.0"
449
450 root = None
451
452 def translate_path(self, path):
453 """Translate a /-separated PATH to the local filename syntax.
454
455 Components that mean special things to the local file system
456 (e.g. drive or directory names) are ignored. (XXX They should
457 probably be diagnosed.)
458
459 """
460 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000461 path = urllib.parse.urlparse(path)[2]
462 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000463 words = path.split('/')
464 words = filter(None, words)
465 path = self.root
466 for word in words:
467 drive, word = os.path.splitdrive(word)
468 head, word = os.path.split(word)
469 if word in self.root: continue
470 path = os.path.join(path, word)
471 return path
472
473 def log_message(self, format, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000474 # we override this to suppress logging unless "verbose"
475
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000476 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000477 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
478 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000479 self.server.server_port,
480 self.request.cipher(),
481 self.log_date_time_string(),
482 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000483
484
Trent Nelson78520002008-04-10 20:54:35 +0000485 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000486 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000487 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
488 self.server = self.HTTPSServer(
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000489 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
490 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000491 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000492 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000493
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000494 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000495 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000496
Antoine Pitrou91382d82010-04-28 21:39:56 +0000497 def start(self, flag=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000498 self.flag = flag
499 threading.Thread.start(self)
500
Antoine Pitrou91382d82010-04-28 21:39:56 +0000501 def run(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000502 if self.flag:
503 self.flag.set()
Antoine Pitroube168132010-04-27 10:41:37 +0000504 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000505
Antoine Pitrou91382d82010-04-28 21:39:56 +0000506 def stop(self):
Antoine Pitroube168132010-04-27 10:41:37 +0000507 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000508
509
Bill Janssen54cc54c2007-12-14 22:08:56 +0000510 class AsyncoreEchoServer(threading.Thread):
511
512 # this one's based on asyncore.dispatcher
513
514 class EchoServer (asyncore.dispatcher):
515
516 class ConnectionHandler (asyncore.dispatcher_with_send):
517
518 def __init__(self, conn, certfile):
519 self.socket = ssl.wrap_socket(conn, server_side=True,
520 certfile=certfile,
521 do_handshake_on_connect=False)
522 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitrouec146182010-04-24 21:30:20 +0000523 self._ssl_accepting = True
524 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000525
526 def readable(self):
527 if isinstance(self.socket, ssl.SSLSocket):
528 while self.socket.pending() > 0:
529 self.handle_read_event()
530 return True
531
Antoine Pitrouec146182010-04-24 21:30:20 +0000532 def _do_ssl_handshake(self):
533 try:
534 self.socket.do_handshake()
535 except ssl.SSLError as err:
536 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
537 ssl.SSL_ERROR_WANT_WRITE):
538 return
539 elif err.args[0] == ssl.SSL_ERROR_EOF:
540 return self.handle_close()
541 raise
542 except socket.error as err:
543 if err.args[0] == errno.ECONNABORTED:
544 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000545 else:
Antoine Pitrouec146182010-04-24 21:30:20 +0000546 self._ssl_accepting = False
547
548 def handle_read(self):
549 if self._ssl_accepting:
550 self._do_ssl_handshake()
551 else:
552 data = self.recv(1024)
553 if support.verbose:
554 sys.stdout.write(" server: read %s from client\n" % repr(data))
555 if not data:
556 self.close()
557 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000558 self.send(data.lower())
Bill Janssen54cc54c2007-12-14 22:08:56 +0000559
560 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000561 self.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000562 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000563 sys.stdout.write(" server: closed connection %s\n" % self.socket)
564
565 def handle_error(self):
566 raise
567
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000568 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000569 self.certfile = certfile
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000570 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
571 self.port = support.bind_port(sock, '')
572 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000573 self.listen(5)
574
575 def handle_accept(self):
576 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000577 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000578 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
579 self.ConnectionHandler(sock_obj, self.certfile)
580
581 def handle_error(self):
582 raise
583
Trent Nelson78520002008-04-10 20:54:35 +0000584 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000585 self.flag = None
586 self.active = False
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000587 self.server = self.EchoServer(certfile)
588 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000589 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000590 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000591
592 def __str__(self):
593 return "<%s %s>" % (self.__class__.__name__, self.server)
594
595 def start (self, flag=None):
596 self.flag = flag
597 threading.Thread.start(self)
598
Antoine Pitrou91382d82010-04-28 21:39:56 +0000599 def run(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000600 self.active = True
601 if self.flag:
602 self.flag.set()
603 while self.active:
604 try:
605 asyncore.loop(1)
606 except:
607 pass
608
Antoine Pitrou91382d82010-04-28 21:39:56 +0000609 def stop(self):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000610 self.active = False
611 self.server.close()
612
Antoine Pitrou91382d82010-04-28 21:39:56 +0000613 def bad_cert_test(certfile):
614 """
615 Launch a server with CERT_REQUIRED, and check that trying to
616 connect to it with the given client certificate fails.
617 """
Trent Nelson78520002008-04-10 20:54:35 +0000618 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000619 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000620 cacerts=CERTFILE, chatty=False,
621 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000622 flag = threading.Event()
623 server.start(flag)
624 # wait for it to start
625 flag.wait()
626 # try to connect
627 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000628 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000629 s = ssl.wrap_socket(socket.socket(),
630 certfile=certfile,
631 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000632 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000633 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000634 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000635 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou537bed62010-04-27 13:16:06 +0000636 except socket.error as x:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000637 if support.verbose:
Antoine Pitrou537bed62010-04-27 13:16:06 +0000638 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000639 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000640 self.fail("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000641 finally:
642 server.stop()
643 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000644
Antoine Pitrou91382d82010-04-28 21:39:56 +0000645 def server_params_test(certfile, protocol, certreqs, cacertsfile,
646 client_certfile, client_protocol=None, indata=b"FOO\n",
647 chatty=True, connectionchatty=False):
648 """
649 Launch a server, connect a client to it and try various reads
650 and writes.
651 """
Trent Nelson78520002008-04-10 20:54:35 +0000652 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000653 certreqs=certreqs,
654 ssl_version=protocol,
655 cacerts=cacertsfile,
656 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000657 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000658 flag = threading.Event()
659 server.start(flag)
660 # wait for it to start
661 flag.wait()
662 # try to connect
663 if client_protocol is None:
664 client_protocol = protocol
665 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000666 s = ssl.wrap_socket(socket.socket(),
667 certfile=client_certfile,
668 ca_certs=cacertsfile,
669 cert_reqs=certreqs,
670 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000671 s.connect((HOST, server.port))
Antoine Pitrou91382d82010-04-28 21:39:56 +0000672 arg = indata
Bill Janssen6e027db2007-11-15 22:23:56 +0000673 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000674 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000675 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000676 " client: sending %r...\n" % indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000677 s.write(arg)
Bill Janssen6e027db2007-11-15 22:23:56 +0000678 outdata = s.read()
679 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000680 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000681 sys.stdout.write(" client: read %r\n" % outdata)
Bill Janssen6e027db2007-11-15 22:23:56 +0000682 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000683 self.fail(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000684 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
685 % (outdata[:20], len(outdata),
686 indata[:20].lower(), len(indata)))
687 s.write(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000688 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000689 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000690 sys.stdout.write(" client: closing connection.\n")
691 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000692 finally:
693 server.stop()
694 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000695
Antoine Pitrou91382d82010-04-28 21:39:56 +0000696 def try_protocol_combo(server_protocol,
697 client_protocol,
698 expect_success,
699 certsreqs=None):
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000700 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000701 certsreqs = ssl.CERT_NONE
Antoine Pitrou91382d82010-04-28 21:39:56 +0000702 certtype = {
703 ssl.CERT_NONE: "CERT_NONE",
704 ssl.CERT_OPTIONAL: "CERT_OPTIONAL",
705 ssl.CERT_REQUIRED: "CERT_REQUIRED",
706 }[certsreqs]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000707 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000708 formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n"
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000709 sys.stdout.write(formatstr %
710 (ssl.get_protocol_name(client_protocol),
711 ssl.get_protocol_name(server_protocol),
712 certtype))
713 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000714 server_params_test(CERTFILE, server_protocol, certsreqs,
715 CERTFILE, CERTFILE, client_protocol,
716 chatty=False,
717 connectionchatty=False)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000718 # Protocol mismatch can result in either an SSLError, or a
719 # "Connection reset by peer" error.
720 except ssl.SSLError:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000721 if expect_success:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000722 raise
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000723 except socket.error as e:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000724 if expect_success or e.errno != errno.ECONNRESET:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000725 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000726 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000727 if not expect_success:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000728 raise AssertionError(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000729 "Client protocol %s succeeded with server protocol %s!"
730 % (ssl.get_protocol_name(client_protocol),
731 ssl.get_protocol_name(server_protocol)))
732
733
Bill Janssen6e027db2007-11-15 22:23:56 +0000734 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000735
Antoine Pitrou91382d82010-04-28 21:39:56 +0000736 def test_echo(self):
737 """Basic test of an SSL client connecting to a server"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000738 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000739 sys.stdout.write("\n")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000740 server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
741 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
742 chatty=True, connectionchatty=True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000743
Antoine Pitrou91382d82010-04-28 21:39:56 +0000744 def test_getpeercert(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000745 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000746 sys.stdout.write("\n")
747 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000748 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000749 certreqs=ssl.CERT_NONE,
750 ssl_version=ssl.PROTOCOL_SSLv23,
751 cacerts=CERTFILE,
752 chatty=False)
753 flag = threading.Event()
754 server.start(flag)
755 # wait for it to start
756 flag.wait()
757 # try to connect
758 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000759 s = ssl.wrap_socket(socket.socket(),
760 certfile=CERTFILE,
761 ca_certs=CERTFILE,
762 cert_reqs=ssl.CERT_REQUIRED,
763 ssl_version=ssl.PROTOCOL_SSLv23)
764 s.connect((HOST, server.port))
765 cert = s.getpeercert()
766 self.assertTrue(cert, "Can't get peer certificate.")
767 cipher = s.cipher()
768 if support.verbose:
769 sys.stdout.write(pprint.pformat(cert) + '\n')
770 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
771 if 'subject' not in cert:
772 self.fail("No subject field in certificate: %s." %
773 pprint.pformat(cert))
774 if ((('organizationName', 'Python Software Foundation'),)
775 not in cert['subject']):
776 self.fail(
777 "Missing or invalid 'organizationName' field in certificate subject; "
778 "should be 'Python Software Foundation'.")
779 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000780 finally:
781 server.stop()
782 server.join()
783
Antoine Pitrou91382d82010-04-28 21:39:56 +0000784 def test_empty_cert(self):
785 """Connecting with an empty cert file"""
786 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
787 "nullcert.pem"))
788 def test_malformed_cert(self):
789 """Connecting with a badly formatted certificate (syntax error)"""
790 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
791 "badcert.pem"))
792 def test_nonexisting_cert(self):
793 """Connecting with a non-existing cert file"""
794 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
795 "wrongcert.pem"))
796 def test_malformed_key(self):
797 """Connecting with a badly formatted key (syntax error)"""
798 bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
799 "badkey.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000800
Antoine Pitrou91382d82010-04-28 21:39:56 +0000801 def test_rude_shutdown(self):
802 """A brutal shutdown of an SSL server should raise an IOError
803 in the client when attempting handshake.
804 """
Trent Nelson6b240cd2008-04-10 20:12:06 +0000805 listener_ready = threading.Event()
806 listener_gone = threading.Event()
Antoine Pitrou91382d82010-04-28 21:39:56 +0000807
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000808 s = socket.socket()
809 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000810
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000811 # `listener` runs in a thread. It sits in an accept() until
812 # the main thread connects. Then it rudely closes the socket,
813 # and sets Event `listener_gone` to let the main thread know
814 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000815 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000816 s.listen(5)
817 listener_ready.set()
818 s.accept()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000819 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000820 listener_gone.set()
821
822 def connector():
823 listener_ready.wait()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000824 c = socket.socket()
825 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000826 listener_gone.wait()
827 try:
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000828 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000829 except IOError:
830 pass
831 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000832 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +0000833
834 t = threading.Thread(target=listener)
835 t.start()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000836 try:
837 connector()
838 finally:
839 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000840
Antoine Pitrou91382d82010-04-28 21:39:56 +0000841 def test_protocol_sslv2(self):
842 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000843 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000844 sys.stdout.write("\ntest_protocol_sslv2 disabled, "
845 "as it fails on OpenSSL 1.0.0+")
846 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000847 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
848 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
849 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
850 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
851 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
852 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000853
Antoine Pitrou91382d82010-04-28 21:39:56 +0000854 def test_protocol_sslv23(self):
855 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000856 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000857 sys.stdout.write("\ntest_protocol_sslv23 disabled, "
858 "as it fails on OpenSSL 1.0.0+")
859 return
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000860 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000861 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000862 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000863 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000864 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865 sys.stdout.write(
866 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
867 % str(x))
Antoine Pitrou91382d82010-04-28 21:39:56 +0000868 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
869 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
870 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000871
Antoine Pitrou91382d82010-04-28 21:39:56 +0000872 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
873 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
874 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000875
Antoine Pitrou91382d82010-04-28 21:39:56 +0000876 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
877 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
878 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000879
Antoine Pitrou91382d82010-04-28 21:39:56 +0000880 def test_protocol_sslv3(self):
881 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000882 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000883 sys.stdout.write("\ntest_protocol_sslv3 disabled, "
884 "as it fails on OpenSSL 1.0.0+")
885 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000886 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
887 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
888 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
889 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
890 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
891 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000892
Antoine Pitrou91382d82010-04-28 21:39:56 +0000893 def test_protocol_tlsv1(self):
894 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000895 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000896 sys.stdout.write("\ntest_protocol_tlsv1 disabled, "
897 "as it fails on OpenSSL 1.0.0+")
898 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000899 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
900 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
901 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
902 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
903 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
904 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000905
Antoine Pitrou91382d82010-04-28 21:39:56 +0000906 def test_starttls(self):
907 """Switching from clear text to encrypted and back again."""
908 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 +0000909
Trent Nelson78520002008-04-10 20:54:35 +0000910 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000911 ssl_version=ssl.PROTOCOL_TLSv1,
912 starttls_server=True,
913 chatty=True,
914 connectionchatty=True)
915 flag = threading.Event()
916 server.start(flag)
917 # wait for it to start
918 flag.wait()
919 # try to connect
920 wrapped = False
921 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000922 s = socket.socket()
923 s.setblocking(1)
924 s.connect((HOST, server.port))
925 if support.verbose:
926 sys.stdout.write("\n")
927 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000928 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000929 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000930 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000931 if wrapped:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000932 conn.write(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000933 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000934 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000935 s.send(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000936 outdata = s.recv(1024)
Antoine Pitrou91382d82010-04-28 21:39:56 +0000937 msg = outdata.strip().lower()
938 if indata == b"STARTTLS" and msg.startswith(b"ok"):
939 # STARTTLS ok, switch to secure mode
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000940 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000941 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000942 " client: read %r from server, starting TLS...\n"
943 % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000944 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
945 wrapped = True
Antoine Pitrou91382d82010-04-28 21:39:56 +0000946 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
947 # ENDTLS ok, switch back to clear text
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000948 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000949 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000950 " client: read %r from server, ending TLS...\n"
951 % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000952 s = conn.unwrap()
953 wrapped = False
954 else:
955 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000956 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000957 " client: read %r from server\n" % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000958 if support.verbose:
959 sys.stdout.write(" client: closing connection.\n")
960 if wrapped:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000961 conn.write(b"over\n")
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000962 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000963 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000964 if wrapped:
965 conn.close()
966 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000967 s.close()
968 finally:
969 server.stop()
970 server.join()
971
Antoine Pitrou91382d82010-04-28 21:39:56 +0000972 def test_socketserver(self):
973 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +0000974 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000975 flag = threading.Event()
976 server.start(flag)
977 # wait for it to start
978 flag.wait()
979 # try to connect
980 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000981 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000982 sys.stdout.write('\n')
Antoine Pitrou91382d82010-04-28 21:39:56 +0000983 with open(CERTFILE, 'rb') as f:
984 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000985 d2 = ''
986 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +0000987 url = 'https://%s:%d/%s' % (
988 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000989 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +0000990 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991 if dlen and (int(dlen) > 0):
992 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000993 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000994 sys.stdout.write(
995 " client: read %d bytes from remote server '%s'\n"
996 % (len(d2), server))
997 f.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000998 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000999 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001000 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001001 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001002 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001003 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001004 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001005 server.join()
1006
Antoine Pitrou91382d82010-04-28 21:39:56 +00001007 def test_asyncore_server(self):
1008 """Check the example asyncore integration."""
1009 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001010
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001011 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001012 sys.stdout.write("\n")
1013
Antoine Pitrou91382d82010-04-28 21:39:56 +00001014 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001015 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001016 flag = threading.Event()
1017 server.start(flag)
1018 # wait for it to start
1019 flag.wait()
1020 # try to connect
1021 try:
1022 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001023 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001024 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001025 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +00001026 " client: sending %r...\n" % indata)
1027 s.write(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001028 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001029 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001030 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001031 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001032 self.fail(
Antoine Pitrou91382d82010-04-28 21:39:56 +00001033 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1034 % (outdata[:20], len(outdata),
1035 indata[:20].lower(), len(indata)))
1036 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001037 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001038 sys.stdout.write(" client: closing connection.\n")
1039 s.close()
1040 finally:
1041 server.stop()
1042 server.join()
1043
Antoine Pitrou91382d82010-04-28 21:39:56 +00001044 def test_recv_send(self):
1045 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001046 if support.verbose:
1047 sys.stdout.write("\n")
1048
1049 server = ThreadedEchoServer(CERTFILE,
1050 certreqs=ssl.CERT_NONE,
1051 ssl_version=ssl.PROTOCOL_TLSv1,
1052 cacerts=CERTFILE,
1053 chatty=True,
1054 connectionchatty=False)
1055 flag = threading.Event()
1056 server.start(flag)
1057 # wait for it to start
1058 flag.wait()
1059 # try to connect
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001060 s = ssl.wrap_socket(socket.socket(),
1061 server_side=False,
1062 certfile=CERTFILE,
1063 ca_certs=CERTFILE,
1064 cert_reqs=ssl.CERT_NONE,
1065 ssl_version=ssl.PROTOCOL_TLSv1)
1066 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001067 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001068 # helper methods for standardising recv* method signatures
1069 def _recv_into():
1070 b = bytearray(b"\0"*100)
1071 count = s.recv_into(b)
1072 return b[:count]
1073
1074 def _recvfrom_into():
1075 b = bytearray(b"\0"*100)
1076 count, addr = s.recvfrom_into(b)
1077 return b[:count]
1078
1079 # (name, method, whether to expect success, *args)
1080 send_methods = [
1081 ('send', s.send, True, []),
1082 ('sendto', s.sendto, False, ["some.address"]),
1083 ('sendall', s.sendall, True, []),
1084 ]
1085 recv_methods = [
1086 ('recv', s.recv, True, []),
1087 ('recvfrom', s.recvfrom, False, ["some.address"]),
1088 ('recv_into', _recv_into, True, []),
1089 ('recvfrom_into', _recvfrom_into, False, []),
1090 ]
1091 data_prefix = "PREFIX_"
1092
1093 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001094 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001095 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001096 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001097 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001098 if outdata != indata.lower():
1099 raise support.TestFailed(
1100 "While sending with <<{name:s}>> bad data "
Antoine Pitrou91382d82010-04-28 21:39:56 +00001101 "<<{outdata:r}>> ({nout:d}) received; "
1102 "expected <<{indata:r}>> ({nin:d})\n".format(
1103 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001104 nout=len(outdata),
Antoine Pitrou91382d82010-04-28 21:39:56 +00001105 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001106 )
1107 )
1108 except ValueError as e:
1109 if expect_success:
1110 raise support.TestFailed(
1111 "Failed to send with method <<{name:s}>>; "
1112 "expected to succeed.\n".format(name=meth_name)
1113 )
1114 if not str(e).startswith(meth_name):
1115 raise support.TestFailed(
1116 "Method <<{name:s}>> failed with unexpected "
1117 "exception message: {exp:s}\n".format(
1118 name=meth_name, exp=e
1119 )
1120 )
1121
1122 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001123 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001124 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001125 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001126 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001127 if outdata != indata.lower():
1128 raise support.TestFailed(
1129 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou91382d82010-04-28 21:39:56 +00001130 "<<{outdata:r}>> ({nout:d}) received; "
1131 "expected <<{indata:r}>> ({nin:d})\n".format(
1132 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001133 nout=len(outdata),
Antoine Pitrou91382d82010-04-28 21:39:56 +00001134 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001135 )
1136 )
1137 except ValueError as e:
1138 if expect_success:
1139 raise support.TestFailed(
1140 "Failed to receive with method <<{name:s}>>; "
1141 "expected to succeed.\n".format(name=meth_name)
1142 )
1143 if not str(e).startswith(meth_name):
1144 raise support.TestFailed(
1145 "Method <<{name:s}>> failed with unexpected "
1146 "exception message: {exp:s}\n".format(
1147 name=meth_name, exp=e
1148 )
1149 )
1150 # consume data
1151 s.read()
1152
Antoine Pitrou91382d82010-04-28 21:39:56 +00001153 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001154 s.close()
1155 finally:
1156 server.stop()
1157 server.join()
1158
Antoine Pitrouec146182010-04-24 21:30:20 +00001159 def test_handshake_timeout(self):
1160 # Issue #5103: SSL handshake must respect the socket timeout
1161 server = socket.socket(socket.AF_INET)
1162 host = "127.0.0.1"
1163 port = support.bind_port(server)
1164 started = threading.Event()
1165 finish = False
1166
1167 def serve():
1168 server.listen(5)
1169 started.set()
1170 conns = []
1171 while not finish:
1172 r, w, e = select.select([server], [], [], 0.1)
1173 if server in r:
1174 # Let the socket hang around rather than having
1175 # it closed by garbage collection.
1176 conns.append(server.accept()[0])
1177
1178 t = threading.Thread(target=serve)
1179 t.start()
1180 started.wait()
1181
1182 try:
Antoine Pitrouc2203f92010-04-24 22:07:51 +00001183 try:
1184 c = socket.socket(socket.AF_INET)
1185 c.settimeout(0.2)
1186 c.connect((host, port))
1187 # Will attempt handshake and time out
1188 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1189 ssl.wrap_socket, c)
1190 finally:
1191 c.close()
Antoine Pitrouec146182010-04-24 21:30:20 +00001192 try:
1193 c = socket.socket(socket.AF_INET)
1194 c = ssl.wrap_socket(c)
1195 c.settimeout(0.2)
1196 # Will attempt handshake and time out
1197 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1198 c.connect, (host, port))
1199 finally:
1200 c.close()
1201 finally:
1202 finish = True
1203 t.join()
1204 server.close()
1205
Bill Janssen58afe4c2008-09-08 16:45:19 +00001206
Thomas Woutersed03b412007-08-28 21:37:11 +00001207def test_main(verbose=False):
1208 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001209 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001210
Trent Nelson78520002008-04-10 20:54:35 +00001211 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Thomas Woutersed03b412007-08-28 21:37:11 +00001212 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
1213 "keycert.pem")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001214 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1215 os.path.dirname(__file__) or os.curdir,
1216 "https_svn_python_org_root.pem")
1217
1218 if (not os.path.exists(CERTFILE) or
1219 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001220 raise support.TestFailed("Can't read certificate files!")
Bill Janssen6e027db2007-11-15 22:23:56 +00001221
Thomas Woutersed03b412007-08-28 21:37:11 +00001222 tests = [BasicTests]
1223
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001224 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001225 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001226
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001227 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001228 thread_info = support.threading_setup()
1229 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001230 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001231
Antoine Pitrou91382d82010-04-28 21:39:56 +00001232 try:
1233 support.run_unittest(*tests)
1234 finally:
1235 if _have_threads:
1236 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001237
1238if __name__ == "__main__":
1239 test_main()