blob: 440c80212b68a8ad7e153db568f574ff6ffeb342 [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
Bill Janssen934b16d2008-06-28 22:19:33 +0000129class NetworkedTests(unittest.TestCase):
Bill Janssen296a59d2007-09-16 22:06:00 +0000130
131 def testConnect(self):
Bill Janssen296a59d2007-09-16 22:06:00 +0000132 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
133 cert_reqs=ssl.CERT_NONE)
134 s.connect(("svn.python.org", 443))
135 c = s.getpeercert()
136 if c:
137 raise test_support.TestFailed("Peer cert %s shouldn't be here!")
138 s.close()
139
140 # this should fail because we have no verification certs
141 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
142 cert_reqs=ssl.CERT_REQUIRED)
143 try:
144 s.connect(("svn.python.org", 443))
145 except ssl.SSLError:
146 pass
147 finally:
148 s.close()
149
150 # this should succeed because we specify the root cert
151 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
152 cert_reqs=ssl.CERT_REQUIRED,
153 ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
154 try:
155 s.connect(("svn.python.org", 443))
156 except ssl.SSLError, x:
157 raise test_support.TestFailed("Unexpected exception %s" % x)
158 finally:
159 s.close()
160
Antoine Pitrou0753d942010-04-24 11:09:52 +0000161 def test_makefile_close(self):
162 # Issue #5238: creating a file-like object with makefile() shouldn't
163 # delay closing the underlying "real socket" (here tested with its
164 # file descriptor, hence skipping the test under Windows).
165 if os.name == "nt":
166 if test_support.verbose:
167 print "Skipped: can't use a socket as a file under Windows"
168 return
169 ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
170 ss.connect(("svn.python.org", 443))
171 fd = ss.fileno()
172 f = ss.makefile()
173 f.close()
174 # The fd is still open
175 os.read(fd, 0)
176 # Closing the SSL socket should close the fd too
177 ss.close()
178 gc.collect()
179 try:
180 os.read(fd, 0)
181 except OSError, e:
182 self.assertEqual(e.errno, errno.EBADF)
183 else:
184 self.fail("OSError wasn't raised")
Bill Janssen934b16d2008-06-28 22:19:33 +0000185
186 def testNonBlockingHandshake(self):
187 s = socket.socket(socket.AF_INET)
188 s.connect(("svn.python.org", 443))
189 s.setblocking(False)
190 s = ssl.wrap_socket(s,
191 cert_reqs=ssl.CERT_NONE,
192 do_handshake_on_connect=False)
193 count = 0
194 while True:
195 try:
196 count += 1
197 s.do_handshake()
198 break
199 except ssl.SSLError, err:
200 if err.args[0] == ssl.SSL_ERROR_WANT_READ:
201 select.select([s], [], [])
202 elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
203 select.select([], [s], [])
204 else:
205 raise
206 s.close()
207 if test_support.verbose:
208 sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count)
209
Bill Janssen296a59d2007-09-16 22:06:00 +0000210 def testFetchServerCert(self):
211
212 pem = ssl.get_server_certificate(("svn.python.org", 443))
213 if not pem:
214 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
215
216 try:
217 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=CERTFILE)
218 except ssl.SSLError:
219 #should fail
220 pass
221 else:
222 raise test_support.TestFailed("Got server certificate %s for svn.python.org!" % pem)
223
224 pem = ssl.get_server_certificate(("svn.python.org", 443), ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
225 if not pem:
226 raise test_support.TestFailed("No server certificate on svn.python.org:443!")
227 if test_support.verbose:
228 sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem)
229
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000230 # Test disabled: OPENSSL_VERSION* not available in Python 2.6
Antoine Pitrou878602a2010-04-21 19:41:28 +0000231 def test_algorithms(self):
Antoine Pitroub7c656f2010-04-22 18:42:58 +0000232 if test_support.verbose:
233 sys.stdout.write("test_algorithms disabled, "
234 "as it fails on some old OpenSSL versions")
235 return
Antoine Pitrou878602a2010-04-21 19:41:28 +0000236 # Issue #8484: all algorithms should be available when verifying a
237 # certificate.
238 # NOTE: https://sha256.tbs-internet.com is another possible test host
239 remote = ("sha2.hboeck.de", 443)
240 sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
241 s = ssl.wrap_socket(socket.socket(socket.AF_INET),
242 cert_reqs=ssl.CERT_REQUIRED,
243 ca_certs=sha256_cert,)
244 with test_support.transient_internet():
245 try:
246 s.connect(remote)
247 if test_support.verbose:
248 sys.stdout.write("\nCipher with %r is %r\n" %
249 (remote, s.cipher()))
250 sys.stdout.write("Certificate is:\n%s\n" %
251 pprint.pformat(s.getpeercert()))
252 finally:
253 s.close()
254
Bill Janssen296a59d2007-09-16 22:06:00 +0000255
Bill Janssen98d19da2007-09-10 21:51:02 +0000256try:
257 import threading
258except ImportError:
259 _have_threads = False
260else:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000261
Bill Janssen98d19da2007-09-10 21:51:02 +0000262 _have_threads = True
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000263
Bill Janssen98d19da2007-09-10 21:51:02 +0000264 class ThreadedEchoServer(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000265
Bill Janssen98d19da2007-09-10 21:51:02 +0000266 class ConnectionHandler(threading.Thread):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000267
Bill Janssen98d19da2007-09-10 21:51:02 +0000268 """A mildly complicated class, because we want it to work both
269 with and without the SSL wrapper around the socket connection, so
270 that we can test the STARTTLS functionality."""
271
272 def __init__(self, server, connsock):
273 self.server = server
274 self.running = False
275 self.sock = connsock
276 self.sock.setblocking(1)
277 self.sslconn = None
278 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000279 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000280
Bill Janssen934b16d2008-06-28 22:19:33 +0000281 def show_conn_details(self):
282 if self.server.certreqs == ssl.CERT_REQUIRED:
283 cert = self.sslconn.getpeercert()
284 if test_support.verbose and self.server.chatty:
285 sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n")
286 cert_binary = self.sslconn.getpeercert(True)
287 if test_support.verbose and self.server.chatty:
288 sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n")
289 cipher = self.sslconn.cipher()
290 if test_support.verbose and self.server.chatty:
291 sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n")
292
Bill Janssen98d19da2007-09-10 21:51:02 +0000293 def wrap_conn (self):
294 try:
295 self.sslconn = ssl.wrap_socket(self.sock, server_side=True,
296 certfile=self.server.certificate,
297 ssl_version=self.server.protocol,
298 ca_certs=self.server.cacerts,
299 cert_reqs=self.server.certreqs)
300 except:
301 if self.server.chatty:
302 handle_error("\n server: bad connection attempt from " +
303 str(self.sock.getpeername()) + ":\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000304 self.close()
Bill Janssen98d19da2007-09-10 21:51:02 +0000305 if not self.server.expect_bad_connects:
306 # here, we want to stop the server, because this shouldn't
307 # happen in the context of our test case
308 self.running = False
309 # normally, we'd just stop here, but for the test
310 # harness, we want to stop the server
311 self.server.stop()
312 return False
313
314 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()
384 except:
385 handle_error('')
386
Trent Nelsone41b0062008-04-08 23:47:30 +0000387 def __init__(self, certificate, ssl_version=None,
Bill Janssen98d19da2007-09-10 21:51:02 +0000388 certreqs=None, cacerts=None, expect_bad_connects=False,
Bill Janssen934b16d2008-06-28 22:19:33 +0000389 chatty=True, connectionchatty=False, starttls_server=False,
390 wrap_accepting_socket=False):
391
Bill Janssen98d19da2007-09-10 21:51:02 +0000392 if ssl_version is None:
393 ssl_version = ssl.PROTOCOL_TLSv1
394 if certreqs is None:
395 certreqs = ssl.CERT_NONE
396 self.certificate = certificate
397 self.protocol = ssl_version
398 self.certreqs = certreqs
399 self.cacerts = cacerts
400 self.expect_bad_connects = expect_bad_connects
401 self.chatty = chatty
402 self.connectionchatty = connectionchatty
403 self.starttls_server = starttls_server
404 self.sock = socket.socket()
405 self.flag = None
Bill Janssen934b16d2008-06-28 22:19:33 +0000406 if wrap_accepting_socket:
407 self.sock = ssl.wrap_socket(self.sock, server_side=True,
408 certfile=self.certificate,
409 cert_reqs = self.certreqs,
410 ca_certs = self.cacerts,
411 ssl_version = self.protocol)
412 if test_support.verbose and self.chatty:
413 sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock))
414 self.port = test_support.bind_port(self.sock)
Bill Janssen98d19da2007-09-10 21:51:02 +0000415 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000416 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000417 self.daemon = True
Bill Janssen98d19da2007-09-10 21:51:02 +0000418
419 def start (self, flag=None):
420 self.flag = flag
421 threading.Thread.start(self)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000422
423 def run (self):
Bill Janssen98d19da2007-09-10 21:51:02 +0000424 self.sock.settimeout(0.5)
425 self.sock.listen(5)
426 self.active = True
427 if self.flag:
428 # signal an event
429 self.flag.set()
430 while self.active:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000431 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000432 newconn, connaddr = self.sock.accept()
433 if test_support.verbose and self.chatty:
434 sys.stdout.write(' server: new connection from '
435 + str(connaddr) + '\n')
436 handler = self.ConnectionHandler(self, newconn)
437 handler.start()
438 except socket.timeout:
439 pass
440 except KeyboardInterrupt:
441 self.stop()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000442 except:
Bill Janssen98d19da2007-09-10 21:51:02 +0000443 if self.chatty:
444 handle_error("Test server failure:\n")
Bill Janssen934b16d2008-06-28 22:19:33 +0000445 self.sock.close()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000446
Bill Janssen98d19da2007-09-10 21:51:02 +0000447 def stop (self):
448 self.active = False
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000449
Bill Janssen934b16d2008-06-28 22:19:33 +0000450 class AsyncoreEchoServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000451
Bill Janssen934b16d2008-06-28 22:19:33 +0000452 class EchoServer (asyncore.dispatcher):
453
454 class ConnectionHandler (asyncore.dispatcher_with_send):
455
456 def __init__(self, conn, certfile):
457 asyncore.dispatcher_with_send.__init__(self, conn)
458 self.socket = ssl.wrap_socket(conn, server_side=True,
459 certfile=certfile,
460 do_handshake_on_connect=True)
461
462 def readable(self):
463 if isinstance(self.socket, ssl.SSLSocket):
464 while self.socket.pending() > 0:
465 self.handle_read_event()
466 return True
467
468 def handle_read(self):
469 data = self.recv(1024)
470 self.send(data.lower())
471
472 def handle_close(self):
Bill Janssende34d912008-06-28 23:00:39 +0000473 self.close()
Bill Janssen934b16d2008-06-28 22:19:33 +0000474 if test_support.verbose:
475 sys.stdout.write(" server: closed connection %s\n" % self.socket)
476
477 def handle_error(self):
478 raise
479
480 def __init__(self, certfile):
481 self.certfile = certfile
482 asyncore.dispatcher.__init__(self)
483 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
484 self.port = test_support.bind_port(self.socket)
485 self.listen(5)
486
487 def handle_accept(self):
488 sock_obj, addr = self.accept()
489 if test_support.verbose:
490 sys.stdout.write(" server: new connection from %s:%s\n" %addr)
491 self.ConnectionHandler(sock_obj, self.certfile)
492
493 def handle_error(self):
494 raise
495
496 def __init__(self, certfile):
497 self.flag = None
498 self.active = False
499 self.server = self.EchoServer(certfile)
500 self.port = self.server.port
501 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000502 self.daemon = True
Bill Janssen934b16d2008-06-28 22:19:33 +0000503
504 def __str__(self):
505 return "<%s %s>" % (self.__class__.__name__, self.server)
506
507 def start (self, flag=None):
508 self.flag = flag
509 threading.Thread.start(self)
510
511 def run (self):
512 self.active = True
513 if self.flag:
514 self.flag.set()
515 while self.active:
516 try:
517 asyncore.loop(1)
518 except:
519 pass
520
521 def stop (self):
522 self.active = False
523 self.server.close()
524
525 class SocketServerHTTPSServer(threading.Thread):
Bill Janssen296a59d2007-09-16 22:06:00 +0000526
527 class HTTPSServer(HTTPServer):
528
529 def __init__(self, server_address, RequestHandlerClass, certfile):
530
531 HTTPServer.__init__(self, server_address, RequestHandlerClass)
532 # we assume the certfile contains both private key and certificate
533 self.certfile = certfile
534 self.active = False
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000535 self.active_lock = threading.Lock()
Bill Janssen296a59d2007-09-16 22:06:00 +0000536 self.allow_reuse_address = True
537
Bill Janssen934b16d2008-06-28 22:19:33 +0000538 def __str__(self):
539 return ('<%s %s:%s>' %
540 (self.__class__.__name__,
541 self.server_name,
542 self.server_port))
543
Bill Janssen296a59d2007-09-16 22:06:00 +0000544 def get_request (self):
545 # override this to wrap socket with SSL
546 sock, addr = self.socket.accept()
547 sslconn = ssl.wrap_socket(sock, server_side=True,
548 certfile=self.certfile)
549 return sslconn, addr
550
551 # The methods overridden below this are mainly so that we
552 # can run it in a thread and be able to stop it from another
553 # You probably wouldn't need them in other uses.
554
555 def server_activate(self):
556 # We want to run this in a thread for testing purposes,
557 # so we override this to set timeout, so that we get
558 # a chance to stop the server
559 self.socket.settimeout(0.5)
560 HTTPServer.server_activate(self)
561
562 def serve_forever(self):
563 # We want this to run in a thread, so we use a slightly
564 # modified version of "forever".
565 self.active = True
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000566 while 1:
Bill Janssen296a59d2007-09-16 22:06:00 +0000567 try:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000568 # We need to lock while handling the request.
569 # Another thread can close the socket after self.active
570 # has been checked and before the request is handled.
571 # This causes an exception when using the closed socket.
572 with self.active_lock:
573 if not self.active:
574 break
575 self.handle_request()
Bill Janssen296a59d2007-09-16 22:06:00 +0000576 except socket.timeout:
577 pass
578 except KeyboardInterrupt:
579 self.server_close()
580 return
581 except:
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000582 sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info())))
583 break
Neal Norwitzd0a91af2008-04-02 05:54:27 +0000584 time.sleep(0.1)
Bill Janssen296a59d2007-09-16 22:06:00 +0000585
586 def server_close(self):
587 # Again, we want this to run in a thread, so we need to override
588 # close to clear the "active" flag, so that serve_forever() will
589 # terminate.
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000590 with self.active_lock:
591 HTTPServer.server_close(self)
592 self.active = False
Bill Janssen296a59d2007-09-16 22:06:00 +0000593
594 class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):
595
596 # need to override translate_path to get a known root,
597 # instead of using os.curdir, since the test could be
598 # run from anywhere
599
600 server_version = "TestHTTPS/1.0"
601
602 root = None
603
604 def translate_path(self, path):
605 """Translate a /-separated PATH to the local filename syntax.
606
607 Components that mean special things to the local file system
608 (e.g. drive or directory names) are ignored. (XXX They should
609 probably be diagnosed.)
610
611 """
612 # abandon query parameters
613 path = urlparse.urlparse(path)[2]
614 path = os.path.normpath(urllib.unquote(path))
615 words = path.split('/')
616 words = filter(None, words)
617 path = self.root
618 for word in words:
619 drive, word = os.path.splitdrive(word)
620 head, word = os.path.split(word)
621 if word in self.root: continue
622 path = os.path.join(path, word)
623 return path
624
625 def log_message(self, format, *args):
626
627 # we override this to suppress logging unless "verbose"
628
629 if test_support.verbose:
Bill Janssen934b16d2008-06-28 22:19:33 +0000630 sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" %
631 (self.server.server_address,
Bill Janssen296a59d2007-09-16 22:06:00 +0000632 self.server.server_port,
633 self.request.cipher(),
634 self.log_date_time_string(),
635 format%args))
636
637
Trent Nelsone41b0062008-04-08 23:47:30 +0000638 def __init__(self, certfile):
Bill Janssen296a59d2007-09-16 22:06:00 +0000639 self.flag = None
640 self.active = False
641 self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0]
Trent Nelsone41b0062008-04-08 23:47:30 +0000642 self.port = test_support.find_unused_port()
Bill Janssen296a59d2007-09-16 22:06:00 +0000643 self.server = self.HTTPSServer(
Trent Nelsone41b0062008-04-08 23:47:30 +0000644 (HOST, self.port), self.RootedHTTPRequestHandler, certfile)
Bill Janssen296a59d2007-09-16 22:06:00 +0000645 threading.Thread.__init__(self)
Benjamin Peterson26f52162008-08-18 18:39:57 +0000646 self.daemon = True
Bill Janssen296a59d2007-09-16 22:06:00 +0000647
648 def __str__(self):
Bill Janssen934b16d2008-06-28 22:19:33 +0000649 return "<%s %s>" % (self.__class__.__name__, self.server)
Bill Janssen296a59d2007-09-16 22:06:00 +0000650
651 def start (self, flag=None):
652 self.flag = flag
653 threading.Thread.start(self)
654
655 def run (self):
656 self.active = True
657 if self.flag:
658 self.flag.set()
659 self.server.serve_forever()
660 self.active = False
661
662 def stop (self):
663 self.active = False
664 self.server.server_close()
665
666
Bill Janssen98d19da2007-09-10 21:51:02 +0000667 def badCertTest (certfile):
Trent Nelsone41b0062008-04-08 23:47:30 +0000668 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000669 certreqs=ssl.CERT_REQUIRED,
670 cacerts=CERTFILE, chatty=False)
671 flag = threading.Event()
672 server.start(flag)
673 # wait for it to start
674 flag.wait()
675 # try to connect
676 try:
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000677 try:
Bill Janssen98d19da2007-09-10 21:51:02 +0000678 s = ssl.wrap_socket(socket.socket(),
679 certfile=certfile,
680 ssl_version=ssl.PROTOCOL_TLSv1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000681 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000682 except ssl.SSLError, x:
Neal Norwitz9eb9b102007-08-27 01:15:33 +0000683 if test_support.verbose:
Bill Janssen98d19da2007-09-10 21:51:02 +0000684 sys.stdout.write("\nSSLError is %s\n" % x[1])
Bill Janssen0c1dbf82008-07-17 18:01:57 +0000685 except socket.error, x:
686 if test_support.verbose:
687 sys.stdout.write("\nsocket.error is %s\n" % x[1])
Bill Janssen98d19da2007-09-10 21:51:02 +0000688 else:
689 raise test_support.TestFailed(
690 "Use of invalid cert should have failed!")
691 finally:
692 server.stop()
693 server.join()
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +0000694
Bill Janssen98d19da2007-09-10 21:51:02 +0000695 def serverParamsTest (certfile, protocol, certreqs, cacertsfile,
696 client_certfile, client_protocol=None, indata="FOO\n",
Bill Janssen934b16d2008-06-28 22:19:33 +0000697 chatty=True, connectionchatty=False,
698 wrap_accepting_socket=False):
Bill Janssen98d19da2007-09-10 21:51:02 +0000699
Trent Nelsone41b0062008-04-08 23:47:30 +0000700 server = ThreadedEchoServer(certfile,
Bill Janssen98d19da2007-09-10 21:51:02 +0000701 certreqs=certreqs,
702 ssl_version=protocol,
703 cacerts=cacertsfile,
704 chatty=chatty,
Bill Janssen934b16d2008-06-28 22:19:33 +0000705 connectionchatty=connectionchatty,
706 wrap_accepting_socket=wrap_accepting_socket)
Bill Janssen98d19da2007-09-10 21:51:02 +0000707 flag = threading.Event()
708 server.start(flag)
709 # wait for it to start
710 flag.wait()
711 # try to connect
712 if client_protocol is None:
713 client_protocol = protocol
714 try:
715 try:
716 s = ssl.wrap_socket(socket.socket(),
717 certfile=client_certfile,
718 ca_certs=cacertsfile,
719 cert_reqs=certreqs,
720 ssl_version=client_protocol)
Trent Nelsone41b0062008-04-08 23:47:30 +0000721 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000722 except ssl.SSLError, x:
723 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
724 except Exception, x:
725 raise test_support.TestFailed("Unexpected exception: " + str(x))
726 else:
727 if connectionchatty:
728 if test_support.verbose:
729 sys.stdout.write(
730 " client: sending %s...\n" % (repr(indata)))
731 s.write(indata)
732 outdata = s.read()
733 if connectionchatty:
734 if test_support.verbose:
735 sys.stdout.write(" client: read %s\n" % repr(outdata))
736 if outdata != indata.lower():
737 raise test_support.TestFailed(
738 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
739 % (outdata[:min(len(outdata),20)], len(outdata),
740 indata[:min(len(indata),20)].lower(), len(indata)))
741 s.write("over\n")
742 if connectionchatty:
743 if test_support.verbose:
744 sys.stdout.write(" client: closing connection.\n")
Bill Janssen98d19da2007-09-10 21:51:02 +0000745 s.close()
746 finally:
747 server.stop()
748 server.join()
749
750 def tryProtocolCombo (server_protocol,
751 client_protocol,
752 expectedToWork,
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000753 certsreqs=None):
754
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000755 if certsreqs is None:
Bill Janssene3f1d7d2007-09-11 01:09:19 +0000756 certsreqs = ssl.CERT_NONE
Bill Janssen98d19da2007-09-10 21:51:02 +0000757
758 if certsreqs == ssl.CERT_NONE:
759 certtype = "CERT_NONE"
760 elif certsreqs == ssl.CERT_OPTIONAL:
761 certtype = "CERT_OPTIONAL"
762 elif certsreqs == ssl.CERT_REQUIRED:
763 certtype = "CERT_REQUIRED"
764 if test_support.verbose:
765 formatstr = (expectedToWork and " %s->%s %s\n") or " {%s->%s} %s\n"
766 sys.stdout.write(formatstr %
767 (ssl.get_protocol_name(client_protocol),
768 ssl.get_protocol_name(server_protocol),
769 certtype))
770 try:
771 serverParamsTest(CERTFILE, server_protocol, certsreqs,
772 CERTFILE, CERTFILE, client_protocol, chatty=False)
773 except test_support.TestFailed:
774 if expectedToWork:
775 raise
776 else:
777 if not expectedToWork:
778 raise test_support.TestFailed(
779 "Client protocol %s succeeded with server protocol %s!"
780 % (ssl.get_protocol_name(client_protocol),
781 ssl.get_protocol_name(server_protocol)))
782
783
Bill Janssen934b16d2008-06-28 22:19:33 +0000784 class ThreadedTests(unittest.TestCase):
Bill Janssen98d19da2007-09-10 21:51:02 +0000785
786 def testRudeShutdown(self):
787
788 listener_ready = threading.Event()
789 listener_gone = threading.Event()
Trent Nelsone41b0062008-04-08 23:47:30 +0000790 port = test_support.find_unused_port()
Bill Janssen98d19da2007-09-10 21:51:02 +0000791
792 # `listener` runs in a thread. It opens a socket listening on
793 # PORT, and sits in an accept() until the main thread connects.
794 # Then it rudely closes the socket, and sets Event `listener_gone`
795 # to let the main thread know the socket is gone.
796 def listener():
797 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000798 s.bind((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000799 s.listen(5)
800 listener_ready.set()
801 s.accept()
802 s = None # reclaim the socket object, which also closes it
803 listener_gone.set()
804
805 def connector():
806 listener_ready.wait()
807 s = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000808 s.connect((HOST, port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000809 listener_gone.wait()
810 try:
811 ssl_sock = ssl.wrap_socket(s)
Bill Janssen934b16d2008-06-28 22:19:33 +0000812 except IOError:
Bill Janssen98d19da2007-09-10 21:51:02 +0000813 pass
814 else:
815 raise test_support.TestFailed(
816 'connecting to closed SSL socket should have failed')
817
818 t = threading.Thread(target=listener)
819 t.start()
820 connector()
821 t.join()
822
823 def testEcho (self):
824
825 if test_support.verbose:
826 sys.stdout.write("\n")
827 serverParamsTest(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE,
828 CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1,
829 chatty=True, connectionchatty=True)
830
831 def testReadCert(self):
832
833 if test_support.verbose:
834 sys.stdout.write("\n")
835 s2 = socket.socket()
Trent Nelsone41b0062008-04-08 23:47:30 +0000836 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000837 certreqs=ssl.CERT_NONE,
838 ssl_version=ssl.PROTOCOL_SSLv23,
839 cacerts=CERTFILE,
840 chatty=False)
841 flag = threading.Event()
842 server.start(flag)
843 # wait for it to start
844 flag.wait()
845 # try to connect
846 try:
847 try:
848 s = ssl.wrap_socket(socket.socket(),
849 certfile=CERTFILE,
850 ca_certs=CERTFILE,
851 cert_reqs=ssl.CERT_REQUIRED,
852 ssl_version=ssl.PROTOCOL_SSLv23)
Trent Nelsone41b0062008-04-08 23:47:30 +0000853 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000854 except ssl.SSLError, x:
855 raise test_support.TestFailed(
856 "Unexpected SSL error: " + str(x))
857 except Exception, x:
858 raise test_support.TestFailed(
859 "Unexpected exception: " + str(x))
860 else:
861 if not s:
862 raise test_support.TestFailed(
863 "Can't SSL-handshake with test server")
864 cert = s.getpeercert()
865 if not cert:
866 raise test_support.TestFailed(
867 "Can't get peer certificate.")
868 cipher = s.cipher()
869 if test_support.verbose:
870 sys.stdout.write(pprint.pformat(cert) + '\n')
871 sys.stdout.write("Connection cipher is " + str(cipher) + '.\n')
872 if not cert.has_key('subject'):
873 raise test_support.TestFailed(
874 "No subject field in certificate: %s." %
875 pprint.pformat(cert))
876 if ((('organizationName', 'Python Software Foundation'),)
877 not in cert['subject']):
878 raise test_support.TestFailed(
879 "Missing or invalid 'organizationName' field in certificate subject; "
Neal Norwitz0098c9d2008-03-09 19:03:42 +0000880 "should be 'Python Software Foundation'.")
Bill Janssen98d19da2007-09-10 21:51:02 +0000881 s.close()
882 finally:
883 server.stop()
884 server.join()
885
886 def testNULLcert(self):
887 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
888 "nullcert.pem"))
889 def testMalformedCert(self):
890 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
891 "badcert.pem"))
Bill Janssen934b16d2008-06-28 22:19:33 +0000892 def testWrongCert(self):
893 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
894 "wrongcert.pem"))
Bill Janssen98d19da2007-09-10 21:51:02 +0000895 def testMalformedKey(self):
896 badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir,
897 "badkey.pem"))
898
899 def testProtocolSSL2(self):
900 if test_support.verbose:
901 sys.stdout.write("\n")
902 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
903 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
904 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
905 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True)
906 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
907 tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
908
909 def testProtocolSSL23(self):
910 if test_support.verbose:
911 sys.stdout.write("\n")
912 try:
913 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True)
914 except test_support.TestFailed, x:
915 # this fails on some older versions of OpenSSL (0.9.7l, for instance)
916 if test_support.verbose:
917 sys.stdout.write(
918 " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
919 % str(x))
920 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True)
921 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)
922 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)
923
924 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
925 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)
926 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
927
928 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
929 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)
930 tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
931
932 def testProtocolSSL3(self):
933 if test_support.verbose:
934 sys.stdout.write("\n")
935 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True)
936 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)
937 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
938 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
939 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
940 tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
941
942 def testProtocolTLS1(self):
943 if test_support.verbose:
944 sys.stdout.write("\n")
945 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True)
946 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)
947 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)
948 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
949 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
950 tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
951
952 def testSTARTTLS (self):
953
Bill Janssen39295c22008-08-12 16:31:21 +0000954 msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6")
Bill Janssen98d19da2007-09-10 21:51:02 +0000955
Trent Nelsone41b0062008-04-08 23:47:30 +0000956 server = ThreadedEchoServer(CERTFILE,
Bill Janssen98d19da2007-09-10 21:51:02 +0000957 ssl_version=ssl.PROTOCOL_TLSv1,
958 starttls_server=True,
959 chatty=True,
960 connectionchatty=True)
961 flag = threading.Event()
962 server.start(flag)
963 # wait for it to start
964 flag.wait()
965 # try to connect
966 wrapped = False
967 try:
968 try:
969 s = socket.socket()
970 s.setblocking(1)
Trent Nelsone41b0062008-04-08 23:47:30 +0000971 s.connect((HOST, server.port))
Bill Janssen98d19da2007-09-10 21:51:02 +0000972 except Exception, x:
973 raise test_support.TestFailed("Unexpected exception: " + str(x))
974 else:
975 if test_support.verbose:
976 sys.stdout.write("\n")
977 for indata in msgs:
978 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000979 sys.stdout.write(
980 " client: sending %s...\n" % repr(indata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000981 if wrapped:
982 conn.write(indata)
983 outdata = conn.read()
984 else:
985 s.send(indata)
986 outdata = s.recv(1024)
Bill Janssen296a59d2007-09-16 22:06:00 +0000987 if (indata == "STARTTLS" and
988 outdata.strip().lower().startswith("ok")):
Bill Janssen98d19da2007-09-10 21:51:02 +0000989 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +0000990 sys.stdout.write(
991 " client: read %s from server, starting TLS...\n"
992 % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +0000993 conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
Bill Janssen98d19da2007-09-10 21:51:02 +0000994 wrapped = True
Bill Janssen39295c22008-08-12 16:31:21 +0000995 elif (indata == "ENDTLS" and
996 outdata.strip().lower().startswith("ok")):
997 if test_support.verbose:
998 sys.stdout.write(
999 " client: read %s from server, ending TLS...\n"
1000 % repr(outdata))
1001 s = conn.unwrap()
1002 wrapped = False
Bill Janssen98d19da2007-09-10 21:51:02 +00001003 else:
1004 if test_support.verbose:
Bill Janssen296a59d2007-09-16 22:06:00 +00001005 sys.stdout.write(
1006 " client: read %s from server\n" % repr(outdata))
Bill Janssen98d19da2007-09-10 21:51:02 +00001007 if test_support.verbose:
1008 sys.stdout.write(" client: closing connection.\n")
1009 if wrapped:
1010 conn.write("over\n")
Bill Janssen98d19da2007-09-10 21:51:02 +00001011 else:
1012 s.send("over\n")
1013 s.close()
1014 finally:
1015 server.stop()
1016 server.join()
1017
Bill Janssen934b16d2008-06-28 22:19:33 +00001018 def testSocketServer(self):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001019
Bill Janssen934b16d2008-06-28 22:19:33 +00001020 server = SocketServerHTTPSServer(CERTFILE)
Bill Janssen296a59d2007-09-16 22:06:00 +00001021 flag = threading.Event()
1022 server.start(flag)
1023 # wait for it to start
1024 flag.wait()
1025 # try to connect
1026 try:
1027 if test_support.verbose:
1028 sys.stdout.write('\n')
Bill Janssenbf10c472007-09-16 23:16:46 +00001029 d1 = open(CERTFILE, 'rb').read()
Bill Janssen296a59d2007-09-16 22:06:00 +00001030 d2 = ''
1031 # now fetch the same data from the HTTPS server
Bill Janssen934b16d2008-06-28 22:19:33 +00001032 url = 'https://127.0.0.1:%d/%s' % (
1033 server.port, os.path.split(CERTFILE)[1])
Bill Janssen296a59d2007-09-16 22:06:00 +00001034 f = urllib.urlopen(url)
1035 dlen = f.info().getheader("content-length")
1036 if dlen and (int(dlen) > 0):
1037 d2 = f.read(int(dlen))
1038 if test_support.verbose:
1039 sys.stdout.write(
1040 " client: read %d bytes from remote server '%s'\n"
1041 % (len(d2), server))
1042 f.close()
1043 except:
1044 msg = ''.join(traceback.format_exception(*sys.exc_info()))
1045 if test_support.verbose:
1046 sys.stdout.write('\n' + msg)
1047 raise test_support.TestFailed(msg)
1048 else:
1049 if not (d1 == d2):
1050 raise test_support.TestFailed(
1051 "Couldn't fetch data from HTTPS server")
1052 finally:
1053 server.stop()
1054 server.join()
Neal Norwitz7fc8e292007-08-26 18:50:39 +00001055
Bill Janssen934b16d2008-06-28 22:19:33 +00001056 def testWrappedAccept (self):
1057
1058 if test_support.verbose:
1059 sys.stdout.write("\n")
1060 serverParamsTest(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED,
1061 CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23,
1062 chatty=True, connectionchatty=True,
1063 wrap_accepting_socket=True)
1064
1065
1066 def testAsyncoreServer (self):
1067
1068 indata = "TEST MESSAGE of mixed case\n"
1069
1070 if test_support.verbose:
1071 sys.stdout.write("\n")
1072 server = AsyncoreEchoServer(CERTFILE)
1073 flag = threading.Event()
1074 server.start(flag)
1075 # wait for it to start
1076 flag.wait()
1077 # try to connect
1078 try:
1079 try:
1080 s = ssl.wrap_socket(socket.socket())
1081 s.connect(('127.0.0.1', server.port))
1082 except ssl.SSLError, x:
1083 raise test_support.TestFailed("Unexpected SSL error: " + str(x))
1084 except Exception, x:
1085 raise test_support.TestFailed("Unexpected exception: " + str(x))
1086 else:
1087 if test_support.verbose:
1088 sys.stdout.write(
1089 " client: sending %s...\n" % (repr(indata)))
1090 s.write(indata)
1091 outdata = s.read()
1092 if test_support.verbose:
1093 sys.stdout.write(" client: read %s\n" % repr(outdata))
1094 if outdata != indata.lower():
1095 raise test_support.TestFailed(
1096 "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n"
1097 % (outdata[:min(len(outdata),20)], len(outdata),
1098 indata[:min(len(indata),20)].lower(), len(indata)))
1099 s.write("over\n")
1100 if test_support.verbose:
1101 sys.stdout.write(" client: closing connection.\n")
1102 s.close()
1103 finally:
1104 server.stop()
1105 # wait for server thread to end
1106 server.join()
1107
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001108
Bill Janssen61c001a2008-09-08 16:37:24 +00001109 def testAllRecvAndSendMethods(self):
1110
1111 if test_support.verbose:
1112 sys.stdout.write("\n")
1113
1114 server = ThreadedEchoServer(CERTFILE,
1115 certreqs=ssl.CERT_NONE,
1116 ssl_version=ssl.PROTOCOL_TLSv1,
1117 cacerts=CERTFILE,
1118 chatty=True,
1119 connectionchatty=False)
1120 flag = threading.Event()
1121 server.start(flag)
1122 # wait for it to start
1123 flag.wait()
1124 # try to connect
1125 try:
1126 s = ssl.wrap_socket(socket.socket(),
1127 server_side=False,
1128 certfile=CERTFILE,
1129 ca_certs=CERTFILE,
1130 cert_reqs=ssl.CERT_NONE,
1131 ssl_version=ssl.PROTOCOL_TLSv1)
1132 s.connect((HOST, server.port))
1133 except ssl.SSLError as x:
1134 raise support.TestFailed("Unexpected SSL error: " + str(x))
1135 except Exception as x:
1136 raise support.TestFailed("Unexpected exception: " + str(x))
1137 else:
1138 # helper methods for standardising recv* method signatures
1139 def _recv_into():
1140 b = bytearray("\0"*100)
1141 count = s.recv_into(b)
1142 return b[:count]
1143
1144 def _recvfrom_into():
1145 b = bytearray("\0"*100)
1146 count, addr = s.recvfrom_into(b)
1147 return b[:count]
1148
1149 # (name, method, whether to expect success, *args)
1150 send_methods = [
1151 ('send', s.send, True, []),
1152 ('sendto', s.sendto, False, ["some.address"]),
1153 ('sendall', s.sendall, True, []),
1154 ]
1155 recv_methods = [
1156 ('recv', s.recv, True, []),
1157 ('recvfrom', s.recvfrom, False, ["some.address"]),
1158 ('recv_into', _recv_into, True, []),
1159 ('recvfrom_into', _recvfrom_into, False, []),
1160 ]
1161 data_prefix = u"PREFIX_"
1162
1163 for meth_name, send_meth, expect_success, args in send_methods:
1164 indata = data_prefix + meth_name
1165 try:
1166 send_meth(indata.encode('ASCII', 'strict'), *args)
1167 outdata = s.read()
1168 outdata = outdata.decode('ASCII', 'strict')
1169 if outdata != indata.lower():
1170 raise support.TestFailed(
1171 "While sending with <<%s>> bad data "
1172 "<<%r>> (%d) received; "
1173 "expected <<%r>> (%d)\n" % (
1174 meth_name, outdata[:20], len(outdata),
1175 indata[:20], len(indata)
1176 )
1177 )
1178 except ValueError as e:
1179 if expect_success:
1180 raise support.TestFailed(
1181 "Failed to send with method <<%s>>; "
1182 "expected to succeed.\n" % (meth_name,)
1183 )
1184 if not str(e).startswith(meth_name):
1185 raise support.TestFailed(
1186 "Method <<%s>> failed with unexpected "
1187 "exception message: %s\n" % (
1188 meth_name, e
1189 )
1190 )
1191
1192 for meth_name, recv_meth, expect_success, args in recv_methods:
1193 indata = data_prefix + meth_name
1194 try:
1195 s.send(indata.encode('ASCII', 'strict'))
1196 outdata = recv_meth(*args)
1197 outdata = outdata.decode('ASCII', 'strict')
1198 if outdata != indata.lower():
1199 raise support.TestFailed(
1200 "While receiving with <<%s>> bad data "
1201 "<<%r>> (%d) received; "
1202 "expected <<%r>> (%d)\n" % (
1203 meth_name, outdata[:20], len(outdata),
1204 indata[:20], len(indata)
1205 )
1206 )
1207 except ValueError as e:
1208 if expect_success:
1209 raise support.TestFailed(
1210 "Failed to receive with method <<%s>>; "
1211 "expected to succeed.\n" % (meth_name,)
1212 )
1213 if not str(e).startswith(meth_name):
1214 raise support.TestFailed(
1215 "Method <<%s>> failed with unexpected "
1216 "exception message: %s\n" % (
1217 meth_name, e
1218 )
1219 )
1220 # consume data
1221 s.read()
1222
1223 s.write("over\n".encode("ASCII", "strict"))
1224 s.close()
1225 finally:
1226 server.stop()
1227 server.join()
1228
1229
Neal Norwitz9eb9b102007-08-27 01:15:33 +00001230def test_main(verbose=False):
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001231 if skip_expected:
Bill Janssenffe576d2007-09-05 00:46:27 +00001232 raise test_support.TestSkipped("No SSL support")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001233
Trent Nelsone41b0062008-04-08 23:47:30 +00001234 global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT
Guido van Rossumba8c5652007-08-27 17:19:42 +00001235 CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
Bill Janssen296a59d2007-09-16 22:06:00 +00001236 "keycert.pem")
1237 SVN_PYTHON_ORG_ROOT_CERT = os.path.join(
1238 os.path.dirname(__file__) or os.curdir,
1239 "https_svn_python_org_root.pem")
1240
1241 if (not os.path.exists(CERTFILE) or
1242 not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT)):
Bill Janssen98d19da2007-09-10 21:51:02 +00001243 raise test_support.TestFailed("Can't read certificate files!")
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001244
Bill Janssen934b16d2008-06-28 22:19:33 +00001245 TESTPORT = test_support.find_unused_port()
1246 if not TESTPORT:
1247 raise test_support.TestFailed("Can't find open port to test servers on!")
1248
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001249 tests = [BasicTests]
1250
Bill Janssen296a59d2007-09-16 22:06:00 +00001251 if test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001252 tests.append(NetworkedTests)
Bill Janssen296a59d2007-09-16 22:06:00 +00001253
Bill Janssen98d19da2007-09-10 21:51:02 +00001254 if _have_threads:
1255 thread_info = test_support.threading_setup()
Bill Janssen296a59d2007-09-16 22:06:00 +00001256 if thread_info and test_support.is_resource_enabled('network'):
Bill Janssen934b16d2008-06-28 22:19:33 +00001257 tests.append(ThreadedTests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001258
Bill Janssen98d19da2007-09-10 21:51:02 +00001259 test_support.run_unittest(*tests)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001260
Bill Janssen98d19da2007-09-10 21:51:02 +00001261 if _have_threads:
1262 test_support.threading_cleanup(*thread_info)
Guido van Rossum4f2c3dd2007-08-25 15:08:43 +00001263
1264if __name__ == "__main__":
1265 test_main()