blob: e5f4a9ed866ee7116ba10e29a848e0a278f21457 [file] [log] [blame]
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001# Test the support for SSL and sockets
2
3import sys
4import unittest
5from test import test_support
Bill Janssen934b16d2008-06-28 22:19:33 +00006import asyncore
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00007import socket
Bill Janssen934b16d2008-06-28 22:19:33 +00008import select
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00009import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000010import subprocess
11import time
Antoine Pitroud4030da2010-04-23 23:35:01 +000012import gc
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000013import os
Antoine Pitroud4030da2010-04-23 23:35:01 +000014import errno
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000015import pprint
Bill Janssen296a59d2007-09-16 22:06:00 +000016import urllib, urlparse
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000017import shutil
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000018import traceback
Antoine Pitrou3df58d12010-04-23 23:07:37 +000019import weakref
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000020
Bill Janssen296a59d2007-09-16 22:06:00 +000021from BaseHTTPServer import HTTPServer
22from SimpleHTTPServer import SimpleHTTPRequestHandler
23
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000024# Optionally test SSL support, if we have it in the tested platform
25skip_expected = False
26try:
27 import ssl
28except ImportError:
29 skip_expected = True
30
Trent Nelsone41b0062008-04-08 23:47:30 +000031HOST = test_support.HOST
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000032CERTFILE = None
Bill Janssen296a59d2007-09-16 22:06:00 +000033SVN_PYTHON_ORG_ROOT_CERT = None
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000034
Neal Norwitz3e533c22007-08-27 01:03:18 +000035def handle_error(prefix):
36 exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
Bill Janssen98d19da2007-09-10 21:51:02 +000037 if test_support.verbose:
38 sys.stdout.write(prefix + exc_format)
Neal Norwitz3e533c22007-08-27 01:03:18 +000039
Antoine Pitrou77a1c362010-04-27 09:54:14 +000040
41class BasicTests(unittest.TestCase):
42
Bill Jansseneb257ac2008-09-29 18:56:38 +000043 def testSimpleSSLwrap(self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +000044 # A crude test for the legacy API
Bill Jansseneb257ac2008-09-29 18:56:38 +000045 try:
46 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
47 except IOError, e:
48 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
49 pass
50 else:
51 raise
52 try:
53 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
54 except IOError, e:
55 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
56 pass
57 else:
58 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000059
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000060 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000061 if not test_support.is_resource_enabled('network'):
62 return
Bill Janssen296a59d2007-09-16 22:06:00 +000063 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
64 cert_reqs=ssl.CERT_NONE)
65 s.connect(("svn.python.org", 443))
66 c = s.getpeercert()
67 if c:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +000068 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +000069 s.close()
70
71 # this should fail because we have no verification certs
72 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
73 cert_reqs=ssl.CERT_REQUIRED)
74 try:
75 s.connect(("svn.python.org", 443))
76 except ssl.SSLError:
77 pass
78 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000079 s.close()
80
Bill Janssen98d19da2007-09-10 21:51:02 +000081 def testCrucialConstants(self):
82 ssl.PROTOCOL_SSLv2
83 ssl.PROTOCOL_SSLv23
84 ssl.PROTOCOL_SSLv3
85 ssl.PROTOCOL_TLSv1
86 ssl.CERT_NONE
87 ssl.CERT_OPTIONAL
88 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000089
Bill Janssen98d19da2007-09-10 21:51:02 +000090 def testRAND(self):
91 v = ssl.RAND_status()
92 if test_support.verbose:
93 sys.stdout.write("\n RAND_status is %d (%s)\n"
94 % (v, (v and "sufficient randomness") or
95 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000096 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000097 ssl.RAND_egd(1)
98 except TypeError:
99 pass
Guido van Rossume4729332007-08-26 19:35:09 +0000100 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000101 print "didn't raise TypeError"
102 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000103
Bill Janssen98d19da2007-09-10 21:51:02 +0000104 def testParseCert(self):
105 # note that this uses an 'unofficial' function in _ssl.c,
106 # provided solely for this test, to exercise the certificate
107 # parsing code
108 p = ssl._ssl._test_decode_cert(CERTFILE, False)
109 if test_support.verbose:
110 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000111
Bill Janssen296a59d2007-09-16 22:06:00 +0000112 def testDERtoPEM(self):
113
114 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
115 d1 = ssl.PEM_cert_to_DER_cert(pem)
116 p2 = ssl.DER_cert_to_PEM_cert(d1)
117 d2 = ssl.PEM_cert_to_DER_cert(p2)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000118 self.assertEqual(d1, d2)
Antoine Pitrou12cb1292010-04-27 22:05:18 +0000119 if not p2.startswith(ssl.PEM_HEADER + '\n'):
120 self.fail("DER-to-PEM didn't include correct header:\n%r\n" % p2)
121 if not p2.endswith('\n' + ssl.PEM_FOOTER + '\n'):
122 self.fail("DER-to-PEM didn't include correct footer:\n%r\n" % p2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000123
Antoine Pitrou3df58d12010-04-23 23:07:37 +0000124 def test_refcycle(self):
125 # Issue #7943: an SSL object doesn't create reference cycles with
126 # itself.
127 s = socket.socket(socket.AF_INET)
128 ss = ssl.wrap_socket(s)
129 wr = weakref.ref(ss)
130 del ss
131 self.assertEqual(wr(), None)
132
Antoine Pitroud4030da2010-04-23 23:35:01 +0000133
Bill Janssen934b16d2008-06-28 22:19:33 +0000134class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000135
136 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000137 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
138 cert_reqs=ssl.CERT_NONE)
139 s.connect(("svn.python.org", 443))
140 c = s.getpeercert()
141 if c:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000142 self.fail("Peer cert %s shouldn't be here!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000143 s.close()
144
145 # this should fail because we have no verification certs
146 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
147 cert_reqs=ssl.CERT_REQUIRED)
148 try:
149 s.connect(("svn.python.org", 443))
150 except ssl.SSLError:
151 pass
152 finally:
153 s.close()
154
155 # this should succeed because we specify the root cert
156 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
157 cert_reqs=ssl.CERT_REQUIRED,
158 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
159 try:
160 s.connect(("svn.python.org", 443))
Bill Janssen296a59d2007-09-16 22:06:00 +0000161 finally:
162 s.close()
163
Antoine Pitrou0753d942010-04-24 11:09:52 +0000164 def test_makefile_close(self):
165 # Issue #5238: creating a file-like object with makefile() shouldn't
166 # delay closing the underlying "real socket" (here tested with its
167 # file descriptor, hence skipping the test under Windows).
168 if os.name == "nt":
169 if test_support.verbose:
170 print "Skipped: can't use a socket as a file under Windows"
171 return
172 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
173 ss.connect(("svn.python.org", 443))
174 fd = ss.fileno()
175 f = ss.makefile()
176 f.close()
177 # The fd is still open
178 os.read(fd, 0)
179 # Closing the SSL socket should close the fd too
180 ss.close()
181 gc.collect()
182 try:
183 os.read(fd, 0)
184 except OSError, e:
185 self.assertEqual(e.errno, errno.EBADF)
186 else:
187 self.fail("OSError wasn't raised")
Bill Janssen934b16d2008-06-28 22:19:33 +0000188
189 def testNonBlockingHandshake(self):
190 s = socket.socket(socket.AF_INET)
191 s.connect(("svn.python.org", 443))
192 s.setblocking(False)
193 s = ssl.wrap_socket(s,
194 cert_reqs=ssl.CERT_NONE,
195 do_handshake_on_connect=False)
196 count = 0
197 while True:
198 try:
199 count += 1
200 s.do_handshake()
201 break
202 except ssl.SSLError, err:
203 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
204 select.select([s], [], [])
205 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
206 select.select([], [s], [])
207 else:
208 raise
209 s.close()
210 if test_support.verbose:
211 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
212
Bill Janssen296a59d2007-09-16 22:06:00 +0000213 def testFetchServerCert(self):
214
215 pem = ssl.get_server_certificate(("svn.python.org", 443))
216 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000217 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000218
219 try:
220 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
221 except ssl.SSLError:
222 #should fail
223 pass
224 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000225 self.fail("Got server certificate %s for svn.python.org!" % pem)
Bill Janssen296a59d2007-09-16 22:06:00 +0000226
227 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
228 if not pem:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000229 self.fail("No server certificate on svn.python.org:443!")
Bill Janssen296a59d2007-09-16 22:06:00 +0000230 if test_support.verbose:
231 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
232
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000233 # Test disabled: OPENSSL_VERSION* not available in Python 2.6
Antoine Pitrou878602a2010-04-21 19:41:28 +0000234 def test_algorithms(self):
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000235 if test_support.verbose:
236 sys.stdout.write("test_algorithms disabled, "
237 "as it fails on some old OpenSSL versions")
238 return
Antoine Pitrou878602a2010-04-21 19:41:28 +0000239 # Issue #8484: all algorithms should be available when verifying a
240 # certificate.
241 # NOTE: https://sha256.tbs-internet.com is another possible test host
242 remote = ("sha2.hboeck.de", 443)
243 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
244 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
245 cert_reqs=ssl.CERT_REQUIRED,
246 ca_certs=sha256_cert,)
247 with test_support.transient_internet():
248 try:
249 s.connect(remote)
250 if test_support.verbose:
251 sys.stdout.write("\nCipher with %r is %r\n" %
252 (remote, s.cipher()))
253 sys.stdout.write("Certificate is:\n%s\n" %
254 pprint.pformat(s.getpeercert()))
255 finally:
256 s.close()
257
Bill Janssen296a59d2007-09-16 22:06:00 +0000258
Bill Janssen98d19da2007-09-10 21:51:02 +0000259try:
260 import threading
261except ImportError:
262 _have_threads = False
263else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000264
Bill Janssen98d19da2007-09-10 21:51:02 +0000265 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000266
Bill Janssen98d19da2007-09-10 21:51:02 +0000267 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000268
Bill Janssen98d19da2007-09-10 21:51:02 +0000269 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000270
Bill Janssen98d19da2007-09-10 21:51:02 +0000271 """A mildly complicated class, because we want it to work both
272 with and without the SSL wrapper around the socket connection, so
273 that we can test the STARTTLS functionality."""
274
275 def __init__(self, server, connsock):
276 self.server = server
277 self.running = False
278 self.sock = connsock
279 self.sock.setblocking(1)
280 self.sslconn = None
281 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000282 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000283
Bill Janssen934b16d2008-06-28 22:19:33 +0000284 def show_conn_details(self):
285 if self.server.certreqs == ssl.CERT_REQUIRED:
286 cert = self.sslconn.getpeercert()
287 if test_support.verbose and self.server.chatty:
288 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
289 cert_binary = self.sslconn.getpeercert(True)
290 if test_support.verbose and self.server.chatty:
291 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
292 cipher = self.sslconn.cipher()
293 if test_support.verbose and self.server.chatty:
294 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
295
Bill Janssen98d19da2007-09-10 21:51:02 +0000296 def wrap_conn (self):
297 try:
298 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
299 certfile=self.server.certificate,
300 ssl_version=self.server.protocol,
301 ca_certs=self.server.cacerts,
302 cert_reqs=self.server.certreqs)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000303 except ssl.SSLError:
304 # XXX Various errors can have happened here, for example
305 # a mismatching protocol version, an invalid certificate,
306 # or a low-level bug. This should be made more discriminating.
Bill Janssen98d19da2007-09-10 21:51:02 +0000307 if self.server.chatty:
308 handle_error("\n server: bad connection attempt from " +
309 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000310 self.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000311 self.running = False
312 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000313 return False
Bill Janssen98d19da2007-09-10 21:51:02 +0000314 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000315 return True
316
317 def read(self):
318 if self.sslconn:
319 return self.sslconn.read()
320 else:
321 return self.sock.recv(1024)
322
323 def write(self, bytes):
324 if self.sslconn:
325 return self.sslconn.write(bytes)
326 else:
327 return self.sock.send(bytes)
328
329 def close(self):
330 if self.sslconn:
331 self.sslconn.close()
332 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000333 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000334
335 def run (self):
336 self.running = True
337 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000338 if isinstance(self.sock, ssl.SSLSocket):
339 self.sslconn = self.sock
340 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000341 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000342 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000343 while self.running:
344 try:
345 msg = self.read()
346 if not msg:
347 # eof, so quit this handler
348 self.running = False
349 self.close()
350 elif msg.strip() == 'over':
351 if test_support.verbose and self.server.connectionchatty:
352 sys.stdout.write(" server: client closed connection\n")
353 self.close()
354 return
355 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
356 if test_support.verbose and self.server.connectionchatty:
357 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
358 self.write("OK\n")
359 if not self.wrap_conn():
360 return
Bill Janssen39295c22008-08-12 16:31:21 +0000361 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
362 if test_support.verbose and self.server.connectionchatty:
363 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
364 self.write("OK\n")
365 self.sslconn.unwrap()
366 self.sslconn = None
367 if test_support.verbose and self.server.connectionchatty:
368 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000369 else:
370 if (test_support.verbose and
371 self.server.connectionchatty):
372 ctype = (self.sslconn and "encrypted") or "unencrypted"
373 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
374 % (repr(msg), ctype, repr(msg.lower()), ctype))
375 self.write(msg.lower())
376 except ssl.SSLError:
377 if self.server.chatty:
378 handle_error("Test server failure:\n")
379 self.close()
380 self.running = False
381 # normally, we'd just stop here, but for the test
382 # harness, we want to stop the server
383 self.server.stop()
Bill Janssen98d19da2007-09-10 21:51:02 +0000384
Trent Nelsone41b0062008-04-08 23:47:30 +0000385 def __init__(self, certificate, ssl_version=None,
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000386 certreqs=None, cacerts=None,
Bill Janssen934b16d2008-06-28 22:19:33 +0000387 chatty=True, connectionchatty=False, starttls_server=False,
388 wrap_accepting_socket=False):
389
Bill Janssen98d19da2007-09-10 21:51:02 +0000390 if ssl_version is None:
391 ssl_version = ssl.PROTOCOL_TLSv1
392 if certreqs is None:
393 certreqs = ssl.CERT_NONE
394 self.certificate = certificate
395 self.protocol = ssl_version
396 self.certreqs = certreqs
397 self.cacerts = cacerts
Bill Janssen98d19da2007-09-10 21:51:02 +0000398 self.chatty = chatty
399 self.connectionchatty = connectionchatty
400 self.starttls_server = starttls_server
401 self.sock = socket.socket()
402 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000403 if wrap_accepting_socket:
404 self.sock = ssl.wrap_socket(self.sock, server_side=True,
405 certfile=self.certificate,
406 cert_reqs = self.certreqs,
407 ca_certs = self.cacerts,
408 ssl_version = self.protocol)
409 if test_support.verbose and self.chatty:
410 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
411 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000412 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000413 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000414 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000415
416 def start (self, flag=None):
417 self.flag = flag
418 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000419
420 def run (self):
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000421 self.sock.settimeout(0.05)
Bill Janssen98d19da2007-09-10 21:51:02 +0000422 self.sock.listen(5)
423 self.active = True
424 if self.flag:
425 # signal an event
426 self.flag.set()
427 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000428 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000429 newconn, connaddr = self.sock.accept()
430 if test_support.verbose and self.chatty:
431 sys.stdout.write(' server: new connection from '
432 + str(connaddr) + '\n')
433 handler = self.ConnectionHandler(self, newconn)
434 handler.start()
435 except socket.timeout:
436 pass
437 except KeyboardInterrupt:
438 self.stop()
Bill Janssen934b16d2008-06-28 22:19:33 +0000439 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000440
Bill Janssen98d19da2007-09-10 21:51:02 +0000441 def stop (self):
442 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000443
Bill Janssen934b16d2008-06-28 22:19:33 +0000444 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000445
Bill Janssen934b16d2008-06-28 22:19:33 +0000446 class EchoServer (asyncore.dispatcher):
447
448 class ConnectionHandler (asyncore.dispatcher_with_send):
449
450 def __init__(self, conn, certfile):
451 asyncore.dispatcher_with_send.__init__(self, conn)
452 self.socket = ssl.wrap_socket(conn, server_side=True,
453 certfile=certfile,
Antoine Pitrouc689d962010-04-24 20:13:37 +0000454 do_handshake_on_connect=False)
455 self._ssl_accepting = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000456
457 def readable(self):
458 if isinstance(self.socket, ssl.SSLSocket):
459 while self.socket.pending() > 0:
460 self.handle_read_event()
461 return True
462
Antoine Pitrouc689d962010-04-24 20:13:37 +0000463 def _do_ssl_handshake(self):
464 try:
465 self.socket.do_handshake()
466 except ssl.SSLError, err:
467 if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
468 ssl.SSL_ERROR_WANT_WRITE):
469 return
470 elif err.args[0] == ssl.SSL_ERROR_EOF:
471 return self.handle_close()
472 raise
473 except socket.error, err:
474 if err.args[0] == errno.ECONNABORTED:
475 return self.handle_close()
476 else:
477 self._ssl_accepting = False
478
Bill Janssen934b16d2008-06-28 22:19:33 +0000479 def handle_read(self):
Antoine Pitrouc689d962010-04-24 20:13:37 +0000480 if self._ssl_accepting:
481 self._do_ssl_handshake()
482 else:
483 data = self.recv(1024)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000484 if data and data.strip() != 'over':
485 self.send(data.lower())
Bill Janssen934b16d2008-06-28 22:19:33 +0000486
487 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000488 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000489 if test_support.verbose:
490 sys.stdout.write(" server: closed connection %s\n" % self.socket)
491
492 def handle_error(self):
493 raise
494
495 def __init__(self, certfile):
496 self.certfile = certfile
497 asyncore.dispatcher.__init__(self)
498 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
499 self.port = test_support.bind_port(self.socket)
500 self.listen(5)
501
502 def handle_accept(self):
503 sock_obj, addr = self.accept()
504 if test_support.verbose:
505 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
506 self.ConnectionHandler(sock_obj, self.certfile)
507
508 def handle_error(self):
509 raise
510
511 def __init__(self, certfile):
512 self.flag = None
513 self.active = False
514 self.server = self.EchoServer(certfile)
515 self.port = self.server.port
516 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000517 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000518
519 def __str__(self):
520 return "<%s %s>" % (self.__class__.__name__, self.server)
521
522 def start (self, flag=None):
523 self.flag = flag
524 threading.Thread.start(self)
525
526 def run (self):
527 self.active = True
528 if self.flag:
529 self.flag.set()
530 while self.active:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000531 asyncore.loop(0.05)
Bill Janssen934b16d2008-06-28 22:19:33 +0000532
533 def stop (self):
534 self.active = False
535 self.server.close()
536
537 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000538
539 class HTTPSServer(HTTPServer):
540
541 def __init__(self, server_address, RequestHandlerClass, certfile):
542
543 HTTPServer.__init__(self, server_address, RequestHandlerClass)
544 # we assume the certfile contains both private key and certificate
545 self.certfile = certfile
546 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000547 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000548 self.allow_reuse_address = True
549
Bill Janssen934b16d2008-06-28 22:19:33 +0000550 def __str__(self):
551 return ('<%s %s:%s>' %
552 (self.__class__.__name__,
553 self.server_name,
554 self.server_port))
555
Bill Janssen296a59d2007-09-16 22:06:00 +0000556 def get_request (self):
557 # override this to wrap socket with SSL
558 sock, addr = self.socket.accept()
559 sslconn = ssl.wrap_socket(sock, server_side=True,
560 certfile=self.certfile)
561 return sslconn, addr
562
Bill Janssen296a59d2007-09-16 22:06:00 +0000563 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
564
565 # need to override translate_path to get a known root,
566 # instead of using os.curdir, since the test could be
567 # run from anywhere
568
569 server_version = "TestHTTPS/1.0"
570
571 root = None
572
573 def translate_path(self, path):
574 """Translate a /-separated PATH to the local filename syntax.
575
576 Components that mean special things to the local file system
577 (e.g. drive or directory names) are ignored. (XXX They should
578 probably be diagnosed.)
579
580 """
581 # abandon query parameters
582 path = urlparse.urlparse(path)[2]
583 path = os.path.normpath(urllib.unquote(path))
584 words = path.split('/')
585 words = filter(None, words)
586 path = self.root
587 for word in words:
588 drive, word = os.path.splitdrive(word)
589 head, word = os.path.split(word)
590 if word in self.root: continue
591 path = os.path.join(path, word)
592 return path
593
594 def log_message(self, format, *args):
595
596 # we override this to suppress logging unless "verbose"
597
598 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000599 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
600 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000601 self.server.server_port,
602 self.request.cipher(),
603 self.log_date_time_string(),
604 format%args))
605
606
Trent Nelsone41b0062008-04-08 23:47:30 +0000607 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000608 self.flag = None
609 self.active = False
610 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
611 self.server = self.HTTPSServer(
Antoine Pitrou6535b312010-04-27 08:43:11 +0000612 (HOST, 0), self.RootedHTTPRequestHandler, certfile)
613 self.port = self.server.server_port
Bill Janssen296a59d2007-09-16 22:06:00 +0000614 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000615 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000616
617 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000618 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000619
620 def start (self, flag=None):
621 self.flag = flag
622 threading.Thread.start(self)
623
624 def run (self):
625 self.active = True
626 if self.flag:
627 self.flag.set()
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000628 self.server.serve_forever(0.05)
Bill Janssen296a59d2007-09-16 22:06:00 +0000629 self.active = False
630
631 def stop (self):
632 self.active = False
Antoine Pitrou77a1c362010-04-27 09:54:14 +0000633 self.server.shutdown()
Bill Janssen296a59d2007-09-16 22:06:00 +0000634
635
Bill Janssen98d19da2007-09-10 21:51:02 +0000636 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000637 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000638 certreqs=ssl.CERT_REQUIRED,
639 cacerts=CERTFILE, chatty=False)
640 flag = threading.Event()
641 server.start(flag)
642 # wait for it to start
643 flag.wait()
644 # try to connect
645 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000646 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000647 s = ssl.wrap_socket(socket.socket(),
648 certfile=certfile,
649 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000650 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000651 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000652 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000653 sys.stdout.write("\nSSLError is %s\n" % x[1])
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000654 except socket.error, x:
655 if test_support.verbose:
656 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000657 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000658 self.fail("Use of invalid cert should have failed!")
Bill Janssen98d19da2007-09-10 21:51:02 +0000659 finally:
660 server.stop()
661 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000662
Bill Janssen98d19da2007-09-10 21:51:02 +0000663 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
664 client_certfile, client_protocol=None, indata="FOO\n",
Bill Janssen934b16d2008-06-28 22:19:33 +0000665 chatty=True, connectionchatty=False,
666 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000667
Trent Nelsone41b0062008-04-08 23:47:30 +0000668 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000669 certreqs=certreqs,
670 ssl_version=protocol,
671 cacerts=cacertsfile,
672 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000673 connectionchatty=connectionchatty,
674 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000675 flag = threading.Event()
676 server.start(flag)
677 # wait for it to start
678 flag.wait()
679 # try to connect
680 if client_protocol is None:
681 client_protocol = protocol
682 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000683 s = ssl.wrap_socket(socket.socket(),
684 certfile=client_certfile,
685 ca_certs=cacertsfile,
686 cert_reqs=certreqs,
687 ssl_version=client_protocol)
688 s.connect((HOST, server.port))
689 if connectionchatty:
690 if test_support.verbose:
691 sys.stdout.write(
692 " client: sending %s...\n" % (repr(indata)))
693 s.write(indata)
694 outdata = s.read()
695 if connectionchatty:
696 if test_support.verbose:
697 sys.stdout.write(" client: read %s\n" % repr(outdata))
698 if outdata != indata.lower():
699 self.fail(
700 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
701 % (outdata[:min(len(outdata),20)], len(outdata),
702 indata[:min(len(indata),20)].lower(), len(indata)))
703 s.write("over\n")
704 if connectionchatty:
705 if test_support.verbose:
706 sys.stdout.write(" client: closing connection.\n")
707 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000708 finally:
709 server.stop()
710 server.join()
711
712 def tryProtocolCombo (server_protocol,
713 client_protocol,
714 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000715 certsreqs=None):
716
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000717 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000718 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000719
720 if certsreqs == ssl.CERT_NONE:
721 certtype = "CERT_NONE"
722 elif certsreqs == ssl.CERT_OPTIONAL:
723 certtype = "CERT_OPTIONAL"
724 elif certsreqs == ssl.CERT_REQUIRED:
725 certtype = "CERT_REQUIRED"
726 if test_support.verbose:
727 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
728 sys.stdout.write(formatstr %
729 (ssl.get_protocol_name(client_protocol),
730 ssl.get_protocol_name(server_protocol),
731 certtype))
732 try:
733 serverParamsTest(CERTFILE, server_protocol, certsreqs,
734 CERTFILE, CERTFILE, client_protocol, chatty=False)
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000735 # Protocol mismatch can result in either an SSLError, or a
736 # "Connection reset by peer" error.
737 except ssl.SSLError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000738 if expectedToWork:
739 raise
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000740 except socket.error as e:
741 if expectedToWork or e.errno != errno.ECONNRESET:
742 raise
Bill Janssen98d19da2007-09-10 21:51:02 +0000743 else:
744 if not expectedToWork:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000745 self.fail(
Bill Janssen98d19da2007-09-10 21:51:02 +0000746 "Client protocol %s succeeded with server protocol %s!"
747 % (ssl.get_protocol_name(client_protocol),
748 ssl.get_protocol_name(server_protocol)))
749
750
Bill Janssen934b16d2008-06-28 22:19:33 +0000751 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000752
753 def testRudeShutdown(self):
754
755 listener_ready = threading.Event()
756 listener_gone = threading.Event()
757
Antoine Pitrou6535b312010-04-27 08:43:11 +0000758 s = socket.socket()
759 port = test_support.bind_port(s, HOST)
760
761 # `listener` runs in a thread. It sits in an accept() until
762 # the main thread connects. Then it rudely closes the socket,
763 # and sets Event `listener_gone` to let the main thread know
764 # the socket is gone.
Bill Janssen98d19da2007-09-10 21:51:02 +0000765 def listener():
Bill Janssen98d19da2007-09-10 21:51:02 +0000766 s.listen(5)
767 listener_ready.set()
768 s.accept()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000769 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000770 listener_gone.set()
771
772 def connector():
773 listener_ready.wait()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000774 c = socket.socket()
775 c.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000776 listener_gone.wait()
777 try:
Antoine Pitrou6535b312010-04-27 08:43:11 +0000778 ssl_sock = ssl.wrap_socket(c)
Bill Janssen934b16d2008-06-28 22:19:33 +0000779 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000780 pass
781 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000782 self.fail('connecting to closed SSL socket should have failed')
Bill Janssen98d19da2007-09-10 21:51:02 +0000783
784 t = threading.Thread(target=listener)
785 t.start()
Antoine Pitrou6535b312010-04-27 08:43:11 +0000786 try:
787 connector()
788 finally:
789 t.join()
Bill Janssen98d19da2007-09-10 21:51:02 +0000790
791 def testEcho (self):
792
793 if test_support.verbose:
794 sys.stdout.write("\n")
795 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
796 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
797 chatty=True, connectionchatty=True)
798
799 def testReadCert(self):
800
801 if test_support.verbose:
802 sys.stdout.write("\n")
803 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000804 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000805 certreqs=ssl.CERT_NONE,
806 ssl_version=ssl.PROTOCOL_SSLv23,
807 cacerts=CERTFILE,
808 chatty=False)
809 flag = threading.Event()
810 server.start(flag)
811 # wait for it to start
812 flag.wait()
813 # try to connect
814 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000815 s = ssl.wrap_socket(socket.socket(),
816 certfile=CERTFILE,
817 ca_certs=CERTFILE,
818 cert_reqs=ssl.CERT_REQUIRED,
819 ssl_version=ssl.PROTOCOL_SSLv23)
820 s.connect((HOST, server.port))
821 cert = s.getpeercert()
822 self.assertTrue(cert, "Can't get peer certificate.")
823 cipher = s.cipher()
824 if test_support.verbose:
825 sys.stdout.write(pprint.pformat(cert) + '\n')
826 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
827 if 'subject' not in cert:
828 self.fail("No subject field in certificate: %s." %
829 pprint.pformat(cert))
830 if ((('organizationName', 'Python Software Foundation'),)
831 not in cert['subject']):
832 self.fail(
833 "Missing or invalid 'organizationName' field in certificate subject; "
834 "should be 'Python Software Foundation'.")
835 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000836 finally:
837 server.stop()
838 server.join()
839
840 def testNULLcert(self):
841 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
842 "nullcert.pem"))
843 def testMalformedCert(self):
844 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
845 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000846 def testWrongCert(self):
847 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
848 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000849 def testMalformedKey(self):
850 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
851 "badkey.pem"))
852
853 def testProtocolSSL2(self):
854 if test_support.verbose:
855 sys.stdout.write("\n")
856 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
857 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
858 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
859 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
860 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
861 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
862
863 def testProtocolSSL23(self):
864 if test_support.verbose:
865 sys.stdout.write("\n")
866 try:
867 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
Antoine Pitrou94d6fba2010-04-27 13:14:50 +0000868 except (ssl.SSLError, socket.error), x:
Bill Janssen98d19da2007-09-10 21:51:02 +0000869 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
870 if test_support.verbose:
871 sys.stdout.write(
872 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
873 % str(x))
874 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
875 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
876 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
877
878 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
879 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
880 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
881
882 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
883 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
884 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
885
886 def testProtocolSSL3(self):
887 if test_support.verbose:
888 sys.stdout.write("\n")
889 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
890 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
891 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
892 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
893 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
894 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
895
896 def testProtocolTLS1(self):
897 if test_support.verbose:
898 sys.stdout.write("\n")
899 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
900 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
901 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
902 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
903 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
904 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
905
906 def testSTARTTLS (self):
907
Bill Janssen39295c22008-08-12 16:31:21 +0000908 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000909
Trent Nelsone41b0062008-04-08 23:47:30 +0000910 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000911 ssl_version=ssl.PROTOCOL_TLSv1,
912 starttls_server=True,
913 chatty=True,
914 connectionchatty=True)
915 flag = threading.Event()
916 server.start(flag)
917 # wait for it to start
918 flag.wait()
919 # try to connect
920 wrapped = False
921 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000922 s = socket.socket()
923 s.setblocking(1)
924 s.connect((HOST, server.port))
925 if test_support.verbose:
926 sys.stdout.write("\n")
927 for indata in msgs:
Bill Janssen98d19da2007-09-10 21:51:02 +0000928 if test_support.verbose:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000929 sys.stdout.write(
930 " client: sending %s...\n" % repr(indata))
931 if wrapped:
932 conn.write(indata)
933 outdata = conn.read()
934 else:
935 s.send(indata)
936 outdata = s.recv(1024)
937 if (indata == "STARTTLS" and
938 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000939 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000940 sys.stdout.write(
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000941 " client: read %s from server, starting TLS...\n"
942 % repr(outdata))
943 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
944 wrapped = True
945 elif (indata == "ENDTLS" and
946 outdata.strip().lower().startswith("ok")):
947 if test_support.verbose:
948 sys.stdout.write(
949 " client: read %s from server, ending TLS...\n"
950 % repr(outdata))
951 s = conn.unwrap()
952 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000953 else:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000954 if test_support.verbose:
955 sys.stdout.write(
956 " client: read %s from server\n" % repr(outdata))
957 if test_support.verbose:
958 sys.stdout.write(" client: closing connection.\n")
959 if wrapped:
960 conn.write("over\n")
961 else:
962 s.send("over\n")
963 s.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000964 finally:
965 server.stop()
966 server.join()
967
Bill Janssen934b16d2008-06-28 22:19:33 +0000968 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000969
Bill Janssen934b16d2008-06-28 22:19:33 +0000970 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +0000971 flag = threading.Event()
972 server.start(flag)
973 # wait for it to start
974 flag.wait()
975 # try to connect
976 try:
977 if test_support.verbose:
978 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +0000979 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +0000980 d2 = ''
981 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +0000982 url = 'https://127.0.0.1:%d/%s' % (
983 server.port, os.path.split(CERTFILE)[1])
Bill Janssen296a59d2007-09-16 22:06:00 +0000984 f = urllib.urlopen(url)
985 dlen = f.info().getheader("content-length")
986 if dlen and (int(dlen) > 0):
987 d2 = f.read(int(dlen))
988 if test_support.verbose:
989 sys.stdout.write(
990 " client: read %d bytes from remote server '%s'\n"
991 % (len(d2), server))
992 f.close()
Antoine Pitrou6ab7f002010-04-27 10:41:42 +0000993 self.assertEqual(d1, d2)
Bill Janssen296a59d2007-09-16 22:06:00 +0000994 finally:
995 server.stop()
996 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +0000997
Bill Janssen934b16d2008-06-28 22:19:33 +0000998 def testWrappedAccept (self):
999
1000 if test_support.verbose:
1001 sys.stdout.write("\n")
1002 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1003 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1004 chatty=True, connectionchatty=True,
1005 wrap_accepting_socket=True)
1006
1007
1008 def testAsyncoreServer (self):
1009
1010 indata = "TEST MESSAGE of mixed case\n"
1011
1012 if test_support.verbose:
1013 sys.stdout.write("\n")
1014 server = AsyncoreEchoServer(CERTFILE)
1015 flag = threading.Event()
1016 server.start(flag)
1017 # wait for it to start
1018 flag.wait()
1019 # try to connect
1020 try:
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001021 s = ssl.wrap_socket(socket.socket())
1022 s.connect(('127.0.0.1', server.port))
1023 if test_support.verbose:
1024 sys.stdout.write(
1025 " client: sending %s...\n" % (repr(indata)))
1026 s.write(indata)
1027 outdata = s.read()
1028 if test_support.verbose:
1029 sys.stdout.write(" client: read %s\n" % repr(outdata))
1030 if outdata != indata.lower():
1031 self.fail(
1032 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1033 % (outdata[:min(len(outdata),20)], len(outdata),
1034 indata[:min(len(indata),20)].lower(), len(indata)))
1035 s.write("over\n")
1036 if test_support.verbose:
1037 sys.stdout.write(" client: closing connection.\n")
1038 s.close()
Bill Janssen934b16d2008-06-28 22:19:33 +00001039 finally:
1040 server.stop()
1041 # wait for server thread to end
1042 server.join()
1043
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001044
Bill Janssen61c001a2008-09-08 16:37:24 +00001045 def testAllRecvAndSendMethods(self):
1046
1047 if test_support.verbose:
1048 sys.stdout.write("\n")
1049
1050 server = ThreadedEchoServer(CERTFILE,
1051 certreqs=ssl.CERT_NONE,
1052 ssl_version=ssl.PROTOCOL_TLSv1,
1053 cacerts=CERTFILE,
1054 chatty=True,
1055 connectionchatty=False)
1056 flag = threading.Event()
1057 server.start(flag)
1058 # wait for it to start
1059 flag.wait()
1060 # try to connect
Antoine Pitrou6ab7f002010-04-27 10:41:42 +00001061 s = ssl.wrap_socket(socket.socket(),
1062 server_side=False,
1063 certfile=CERTFILE,
1064 ca_certs=CERTFILE,
1065 cert_reqs=ssl.CERT_NONE,
1066 ssl_version=ssl.PROTOCOL_TLSv1)
1067 s.connect((HOST, server.port))
Bill Janssen61c001a2008-09-08 16:37:24 +00001068 try:
Bill Janssen61c001a2008-09-08 16:37:24 +00001069 # helper methods for standardising recv* method signatures
1070 def _recv_into():
1071 b = bytearray("\0"*100)
1072 count = s.recv_into(b)
1073 return b[:count]
1074
1075 def _recvfrom_into():
1076 b = bytearray("\0"*100)
1077 count, addr = s.recvfrom_into(b)
1078 return b[:count]
1079
1080 # (name, method, whether to expect success, *args)
1081 send_methods = [
1082 ('send', s.send, True, []),
1083 ('sendto', s.sendto, False, ["some.address"]),
1084 ('sendall', s.sendall, True, []),
1085 ]
1086 recv_methods = [
1087 ('recv', s.recv, True, []),
1088 ('recvfrom', s.recvfrom, False, ["some.address"]),
1089 ('recv_into', _recv_into, True, []),
1090 ('recvfrom_into', _recvfrom_into, False, []),
1091 ]
1092 data_prefix = u"PREFIX_"
1093
1094 for meth_name, send_meth, expect_success, args in send_methods:
1095 indata = data_prefix + meth_name
1096 try:
1097 send_meth(indata.encode('ASCII', 'strict'), *args)
1098 outdata = s.read()
1099 outdata = outdata.decode('ASCII', 'strict')
1100 if outdata != indata.lower():
1101 raise support.TestFailed(
1102 "While sending with <<%s>> bad data "
1103 "<<%r>> (%d) received; "
1104 "expected <<%r>> (%d)\n" % (
1105 meth_name, outdata[:20], len(outdata),
1106 indata[:20], len(indata)
1107 )
1108 )
1109 except ValueError as e:
1110 if expect_success:
1111 raise support.TestFailed(
1112 "Failed to send with method <<%s>>; "
1113 "expected to succeed.\n" % (meth_name,)
1114 )
1115 if not str(e).startswith(meth_name):
1116 raise support.TestFailed(
1117 "Method <<%s>> failed with unexpected "
1118 "exception message: %s\n" % (
1119 meth_name, e
1120 )
1121 )
1122
1123 for meth_name, recv_meth, expect_success, args in recv_methods:
1124 indata = data_prefix + meth_name
1125 try:
1126 s.send(indata.encode('ASCII', 'strict'))
1127 outdata = recv_meth(*args)
1128 outdata = outdata.decode('ASCII', 'strict')
1129 if outdata != indata.lower():
1130 raise support.TestFailed(
1131 "While receiving with <<%s>> bad data "
1132 "<<%r>> (%d) received; "
1133 "expected <<%r>> (%d)\n" % (
1134 meth_name, outdata[:20], len(outdata),
1135 indata[:20], len(indata)
1136 )
1137 )
1138 except ValueError as e:
1139 if expect_success:
1140 raise support.TestFailed(
1141 "Failed to receive with method <<%s>>; "
1142 "expected to succeed.\n" % (meth_name,)
1143 )
1144 if not str(e).startswith(meth_name):
1145 raise support.TestFailed(
1146 "Method <<%s>> failed with unexpected "
1147 "exception message: %s\n" % (
1148 meth_name, e
1149 )
1150 )
1151 # consume data
1152 s.read()
1153
1154 s.write("over\n".encode("ASCII", "strict"))
1155 s.close()
1156 finally:
1157 server.stop()
1158 server.join()
1159
Antoine Pitrouc689d962010-04-24 20:13:37 +00001160 def test_handshake_timeout(self):
1161 # Issue #5103: SSL handshake must respect the socket timeout
1162 server = socket.socket(socket.AF_INET)
1163 host = "127.0.0.1"
1164 port = test_support.bind_port(server)
1165 started = threading.Event()
1166 finish = False
1167
1168 def serve():
1169 server.listen(5)
1170 started.set()
1171 conns = []
1172 while not finish:
1173 r, w, e = select.select([server], [], [], 0.1)
1174 if server in r:
1175 # Let the socket hang around rather than having
1176 # it closed by garbage collection.
1177 conns.append(server.accept()[0])
1178
1179 t = threading.Thread(target=serve)
1180 t.start()
1181 started.wait()
1182
1183 try:
1184 try:
1185 c = socket.socket(socket.AF_INET)
1186 c.settimeout(0.2)
1187 c.connect((host, port))
1188 # Will attempt handshake and time out
1189 try:
1190 ssl.wrap_socket(c)
1191 except ssl.SSLError, e:
1192 self.assertTrue("timed out" in str(e), str(e))
1193 else:
1194 self.fail("SSLError wasn't raised")
1195 finally:
1196 c.close()
1197 try:
1198 c = socket.socket(socket.AF_INET)
1199 c.settimeout(0.2)
1200 c = ssl.wrap_socket(c)
1201 # Will attempt handshake and time out
1202 try:
1203 c.connect((host, port))
1204 except ssl.SSLError, e:
1205 self.assertTrue("timed out" in str(e), str(e))
1206 else:
1207 self.fail("SSLError wasn't raised")
1208 finally:
1209 c.close()
1210 finally:
1211 finish = True
1212 t.join()
1213 server.close()
1214
Bill Janssen61c001a2008-09-08 16:37:24 +00001215
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001216def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001217 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001218 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001219
Trent Nelsone41b0062008-04-08 23:47:30 +00001220 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001221 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001222 "keycert.pem")
1223 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1224 os.path.dirname(__file__) or os.curdir,
1225 "https_svn_python_org_root.pem")
1226
1227 if (not os.path.exists(CERTFILE) or
1228 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001229 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001230
1231 tests = [BasicTests]
1232
Bill Janssen296a59d2007-09-16 22:06:00 +00001233 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001234 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001235
Bill Janssen98d19da2007-09-10 21:51:02 +00001236 if _have_threads:
1237 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001238 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001239 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001240
Bill Janssen98d19da2007-09-10 21:51:02 +00001241 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001242
Bill Janssen98d19da2007-09-10 21:51:02 +00001243 if _have_threads:
1244 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001245
1246if __name__ == "__main__":
1247 test_main()