blob: f2f4f80fc69bf7565070226241211b86d29a189c [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):
Victor Stinneree18b6f2011-05-10 00:38:00 +020043 #ssl.PROTOCOL_SSLv2
Thomas Wouters1b7f8912007-09-19 03:06:30 +000044 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 Pitrou50778ab2011-01-08 10:31:09 +0000231 with support.transient_internet("sha256.tbs-internet.com"):
Antoine Pitrou4d7979b2010-09-07 21:22:56 +0000232 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:
Georg Brandlf55aa802010-11-26 08:59:40 +0000638 sys.stdout.write("\nsocket.error is %s\n" % x.args[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
Victor Stinneree18b6f2011-05-10 00:38:00 +0200841 @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), "need SSLv2")
Antoine Pitrou91382d82010-04-28 21:39:56 +0000842 def test_protocol_sslv2(self):
843 """Connecting to an SSLv2 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000844 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000845 sys.stdout.write("\ntest_protocol_sslv2 disabled, "
846 "as it fails on OpenSSL 1.0.0+")
847 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000848 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
849 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
850 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
851 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
852 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
853 try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000854
Antoine Pitrou91382d82010-04-28 21:39:56 +0000855 def test_protocol_sslv23(self):
856 """Connecting to an SSLv23 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000857 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000858 sys.stdout.write("\ntest_protocol_sslv23 disabled, "
859 "as it fails on OpenSSL 1.0.0+")
860 return
Victor Stinneree18b6f2011-05-10 00:38:00 +0200861 if hasattr(ssl, 'PROTOCOL_SSLv2'):
862 try:
863 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
864 except (ssl.SSLError, socket.error) as x:
865 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
866 if support.verbose:
867 sys.stdout.write(
868 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
869 % str(x))
Antoine Pitrou91382d82010-04-28 21:39:56 +0000870 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
871 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
872 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000873
Antoine Pitrou91382d82010-04-28 21:39:56 +0000874 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
875 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
876 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000877
Antoine Pitrou91382d82010-04-28 21:39:56 +0000878 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
879 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
880 try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000881
Antoine Pitrou91382d82010-04-28 21:39:56 +0000882 def test_protocol_sslv3(self):
883 """Connecting to an SSLv3 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000884 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000885 sys.stdout.write("\ntest_protocol_sslv3 disabled, "
886 "as it fails on OpenSSL 1.0.0+")
887 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000888 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
889 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
890 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +0200891 if hasattr(ssl, 'PROTOCOL_SSLv2'):
892 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou91382d82010-04-28 21:39:56 +0000893 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
894 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895
Antoine Pitrou91382d82010-04-28 21:39:56 +0000896 def test_protocol_tlsv1(self):
897 """Connecting to a TLSv1 server with various client options"""
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000898 if support.verbose:
Antoine Pitrou452a5802010-05-06 13:54:43 +0000899 sys.stdout.write("\ntest_protocol_tlsv1 disabled, "
900 "as it fails on OpenSSL 1.0.0+")
901 return
Antoine Pitrou91382d82010-04-28 21:39:56 +0000902 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
903 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
904 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
Victor Stinneree18b6f2011-05-10 00:38:00 +0200905 if hasattr(ssl, 'PROTOCOL_SSLv2'):
906 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
Antoine Pitrou91382d82010-04-28 21:39:56 +0000907 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
908 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000909
Antoine Pitrou91382d82010-04-28 21:39:56 +0000910 def test_starttls(self):
911 """Switching from clear text to encrypted and back again."""
912 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 +0000913
Trent Nelson78520002008-04-10 20:54:35 +0000914 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000915 ssl_version=ssl.PROTOCOL_TLSv1,
916 starttls_server=True,
917 chatty=True,
918 connectionchatty=True)
919 flag = threading.Event()
920 server.start(flag)
921 # wait for it to start
922 flag.wait()
923 # try to connect
924 wrapped = False
925 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000926 s = socket.socket()
927 s.setblocking(1)
928 s.connect((HOST, server.port))
929 if support.verbose:
930 sys.stdout.write("\n")
931 for indata in msgs:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000932 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000933 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000934 " client: sending %r...\n" % indata)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000935 if wrapped:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000936 conn.write(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000937 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000938 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000939 s.send(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000940 outdata = s.recv(1024)
Antoine Pitrou91382d82010-04-28 21:39:56 +0000941 msg = outdata.strip().lower()
942 if indata == b"STARTTLS" and msg.startswith(b"ok"):
943 # STARTTLS ok, switch to secure mode
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000944 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000945 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000946 " client: read %r from server, starting TLS...\n"
947 % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000948 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
949 wrapped = True
Antoine Pitrou91382d82010-04-28 21:39:56 +0000950 elif indata == b"ENDTLS" and msg.startswith(b"ok"):
951 # ENDTLS ok, switch back to clear text
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000952 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000953 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000954 " client: read %r from server, ending TLS...\n"
955 % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000956 s = conn.unwrap()
957 wrapped = False
958 else:
959 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000960 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +0000961 " client: read %r from server\n" % msg)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000962 if support.verbose:
963 sys.stdout.write(" client: closing connection.\n")
964 if wrapped:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000965 conn.write(b"over\n")
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000966 else:
Antoine Pitrou91382d82010-04-28 21:39:56 +0000967 s.send(b"over\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000968 if wrapped:
969 conn.close()
970 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000971 s.close()
972 finally:
973 server.stop()
974 server.join()
975
Antoine Pitrou91382d82010-04-28 21:39:56 +0000976 def test_socketserver(self):
977 """Using a SocketServer to create and manage SSL connections."""
Trent Nelson78520002008-04-10 20:54:35 +0000978 server = OurHTTPSServer(CERTFILE)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000979 flag = threading.Event()
980 server.start(flag)
981 # wait for it to start
982 flag.wait()
983 # try to connect
984 try:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000985 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000986 sys.stdout.write('\n')
Antoine Pitrou91382d82010-04-28 21:39:56 +0000987 with open(CERTFILE, 'rb') as f:
988 d1 = f.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000989 d2 = ''
990 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +0000991 url = 'https://%s:%d/%s' % (
992 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000993 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +0000994 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000995 if dlen and (int(dlen) > 0):
996 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000997 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 sys.stdout.write(
999 " client: read %d bytes from remote server '%s'\n"
1000 % (len(d2), server))
1001 f.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001002 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001003 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001004 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001005 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001006 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001007 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001008 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001009 server.join()
1010
Antoine Pitrou91382d82010-04-28 21:39:56 +00001011 def test_asyncore_server(self):
1012 """Check the example asyncore integration."""
1013 indata = "TEST MESSAGE of mixed case\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +00001014
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001015 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001016 sys.stdout.write("\n")
1017
Antoine Pitrou91382d82010-04-28 21:39:56 +00001018 indata = b"FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001019 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001020 flag = threading.Event()
1021 server.start(flag)
1022 # wait for it to start
1023 flag.wait()
1024 # try to connect
1025 try:
1026 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001027 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001028 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001029 sys.stdout.write(
Antoine Pitrou91382d82010-04-28 21:39:56 +00001030 " client: sending %r...\n" % indata)
1031 s.write(indata)
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001032 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001033 if support.verbose:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001034 sys.stdout.write(" client: read %r\n" % outdata)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001035 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001036 self.fail(
Antoine Pitrou91382d82010-04-28 21:39:56 +00001037 "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n"
1038 % (outdata[:20], len(outdata),
1039 indata[:20].lower(), len(indata)))
1040 s.write(b"over\n")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001041 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001042 sys.stdout.write(" client: closing connection.\n")
1043 s.close()
1044 finally:
1045 server.stop()
1046 server.join()
1047
Antoine Pitrou91382d82010-04-28 21:39:56 +00001048 def test_recv_send(self):
1049 """Test recv(), send() and friends."""
Bill Janssen58afe4c2008-09-08 16:45:19 +00001050 if support.verbose:
1051 sys.stdout.write("\n")
1052
1053 server = ThreadedEchoServer(CERTFILE,
1054 certreqs=ssl.CERT_NONE,
1055 ssl_version=ssl.PROTOCOL_TLSv1,
1056 cacerts=CERTFILE,
1057 chatty=True,
1058 connectionchatty=False)
1059 flag = threading.Event()
1060 server.start(flag)
1061 # wait for it to start
1062 flag.wait()
1063 # try to connect
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001064 s = ssl.wrap_socket(socket.socket(),
1065 server_side=False,
1066 certfile=CERTFILE,
1067 ca_certs=CERTFILE,
1068 cert_reqs=ssl.CERT_NONE,
1069 ssl_version=ssl.PROTOCOL_TLSv1)
1070 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001071 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001072 # helper methods for standardising recv* method signatures
1073 def _recv_into():
1074 b = bytearray(b"\0"*100)
1075 count = s.recv_into(b)
1076 return b[:count]
1077
1078 def _recvfrom_into():
1079 b = bytearray(b"\0"*100)
1080 count, addr = s.recvfrom_into(b)
1081 return b[:count]
1082
1083 # (name, method, whether to expect success, *args)
1084 send_methods = [
1085 ('send', s.send, True, []),
1086 ('sendto', s.sendto, False, ["some.address"]),
1087 ('sendall', s.sendall, True, []),
1088 ]
1089 recv_methods = [
1090 ('recv', s.recv, True, []),
1091 ('recvfrom', s.recvfrom, False, ["some.address"]),
1092 ('recv_into', _recv_into, True, []),
1093 ('recvfrom_into', _recvfrom_into, False, []),
1094 ]
1095 data_prefix = "PREFIX_"
1096
1097 for meth_name, send_meth, expect_success, args in send_methods:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001098 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001099 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001100 send_meth(indata, *args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001101 outdata = s.read()
Bill Janssen58afe4c2008-09-08 16:45:19 +00001102 if outdata != indata.lower():
1103 raise support.TestFailed(
1104 "While sending with <<{name:s}>> bad data "
Antoine Pitrou91382d82010-04-28 21:39:56 +00001105 "<<{outdata:r}>> ({nout:d}) received; "
1106 "expected <<{indata:r}>> ({nin:d})\n".format(
1107 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001108 nout=len(outdata),
Antoine Pitrou91382d82010-04-28 21:39:56 +00001109 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001110 )
1111 )
1112 except ValueError as e:
1113 if expect_success:
1114 raise support.TestFailed(
1115 "Failed to send with method <<{name:s}>>; "
1116 "expected to succeed.\n".format(name=meth_name)
1117 )
1118 if not str(e).startswith(meth_name):
1119 raise support.TestFailed(
1120 "Method <<{name:s}>> failed with unexpected "
1121 "exception message: {exp:s}\n".format(
1122 name=meth_name, exp=e
1123 )
1124 )
1125
1126 for meth_name, recv_meth, expect_success, args in recv_methods:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001127 indata = (data_prefix + meth_name).encode('ascii')
Bill Janssen58afe4c2008-09-08 16:45:19 +00001128 try:
Antoine Pitrou91382d82010-04-28 21:39:56 +00001129 s.send(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001130 outdata = recv_meth(*args)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001131 if outdata != indata.lower():
1132 raise support.TestFailed(
1133 "While receiving with <<{name:s}>> bad data "
Antoine Pitrou91382d82010-04-28 21:39:56 +00001134 "<<{outdata:r}>> ({nout:d}) received; "
1135 "expected <<{indata:r}>> ({nin:d})\n".format(
1136 name=meth_name, outdata=outdata[:20],
Bill Janssen58afe4c2008-09-08 16:45:19 +00001137 nout=len(outdata),
Antoine Pitrou91382d82010-04-28 21:39:56 +00001138 indata=indata[:20], nin=len(indata)
Bill Janssen58afe4c2008-09-08 16:45:19 +00001139 )
1140 )
1141 except ValueError as e:
1142 if expect_success:
1143 raise support.TestFailed(
1144 "Failed to receive with method <<{name:s}>>; "
1145 "expected to succeed.\n".format(name=meth_name)
1146 )
1147 if not str(e).startswith(meth_name):
1148 raise support.TestFailed(
1149 "Method <<{name:s}>> failed with unexpected "
1150 "exception message: {exp:s}\n".format(
1151 name=meth_name, exp=e
1152 )
1153 )
1154 # consume data
1155 s.read()
1156
Antoine Pitrou91382d82010-04-28 21:39:56 +00001157 s.write(b"over\n")
Bill Janssen58afe4c2008-09-08 16:45:19 +00001158 s.close()
1159 finally:
1160 server.stop()
1161 server.join()
1162
Antoine Pitrouec146182010-04-24 21:30:20 +00001163 def test_handshake_timeout(self):
1164 # Issue #5103: SSL handshake must respect the socket timeout
1165 server = socket.socket(socket.AF_INET)
1166 host = "127.0.0.1"
1167 port = support.bind_port(server)
1168 started = threading.Event()
1169 finish = False
1170
1171 def serve():
1172 server.listen(5)
1173 started.set()
1174 conns = []
1175 while not finish:
1176 r, w, e = select.select([server], [], [], 0.1)
1177 if server in r:
1178 # Let the socket hang around rather than having
1179 # it closed by garbage collection.
1180 conns.append(server.accept()[0])
1181
1182 t = threading.Thread(target=serve)
1183 t.start()
1184 started.wait()
1185
1186 try:
Antoine Pitrouc2203f92010-04-24 22:07:51 +00001187 try:
1188 c = socket.socket(socket.AF_INET)
1189 c.settimeout(0.2)
1190 c.connect((host, port))
1191 # Will attempt handshake and time out
1192 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1193 ssl.wrap_socket, c)
1194 finally:
1195 c.close()
Antoine Pitrouec146182010-04-24 21:30:20 +00001196 try:
1197 c = socket.socket(socket.AF_INET)
1198 c = ssl.wrap_socket(c)
1199 c.settimeout(0.2)
1200 # Will attempt handshake and time out
1201 self.assertRaisesRegexp(ssl.SSLError, "timed out",
1202 c.connect, (host, port))
1203 finally:
1204 c.close()
1205 finally:
1206 finish = True
1207 t.join()
1208 server.close()
1209
Bill Janssen58afe4c2008-09-08 16:45:19 +00001210
Thomas Woutersed03b412007-08-28 21:37:11 +00001211def test_main(verbose=False):
1212 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +00001213 raise unittest.SkipTest("No SSL support")
Thomas Woutersed03b412007-08-28 21:37:11 +00001214
Trent Nelson78520002008-04-10 20:54:35 +00001215 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Thomas Woutersed03b412007-08-28 21:37:11 +00001216 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
1217 "keycert.pem")
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001218 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1219 os.path.dirname(__file__) or os.curdir,
1220 "https_svn_python_org_root.pem")
1221
1222 if (not os.path.exists(CERTFILE) or
1223 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001224 raise support.TestFailed("Can't read certificate files!")
Bill Janssen6e027db2007-11-15 22:23:56 +00001225
Thomas Woutersed03b412007-08-28 21:37:11 +00001226 tests = [BasicTests]
1227
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001228 if support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001229 tests.append(NetworkedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001230
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001231 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001232 thread_info = support.threading_setup()
1233 if thread_info and support.is_resource_enabled('network'):
Bill Janssen6e027db2007-11-15 22:23:56 +00001234 tests.append(ThreadedTests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001235
Antoine Pitrou91382d82010-04-28 21:39:56 +00001236 try:
1237 support.run_unittest(*tests)
1238 finally:
1239 if _have_threads:
1240 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001241
1242if __name__ == "__main__":
1243 test_main()