blob: 042d1797ba591e7878f00560ad954b1c14b9b8d8 [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
Georg Brandlfceab5a2008-01-19 20:08:23 +000042 def testSSLconnect(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000043 if not support.is_resource_enabled('network'):
Georg Brandlfceab5a2008-01-19 20:08:23 +000044 return
45 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
46 cert_reqs=ssl.CERT_NONE)
47 s.connect(("svn.python.org", 443))
48 c = s.getpeercert()
49 if c:
Antoine Pitrou66ffb262010-04-27 11:05:15 +000050 self.fail("Peer cert %s shouldn't be here!")
Georg Brandlfceab5a2008-01-19 20:08:23 +000051 s.close()
52
53 # this should fail because we have no verification certs
54 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
55 cert_reqs=ssl.CERT_REQUIRED)
56 try:
57 s.connect(("svn.python.org", 443))
58 except ssl.SSLError:
59 pass
60 finally:
61 s.close()
62
Thomas Wouters1b7f8912007-09-19 03:06:30 +000063 def testCrucialConstants(self):
64 ssl.PROTOCOL_SSLv2
65 ssl.PROTOCOL_SSLv23
66 ssl.PROTOCOL_SSLv3
67 ssl.PROTOCOL_TLSv1
68 ssl.CERT_NONE
69 ssl.CERT_OPTIONAL
70 ssl.CERT_REQUIRED
Thomas Woutersed03b412007-08-28 21:37:11 +000071
Thomas Wouters1b7f8912007-09-19 03:06:30 +000072 def testRAND(self):
73 v = ssl.RAND_status()
Benjamin Petersonee8712c2008-05-20 21:35:26 +000074 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000075 sys.stdout.write("\n RAND_status is %d (%s)\n"
76 % (v, (v and "sufficient randomness") or
77 "insufficient randomness"))
Thomas Woutersed03b412007-08-28 21:37:11 +000078 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000079 ssl.RAND_egd(1)
80 except TypeError:
81 pass
Thomas Woutersed03b412007-08-28 21:37:11 +000082 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000083 print("didn't raise TypeError")
84 ssl.RAND_add("this is a random string", 75.0)
Thomas Woutersed03b412007-08-28 21:37:11 +000085
Thomas Wouters1b7f8912007-09-19 03:06:30 +000086 def testParseCert(self):
87 # note that this uses an 'unofficial' function in _ssl.c,
88 # provided solely for this test, to exercise the certificate
89 # parsing code
90 p = ssl._ssl._test_decode_cert(CERTFILE, False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +000091 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +000092 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Thomas Woutersed03b412007-08-28 21:37:11 +000093
Thomas Wouters1b7f8912007-09-19 03:06:30 +000094 def testDERtoPEM(self):
95
96 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
97 d1 = ssl.PEM_cert_to_DER_cert(pem)
98 p2 = ssl.DER_cert_to_PEM_cert(d1)
99 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000100 self.assertEqual(d1, d2)
Antoine Pitrou00f905e2010-04-27 22:09:05 +0000101 if not p2.startswith(ssl.PEM_HEADER + '\n'):
102 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
103 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
104 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105
Antoine Pitrou78f4a9a2010-04-23 23:12:22 +0000106 @support.cpython_only
107 def test_refcycle(self):
108 # Issue #7943: an SSL object doesn't create reference cycles with
109 # itself.
110 s = socket.socket(socket.AF_INET)
111 ss = ssl.wrap_socket(s)
112 wr = weakref.ref(ss)
113 del ss
114 self.assertEqual(wr(), None)
115
Antoine Pitrouc2203f92010-04-24 22:07:51 +0000116 def test_timeout(self):
117 # Issue #8524: when creating an SSL socket, the timeout of the
118 # original socket should be retained.
119 for timeout in (None, 0.0, 5.0):
120 s = socket.socket(socket.AF_INET)
121 s.settimeout(timeout)
122 ss = ssl.wrap_socket(s)
123 self.assertEqual(timeout, ss.gettimeout())
124
Antoine Pitrou3b9b9ba2010-04-23 23:33:50 +0000125
Bill Janssen6e027db2007-11-15 22:23:56 +0000126class NetworkedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000127
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128 def testConnect(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
130 cert_reqs=ssl.CERT_NONE)
131 s.connect(("svn.python.org", 443))
132 c = s.getpeercert()
133 if c:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000134 self.fail("Peer cert %s shouldn't be here!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000135 s.close()
136
137 # this should fail because we have no verification certs
138 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
139 cert_reqs=ssl.CERT_REQUIRED)
Thomas Woutersed03b412007-08-28 21:37:11 +0000140 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000141 s.connect(("svn.python.org", 443))
142 except ssl.SSLError:
143 pass
144 finally:
145 s.close()
146
147 # this should succeed because we specify the root cert
148 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
149 cert_reqs=ssl.CERT_REQUIRED,
150 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
151 try:
152 s.connect(("svn.python.org", 443))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000153 finally:
154 s.close()
155
Antoine Pitroufe0f1172010-04-24 11:17:37 +0000156 @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
157 def test_makefile_close(self):
158 # Issue #5238: creating a file-like object with makefile() shouldn't
159 # delay closing the underlying "real socket" (here tested with its
160 # file descriptor, hence skipping the test under Windows).
161 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
162 ss.connect(("svn.python.org", 443))
163 fd = ss.fileno()
164 f = ss.makefile()
165 f.close()
166 # The fd is still open
167 os.read(fd, 0)
168 # Closing the SSL socket should close the fd too
169 ss.close()
170 gc.collect()
171 try:
172 os.read(fd, 0)
173 except OSError as e:
174 self.assertEqual(e.errno, errno.EBADF)
175 else:
176 self.fail("OSError wasn't raised")
177
Bill Janssen6e027db2007-11-15 22:23:56 +0000178 def testNonBlockingHandshake(self):
179 s = socket.socket(socket.AF_INET)
180 s.connect(("svn.python.org", 443))
181 s.setblocking(False)
182 s = ssl.wrap_socket(s,
183 cert_reqs=ssl.CERT_NONE,
184 do_handshake_on_connect=False)
185 count = 0
186 while True:
187 try:
188 count += 1
189 s.do_handshake()
190 break
191 except ssl.SSLError as err:
192 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
193 select.select([s], [], [])
194 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
195 select.select([], [s], [])
196 else:
197 raise
198 s.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000199 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000200 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000201
Bill Janssen54cc54c2007-12-14 22:08:56 +0000202 def testFetchServerCert(self):
203
204 pem = ssl.get_server_certificate(("svn.python.org", 443))
205 if not pem:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000206 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen54cc54c2007-12-14 22:08:56 +0000207
208 return
209
210 try:
211 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
212 except ssl.SSLError as x:
213 #should fail
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000214 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000215 sys.stdout.write("%s\n" % x)
216 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000217 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000218
219 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
220 if not pem:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000221 self.fail("No server certificate on svn.python.org:443!")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000222 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000223 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
224
Antoine Pitrou754b98c2010-04-22 18:47:06 +0000225 # Test disabled: OPENSSL_VERSION* not available in Python 3.1
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000226 def test_algorithms(self):
Antoine Pitrouae92a722010-04-22 18:46:16 +0000227 if support.verbose:
228 sys.stdout.write("test_algorithms disabled, "
229 "as it fails on some old OpenSSL versions")
230 return
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000231 # Issue #8484: all algorithms should be available when verifying a
232 # certificate.
Antoine Pitrouae92a722010-04-22 18:46:16 +0000233 # SHA256 was added in OpenSSL 0.9.8
234 if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15):
235 self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION)
Antoine Pitrouda6902c2010-04-21 19:52:52 +0000236 # NOTE: https://sha256.tbs-internet.com is another possible test host
237 remote = ("sha2.hboeck.de", 443)
238 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
239 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
240 cert_reqs=ssl.CERT_REQUIRED,
241 ca_certs=sha256_cert,)
242 with support.transient_internet():
243 try:
244 s.connect(remote)
245 if support.verbose:
246 sys.stdout.write("\nCipher with %r is %r\n" %
247 (remote, s.cipher()))
248 sys.stdout.write("Certificate is:\n%s\n" %
249 pprint.pformat(s.getpeercert()))
250 finally:
251 s.close()
252
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000253
254try:
255 import threading
256except ImportError:
257 _have_threads = False
258else:
259
260 _have_threads = True
261
262 class ThreadedEchoServer(threading.Thread):
263
264 class ConnectionHandler(threading.Thread):
265
266 """A mildly complicated class, because we want it to work both
267 with and without the SSL wrapper around the socket connection, so
268 that we can test the STARTTLS functionality."""
269
Bill Janssen6e027db2007-11-15 22:23:56 +0000270 def __init__(self, server, connsock, addr):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000271 self.server = server
272 self.running = False
273 self.sock = connsock
Bill Janssen6e027db2007-11-15 22:23:56 +0000274 self.addr = addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000275 self.sock.setblocking(1)
276 self.sslconn = None
277 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000278 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000279
280 def wrap_conn (self):
281 try:
282 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
283 certfile=self.server.certificate,
284 ssl_version=self.server.protocol,
285 ca_certs=self.server.cacerts,
286 cert_reqs=self.server.certreqs)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000287 except ssl.SSLError:
288 # XXX Various errors can have happened here, for example
289 # a mismatching protocol version, an invalid certificate,
290 # or a low-level bug. This should be made more discriminating.
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000291 if self.server.chatty:
Bill Janssen6e027db2007-11-15 22:23:56 +0000292 handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n")
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000293 self.running = False
294 self.server.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000295 self.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000296 return False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000297 else:
298 if self.server.certreqs == ssl.CERT_REQUIRED:
299 cert = self.sslconn.getpeercert()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000300 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000301 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
302 cert_binary = self.sslconn.getpeercert(True)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000303 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000304 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
305 cipher = self.sslconn.cipher()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000306 if support.verbose and self.server.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000307 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
308 return True
309
310 def read(self):
311 if self.sslconn:
312 return self.sslconn.read()
313 else:
314 return self.sock.recv(1024)
315
316 def write(self, bytes):
317 if self.sslconn:
318 return self.sslconn.write(bytes)
319 else:
320 return self.sock.send(bytes)
321
322 def close(self):
323 if self.sslconn:
324 self.sslconn.close()
325 else:
326 self.sock.close()
327
328 def run (self):
329 self.running = True
330 if not self.server.starttls_server:
331 if not self.wrap_conn():
332 return
333 while self.running:
334 try:
335 msg = self.read()
Bill Janssen6e027db2007-11-15 22:23:56 +0000336 amsg = (msg and str(msg, 'ASCII', 'strict')) or ''
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000337 if not msg:
338 # eof, so quit this handler
339 self.running = False
340 self.close()
Bill Janssen6e027db2007-11-15 22:23:56 +0000341 elif amsg.strip() == 'over':
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000342 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000343 sys.stdout.write(" server: client closed connection\n")
344 self.close()
345 return
Bill Janssen6e027db2007-11-15 22:23:56 +0000346 elif (self.server.starttls_server and
347 amsg.strip() == 'STARTTLS'):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000348 if support.verbose and self.server.connectionchatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000349 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
Bill Janssen6e027db2007-11-15 22:23:56 +0000350 self.write("OK\n".encode("ASCII", "strict"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000351 if not self.wrap_conn():
352 return
Bill Janssen40a0f662008-08-12 16:56:25 +0000353 elif (self.server.starttls_server and self.sslconn
354 and amsg.strip() == 'ENDTLS'):
355 if support.verbose and self.server.connectionchatty:
356 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
357 self.write("OK\n".encode("ASCII", "strict"))
358 self.sock = self.sslconn.unwrap()
359 self.sslconn = None
360 if support.verbose and self.server.connectionchatty:
361 sys.stdout.write(" server: connection is now unencrypted...\n")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000362 else:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000363 if (support.verbose and
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000364 self.server.connectionchatty):
365 ctype = (self.sslconn and "encrypted") or "unencrypted"
366 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
367 % (repr(msg), ctype, repr(msg.lower()), ctype))
Bill Janssen6e027db2007-11-15 22:23:56 +0000368 self.write(amsg.lower().encode('ASCII', 'strict'))
369 except socket.error:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000370 if self.server.chatty:
371 handle_error("Test server failure:\n")
372 self.close()
373 self.running = False
374 # normally, we'd just stop here, but for the test
375 # harness, we want to stop the server
376 self.server.stop()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000377
Trent Nelson78520002008-04-10 20:54:35 +0000378 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000379 certreqs=None, cacerts=None,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000380 chatty=True, connectionchatty=False, starttls_server=False):
381 if ssl_version is None:
382 ssl_version = ssl.PROTOCOL_TLSv1
383 if certreqs is None:
384 certreqs = ssl.CERT_NONE
385 self.certificate = certificate
386 self.protocol = ssl_version
387 self.certreqs = certreqs
388 self.cacerts = cacerts
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000389 self.chatty = chatty
390 self.connectionchatty = connectionchatty
391 self.starttls_server = starttls_server
392 self.sock = socket.socket()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000393 self.port = support.bind_port(self.sock)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000394 self.flag = None
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000395 self.active = False
396 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000397 self.daemon = True
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000398
399 def start (self, flag=None):
400 self.flag = flag
401 threading.Thread.start(self)
402
403 def run (self):
Antoine Pitroube168132010-04-27 10:41:37 +0000404 self.sock.settimeout(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000405 self.sock.listen(5)
406 self.active = True
407 if self.flag:
408 # signal an event
409 self.flag.set()
410 while self.active:
411 try:
412 newconn, connaddr = self.sock.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000413 if support.verbose and self.chatty:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000414 sys.stdout.write(' server: new connection from '
Bill Janssen6e027db2007-11-15 22:23:56 +0000415 + repr(connaddr) + '\n')
416 handler = self.ConnectionHandler(self, newconn, connaddr)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000417 handler.start()
418 except socket.timeout:
419 pass
420 except KeyboardInterrupt:
421 self.stop()
Bill Janssen6e027db2007-11-15 22:23:56 +0000422 self.sock.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000423
424 def stop (self):
425 self.active = False
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000426
Bill Janssen54cc54c2007-12-14 22:08:56 +0000427 class OurHTTPSServer(threading.Thread):
428
429 # This one's based on HTTPServer, which is based on SocketServer
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000430
431 class HTTPSServer(HTTPServer):
432
433 def __init__(self, server_address, RequestHandlerClass, certfile):
434
435 HTTPServer.__init__(self, server_address, RequestHandlerClass)
436 # we assume the certfile contains both private key and certificate
437 self.certfile = certfile
438 self.active = False
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000439 self.active_lock = threading.Lock()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000440 self.allow_reuse_address = True
441
Bill Janssen6e027db2007-11-15 22:23:56 +0000442 def __str__(self):
443 return ('<%s %s:%s>' %
444 (self.__class__.__name__,
445 self.server_name,
446 self.server_port))
447
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000448 def get_request (self):
449 # override this to wrap socket with SSL
450 sock, addr = self.socket.accept()
451 sslconn = ssl.wrap_socket(sock, server_side=True,
452 certfile=self.certfile)
453 return sslconn, addr
454
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000455 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
456
457 # need to override translate_path to get a known root,
458 # instead of using os.curdir, since the test could be
459 # run from anywhere
460
461 server_version = "TestHTTPS/1.0"
462
463 root = None
464
465 def translate_path(self, path):
466 """Translate a /-separated PATH to the local filename syntax.
467
468 Components that mean special things to the local file system
469 (e.g. drive or directory names) are ignored. (XXX They should
470 probably be diagnosed.)
471
472 """
473 # abandon query parameters
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000474 path = urllib.parse.urlparse(path)[2]
475 path = os.path.normpath(urllib.parse.unquote(path))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000476 words = path.split('/')
477 words = filter(None, words)
478 path = self.root
479 for word in words:
480 drive, word = os.path.splitdrive(word)
481 head, word = os.path.split(word)
482 if word in self.root: continue
483 path = os.path.join(path, word)
484 return path
485
486 def log_message(self, format, *args):
487
488 # we override this to suppress logging unless "verbose"
489
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000490 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000491 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
492 (self.server.server_address,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000493 self.server.server_port,
494 self.request.cipher(),
495 self.log_date_time_string(),
496 format%args))
Thomas Woutersed03b412007-08-28 21:37:11 +0000497
498
Trent Nelson78520002008-04-10 20:54:35 +0000499 def __init__(self, certfile):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000500 self.flag = None
501 self.active = False
502 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
503 self.server = self.HTTPSServer(
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000504 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
505 self.port = self.server.server_port
Thomas Woutersed03b412007-08-28 21:37:11 +0000506 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000507 self.daemon = True
Thomas Woutersed03b412007-08-28 21:37:11 +0000508
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000509 def __str__(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000510 return "<%s %s>" % (self.__class__.__name__, self.server)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000511
512 def start (self, flag=None):
513 self.flag = flag
514 threading.Thread.start(self)
515
Thomas Woutersed03b412007-08-28 21:37:11 +0000516 def run (self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000517 self.active = True
518 if self.flag:
519 self.flag.set()
Antoine Pitroube168132010-04-27 10:41:37 +0000520 self.server.serve_forever(0.05)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000521 self.active = False
522
523 def stop (self):
524 self.active = False
Antoine Pitroube168132010-04-27 10:41:37 +0000525 self.server.shutdown()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000526
527
Bill Janssen54cc54c2007-12-14 22:08:56 +0000528 class AsyncoreEchoServer(threading.Thread):
529
530 # this one's based on asyncore.dispatcher
531
532 class EchoServer (asyncore.dispatcher):
533
534 class ConnectionHandler (asyncore.dispatcher_with_send):
535
536 def __init__(self, conn, certfile):
537 self.socket = ssl.wrap_socket(conn, server_side=True,
538 certfile=certfile,
539 do_handshake_on_connect=False)
540 asyncore.dispatcher_with_send.__init__(self, self.socket)
Antoine Pitrouec146182010-04-24 21:30:20 +0000541 self._ssl_accepting = True
542 self._do_ssl_handshake()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000543
544 def readable(self):
545 if isinstance(self.socket, ssl.SSLSocket):
546 while self.socket.pending() > 0:
547 self.handle_read_event()
548 return True
549
Antoine Pitrouec146182010-04-24 21:30:20 +0000550 def _do_ssl_handshake(self):
551 try:
552 self.socket.do_handshake()
553 except ssl.SSLError as err:
554 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
555 ssl.SSL_ERROR_WANT_WRITE):
556 return
557 elif err.args[0] == ssl.SSL_ERROR_EOF:
558 return self.handle_close()
559 raise
560 except socket.error as err:
561 if err.args[0] == errno.ECONNABORTED:
562 return self.handle_close()
Bill Janssen54cc54c2007-12-14 22:08:56 +0000563 else:
Antoine Pitrouec146182010-04-24 21:30:20 +0000564 self._ssl_accepting = False
565
566 def handle_read(self):
567 if self._ssl_accepting:
568 self._do_ssl_handshake()
569 else:
570 data = self.recv(1024)
571 if support.verbose:
572 sys.stdout.write(" server: read %s from client\n" % repr(data))
573 if not data:
574 self.close()
575 else:
576 self.send(str(data, 'ASCII', 'strict').lower().encode('ASCII', 'strict'))
Bill Janssen54cc54c2007-12-14 22:08:56 +0000577
578 def handle_close(self):
Bill Janssen2f5799b2008-06-29 00:08:12 +0000579 self.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000580 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000581 sys.stdout.write(" server: closed connection %s\n" % self.socket)
582
583 def handle_error(self):
584 raise
585
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000586 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000587 self.certfile = certfile
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000588 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
589 self.port = support.bind_port(sock, '')
590 asyncore.dispatcher.__init__(self, sock)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000591 self.listen(5)
592
593 def handle_accept(self):
594 sock_obj, addr = self.accept()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000595 if support.verbose:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000596 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
597 self.ConnectionHandler(sock_obj, self.certfile)
598
599 def handle_error(self):
600 raise
601
Trent Nelson78520002008-04-10 20:54:35 +0000602 def __init__(self, certfile):
Bill Janssen54cc54c2007-12-14 22:08:56 +0000603 self.flag = None
604 self.active = False
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000605 self.server = self.EchoServer(certfile)
606 self.port = self.server.port
Bill Janssen54cc54c2007-12-14 22:08:56 +0000607 threading.Thread.__init__(self)
Benjamin Peterson4171da52008-08-18 21:11:09 +0000608 self.daemon = True
Bill Janssen54cc54c2007-12-14 22:08:56 +0000609
610 def __str__(self):
611 return "<%s %s>" % (self.__class__.__name__, self.server)
612
613 def start (self, flag=None):
614 self.flag = flag
615 threading.Thread.start(self)
616
617 def run (self):
618 self.active = True
619 if self.flag:
620 self.flag.set()
621 while self.active:
622 try:
623 asyncore.loop(1)
624 except:
625 pass
626
627 def stop (self):
628 self.active = False
629 self.server.close()
630
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000631 def badCertTest (certfile):
Trent Nelson78520002008-04-10 20:54:35 +0000632 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000633 certreqs=ssl.CERT_REQUIRED,
Bill Janssen6e027db2007-11-15 22:23:56 +0000634 cacerts=CERTFILE, chatty=False,
635 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000636 flag = threading.Event()
637 server.start(flag)
638 # wait for it to start
639 flag.wait()
640 # try to connect
641 try:
Thomas Woutersed03b412007-08-28 21:37:11 +0000642 try:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000643 s = ssl.wrap_socket(socket.socket(),
644 certfile=certfile,
645 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelson78520002008-04-10 20:54:35 +0000646 s.connect((HOST, server.port))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000647 except ssl.SSLError as x:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000648 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000649 sys.stdout.write("\nSSLError is %s\n" % x.args[1])
Antoine Pitrou537bed62010-04-27 13:16:06 +0000650 except socket.error as x:
651 if test_support.verbose:
652 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000653 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000654 self.fail("Use of invalid cert should have failed!")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000655 finally:
656 server.stop()
657 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000658
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000659 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
Bill Janssen6e027db2007-11-15 22:23:56 +0000660 client_certfile, client_protocol=None,
661 indata="FOO\n",
662 chatty=False, connectionchatty=False):
Thomas Woutersed03b412007-08-28 21:37:11 +0000663
Trent Nelson78520002008-04-10 20:54:35 +0000664 server = ThreadedEchoServer(certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000665 certreqs=certreqs,
666 ssl_version=protocol,
667 cacerts=cacertsfile,
668 chatty=chatty,
Bill Janssen6e027db2007-11-15 22:23:56 +0000669 connectionchatty=False)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000670 flag = threading.Event()
671 server.start(flag)
672 # wait for it to start
673 flag.wait()
674 # try to connect
675 if client_protocol is None:
676 client_protocol = protocol
677 try:
Bill Janssen6e027db2007-11-15 22:23:56 +0000678 s = ssl.wrap_socket(socket.socket(),
679 certfile=client_certfile,
680 ca_certs=cacertsfile,
681 cert_reqs=certreqs,
682 ssl_version=client_protocol)
Trent Nelson78520002008-04-10 20:54:35 +0000683 s.connect((HOST, server.port))
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000684 arg = indata.encode('ASCII', 'strict')
Bill Janssen6e027db2007-11-15 22:23:56 +0000685 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000686 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000687 sys.stdout.write(
688 " client: sending %s...\n" % (repr(indata)))
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000689 s.write(arg)
Bill Janssen6e027db2007-11-15 22:23:56 +0000690 outdata = s.read()
691 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000692 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000693 sys.stdout.write(" client: read %s\n" % repr(outdata))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000694 outdata = str(outdata, 'ASCII', 'strict')
Bill Janssen6e027db2007-11-15 22:23:56 +0000695 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000696 self.fail(
Bill Janssen6e027db2007-11-15 22:23:56 +0000697 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
Trent Nelson6b240cd2008-04-10 20:12:06 +0000698 % (repr(outdata[:min(len(outdata),20)]), len(outdata),
699 repr(indata[:min(len(indata),20)].lower()), len(indata)))
700 s.write("over\n".encode("ASCII", "strict"))
Bill Janssen6e027db2007-11-15 22:23:56 +0000701 if connectionchatty:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000702 if support.verbose:
Bill Janssen6e027db2007-11-15 22:23:56 +0000703 sys.stdout.write(" client: closing connection.\n")
704 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000705 finally:
706 server.stop()
707 server.join()
Thomas Woutersed03b412007-08-28 21:37:11 +0000708
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000709 def tryProtocolCombo (server_protocol,
710 client_protocol,
711 expectedToWork,
712 certsreqs=None):
Thomas Woutersed03b412007-08-28 21:37:11 +0000713
Benjamin Peterson2a691a82008-03-31 01:51:45 +0000714 if certsreqs is None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000715 certsreqs = ssl.CERT_NONE
Thomas Woutersed03b412007-08-28 21:37:11 +0000716
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000717 if certsreqs == ssl.CERT_NONE:
718 certtype = "CERT_NONE"
719 elif certsreqs == ssl.CERT_OPTIONAL:
720 certtype = "CERT_OPTIONAL"
721 elif certsreqs == ssl.CERT_REQUIRED:
722 certtype = "CERT_REQUIRED"
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000723 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000724 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
725 sys.stdout.write(formatstr %
726 (ssl.get_protocol_name(client_protocol),
727 ssl.get_protocol_name(server_protocol),
728 certtype))
729 try:
730 serverParamsTest(CERTFILE, server_protocol, certsreqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000731 CERTFILE, CERTFILE, client_protocol,
732 chatty=False, connectionchatty=False)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000733 # Protocol mismatch can result in either an SSLError, or a
734 # "Connection reset by peer" error.
735 except ssl.SSLError:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000736 if expectedToWork:
737 raise
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000738 except socket.error as e:
739 if expectedToWork or e.errno != errno.ECONNRESET:
740 raise
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000741 else:
742 if not expectedToWork:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000743 self.fail(
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000744 "Client protocol %s succeeded with server protocol %s!"
745 % (ssl.get_protocol_name(client_protocol),
746 ssl.get_protocol_name(server_protocol)))
747
748
Bill Janssen6e027db2007-11-15 22:23:56 +0000749 class ThreadedTests(unittest.TestCase):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000750
Trent Nelson6b240cd2008-04-10 20:12:06 +0000751 def testEcho (self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000752
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000753 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000754 sys.stdout.write("\n")
755 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
756 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
757 chatty=True, connectionchatty=True)
758
759 def testReadCert(self):
760
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000761 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000762 sys.stdout.write("\n")
763 s2 = socket.socket()
Trent Nelson78520002008-04-10 20:54:35 +0000764 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000765 certreqs=ssl.CERT_NONE,
766 ssl_version=ssl.PROTOCOL_SSLv23,
767 cacerts=CERTFILE,
768 chatty=False)
769 flag = threading.Event()
770 server.start(flag)
771 # wait for it to start
772 flag.wait()
773 # try to connect
774 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000775 s = ssl.wrap_socket(socket.socket(),
776 certfile=CERTFILE,
777 ca_certs=CERTFILE,
778 cert_reqs=ssl.CERT_REQUIRED,
779 ssl_version=ssl.PROTOCOL_SSLv23)
780 s.connect((HOST, server.port))
781 cert = s.getpeercert()
782 self.assertTrue(cert, "Can't get peer certificate.")
783 cipher = s.cipher()
784 if support.verbose:
785 sys.stdout.write(pprint.pformat(cert) + '\n')
786 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
787 if 'subject' not in cert:
788 self.fail("No subject field in certificate: %s." %
789 pprint.pformat(cert))
790 if ((('organizationName', 'Python Software Foundation'),)
791 not in cert['subject']):
792 self.fail(
793 "Missing or invalid 'organizationName' field in certificate subject; "
794 "should be 'Python Software Foundation'.")
795 s.close()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000796 finally:
797 server.stop()
798 server.join()
799
800 def testNULLcert(self):
801 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
802 "nullcert.pem"))
803 def testMalformedCert(self):
804 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
805 "badcert.pem"))
Bill Janssen58afe4c2008-09-08 16:45:19 +0000806 def testWrongCert(self):
807 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
808 "wrongcert.pem"))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000809 def testMalformedKey(self):
810 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
811 "badkey.pem"))
812
Trent Nelson6b240cd2008-04-10 20:12:06 +0000813 def testRudeShutdown(self):
814
815 listener_ready = threading.Event()
816 listener_gone = threading.Event()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000817 s = socket.socket()
818 port = support.bind_port(s, HOST)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000819
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000820 # `listener` runs in a thread. It sits in an accept() until
821 # the main thread connects. Then it rudely closes the socket,
822 # and sets Event `listener_gone` to let the main thread know
823 # the socket is gone.
Trent Nelson6b240cd2008-04-10 20:12:06 +0000824 def listener():
Trent Nelson6b240cd2008-04-10 20:12:06 +0000825 s.listen(5)
826 listener_ready.set()
827 s.accept()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000828 s.close()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000829 listener_gone.set()
830
831 def connector():
832 listener_ready.wait()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000833 c = socket.socket()
834 c.connect((HOST, port))
Trent Nelson6b240cd2008-04-10 20:12:06 +0000835 listener_gone.wait()
836 try:
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000837 ssl_sock = ssl.wrap_socket(c)
Trent Nelson6b240cd2008-04-10 20:12:06 +0000838 except IOError:
839 pass
840 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000841 self.fail('connecting to closed SSL socket should have failed')
Trent Nelson6b240cd2008-04-10 20:12:06 +0000842
843 t = threading.Thread(target=listener)
844 t.start()
Antoine Pitrou0fb2e542010-04-27 08:58:38 +0000845 try:
846 connector()
847 finally:
848 t.join()
Trent Nelson6b240cd2008-04-10 20:12:06 +0000849
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000850 def testProtocolSSL2(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000851 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000852 sys.stdout.write("\n")
853 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
854 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
855 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
856 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
857 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
858 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
859
860 def testProtocolSSL23(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000861 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000862 sys.stdout.write("\n")
863 try:
864 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000865 except (ssl.SSLError, socket.error) as x:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000866 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000867 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000868 sys.stdout.write(
869 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
870 % str(x))
871 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
872 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
873 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
874
875 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
876 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
877 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
878
879 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
880 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
881 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
882
883 def testProtocolSSL3(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000884 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000885 sys.stdout.write("\n")
886 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
887 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
888 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
889 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
890 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
891 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
892
893 def testProtocolTLS1(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000894 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895 sys.stdout.write("\n")
896 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
897 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
898 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
899 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
900 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
901 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
902
903 def testSTARTTLS (self):
904
Bill Janssen40a0f662008-08-12 16:56:25 +0000905 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000906
Trent Nelson78520002008-04-10 20:54:35 +0000907 server = ThreadedEchoServer(CERTFILE,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000908 ssl_version=ssl.PROTOCOL_TLSv1,
909 starttls_server=True,
910 chatty=True,
911 connectionchatty=True)
912 flag = threading.Event()
913 server.start(flag)
914 # wait for it to start
915 flag.wait()
916 # try to connect
917 wrapped = False
918 try:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000919 s = socket.socket()
920 s.setblocking(1)
921 s.connect((HOST, server.port))
922 if support.verbose:
923 sys.stdout.write("\n")
924 for indata in msgs:
925 msg = indata.encode('ASCII', 'replace')
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000926 if support.verbose:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000927 sys.stdout.write(
928 " client: sending %s...\n" % repr(msg))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000929 if wrapped:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000930 conn.write(msg)
931 outdata = conn.read()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000932 else:
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000933 s.send(msg)
934 outdata = s.recv(1024)
935 if (indata == "STARTTLS" and
936 str(outdata, 'ASCII', 'replace').strip().lower().startswith("ok")):
937 if support.verbose:
938 msg = str(outdata, 'ASCII', 'replace')
939 sys.stdout.write(
940 " client: read %s from server, starting TLS...\n"
941 % repr(msg))
942 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
943 wrapped = True
944 elif (indata == "ENDTLS" and
945 str(outdata, 'ASCII', 'replace').strip().lower().startswith("ok")):
946 if support.verbose:
947 msg = str(outdata, 'ASCII', 'replace')
948 sys.stdout.write(
949 " client: read %s from server, ending TLS...\n"
950 % repr(msg))
951 s = conn.unwrap()
952 wrapped = False
953 else:
954 if support.verbose:
955 msg = str(outdata, 'ASCII', 'replace')
956 sys.stdout.write(
957 " client: read %s from server\n" % repr(msg))
958 if support.verbose:
959 sys.stdout.write(" client: closing connection.\n")
960 if wrapped:
961 conn.write("over\n".encode("ASCII", "strict"))
962 else:
963 s.send("over\n".encode("ASCII", "strict"))
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
Bill Janssen54cc54c2007-12-14 22:08:56 +0000972 def testSocketServer(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000973
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')
983 d1 = open(CERTFILE, 'rb').read()
984 d2 = ''
985 # now fetch the same data from the HTTPS server
Trent Nelson78520002008-04-10 20:54:35 +0000986 url = 'https://%s:%d/%s' % (
987 HOST, server.port, os.path.split(CERTFILE)[1])
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000988 f = urllib.request.urlopen(url)
Barry Warsaw820c1202008-06-12 04:06:45 +0000989 dlen = f.info().get("content-length")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000990 if dlen and (int(dlen) > 0):
991 d2 = f.read(int(dlen))
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000992 if support.verbose:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000993 sys.stdout.write(
994 " client: read %d bytes from remote server '%s'\n"
995 % (len(d2), server))
996 f.close()
Antoine Pitrou66ffb262010-04-27 11:05:15 +0000997 self.assertEqual(d1, d2)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000998 finally:
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000999 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001000 sys.stdout.write('stopping server\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001001 server.stop()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001002 if support.verbose:
Neal Norwitzf9ff5f02008-03-31 05:39:26 +00001003 sys.stdout.write('joining thread\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001004 server.join()
1005
Trent Nelson6b240cd2008-04-10 20:12:06 +00001006 def testAsyncoreServer(self):
1007
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001008 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001009 sys.stdout.write("\n")
1010
1011 indata="FOO\n"
Trent Nelson78520002008-04-10 20:54:35 +00001012 server = AsyncoreEchoServer(CERTFILE)
Trent Nelson6b240cd2008-04-10 20:12:06 +00001013 flag = threading.Event()
1014 server.start(flag)
1015 # wait for it to start
1016 flag.wait()
1017 # try to connect
1018 try:
1019 s = ssl.wrap_socket(socket.socket())
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001020 s.connect(('127.0.0.1', server.port))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001021 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001022 sys.stdout.write(
1023 " client: sending %s...\n" % (repr(indata)))
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001024 s.write(indata.encode('ASCII', 'strict'))
1025 outdata = s.read()
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001026 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001027 sys.stdout.write(" client: read %s\n" % repr(outdata))
1028 outdata = str(outdata, 'ASCII', 'strict')
1029 if outdata != indata.lower():
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001030 self.fail(
Trent Nelson6b240cd2008-04-10 20:12:06 +00001031 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001032 % (outdata[:min(len(outdata),20)], len(outdata),
1033 indata[:min(len(indata),20)].lower(), len(indata)))
Trent Nelson6b240cd2008-04-10 20:12:06 +00001034 s.write("over\n".encode("ASCII", "strict"))
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001035 if support.verbose:
Trent Nelson6b240cd2008-04-10 20:12:06 +00001036 sys.stdout.write(" client: closing connection.\n")
1037 s.close()
1038 finally:
1039 server.stop()
1040 server.join()
1041
Bill Janssen58afe4c2008-09-08 16:45:19 +00001042 def testAllRecvAndSendMethods(self):
1043
1044 if support.verbose:
1045 sys.stdout.write("\n")
1046
1047 server = ThreadedEchoServer(CERTFILE,
1048 certreqs=ssl.CERT_NONE,
1049 ssl_version=ssl.PROTOCOL_TLSv1,
1050 cacerts=CERTFILE,
1051 chatty=True,
1052 connectionchatty=False)
1053 flag = threading.Event()
1054 server.start(flag)
1055 # wait for it to start
1056 flag.wait()
1057 # try to connect
Antoine Pitrou66ffb262010-04-27 11:05:15 +00001058 s = ssl.wrap_socket(socket.socket(),
1059 server_side=False,
1060 certfile=CERTFILE,
1061 ca_certs=CERTFILE,
1062 cert_reqs=ssl.CERT_NONE,
1063 ssl_version=ssl.PROTOCOL_TLSv1)
1064 s.connect((HOST, server.port))
Bill Janssen58afe4c2008-09-08 16:45:19 +00001065 try:
Bill Janssen58afe4c2008-09-08 16:45:19 +00001066 # helper methods for standardising recv* method signatures
1067 def _recv_into():
1068 b = bytearray(b"\0"*100)
1069 count = s.recv_into(b)
1070 return b[:count]
1071
1072 def _recvfrom_into():
1073 b = bytearray(b"\0"*100)
1074 count, addr = s.recvfrom_into(b)
1075 return b[:count]
1076
1077 # (name, method, whether to expect success, *args)
1078 send_methods = [
1079 ('send', s.send, True, []),
1080 ('sendto', s.sendto, False, ["some.address"]),
1081 ('sendall', s.sendall, True, []),
1082 ]
1083 recv_methods = [
1084 ('recv', s.recv, True, []),
1085 ('recvfrom', s.recvfrom, False, ["some.address"]),
1086 ('recv_into', _recv_into, True, []),
1087 ('recvfrom_into', _recvfrom_into, False, []),
1088 ]
1089 data_prefix = "PREFIX_"
1090
1091 for meth_name, send_meth, expect_success, args in send_methods:
1092 indata = data_prefix + meth_name
1093 try:
1094 send_meth(indata.encode('ASCII', 'strict'), *args)
1095 outdata = s.read()
1096 outdata = str(outdata, 'ASCII', 'strict')
1097 if outdata != indata.lower():
1098 raise support.TestFailed(
1099 "While sending with <<{name:s}>> bad data "
1100 "<<{outdata:s}>> ({nout:d}) received; "
1101 "expected <<{indata:s}>> ({nin:d})\n".format(
1102 name=meth_name, outdata=repr(outdata[:20]),
1103 nout=len(outdata),
1104 indata=repr(indata[:20]), nin=len(indata)
1105 )
1106 )
1107 except ValueError as e:
1108 if expect_success:
1109 raise support.TestFailed(
1110 "Failed to send with method <<{name:s}>>; "
1111 "expected to succeed.\n".format(name=meth_name)
1112 )
1113 if not str(e).startswith(meth_name):
1114 raise support.TestFailed(
1115 "Method <<{name:s}>> failed with unexpected "
1116 "exception message: {exp:s}\n".format(
1117 name=meth_name, exp=e
1118 )
1119 )
1120
1121 for meth_name, recv_meth, expect_success, args in recv_methods:
1122 indata = data_prefix + meth_name
1123 try:
1124 s.send(indata.encode('ASCII', 'strict'))
1125 outdata = recv_meth(*args)
1126 outdata = str(outdata, 'ASCII', 'strict')
1127 if outdata != indata.lower():
1128 raise support.TestFailed(
1129 "While receiving with <<{name:s}>> bad data "
1130 "<<{outdata:s}>> ({nout:d}) received; "
1131 "expected <<{indata:s}>> ({nin:d})\n".format(
1132 name=meth_name, outdata=repr(outdata[:20]),
1133 nout=len(outdata),
1134 indata=repr(indata[:20]), nin=len(indata)
1135 )
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
1153 s.write("over\n".encode("ASCII", "strict"))
1154 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
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001232 support.run_unittest(*tests)
Thomas Woutersed03b412007-08-28 21:37:11 +00001233
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001234 if _have_threads:
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001235 support.threading_cleanup(*thread_info)
Thomas Woutersed03b412007-08-28 21:37:11 +00001236
1237if __name__ == "__main__":
1238 test_main()