blob: c1de0c1efb1b39861e26fa7e7ae1e4cb286a99e6 [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
Bill Jansseneb257ac2008-09-29 18:56:38 +000040 def testSimpleSSLwrap(self):
41 try:
42 ssl.sslwrap_simple(socket.socket(socket.AF_INET))
43 except IOError, e:
44 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
45 pass
46 else:
47 raise
48 try:
49 ssl.sslwrap_simple(socket.socket(socket.AF_INET)._sock)
50 except IOError, e:
51 if e.errno == 32: # broken pipe when ssl_sock.do_handshake(), this test doesn't care about that
52 pass
53 else:
54 raise
Neal Norwitz3e533c22007-08-27 01:03:18 +000055
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000056class BasicTests(unittest.TestCase):
57
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000058 def testSSLconnect(self):
Christian Heimes6c29be52008-01-19 16:39:27 +000059 if not test_support.is_resource_enabled('network'):
60 return
Bill Janssen296a59d2007-09-16 22:06:00 +000061 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
62 cert_reqs=ssl.CERT_NONE)
63 s.connect(("svn.python.org", 443))
64 c = s.getpeercert()
65 if c:
66 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
67 s.close()
68
69 # this should fail because we have no verification certs
70 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
71 cert_reqs=ssl.CERT_REQUIRED)
72 try:
73 s.connect(("svn.python.org", 443))
74 except ssl.SSLError:
75 pass
76 finally:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000077 s.close()
78
Bill Janssen98d19da2007-09-10 21:51:02 +000079 def testCrucialConstants(self):
80 ssl.PROTOCOL_SSLv2
81 ssl.PROTOCOL_SSLv23
82 ssl.PROTOCOL_SSLv3
83 ssl.PROTOCOL_TLSv1
84 ssl.CERT_NONE
85 ssl.CERT_OPTIONAL
86 ssl.CERT_REQUIRED
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +000087
Bill Janssen98d19da2007-09-10 21:51:02 +000088 def testRAND(self):
89 v = ssl.RAND_status()
90 if test_support.verbose:
91 sys.stdout.write("\n RAND_status is %d (%s)\n"
92 % (v, (v and "sufficient randomness") or
93 "insufficient randomness"))
Guido van Rossume4729332007-08-26 19:35:09 +000094 try:
Bill Janssen98d19da2007-09-10 21:51:02 +000095 ssl.RAND_egd(1)
96 except TypeError:
97 pass
Guido van Rossume4729332007-08-26 19:35:09 +000098 else:
Bill Janssen98d19da2007-09-10 21:51:02 +000099 print "didn't raise TypeError"
100 ssl.RAND_add("this is a random string", 75.0)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000101
Bill Janssen98d19da2007-09-10 21:51:02 +0000102 def testParseCert(self):
103 # note that this uses an 'unofficial' function in _ssl.c,
104 # provided solely for this test, to exercise the certificate
105 # parsing code
106 p = ssl._ssl._test_decode_cert(CERTFILE, False)
107 if test_support.verbose:
108 sys.stdout.write("\n" + pprint.pformat(p) + "\n")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000109
Bill Janssen296a59d2007-09-16 22:06:00 +0000110 def testDERtoPEM(self):
111
112 pem = open(SVN_PYTHON_ORG_ROOT_CERT, 'r').read()
113 d1 = ssl.PEM_cert_to_DER_cert(pem)
114 p2 = ssl.DER_cert_to_PEM_cert(d1)
115 d2 = ssl.PEM_cert_to_DER_cert(p2)
116 if (d1 != d2):
117 raise test_support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
118
Antoine Pitrou3df58d12010-04-23 23:07:37 +0000119 def test_refcycle(self):
120 # Issue #7943: an SSL object doesn't create reference cycles with
121 # itself.
122 s = socket.socket(socket.AF_INET)
123 ss = ssl.wrap_socket(s)
124 wr = weakref.ref(ss)
125 del ss
126 self.assertEqual(wr(), None)
127
Antoine Pitroud4030da2010-04-23 23:35:01 +0000128 def test_makefile_close(self):
129 # Issue #5238: creating a file-like object with makefile() shouldn't
130 # leak the underlying file descriptor.
131 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
132 fd = ss.fileno()
133 f = ss.makefile()
134 f.close()
135 # The fd is still open
136 os.read(fd, 0)
137 # Closing the SSL socket should close the fd too
138 ss.close()
139 gc.collect()
140 try:
141 os.read(fd, 0)
142 except OSError, e:
143 self.assertEqual(e.errno, errno.EBADF)
144 else:
145 self.fail("OSError wasn't raised")
146
147
Bill Janssen934b16d2008-06-28 22:19:33 +0000148class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000149
150 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000151 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
152 cert_reqs=ssl.CERT_NONE)
153 s.connect(("svn.python.org", 443))
154 c = s.getpeercert()
155 if c:
156 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
157 s.close()
158
159 # this should fail because we have no verification certs
160 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
161 cert_reqs=ssl.CERT_REQUIRED)
162 try:
163 s.connect(("svn.python.org", 443))
164 except ssl.SSLError:
165 pass
166 finally:
167 s.close()
168
169 # this should succeed because we specify the root cert
170 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
171 cert_reqs=ssl.CERT_REQUIRED,
172 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
173 try:
174 s.connect(("svn.python.org", 443))
175 except ssl.SSLError, x:
176 raise test_support.TestFailed("Unexpected exception %s" % x)
177 finally:
178 s.close()
179
Bill Janssen934b16d2008-06-28 22:19:33 +0000180
181 def testNonBlockingHandshake(self):
182 s = socket.socket(socket.AF_INET)
183 s.connect(("svn.python.org", 443))
184 s.setblocking(False)
185 s = ssl.wrap_socket(s,
186 cert_reqs=ssl.CERT_NONE,
187 do_handshake_on_connect=False)
188 count = 0
189 while True:
190 try:
191 count += 1
192 s.do_handshake()
193 break
194 except ssl.SSLError, err:
195 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
196 select.select([s], [], [])
197 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
198 select.select([], [s], [])
199 else:
200 raise
201 s.close()
202 if test_support.verbose:
203 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
204
Bill Janssen296a59d2007-09-16 22:06:00 +0000205 def testFetchServerCert(self):
206
207 pem = ssl.get_server_certificate(("svn.python.org", 443))
208 if not pem:
209 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
210
211 try:
212 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
213 except ssl.SSLError:
214 #should fail
215 pass
216 else:
217 raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
218
219 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
220 if not pem:
221 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
222 if test_support.verbose:
223 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
224
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000225 # Test disabled: OPENSSL_VERSION* not available in Python 2.6
Antoine Pitrou878602a2010-04-21 19:41:28 +0000226 def test_algorithms(self):
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000227 if test_support.verbose:
228 sys.stdout.write("test_algorithms disabled, "
229 "as it fails on some old OpenSSL versions")
230 return
Antoine Pitrou878602a2010-04-21 19:41:28 +0000231 # Issue #8484: all algorithms should be available when verifying a
232 # certificate.
233 # NOTE: https://sha256.tbs-internet.com is another possible test host
234 remote = ("sha2.hboeck.de", 443)
235 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
236 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
237 cert_reqs=ssl.CERT_REQUIRED,
238 ca_certs=sha256_cert,)
239 with test_support.transient_internet():
240 try:
241 s.connect(remote)
242 if test_support.verbose:
243 sys.stdout.write("\nCipher with %r is %r\n" %
244 (remote, s.cipher()))
245 sys.stdout.write("Certificate is:\n%s\n" %
246 pprint.pformat(s.getpeercert()))
247 finally:
248 s.close()
249
Bill Janssen296a59d2007-09-16 22:06:00 +0000250
Bill Janssen98d19da2007-09-10 21:51:02 +0000251try:
252 import threading
253except ImportError:
254 _have_threads = False
255else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000256
Bill Janssen98d19da2007-09-10 21:51:02 +0000257 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000258
Bill Janssen98d19da2007-09-10 21:51:02 +0000259 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000260
Bill Janssen98d19da2007-09-10 21:51:02 +0000261 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000262
Bill Janssen98d19da2007-09-10 21:51:02 +0000263 """A mildly complicated class, because we want it to work both
264 with and without the SSL wrapper around the socket connection, so
265 that we can test the STARTTLS functionality."""
266
267 def __init__(self, server, connsock):
268 self.server = server
269 self.running = False
270 self.sock = connsock
271 self.sock.setblocking(1)
272 self.sslconn = None
273 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000274 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000275
Bill Janssen934b16d2008-06-28 22:19:33 +0000276 def show_conn_details(self):
277 if self.server.certreqs == ssl.CERT_REQUIRED:
278 cert = self.sslconn.getpeercert()
279 if test_support.verbose and self.server.chatty:
280 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
281 cert_binary = self.sslconn.getpeercert(True)
282 if test_support.verbose and self.server.chatty:
283 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
284 cipher = self.sslconn.cipher()
285 if test_support.verbose and self.server.chatty:
286 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
287
Bill Janssen98d19da2007-09-10 21:51:02 +0000288 def wrap_conn (self):
289 try:
290 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
291 certfile=self.server.certificate,
292 ssl_version=self.server.protocol,
293 ca_certs=self.server.cacerts,
294 cert_reqs=self.server.certreqs)
295 except:
296 if self.server.chatty:
297 handle_error("\n server: bad connection attempt from " +
298 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000299 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000300 if not self.server.expect_bad_connects:
301 # here, we want to stop the server, because this shouldn't
302 # happen in the context of our test case
303 self.running = False
304 # normally, we'd just stop here, but for the test
305 # harness, we want to stop the server
306 self.server.stop()
307 return False
308
309 else:
Bill Janssen98d19da2007-09-10 21:51:02 +0000310 return True
311
312 def read(self):
313 if self.sslconn:
314 return self.sslconn.read()
315 else:
316 return self.sock.recv(1024)
317
318 def write(self, bytes):
319 if self.sslconn:
320 return self.sslconn.write(bytes)
321 else:
322 return self.sock.send(bytes)
323
324 def close(self):
325 if self.sslconn:
326 self.sslconn.close()
327 else:
Bill Janssen934b16d2008-06-28 22:19:33 +0000328 self.sock._sock.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000329
330 def run (self):
331 self.running = True
332 if not self.server.starttls_server:
Bill Janssen934b16d2008-06-28 22:19:33 +0000333 if isinstance(self.sock, ssl.SSLSocket):
334 self.sslconn = self.sock
335 elif not self.wrap_conn():
Bill Janssen98d19da2007-09-10 21:51:02 +0000336 return
Bill Janssen934b16d2008-06-28 22:19:33 +0000337 self.show_conn_details()
Bill Janssen98d19da2007-09-10 21:51:02 +0000338 while self.running:
339 try:
340 msg = self.read()
341 if not msg:
342 # eof, so quit this handler
343 self.running = False
344 self.close()
345 elif msg.strip() == 'over':
346 if test_support.verbose and self.server.connectionchatty:
347 sys.stdout.write(" server: client closed connection\n")
348 self.close()
349 return
350 elif self.server.starttls_server and msg.strip() == 'STARTTLS':
351 if test_support.verbose and self.server.connectionchatty:
352 sys.stdout.write(" server: read STARTTLS from client, sending OK...\n")
353 self.write("OK\n")
354 if not self.wrap_conn():
355 return
Bill Janssen39295c22008-08-12 16:31:21 +0000356 elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS':
357 if test_support.verbose and self.server.connectionchatty:
358 sys.stdout.write(" server: read ENDTLS from client, sending OK...\n")
359 self.write("OK\n")
360 self.sslconn.unwrap()
361 self.sslconn = None
362 if test_support.verbose and self.server.connectionchatty:
363 sys.stdout.write(" server: connection is now unencrypted...\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000364 else:
365 if (test_support.verbose and
366 self.server.connectionchatty):
367 ctype = (self.sslconn and "encrypted") or "unencrypted"
368 sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n"
369 % (repr(msg), ctype, repr(msg.lower()), ctype))
370 self.write(msg.lower())
371 except ssl.SSLError:
372 if self.server.chatty:
373 handle_error("Test server failure:\n")
374 self.close()
375 self.running = False
376 # normally, we'd just stop here, but for the test
377 # harness, we want to stop the server
378 self.server.stop()
379 except:
380 handle_error('')
381
Trent Nelsone41b0062008-04-08 23:47:30 +0000382 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000383 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000384 chatty=True, connectionchatty=False, starttls_server=False,
385 wrap_accepting_socket=False):
386
Bill Janssen98d19da2007-09-10 21:51:02 +0000387 if ssl_version is None:
388 ssl_version = ssl.PROTOCOL_TLSv1
389 if certreqs is None:
390 certreqs = ssl.CERT_NONE
391 self.certificate = certificate
392 self.protocol = ssl_version
393 self.certreqs = certreqs
394 self.cacerts = cacerts
395 self.expect_bad_connects = expect_bad_connects
396 self.chatty = chatty
397 self.connectionchatty = connectionchatty
398 self.starttls_server = starttls_server
399 self.sock = socket.socket()
400 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000401 if wrap_accepting_socket:
402 self.sock = ssl.wrap_socket(self.sock, server_side=True,
403 certfile=self.certificate,
404 cert_reqs = self.certreqs,
405 ca_certs = self.cacerts,
406 ssl_version = self.protocol)
407 if test_support.verbose and self.chatty:
408 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
409 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000410 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000411 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000412 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000413
414 def start (self, flag=None):
415 self.flag = flag
416 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000417
418 def run (self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000419 self.sock.settimeout(0.5)
420 self.sock.listen(5)
421 self.active = True
422 if self.flag:
423 # signal an event
424 self.flag.set()
425 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000426 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000427 newconn, connaddr = self.sock.accept()
428 if test_support.verbose and self.chatty:
429 sys.stdout.write(' server: new connection from '
430 + str(connaddr) + '\n')
431 handler = self.ConnectionHandler(self, newconn)
432 handler.start()
433 except socket.timeout:
434 pass
435 except KeyboardInterrupt:
436 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000437 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000438 if self.chatty:
439 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000440 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000441
Bill Janssen98d19da2007-09-10 21:51:02 +0000442 def stop (self):
443 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000444
Bill Janssen934b16d2008-06-28 22:19:33 +0000445 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000446
Bill Janssen934b16d2008-06-28 22:19:33 +0000447 class EchoServer (asyncore.dispatcher):
448
449 class ConnectionHandler (asyncore.dispatcher_with_send):
450
451 def __init__(self, conn, certfile):
452 asyncore.dispatcher_with_send.__init__(self, conn)
453 self.socket = ssl.wrap_socket(conn, server_side=True,
454 certfile=certfile,
455 do_handshake_on_connect=True)
456
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
463 def handle_read(self):
464 data = self.recv(1024)
465 self.send(data.lower())
466
467 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000468 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000469 if test_support.verbose:
470 sys.stdout.write(" server: closed connection %s\n" % self.socket)
471
472 def handle_error(self):
473 raise
474
475 def __init__(self, certfile):
476 self.certfile = certfile
477 asyncore.dispatcher.__init__(self)
478 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
479 self.port = test_support.bind_port(self.socket)
480 self.listen(5)
481
482 def handle_accept(self):
483 sock_obj, addr = self.accept()
484 if test_support.verbose:
485 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
486 self.ConnectionHandler(sock_obj, self.certfile)
487
488 def handle_error(self):
489 raise
490
491 def __init__(self, certfile):
492 self.flag = None
493 self.active = False
494 self.server = self.EchoServer(certfile)
495 self.port = self.server.port
496 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000497 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000498
499 def __str__(self):
500 return "<%s %s>" % (self.__class__.__name__, self.server)
501
502 def start (self, flag=None):
503 self.flag = flag
504 threading.Thread.start(self)
505
506 def run (self):
507 self.active = True
508 if self.flag:
509 self.flag.set()
510 while self.active:
511 try:
512 asyncore.loop(1)
513 except:
514 pass
515
516 def stop (self):
517 self.active = False
518 self.server.close()
519
520 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000521
522 class HTTPSServer(HTTPServer):
523
524 def __init__(self, server_address, RequestHandlerClass, certfile):
525
526 HTTPServer.__init__(self, server_address, RequestHandlerClass)
527 # we assume the certfile contains both private key and certificate
528 self.certfile = certfile
529 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000530 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000531 self.allow_reuse_address = True
532
Bill Janssen934b16d2008-06-28 22:19:33 +0000533 def __str__(self):
534 return ('<%s %s:%s>' %
535 (self.__class__.__name__,
536 self.server_name,
537 self.server_port))
538
Bill Janssen296a59d2007-09-16 22:06:00 +0000539 def get_request (self):
540 # override this to wrap socket with SSL
541 sock, addr = self.socket.accept()
542 sslconn = ssl.wrap_socket(sock, server_side=True,
543 certfile=self.certfile)
544 return sslconn, addr
545
546 # The methods overridden below this are mainly so that we
547 # can run it in a thread and be able to stop it from another
548 # You probably wouldn't need them in other uses.
549
550 def server_activate(self):
551 # We want to run this in a thread for testing purposes,
552 # so we override this to set timeout, so that we get
553 # a chance to stop the server
554 self.socket.settimeout(0.5)
555 HTTPServer.server_activate(self)
556
557 def serve_forever(self):
558 # We want this to run in a thread, so we use a slightly
559 # modified version of "forever".
560 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000561 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000562 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000563 # We need to lock while handling the request.
564 # Another thread can close the socket after self.active
565 # has been checked and before the request is handled.
566 # This causes an exception when using the closed socket.
567 with self.active_lock:
568 if not self.active:
569 break
570 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000571 except socket.timeout:
572 pass
573 except KeyboardInterrupt:
574 self.server_close()
575 return
576 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000577 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
578 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000579 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000580
581 def server_close(self):
582 # Again, we want this to run in a thread, so we need to override
583 # close to clear the "active" flag, so that serve_forever() will
584 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000585 with self.active_lock:
586 HTTPServer.server_close(self)
587 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000588
589 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
590
591 # need to override translate_path to get a known root,
592 # instead of using os.curdir, since the test could be
593 # run from anywhere
594
595 server_version = "TestHTTPS/1.0"
596
597 root = None
598
599 def translate_path(self, path):
600 """Translate a /-separated PATH to the local filename syntax.
601
602 Components that mean special things to the local file system
603 (e.g. drive or directory names) are ignored. (XXX They should
604 probably be diagnosed.)
605
606 """
607 # abandon query parameters
608 path = urlparse.urlparse(path)[2]
609 path = os.path.normpath(urllib.unquote(path))
610 words = path.split('/')
611 words = filter(None, words)
612 path = self.root
613 for word in words:
614 drive, word = os.path.splitdrive(word)
615 head, word = os.path.split(word)
616 if word in self.root: continue
617 path = os.path.join(path, word)
618 return path
619
620 def log_message(self, format, *args):
621
622 # we override this to suppress logging unless "verbose"
623
624 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000625 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
626 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000627 self.server.server_port,
628 self.request.cipher(),
629 self.log_date_time_string(),
630 format%args))
631
632
Trent Nelsone41b0062008-04-08 23:47:30 +0000633 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000634 self.flag = None
635 self.active = False
636 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Trent Nelsone41b0062008-04-08 23:47:30 +0000637 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000638 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000639 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Bill Janssen296a59d2007-09-16 22:06:00 +0000640 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000641 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000642
643 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000644 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000645
646 def start (self, flag=None):
647 self.flag = flag
648 threading.Thread.start(self)
649
650 def run (self):
651 self.active = True
652 if self.flag:
653 self.flag.set()
654 self.server.serve_forever()
655 self.active = False
656
657 def stop (self):
658 self.active = False
659 self.server.server_close()
660
661
Bill Janssen98d19da2007-09-10 21:51:02 +0000662 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000663 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000664 certreqs=ssl.CERT_REQUIRED,
665 cacerts=CERTFILE, chatty=False)
666 flag = threading.Event()
667 server.start(flag)
668 # wait for it to start
669 flag.wait()
670 # try to connect
671 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000672 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000673 s = ssl.wrap_socket(socket.socket(),
674 certfile=certfile,
675 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000676 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000677 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000678 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000679 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000680 except socket.error, x:
681 if test_support.verbose:
682 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000683 else:
684 raise test_support.TestFailed(
685 "Use of invalid cert should have failed!")
686 finally:
687 server.stop()
688 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000689
Bill Janssen98d19da2007-09-10 21:51:02 +0000690 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
691 client_certfile, client_protocol=None, indata="FOO\n",
Bill Janssen934b16d2008-06-28 22:19:33 +0000692 chatty=True, connectionchatty=False,
693 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000694
Trent Nelsone41b0062008-04-08 23:47:30 +0000695 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000696 certreqs=certreqs,
697 ssl_version=protocol,
698 cacerts=cacertsfile,
699 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000700 connectionchatty=connectionchatty,
701 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000702 flag = threading.Event()
703 server.start(flag)
704 # wait for it to start
705 flag.wait()
706 # try to connect
707 if client_protocol is None:
708 client_protocol = protocol
709 try:
710 try:
711 s = ssl.wrap_socket(socket.socket(),
712 certfile=client_certfile,
713 ca_certs=cacertsfile,
714 cert_reqs=certreqs,
715 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000716 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000717 except ssl.SSLError, x:
718 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
719 except Exception, x:
720 raise test_support.TestFailed("Unexpected exception: " + str(x))
721 else:
722 if connectionchatty:
723 if test_support.verbose:
724 sys.stdout.write(
725 " client: sending %s...\n" % (repr(indata)))
726 s.write(indata)
727 outdata = s.read()
728 if connectionchatty:
729 if test_support.verbose:
730 sys.stdout.write(" client: read %s\n" % repr(outdata))
731 if outdata != indata.lower():
732 raise test_support.TestFailed(
733 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
734 % (outdata[:min(len(outdata),20)], len(outdata),
735 indata[:min(len(indata),20)].lower(), len(indata)))
736 s.write("over\n")
737 if connectionchatty:
738 if test_support.verbose:
739 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000740 s.close()
741 finally:
742 server.stop()
743 server.join()
744
745 def tryProtocolCombo (server_protocol,
746 client_protocol,
747 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000748 certsreqs=None):
749
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000750 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000751 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000752
753 if certsreqs == ssl.CERT_NONE:
754 certtype = "CERT_NONE"
755 elif certsreqs == ssl.CERT_OPTIONAL:
756 certtype = "CERT_OPTIONAL"
757 elif certsreqs == ssl.CERT_REQUIRED:
758 certtype = "CERT_REQUIRED"
759 if test_support.verbose:
760 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
761 sys.stdout.write(formatstr %
762 (ssl.get_protocol_name(client_protocol),
763 ssl.get_protocol_name(server_protocol),
764 certtype))
765 try:
766 serverParamsTest(CERTFILE, server_protocol, certsreqs,
767 CERTFILE, CERTFILE, client_protocol, chatty=False)
768 except test_support.TestFailed:
769 if expectedToWork:
770 raise
771 else:
772 if not expectedToWork:
773 raise test_support.TestFailed(
774 "Client protocol %s succeeded with server protocol %s!"
775 % (ssl.get_protocol_name(client_protocol),
776 ssl.get_protocol_name(server_protocol)))
777
778
Bill Janssen934b16d2008-06-28 22:19:33 +0000779 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000780
781 def testRudeShutdown(self):
782
783 listener_ready = threading.Event()
784 listener_gone = threading.Event()
Trent Nelsone41b0062008-04-08 23:47:30 +0000785 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000786
787 # `listener` runs in a thread. It opens a socket listening on
788 # PORT, and sits in an accept() until the main thread connects.
789 # Then it rudely closes the socket, and sets Event `listener_gone`
790 # to let the main thread know the socket is gone.
791 def listener():
792 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000793 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000794 s.listen(5)
795 listener_ready.set()
796 s.accept()
797 s = None # reclaim the socket object, which also closes it
798 listener_gone.set()
799
800 def connector():
801 listener_ready.wait()
802 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000803 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000804 listener_gone.wait()
805 try:
806 ssl_sock = ssl.wrap_socket(s)
Bill Janssen934b16d2008-06-28 22:19:33 +0000807 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000808 pass
809 else:
810 raise test_support.TestFailed(
811 'connecting to closed SSL socket should have failed')
812
813 t = threading.Thread(target=listener)
814 t.start()
815 connector()
816 t.join()
817
818 def testEcho (self):
819
820 if test_support.verbose:
821 sys.stdout.write("\n")
822 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
823 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
824 chatty=True, connectionchatty=True)
825
826 def testReadCert(self):
827
828 if test_support.verbose:
829 sys.stdout.write("\n")
830 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000831 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000832 certreqs=ssl.CERT_NONE,
833 ssl_version=ssl.PROTOCOL_SSLv23,
834 cacerts=CERTFILE,
835 chatty=False)
836 flag = threading.Event()
837 server.start(flag)
838 # wait for it to start
839 flag.wait()
840 # try to connect
841 try:
842 try:
843 s = ssl.wrap_socket(socket.socket(),
844 certfile=CERTFILE,
845 ca_certs=CERTFILE,
846 cert_reqs=ssl.CERT_REQUIRED,
847 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000848 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000849 except ssl.SSLError, x:
850 raise test_support.TestFailed(
851 "Unexpected SSL error: " + str(x))
852 except Exception, x:
853 raise test_support.TestFailed(
854 "Unexpected exception: " + str(x))
855 else:
856 if not s:
857 raise test_support.TestFailed(
858 "Can't SSL-handshake with test server")
859 cert = s.getpeercert()
860 if not cert:
861 raise test_support.TestFailed(
862 "Can't get peer certificate.")
863 cipher = s.cipher()
864 if test_support.verbose:
865 sys.stdout.write(pprint.pformat(cert) + '\n')
866 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
867 if not cert.has_key('subject'):
868 raise test_support.TestFailed(
869 "No subject field in certificate: %s." %
870 pprint.pformat(cert))
871 if ((('organizationName', 'Python Software Foundation'),)
872 not in cert['subject']):
873 raise test_support.TestFailed(
874 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000875 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000876 s.close()
877 finally:
878 server.stop()
879 server.join()
880
881 def testNULLcert(self):
882 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
883 "nullcert.pem"))
884 def testMalformedCert(self):
885 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
886 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000887 def testWrongCert(self):
888 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
889 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000890 def testMalformedKey(self):
891 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
892 "badkey.pem"))
893
894 def testProtocolSSL2(self):
895 if test_support.verbose:
896 sys.stdout.write("\n")
897 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
898 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
899 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
900 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
901 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
902 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
903
904 def testProtocolSSL23(self):
905 if test_support.verbose:
906 sys.stdout.write("\n")
907 try:
908 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
909 except test_support.TestFailed, x:
910 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
911 if test_support.verbose:
912 sys.stdout.write(
913 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
914 % str(x))
915 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
916 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
917 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
918
919 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
920 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
921 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
922
923 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
924 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
925 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
926
927 def testProtocolSSL3(self):
928 if test_support.verbose:
929 sys.stdout.write("\n")
930 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
931 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
932 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
933 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
934 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
935 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
936
937 def testProtocolTLS1(self):
938 if test_support.verbose:
939 sys.stdout.write("\n")
940 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
941 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
942 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
943 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
944 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
945 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
946
947 def testSTARTTLS (self):
948
Bill Janssen39295c22008-08-12 16:31:21 +0000949 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000950
Trent Nelsone41b0062008-04-08 23:47:30 +0000951 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000952 ssl_version=ssl.PROTOCOL_TLSv1,
953 starttls_server=True,
954 chatty=True,
955 connectionchatty=True)
956 flag = threading.Event()
957 server.start(flag)
958 # wait for it to start
959 flag.wait()
960 # try to connect
961 wrapped = False
962 try:
963 try:
964 s = socket.socket()
965 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000966 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000967 except Exception, x:
968 raise test_support.TestFailed("Unexpected exception: " + str(x))
969 else:
970 if test_support.verbose:
971 sys.stdout.write("\n")
972 for indata in msgs:
973 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000974 sys.stdout.write(
975 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000976 if wrapped:
977 conn.write(indata)
978 outdata = conn.read()
979 else:
980 s.send(indata)
981 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +0000982 if (indata == "STARTTLS" and
983 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000984 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000985 sys.stdout.write(
986 " client: read %s from server, starting TLS...\n"
987 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000988 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000989 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +0000990 elif (indata == "ENDTLS" and
991 outdata.strip().lower().startswith("ok")):
992 if test_support.verbose:
993 sys.stdout.write(
994 " client: read %s from server, ending TLS...\n"
995 % repr(outdata))
996 s = conn.unwrap()
997 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +0000998 else:
999 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001000 sys.stdout.write(
1001 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001002 if test_support.verbose:
1003 sys.stdout.write(" client: closing connection.\n")
1004 if wrapped:
1005 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001006 else:
1007 s.send("over\n")
1008 s.close()
1009 finally:
1010 server.stop()
1011 server.join()
1012
Bill Janssen934b16d2008-06-28 22:19:33 +00001013 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001014
Bill Janssen934b16d2008-06-28 22:19:33 +00001015 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001016 flag = threading.Event()
1017 server.start(flag)
1018 # wait for it to start
1019 flag.wait()
1020 # try to connect
1021 try:
1022 if test_support.verbose:
1023 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001024 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001025 d2 = ''
1026 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001027 url = 'https://127.0.0.1:%d/%s' % (
1028 server.port, os.path.split(CERTFILE)[1])
Bill Janssen296a59d2007-09-16 22:06:00 +00001029 f = urllib.urlopen(url)
1030 dlen = f.info().getheader("content-length")
1031 if dlen and (int(dlen) > 0):
1032 d2 = f.read(int(dlen))
1033 if test_support.verbose:
1034 sys.stdout.write(
1035 " client: read %d bytes from remote server '%s'\n"
1036 % (len(d2), server))
1037 f.close()
1038 except:
1039 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1040 if test_support.verbose:
1041 sys.stdout.write('\n' + msg)
1042 raise test_support.TestFailed(msg)
1043 else:
1044 if not (d1 == d2):
1045 raise test_support.TestFailed(
1046 "Couldn't fetch data from HTTPS server")
1047 finally:
1048 server.stop()
1049 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001050
Bill Janssen934b16d2008-06-28 22:19:33 +00001051 def testWrappedAccept (self):
1052
1053 if test_support.verbose:
1054 sys.stdout.write("\n")
1055 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1056 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1057 chatty=True, connectionchatty=True,
1058 wrap_accepting_socket=True)
1059
1060
1061 def testAsyncoreServer (self):
1062
1063 indata = "TEST MESSAGE of mixed case\n"
1064
1065 if test_support.verbose:
1066 sys.stdout.write("\n")
1067 server = AsyncoreEchoServer(CERTFILE)
1068 flag = threading.Event()
1069 server.start(flag)
1070 # wait for it to start
1071 flag.wait()
1072 # try to connect
1073 try:
1074 try:
1075 s = ssl.wrap_socket(socket.socket())
1076 s.connect(('127.0.0.1', server.port))
1077 except ssl.SSLError, x:
1078 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1079 except Exception, x:
1080 raise test_support.TestFailed("Unexpected exception: " + str(x))
1081 else:
1082 if test_support.verbose:
1083 sys.stdout.write(
1084 " client: sending %s...\n" % (repr(indata)))
1085 s.write(indata)
1086 outdata = s.read()
1087 if test_support.verbose:
1088 sys.stdout.write(" client: read %s\n" % repr(outdata))
1089 if outdata != indata.lower():
1090 raise test_support.TestFailed(
1091 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1092 % (outdata[:min(len(outdata),20)], len(outdata),
1093 indata[:min(len(indata),20)].lower(), len(indata)))
1094 s.write("over\n")
1095 if test_support.verbose:
1096 sys.stdout.write(" client: closing connection.\n")
1097 s.close()
1098 finally:
1099 server.stop()
1100 # wait for server thread to end
1101 server.join()
1102
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001103
Bill Janssen61c001a2008-09-08 16:37:24 +00001104 def testAllRecvAndSendMethods(self):
1105
1106 if test_support.verbose:
1107 sys.stdout.write("\n")
1108
1109 server = ThreadedEchoServer(CERTFILE,
1110 certreqs=ssl.CERT_NONE,
1111 ssl_version=ssl.PROTOCOL_TLSv1,
1112 cacerts=CERTFILE,
1113 chatty=True,
1114 connectionchatty=False)
1115 flag = threading.Event()
1116 server.start(flag)
1117 # wait for it to start
1118 flag.wait()
1119 # try to connect
1120 try:
1121 s = ssl.wrap_socket(socket.socket(),
1122 server_side=False,
1123 certfile=CERTFILE,
1124 ca_certs=CERTFILE,
1125 cert_reqs=ssl.CERT_NONE,
1126 ssl_version=ssl.PROTOCOL_TLSv1)
1127 s.connect((HOST, server.port))
1128 except ssl.SSLError as x:
1129 raise support.TestFailed("Unexpected SSL error: " + str(x))
1130 except Exception as x:
1131 raise support.TestFailed("Unexpected exception: " + str(x))
1132 else:
1133 # helper methods for standardising recv* method signatures
1134 def _recv_into():
1135 b = bytearray("\0"*100)
1136 count = s.recv_into(b)
1137 return b[:count]
1138
1139 def _recvfrom_into():
1140 b = bytearray("\0"*100)
1141 count, addr = s.recvfrom_into(b)
1142 return b[:count]
1143
1144 # (name, method, whether to expect success, *args)
1145 send_methods = [
1146 ('send', s.send, True, []),
1147 ('sendto', s.sendto, False, ["some.address"]),
1148 ('sendall', s.sendall, True, []),
1149 ]
1150 recv_methods = [
1151 ('recv', s.recv, True, []),
1152 ('recvfrom', s.recvfrom, False, ["some.address"]),
1153 ('recv_into', _recv_into, True, []),
1154 ('recvfrom_into', _recvfrom_into, False, []),
1155 ]
1156 data_prefix = u"PREFIX_"
1157
1158 for meth_name, send_meth, expect_success, args in send_methods:
1159 indata = data_prefix + meth_name
1160 try:
1161 send_meth(indata.encode('ASCII', 'strict'), *args)
1162 outdata = s.read()
1163 outdata = outdata.decode('ASCII', 'strict')
1164 if outdata != indata.lower():
1165 raise support.TestFailed(
1166 "While sending with <<%s>> bad data "
1167 "<<%r>> (%d) received; "
1168 "expected <<%r>> (%d)\n" % (
1169 meth_name, outdata[:20], len(outdata),
1170 indata[:20], len(indata)
1171 )
1172 )
1173 except ValueError as e:
1174 if expect_success:
1175 raise support.TestFailed(
1176 "Failed to send with method <<%s>>; "
1177 "expected to succeed.\n" % (meth_name,)
1178 )
1179 if not str(e).startswith(meth_name):
1180 raise support.TestFailed(
1181 "Method <<%s>> failed with unexpected "
1182 "exception message: %s\n" % (
1183 meth_name, e
1184 )
1185 )
1186
1187 for meth_name, recv_meth, expect_success, args in recv_methods:
1188 indata = data_prefix + meth_name
1189 try:
1190 s.send(indata.encode('ASCII', 'strict'))
1191 outdata = recv_meth(*args)
1192 outdata = outdata.decode('ASCII', 'strict')
1193 if outdata != indata.lower():
1194 raise support.TestFailed(
1195 "While receiving with <<%s>> bad data "
1196 "<<%r>> (%d) received; "
1197 "expected <<%r>> (%d)\n" % (
1198 meth_name, outdata[:20], len(outdata),
1199 indata[:20], len(indata)
1200 )
1201 )
1202 except ValueError as e:
1203 if expect_success:
1204 raise support.TestFailed(
1205 "Failed to receive with method <<%s>>; "
1206 "expected to succeed.\n" % (meth_name,)
1207 )
1208 if not str(e).startswith(meth_name):
1209 raise support.TestFailed(
1210 "Method <<%s>> failed with unexpected "
1211 "exception message: %s\n" % (
1212 meth_name, e
1213 )
1214 )
1215 # consume data
1216 s.read()
1217
1218 s.write("over\n".encode("ASCII", "strict"))
1219 s.close()
1220 finally:
1221 server.stop()
1222 server.join()
1223
1224
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001225def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001226 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001227 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001228
Trent Nelsone41b0062008-04-08 23:47:30 +00001229 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001230 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001231 "keycert.pem")
1232 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1233 os.path.dirname(__file__) or os.curdir,
1234 "https_svn_python_org_root.pem")
1235
1236 if (not os.path.exists(CERTFILE) or
1237 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001238 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001239
Bill Janssen934b16d2008-06-28 22:19:33 +00001240 TESTPORT = test_support.find_unused_port()
1241 if not TESTPORT:
1242 raise test_support.TestFailed("Can't find open port to test servers on!")
1243
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001244 tests = [BasicTests]
1245
Bill Janssen296a59d2007-09-16 22:06:00 +00001246 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001247 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001248
Bill Janssen98d19da2007-09-10 21:51:02 +00001249 if _have_threads:
1250 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001251 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001252 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001253
Bill Janssen98d19da2007-09-10 21:51:02 +00001254 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001255
Bill Janssen98d19da2007-09-10 21:51:02 +00001256 if _have_threads:
1257 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001258
1259if __name__ == "__main__":
1260 test_main()